Add Murax SoC (very light, work on ice40)
This commit is contained in:
parent
1450077b70
commit
823ac353ff
|
@ -7,7 +7,7 @@ scalaVersion := "2.11.8"
|
|||
EclipseKeys.withSource := true
|
||||
|
||||
libraryDependencies ++= Seq(
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "0.10.14",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "0.10.14",
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "0.10.15",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "0.10.15",
|
||||
"org.yaml" % "snakeyaml" % "1.8"
|
||||
)
|
|
@ -2,6 +2,8 @@ package vexriscv.demo
|
|||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.bus.amba3.apb.{Apb3Decoder, Apb3Gpio, Apb3}
|
||||
import spinal.lib.bus.misc.SizeMapping
|
||||
import spinal.lib.com.jtag.Jtag
|
||||
import spinal.lib.com.uart.Uart
|
||||
import spinal.lib.io.TriStateArray
|
||||
|
@ -60,7 +62,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
val jtag = slave(Jtag())
|
||||
|
||||
//Peripherals IO
|
||||
// val gpioA = master(TriStateArray(32 bits))
|
||||
val gpioA = master(TriStateArray(32 bits))
|
||||
// val uart = master(Uart())
|
||||
}
|
||||
|
||||
|
@ -164,7 +166,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
plugin.externalInterrupt := BufferCC(io.coreInterrupt)
|
||||
plugin.timerInterrupt := timerCtrl.io.interrupt
|
||||
}*/
|
||||
case plugin : DebugPlugin => {
|
||||
case plugin : DebugPlugin => plugin.debugClockDomain{
|
||||
resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut))
|
||||
io.jtag <> plugin.io.bus.fromJtag()
|
||||
}
|
||||
|
@ -192,11 +194,11 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
when(mainBus.cmd.fire){
|
||||
rspTarget := dBus.cmd.valid
|
||||
}
|
||||
iBus.rsp.ready := mainBus.rsp.valid && rspTarget
|
||||
iBus.rsp.ready := mainBus.rsp.valid && !rspTarget
|
||||
iBus.rsp.inst := mainBus.rsp.data
|
||||
iBus.rsp.error := False
|
||||
|
||||
dBus.rsp.ready := mainBus.rsp.valid && !rspTarget
|
||||
dBus.rsp.ready := mainBus.rsp.valid && rspTarget
|
||||
dBus.rsp.data := mainBus.rsp.data
|
||||
dBus.rsp.error := False
|
||||
|
||||
|
@ -207,11 +209,11 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
}
|
||||
|
||||
val ram = new Area{
|
||||
def bus = mainBus//SimpleBus()
|
||||
val ram = Mem(Bits(32 bits), (onChipRamSize / 4).toInt)
|
||||
val bus = SimpleBus()
|
||||
val ram = Mem(Bits(32 bits), onChipRamSize / 4)
|
||||
bus.rsp.valid := RegNext(bus.cmd.fire && !bus.cmd.wr) init(False)
|
||||
bus.rsp.data := ram.readWriteSync(
|
||||
address = bus.cmd.address.resized,
|
||||
address = (bus.cmd.address >> 2).resized,
|
||||
data = bus.cmd.data,
|
||||
enable = bus.cmd.valid,
|
||||
write = bus.cmd.wr,
|
||||
|
@ -221,12 +223,76 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
}
|
||||
|
||||
|
||||
/* val interconnect = new Area {
|
||||
ramPort.enable := iBus.cmd.valid || dBus.cmd.valid
|
||||
ramPort.
|
||||
}
|
||||
*/
|
||||
|
||||
val apbBridge = new Area{
|
||||
val bus = SimpleBus()
|
||||
val apb = Apb3(
|
||||
addressWidth = 20,
|
||||
dataWidth = 32
|
||||
)
|
||||
val cmdStage = bus.cmd.halfPipe()
|
||||
val state = RegInit(False)
|
||||
cmdStage.ready := False
|
||||
|
||||
apb.PSEL(0) := cmdStage.valid
|
||||
apb.PENABLE := state
|
||||
apb.PWRITE := cmdStage.wr
|
||||
apb.PADDR := cmdStage.address.resized
|
||||
apb.PWDATA := cmdStage.data
|
||||
|
||||
bus.rsp.valid := False
|
||||
bus.rsp.data := apb.PRDATA
|
||||
when(!state){
|
||||
state := cmdStage.valid
|
||||
} otherwise{
|
||||
when(apb.PREADY){
|
||||
state := False
|
||||
bus.rsp.valid := !cmdStage.wr
|
||||
cmdStage.ready := True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val interconnect = new Area {
|
||||
def masterBus = mainBus
|
||||
val specification = List[(SimpleBus,SizeMapping)](
|
||||
ram.bus -> (0x00000000l, onChipRamSize kB),
|
||||
apbBridge.bus -> (0xF0000000l, 1 MB)
|
||||
)
|
||||
|
||||
val slaveBuses = specification.map(_._1)
|
||||
val memorySpaces = specification.map(_._2)
|
||||
|
||||
val hits = for((slaveBus, memorySpace) <- specification) yield {
|
||||
val hit = memorySpace.hit(masterBus.cmd.address)
|
||||
slaveBus.cmd.valid := masterBus.cmd.valid && hit
|
||||
slaveBus.cmd.payload := masterBus.cmd.payload
|
||||
hit
|
||||
}
|
||||
masterBus.cmd.ready := (hits,slaveBuses).zipped.map(_ && _.cmd.ready).orR
|
||||
|
||||
val rspPending = RegInit(False) clearWhen(masterBus.rsp.valid) setWhen(masterBus.cmd.fire && !masterBus.cmd.wr)
|
||||
val rspSourceId = RegNextWhen(OHToUInt(hits), masterBus.cmd.fire)
|
||||
masterBus.rsp.valid := slaveBuses.map(_.rsp.valid).orR
|
||||
masterBus.rsp.payload := slaveBuses.map(_.rsp.payload).read(rspSourceId)
|
||||
|
||||
when(rspPending && !masterBus.rsp.valid) { //Only one pending read request is allowed
|
||||
masterBus.cmd.ready := False
|
||||
slaveBuses.foreach(_.cmd.valid := False)
|
||||
}
|
||||
}
|
||||
|
||||
val gpioACtrl = Apb3Gpio(
|
||||
gpioWidth = 32
|
||||
)
|
||||
io.gpioA <> gpioACtrl.io.gpio
|
||||
|
||||
val apbDecoder = Apb3Decoder(
|
||||
master = apbBridge.apb,
|
||||
slaves = List(
|
||||
gpioACtrl.io.apb -> (0x00000, 4 kB)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -23,468 +23,11 @@
|
|||
#include "VBriey_VexRiscv.h"
|
||||
|
||||
|
||||
class SimElement{
|
||||
public:
|
||||
virtual ~SimElement(){}
|
||||
virtual void onReset(){}
|
||||
virtual void postReset(){}
|
||||
virtual void preCycle(){}
|
||||
virtual void postCycle(){}
|
||||
};
|
||||
#include "../common/framework.h"
|
||||
#include "../common/jtag.h"
|
||||
|
||||
//#include <functional>
|
||||
class TimeProcess{
|
||||
public:
|
||||
uint64_t wakeDelay = 0;
|
||||
bool wakeEnable = false;
|
||||
// std::function<int(double)> lambda;
|
||||
virtual ~TimeProcess(){}
|
||||
virtual void schedule(uint64_t delay){
|
||||
wakeDelay = delay;
|
||||
wakeEnable = true;
|
||||
}
|
||||
virtual void tick(){
|
||||
// lambda = [this](double x) { return x+1 + this->wakeDelay; };
|
||||
// lambda(1.0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SensitiveProcess{
|
||||
public:
|
||||
|
||||
virtual ~SensitiveProcess(){}
|
||||
virtual void tick(uint64_t time){
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class ClockDomain : public TimeProcess{
|
||||
public:
|
||||
CData* clk;
|
||||
CData* reset;
|
||||
uint64_t tooglePeriod;
|
||||
vector<SimElement*> simElements;
|
||||
ClockDomain(CData *clk, CData *reset, uint64_t period, uint64_t delay){
|
||||
this->clk = clk;
|
||||
this->reset = reset;
|
||||
*clk = 0;
|
||||
this->tooglePeriod = period/2;
|
||||
schedule(delay);
|
||||
}
|
||||
|
||||
|
||||
bool postCycle = false;
|
||||
virtual void tick(){
|
||||
if(*clk == 0){
|
||||
for(SimElement* simElement : simElements){
|
||||
simElement->preCycle();
|
||||
}
|
||||
postCycle = true;
|
||||
*clk = 1;
|
||||
schedule(0);
|
||||
}else{
|
||||
if(postCycle){
|
||||
postCycle = false;
|
||||
for(SimElement* simElement : simElements){
|
||||
simElement->postCycle();
|
||||
}
|
||||
}else{
|
||||
*clk = 0;
|
||||
}
|
||||
schedule(tooglePeriod);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void add(SimElement *that){
|
||||
simElements.push_back(that);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class AsyncReset : public TimeProcess{
|
||||
public:
|
||||
CData* reset;
|
||||
uint32_t state;
|
||||
uint64_t duration;
|
||||
AsyncReset(CData *reset, uint64_t duration){
|
||||
this->reset = reset;
|
||||
*reset = 0;
|
||||
state = 0;
|
||||
this->duration = duration;
|
||||
schedule(0);
|
||||
}
|
||||
|
||||
virtual void tick(){
|
||||
switch(state){
|
||||
case 0:
|
||||
*reset = 1;
|
||||
state = 1;
|
||||
schedule(duration);
|
||||
break;
|
||||
case 1:
|
||||
*reset = 0;
|
||||
state = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
/** Returns true on success, or false if there was an error */
|
||||
bool SetSocketBlockingEnabled(int fd, bool blocking)
|
||||
{
|
||||
if (fd < 0) return false;
|
||||
|
||||
#ifdef WIN32
|
||||
unsigned long mode = blocking ? 0 : 1;
|
||||
return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? true : false;
|
||||
#else
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
if (flags < 0) return false;
|
||||
flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
|
||||
return (fcntl(fd, F_SETFL, flags) == 0) ? true : false;
|
||||
#endif
|
||||
}
|
||||
|
||||
class Jtag : public TimeProcess{
|
||||
public:
|
||||
CData *tms, *tdi, *tdo, *tck;
|
||||
enum State {reset};
|
||||
uint32_t state;
|
||||
|
||||
int serverSocket, clientHandle;
|
||||
struct sockaddr_in serverAddr;
|
||||
struct sockaddr_storage serverStorage;
|
||||
socklen_t addr_size;
|
||||
uint64_t tooglePeriod;
|
||||
// char buffer[1024];
|
||||
|
||||
Jtag(CData *tms, CData *tdi, CData *tdo, CData* tck,uint64_t period){
|
||||
this->tms = tms;
|
||||
this->tdi = tdi;
|
||||
this->tdo = tdo;
|
||||
this->tck = tck;
|
||||
this->tooglePeriod = period/2;
|
||||
*tms = 0;
|
||||
*tdi = 0;
|
||||
*tdo = 0;
|
||||
*tck = 0;
|
||||
state = 0;
|
||||
schedule(0);
|
||||
|
||||
//---- Create the socket. The three arguments are: ----//
|
||||
// 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) //
|
||||
serverSocket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
assert(serverSocket != -1);
|
||||
int flag = 1;
|
||||
setsockopt( serverSocket, /* socket affected */
|
||||
IPPROTO_TCP, /* set option at TCP level */
|
||||
TCP_NODELAY, /* name of option */
|
||||
(char *) &flag, /* the cast is historical
|
||||
cruft */
|
||||
sizeof(int)); /* length of option value */
|
||||
|
||||
/*int a = 0xFFF;
|
||||
if (setsockopt(serverSocket, SOL_SOCKET, SO_RCVBUF, &a, sizeof(int)) == -1) {
|
||||
fprintf(stderr, "Error setting socket opts: %s\n", strerror(errno));
|
||||
}
|
||||
a = 0xFFFFFF;
|
||||
if (setsockopt(serverSocket, SOL_SOCKET, SO_SNDBUF, &a, sizeof(int)) == -1) {
|
||||
fprintf(stderr, "Error setting socket opts: %s\n", strerror(errno));
|
||||
}*/
|
||||
|
||||
SetSocketBlockingEnabled(serverSocket,0);
|
||||
|
||||
|
||||
//---- Configure settings of the server address struct ----//
|
||||
// Address family = Internet //
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(7894);
|
||||
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
|
||||
|
||||
//---- Bind the address struct to the socket ----//
|
||||
bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
|
||||
|
||||
//---- Listen on the socket, with 5 max connection requests queued ----//
|
||||
listen(serverSocket,1);
|
||||
|
||||
//---- Accept call creates a new socket for the incoming connection ----//
|
||||
addr_size = sizeof serverStorage;
|
||||
clientHandle = -1;
|
||||
|
||||
}
|
||||
void connectionReset(){
|
||||
printf("CONNECTION RESET\n");
|
||||
shutdown(clientHandle,SHUT_RDWR);
|
||||
clientHandle = -1;
|
||||
}
|
||||
|
||||
|
||||
virtual ~Jtag(){
|
||||
if(clientHandle != -1) {
|
||||
shutdown(clientHandle,SHUT_RDWR);
|
||||
usleep(100);
|
||||
}
|
||||
if(serverSocket != -1) {
|
||||
close(serverSocket);
|
||||
usleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t selfSleep = 0;
|
||||
uint32_t checkNewConnectionsTimer = 0;
|
||||
uint8_t rxBuffer[100];
|
||||
int32_t rxBufferSize = 0;
|
||||
int32_t rxBufferRemaining = 0;
|
||||
virtual void tick(){
|
||||
checkNewConnectionsTimer++;
|
||||
if(checkNewConnectionsTimer == 5000){
|
||||
checkNewConnectionsTimer = 0;
|
||||
int newclientHandle = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
|
||||
if(newclientHandle != -1){
|
||||
if(clientHandle != -1){
|
||||
connectionReset();
|
||||
}
|
||||
clientHandle = newclientHandle;
|
||||
printf("CONNECTED\n");
|
||||
}
|
||||
else{
|
||||
if(clientHandle == -1)
|
||||
selfSleep = 1000;
|
||||
}
|
||||
}
|
||||
if(selfSleep)
|
||||
selfSleep--;
|
||||
else{
|
||||
if(clientHandle != -1){
|
||||
uint8_t buffer;
|
||||
int n;
|
||||
|
||||
if(rxBufferRemaining == 0){
|
||||
if(ioctl(clientHandle,FIONREAD,&n) != 0)
|
||||
connectionReset();
|
||||
else if(n >= 1){
|
||||
rxBufferSize = read(clientHandle,&rxBuffer,100);
|
||||
if(rxBufferSize < 0){
|
||||
connectionReset();
|
||||
}else {
|
||||
rxBufferRemaining = rxBufferSize;
|
||||
}
|
||||
}else {
|
||||
selfSleep = 30;
|
||||
}
|
||||
}
|
||||
|
||||
if(rxBufferRemaining != 0){
|
||||
uint8_t buffer = rxBuffer[rxBufferSize - (rxBufferRemaining--)];
|
||||
*tms = (buffer & 1) != 0;
|
||||
*tdi = (buffer & 2) != 0;
|
||||
*tck = (buffer & 8) != 0;
|
||||
if(buffer & 4){
|
||||
buffer = (*tdo != 0);
|
||||
//printf("TDO=%d\n",buffer);
|
||||
if(-1 == send(clientHandle,&buffer,1,0))
|
||||
connectionReset();
|
||||
}else {
|
||||
|
||||
// printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
schedule(tooglePeriod);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class success : public std::exception { };
|
||||
|
||||
class Workspace{
|
||||
public:
|
||||
static uint32_t cycles;
|
||||
vector<TimeProcess*> timeProcesses;
|
||||
vector<SensitiveProcess*> checkProcesses;
|
||||
VBriey* top;
|
||||
bool resetDone = false;
|
||||
double timeToSec = 1e-12;
|
||||
double speedFactor = 1.0;
|
||||
uint64_t allowedTime = 0;
|
||||
string name;
|
||||
uint64_t time = 0;
|
||||
#ifdef TRACE
|
||||
VerilatedVcdC* tfp;
|
||||
#endif
|
||||
|
||||
ofstream logTraces;
|
||||
|
||||
Workspace(string name){
|
||||
this->name = name;
|
||||
top = new VBriey;
|
||||
logTraces.open (name + ".logTrace");
|
||||
}
|
||||
|
||||
virtual ~Workspace(){
|
||||
delete top;
|
||||
#ifdef TRACE
|
||||
delete tfp;
|
||||
#endif
|
||||
|
||||
for(auto* p : timeProcesses) delete p;
|
||||
for(auto* p : checkProcesses) delete p;
|
||||
|
||||
}
|
||||
|
||||
Workspace* setSpeedFactor(double value){
|
||||
speedFactor = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
virtual void postReset() {}
|
||||
virtual void checks(){}
|
||||
virtual void pass(){ throw success();}
|
||||
virtual void fail(){ throw std::exception();}
|
||||
virtual void fillSimELements();
|
||||
|
||||
virtual void dump(uint64_t i){
|
||||
#ifdef TRACE
|
||||
if(i >= TRACE_START) tfp->dump(i);
|
||||
#endif
|
||||
}
|
||||
|
||||
Workspace* run(uint32_t timeout = 5000){
|
||||
|
||||
fillSimELements();
|
||||
// init trace dump
|
||||
#ifdef TRACE
|
||||
Verilated::traceEverOn(true);
|
||||
tfp = new VerilatedVcdC;
|
||||
top->trace(tfp, 99);
|
||||
tfp->open((string(name)+ ".vcd").c_str());
|
||||
#endif
|
||||
|
||||
struct timespec start_time,tick_time;
|
||||
uint64_t tickLastSimTime = 0;
|
||||
top->eval();
|
||||
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tick_time);
|
||||
|
||||
uint32_t flushCounter = 0;
|
||||
try {
|
||||
while(1){
|
||||
uint64_t delay = ~0l;
|
||||
for(TimeProcess* p : timeProcesses)
|
||||
if(p->wakeEnable && p->wakeDelay < delay)
|
||||
delay = p->wakeDelay;
|
||||
|
||||
if(delay == ~0l){
|
||||
fail();
|
||||
}
|
||||
if(delay != 0){
|
||||
dump(time);
|
||||
}
|
||||
for(TimeProcess* p : timeProcesses) {
|
||||
p->wakeDelay -= delay;
|
||||
if(p->wakeDelay == 0){
|
||||
p->wakeEnable = false;
|
||||
p->tick();
|
||||
}
|
||||
}
|
||||
|
||||
top->eval();
|
||||
for(auto* p : checkProcesses) p->tick(time);
|
||||
|
||||
if(delay != 0){
|
||||
if(time - tickLastSimTime > 1000*400000 || time - tickLastSimTime > 1.0*speedFactor/timeToSec){
|
||||
struct timespec end_time;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
|
||||
uint64_t diffInNanos = end_time.tv_sec*1e9 + end_time.tv_nsec - tick_time.tv_sec*1e9 - tick_time.tv_nsec;
|
||||
tick_time = end_time;
|
||||
double dt = diffInNanos*1e-9;
|
||||
#ifdef PRINT_PERF
|
||||
printf("Simulation speed : %f ms/realTime\n",(time - tickLastSimTime)/dt*timeToSec*1e3);
|
||||
#endif
|
||||
tickLastSimTime = time;
|
||||
}
|
||||
time += delay;
|
||||
while(allowedTime < delay){
|
||||
struct timespec end_time;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
|
||||
uint64_t diffInNanos = end_time.tv_sec*1e9 + end_time.tv_nsec - start_time.tv_sec*1e9 - start_time.tv_nsec;
|
||||
start_time = end_time;
|
||||
double dt = diffInNanos*1e-9;
|
||||
allowedTime += dt*speedFactor/timeToSec;
|
||||
if(allowedTime > 0.01*speedFactor/timeToSec)
|
||||
allowedTime = 0.01*speedFactor/timeToSec;
|
||||
|
||||
}
|
||||
allowedTime-=delay;
|
||||
|
||||
flushCounter++;
|
||||
if(flushCounter > 100000){
|
||||
#ifdef TRACE
|
||||
tfp->flush();
|
||||
//printf("flush\n");
|
||||
#endif
|
||||
flushCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Verilated::gotFinish())
|
||||
exit(0);
|
||||
}
|
||||
cout << "timeout" << endl;
|
||||
fail();
|
||||
} catch (const success e) {
|
||||
cout <<"SUCCESS " << name << endl;
|
||||
} catch (const std::exception& e) {
|
||||
cout << "FAIL " << name << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
dump(time);
|
||||
dump(time+10);
|
||||
#ifdef TRACE
|
||||
tfp->close();
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void Workspace::fillSimELements(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint32_t Workspace::cycles = 0;
|
||||
/*class SimElement{
|
||||
public:
|
||||
virtual ~SimElement(){}
|
||||
virtual void onReset(){}
|
||||
virtual void postReset(){}
|
||||
virtual void preCycle(){}
|
||||
virtual void postCycle(){}
|
||||
};*/
|
||||
|
||||
class SdramConfig{
|
||||
public:
|
||||
uint32_t byteCount;
|
||||
|
@ -882,7 +425,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class BrieyWorkspace : public Workspace{
|
||||
class BrieyWorkspace : public Workspace<VBriey>{
|
||||
public:
|
||||
BrieyWorkspace() : Workspace("Briey"){
|
||||
ClockDomain *axiClk = new ClockDomain(&top->io_axiClk,NULL,20000,100000);
|
||||
|
@ -961,14 +504,6 @@ long timer_end(struct timespec start_time){
|
|||
return diffInNanos;
|
||||
}
|
||||
|
||||
#define redo(count,that) for(uint32_t xxx = 0;xxx < count;xxx++) that
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
|
@ -979,11 +514,11 @@ int main(int argc, char **argv, char **env) {
|
|||
printf("BOOT\n");
|
||||
timespec startedAt = timer_start();
|
||||
|
||||
BrieyWorkspace().run(100e6);
|
||||
BrieyWorkspace().run(1e9);
|
||||
|
||||
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-9) << " Khz)" << endl;
|
||||
cout << "Had simulate " << workspaceCycles << " clock cycles in " << duration*1e-9 << " s (" << workspaceCycles / (duration*1e-9) << " Khz)" << endl;
|
||||
cout << "****************************************************************" << endl << endl;
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
class SimElement{
|
||||
public:
|
||||
virtual ~SimElement(){}
|
||||
virtual void onReset(){}
|
||||
virtual void postReset(){}
|
||||
virtual void preCycle(){}
|
||||
virtual void postCycle(){}
|
||||
};
|
||||
|
||||
//#include <functional>
|
||||
class TimeProcess{
|
||||
public:
|
||||
uint64_t wakeDelay = 0;
|
||||
bool wakeEnable = false;
|
||||
// std::function<int(double)> lambda;
|
||||
virtual ~TimeProcess(){}
|
||||
virtual void schedule(uint64_t delay){
|
||||
wakeDelay = delay;
|
||||
wakeEnable = true;
|
||||
}
|
||||
virtual void tick(){
|
||||
// lambda = [this](double x) { return x+1 + this->wakeDelay; };
|
||||
// lambda(1.0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SensitiveProcess{
|
||||
public:
|
||||
|
||||
virtual ~SensitiveProcess(){}
|
||||
virtual void tick(uint64_t time){
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class ClockDomain : public TimeProcess{
|
||||
public:
|
||||
CData* clk;
|
||||
CData* reset;
|
||||
uint64_t tooglePeriod;
|
||||
vector<SimElement*> simElements;
|
||||
ClockDomain(CData *clk, CData *reset, uint64_t period, uint64_t delay){
|
||||
this->clk = clk;
|
||||
this->reset = reset;
|
||||
*clk = 0;
|
||||
this->tooglePeriod = period/2;
|
||||
schedule(delay);
|
||||
}
|
||||
|
||||
|
||||
bool postCycle = false;
|
||||
virtual void tick(){
|
||||
if(*clk == 0){
|
||||
for(SimElement* simElement : simElements){
|
||||
simElement->preCycle();
|
||||
}
|
||||
postCycle = true;
|
||||
*clk = 1;
|
||||
schedule(0);
|
||||
}else{
|
||||
if(postCycle){
|
||||
postCycle = false;
|
||||
for(SimElement* simElement : simElements){
|
||||
simElement->postCycle();
|
||||
}
|
||||
}else{
|
||||
*clk = 0;
|
||||
}
|
||||
schedule(tooglePeriod);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void add(SimElement *that){
|
||||
simElements.push_back(that);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class AsyncReset : public TimeProcess{
|
||||
public:
|
||||
CData* reset;
|
||||
uint32_t state;
|
||||
uint64_t duration;
|
||||
AsyncReset(CData *reset, uint64_t duration){
|
||||
this->reset = reset;
|
||||
*reset = 0;
|
||||
state = 0;
|
||||
this->duration = duration;
|
||||
schedule(0);
|
||||
}
|
||||
|
||||
virtual void tick(){
|
||||
switch(state){
|
||||
case 0:
|
||||
*reset = 1;
|
||||
state = 1;
|
||||
schedule(duration);
|
||||
break;
|
||||
case 1:
|
||||
*reset = 0;
|
||||
state = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class success : public std::exception { };
|
||||
static uint32_t workspaceCycles = 0;
|
||||
template <class T> class Workspace{
|
||||
public:
|
||||
|
||||
vector<TimeProcess*> timeProcesses;
|
||||
vector<SensitiveProcess*> checkProcesses;
|
||||
T* top;
|
||||
bool resetDone = false;
|
||||
double timeToSec = 1e-12;
|
||||
double speedFactor = 1.0;
|
||||
uint64_t allowedTime = 0;
|
||||
string name;
|
||||
uint64_t time = 0;
|
||||
#ifdef TRACE
|
||||
VerilatedVcdC* tfp;
|
||||
#endif
|
||||
|
||||
ofstream logTraces;
|
||||
|
||||
Workspace(string name){
|
||||
this->name = name;
|
||||
top = new T;
|
||||
logTraces.open (name + ".logTrace");
|
||||
}
|
||||
|
||||
virtual ~Workspace(){
|
||||
delete top;
|
||||
#ifdef TRACE
|
||||
delete tfp;
|
||||
#endif
|
||||
|
||||
for(auto* p : timeProcesses) delete p;
|
||||
for(auto* p : checkProcesses) delete p;
|
||||
|
||||
}
|
||||
|
||||
Workspace* setSpeedFactor(double value){
|
||||
speedFactor = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
virtual void postReset() {}
|
||||
virtual void checks(){}
|
||||
virtual void pass(){ throw success();}
|
||||
virtual void fail(){ throw std::exception();}
|
||||
|
||||
virtual void dump(uint64_t i){
|
||||
#ifdef TRACE
|
||||
if(i >= TRACE_START) tfp->dump(i);
|
||||
#endif
|
||||
}
|
||||
|
||||
Workspace* run(uint32_t timeout = 5000){
|
||||
|
||||
// init trace dump
|
||||
#ifdef TRACE
|
||||
Verilated::traceEverOn(true);
|
||||
tfp = new VerilatedVcdC;
|
||||
top->trace(tfp, 99);
|
||||
tfp->open((string(name)+ ".vcd").c_str());
|
||||
#endif
|
||||
|
||||
struct timespec start_time,tick_time;
|
||||
uint64_t tickLastSimTime = 0;
|
||||
top->eval();
|
||||
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tick_time);
|
||||
|
||||
uint32_t flushCounter = 0;
|
||||
try {
|
||||
while(1){
|
||||
uint64_t delay = ~0l;
|
||||
for(TimeProcess* p : timeProcesses)
|
||||
if(p->wakeEnable && p->wakeDelay < delay)
|
||||
delay = p->wakeDelay;
|
||||
|
||||
if(delay == ~0l){
|
||||
fail();
|
||||
}
|
||||
if(delay != 0){
|
||||
dump(time);
|
||||
}
|
||||
for(TimeProcess* p : timeProcesses) {
|
||||
p->wakeDelay -= delay;
|
||||
if(p->wakeDelay == 0){
|
||||
p->wakeEnable = false;
|
||||
p->tick();
|
||||
}
|
||||
}
|
||||
|
||||
top->eval();
|
||||
for(auto* p : checkProcesses) p->tick(time);
|
||||
|
||||
if(delay != 0){
|
||||
if(time - tickLastSimTime > 1000*400000 || time - tickLastSimTime > 1.0*speedFactor/timeToSec){
|
||||
struct timespec end_time;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
|
||||
uint64_t diffInNanos = end_time.tv_sec*1e9 + end_time.tv_nsec - tick_time.tv_sec*1e9 - tick_time.tv_nsec;
|
||||
tick_time = end_time;
|
||||
double dt = diffInNanos*1e-9;
|
||||
#ifdef PRINT_PERF
|
||||
printf("Simulation speed : %f ms/realTime\n",(time - tickLastSimTime)/dt*timeToSec*1e3);
|
||||
#endif
|
||||
tickLastSimTime = time;
|
||||
}
|
||||
time += delay;
|
||||
while(allowedTime < delay){
|
||||
struct timespec end_time;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
|
||||
uint64_t diffInNanos = end_time.tv_sec*1e9 + end_time.tv_nsec - start_time.tv_sec*1e9 - start_time.tv_nsec;
|
||||
start_time = end_time;
|
||||
double dt = diffInNanos*1e-9;
|
||||
allowedTime += dt*speedFactor/timeToSec;
|
||||
if(allowedTime > 0.01*speedFactor/timeToSec)
|
||||
allowedTime = 0.01*speedFactor/timeToSec;
|
||||
|
||||
}
|
||||
allowedTime-=delay;
|
||||
|
||||
flushCounter++;
|
||||
if(flushCounter > 100000){
|
||||
#ifdef TRACE
|
||||
tfp->flush();
|
||||
//printf("flush\n");
|
||||
#endif
|
||||
flushCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Verilated::gotFinish())
|
||||
exit(0);
|
||||
}
|
||||
cout << "timeout" << endl;
|
||||
fail();
|
||||
} catch (const success e) {
|
||||
cout <<"SUCCESS " << name << endl;
|
||||
} catch (const std::exception& e) {
|
||||
cout << "FAIL " << name << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
dump(time);
|
||||
dump(time+10);
|
||||
#ifdef TRACE
|
||||
tfp->close();
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
/** Returns true on success, or false if there was an error */
|
||||
bool SetSocketBlockingEnabled(int fd, bool blocking)
|
||||
{
|
||||
if (fd < 0) return false;
|
||||
|
||||
#ifdef WIN32
|
||||
unsigned long mode = blocking ? 0 : 1;
|
||||
return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? true : false;
|
||||
#else
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
if (flags < 0) return false;
|
||||
flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
|
||||
return (fcntl(fd, F_SETFL, flags) == 0) ? true : false;
|
||||
#endif
|
||||
}
|
||||
|
||||
class Jtag : public TimeProcess{
|
||||
public:
|
||||
CData *tms, *tdi, *tdo, *tck;
|
||||
enum State {reset};
|
||||
uint32_t state;
|
||||
|
||||
int serverSocket, clientHandle;
|
||||
struct sockaddr_in serverAddr;
|
||||
struct sockaddr_storage serverStorage;
|
||||
socklen_t addr_size;
|
||||
uint64_t tooglePeriod;
|
||||
// char buffer[1024];
|
||||
|
||||
Jtag(CData *tms, CData *tdi, CData *tdo, CData* tck,uint64_t period){
|
||||
this->tms = tms;
|
||||
this->tdi = tdi;
|
||||
this->tdo = tdo;
|
||||
this->tck = tck;
|
||||
this->tooglePeriod = period/2;
|
||||
*tms = 0;
|
||||
*tdi = 0;
|
||||
*tdo = 0;
|
||||
*tck = 0;
|
||||
state = 0;
|
||||
schedule(0);
|
||||
|
||||
//---- Create the socket. The three arguments are: ----//
|
||||
// 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) //
|
||||
serverSocket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
assert(serverSocket != -1);
|
||||
int flag = 1;
|
||||
setsockopt( serverSocket, /* socket affected */
|
||||
IPPROTO_TCP, /* set option at TCP level */
|
||||
TCP_NODELAY, /* name of option */
|
||||
(char *) &flag, /* the cast is historical
|
||||
cruft */
|
||||
sizeof(int)); /* length of option value */
|
||||
|
||||
/*int a = 0xFFF;
|
||||
if (setsockopt(serverSocket, SOL_SOCKET, SO_RCVBUF, &a, sizeof(int)) == -1) {
|
||||
fprintf(stderr, "Error setting socket opts: %s\n", strerror(errno));
|
||||
}
|
||||
a = 0xFFFFFF;
|
||||
if (setsockopt(serverSocket, SOL_SOCKET, SO_SNDBUF, &a, sizeof(int)) == -1) {
|
||||
fprintf(stderr, "Error setting socket opts: %s\n", strerror(errno));
|
||||
}*/
|
||||
|
||||
SetSocketBlockingEnabled(serverSocket,0);
|
||||
|
||||
|
||||
//---- Configure settings of the server address struct ----//
|
||||
// Address family = Internet //
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(7894);
|
||||
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
|
||||
|
||||
//---- Bind the address struct to the socket ----//
|
||||
bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
|
||||
|
||||
//---- Listen on the socket, with 5 max connection requests queued ----//
|
||||
listen(serverSocket,1);
|
||||
|
||||
//---- Accept call creates a new socket for the incoming connection ----//
|
||||
addr_size = sizeof serverStorage;
|
||||
clientHandle = -1;
|
||||
|
||||
}
|
||||
void connectionReset(){
|
||||
printf("CONNECTION RESET\n");
|
||||
shutdown(clientHandle,SHUT_RDWR);
|
||||
clientHandle = -1;
|
||||
}
|
||||
|
||||
|
||||
virtual ~Jtag(){
|
||||
if(clientHandle != -1) {
|
||||
shutdown(clientHandle,SHUT_RDWR);
|
||||
usleep(100);
|
||||
}
|
||||
if(serverSocket != -1) {
|
||||
close(serverSocket);
|
||||
usleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t selfSleep = 0;
|
||||
uint32_t checkNewConnectionsTimer = 0;
|
||||
uint8_t rxBuffer[100];
|
||||
int32_t rxBufferSize = 0;
|
||||
int32_t rxBufferRemaining = 0;
|
||||
virtual void tick(){
|
||||
checkNewConnectionsTimer++;
|
||||
if(checkNewConnectionsTimer == 5000){
|
||||
checkNewConnectionsTimer = 0;
|
||||
int newclientHandle = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
|
||||
if(newclientHandle != -1){
|
||||
if(clientHandle != -1){
|
||||
connectionReset();
|
||||
}
|
||||
clientHandle = newclientHandle;
|
||||
printf("CONNECTED\n");
|
||||
}
|
||||
else{
|
||||
if(clientHandle == -1)
|
||||
selfSleep = 1000;
|
||||
}
|
||||
}
|
||||
if(selfSleep)
|
||||
selfSleep--;
|
||||
else{
|
||||
if(clientHandle != -1){
|
||||
uint8_t buffer;
|
||||
int n;
|
||||
|
||||
if(rxBufferRemaining == 0){
|
||||
if(ioctl(clientHandle,FIONREAD,&n) != 0)
|
||||
connectionReset();
|
||||
else if(n >= 1){
|
||||
rxBufferSize = read(clientHandle,&rxBuffer,100);
|
||||
if(rxBufferSize < 0){
|
||||
connectionReset();
|
||||
}else {
|
||||
rxBufferRemaining = rxBufferSize;
|
||||
}
|
||||
}else {
|
||||
selfSleep = 30;
|
||||
}
|
||||
}
|
||||
|
||||
if(rxBufferRemaining != 0){
|
||||
uint8_t buffer = rxBuffer[rxBufferSize - (rxBufferRemaining--)];
|
||||
*tms = (buffer & 1) != 0;
|
||||
*tdi = (buffer & 2) != 0;
|
||||
*tck = (buffer & 8) != 0;
|
||||
if(buffer & 4){
|
||||
buffer = (*tdo != 0);
|
||||
//printf("TDO=%d\n",buffer);
|
||||
if(-1 == send(clientHandle,&buffer,1,0))
|
||||
connectionReset();
|
||||
}else {
|
||||
|
||||
// printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
schedule(tooglePeriod);
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,61 @@
|
|||
#include "VMurax.h"
|
||||
#include "VMurax_Murax.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_vcd_c.h"
|
||||
|
||||
#include "../common/framework.h"
|
||||
#include "../common/jtag.h"
|
||||
|
||||
class MuraxWorkspace : public Workspace<VMurax>{
|
||||
public:
|
||||
MuraxWorkspace() : Workspace("Murax"){
|
||||
ClockDomain *mainClk = new ClockDomain(&top->io_mainClk,NULL,83333,300000);
|
||||
AsyncReset *asyncReset = new AsyncReset(&top->io_asyncReset,50000);
|
||||
|
||||
timeProcesses.push_back(mainClk);
|
||||
timeProcesses.push_back(asyncReset);
|
||||
|
||||
Jtag *jtag = new Jtag(&top->io_jtag_tms,&top->io_jtag_tdi,&top->io_jtag_tdo,&top->io_jtag_tck,83333*4);
|
||||
timeProcesses.push_back(jtag);
|
||||
|
||||
#ifdef TRACE
|
||||
speedFactor = 10e-3;
|
||||
cout << "Simulation caped to " << speedFactor << " of real time"<< endl;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct timespec timer_start(){
|
||||
struct timespec start_time;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
|
||||
return start_time;
|
||||
}
|
||||
|
||||
long timer_end(struct timespec start_time){
|
||||
struct timespec end_time;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
|
||||
uint64_t diffInNanos = end_time.tv_sec*1e9 + end_time.tv_nsec - start_time.tv_sec*1e9 - start_time.tv_nsec;
|
||||
return diffInNanos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
|
||||
Verilated::randReset(2);
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
printf("BOOT\n");
|
||||
timespec startedAt = timer_start();
|
||||
|
||||
MuraxWorkspace().run(100e6);
|
||||
|
||||
uint64_t duration = timer_end(startedAt);
|
||||
cout << endl << "****************************************************************" << endl;
|
||||
cout << "Had simulate " << workspaceCycles << " clock cycles in " << duration*1e-9 << " s (" << workspaceCycles / (duration*1e-9) << " Khz)" << endl;
|
||||
cout << "****************************************************************" << endl << endl;
|
||||
|
||||
|
||||
exit(0);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
DEBUG?=no
|
||||
TRACE?=no
|
||||
PRINT_PERF?=no
|
||||
TRACE_START=0
|
||||
ADDCFLAGS += -CFLAGS -pthread
|
||||
|
||||
|
||||
ifeq ($(TRACE),yes)
|
||||
VERILATOR_ARGS += --trace
|
||||
ADDCFLAGS += -CFLAGS -DTRACE
|
||||
endif
|
||||
ifeq ($(DEBUG),yes)
|
||||
ADDCFLAGS += -CFLAGS "-g3 -O0"
|
||||
endif
|
||||
ifneq ($(DEBUG),yes)
|
||||
ADDCFLAGS += -CFLAGS "-O3"
|
||||
endif
|
||||
ifeq ($(PRINT_PERF),yes)
|
||||
ADDCFLAGS += -CFLAGS -DPRINT_PERF
|
||||
endif
|
||||
|
||||
ADDCFLAGS += -CFLAGS -DTRACE_START=${TRACE_START}
|
||||
|
||||
|
||||
|
||||
all: clean compile
|
||||
|
||||
run: compile
|
||||
./obj_dir/VMurax
|
||||
|
||||
verilate:
|
||||
verilator -cc ../../../../Murax.v -CFLAGS -std=c++11 ${ADDCFLAGS} --gdbbt ${VERILATOR_ARGS} -Wno-WIDTH --x-assign unique --exe main.cpp
|
||||
|
||||
compile: verilate
|
||||
make -j -C obj_dir/ -f VMurax.mk VMurax
|
||||
|
||||
clean:
|
||||
rm -rf obj_dir
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
[*]
|
||||
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
|
||||
[*] Fri Jul 28 18:56:29 2017
|
||||
[*]
|
||||
[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/murax/Murax.vcd"
|
||||
[dumpfile_mtime] "Fri Jul 28 18:50:07 2017"
|
||||
[dumpfile_size] 141674930
|
||||
[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/murax/murax.gtkw"
|
||||
[timestart] 52797277000
|
||||
[size] 1776 953
|
||||
[pos] -775 -1
|
||||
*-19.000000 52799592000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] TOP.
|
||||
[treeopen] TOP.Murax.
|
||||
[sst_width] 269
|
||||
[signals_width] 398
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 279
|
||||
@22
|
||||
TOP.io_gpioA_read[31:0]
|
||||
TOP.io_gpioA_writeEnable[31:0]
|
||||
TOP.io_gpioA_write[31:0]
|
||||
[color] 3
|
||||
TOP.Murax.system_mainBus_cmd_payload_address[31:0]
|
||||
[color] 3
|
||||
TOP.Murax.system_mainBus_cmd_payload_data[31:0]
|
||||
[color] 3
|
||||
TOP.Murax.system_mainBus_cmd_payload_mask[3:0]
|
||||
@28
|
||||
[color] 3
|
||||
TOP.Murax.system_mainBus_cmd_payload_wr
|
||||
[color] 3
|
||||
TOP.Murax.system_mainBus_cmd_valid
|
||||
[color] 3
|
||||
TOP.Murax.system_mainBus_cmd_ready
|
||||
@22
|
||||
[color] 3
|
||||
TOP.Murax.system_mainBus_rsp_payload_data[31:0]
|
||||
@28
|
||||
[color] 3
|
||||
TOP.Murax.system_mainBus_rsp_valid
|
||||
@29
|
||||
TOP.Murax.system_ram_bus_cmd_valid
|
||||
@28
|
||||
TOP.Murax.system_ram_bus_cmd_ready
|
||||
@22
|
||||
TOP.Murax.system_ram_bus_cmd_payload_address[31:0]
|
||||
TOP.Murax.system_ram_bus_cmd_payload_data[31:0]
|
||||
TOP.Murax.system_ram_bus_cmd_payload_mask[3:0]
|
||||
@28
|
||||
TOP.Murax.system_ram_bus_cmd_payload_wr
|
||||
@22
|
||||
TOP.Murax.system_ram_bus_rsp_payload_data[31:0]
|
||||
@28
|
||||
TOP.Murax.system_ram_bus_rsp_valid
|
||||
@22
|
||||
[color] 1
|
||||
TOP.Murax.system_apbBridge_bus_cmd_payload_address[31:0]
|
||||
[color] 1
|
||||
TOP.Murax.system_apbBridge_bus_cmd_payload_data[31:0]
|
||||
@28
|
||||
[color] 1
|
||||
TOP.Murax.system_apbBridge_bus_cmd_payload_wr
|
||||
[color] 1
|
||||
TOP.Murax.system_apbBridge_bus_cmd_ready
|
||||
[color] 1
|
||||
TOP.Murax.system_apbBridge_bus_cmd_valid
|
||||
@22
|
||||
[color] 1
|
||||
TOP.Murax.system_apbBridge_bus_rsp_payload_data[31:0]
|
||||
@28
|
||||
[color] 1
|
||||
TOP.Murax.system_apbBridge_bus_rsp_valid
|
||||
@22
|
||||
TOP.Murax.system_apbBridge_apb_PADDR[19:0]
|
||||
@28
|
||||
TOP.Murax.system_apbBridge_apb_PSEL[0]
|
||||
TOP.Murax.system_apbBridge_apb_PENABLE
|
||||
@22
|
||||
TOP.Murax.system_apbBridge_apb_PRDATA[31:0]
|
||||
@28
|
||||
TOP.Murax.system_apbBridge_apb_PREADY
|
||||
@22
|
||||
TOP.Murax.system_apbBridge_apb_PWDATA[31:0]
|
||||
@28
|
||||
TOP.Murax.system_apbBridge_apb_PWRITE
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
|
@ -1291,7 +1291,11 @@ public:
|
|||
}
|
||||
|
||||
virtual void checks(){
|
||||
if(/*top->VexRiscv->writeBack_arbitration_isValid == 1 && */top->VexRiscv->writeBack_INSTRUCTION == 0x00000073){
|
||||
if(top->VexRiscv->writeBack_INSTRUCTION == 0x00000073){
|
||||
uint32_t instruction;
|
||||
bool error;
|
||||
iBusAccess(top->VexRiscv->writeBack_PC, &instruction, &error);
|
||||
if(instruction == 0x00000073){
|
||||
uint32_t code = top->VexRiscv->RegFilePlugin_regFile[28];
|
||||
if((code & 1) == 0){
|
||||
cout << "Wrong error code"<< endl;
|
||||
|
@ -1305,6 +1309,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error){
|
||||
Workspace::iBusAccess(addr,data,error);
|
||||
|
|
Loading…
Reference in New Issue