#60 Added automated linux regression in travis

Fix DBusCached plugin access sharing for the MMU deadlock when exception is in the decode stage
Fix IBusSimplePlugin issues with used with non regular configs + MMU
Bring back the LinuxGen config into a light one
This commit is contained in:
Charles Papon 2019-04-19 17:35:48 +02:00
parent 2810ff05b0
commit e47b76fa67
15 changed files with 222 additions and 82 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "src/test/resources/VexRiscvRegressionData"]
path = src/test/resources/VexRiscvRegressionData
url = ../VexRiscvRegressionData.git

View File

@ -11,8 +11,8 @@ scala:
sbt_args: -no-colors -J-Xss2m
script:
- export VEXRISCV_REGRESSION_CONFIG_COUNT=100
- export VEXRISCV_REGRESSION_FREERTOS_COUNT=no
- export VEXRISCV_REGRESSION_THREAD_COUNT=1
- sbt -jvm-opts travis/jvmopts.compile compile
- sbt -jvm-opts travis/jvmopts.test test
@ -22,7 +22,11 @@ jdk:
# - openjdk7
env:
- secure: "v7FHP8yK/zixpv1ML05qcRhZfDVDFdTmTPjfMZHL7gmrJveVDgze22x4tY4tB1+JEXhKuVTYvimOrX/Ok+rOOT5gVKLowv4PUQwCR+HgWVIbqjcfZNLsa369v03/p4K/zbjJSiXFahZYOXa0ApED2KWHcVfCrNsPv0UF7YZGiIa1Q/lPBwfmpN1rLih2Mpgn4KVaJky22t7JXJyVrNdGVmIA51slVbyFwFAE8Ww/0tkC+i2PUcWWRMIxtXP4iyq/9Npcq5VdqOatKfWHqAElLfKSPNMYLMlcyxyNpNx4paq8cL6fQxFcBLi9M2msz2i/qpKv30a0tzNo5bQQgucAXOQJB2Buks728upLuqsr+k25hwcqrtjyMOr9UQkt7qXAJH/0kimW7aW1yoMxbm/6mNG98X9D1EzNRewHAKatwJeFy1bw5qIuSQxPBwQMGloManrHOHGotmHKk7Y+dgM/z1UlaAdxSQuKWGXBc8QlQvif8puPYEdJMoInJNRxiWfYu06XnmzTXgMketK7RdULM9DVYzw8hzS2EIWKu8Oa0zn0PTevD2YeJNd4G8mDqO0vz5hloIc7pFsq/exQUB/kFozfCsnvhW8P+MPN0LpuSpptBQTsLWbM5BH0hd46HoWcneDdlMvVrUcgsTPmmSroIkLIEUo+Y2iN5eQHPPp85Cw="
- VEXRISCV_REGRESSION_CONFIG_COUNT=0
- VEXRISCV_REGRESSION_CONFIG_COUNT=5
- VEXRISCV_REGRESSION_CONFIG_COUNT=5
- VEXRISCV_REGRESSION_CONFIG_COUNT=5
- VEXRISCV_REGRESSION_CONFIG_COUNT=5
before_install:
# JDK fix
@ -34,11 +38,9 @@ before_install:
# Verilator
- sudo apt-get install git make autoconf g++ flex bison -y # First time prerequisites
- git clone http://git.veripool.org/git/verilator # Only first time
- unset VERILATOR_ROOT # For bash
- wget https://www.veripool.org/ftp/verilator-4.012.tgz
- tar xvzf verilator*.t*gz
- cd verilator
- git pull # Make sure we're up-to-date
- git checkout verilator_3_916
- autoconf # Create ./configure script
- ./configure
- make -j$(nproc)
@ -48,6 +50,7 @@ before_install:
- git clone https://github.com/SpinalHDL/SpinalHDL.git -b dev
- cd VexRiscv
- git submodule update --init --recursive
#- curl -T README.md -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/README.md
#- curl -X POST -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/publish
#- sbt compile

View File

