diff --git a/src/main/scala/SpinalRiscv/demo/Briey.scala b/src/main/scala/SpinalRiscv/demo/Briey.scala
index 6698775..3d53a48 100644
--- a/src/main/scala/SpinalRiscv/demo/Briey.scala
+++ b/src/main/scala/SpinalRiscv/demo/Briey.scala
@@ -339,7 +339,7 @@ class Briey(config: BrieyConfig) extends Component{
object Briey{
def main(args: Array[String]) {
- val config = SpinalConfig().dumpWave()
+ val config = SpinalConfig()
config.generateVerilog({
val toplevel = new Briey(BrieyConfig.default)
toplevel
diff --git a/src/main/scala/SpinalRiscv/ip/DataCache.scala b/src/main/scala/SpinalRiscv/ip/DataCache.scala
index 879cb0e..e94ba36 100644
--- a/src/main/scala/SpinalRiscv/ip/DataCache.scala
+++ b/src/main/scala/SpinalRiscv/ip/DataCache.scala
@@ -187,6 +187,7 @@ case class DataCacheMemCmd(p : DataCacheConfig) extends Bundle{
val data = Bits(p.memDataWidth bits)
val mask = Bits(p.memDataWidth/8 bits)
val length = UInt(log2Up(p.burstLength) bits)
+ val last = Bool
}
case class DataCacheMemRsp(p : DataCacheConfig) extends Bundle{
val data = Bits(p.memDataWidth bit)
@@ -212,21 +213,23 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
)
val cmdPreFork = if (stageCmd) cmd.stage.stage().s2mPipe() else cmd
- val (cmdFork, dataFork) = StreamFork2(cmdPreFork.haltWhen((pendingWrites =/= 0 && !cmdPreFork.wr) || pendingWrites === pendingWritesMax))
- axi.sharedCmd.arbitrationFrom(cmdFork)
- axi.sharedCmd.write := cmdFork.wr
+ val hazard = (pendingWrites =/= 0 && !cmdPreFork.wr) || pendingWrites === pendingWritesMax
+ val (cmdFork, dataFork) = StreamFork2(cmdPreFork.haltWhen(hazard))
+ val cmdStage = cmdFork.throwWhen(RegNextWhen(!cmdFork.last,cmdFork.fire).init(False))
+ val dataStage = dataFork.throwWhen(!dataFork.wr)
+
+ axi.sharedCmd.arbitrationFrom(cmdStage)
+ axi.sharedCmd.write := cmdStage.wr
axi.sharedCmd.prot := "010"
axi.sharedCmd.cache := "1111"
axi.sharedCmd.size := log2Up(p.memDataWidth/8)
- axi.sharedCmd.addr := cmdFork.address
- axi.sharedCmd.len := cmdFork.length.resized
+ axi.sharedCmd.addr := cmdStage.address
+ axi.sharedCmd.len := cmdStage.length.resized
- val dataStage = dataFork.throwWhen(!dataFork.wr)
axi.writeData.arbitrationFrom(dataStage)
- axi.writeData.last := True
axi.writeData.data := dataStage.data
axi.writeData.strb := dataStage.mask
-
+ axi.writeData.last := dataStage.last
rsp.valid := axi.r.valid
rsp.error := !axi.r.isOKAY()
@@ -441,6 +444,7 @@ class DataCache(p : DataCacheConfig) extends Component{
io.mem.cmd.length := p.burstLength-1
io.mem.cmd.data := bufferReaded.payload
io.mem.cmd.mask := (1<<(wordWidth/8))-1
+ io.mem.cmd.last := bufferReadedCounter === bufferReadedCounter.maxValue
when(!memCmdAlreadyUsed && io.mem.cmd.ready){
bufferReaded.ready := True
@@ -556,6 +560,7 @@ class DataCache(p : DataCacheConfig) extends Component{
io.mem.cmd.mask := writeMask
io.mem.cmd.data := request.data
io.mem.cmd.length := 0
+ io.mem.cmd.last := True
when(!memCmdSent) {
io.mem.cmd.valid := True
@@ -606,6 +611,7 @@ class DataCache(p : DataCacheConfig) extends Component{
io.mem.cmd.wr := False
io.mem.cmd.address := baseAddress(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
io.mem.cmd.length := p.burstLength-1
+ io.mem.cmd.last := True
}
when(valid && io.mem.cmd.ready){
diff --git a/src/test/cpp/briey/.cproject b/src/test/cpp/briey/.cproject
new file mode 100644
index 0000000..be7ad7a
--- /dev/null
+++ b/src/test/cpp/briey/.cproject
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/cpp/briey/installs.txt b/src/test/cpp/briey/installs.txt
new file mode 100644
index 0000000..aaada0d
--- /dev/null
+++ b/src/test/cpp/briey/installs.txt
@@ -0,0 +1,19 @@
+sudo apt-get update
+sudo apt-get install build-essential software-properties-common -y
+sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
+sudo apt-get update
+sudo apt-get install gcc-6 g++-6 -y
+sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-6
+
+
+wget -O boost_1_64_0.tar.gz http://sourceforge.net/projects/boost/files/boost/1.64.0/boost_1_64_0.tar.gz/download
+tar xzvf boost_1_64_0.tar.gz
+cd boost_1_64_0/
+./bootstrap.sh --prefix=/usr/local
+./b2
+sudo ./b2 install
+
+
+
+echo "using gcc : 6.3 : /usr/bin/g++-6 ; " >> tools/build/src/user-config.jam
+bjam --toolset=gcc-6
\ No newline at end of file
diff --git a/src/test/cpp/briey/jtag.gtkw b/src/test/cpp/briey/jtag.gtkw
new file mode 100644
index 0000000..2faf5d8
--- /dev/null
+++ b/src/test/cpp/briey/jtag.gtkw
@@ -0,0 +1,98 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Tue Jun 6 08:32:08 2017
+[*]
+[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/briey/Briey.vcd"
+[dumpfile_mtime] "Tue Jun 6 08:32:08 2017"
+[dumpfile_size] 23745041
+[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/briey/jtag.gtkw"
+[timestart] 6592000000
+[size] 1776 953
+[pos] -775 -353
+*-21.000000 5877400000 -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.Briey.
+[treeopen] TOP.Briey.axi_jtagCtrl.
+[treeopen] TOP.Briey.axi_jtagCtrl.jtagBridge_1.
+[sst_width] 399
+[signals_width] 363
+[sst_expanded] 1
+[sst_vpaned_height] 503
+@28
+TOP.io_jtag_tck
+TOP.io_jtag_tdi
+TOP.io_jtag_tdo
+TOP.io_jtag_tms
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_axiClk
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_jtag_tck
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_jtag_tdi
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_jtag_tdo
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_jtag_tms
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.jtag_idcodeArea_instructionHit
+@22
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.jtag_idcodeArea_shifter[31:0]
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.jtag_tap_fsm_state[3:0]
+@28
+TOP.Briey.axi_jtagCtrl.debugger_io_mem_cmd_valid
+@22
+TOP.Briey.axi_jtagCtrl.debugger_io_mem_cmd_payload_address[31:0]
+TOP.Briey.axi_jtagCtrl.debugger_io_mem_cmd_payload_data[31:0]
+@28
+TOP.Briey.axi_jtagCtrl.debugger_io_mem_cmd_payload_size[1:0]
+TOP.Briey.axi_jtagCtrl.debugger_io_mem_cmd_payload_wr
+TOP.Briey.axi_jtagCtrl.debugger_io_mem_rsp_valid
+@22
+TOP.Briey.axi_jtagCtrl.io_axi_arw_payload_addr[31:0]
+@28
+TOP.Briey.axi_jtagCtrl.io_axi_arw_payload_size[2:0]
+TOP.Briey.axi_jtagCtrl.io_axi_arw_payload_write
+TOP.Briey.axi_jtagCtrl.io_axi_arw_ready
+TOP.Briey.axi_jtagCtrl.io_axi_arw_valid
+TOP.Briey.axi_jtagCtrl.io_axi_b_ready
+@22
+TOP.Briey.axi_jtagCtrl.io_axi_r_payload_data[31:0]
+@28
+TOP.Briey.axi_jtagCtrl.io_axi_r_ready
+TOP.Briey.axi_jtagCtrl.io_axi_r_valid
+@22
+TOP.Briey.axi_jtagCtrl.io_axi_w_payload_data[31:0]
+@28
+TOP.Briey.axi_jtagCtrl.io_axi_w_payload_last
+@22
+TOP.Briey.axi_jtagCtrl.io_axi_w_payload_strb[3:0]
+@28
+TOP.Briey.axi_jtagCtrl.io_axi_w_ready
+TOP.Briey.axi_jtagCtrl.io_axi_w_valid
+TOP.Briey.axi_jtagCtrl.debugger.io_remote_cmd_payload_fragment[0]
+TOP.Briey.axi_jtagCtrl.debugger.io_remote_cmd_payload_last
+TOP.Briey.axi_jtagCtrl.debugger.io_remote_cmd_valid
+@22
+TOP.Briey.axi_jtagCtrl.debugger.io_remote_rsp_payload_data[31:0]
+@28
+TOP.Briey.axi_jtagCtrl.debugger.io_remote_rsp_payload_error
+TOP.Briey.axi_jtagCtrl.debugger.io_remote_rsp_valid
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_remote_cmd_payload_fragment[0]
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_remote_cmd_payload_last
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_remote_cmd_valid
+@22
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_remote_rsp_payload_data[31:0]
+@28
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_remote_rsp_payload_error
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_remote_rsp_valid
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.flowCCByToggle_1.io_input_payload_fragment[0]
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.flowCCByToggle_1.io_input_payload_last
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.flowCCByToggle_1.io_input_valid
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.flowCCByToggle_1.io_jtag_tck
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.flowCCByToggle_1.io_output_payload_fragment[0]
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.flowCCByToggle_1.io_output_payload_last
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.flowCCByToggle_1.io_output_valid
+@29
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_jtag_tck
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_jtag_tdi
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_jtag_tdo
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.io_jtag_tms
+@22
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.jtag_tap_fsm_state[3:0]
+TOP.Briey.axi_jtagCtrl.jtagBridge_1.jtag_tap_instruction[3:0]
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/src/test/cpp/briey/main.cpp b/src/test/cpp/briey/main.cpp
new file mode 100644
index 0000000..0628a75
--- /dev/null
+++ b/src/test/cpp/briey/main.cpp
@@ -0,0 +1,722 @@
+#include "VBriey.h"
+#include "VBriey_Briey.h"
+#ifdef REF
+#include "VBriey_RiscvCore.h"
+#endif
+#include "verilated.h"
+#include "verilated_vcd_c.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+
+
+class SimElement{
+public:
+ virtual ~SimElement(){}
+ virtual void onReset(){}
+ virtual void postReset(){}
+ virtual void preCycle(){}
+ virtual void postCycle(){}
+};
+
+//#include
+class Process{
+public:
+ uint64_t wakeDelay = 0;
+ bool wakeEnable = false;
+// std::function lambda;
+ virtual ~Process(){}
+ 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 ClockDomain : public Process{
+public:
+ CData* clk;
+ CData* reset;
+ uint64_t tooglePeriod;
+ vector 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 Process{
+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
+#include
+#include
+#include
+#include
+#include
+#include
+
+/** 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 Process{
+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 period;
+// 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->period = period;
+ *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);
+ 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);
+ }
+ }
+ virtual void tick(){
+ if(clientHandle == -1){
+ clientHandle = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
+ if(clientHandle != -1)
+ printf("CONNECTED\n");
+ }
+ if(clientHandle != -1){
+ uint8_t buffer;
+ int n;
+
+ if(ioctl(clientHandle,FIONREAD,&n) != 0)
+ connectionReset();
+ else if(n >= 1){
+ switch(read(clientHandle,&buffer,1)){
+ case 0: break;
+ case 1:
+ *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");
+ }
+ break;
+ default:
+ connectionReset();
+ break;
+ }
+ }
+ }
+ schedule(period);
+ }
+
+};
+
+
+class success : public std::exception { };
+
+class Workspace{
+public:
+ static uint32_t cycles;
+ vector processes;
+ 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(Process* p : processes) 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();
+
+ 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(Process* p : processes)
+ if(p->wakeEnable && p->wakeDelay < delay)
+ delay = p->wakeDelay;
+
+ if(delay == ~0l){
+ fail();
+ }
+ if(delay != 0){
+ dump(time);
+ }
+ for(Process* p : processes) {
+ p->wakeDelay -= delay;
+ if(p->wakeDelay == 0){
+ p->wakeEnable = false;
+ p->tick();
+ }
+ }
+
+ top->eval();
+
+
+ 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;
+ printf("Simulation speed : %f ms/realTime\n",(time - tickLastSimTime)/dt*timeToSec*1e3);
+ 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;
+ uint32_t bankCount;
+ uint32_t rowSize;
+ uint32_t colSize;
+
+ SdramConfig(uint32_t byteCount,
+ uint32_t bankCount,
+ uint32_t rowSize,
+ uint32_t colSize){
+ this->byteCount = byteCount;
+ this->bankCount = bankCount;
+ this->rowSize = rowSize;
+ this->colSize = colSize;
+ }
+};
+
+class SdramIo{
+public:
+ CData *BA;
+ CData *DQM;
+ CData *CASn;
+ CData *CKE;
+ CData *CSn;
+ CData *RASn;
+ CData *WEn;
+ SData *ADDR;
+ CData *DQ_read;
+ CData *DQ_write;
+ CData *DQ_writeEnable;
+};
+
+class Sdram : public SimElement{
+public:
+
+ SdramConfig *config;
+ SdramIo *io;
+
+ uint32_t CAS;
+ uint32_t burstLength;
+
+ class Bank{
+ public:
+ uint8_t *data;
+ SdramConfig *config;
+
+ bool opened;
+ uint32_t openedRow;
+ void init(SdramConfig *config){
+ this->config = config;
+ data = new uint8_t[config->rowSize * config->colSize * config->byteCount];
+ opened = false;
+ }
+
+ virtual ~Bank(){
+ delete data;
+ }
+
+ void activate(uint32_t row){
+ if(opened)
+ cout << "SDRAM error open unclosed bank" << endl;
+ openedRow = row;
+ opened = true;
+ }
+
+ void precharge(){
+ opened = false;
+ }
+
+ void write(uint32_t column, CData byteId, CData data){
+ if(!opened)
+ cout << "SDRAM : write in closed bank" << endl;
+ uint32_t addr = byteId + (column + openedRow * config->colSize) * config->byteCount;
+ this->data[addr] = data;
+
+ //printf("SDRAM : Write A=%08x D=%02x\n",addr,data);
+ }
+
+ CData read(uint32_t column, CData byteId){
+ if(!opened)
+ cout << "SDRAM : write in closed bank" << endl;
+ uint32_t addr = byteId + (column + openedRow * config->colSize) * config->byteCount;
+ //printf("SDRAM : Read A=%08x D=%02x\n",addr,data[addr]);
+ return data[addr];
+ }
+ };
+
+ Bank* banks;
+
+ CData * readShifter;
+
+ Sdram(SdramConfig *config,SdramIo* io){
+ this->config = config;
+ this->io = io;
+ banks = new Bank[config->bankCount];
+ for(uint32_t bankId = 0;bankId < config->bankCount;bankId++) banks[bankId].init(config);
+ readShifter = new CData[config->byteCount*3];
+ }
+
+ virtual ~Sdram(){
+ delete banks;
+ delete readShifter;
+ }
+
+
+ uint8_t ckeLast = 0;
+
+
+ virtual void postCycle(){
+ if(CAS >= 2 && CAS <=3){
+ for(uint32_t byteId = 0;byteId != config->byteCount;byteId++){
+ io->DQ_read[byteId] = readShifter[byteId + (CAS-1)*config->byteCount];
+ }
+ for(uint32_t latency = CAS-1;latency != 0;latency--){ //missing CKE
+ for(uint32_t byteId = 0;byteId != config->byteCount;byteId++){
+ readShifter[byteId+latency*config->byteCount] = readShifter[byteId+(latency-1)*config->byteCount];
+ }
+ }
+ }
+ }
+
+ virtual void preCycle(){
+ if(!*io->CSn && ckeLast){
+ uint32_t code = ((*io->RASn) << 2) | ((*io->CASn) << 1) | ((*io->WEn) << 0);
+ switch(code){
+ case 0: //Mode register set
+ if(*io->BA == 0 && (*io->ADDR & 0x400) == 0){
+ CAS = ((*io->ADDR) >> 4) & 0x7;
+ burstLength = ((*io->ADDR) >> 0) & 0x7;
+ if((*io->ADDR & 0x388) != 0)
+ cout << "SDRAM : ???" << endl;
+ printf("SDRAM : MODE REGISTER DEFINITION CAS=%d burstLength=%d\n",CAS,burstLength);
+ }
+ break;
+ case 2: //Bank precharge
+ if((*io->ADDR & 0x400) != 0){ //all
+ for(uint32_t bankId = 0;bankId < config->bankCount;bankId++)
+ banks[bankId].precharge();
+ } else { //single
+ banks[*io->BA].precharge();
+ }
+ break;
+ case 3: //Bank activate
+ banks[*io->BA].activate(*io->ADDR & 0x7FF);
+ break;
+ case 4: //Write
+ if((*io->ADDR & 0x400) != 0)
+ cout << "SDRAM : Write autoprecharge not supported" << endl;
+
+ if(*io->DQ_writeEnable == 0)
+ cout << "SDRAM : Write Wrong DQ direction" << endl;
+
+ for(uint32_t byteId = 0;byteId < config->byteCount;byteId++){
+ if(((*io->DQM >> byteId) & 1) == 0)
+ banks[*io->BA].write(*io->ADDR, byteId ,io->DQ_write[byteId]);
+ }
+ break;
+
+ case 5: //Read
+ if((*io->ADDR & 0x400) != 0)
+ cout << "SDRAM : READ autoprecharge not supported" << endl;
+
+ if(*io->DQ_writeEnable != 0)
+ cout << "SDRAM : READ Wrong DQ direction" << endl;
+
+ //if(*io->DQM != config->byteCount-1)
+ //cout << "SDRAM : READ wrong DQM" << endl;
+
+ for(uint32_t byteId = 0;byteId < config->byteCount;byteId++){
+ readShifter[byteId] = banks[*io->BA].read(*io->ADDR, byteId);
+ }
+ break;
+ case 1: // Self refresh
+ break;
+ case 7: // NOP
+ break;
+ default:
+ cout << "SDRAM : unknown code" << endl;
+ break;
+ }
+ }
+ ckeLast = *io->CKE;
+ }
+};
+
+
+class BrieyWorkspace : public Workspace{
+public:
+ BrieyWorkspace() : Workspace("Briey"){
+ ClockDomain *axiClk = new ClockDomain(&top->io_axiClk,NULL,20000,100000);
+ ClockDomain *vgaClk = new ClockDomain(&top->io_vgaClk,NULL,40000,100000);
+ AsyncReset *asyncReset = new AsyncReset(&top->io_asyncReset,50000);
+ Jtag *jtag = new Jtag(&top->io_jtag_tms,&top->io_jtag_tdi,&top->io_jtag_tdo,&top->io_jtag_tck,200000);
+ processes.push_back(axiClk);
+ processes.push_back(vgaClk);
+ processes.push_back(asyncReset);
+ processes.push_back(jtag);
+
+ SdramConfig *sdramConfig = new SdramConfig(
+ 2, //byteCount
+ 4, //bankCount
+ 13, //rowSize
+ 10 //colSize
+ );
+ SdramIo *sdramIo = new SdramIo();
+ sdramIo->BA = &top->io_sdram_BA ;
+ sdramIo->DQM = &top->io_sdram_DQM ;
+ sdramIo->CASn = &top->io_sdram_CASn ;
+ sdramIo->CKE = &top->io_sdram_CKE ;
+ sdramIo->CSn = &top->io_sdram_CSn ;
+ sdramIo->RASn = &top->io_sdram_RASn ;
+ sdramIo->WEn = &top->io_sdram_WEn ;
+ sdramIo->ADDR = &top->io_sdram_ADDR ;
+ sdramIo->DQ_read = (CData*)&top->io_sdram_DQ_read ;
+ sdramIo->DQ_write = (CData*)&top->io_sdram_DQ_write ;
+ sdramIo->DQ_writeEnable = &top->io_sdram_DQ_writeEnable;
+ Sdram *sdram = new Sdram(sdramConfig, sdramIo);
+
+ axiClk->add(sdram);
+ #ifdef TRACE
+ speedFactor = 100e-6;
+ cout << "Simulation caped to " << timeToSec << " 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;
+}
+
+#define redo(count,that) for(uint32_t xxx = 0;xxx < count;xxx++) that
+
+
+
+
+/*
+#include
+#include
+#include
+
+using boost::coroutines2::coroutine;
+
+void cooperative(coroutine::push_type &sink, int i)
+{
+ int j = i;
+ sink(++j);
+ sink(++j);
+ std::cout << "end\n";
+}
+
+int main2()
+{
+ using std::placeholders::_1;
+ coroutine::pull_type source{std::bind(cooperative, _1, 0)};
+ std::cout << source.get() << '\n';
+ source();
+ std::cout << source.get() << '\n';
+ source();
+}*/
+
+int main(int argc, char **argv, char **env) {
+
+ Verilated::randReset(2);
+ Verilated::commandArgs(argc, argv);
+
+ printf("BOOT\n");
+ timespec startedAt = timer_start();
+
+ BrieyWorkspace().run(100e6);
+
+ 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;
+ /*if(successCounter == testsCounter)
+ cout << "SUCCESS " << successCounter << "/" << testsCounter << endl;
+ else
+ cout<< "FAILURE " << testsCounter - successCounter << "/" << testsCounter << endl;*/
+ cout << "****************************************************************" << endl << endl;
+
+
+ exit(0);
+}
diff --git a/src/test/cpp/briey/makefile b/src/test/cpp/briey/makefile
new file mode 100644
index 0000000..39d43a5
--- /dev/null
+++ b/src/test/cpp/briey/makefile
@@ -0,0 +1,34 @@
+DEBUG?=no
+TRACE?=no
+TRACE_START=0
+ADDCFLAGS += -CFLAGS -pthread
+
+ifeq ($(TRACE),yes)
+ VERILATOR_ARGS += --trace
+ ADDCFLAGS += -CFLAGS -DTRACE
+endif
+ifeq ($(DEBUG),yes)
+ ADDCFLAGS += -CFLAGS "-g -O0"
+endif
+ifneq ($(DEBUG),yes)
+ ADDCFLAGS += -CFLAGS "-O3"
+endif
+
+ADDCFLAGS += -CFLAGS -DTRACE_START=${TRACE_START}
+
+
+
+all: clean compile
+
+run: compile
+ ./obj_dir/VBriey
+
+verilate:
+ verilator -cc ../../../../Briey.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 VBriey.mk VBriey
+
+clean:
+ rm -rf obj_dir
+
diff --git a/src/test/cpp/briey/makefile~ b/src/test/cpp/briey/makefile~
new file mode 100644
index 0000000..773ecb3
--- /dev/null
+++ b/src/test/cpp/briey/makefile~
@@ -0,0 +1,26 @@
+TRACE?=no
+TRACE_START=0
+
+ADDCFLAGS += -CFLAGS -pthread
+
+
+
+ifeq ($(TRACE),yes)
+ VERILATOR_ARGS += --trace
+ ADDCFLAGS += -CFLAGS -DTRACE
+endif
+ADDCFLAGS += -CFLAGS -DTRACE_START=${TRACE_START}
+
+
+run: compile
+ ./obj_dir/VBriey
+
+verilate:
+ verilator -cc ../../../../Briey.v -O3 -CFLAGS -std=c++11 -LDFLAGS -pthread ${ADDCFLAGS} --gdbbt ${VERILATOR_ARGS} -Wno-WIDTH --x-assign unique --exe main.cpp
+
+compile: verilate
+ make -j -C obj_dir/ -f VBriey.mk VBriey
+
+clean:
+ rm -rf obj_dir
+
diff --git a/src/test/cpp/briey/sdram.gtkw b/src/test/cpp/briey/sdram.gtkw
new file mode 100644
index 0000000..e3fcbc8
--- /dev/null
+++ b/src/test/cpp/briey/sdram.gtkw
@@ -0,0 +1,115 @@
+[*]
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Wed Jun 7 01:18:28 2017
+[*]
+[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/briey/Briey.vcd"
+[dumpfile_mtime] "Wed Jun 7 01:17:07 2017"
+[dumpfile_size] 1021433582
+[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/briey/sdram.gtkw"
+[timestart] 20762992700
+[size] 1776 953
+[pos] -1 -353
+*-16.000000 20763117800 -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.Briey.
+[treeopen] TOP.Briey.axi_jtagCtrl.
+[treeopen] TOP.Briey.axi_sdramCtrl.
+[sst_width] 325
+[signals_width] 456
+[sst_expanded] 1
+[sst_vpaned_height] 503
+@28
+TOP.Briey.axi_core_cpu.DebugPlugin_haltIt
+TOP.Briey.axi_sdramCtrl.io_sdram_BA[1:0]
+TOP.Briey.axi_sdramCtrl.io_sdram_CKE
+TOP.Briey.axi_sdramCtrl.io_sdram_CSn
+TOP.Briey.axi_sdramCtrl.io_sdram_DQM[1:0]
+@22
+TOP.Briey.axi_sdramCtrl.io_sdram_DQ_read[15:0]
+@28
+TOP.Briey.axi_sdramCtrl.io_sdram_DQ_writeEnable
+@22
+TOP.Briey.axi_sdramCtrl.io_sdram_DQ_write[15:0]
+@28
+TOP.Briey.axi_sdramCtrl.io_sdram_RASn
+TOP.Briey.axi_sdramCtrl.io_sdram_CASn
+TOP.Briey.axi_sdramCtrl.io_sdram_WEn
+@24
+TOP.Briey.axi_sdramCtrl.io_sdram_ADDR[12:0]
+@22
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_cmd_payload_context_id[3:0]
+@28
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_cmd_payload_context_last
+@22
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_cmd_payload_data[15:0]
+@28
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_cmd_payload_mask[1:0]
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_cmd_valid
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_cmd_ready
+@22
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_cmd_payload_address[24:0]
+@28
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_cmd_payload_write
+@22
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_rsp_payload_context_id[3:0]
+@28
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_rsp_payload_context_last
+@22
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_rsp_payload_data[15:0]
+@28
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_rsp_ready
+TOP.Briey.axi_sdramCtrl.ctrl.io_bus_rsp_valid
+TOP.Briey.axi_core_cpu.DebugPlugin_haltIt
+TOP.Briey.axi_core_cpu.DebugPlugin_haltedByBreak
+TOP.Briey.axi_core_cpu.DebugPlugin_isPipBusy
+TOP.Briey.axi_core_cpu.DebugPlugin_resetIt
+TOP.Briey.axi_core_cpu.DebugPlugin_stepIt
+TOP.Briey.axi_core_cpu.DebugPlugin_insertDecodeInstruction
+@22
+TOP.Briey.axi_jtagCtrl.debugger.io_mem_cmd_payload_address[31:0]
+TOP.Briey.axi_jtagCtrl.debugger.io_mem_cmd_payload_data[31:0]
+@28
+TOP.Briey.axi_jtagCtrl.debugger.io_mem_cmd_payload_size[1:0]
+TOP.Briey.axi_jtagCtrl.debugger.io_mem_cmd_payload_wr
+@29
+TOP.Briey.axi_jtagCtrl.debugger.io_mem_cmd_ready
+@28
+TOP.Briey.axi_jtagCtrl.debugger.io_mem_cmd_valid
+@22
+TOP.Briey.axi_jtagCtrl.debugger.io_mem_rsp_payload[31:0]
+@28
+TOP.Briey.axi_jtagCtrl.debugger.io_mem_rsp_valid
+@22
+TOP.Briey.axi_core_cpu.prefetch_PC[31:0]
+TOP.Briey.axi_core_cpu.execute_PC[31:0]
+@28
+TOP.Briey.axi_core_cpu.execute_IS_EBREAK
+TOP.Briey.axi_core_cpu.execute_arbitration_isValid
+@22
+TOP.Briey.axi_core_cpu.DebugPlugin_busReadDataReg[31:0]
+@28
+TOP.Briey.axi_core_cpu.writeBack_arbitration_isValid
+@22
+TOP.Briey.axi_core_cpu.writeBack_REGFILE_WRITE_DATA[31:0]
+TOP.Briey.axi_core_cpu.writeBack_PC[31:0]
+TOP.Briey.axi_core_cpu.execute_REGFILE_WRITE_DATA[31:0]
+TOP.Briey.axi_core_cpu.execute_SRC1[31:0]
+TOP.Briey.axi_core_cpu.execute_SRC2[31:0]
+TOP.Briey.axi_core_cpu.decode_SRC1[31:0]
+@28
+TOP.Briey.axi_core_cpu.decode_SRC1_CTRL[1:0]
+@22
+TOP.Briey.axi_core_cpu.decode_SRC2[31:0]
+@28
+TOP.Briey.axi_core_cpu.decode_SRC2_CTRL[1:0]
+@22
+TOP.Briey.axi_core_cpu.decode_REG1[31:0]
+TOP.Briey.axi_core_cpu.RegFilePlugin_regFile(0)[31:0]
+TOP.Briey.axi_core_cpu.decode_RegFilePlugin_regFileReadAddress1[4:0]
+@28
+TOP.Briey.axi_core_cpu.decode_IS_EBREAK
+TOP.Briey.axi_core_cpu.decode_arbitration_isValid
+@22
+TOP.Briey.axi_core_cpu.decode_INSTRUCTION[31:0]
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/src/test/cpp/regression/.cproject b/src/test/cpp/regression/.cproject
new file mode 100644
index 0000000..50a0b30
--- /dev/null
+++ b/src/test/cpp/regression/.cproject
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp
index d01514b..ac3e3a9 100644
--- a/src/test/cpp/regression/main.cpp
+++ b/src/test/cpp/regression/main.cpp
@@ -307,8 +307,8 @@ public:
currentTime = 4;
// init trace dump
- Verilated::traceEverOn(true);
#ifdef TRACE
+ Verilated::traceEverOn(true);
tfp = new VerilatedVcdC;
top->trace(tfp, 99);
tfp->open((string(name)+ ".vcd").c_str());
diff --git a/src/test/cpp/regression/makefile b/src/test/cpp/regression/makefile
index 6438b48..e749621 100644
--- a/src/test/cpp/regression/makefile
+++ b/src/test/cpp/regression/makefile
@@ -66,6 +66,7 @@ ifeq ($(FREE_RTOS),yes)
ADDCFLAGS += -CFLAGS -DFREE_RTOS
endif
+all: clean run
run: compile
./obj_dir/VVexRiscv