D$ now support memDataWidth > 32

This commit is contained in:
Dolu1990 2020-05-04 12:54:16 +02:00
parent 93b386e16e
commit b0f7f37ac8
5 changed files with 104 additions and 60 deletions

View File

@ -27,7 +27,7 @@ import spinal.lib.bus.avalon.AvalonMM
import spinal.lib.eda.altera.{InterruptReceiverTag, ResetEmitterTag} import spinal.lib.eda.altera.{InterruptReceiverTag, ResetEmitterTag}
//make clean all SEED=42 MMU=no STOP_ON_ERROR=yes DBUS_EXCLUSIVE=yes DBUS_INVALIDATE=yes SUPERVISOR=yes REDO=0 DHRYSTONE=no LRSC=yes AMO=yes LINUX_REGRESSION=yes TRACE=yes TRACE_START=9546629800l FLOW_INFO=ye // make clean all SEED=42 MMU=no STOP_ON_ERROR=yes DBUS_EXCLUSIVE=yes DBUS_INVALIDATE=yes SUPERVISOR=yes REDO=1 DHRYSTONE=yes LRSC=yes AMO=yes LINUX_REGRESSION=yes TRACE=yes TRACE_START=1000000000 FLOW_INFO=ye IBUS_DATA_WIDTH=128 DBUS_DATA_WIDTH=128
object TestsWorkspace { object TestsWorkspace {
def main(args: Array[String]) { def main(args: Array[String]) {
def configFull = { def configFull = {
@ -60,7 +60,7 @@ object TestsWorkspace {
injectorStage = false, injectorStage = false,
config = InstructionCacheConfig( config = InstructionCacheConfig(
cacheSize = 4096*1, cacheSize = 4096*1,
bytePerLine = 32, bytePerLine = 64,
wayCount = 1, wayCount = 1,
addressWidth = 32, addressWidth = 32,
cpuDataWidth = 32, cpuDataWidth = 32,
@ -92,11 +92,11 @@ object TestsWorkspace {
dBusRspSlavePipe = true, dBusRspSlavePipe = true,
config = new DataCacheConfig( config = new DataCacheConfig(
cacheSize = 4096*1, cacheSize = 4096*1,
bytePerLine = 32, bytePerLine = 64,
wayCount = 1, wayCount = 1,
addressWidth = 32, addressWidth = 32,
cpuDataWidth = 32, cpuDataWidth = 32,
memDataWidth = 32, memDataWidth = 128,
catchAccessError = true, catchAccessError = true,
catchIllegal = true, catchIllegal = true,
catchUnaligned = true, catchUnaligned = true,

View File

@ -34,7 +34,7 @@ case class DataCacheConfig(cacheSize : Int,
assert(isPow2(pendingMax)) assert(isPow2(pendingMax))
def withWriteResponse = withExclusive def withWriteResponse = withExclusive
def burstSize = bytePerLine*8/memDataWidth def burstSize = bytePerLine*8/memDataWidth
val burstLength = bytePerLine/(memDataWidth/8) val burstLength = bytePerLine/(cpuDataWidth/8)
def catchSomething = catchUnaligned || catchIllegal || catchAccessError def catchSomething = catchUnaligned || catchIllegal || catchAccessError
def withInternalAmo = withAmo && !withExclusive def withInternalAmo = withAmo && !withExclusive
def withInternalLrSc = withLrSc && !withExclusive def withInternalLrSc = withLrSc && !withExclusive
@ -196,8 +196,8 @@ case class DataCacheMemCmd(p : DataCacheConfig) extends Bundle{
val wr = Bool val wr = Bool
val uncached = Bool val uncached = Bool
val address = UInt(p.addressWidth bit) val address = UInt(p.addressWidth bit)
val data = Bits(p.memDataWidth bits) val data = Bits(p.cpuDataWidth bits)
val mask = Bits(p.memDataWidth/8 bits) val mask = Bits(p.cpuDataWidth/8 bits)
val length = UInt(log2Up(p.burstLength) bits) val length = UInt(log2Up(p.burstLength) bits)
val exclusive = p.withExclusive generate Bool() val exclusive = p.withExclusive generate Bool()
val last = Bool val last = Bool
@ -424,7 +424,6 @@ object DataCacheExternalAmoStates extends SpinalEnum{
//If external amo, mem rsp should stay //If external amo, mem rsp should stay
class DataCache(val p : DataCacheConfig) extends Component{ class DataCache(val p : DataCacheConfig) extends Component{
import p._ import p._
assert(cpuDataWidth == memDataWidth)
val io = new Bundle{ val io = new Bundle{
val cpu = slave(DataCacheCpuBus(p)) val cpu = slave(DataCacheCpuBus(p))
@ -434,19 +433,24 @@ class DataCache(val p : DataCacheConfig) extends Component{
val haltCpu = False val haltCpu = False
val lineWidth = bytePerLine*8 val lineWidth = bytePerLine*8
val lineCount = cacheSize/bytePerLine val lineCount = cacheSize/bytePerLine
val wordWidth = Math.max(memDataWidth,cpuDataWidth) val wordWidth = cpuDataWidth
val wordWidthLog2 = log2Up(wordWidth) val wordWidthLog2 = log2Up(wordWidth)
val wordPerLine = lineWidth/wordWidth val wordPerLine = lineWidth/wordWidth
val bytePerWord = wordWidth/8 val bytePerWord = wordWidth/8
val wayLineCount = lineCount/wayCount val wayLineCount = lineCount/wayCount
val wayLineLog2 = log2Up(wayLineCount) val wayLineLog2 = log2Up(wayLineCount)
val wayWordCount = wayLineCount * wordPerLine val wayWordCount = wayLineCount * wordPerLine
val memWordPerLine = lineWidth/memDataWidth
val memTransactionPerLine = p.bytePerLine / (p.memDataWidth/8) val memTransactionPerLine = p.bytePerLine / (p.memDataWidth/8)
val bytePerMemWord = memDataWidth/8
val wayMemWordCount = wayLineCount * memWordPerLine
val tagRange = addressWidth-1 downto log2Up(wayLineCount*bytePerLine) val tagRange = addressWidth-1 downto log2Up(wayLineCount*bytePerLine)
val lineRange = tagRange.low-1 downto log2Up(bytePerLine) val lineRange = tagRange.low-1 downto log2Up(bytePerLine)
val wordRange = log2Up(bytePerLine)-1 downto log2Up(bytePerWord) val cpuWordRange = log2Up(bytePerLine)-1 downto log2Up(bytePerWord)
val memWordRange = log2Up(bytePerLine)-1 downto log2Up(bytePerMemWord)
val hitRange = tagRange.high downto lineRange.low val hitRange = tagRange.high downto lineRange.low
val memWordToCpuWordRange = log2Up(bytePerMemWord)-1 downto log2Up(bytePerWord)
class LineInfo() extends Bundle{ class LineInfo() extends Bundle{
@ -464,23 +468,24 @@ class DataCache(val p : DataCacheConfig) extends Component{
val tagsWriteLastCmd = RegNext(tagsWriteCmd) val tagsWriteLastCmd = RegNext(tagsWriteCmd)
val dataReadCmd = Flow(UInt(log2Up(wayWordCount) bits)) val dataReadCmd = Flow(UInt(log2Up(wayMemWordCount) bits))
val dataWriteCmd = Flow(new Bundle{ val dataWriteCmd = Flow(new Bundle{
val way = Bits(wayCount bits) val way = Bits(wayCount bits)
val address = UInt(log2Up(wayWordCount) bits) val address = UInt(log2Up(wayMemWordCount) bits)
val data = Bits(wordWidth bits) val data = Bits(memDataWidth bits)
val mask = Bits(wordWidth/8 bits) val mask = Bits(memDataWidth/8 bits)
}) })
val ways = for(i <- 0 until wayCount) yield new Area{ val ways = for(i <- 0 until wayCount) yield new Area{
val tags = Mem(new LineInfo(), wayLineCount) val tags = Mem(new LineInfo(), wayLineCount)
val data = Mem(Bits(wordWidth bit), wayWordCount) val data = Mem(Bits(memDataWidth bit), wayMemWordCount)
//Reads //Reads
val tagsReadRsp = tags.readSync(tagsReadCmd.payload, tagsReadCmd.valid && !io.cpu.memory.isStuck) val tagsReadRsp = tags.readSync(tagsReadCmd.payload, tagsReadCmd.valid && !io.cpu.memory.isStuck)
val dataReadRsp = data.readSync(dataReadCmd.payload, dataReadCmd.valid && !io.cpu.memory.isStuck) val dataReadRspMem = data.readSync(dataReadCmd.payload, dataReadCmd.valid && !io.cpu.memory.isStuck)
val dataReadRspSel = if(mergeExecuteMemory) io.cpu.writeBack.address else io.cpu.memory.address
val dataReadRsp = dataReadRspMem.subdivideIn(cpuDataWidth bits).read(dataReadRspSel(memWordToCpuWordRange))
val tagsInvReadRsp = withInvalidate generate tags.readSync(tagsInvReadCmd.payload, tagsInvReadCmd.valid) val tagsInvReadRsp = withInvalidate generate tags.readSync(tagsInvReadCmd.payload, tagsInvReadCmd.valid)
@ -511,13 +516,15 @@ class DataCache(val p : DataCacheConfig) extends Component{
tagsReadCmd.valid := True tagsReadCmd.valid := True
dataReadCmd.valid := True dataReadCmd.valid := True
tagsReadCmd.payload := io.cpu.execute.address(lineRange) tagsReadCmd.payload := io.cpu.execute.address(lineRange)
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low) dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto memWordRange.low)
} }
def collisionProcess(readAddress : UInt, readMask : Bits): Bits ={ def collisionProcess(readAddress : UInt, readMask : Bits): Bits ={
val ret = Bits(wayCount bits) val ret = Bits(wayCount bits)
val readAddressAligned = (readAddress >> log2Up(memDataWidth/cpuDataWidth))
val dataWriteMaskAligned = dataWriteCmd.mask.subdivideIn(memDataWidth/cpuDataWidth slices).read(readAddress(log2Up(memDataWidth/cpuDataWidth)-1 downto 0))
for(i <- 0 until wayCount){ for(i <- 0 until wayCount){
ret(i) := dataWriteCmd.valid && dataWriteCmd.way(i) && dataWriteCmd.address === readAddress && (readMask & dataWriteCmd.mask) =/= 0 ret(i) := dataWriteCmd.valid && dataWriteCmd.way(i) && dataWriteCmd.address === readAddressAligned && (readMask & dataWriteMaskAligned) =/= 0
} }
ret ret
} }
@ -600,7 +607,7 @@ class DataCache(val p : DataCacheConfig) extends Component{
U(1) -> B"0011", U(1) -> B"0011",
default -> B"1111" default -> B"1111"
) |<< io.cpu.execute.address(1 downto 0) ) |<< io.cpu.execute.address(1 downto 0)
val dataColisions = collisionProcess(io.cpu.execute.address(lineRange.high downto wordRange.low), mask) val dataColisions = collisionProcess(io.cpu.execute.address(lineRange.high downto cpuWordRange.low), mask)
val wayInvalidate = B(0, wayCount bits) //Used if invalidate enabled val wayInvalidate = B(0, wayCount bits) //Used if invalidate enabled
val isAmo = if(withAmo) io.cpu.execute.isAmo else False val isAmo = if(withAmo) io.cpu.execute.isAmo else False
@ -643,7 +650,7 @@ class DataCache(val p : DataCacheConfig) extends Component{
stagePipe(stage0.dataColisions) stagePipe(stage0.dataColisions)
} else { } else {
//Assume the writeback stage will never be unstall memory acces while memory stage is stalled //Assume the writeback stage will never be unstall memory acces while memory stage is stalled
stagePipe(stage0.dataColisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask) stagePipe(stage0.dataColisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto cpuWordRange.low), mask)
} }
} }
@ -667,7 +674,7 @@ class DataCache(val p : DataCacheConfig) extends Component{
//Loader interface //Loader interface
val loaderValid = False val loaderValid = False
val ioMemRspMuxed = io.mem.rsp.data.subdivideIn(cpuDataWidth bits).read(io.cpu.writeBack.address(memWordToCpuWordRange))
io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid
@ -717,7 +724,7 @@ class DataCache(val p : DataCacheConfig) extends Component{
import DataCacheExternalAmoStates._ import DataCacheExternalAmoStates._
val amo = withAmo generate new Area{ val amo = withAmo generate new Area{
def rf = request.data def rf = request.data
def mem = if(withInternalAmo) dataMux else io.mem.rsp.data def mem = if(withInternalAmo) dataMux else ioMemRspMuxed
val compare = request.amoCtrl.alu.msb val compare = request.amoCtrl.alu.msb
val unsigned = request.amoCtrl.alu(2 downto 1) === B"11" val unsigned = request.amoCtrl.alu(2 downto 1) === B"11"
val addSub = (rf.asSInt + Mux(compare, ~mem, mem).asSInt + Mux(compare, S(1), S(0))).asBits val addSub = (rf.asSInt + Mux(compare, ~mem, mem).asSInt + Mux(compare, S(1), S(0))).asBits
@ -748,9 +755,10 @@ class DataCache(val p : DataCacheConfig) extends Component{
val cpuWriteToCache = False val cpuWriteToCache = False
when(cpuWriteToCache){ when(cpuWriteToCache){
dataWriteCmd.valid setWhen(request.wr && waysHit) dataWriteCmd.valid setWhen(request.wr && waysHit)
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low) dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto memWordRange.low)
dataWriteCmd.data := requestDataBypass dataWriteCmd.data.subdivideIn(cpuDataWidth bits).foreach(_ := requestDataBypass)
dataWriteCmd.mask := mask dataWriteCmd.mask := 0
dataWriteCmd.mask.subdivideIn(cpuDataWidth/8 bits).write(io.cpu.writeBack.address(memWordToCpuWordRange), mask)
dataWriteCmd.way := waysHits dataWriteCmd.way := waysHits
} }
@ -761,7 +769,7 @@ class DataCache(val p : DataCacheConfig) extends Component{
io.cpu.writeBack.isWrite := request.wr io.cpu.writeBack.isWrite := request.wr
io.mem.cmd.valid := False io.mem.cmd.valid := False
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit) io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto cpuWordRange.low) @@ U(0, cpuWordRange.low bits)
io.mem.cmd.length := 0 io.mem.cmd.length := 0
io.mem.cmd.last := True io.mem.cmd.last := True
io.mem.cmd.wr := request.wr io.mem.cmd.wr := request.wr
@ -825,7 +833,7 @@ class DataCache(val p : DataCacheConfig) extends Component{
//Write through //Write through
io.mem.cmd.valid setWhen(request.wr) io.mem.cmd.valid setWhen(request.wr)
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit) io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto cpuWordRange.low) @@ U(0, cpuWordRange.low bits)
io.mem.cmd.length := 0 io.mem.cmd.length := 0
io.cpu.writeBack.haltIt clearWhen(!request.wr || io.mem.cmd.ready) io.cpu.writeBack.haltIt clearWhen(!request.wr || io.mem.cmd.ready)
@ -861,7 +869,7 @@ class DataCache(val p : DataCacheConfig) extends Component{
} }
when(bypassCache){ when(bypassCache){
io.cpu.writeBack.data := io.mem.rsp.data io.cpu.writeBack.data := ioMemRspMuxed
if(catchAccessError) io.cpu.writeBack.accessError := io.mem.rsp.valid && io.mem.rsp.error if(catchAccessError) io.cpu.writeBack.accessError := io.mem.rsp.valid && io.mem.rsp.error
} otherwise { } otherwise {
io.cpu.writeBack.data := dataMux io.cpu.writeBack.data := dataMux

View File

@ -2028,7 +2028,7 @@ public:
#endif #endif
error = false; error = false;
for(int idx = 0;idx < IBUS_DATA_WIDTH/32;idx++){ for(int idx = 0;idx < IBUS_DATA_WIDTH/32;idx++){
bool localError; bool localError = false;
ws->iBusAccess(address+idx*4,((uint32_t*)&top->iBus_rsp_payload_data)+idx,&localError); ws->iBusAccess(address+idx*4,((uint32_t*)&top->iBus_rsp_payload_data)+idx,&localError);
error |= localError; error |= localError;
} }
@ -2342,7 +2342,7 @@ public:
#include <queue> #include <queue>
struct DBusCachedTask{ struct DBusCachedTask{
uint32_t data; char data[DBUS_DATA_WIDTH/8];
bool error; bool error;
bool last; bool last;
bool exclusive; bool exclusive;
@ -2386,21 +2386,43 @@ public:
bool error; bool error;
ws->dBusAccess(top->dBus_cmd_payload_address,1,2,top->dBus_cmd_payload_mask,&top->dBus_cmd_payload_data,&error); ws->dBusAccess(top->dBus_cmd_payload_address,1,2,top->dBus_cmd_payload_mask,&top->dBus_cmd_payload_data,&error);
#else #else
bool cancel = false; bool cancel = false, error = false;
if(top->dBus_cmd_payload_exclusive){ if(top->dBus_cmd_payload_exclusive){
bool hit = reservationValid && reservationAddress == top->dBus_cmd_payload_address; bool hit = reservationValid && reservationAddress == top->dBus_cmd_payload_address;
rsp.exclusive = hit; rsp.exclusive = hit;
cancel = !hit; cancel = !hit;
reservationValid = false; reservationValid = false;
} }
if(!cancel) ws->dBusAccess(top->dBus_cmd_payload_address,1,2,top->dBus_cmd_payload_mask,&top->dBus_cmd_payload_data,&rsp.error); if(!cancel) {
for(int idx = 0;idx < 1;idx++){
bool localError = false;
ws->dBusAccess(top->dBus_cmd_payload_address+idx*4,1,2,top->dBus_cmd_payload_mask >> idx*4,((uint32_t*)&top->dBus_cmd_payload_data)+idx, &localError);
error |= localError;
//printf("%d ", (int)localError);
}
}
// printf("%x %d\n", top->dBus_cmd_payload_address, (int)error);
rsp.last = true; rsp.last = true;
rsp.error = error;
rsps.push(rsp); rsps.push(rsp);
#endif #endif
} else { } else {
for(int beat = 0;beat <= top->dBus_cmd_payload_length;beat++){ bool error = false;
ws->dBusAccess(top->dBus_cmd_payload_address + beat * 4,0,2,0,&rsp.data,&rsp.error); uint32_t beatCount = top->dBus_cmd_payload_length*32/DBUS_DATA_WIDTH;
rsp.last = beat == top->dBus_cmd_payload_length; for(int beat = 0;beat <= beatCount;beat++){
if(top->dBus_cmd_payload_length == 0){
uint32_t sel = (top->dBus_cmd_payload_address >> 2) & (DBUS_DATA_WIDTH/32-1);
ws->dBusAccess(top->dBus_cmd_payload_address,0,2,0,((uint32_t*)rsp.data) + sel,&error);
} else {
for(int idx = 0;idx < DBUS_DATA_WIDTH/32;idx++){
bool localError = false;
ws->dBusAccess(top->dBus_cmd_payload_address + beat * DBUS_DATA_WIDTH/8 + idx*4,0,2,0,((uint32_t*)rsp.data)+idx, &localError);
error |= localError;
}
}
rsp.last = beat == beatCount;
#ifdef DBUS_EXCLUSIVE #ifdef DBUS_EXCLUSIVE
if(top->dBus_cmd_payload_exclusive){ if(top->dBus_cmd_payload_exclusive){
rsp.exclusive = true; rsp.exclusive = true;
@ -2408,6 +2430,7 @@ public:
reservationAddress = top->dBus_cmd_payload_address; reservationAddress = top->dBus_cmd_payload_address;
} }
#endif #endif
rsp.error = error;
rsps.push(rsp); rsps.push(rsp);
} }
@ -2434,14 +2457,18 @@ public:
rsps.pop(); rsps.pop();
top->dBus_rsp_valid = 1; top->dBus_rsp_valid = 1;
top->dBus_rsp_payload_error = rsp.error; top->dBus_rsp_payload_error = rsp.error;
top->dBus_rsp_payload_data = rsp.data; for(int idx = 0;idx < DBUS_DATA_WIDTH/32;idx++){
((uint32_t*)&top->dBus_rsp_payload_data)[idx] = ((uint32_t*)rsp.data)[idx];
}
top->dBus_rsp_payload_last = rsp.last; top->dBus_rsp_payload_last = rsp.last;
#ifdef DBUS_EXCLUSIVE #ifdef DBUS_EXCLUSIVE
top->dBus_rsp_payload_exclusive = rsp.exclusive; top->dBus_rsp_payload_exclusive = rsp.exclusive;
#endif #endif
} else{ } else{
top->dBus_rsp_valid = 0; top->dBus_rsp_valid = 0;
top->dBus_rsp_payload_data = VL_RANDOM_I(32); for(int idx = 0;idx < DBUS_DATA_WIDTH/32;idx++){
((uint32_t*)&top->dBus_rsp_payload_data)[idx] = VL_RANDOM_I(32);
}
top->dBus_rsp_payload_error = VL_RANDOM_I(1); top->dBus_rsp_payload_error = VL_RANDOM_I(1);
top->dBus_rsp_payload_last = VL_RANDOM_I(1); top->dBus_rsp_payload_last = VL_RANDOM_I(1);
#ifdef DBUS_EXCLUSIVE #ifdef DBUS_EXCLUSIVE

View File

@ -5,6 +5,7 @@ IBUS?=CACHED
IBUS_TC?=no IBUS_TC?=no
IBUS_DATA_WIDTH?=32 IBUS_DATA_WIDTH?=32
DBUS?=CACHED DBUS?=CACHED
DBUS_DATA_WIDTH?=32
TRACE?=no TRACE?=no
TRACE_ACCESS?=no TRACE_ACCESS?=no
TRACE_START=0 TRACE_START=0
@ -46,6 +47,7 @@ WITH_USER_IO?=no
ADDCFLAGS += -CFLAGS -DREGRESSION_PATH='\"$(REGRESSION_PATH)/\"' ADDCFLAGS += -CFLAGS -DREGRESSION_PATH='\"$(REGRESSION_PATH)/\"'
ADDCFLAGS += -CFLAGS -DIBUS_${IBUS} ADDCFLAGS += -CFLAGS -DIBUS_${IBUS}
ADDCFLAGS += -CFLAGS -DIBUS_DATA_WIDTH=${IBUS_DATA_WIDTH} ADDCFLAGS += -CFLAGS -DIBUS_DATA_WIDTH=${IBUS_DATA_WIDTH}
ADDCFLAGS += -CFLAGS -DDBUS_DATA_WIDTH=${DBUS_DATA_WIDTH}
ADDCFLAGS += -CFLAGS -DDBUS_${DBUS} ADDCFLAGS += -CFLAGS -DDBUS_${DBUS}
ADDCFLAGS += -CFLAGS -DREDO=${REDO} ADDCFLAGS += -CFLAGS -DREDO=${REDO}

View File

@ -1,7 +1,7 @@
package vexriscv package vexriscv
import java.io.{File, OutputStream} import java.io.{File, OutputStream}
import java.util.concurrent.TimeUnit import java.util.concurrent.{ForkJoinPool, TimeUnit}
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import org.scalatest.{BeforeAndAfterAll, FunSuite, ParallelTestExecution, Tag, Transformer} import org.scalatest.{BeforeAndAfterAll, FunSuite, ParallelTestExecution, Tag, Transformer}
@ -426,7 +426,8 @@ class DBusDimension extends VexRiscvDimension("DBus") {
// override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition]) // override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition])
} }
} else { } else {
val bytePerLine = List(8,16,32,64)(r.nextInt(4)) val memDataWidth = List(32,64,128)(r.nextInt(3))
val bytePerLine = Math.max(memDataWidth/8, List(8,16,32,64)(r.nextInt(4)))
var cacheSize = 0 var cacheSize = 0
var wayCount = 0 var wayCount = 0
val withLrSc = catchAll val withLrSc = catchAll
@ -441,8 +442,8 @@ class DBusDimension extends VexRiscvDimension("DBus") {
cacheSize = 512 << r.nextInt(5) cacheSize = 512 << r.nextInt(5)
wayCount = 1 << r.nextInt(3) wayCount = 1 << r.nextInt(3)
}while(cacheSize/wayCount < 512 || (catchAll && cacheSize/wayCount > 4096)) }while(cacheSize/wayCount < 512 || (catchAll && cacheSize/wayCount > 4096))
new VexRiscvPosition("Cached" + "S" + cacheSize + "W" + wayCount + "BPL" + bytePerLine + (if(dBusCmdMasterPipe) "Cmp " else "") + (if(dBusCmdSlavePipe) "Csp " else "") + (if(dBusRspSlavePipe) "Rsp " else "") + (if(relaxedMemoryTranslationRegister) "Rmtr " else "") + (if(earlyWaysHits) "Ewh " else "") + (if(withAmo) "Amo " else "") + (if(withSmp) "Smp " else "")) { new VexRiscvPosition(s"Cached${memDataWidth}d" + "S" + cacheSize + "W" + wayCount + "BPL" + bytePerLine + (if(dBusCmdMasterPipe) "Cmp " else "") + (if(dBusCmdSlavePipe) "Csp " else "") + (if(dBusRspSlavePipe) "Rsp " else "") + (if(relaxedMemoryTranslationRegister) "Rmtr " else "") + (if(earlyWaysHits) "Ewh " else "") + (if(withAmo) "Amo " else "") + (if(withSmp) "Smp " else "")) {
override def testParam = "DBUS=CACHED " + (if(withLrSc) "LRSC=yes " else "") + (if(withAmo) "AMO=yes " else "") + (if(withSmp) "DBUS_EXCLUSIVE=yes DBUS_INVALIDATE=yes " else "") override def testParam = s"DBUS=CACHED DBUS_DATA_WIDTH=$memDataWidth " + (if(withLrSc) "LRSC=yes " else "") + (if(withAmo) "AMO=yes " else "") + (if(withSmp) "DBUS_EXCLUSIVE=yes DBUS_INVALIDATE=yes " else "")
override def applyOn(config: VexRiscvConfig): Unit = { override def applyOn(config: VexRiscvConfig): Unit = {
config.plugins += new DBusCachedPlugin( config.plugins += new DBusCachedPlugin(
@ -452,7 +453,7 @@ class DBusDimension extends VexRiscvDimension("DBus") {
wayCount = wayCount, wayCount = wayCount,
addressWidth = 32, addressWidth = 32,
cpuDataWidth = 32, cpuDataWidth = 32,
memDataWidth = 32, memDataWidth = memDataWidth,
catchAccessError = catchAll, catchAccessError = catchAll,
catchIllegal = catchAll, catchIllegal = catchAll,
catchUnaligned = catchAll, catchUnaligned = catchAll,
@ -574,8 +575,14 @@ object PlayFuture extends App{
Thread.sleep(8000) Thread.sleep(8000)
} }
class MultithreadedFunSuite extends FunSuite { class MultithreadedFunSuite(threadCount : Int) extends FunSuite {
implicit val ec = ExecutionContext.global val finalThreadCount = if(threadCount > 0) threadCount else {
val systemInfo = new oshi.SystemInfo
systemInfo.getHardware.getProcessor.getLogicalProcessorCount
}
implicit val ec = ExecutionContext.fromExecutorService(
new ForkJoinPool(finalThreadCount, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true)
)
class Job(body : => Unit){ class Job(body : => Unit){
val originalOutput = Console.out val originalOutput = Console.out
val buffer = mutable.Queue[Char]() val buffer = mutable.Queue[Char]()
@ -612,7 +619,7 @@ class MultithreadedFunSuite extends FunSuite {
} }
class FunTestPara extends MultithreadedFunSuite{ class FunTestPara extends MultithreadedFunSuite(3){
def createTest(name : String): Unit ={ def createTest(name : String): Unit ={
test(name){ test(name){
for(i <- 0 to 4) { for(i <- 0 to 4) {
@ -624,20 +631,20 @@ class FunTestPara extends MultithreadedFunSuite{
(0 to 80).map(_.toString).foreach(createTest) (0 to 80).map(_.toString).foreach(createTest)
} }
class FunTestPlay extends FunSuite { //class FunTestPlay extends FunSuite {
def createTest(name : String): Unit ={ // def createTest(name : String): Unit ={
test(name){ // test(name){
Thread.sleep(500) // Thread.sleep(500)
for(i <- 0 to 4) { // for(i <- 0 to 4) {
println(s"$name $i") // println(s"$name $i")
Thread.sleep(500) // Thread.sleep(500)
} // }
} // }
} // }
(0 to 80).map(_.toString).foreach(createTest) // (0 to 80).map(_.toString).foreach(createTest)
} //}
class TestIndividualFeatures extends MultithreadedFunSuite { class TestIndividualFeatures extends MultithreadedFunSuite(sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", "0").toInt) {
val testCount = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_COUNT", "100").toInt val testCount = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_COUNT", "100").toInt
val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong
val testId : Set[Int] = sys.env.get("VEXRISCV_REGRESSION_TEST_ID") match { val testId : Set[Int] = sys.env.get("VEXRISCV_REGRESSION_TEST_ID") match {