@ -33,7 +33,7 @@ case class ExceptionCause() extends Bundle{
trait ExceptionService{
def newExceptionPort(stage : Stage, priority : Int = 0) : Flow[ExceptionCause]
def isExceptionPending() : Bool
def isExceptionPending(stage : Stage) : Bool
}
trait PrivilegeService{

View File

@ -40,13 +40,13 @@ cd VexRiscv
Run regressions =>
sbt "runMain vexriscv.demo.LinuxGen -r"
cd src/test/cpp/regression
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yes SUPERVISOR=yes CSR=yes COMPRESSED=no LRSC=yes AMO=yes REDO=10 TRACE=no
make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yes SUPERVISOR=yes MMU=yes CSR=yes COMPRESSED=no MUL=yes DIV=yes LRSC=yes AMO=yes REDO=10 TRACE=no COREMARK=yes LINUX_REGRESSION=yes
Run linux in simulation (Require the machime mode emulator compiled in SIM mode) =>
sbt "runMain vexriscv.demo.LinuxGen"
cd src/test/cpp/regression
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=no LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes EMULATOR=../../../main/c/emulator/build/emulator.bin VMLINUX=$BUILDROOT/output/images/Image DTB=$BUILDROOT/board/spinal/vexriscv_sim/rv32.dtb RAMDISK=$BUILDROOT/output/images/rootfs.cpio TRACE=no FLOW_INFO=no
make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=no LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes EMULATOR=../../../main/c/emulator/build/emulator.bin VMLINUX=$BUILDROOT/output/images/Image DTB=$BUILDROOT/board/spinal/vexriscv_sim/rv32.dtb RAMDISK=$BUILDROOT/output/images/rootfs.cpio WITH_USER_IO=yes TRACE=no FLOW_INFO=no
Run linux with QEMU (Require the machime mode emulator compiled in QEMU mode)
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
@ -94,10 +94,12 @@ rm VexRiscv.v
cp $DATA/VexRiscv.v ../../../..
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=no LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes EMULATOR=$DATA/emulator.bin VMLINUX=$DATA/vmlinux.bin DTB=$DATA/rv32.dtb RAMDISK=$DATA/rootfs.cpio TRACE=no FLOW_INFO=no
make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=no SUPERVISOR=yes CSR=yes COMPRESSED=no MUL=yes DIV=yes LRSC=yes AMO=yes MMU=yes REDO=1 TRACE=no LINUX_REGRESSION=yes
qemu-system-riscv32 -nographic -machine virt -m 1536M -device loader,file=$DATA/emulator.bin,addr=0x80000000,cpu-num=0 -device loader,file=$DATA/rv32.dtb,addr=0xC3000000 -device loader,file=$DATA/vmlinux.bin,addr=0xC0000000 -device loader,file=$DATA/rootfs.cpio,addr=0xc2000000
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yess SUPERVISOR=yes CSR=yes COMPRESSED=yes MUL=yes DIV=yes LRSC=yes AMO=yes REDO=1 TRACE=no LINUX_REGRESSION=yes
program ../../../main/c/emulator/build/emulator.bin 0x80000000 verify
soc.loadBin(EMULATOR, 0x80000000);
@ -149,12 +151,12 @@ object LinuxGen {
new IBusCachedPlugin(
resetVector = 0x80000000l,
compressedGen = false,
prediction = DYNAMIC_TARGET,
prediction = NONE,
injectorStage = false,
config = InstructionCacheConfig(
cacheSize = 4096*4,
cacheSize = 4096*1,
bytePerLine = 32,
wayCount = 4,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
@ -184,9 +186,9 @@ object LinuxGen {
dBusCmdSlavePipe = true,
dBusRspSlavePipe = true,
config = new DataCacheConfig(
cacheSize = 4096*4,
cacheSize = 4096*1,
bytePerLine = 32,
wayCount = 4,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,

View File

@ -163,3 +163,8 @@ class MuraxApb3Timer extends Component{
interruptCtrl.io.inputs(1) := timerB.io.full
io.interrupt := interruptCtrl.io.pendings.orR
}
object MuraxApb3TimerGen extends App{
SpinalVhdl(new MuraxApb3Timer())
}

View File

@ -327,8 +327,8 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
interface
}
var exceptionPending : Bool = null
override def isExceptionPending(): Bool = exceptionPending
var exceptionPendings : Vec[Bool] = null
override def isExceptionPending(stage : Stage): Bool = exceptionPendings(pipeline.stages.indexOf(stage))
var jumpInterface : Flow[UInt] = null
var timerInterrupt, externalInterrupt, softwareInterrupt : Bool = null
@ -420,7 +420,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
jumpInterface.valid := False
jumpInterface.payload.assignDontCare()
exceptionPending = False
exceptionPendings = Vec(Bool, pipeline.stages.length)
timerInterrupt = in Bool() setName("timerInterrupt")
externalInterrupt = in Bool() setName("externalInterrupt")
softwareInterrupt = in Bool() setName("softwareInterrupt") default(False)
@ -721,7 +721,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
//Avoid the PC register of the last stage to change durring an exception handleing (Used to fill Xepc)
stages.last.dontSample.getOrElseUpdate(PC, ArrayBuffer[Bool]()) += exceptionValids.last
exceptionPending setWhen(exceptionValidsRegs.orR)
exceptionPendings := exceptionValidsRegs
} else null

View File

@ -292,7 +292,8 @@ class DBusCachedPlugin(config : DataCacheConfig,
val forceDatapath = False
when(dBusAccess.cmd.valid){
decode.arbitration.haltByOther := True
when(!stagesFromExecute.map(_.arbitration.isValid).orR && !pipeline.service(classOf[ExceptionService]).isExceptionPending()){
val exceptionService = pipeline.service(classOf[ExceptionService])
when(!stagesFromExecute.map(s => s.arbitration.isValid || exceptionService.isExceptionPending(s)).orR){
when(!cache.io.cpu.redo) {
cache.io.cpu.execute.isValid := True
dBusAccess.cmd.ready := !execute.arbitration.isStuck

View File

@ -66,8 +66,8 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
}
}
val defaults = mutable.HashMap[Stageable[_ <: BaseType], BaseType]()
val encodings = mutable.HashMap[MaskedLiteral,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]]()
val defaults = mutable.LinkedHashMap[Stageable[_ <: BaseType], BaseType]()
val encodings = mutable.LinkedHashMap[MaskedLiteral,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]]()
var decodeExceptionPort : Flow[ExceptionCause] = null
@ -105,7 +105,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
} else {
var offset = 0
var defaultValue, defaultCare = BigInt(0)
val offsetOf = mutable.HashMap[Stageable[_ <: BaseType], Int]()
val offsetOf = mutable.LinkedHashMap[Stageable[_ <: BaseType], Int]()
//Build defaults value and field offset map
stageables.foreach(e => {
@ -191,8 +191,8 @@ object DecodingBench extends App{
object Symplify{
val cache = mutable.HashMap[Bits,mutable.HashMap[Masked,Bool]]()
def getCache(addr : Bits) = cache.getOrElseUpdate(addr,mutable.HashMap[Masked,Bool]())
val cache = mutable.LinkedHashMap[Bits,mutable.LinkedHashMap[Masked,Bool]]()
def getCache(addr : Bits) = cache.getOrElseUpdate(addr,mutable.LinkedHashMap[Masked,Bool]())
//Generate terms logic for the given input
def logicOf(input : Bits,terms : Seq[Masked]) = terms.map(t => getCache(input).getOrElseUpdate(t,t === input)).asBits.orR

View File

@ -21,7 +21,7 @@ class HaltOnExceptionPlugin() extends Plugin[VexRiscv] with ExceptionService {
exceptionPortsInfos += ExceptionPortInfo(interface,stage,priority)
interface
}
override def isExceptionPending(): Bool = False
override def isExceptionPending(stage : Stage): Bool = False
override def build(pipeline: VexRiscv): Unit = {

View File

@ -220,17 +220,18 @@ class IBusSimplePlugin(resetVector : BigInt,
pipeline plug new FetchArea(pipeline) {
var cmd = Stream(IBusSimpleCmd())
iBus.cmd << (if(cmdForkPersistence && !cmdForkOnSecondStage) cmd.s2mPipe() else cmd)
val cmdWithS2mPipe = cmdForkPersistence && (!cmdForkOnSecondStage || mmuBus != null)
iBus.cmd << (if(cmdWithS2mPipe) cmd.s2mPipe() else cmd)
//Avoid sending to many iBus cmd
val pendingCmd = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
val pendingCmdNext = pendingCmd + cmd.fire.asUInt - iBus.rsp.fire.asUInt
pendingCmd := pendingCmdNext
def cmdForkStage = if(!cmdForkPersistence || !cmdForkOnSecondStage) iBusRsp.stages(if(cmdForkOnSecondStage) 1 else 0) else iBusRsp.stages(1)
val secondStagePersistence = cmdForkPersistence && cmdForkOnSecondStage && !cmdWithS2mPipe
def cmdForkStage = if(!secondStagePersistence) iBusRsp.stages(if(cmdForkOnSecondStage) 1 else 0) else iBusRsp.stages(1)
val cmdFork = if(!cmdForkPersistence || !cmdForkOnSecondStage) new Area {
val cmdFork = if(!secondStagePersistence) new Area {
//This implementation keep the cmd on the bus until it's executed or the the pipeline is flushed
def stage = cmdForkStage
stage.halt setWhen(stage.input.valid && (!cmd.valid || !cmd.ready))
@ -255,7 +256,7 @@ class IBusSimplePlugin(resetVector : BigInt,
mmuBus.cmd.isValid := cmdForkStage.input.valid
mmuBus.cmd.virtualAddress := cmdForkStage.input.payload
mmuBus.cmd.bypassTranslation := False
mmuBus.end := !cmdForkStage.output.fire || flush
mmuBus.end := cmdForkStage.output.fire || flush
cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00"
@ -265,7 +266,10 @@ class IBusSimplePlugin(resetVector : BigInt,
cmd.valid := False
}
cmdForkStage.halt.setWhen(mmuBus.busy)
when(mmuBus.busy){
cmdForkStage.input.valid := False
cmdForkStage.input.ready := False
}
val joinCtx = stageXToIBusRsp(cmdForkStage, mmuBus.rsp)
}
@ -280,7 +284,7 @@ class IBusSimplePlugin(resetVector : BigInt,
val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt
when(flush) {
if(cmdForkOnSecondStage && cmdForkPersistence)
if(secondStagePersistence)
discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt
else
discardCounter := (if(cmdForkOnSecondStage) pendingCmdNext else pendingCmd - iBus.rsp.fire.asUInt)
@ -318,7 +322,7 @@ class IBusSimplePlugin(resetVector : BigInt,
if(memoryTranslatorPortConfig != null){
redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling)
redoBranch.valid := redoRequired && iBusRsp.readyForError
redoBranch.payload := stages.last.input.payload
redoBranch.payload := decode.input(PC)
decode.arbitration.flushAll setWhen(redoBranch.valid)
}

View File

@ -149,8 +149,6 @@ class MmuPlugin(ioRange : UInt => Bool,
}
val shared = new Area {
val busy = Reg(Bool) init(False)
val State = new SpinalEnum{
val IDLE, L1_CMD, L1_RSP, L0_CMD, L0_RSP = newElement()
}
@ -182,7 +180,6 @@ class MmuPlugin(ioRange : UInt => Bool,
is(State.IDLE){
for(port <- portsInfo.sortBy(_.priority)){
when(port.bus.cmd.isValid && port.bus.rsp.refilling){
busy := True
vpn(1) := port.bus.cmd.virtualAddress(31 downto 22)
vpn(0) := port.bus.cmd.virtualAddress(21 downto 12)
portId := port.id

View File

@ -1634,6 +1634,7 @@ public:
cout << "FAIL " << name << " at PC=" << hex << setw(8) << top->VexRiscv->writeBack_PC << dec; //<< " seed : " << seed <<
if(riscvRefEnable) cout << hex << " REF PC=" << riscvRef.lastPc << " REF I=" << riscvRef.lastInstruction << dec;
cout << " time=" << i;
cout << endl;
cycles += instanceCycles;
@ -3059,29 +3060,22 @@ public:
//#endif
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
termios stdinRestoreSettings;
void stdinNonBuffered(){
static struct termios old, new1;
tcgetattr(STDIN_FILENO, &old); /* grab old terminal i/o settings */
new1 = old; /* make new settings same as old settings */
new1.c_lflag &= ~ICANON; /* disable buffered i/o */
tcgetattr(STDIN_FILENO, &old); // grab old terminal i/o settings
new1 = old; // make new settings same as old settings
new1.c_lflag &= ~ICANON; // disable buffered i/o
new1.c_lflag &= ~ECHO;
tcsetattr(STDIN_FILENO, TCSANOW, &new1); /* use these new terminal i/o settings now */
tcsetattr(STDIN_FILENO, TCSANOW, &new1); // use these new terminal i/o settings now
setvbuf(stdin, NULL, _IONBF, 0);
stdinRestoreSettings = old;
}
void stdoutNonBuffered(){
setvbuf(stdout, NULL, _IONBF, 0);
}
void stdinRestore(){
tcsetattr(STDIN_FILENO, TCSANOW, &stdinRestoreSettings); /* use these new terminal i/o settings now */
}
bool stdinNonEmpty(){
struct timeval tv;
@ -3094,6 +3088,17 @@ bool stdinNonEmpty(){
return (FD_ISSET(0, &fds));
}
void stdoutNonBuffered(){
setvbuf(stdout, NULL, _IONBF, 0);
}
void stdinRestore(){
tcsetattr(STDIN_FILENO, TCSANOW, &stdinRestoreSettings);
}
void my_handler(int s){
printf("Caught signal %d\n",s);
stdinRestore();
@ -3111,23 +3116,39 @@ void captureCtrlC(){
sigaction(SIGINT, &sigIntHandler, NULL);
}
#ifdef LINUX_SOC
#if defined(LINUX_SOC) || defined(LINUX_REGRESSION)
#include <queue>
class LinuxSoc : public Workspace{
public:
queue <char> customCin;
void pushCin(string m){
for(char& c : m) {
customCin.push(c);
}
}
LinuxSoc(string name) : Workspace(name) {
#ifdef WITH_USER_IO
stdinNonBuffered();
stdoutNonBuffered();
captureCtrlC();
#endif
stdoutNonBuffered();
}
virtual ~LinuxSoc(){
#ifdef WITH_USER_IO
stdinRestore();
#endif
}
virtual bool isDBusCheckedRegion(uint32_t address){ return true;}
virtual bool isPerifRegion(uint32_t addr) { return (addr & 0xF0000000) == 0xF0000000 || (addr & 0xE0000000) == 0xE0000000;}
virtual bool isMmuRegion(uint32_t addr) { return true; }
virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
if(isPerifRegion(addr)) switch(addr){
//TODO Emulate peripherals here
@ -3137,18 +3158,24 @@ public:
case 0xFFFFFFEC: if(wr) mTimeCmp = (mTimeCmp & 0x00000000FFFFFFFF) | (((uint64_t)*data) << 32); else *data = mTimeCmp >> 32; break;
case 0xFFFFFFF8:
if(wr){
cout << (char)*data;
logTraces << (char)*data;
char c = (char)*data;
cout << c;
logTraces << c;
logTraces.flush();
onStdout(c);
} else {
#ifdef WITH_USER_IO
if(stdinNonEmpty()){
char c;
read(0, &c, 1);
*data = c;
//cout << "getchar " << c << endl;
} else
#endif
if(!customCin.empty()){
*data = customCin.front();
customCin.pop();
} else {
*data = -1;
//cout << "getchar NONE" << endl;
}
}
break;
@ -3158,7 +3185,43 @@ public:
Workspace::dBusAccess(addr,wr,size,mask,data,error);
}
virtual void onStdout(char c){
}
};
class LinuxRegression: public LinuxSoc{
public:
string pendingLine = "";
bool pendingLineContain(string m) {
return strstr(pendingLine.c_str(), m.c_str()) != NULL;
}
enum State{LOGIN, ECHO_FILE, HEXDUMP, HEXDUMP_CHECK, PASS};
State state = LOGIN;
LinuxRegression(string name) : LinuxSoc(name) {
}
~LinuxRegression() {
}
virtual void onStdout(char c){
pendingLine += c;
switch(state){
case LOGIN: if (pendingLineContain("buildroot login:")) { pushCin("root\n"); state = ECHO_FILE; } break;
case ECHO_FILE: if (pendingLineContain("# ")) { pushCin("echo \"miaou\" > test.txt\n"); state = HEXDUMP; pendingLine = "";} break;
case HEXDUMP: if (pendingLineContain("# ")) { pushCin("hexdump -C test.txt\n"); state = HEXDUMP_CHECK; pendingLine = "";} break;
case HEXDUMP_CHECK: if (pendingLineContain("00000000 6d 69 61 6f 75 0a ")) { pushCin(""); state = PASS; pendingLine = "";} break;
case PASS: if (pendingLineContain("# ")) { pass(); } break;
}
if(c == '\n' || pendingLine.length() > 200) pendingLine = "";
}
};
#endif
string riscvTestMain[] = {
@ -3490,7 +3553,7 @@ int main(int argc, char **argv, char **env) {
soc.loadBin(DTB, 0xC3000000);
soc.loadBin(RAMDISK, 0xC2000000);
#endif
//soc.setIStall(true); //TODO It currently improve speed but should be removed later
//soc.setIStall(true);
//soc.setDStall(true);
soc.bootAt(0x80000000);
soc.run(0);
@ -3500,6 +3563,10 @@ int main(int argc, char **argv, char **env) {
}
#endif
// #ifdef MMU
// redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
// #endif
@ -3722,15 +3789,36 @@ int main(int argc, char **argv, char **env) {
queue <std::function<void()>> tasksSelected(std::deque<std::function<void()>>(tasks.begin(), tasks.end()));
multiThreadedExecute(tasksSelected);
#endif
#if defined(LINUX_REGRESSION)
{
LinuxRegression soc("linux");
#ifndef DEBUG_PLUGIN_EXTERNAL
soc.withRiscvRef();
soc.loadBin(EMULATOR, 0x80000000);
soc.loadBin(VMLINUX, 0xC0000000);
soc.loadBin(DTB, 0xC3000000);
soc.loadBin(RAMDISK, 0xC2000000);
#endif
//soc.setIStall(true);
//soc.setDStall(true);
soc.bootAt(0x80000000);
soc.run(153995602l*6);
// soc.run((470000000l + 2000000) / 2);
// soc.run(438700000l/2);
}
#endif
}
uint64_t duration = timer_end(startedAt);
cout << endl << "****************************************************************" << endl;
cout << "Had simulate " << Workspace::cycles << " clock cycles in " << duration*1e-9 << " s (" << Workspace::cycles / (duration*1e-6) << " Khz)" << endl;
if(Workspace::successCounter == Workspace::testsCounter)
cout << "SUCCESS " << Workspace::successCounter << "/" << Workspace::testsCounter << endl;
cout << "REGRESSION SUCCESS " << Workspace::successCounter << "/" << Workspace::testsCounter << endl;
else
cout<< "FAILURE " << Workspace::testsCounter - Workspace::successCounter << "/" << Workspace::testsCounter << endl;
cout<< "REGRESSION FAILURE " << Workspace::testsCounter - Workspace::successCounter << "/" << Workspace::testsCounter << endl;
cout << "****************************************************************" << endl << endl;

View File

@ -34,6 +34,7 @@ COMPRESSED?=no
SUPERVISOR?=no
STOP_ON_ERROR?=no
COREMARK=no
WITH_USER_IO?=no
ADDCFLAGS += -CFLAGS -DIBUS_${IBUS}
ADDCFLAGS += -CFLAGS -DDBUS_${DBUS}
@ -66,6 +67,31 @@ ifeq ($(LINUX_SOC),yes)
ADDCFLAGS += -CFLAGS -DEMULATOR='\"$(EMULATOR)\"'
endif
ARCH_LINUX=rv32i
ifeq ($(MUL),yes)
ifeq ($(DIV),yes)
ARCH_LINUX:=$(ARCH_LINUX)m
endif
endif
ARCH_LINUX:=$(ARCH_LINUX)a
ifeq ($(COMPRESSED),yes)
ARCH_LINUX:=$(ARCH_LINUX)c
endif
ifeq ($(LINUX_REGRESSION),yes)
ifneq ($(ARCH_LINUX),rv32iac)
ifneq ($(ARCH_LINUX),rv32ia)
ADDCFLAGS += -CFLAGS -DLINUX_REGRESSION
ADDCFLAGS += -CFLAGS -DARCH_LINUX='\"$(ARCH_LINUX)\"'
ADDCFLAGS += -CFLAGS -DVMLINUX='\"../../resources/VexRiscvRegressionData/sim/linux/$(ARCH_LINUX)/Image\"'
ADDCFLAGS += -CFLAGS -DDTB='\"../../resources/VexRiscvRegressionData/sim/linux/$(ARCH_LINUX)/rv32.dtb\"'
ADDCFLAGS += -CFLAGS -DRAMDISK='\"../../resources/VexRiscvRegressionData/sim/linux/$(ARCH_LINUX)/rootfs.cpio\"'
ADDCFLAGS += -CFLAGS -DEMULATOR='\"../../resources/VexRiscvRegressionData/sim/linux/emulator/emulator.bin\"'
endif
endif
endif
ifeq ($(FLOW_INFO),yes)
ADDCFLAGS += -CFLAGS -DFLOW_INFO
endif
@ -93,6 +119,10 @@ endif
ifeq ($(IBUS_TC),yes)
ADDCFLAGS += -CFLAGS -DIBUS_TC=yes
endif
ifeq ($(WITH_USER_IO),yes)
ADDCFLAGS += -CFLAGS -DWITH_USER_IO=yes
endif
ifeq ($(COMPRESSED),yes)
ADDCFLAGS += -CFLAGS -DCOMPRESSED

@ -0,0 +1 @@
Subproject commit 77b66d304f888369176fb9ac2f9d6302dd4d276d

View File

@ -49,6 +49,11 @@ object VexRiscvUniverse{
val universes = List(CATCH_ALL, MMU)
}
object Hack{
var dCounter = 0
}
class ShiftDimension extends VexRiscvDimension("Shift") {
override def randomPositionImpl(universes: Seq[ConfigUniverse], r: Random) = random(r, List(
new VexRiscvPosition("FullLate") {
@ -287,13 +292,14 @@ class IBusDimension extends VexRiscvDimension("IBus") {
override def instructionAnticipatedOk() = injectorStage
}
} else {
val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL)
val compressed = r.nextBoolean()
val tighlyCoupled = r.nextBoolean()
val tighlyCoupled = r.nextBoolean() && !catchAll
// val tighlyCoupled = false
val prediction = random(r, List(NONE, STATIC, DYNAMIC, DYNAMIC_TARGET))
val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL)
val relaxedPcCalculation, twoCycleCache, injectorStage = r.nextBoolean()
val twoCycleRam = r.nextBoolean() && twoCycleCache
val bytePerLine = List(8,16,32,64)(r.nextInt(4))
var cacheSize = 0
var wayCount = 0
do{
@ -301,7 +307,7 @@ class IBusDimension extends VexRiscvDimension("IBus") {
wayCount = 1 << r.nextInt(3)
}while(cacheSize/wayCount < 512 || (catchAll && cacheSize/wayCount > 4096))
new VexRiscvPosition("Cached" + (if(twoCycleCache) "2cc" else "") + (if(injectorStage) "Injstage" else "") + (if(twoCycleRam) "2cr" else "") + "S" + cacheSize + "W" + wayCount + (if(relaxedPcCalculation) "Relax" else "") + (if(compressed) "Rvc" else "") + prediction.getClass.getTypeName().replace("$","")+ (if(tighlyCoupled)"Tc" else "")) with InstructionAnticipatedPosition{
new VexRiscvPosition("Cached" + (if(twoCycleCache) "2cc" else "") + (if(injectorStage) "Injstage" else "") + (if(twoCycleRam) "2cr" else "") + "S" + cacheSize + "W" + wayCount + "BPL" + bytePerLine + (if(relaxedPcCalculation) "Relax" else "") + (if(compressed) "Rvc" else "") + prediction.getClass.getTypeName().replace("$","")+ (if(tighlyCoupled)"Tc" else "")) with InstructionAnticipatedPosition{
override def testParam = "IBUS=CACHED" + (if(compressed) " COMPRESSED=yes" else "") + (if(tighlyCoupled)" IBUS_TC=yes" else "")
override def applyOn(config: VexRiscvConfig): Unit = {
val p = new IBusCachedPlugin(
@ -313,7 +319,7 @@ class IBusDimension extends VexRiscvDimension("IBus") {
memoryTranslatorPortConfig = mmuConfig,
config = InstructionCacheConfig(
cacheSize = cacheSize,
bytePerLine = 32,
bytePerLine = bytePerLine,
wayCount = wayCount,
addressWidth = 32,
cpuDataWidth = 32,
@ -344,32 +350,37 @@ class DBusDimension extends VexRiscvDimension("DBus") {
val mmuConfig = if(catchAll) MmuPortConfig( portTlbSize = 4) else null
if(r.nextDouble() < 0.4){
val withLrSc = catchAll
val earlyInjection = r.nextBoolean()
new VexRiscvPosition("Simple" + (if(earlyInjection) "Early" else "Late")) {
override def testParam = "DBUS=SIMPLE"
override def testParam = "DBUS=SIMPLE " + (if(withLrSc) "LRSC=yes " else "")
override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new DBusSimplePlugin(
catchAddressMisaligned = catchAll,
catchAccessFault = catchAll,
earlyInjection = earlyInjection,
memoryTranslatorPortConfig = mmuConfig
memoryTranslatorPortConfig = mmuConfig,
withLrSc = withLrSc
)
// override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition])
}
} else {
val bytePerLine = List(8,16,32,64)(r.nextInt(4))
var cacheSize = 0
var wayCount = 0
val withLrSc = catchAll
val withAmo = catchAll && r.nextBoolean()
do{
cacheSize = 512 << r.nextInt(5)
wayCount = 1 << r.nextInt(3)
}while(cacheSize/wayCount < 512 || (catchAll && cacheSize/wayCount > 4096))
new VexRiscvPosition("Cached" + "S" + cacheSize + "W" + wayCount) {
override def testParam = "DBUS=CACHED"
new VexRiscvPosition("Cached" + "S" + cacheSize + "W" + wayCount + "BPL" + bytePerLine) {
override def testParam = "DBUS=CACHED " + (if(withLrSc) "LRSC=yes " else "") + (if(withAmo) "AMO=yes " else "")
override def applyOn(config: VexRiscvConfig): Unit = {
config.plugins += new DBusCachedPlugin(
config = new DataCacheConfig(
cacheSize = cacheSize,
bytePerLine = 32,
bytePerLine = bytePerLine,
wayCount = wayCount,
addressWidth = 32,
cpuDataWidth = 32,
@ -377,7 +388,8 @@ class DBusDimension extends VexRiscvDimension("DBus") {
catchAccessError = catchAll,
catchIllegal = catchAll,
catchUnaligned = catchAll,
withLrSc = false
withLrSc = withLrSc,
withAmo = withAmo
),
memoryTranslatorPortConfig = mmuConfig
)
@ -421,14 +433,14 @@ class MmuDimension extends VexRiscvDimension("DBus") {
trait CatchAllPosition
//TODO CSR without exception
class CsrDimension(freertos : String) extends VexRiscvDimension("Csr") {
override def randomPositionImpl(universes: Seq[ConfigUniverse], r: Random) = {
val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL)
if(catchAll){
new VexRiscvPosition("All") with CatchAllPosition{
override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.linuxFull(0x80000020l))
override def testParam = s"FREERTOS=$freertos"
override def testParam = s"FREERTOS=$freertos LINUX_REGRESSION=yes SUPERVISOR=yes"
}
} else if(r.nextDouble() < 0.2){
new VexRiscvPosition("AllNoException") with CatchAllPosition{
@ -504,7 +516,7 @@ class TestIndividualFeatures extends FunSuite {
new HazardDimension,
new RegFileDimension,
new SrcDimension,
new CsrDimension(sys.env.getOrElse("VEXRISCV_REGRESSION_FREERTOS_COUNT", "yes")),
new CsrDimension("no"),//sys.env.getOrElse("VEXRISCV_REGRESSION_FREERTOS_COUNT", "4")), TODO
new DecoderDimension,
new DebugDimension,
new MmuDimension
@ -541,14 +553,14 @@ class TestIndividualFeatures extends FunSuite {
test(prefix + name + "_test") {
val debug = false
val stdCmd = (if(debug) "make clean run REDO=1 TRACE=yes TRACE_ACCESS=yes STOP_ON_ERROR=yes DHRYSTONE=no THREAD_COUNT=1 TRACE_START=0 " else s"make clean run REDO=10 TRACE=no THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", Runtime.getRuntime().availableProcessors().toString)} ") + s" SEED=${testSeed} "
val debug = true
val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=9999924910246l FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=yes THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", Runtime.getRuntime().availableProcessors().toString)} ") + s" SEED=${testSeed} "
// val stdCmd = "make clean run REDO=40 DHRYSTONE=no STOP_ON_ERROR=yes TRACE=yess "
val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ")
println(testCmd)
val str = doCmd(testCmd)
assert(!str.contains("FAIL") && !str.contains("Broken pipe"))
assert(str.contains("REGRESSION SUCCESS") && !str.contains("Broken pipe"))
// val intFind = "(\\d+\\.?)+".r
// val dmips = intFind.findFirstIn("DMIPS per Mhz\\: (\\d+.?)+".r.findAllIn(str).toList.last).get.toDouble
}
@ -556,8 +568,8 @@ class TestIndividualFeatures extends FunSuite {
// dimensions.foreach(d => d.positions.foreach(p => p.dimension = d))
// val testId : Option[mutable.HashSet[Int]] = None
// val seed = Random.nextLong()
val testId : Option[mutable.HashSet[Int]] = None
val seed = Random.nextLong()
// val testId = Some(mutable.HashSet(18,34,77,85,118,129,132,134,152,167,175,188,191,198,199)) //37/29 sp_flop_rv32i_O3
//val testId = Some(mutable.HashSet(18))
@ -565,13 +577,6 @@ class TestIndividualFeatures extends FunSuite {
// val seed = -2412372746600605141l
//// val testId = Some(mutable.HashSet[Int](0,28,45,93))
val testId = Some(mutable.HashSet[Int](69, 43))
//val testId = Some(mutable.HashSet[Int]( 43))
val seed = -8485282932516819277l
val rand = new Random(seed)
test("Info"){
@ -589,6 +594,7 @@ class TestIndividualFeatures extends FunSuite {
val testSeed = rand.nextInt()
if(testId.isEmpty || testId.get.contains(i))
doTest(positions," random_" + i + "_", testSeed)
Hack.dCounter += 1
}
// println(s"${usedPositions.size}/$positionsCount positions")