#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:
parent
2810ff05b0
commit
e47b76fa67
|
@ -0,0 +1,3 @@
|
|||
[submodule "src/test/resources/VexRiscvRegressionData"]
|
||||
path = src/test/resources/VexRiscvRegressionData
|
||||
url = ../VexRiscvRegressionData.git
|
15
.travis.yml
15
.travis.yml
|
@ -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
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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())
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue