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
|
EclipseKeys.withSource := true
|
||||||
|
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "0.10.14",
|
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "0.10.15",
|
||||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "0.10.14",
|
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "0.10.15",
|
||||||
"org.yaml" % "snakeyaml" % "1.8"
|
"org.yaml" % "snakeyaml" % "1.8"
|
||||||
)
|
)
|
|
@ -2,6 +2,8 @@ package vexriscv.demo
|
||||||
|
|
||||||
import spinal.core._
|
import spinal.core._
|
||||||
import spinal.lib._
|
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.jtag.Jtag
|
||||||
import spinal.lib.com.uart.Uart
|
import spinal.lib.com.uart.Uart
|
||||||
import spinal.lib.io.TriStateArray
|
import spinal.lib.io.TriStateArray
|
||||||
|
@ -60,7 +62,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
val jtag = slave(Jtag())
|
val jtag = slave(Jtag())
|
||||||
|
|
||||||
//Peripherals IO
|
//Peripherals IO
|
||||||
// val gpioA = master(TriStateArray(32 bits))
|
val gpioA = master(TriStateArray(32 bits))
|
||||||
// val uart = master(Uart())
|
// val uart = master(Uart())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +166,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
plugin.externalInterrupt := BufferCC(io.coreInterrupt)
|
plugin.externalInterrupt := BufferCC(io.coreInterrupt)
|
||||||
plugin.timerInterrupt := timerCtrl.io.interrupt
|
plugin.timerInterrupt := timerCtrl.io.interrupt
|
||||||
}*/
|
}*/
|
||||||
case plugin : DebugPlugin => {
|
case plugin : DebugPlugin => plugin.debugClockDomain{
|
||||||
resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut))
|
resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut))
|
||||||
io.jtag <> plugin.io.bus.fromJtag()
|
io.jtag <> plugin.io.bus.fromJtag()
|
||||||
}
|
}
|
||||||
|
@ -192,11 +194,11 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
when(mainBus.cmd.fire){
|
when(mainBus.cmd.fire){
|
||||||
rspTarget := dBus.cmd.valid
|
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.inst := mainBus.rsp.data
|
||||||
iBus.rsp.error := False
|
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.data := mainBus.rsp.data
|
||||||
dBus.rsp.error := False
|
dBus.rsp.error := False
|
||||||
|
|
||||||
|
@ -207,11 +209,11 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
}
|
}
|
||||||
|
|
||||||
val ram = new Area{
|
val ram = new Area{
|
||||||
def bus = mainBus//SimpleBus()
|
val bus = SimpleBus()
|
||||||
val ram = Mem(Bits(32 bits), (onChipRamSize / 4).toInt)
|
val ram = Mem(Bits(32 bits), onChipRamSize / 4)
|
||||||
bus.rsp.valid := RegNext(bus.cmd.fire && !bus.cmd.wr) init(False)
|
bus.rsp.valid := RegNext(bus.cmd.fire && !bus.cmd.wr) init(False)
|
||||||
bus.rsp.data := ram.readWriteSync(
|
bus.rsp.data := ram.readWriteSync(
|
||||||
address = bus.cmd.address.resized,
|
address = (bus.cmd.address >> 2).resized,
|
||||||
data = bus.cmd.data,
|
data = bus.cmd.data,
|
||||||
enable = bus.cmd.valid,
|
enable = bus.cmd.valid,
|
||||||
write = bus.cmd.wr,
|
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"
|
#include "VBriey_VexRiscv.h"
|
||||||
|
|
||||||
|
|
||||||
class SimElement{
|
#include "../common/framework.h"
|
||||||
public:
|
#include "../common/jtag.h"
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#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{
|
class SdramConfig{
|
||||||
public:
|
public:
|
||||||
uint32_t byteCount;
|
uint32_t byteCount;
|
||||||
|
@ -882,7 +425,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BrieyWorkspace : public Workspace{
|
class BrieyWorkspace : public Workspace<VBriey>{
|
||||||
public:
|
public:
|
||||||
BrieyWorkspace() : Workspace("Briey"){
|
BrieyWorkspace() : Workspace("Briey"){
|
||||||
ClockDomain *axiClk = new ClockDomain(&top->io_axiClk,NULL,20000,100000);
|
ClockDomain *axiClk = new ClockDomain(&top->io_axiClk,NULL,20000,100000);
|
||||||
|
@ -961,14 +504,6 @@ long timer_end(struct timespec start_time){
|
||||||
return diffInNanos;
|
return diffInNanos;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define redo(count,that) for(uint32_t xxx = 0;xxx < count;xxx++) that
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv, char **env) {
|
int main(int argc, char **argv, char **env) {
|
||||||
|
@ -979,11 +514,11 @@ int main(int argc, char **argv, char **env) {
|
||||||
printf("BOOT\n");
|
printf("BOOT\n");
|
||||||
timespec startedAt = timer_start();
|
timespec startedAt = timer_start();
|
||||||
|
|
||||||
BrieyWorkspace().run(100e6);
|
BrieyWorkspace().run(1e9);
|
||||||
|
|
||||||
uint64_t duration = timer_end(startedAt);
|
uint64_t duration = timer_end(startedAt);
|
||||||
cout << endl << "****************************************************************" << endl;
|
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;
|
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,17 +1291,22 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void checks(){
|
virtual void checks(){
|
||||||
if(/*top->VexRiscv->writeBack_arbitration_isValid == 1 && */top->VexRiscv->writeBack_INSTRUCTION == 0x00000073){
|
if(top->VexRiscv->writeBack_INSTRUCTION == 0x00000073){
|
||||||
uint32_t code = top->VexRiscv->RegFilePlugin_regFile[28];
|
uint32_t instruction;
|
||||||
if((code & 1) == 0){
|
bool error;
|
||||||
cout << "Wrong error code"<< endl;
|
iBusAccess(top->VexRiscv->writeBack_PC, &instruction, &error);
|
||||||
fail();
|
if(instruction == 0x00000073){
|
||||||
}
|
uint32_t code = top->VexRiscv->RegFilePlugin_regFile[28];
|
||||||
if(code == 1){
|
if((code & 1) == 0){
|
||||||
pass();
|
cout << "Wrong error code"<< endl;
|
||||||
}else{
|
fail();
|
||||||
cout << "Error code " << code/2 << endl;
|
}
|
||||||
fail();
|
if(code == 1){
|
||||||
|
pass();
|
||||||
|
}else{
|
||||||
|
cout << "Error code " << code/2 << endl;
|
||||||
|
fail();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue