Rename some regression commands

Add Avalon regressions (PASS)
DebugModule read response is now 1 cycle latency
This commit is contained in:
Charles Papon 2017-07-21 14:32:49 +02:00
parent 575a410786
commit 52f5020e64
5 changed files with 283 additions and 62 deletions

View file

@ -132,7 +132,7 @@ To run tests (need the verilator simulator), go in the src/test/cpp/regression f
make clean run
# To test the GenSmallest CPU
make clean run IBUS=IBUS_SIMPLE DBUS=DBUS_SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no
make clean run IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no
```
## Interactive debug of the simulated CPU via GDB OpenOCD and Verilator

View file

@ -46,7 +46,7 @@ case class DebugExtensionBus() extends Bundle with IMasterSlave{
}
def fromAvalon(): AvalonMM ={
val bus = AvalonMM(AvalonMMConfig.fixed(addressWidth = 8,dataWidth = 32, readLatency = 0))
val bus = AvalonMM(AvalonMMConfig.fixed(addressWidth = 8,dataWidth = 32, readLatency = 1))
cmd.valid := bus.read || bus.write
cmd.wr := bus.write
@ -99,13 +99,6 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
import pipeline.config._
debugClockDomain {pipeline plug new Area{
val busReadDataReg = Reg(Bits(32 bit))
when(writeBack.arbitration.isValid) {
busReadDataReg := writeBack.output(REGFILE_WRITE_DATA)
}
io.bus.cmd.ready := True
io.bus.rsp.data := busReadDataReg
val insertDecodeInstruction = False
val firstCycle = RegNext(False) setWhen (io.bus.cmd.ready)
val secondCycle = RegNext(firstCycle)
@ -117,6 +110,21 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
val isPipBusy = isPipActive || RegNext(isPipActive)
val haltedByBreak = RegInit(False)
val busReadDataReg = Reg(Bits(32 bit))
when(writeBack.arbitration.isValid) {
busReadDataReg := writeBack.output(REGFILE_WRITE_DATA)
}
io.bus.cmd.ready := True
io.bus.rsp.data := busReadDataReg
when(!RegNext(io.bus.cmd.address(2))){
io.bus.rsp.data(0) := resetIt
io.bus.rsp.data(1) := haltIt
io.bus.rsp.data(2) := isPipBusy
io.bus.rsp.data(3) := haltedByBreak
io.bus.rsp.data(4) := stepIt
}
when(io.bus.cmd.valid) {
switch(io.bus.cmd.address(2 downto 2)) {
is(0) {
@ -125,12 +133,6 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
resetIt setWhen (io.bus.cmd.data(16)) clearWhen (io.bus.cmd.data(24))
haltIt setWhen (io.bus.cmd.data(17)) clearWhen (io.bus.cmd.data(25))
haltedByBreak clearWhen (io.bus.cmd.data(25))
} otherwise {
io.bus.rsp.data(0) := resetIt
io.bus.rsp.data(1) := haltIt
io.bus.rsp.data(2) := isPipBusy
io.bus.rsp.data(3) := haltedByBreak
io.bus.rsp.data(4) := stepIt
}
}
is(1) {
@ -138,7 +140,7 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
insertDecodeInstruction := True
decode.arbitration.isValid setWhen (firstCycle)
decode.arbitration.haltIt setWhen (secondCycle)
io.bus.cmd.ready := !(firstCycle || secondCycle || isPipActive)
io.bus.cmd.ready := !(firstCycle || secondCycle || decode.arbitration.isValid)
}
}
}

View file

@ -229,19 +229,19 @@ object TestsWorkspace {
toplevel.rework {
var iBus : AvalonMM = null
for (plugin <- toplevel.config.plugins) plugin match {
/*case plugin: IBusCachedPlugin => {
case plugin: IBusCachedPlugin => {
plugin.iBus.asDirectionLess() //Unset IO properties of iBus
iBus = master(plugin.iBus.toAvalon())
.setName("iBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
}*/
/* case plugin: DBusCachedPlugin => {
}
case plugin: DBusCachedPlugin => {
plugin.dBus.asDirectionLess()
master(plugin.dBus.toAvalon())
.setName("dBusAvalon")
.addTag(ClockDomainTag(ClockDomain.current))
}*/
/* case plugin: DebugPlugin => {
}
case plugin: DebugPlugin => {
plugin.io.bus.asDirectionLess()
slave(plugin.io.bus.fromAvalon())
.setName("debugBusAvalon")
@ -250,7 +250,7 @@ object TestsWorkspace {
plugin.io.resetOut
.addTag(ResetEmitterTag(plugin.debugClockDomain))
.parent = null //Avoid the io bundle to be interpreted as a QSys conduit
}*/
}
case _ =>
}
for (plugin <- toplevel.config.plugins) plugin match {

View file

@ -495,7 +495,6 @@ public:
#ifdef IBUS_CACHED
class IBusCached : public SimElement{
public:
uint32_t inst_next = VL_RANDOM_I(32);
bool error_next = false;
uint32_t pendingCount = 0;
uint32_t address;
@ -536,6 +535,63 @@ public:
};
#endif
#ifdef IBUS_CACHED_AVALON
#include <queue>
struct IBusCachedAvalonTask{
uint32_t address;
uint32_t pendingCount;
};
class IBusCachedAvalon : public SimElement{
public:
uint32_t inst_next = VL_RANDOM_I(32);
bool error_next = false;
queue<IBusCachedAvalonTask> tasks;
Workspace *ws;
VVexRiscv* top;
IBusCachedAvalon(Workspace* ws){
this->ws = ws;
this->top = ws->top;
}
virtual void onReset(){
top->iBusAvalon_waitRequestn = 1;
top->iBusAvalon_readDataValid = 0;
}
virtual void preCycle(){
if (top->iBusAvalon_read && top->iBusAvalon_waitRequestn) {
assertEq(top->iBusAvalon_address & 3,0);
IBusCachedAvalonTask task;
task.address = top->iBusAvalon_address;
task.pendingCount = top->iBusAvalon_burstCount;
tasks.push(task);
}
}
virtual void postCycle(){
bool error;
top->iBusAvalon_readDataValid = 0;
if(!tasks.empty() && (!ws->iStall || VL_RANDOM_I(7) < 100)){
uint32_t &address = tasks.front().address;
uint32_t &pendingCount = tasks.front().pendingCount;
ws->iBusAccess(address,&top->iBusAvalon_readData,&error);
//top->iBus_rsp_payload_error = error; //TODO
pendingCount--;
address = (address & ~0x1F) + ((address + 4) & 0x1F);
top->iBusAvalon_readDataValid = 1;
if(pendingCount == 0)
tasks.pop();
}
if(ws->iStall)
top->iBusAvalon_waitRequestn = VL_RANDOM_I(7) < 100;
}
};
#endif
#ifdef DBUS_SIMPLE
class DBusSimple : public SimElement{
public:
@ -632,6 +688,69 @@ public:
};
#endif
#ifdef DBUS_CACHED_AVALON
#include <queue>
struct DBusCachedAvalonTask{
uint32_t data;
bool error;
};
class DBusCachedAvalon : public SimElement{
public:
uint32_t beatCounter = 0;
queue<DBusCachedAvalonTask> rsps;
Workspace *ws;
VVexRiscv* top;
DBusCachedAvalon(Workspace* ws){
this->ws = ws;
this->top = ws->top;
}
virtual void onReset(){
top->dBusAvalon_waitRequestn = 1;
top->dBusAvalon_readDataValid = 0;
}
virtual void preCycle(){
if ((top->dBusAvalon_read || top->dBusAvalon_write) && top->dBusAvalon_waitRequestn) {
if(top->dBusAvalon_write){
bool error_next = false;
ws->dBusAccess(top->dBusAvalon_address + beatCounter * 4,1,2,top->dBusAvalon_byteEnable,&top->dBusAvalon_writeData,&error_next);
beatCounter++;
if(beatCounter == top->dBusAvalon_burstCount){
beatCounter = 0;
}
} else {
for(int beat = 0;beat < top->dBusAvalon_burstCount;beat++){
DBusCachedAvalonTask rsp;
ws->dBusAccess(top->dBusAvalon_address + beat * 4,0,2,0,&rsp.data,&rsp.error);
rsps.push(rsp);
}
}
}
}
virtual void postCycle(){
if(!rsps.empty() && (!ws->dStall || VL_RANDOM_I(7) < 100)){
DBusCachedAvalonTask rsp = rsps.front();
rsps.pop();
//top->dBus_rsp_payload_error = rsp.error; //TODO
top->dBusAvalon_readData = rsp.data;
top->dBusAvalon_readDataValid = 1;
} else{
top->dBusAvalon_readDataValid = 0;
top->dBusAvalon_readData = VL_RANDOM_I(32);
//top->dBus_rsp_payload_error = VL_RANDOM_I(1); //TODO
}
top->dBusAvalon_waitRequestn = (ws->dStall ? VL_RANDOM_I(7) < 100 : 1);
}
};
#endif
#ifdef DEBUG_PLUGIN
#include <stdio.h>
@ -659,6 +778,12 @@ bool SetSocketBlockingEnabled(int fd, bool blocking)
#endif
}
struct DebugPluginTask{
bool wr;
uint32_t address;
uint32_t data;
};
class DebugPlugin : public SimElement{
public:
Workspace *ws;
@ -670,6 +795,8 @@ public:
socklen_t addr_size;
char buffer[1024];
uint32_t timeSpacer = 0;
bool taskValid = false;
DebugPluginTask task;
DebugPlugin(Workspace* ws){
this->ws = ws;
@ -725,7 +852,6 @@ public:
}
virtual void onReset(){
top->debug_bus_cmd_valid = 0;
top->debugReset = 1;
}
@ -741,41 +867,21 @@ public:
clientHandle = -1;
}
bool readRsp = false;
bool wasReady = false;
virtual void preCycle(){
}
virtual void postCycle(){
if(clientHandle == -1){
clientHandle = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
if(clientHandle != -1)
printf("CONNECTED\n");
}
if(top->debug_bus_cmd_valid && top->debug_bus_cmd_ready && !top->debug_bus_cmd_payload_wr){
readRsp = true;
}
if(readRsp){
if(clientHandle != -1){
if(send(clientHandle,&top->debug_bus_rsp_data,4,0) == -1) connectionReset();
}
readRsp = false;
}
wasReady = top->debug_bus_cmd_ready;
}
virtual void postCycle(){
top->reset = top->debug_resetOut;
if(wasReady){
if(top->debug_bus_cmd_valid)
timeSpacer = 50;
top->debug_bus_cmd_valid = 0;
top->debug_bus_cmd_payload_wr = VL_RANDOM_I(1);
top->debug_bus_cmd_payload_address = VL_RANDOM_I(8);
top->debug_bus_cmd_payload_data = VL_RANDOM_I(32);
}
if(clientHandle != -1 && top->debug_bus_cmd_valid == 0){
if(clientHandle != -1 && taskValid == false){
if(timeSpacer == 0){
int requiredSize = 1 + 1 + 4 + 4;
int n;
@ -792,11 +898,12 @@ public:
if((address & ~ 0x4) == 0xF00F0000){
assert(size == 2);
timeSpacer = 50;
top->debug_bus_cmd_valid = 1;
top->debug_bus_cmd_payload_wr = wr;
top->debug_bus_cmd_payload_address = address;
top->debug_bus_cmd_payload_data = data;
taskValid = true;
task.wr = wr;
task.address = address;
task.data = data;
} else {
bool dummy;
//printf("wr=%d size=%d address=%x data=%x\n",wr,size,address,data);
@ -820,9 +927,114 @@ public:
}
}
}
void sendRsp(uint32_t data){
if(clientHandle != -1){
if(send(clientHandle,&data,4,0) == -1) connectionReset();
}
}
};
#endif
#ifdef DEBUG_PLUGIN_STD
class DebugPluginStd : public DebugPlugin{
public:
DebugPluginStd(Workspace* ws) : DebugPlugin(ws){
}
virtual void onReset(){
DebugPlugin::onReset();
top->debug_bus_cmd_valid = 0;
}
bool rspFire = false;
virtual void preCycle(){
DebugPlugin::preCycle();
if(rspFire){
sendRsp(top->debug_bus_rsp_data);
rspFire = false;
}
if(top->debug_bus_cmd_valid && top->debug_bus_cmd_ready){
taskValid = false;
if(!top->debug_bus_cmd_payload_wr){
rspFire = true;
}
}
}
virtual void postCycle(){
DebugPlugin::postCycle();
if(taskValid){
top->debug_bus_cmd_valid = 1;
top->debug_bus_cmd_payload_wr = task.wr;
top->debug_bus_cmd_payload_address = task.address;
top->debug_bus_cmd_payload_data = task.data;
}else {
top->debug_bus_cmd_valid = 0;
top->debug_bus_cmd_payload_wr = VL_RANDOM_I(1);
top->debug_bus_cmd_payload_address = VL_RANDOM_I(8);
top->debug_bus_cmd_payload_data = VL_RANDOM_I(32);
}
}
};
#endif
#ifdef DEBUG_PLUGIN_AVALON
class DebugPluginAvalon : public DebugPlugin{
public:
DebugPluginAvalon(Workspace* ws) : DebugPlugin(ws){
}
virtual void onReset(){
DebugPlugin::onReset();
top->debugBusAvalon_read = 0;
top->debugBusAvalon_write = 0;
}
bool rspFire = false;
virtual void preCycle(){
DebugPlugin::preCycle();
if(rspFire){
sendRsp(top->debugBusAvalon_readData);
rspFire = false;
}
if((top->debugBusAvalon_read || top->debugBusAvalon_write) && top->debugBusAvalon_waitRequestn){
taskValid = false;
if(top->debugBusAvalon_read){
rspFire = true;
}
}
}
virtual void postCycle(){
DebugPlugin::postCycle();
if(taskValid){
top->debugBusAvalon_write = task.wr;
top->debugBusAvalon_read = !task.wr;
top->debugBusAvalon_address = task.address;
top->debugBusAvalon_writeData = task.data;
}else {
top->debugBusAvalon_write = 0;
top->debugBusAvalon_read = 0;
top->debugBusAvalon_address = VL_RANDOM_I(8);
top->debugBusAvalon_writeData = VL_RANDOM_I(32);
}
}
};
#endif
void Workspace::fillSimELements(){
#ifdef IBUS_SIMPLE
simElements.push_back(new IBusSimple(this));
@ -839,8 +1051,14 @@ void Workspace::fillSimELements(){
#ifdef DBUS_CACHED
simElements.push_back(new DBusCached(this));
#endif
#ifdef DEBUG_PLUGIN
simElements.push_back(new DebugPlugin(this));
#ifdef DBUS_CACHED_AVALON
simElements.push_back(new DBusCachedAvalon(this));
#endif
#ifdef DEBUG_PLUGIN_STD
simElements.push_back(new DebugPluginStd(this));
#endif
#ifdef DEBUG_PLUGIN_AVALON
simElements.push_back(new DebugPluginAvalon(this));
#endif
}

View file

@ -1,5 +1,5 @@
IBUS?=IBUS_CACHED
DBUS?=DBUS_CACHED
IBUS?=CACHED
DBUS?=CACHED
TRACE?=no
TRACE_ACCESS?=no
TRACE_START=0
@ -7,7 +7,7 @@ MUL?=yes
DIV?=yes
CSR?=yes
MMU?=yes
DEBUG_PLUGIN?=yes
DEBUG_PLUGIN?=STD
DEBUG_PLUGIN_EXTERNAL?=no
DHRYSTONE=yes
FREE_RTOS=no
@ -16,8 +16,8 @@ REF=no
TRACE_WITH_TIME=no
REF_TIME=no
ADDCFLAGS += -CFLAGS -D${IBUS}
ADDCFLAGS += -CFLAGS -D${DBUS}
ADDCFLAGS += -CFLAGS -DIBUS_${IBUS}
ADDCFLAGS += -CFLAGS -DDBUS_${DBUS}
ADDCFLAGS += -CFLAGS -DREDO=${REDO}
ADDCFLAGS += -CFLAGS -pthread
@ -59,8 +59,9 @@ ifeq ($(TRACE_ACCESS),yes)
ADDCFLAGS += -CFLAGS -DTRACE_ACCESS
endif
ifeq ($(DEBUG_PLUGIN),yes)
ifneq ($(DEBUG_PLUGIN),no)
ADDCFLAGS += -CFLAGS -DDEBUG_PLUGIN
ADDCFLAGS += -CFLAGS -DDEBUG_PLUGIN_${DEBUG_PLUGIN}
endif
ifeq ($(DEBUG_PLUGIN_EXTERNAL),yes)