Add LitexSoC workspace / linux loading. Need to emulate peripherals and adapte the kernel now. Probably also need some machine mode emulation Software time !
This commit is contained in:
parent
0656a49332
commit
6c0608f0dd
|
@ -26,8 +26,25 @@ import vexriscv._
|
||||||
import vexriscv.ip._
|
import vexriscv.ip._
|
||||||
import vexriscv.plugin._
|
import vexriscv.plugin._
|
||||||
|
|
||||||
|
/*
|
||||||
|
Setup things =>
|
||||||
|
git clone https://github.com/SpinalHDL/SpinalHDL.git -b dev
|
||||||
|
git clone https://github.com/SpinalHDL/VexRiscv.git -b linux
|
||||||
|
cd VexRiscv
|
||||||
|
|
||||||
|
Run regressions =>
|
||||||
|
sbt "runMain vexriscv.demo.LinuxGen -r"
|
||||||
|
cd src/test/cpp/regression
|
||||||
|
make run DBUS=SIMPLE IBUS=SIMPLE DHRYSTONE=yes SUPERVISOR=yes CSR=yes COMPRESSED=yes REDO=10 TRACE=no
|
||||||
|
|
||||||
|
Run linux =>
|
||||||
|
sbt "runMain vexriscv.demo.LinuxGen"
|
||||||
|
cd src/test/cpp/regression
|
||||||
|
make run DBUS=SIMPLE IBUS=SIMPLE SUPERVISOR=yes CSR=yes COMPRESSED=yes LITEX=yes VMLINUX=/home/spinalvm/hdl/linuxDave/vmlinux.bin RAMDISK=/home/spinalvm/hdl/linuxDave/initramdisk_dave TRACE=no
|
||||||
|
*/
|
||||||
|
|
||||||
object LinuxGen {
|
object LinuxGen {
|
||||||
def configFull(withMmu : Boolean = true) = {
|
def configFull(litex : Boolean, withMmu : Boolean) = {
|
||||||
val config = VexRiscvConfig(
|
val config = VexRiscvConfig(
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
|
@ -171,15 +188,15 @@ object LinuxGen {
|
||||||
)
|
)
|
||||||
if(withMmu) config.plugins += new MmuPlugin(
|
if(withMmu) config.plugins += new MmuPlugin(
|
||||||
virtualRange = a => True,
|
virtualRange = a => True,
|
||||||
ioRange = _(31 downto 28) === 0xF,
|
ioRange = (x => if(litex) x(31 downto 28) === 0xB || x(31 downto 28) === 0xE else x(31 downto 28) === 0xF),
|
||||||
allowUserIo = true
|
allowUserIo = true
|
||||||
)
|
)
|
||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main(args: Array[String]) {
|
def main(args: Array[String]) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// import spinal.core.sim._
|
// import spinal.core.sim._
|
||||||
// SimConfig.withConfig(SpinalConfig(mergeAsyncProcess = false, anonymSignalPrefix = "zz_")).allOptimisation.compile(new VexRiscv(configFull)).doSimUntilVoid{ dut =>
|
// SimConfig.withConfig(SpinalConfig(mergeAsyncProcess = false, anonymSignalPrefix = "zz_")).allOptimisation.compile(new VexRiscv(configFull)).doSimUntilVoid{ dut =>
|
||||||
// dut.clockDomain.forkStimulus(10)
|
// dut.clockDomain.forkStimulus(10)
|
||||||
|
@ -199,7 +216,10 @@ object LinuxGen {
|
||||||
SpinalConfig(mergeAsyncProcess = true).generateVerilog {
|
SpinalConfig(mergeAsyncProcess = true).generateVerilog {
|
||||||
|
|
||||||
|
|
||||||
val toplevel = new VexRiscv(configFull())
|
val toplevel = new VexRiscv(configFull(
|
||||||
|
litex = !args.contains("-r"),
|
||||||
|
withMmu = true
|
||||||
|
))
|
||||||
// val toplevel = new VexRiscv(configLight)
|
// val toplevel = new VexRiscv(configLight)
|
||||||
// val toplevel = new VexRiscv(configTest)
|
// val toplevel = new VexRiscv(configTest)
|
||||||
|
|
||||||
|
@ -288,13 +308,13 @@ object LinuxSyntesisBench extends App{
|
||||||
val withoutMmu = new Rtl {
|
val withoutMmu = new Rtl {
|
||||||
override def getName(): String = "VexRiscv Without Mmu"
|
override def getName(): String = "VexRiscv Without Mmu"
|
||||||
override def getRtlPath(): String = "VexRiscvWithoutMmu.v"
|
override def getRtlPath(): String = "VexRiscvWithoutMmu.v"
|
||||||
SpinalVerilog(new VexRiscv(LinuxGen.configFull(withMmu=false)).setDefinitionName(getRtlPath().split("\\.").head))
|
SpinalVerilog(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = false)).setDefinitionName(getRtlPath().split("\\.").head))
|
||||||
}
|
}
|
||||||
|
|
||||||
val withMmu = new Rtl {
|
val withMmu = new Rtl {
|
||||||
override def getName(): String = "VexRiscv With Mmu"
|
override def getName(): String = "VexRiscv With Mmu"
|
||||||
override def getRtlPath(): String = "VexRiscvWithMmu.v"
|
override def getRtlPath(): String = "VexRiscvWithMmu.v"
|
||||||
SpinalVerilog(new VexRiscv(LinuxGen.configFull(withMmu=true)).setDefinitionName(getRtlPath().split("\\.").head))
|
SpinalVerilog(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = true)).setDefinitionName(getRtlPath().split("\\.").head))
|
||||||
}
|
}
|
||||||
|
|
||||||
val rtls = List(withoutMmu, withMmu)
|
val rtls = List(withoutMmu, withMmu)
|
||||||
|
@ -316,7 +336,7 @@ object LinuxSyntesisBench extends App{
|
||||||
object LinuxSim extends App{
|
object LinuxSim extends App{
|
||||||
import spinal.core.sim._
|
import spinal.core.sim._
|
||||||
|
|
||||||
SimConfig.allOptimisation.compile(new VexRiscv(LinuxGen.configFull())).doSim{dut =>
|
SimConfig.allOptimisation.compile(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = true))).doSim{dut =>
|
||||||
// dut.clockDomain.forkStimulus(10)
|
// dut.clockDomain.forkStimulus(10)
|
||||||
// dut.clockDomain.forkSimSpeedPrinter()
|
// dut.clockDomain.forkSimSpeedPrinter()
|
||||||
// dut.plugins.foreach{
|
// dut.plugins.foreach{
|
||||||
|
|
|
@ -151,6 +151,26 @@ void loadHexImpl(string path,Memory* mem) {
|
||||||
delete [] content;
|
delete [] content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadBinImpl(string path,Memory* mem, uint32_t offset) {
|
||||||
|
FILE *fp = fopen(&path[0], "r");
|
||||||
|
if(fp == 0){
|
||||||
|
cout << path << " not found" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
uint32_t size = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
char* content = new char[size];
|
||||||
|
fread(content, 1, size, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
for(int byteId = 0; byteId < size;byteId++){
|
||||||
|
*(mem->get(offset + byteId)) = content[byteId];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] content;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define TEXTIFY(A) #A
|
#define TEXTIFY(A) #A
|
||||||
|
@ -965,8 +985,8 @@ public:
|
||||||
uint32_t seed;
|
uint32_t seed;
|
||||||
|
|
||||||
bool withInstructionReadCheck = true;
|
bool withInstructionReadCheck = true;
|
||||||
void setIStall(bool enable) { iStall = enable; }
|
Workspace* setIStall(bool enable) { iStall = enable; return this; }
|
||||||
void setDStall(bool enable) { dStall = enable; }
|
Workspace* setDStall(bool enable) { dStall = enable; return this; }
|
||||||
|
|
||||||
ofstream regTraces;
|
ofstream regTraces;
|
||||||
ofstream memTraces;
|
ofstream memTraces;
|
||||||
|
@ -1027,7 +1047,7 @@ public:
|
||||||
}
|
}
|
||||||
if(address & (size-1) != 0)
|
if(address & (size-1) != 0)
|
||||||
cout << "Ref did a unaligned read" << endl;
|
cout << "Ref did a unaligned read" << endl;
|
||||||
if((address & 0xF0000000) == 0xF0000000){
|
if(ws->isPerifRegion(address)){
|
||||||
MemRead t = periphRead.front();
|
MemRead t = periphRead.front();
|
||||||
if(t.address != address || t.size != size){
|
if(t.address != address || t.size != size){
|
||||||
fail();
|
fail();
|
||||||
|
@ -1043,7 +1063,7 @@ public:
|
||||||
virtual void dWrite(int32_t address, int32_t size, uint32_t data){
|
virtual void dWrite(int32_t address, int32_t size, uint32_t data){
|
||||||
if(address & (size-1) != 0)
|
if(address & (size-1) != 0)
|
||||||
cout << "Ref did a unaligned write" << endl;
|
cout << "Ref did a unaligned write" << endl;
|
||||||
if((address & 0xF0000000) == 0xF0000000){
|
if(ws->isPerifRegion(address)){
|
||||||
MemWrite w;
|
MemWrite w;
|
||||||
w.address = address;
|
w.address = address;
|
||||||
w.size = size;
|
w.size = size;
|
||||||
|
@ -1119,6 +1139,12 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Workspace* loadBin(string path, uint32_t offset){
|
||||||
|
loadBinImpl(path,&mem, offset);
|
||||||
|
loadBinImpl(path,&riscvRef.mem, offset);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
Workspace* setCyclesPerSecond(double value){
|
Workspace* setCyclesPerSecond(double value){
|
||||||
cyclesPerSecond = value;
|
cyclesPerSecond = value;
|
||||||
return this;
|
return this;
|
||||||
|
@ -1135,108 +1161,25 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void iBusAccess(uint32_t addr, uint32_t *data, bool *error) {
|
virtual bool isPerifRegion(uint32_t addr) { return false; }
|
||||||
|
|
||||||
|
virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error) {
|
||||||
if(addr % 4 != 0) {
|
if(addr % 4 != 0) {
|
||||||
//cout << "Warning, unaligned IBusAccess : " << addr << endl;
|
cout << "Warning, unaligned IBusAccess : " << addr << endl;
|
||||||
// fail();
|
fail();
|
||||||
}
|
}
|
||||||
*data = ( (mem[addr + 0] << 0)
|
*data = ( (mem[addr + 0] << 0)
|
||||||
| (mem[addr + 1] << 8)
|
| (mem[addr + 1] << 8)
|
||||||
| (mem[addr + 2] << 16)
|
| (mem[addr + 2] << 16)
|
||||||
| (mem[addr + 3] << 24));
|
| (mem[addr + 3] << 24));
|
||||||
*error = addr == 0xF00FFF60u;
|
*error = false;
|
||||||
iBusAccessPatch(addr,data,error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void iBusAccessPatch(uint32_t addr, uint32_t *data, bool *error){}
|
|
||||||
|
|
||||||
virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
|
virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
|
||||||
assertEq(addr % (1 << size), 0);
|
assertEq(addr % (1 << size), 0);
|
||||||
*error = addr == 0xF00FFF60u;
|
if(isPerifRegion(addr)){
|
||||||
if(wr){
|
|
||||||
memTraces <<
|
|
||||||
#ifdef TRACE_WITH_TIME
|
|
||||||
(currentTime
|
|
||||||
#ifdef REF
|
|
||||||
-2
|
|
||||||
#endif
|
|
||||||
) <<
|
|
||||||
#endif
|
|
||||||
" : WRITE mem" << (1 << size) << "[" << addr << "] = " << *data << endl;
|
|
||||||
for(uint32_t b = 0;b < (1 << size);b++){
|
|
||||||
uint32_t offset = (addr+b)&0x3;
|
|
||||||
if((mask >> offset) & 1 == 1)
|
|
||||||
*mem.get(addr + b) = *data >> (offset*8);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(addr){
|
|
||||||
case 0xF0010000u: {
|
|
||||||
cout << mem[0xF0010000u];
|
|
||||||
logTraces << (char)mem[0xF0010000u];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifdef EXTERNAL_INTERRUPT
|
|
||||||
case 0xF0011000u: top->externalInterrupt = *data & 1; break;
|
|
||||||
#endif
|
|
||||||
#ifdef SUPERVISOR
|
|
||||||
case 0xF0012000u: top->externalInterruptS = *data & 1; break;
|
|
||||||
#endif
|
|
||||||
#ifdef CSR
|
|
||||||
case 0xF0013000u: top->softwareInterrupt = *data & 1; break;
|
|
||||||
#endif
|
|
||||||
case 0xF00FFF00u: {
|
|
||||||
cout << mem[0xF00FFF00u];
|
|
||||||
logTraces << (char)mem[0xF00FFF00u];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifndef DEBUG_PLUGIN_EXTERNAL
|
|
||||||
case 0xF00FFF20u:
|
|
||||||
if(*data == 0)
|
|
||||||
pass();
|
|
||||||
else
|
|
||||||
fail();
|
|
||||||
break;
|
|
||||||
case 0xF00FFF24u:
|
|
||||||
cout << "TEST ERROR CODE " << *data << endl;
|
|
||||||
fail();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case 0xF00FFF48u: mTimeCmp = (mTimeCmp & 0xFFFFFFFF00000000) | *data;break;
|
|
||||||
case 0xF00FFF4Cu: mTimeCmp = (mTimeCmp & 0x00000000FFFFFFFF) | (((uint64_t)*data) << 32); /*cout << "mTimeCmp <= " << mTimeCmp << endl; */break;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
*data = VL_RANDOM_I(32);
|
|
||||||
for(uint32_t b = 0;b < (1 << size);b++){
|
|
||||||
uint32_t offset = (addr+b)&0x3;
|
|
||||||
*data &= ~(0xFF << (offset*8));
|
|
||||||
*data |= mem[addr + b] << (offset*8);
|
|
||||||
}
|
|
||||||
switch(addr){
|
|
||||||
case 0xF00FFF10u:
|
|
||||||
*data = mTime;
|
|
||||||
#ifdef REF_TIME
|
|
||||||
mTime += 100000;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case 0xF00FFF40u: *data = mTime; break;
|
|
||||||
case 0xF00FFF44u: *data = mTime >> 32; break;
|
|
||||||
case 0xF00FFF48u: *data = mTimeCmp; break;
|
|
||||||
case 0xF00FFF4Cu: *data = mTimeCmp >> 32; break;
|
|
||||||
case 0xF0010004u: *data = ~0; break;
|
|
||||||
}
|
|
||||||
memTraces <<
|
|
||||||
#ifdef TRACE_WITH_TIME
|
|
||||||
(currentTime
|
|
||||||
#ifdef REF
|
|
||||||
-2
|
|
||||||
#endif
|
|
||||||
) <<
|
|
||||||
#endif
|
|
||||||
" : READ mem" << (1 << size) << "[" << addr << "] = " << *data << endl;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if((addr & 0xF0000000) == 0xF0000000){
|
|
||||||
if(wr){
|
if(wr){
|
||||||
CpuRef::MemWrite w;
|
CpuRef::MemWrite w;
|
||||||
w.address = addr;
|
w.address = addr;
|
||||||
|
@ -1251,8 +1194,61 @@ public:
|
||||||
r.error = *error;
|
r.error = *error;
|
||||||
riscvRef.periphRead.push(r);
|
riscvRef.periphRead.push(r);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if(wr){
|
||||||
|
memTraces <<
|
||||||
|
#ifdef TRACE_WITH_TIME
|
||||||
|
(currentTime
|
||||||
|
#ifdef REF
|
||||||
|
-2
|
||||||
|
#endif
|
||||||
|
) <<
|
||||||
|
#endif
|
||||||
|
" : WRITE mem" << (1 << size) << "[" << addr << "] = " << *data << endl;
|
||||||
|
for(uint32_t b = 0;b < (1 << size);b++){
|
||||||
|
uint32_t offset = (addr+b)&0x3;
|
||||||
|
if((mask >> offset) & 1 == 1)
|
||||||
|
*mem.get(addr + b) = *data >> (offset*8);
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
*data = VL_RANDOM_I(32);
|
||||||
|
for(uint32_t b = 0;b < (1 << size);b++){
|
||||||
|
uint32_t offset = (addr+b)&0x3;
|
||||||
|
*data &= ~(0xFF << (offset*8));
|
||||||
|
*data |= mem[addr + b] << (offset*8);
|
||||||
|
}
|
||||||
|
memTraces <<
|
||||||
|
#ifdef TRACE_WITH_TIME
|
||||||
|
(currentTime
|
||||||
|
#ifdef REF
|
||||||
|
-2
|
||||||
|
#endif
|
||||||
|
) <<
|
||||||
|
#endif
|
||||||
|
" : READ mem" << (1 << size) << "[" << addr << "] = " << *data << endl;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void periphAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error){
|
||||||
|
// if(wr){
|
||||||
|
// CpuRef::MemWrite w;
|
||||||
|
// w.address = addr;
|
||||||
|
// w.size = 1 << size;
|
||||||
|
// w.data = *data;
|
||||||
|
// riscvRef.periphWrites.push(w);
|
||||||
|
// } else {
|
||||||
|
// CpuRef::MemRead r;
|
||||||
|
// r.address = addr;
|
||||||
|
// r.size = 1 << size;
|
||||||
|
// r.data = *data;
|
||||||
|
// r.error = *error;
|
||||||
|
// riscvRef.periphRead.push(r);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
virtual void postReset() {}
|
virtual void postReset() {}
|
||||||
virtual void checks(){}
|
virtual void checks(){}
|
||||||
virtual void pass(){ throw success();}
|
virtual void pass(){ throw success();}
|
||||||
|
@ -1266,6 +1262,7 @@ public:
|
||||||
}
|
}
|
||||||
Workspace* run(uint64_t timeout = 5000){
|
Workspace* run(uint64_t timeout = 5000){
|
||||||
// cout << "Start " << name << endl;
|
// cout << "Start " << name << endl;
|
||||||
|
if(timeout == 0) timeout = 0x7FFFFFFFFFFFFFFF;
|
||||||
|
|
||||||
currentTime = 4;
|
currentTime = 4;
|
||||||
// init trace dump
|
// init trace dump
|
||||||
|
@ -1507,6 +1504,91 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class WorkspaceRegression : public Workspace {
|
||||||
|
public:
|
||||||
|
|
||||||
|
WorkspaceRegression(string name) : Workspace(name){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isPerifRegion(uint32_t addr) { return (addr & 0xF0000000) == 0xF0000000;}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error){
|
||||||
|
Workspace::iBusAccess(addr,data,error);
|
||||||
|
*error = addr == 0xF00FFF60u;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
|
||||||
|
if(wr){
|
||||||
|
switch(addr){
|
||||||
|
case 0xF0010000u: {
|
||||||
|
cout << (char)*data;
|
||||||
|
logTraces << (char)*data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef EXTERNAL_INTERRUPT
|
||||||
|
case 0xF0011000u: top->externalInterrupt = *data & 1; break;
|
||||||
|
#endif
|
||||||
|
#ifdef SUPERVISOR
|
||||||
|
case 0xF0012000u: top->externalInterruptS = *data & 1; break;
|
||||||
|
#endif
|
||||||
|
#ifdef CSR
|
||||||
|
case 0xF0013000u: top->softwareInterrupt = *data & 1; break;
|
||||||
|
#endif
|
||||||
|
case 0xF00FFF00u: {
|
||||||
|
cout << (char)*data;
|
||||||
|
logTraces << (char)*data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef DEBUG_PLUGIN_EXTERNAL
|
||||||
|
case 0xF00FFF20u:
|
||||||
|
if(*data == 0)
|
||||||
|
pass();
|
||||||
|
else
|
||||||
|
fail();
|
||||||
|
break;
|
||||||
|
case 0xF00FFF24u:
|
||||||
|
cout << "TEST ERROR CODE " << *data << endl;
|
||||||
|
fail();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 0xF00FFF48u: mTimeCmp = (mTimeCmp & 0xFFFFFFFF00000000) | *data;break;
|
||||||
|
case 0xF00FFF4Cu: mTimeCmp = (mTimeCmp & 0x00000000FFFFFFFF) | (((uint64_t)*data) << 32); /*cout << "mTimeCmp <= " << mTimeCmp << endl; */break;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
switch(addr){
|
||||||
|
case 0xF00FFF10u:
|
||||||
|
*data = mTime;
|
||||||
|
#ifdef REF_TIME
|
||||||
|
mTime += 100000;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 0xF00FFF40u: *data = mTime; break;
|
||||||
|
case 0xF00FFF44u: *data = mTime >> 32; break;
|
||||||
|
case 0xF00FFF48u: *data = mTimeCmp; break;
|
||||||
|
case 0xF00FFF4Cu: *data = mTimeCmp >> 32; break;
|
||||||
|
case 0xF0010004u: *data = ~0; break;
|
||||||
|
}
|
||||||
|
memTraces <<
|
||||||
|
#ifdef TRACE_WITH_TIME
|
||||||
|
(currentTime
|
||||||
|
#ifdef REF
|
||||||
|
-2
|
||||||
|
#endif
|
||||||
|
) <<
|
||||||
|
#endif
|
||||||
|
" : READ mem" << (1 << size) << "[" << addr << "] = " << *data << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
*error = addr == 0xF00FFF60u;
|
||||||
|
Workspace::dBusAccess(addr,wr,size,mask,data,error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef IBUS_SIMPLE
|
#ifdef IBUS_SIMPLE
|
||||||
class IBusSimple : public SimElement{
|
class IBusSimple : public SimElement{
|
||||||
|
@ -2407,13 +2489,13 @@ uint32_t regFileWriteRefArray[][2] = {
|
||||||
testA2ReagFileWriteRef
|
testA2ReagFileWriteRef
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestA : public Workspace{
|
class TestA : public WorkspaceRegression{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
uint32_t regFileWriteRefIndex = 0;
|
uint32_t regFileWriteRefIndex = 0;
|
||||||
|
|
||||||
TestA() : Workspace("testA") {
|
TestA() : WorkspaceRegression("testA") {
|
||||||
loadHex("../../resources/hex/testA.hex");
|
loadHex("../../resources/hex/testA.hex");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2431,13 +2513,13 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestX28 : public Workspace{
|
class TestX28 : public WorkspaceRegression{
|
||||||
public:
|
public:
|
||||||
uint32_t refIndex = 0;
|
uint32_t refIndex = 0;
|
||||||
uint32_t *ref;
|
uint32_t *ref;
|
||||||
uint32_t refSize;
|
uint32_t refSize;
|
||||||
|
|
||||||
TestX28(string name, uint32_t *ref, uint32_t refSize) : Workspace(name) {
|
TestX28(string name, uint32_t *ref, uint32_t refSize) : WorkspaceRegression(name) {
|
||||||
this->ref = ref;
|
this->ref = ref;
|
||||||
this->refSize = refSize;
|
this->refSize = refSize;
|
||||||
loadHex("../../resources/hex/" + name + ".hex");
|
loadHex("../../resources/hex/" + name + ".hex");
|
||||||
|
@ -2457,9 +2539,9 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class RiscvTest : public Workspace{
|
class RiscvTest : public WorkspaceRegression{
|
||||||
public:
|
public:
|
||||||
RiscvTest(string name) : Workspace(name) {
|
RiscvTest(string name) : WorkspaceRegression(name) {
|
||||||
loadHex("../../resources/hex/" + name + ".hex");
|
loadHex("../../resources/hex/" + name + ".hex");
|
||||||
bootAt(0x800000bcu);
|
bootAt(0x800000bcu);
|
||||||
}
|
}
|
||||||
|
@ -2494,16 +2576,17 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void iBusAccessPatch(uint32_t addr, uint32_t *data, bool *error){
|
virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error){
|
||||||
|
WorkspaceRegression::iBusAccess(addr,data,error);
|
||||||
if(*data == 0x0ff0000f) *data = 0x00000013;
|
if(*data == 0x0ff0000f) *data = 0x00000013;
|
||||||
if(*data == 0x00000073) *data = 0x00000013;
|
if(*data == 0x00000073) *data = 0x00000013;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
class Dhrystone : public Workspace{
|
class Dhrystone : public WorkspaceRegression{
|
||||||
public:
|
public:
|
||||||
string hexName;
|
string hexName;
|
||||||
Dhrystone(string name,string hexName,bool iStall, bool dStall) : Workspace(name) {
|
Dhrystone(string name,string hexName,bool iStall, bool dStall) : WorkspaceRegression(name) {
|
||||||
setIStall(iStall);
|
setIStall(iStall);
|
||||||
setDStall(dStall);
|
setDStall(dStall);
|
||||||
withRiscvRef();
|
withRiscvRef();
|
||||||
|
@ -2543,12 +2626,12 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Compliance : public Workspace{
|
class Compliance : public WorkspaceRegression{
|
||||||
public:
|
public:
|
||||||
string name;
|
string name;
|
||||||
ofstream out32;
|
ofstream out32;
|
||||||
int out32Counter = 0;
|
int out32Counter = 0;
|
||||||
Compliance(string name) : Workspace(name) {
|
Compliance(string name) : WorkspaceRegression(name) {
|
||||||
withRiscvRef();
|
withRiscvRef();
|
||||||
loadHex("../../resources/hex/" + name + ".elf.hex");
|
loadHex("../../resources/hex/" + name + ".elf.hex");
|
||||||
out32.open (name + ".out32");
|
out32.open (name + ".out32");
|
||||||
|
@ -2558,12 +2641,11 @@ public:
|
||||||
|
|
||||||
|
|
||||||
virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
|
virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
|
||||||
Workspace::dBusAccess(addr,wr,size,mask,data,error);
|
|
||||||
if(wr && addr == 0xF00FFF2C){
|
if(wr && addr == 0xF00FFF2C){
|
||||||
out32 << hex << setw(8) << std::setfill('0') << *data << dec;
|
out32 << hex << setw(8) << std::setfill('0') << *data << dec;
|
||||||
if(++out32Counter % 4 == 0) out32 << "\n";
|
if(++out32Counter % 4 == 0) out32 << "\n";
|
||||||
*error = 0;
|
|
||||||
}
|
}
|
||||||
|
WorkspaceRegression::dBusAccess(addr,wr,size,mask,data,error);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void checks(){
|
virtual void checks(){
|
||||||
|
@ -2621,7 +2703,7 @@ public:
|
||||||
#define RISCV_SPINAL_FLAGS_RESET_CLEAR 1<<24
|
#define RISCV_SPINAL_FLAGS_RESET_CLEAR 1<<24
|
||||||
#define RISCV_SPINAL_FLAGS_HALT_CLEAR 1<<25
|
#define RISCV_SPINAL_FLAGS_HALT_CLEAR 1<<25
|
||||||
|
|
||||||
class DebugPluginTest : public Workspace{
|
class DebugPluginTest : public WorkspaceRegression{
|
||||||
public:
|
public:
|
||||||
pthread_t clientThreadId;
|
pthread_t clientThreadId;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
@ -2761,7 +2843,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DebugPluginTest() : Workspace("DebugPluginTest") {
|
DebugPluginTest() : WorkspaceRegression("DebugPluginTest") {
|
||||||
loadHex("../../resources/hex/debugPlugin.hex");
|
loadHex("../../resources/hex/debugPlugin.hex");
|
||||||
pthread_create(&clientThreadId, NULL, &clientThreadWrapper, this);
|
pthread_create(&clientThreadId, NULL, &clientThreadWrapper, this);
|
||||||
noInstructionReadCheck();
|
noInstructionReadCheck();
|
||||||
|
@ -2779,6 +2861,28 @@ public:
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LITEX
|
||||||
|
class LitexSoC : public Workspace{
|
||||||
|
public:
|
||||||
|
|
||||||
|
LitexSoC(string name) : Workspace(name) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isPerifRegion(uint32_t addr) { return (addr & 0xF0000000) == 0xB0000000 || (addr & 0xF0000000) == 0xE0000000;}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
|
||||||
|
switch(addr){
|
||||||
|
//TODO Emulate peripherals here
|
||||||
|
}
|
||||||
|
|
||||||
|
Workspace::dBusAccess(addr,wr,size,mask,data,error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
string riscvTestMain[] = {
|
string riscvTestMain[] = {
|
||||||
//"rv32ui-p-simple",
|
//"rv32ui-p-simple",
|
||||||
"rv32ui-p-lui",
|
"rv32ui-p-lui",
|
||||||
|
@ -3045,17 +3149,30 @@ int main(int argc, char **argv, char **env) {
|
||||||
printf("BOOT\n");
|
printf("BOOT\n");
|
||||||
timespec startedAt = timer_start();
|
timespec startedAt = timer_start();
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LITEX
|
||||||
|
LitexSoC("linux")
|
||||||
|
.withRiscvRef()
|
||||||
|
->loadBin(VMLINUX, 0xc0000000)
|
||||||
|
->loadBin(RAMDISK, 0xc2000000)
|
||||||
|
->setIStall(false) //TODO It currently improve speed but should be removed later
|
||||||
|
->setDStall(false)
|
||||||
|
->bootAt(0xc0000000)
|
||||||
|
->run(0);
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
// #ifdef MMU
|
// #ifdef MMU
|
||||||
// redo(REDO,Workspace("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
|
// redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
|
||||||
// #endif
|
// #endif
|
||||||
// redo(REDO,Workspace("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
|
// redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
|
||||||
// return 0;
|
// return 0;
|
||||||
|
|
||||||
for(int idx = 0;idx < 1;idx++){
|
for(int idx = 0;idx < 1;idx++){
|
||||||
|
|
||||||
#if defined(DEBUG_PLUGIN_EXTERNAL) || defined(RUN_HEX)
|
#if defined(DEBUG_PLUGIN_EXTERNAL) || defined(RUN_HEX)
|
||||||
{
|
{
|
||||||
Workspace w("run");
|
WorkspaceRegression w("run");
|
||||||
#ifdef RUN_HEX
|
#ifdef RUN_HEX
|
||||||
//w.loadHex("/home/spinalvm/hdl/zephyr/zephyrSpinalHdl/samples/synchronization/build/zephyr/zephyr.hex");
|
//w.loadHex("/home/spinalvm/hdl/zephyr/zephyrSpinalHdl/samples/synchronization/build/zephyr/zephyr.hex");
|
||||||
w.loadHex(RUN_HEX);
|
w.loadHex(RUN_HEX);
|
||||||
|
@ -3154,10 +3271,10 @@ int main(int argc, char **argv, char **env) {
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
#ifdef MMU
|
#ifdef MMU
|
||||||
redo(REDO,Workspace("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
|
redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
|
||||||
#endif
|
#endif
|
||||||
#ifdef SUPERVISOR
|
#ifdef SUPERVISOR
|
||||||
redo(REDO,Workspace("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
|
redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_PLUGIN
|
#ifdef DEBUG_PLUGIN
|
||||||
|
@ -3166,16 +3283,16 @@ int main(int argc, char **argv, char **env) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CUSTOM_SIMD_ADD
|
#ifdef CUSTOM_SIMD_ADD
|
||||||
redo(REDO,Workspace("custom_simd_add").loadHex("../custom/simd_add/build/custom_simd_add.hex")->bootAt(0x00000000u)->run(50e3););
|
redo(REDO,WorkspaceRegression("custom_simd_add").loadHex("../custom/simd_add/build/custom_simd_add.hex")->bootAt(0x00000000u)->run(50e3););
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CUSTOM_CSR
|
#ifdef CUSTOM_CSR
|
||||||
redo(REDO,Workspace("custom_csr").loadHex("../custom/custom_csr/build/custom_csr.hex")->bootAt(0x00000000u)->run(50e3););
|
redo(REDO,WorkspaceRegression("custom_csr").loadHex("../custom/custom_csr/build/custom_csr.hex")->bootAt(0x00000000u)->run(50e3););
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef ATOMIC
|
#ifdef ATOMIC
|
||||||
redo(REDO,Workspace("atomic").loadHex("../custom/atomic/build/atomic.hex")->bootAt(0x00000000u)->run(10e3););
|
redo(REDO,WorkspaceRegression("atomic").loadHex("../custom/atomic/build/atomic.hex")->bootAt(0x00000000u)->run(10e3););
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DHRYSTONE
|
#ifdef DHRYSTONE
|
||||||
|
@ -3206,22 +3323,22 @@ int main(int argc, char **argv, char **env) {
|
||||||
#ifdef SEED
|
#ifdef SEED
|
||||||
srand48(SEED);
|
srand48(SEED);
|
||||||
#endif
|
#endif
|
||||||
//redo(1,Workspace("freeRTOS_demo").loadHex("../../resources/hex/freeRTOS_demo.hex")->bootAt(0x80000000u)->run(100e6);)
|
//redo(1,WorkspaceRegression("freeRTOS_demo").loadHex("../../resources/hex/freeRTOS_demo.hex")->bootAt(0x80000000u)->run(100e6);)
|
||||||
vector <std::function<void()>> tasks;
|
vector <std::function<void()>> tasks;
|
||||||
|
|
||||||
/*for(int redo = 0;redo < 4;redo++)*/{
|
/*for(int redo = 0;redo < 4;redo++)*/{
|
||||||
for(const string &name : freeRtosTests){
|
for(const string &name : freeRtosTests){
|
||||||
tasks.push_back([=]() { Workspace(name + "_rv32i_O0").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32i_O0.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O0").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32i_O0.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
||||||
tasks.push_back([=]() { Workspace(name + "_rv32i_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32i_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32i_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
||||||
#ifdef COMPRESSED
|
#ifdef COMPRESSED
|
||||||
tasks.push_back([=]() { Workspace(name + "_rv32ic_O0").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32ic_O0.hex")->bootAt(0x80000000u)->run(5e6*15);});
|
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O0").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32ic_O0.hex")->bootAt(0x80000000u)->run(5e6*15);});
|
||||||
tasks.push_back([=]() { Workspace(name + "_rv32ic_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32ic_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32ic_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
||||||
#endif
|
#endif
|
||||||
#if defined(MUL) && defined(DIV)
|
#if defined(MUL) && defined(DIV)
|
||||||
#ifdef COMPRESSED
|
#ifdef COMPRESSED
|
||||||
tasks.push_back([=]() { Workspace(name + "_rv32imac_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32imac_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32imac_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32imac_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
||||||
#else
|
#else
|
||||||
tasks.push_back([=]() { Workspace(name + "_rv32im_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32im_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32im_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32im_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,13 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(LITEX),yes)
|
||||||
|
ADDCFLAGS += -CFLAGS -DLITEX
|
||||||
|
ADDCFLAGS += -CFLAGS -DVMLINUX='\"$(VMLINUX)\"'
|
||||||
|
ADDCFLAGS += -CFLAGS -DRAMDISK='\"$(RAMDISK)\"'
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(shell grep timerInterrupt ../../../../VexRiscv.v -w),)
|
ifneq ($(shell grep timerInterrupt ../../../../VexRiscv.v -w),)
|
||||||
ADDCFLAGS += -CFLAGS -DTIMER_INTERRUPT
|
ADDCFLAGS += -CFLAGS -DTIMER_INTERRUPT
|
||||||
endif
|
endif
|
||||||
|
|
Loading…
Reference in New Issue