aboutsummaryrefslogtreecommitdiff
path: root/VexRiscv/src/test/cpp/briey/main.cpp
diff options
context:
space:
mode:
authorFriedrich Beckmann <friedrich.beckmann@hs-augsburg.de>2022-07-25 17:55:39 +0200
committerFriedrich Beckmann <friedrich.beckmann@hs-augsburg.de>2022-07-25 17:55:39 +0200
commit3fff6023602822531efdae30bc8ebf862967f1ef (patch)
tree16028102b8d850f8ab3115d28a8539ca6bc5f51d /VexRiscv/src/test/cpp/briey/main.cpp
Initial Commit
Diffstat (limited to 'VexRiscv/src/test/cpp/briey/main.cpp')
-rw-r--r--VexRiscv/src/test/cpp/briey/main.cpp472
1 files changed, 472 insertions, 0 deletions
diff --git a/VexRiscv/src/test/cpp/briey/main.cpp b/VexRiscv/src/test/cpp/briey/main.cpp
new file mode 100644
index 0000000..bebe880
--- /dev/null
+++ b/VexRiscv/src/test/cpp/briey/main.cpp
@@ -0,0 +1,472 @@
+#include "VBriey.h"
+#include "VBriey_Briey.h"
+//#include "VBriey_Axi4VgaCtrl.h"
+//#include "VBriey_VgaCtrl.h"
+#ifdef REF
+#include "VBriey_RiscvCore.h"
+#endif
+#include "verilated.h"
+#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>
+
+#include "VBriey_VexRiscv.h"
+
+
+#include "../common/framework.h"
+#include "../common/jtag.h"
+#include "../common/uart.h"
+
+
+
+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;
+ //printf("SDRAM : Write A=%08x D=%02x\n",addr,data);
+ this->data[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 VexRiscvTracer : public SimElement{
+public:
+ VBriey_VexRiscv *cpu;
+ ofstream instructionTraces;
+ ofstream regTraces;
+
+ VexRiscvTracer(VBriey_VexRiscv *cpu){
+ this->cpu = cpu;
+#ifdef TRACE_INSTRUCTION
+ instructionTraces.open ("instructionTrace.log");
+#endif
+#ifdef TRACE_REG
+ regTraces.open ("regTraces.log");
+#endif
+ }
+
+
+
+ virtual void preCycle(){
+#ifdef TRACE_INSTRUCTION
+ if(cpu->writeBack_arbitration_isFiring){
+ instructionTraces << hex << setw(8) << cpu->writeBack_INSTRUCTION << endl;
+ }
+#endif
+#ifdef TRACE_REG
+ if(cpu->writeBack_RegFilePlugin_regFileWrite_valid == 1 && cpu->writeBack_RegFilePlugin_regFileWrite_payload_address != 0){
+ regTraces << " PC " << hex << setw(8) << cpu->writeBack_PC << " : reg[" << dec << setw(2) << (uint32_t)cpu->writeBack_RegFilePlugin_regFileWrite_payload_address << "] = " << hex << setw(8) << cpu->writeBack_RegFilePlugin_regFileWrite_payload_data << endl;
+ }
+
+#endif
+ }
+};
+
+
+
+
+#include <SDL2/SDL.h>
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+
+class Display : public SimElement{
+public:
+ int width, height;
+ uint32_t *pixels;
+ SDL_Window* window;
+ SDL_Renderer* renderer;
+ SDL_Texture * texture;
+ uint32_t x,y;
+ uint32_t refreshCounter = 0;
+
+ Display(int width, int height){
+ this->width = width;
+ this->height = height;
+ x = y = 0;
+ init();
+ }
+
+ virtual ~Display(){
+ delete[] pixels;
+ SDL_DestroyTexture(texture);
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+ }
+
+ void init(){
+
+ /* Initialize SDL. */
+ if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ return;
+
+ /* Create the window where we will draw. */
+ window = SDL_CreateWindow("VGA",
+ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+ width, height,
+ SDL_WINDOW_SHOWN);
+
+ /* We must call SDL_CreateRenderer in order for draw calls to affect this window. */
+ renderer = SDL_CreateRenderer(window, -1, 0);
+
+ texture = SDL_CreateTexture(renderer,
+ SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height);
+ pixels = new Uint32[width * height];
+ memset(pixels, 0, width * height * sizeof(Uint32));
+ }
+
+ void set(uint32_t color){
+ pixels[x + y*width] = color;
+ }
+
+ void incX(){
+ x++;
+ if(x >= width) x = width;
+ }
+
+ void incY(){
+ y++;
+ if(y >= height) y = height;
+ }
+
+ void refresh(){
+ //cout << "Display refresh " << refreshCounter++ << endl;
+ SDL_UpdateTexture(texture, NULL, pixels, 640 * sizeof(Uint32));
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
+ memset(pixels, 0, width * height * sizeof(Uint32));
+ }
+
+ virtual void postCycle(){
+
+ }
+
+ virtual void preCycle(){
+
+ }
+};
+
+class Vga : public Display{
+public:
+ VBriey* top;
+ Vga(VBriey* top,int width, int height) : Display(width, height){
+ this->top = top;
+ }
+
+ virtual ~Vga(){
+ }
+
+ virtual void postCycle(){
+
+ }
+
+ uint32_t lastvSync = 0,lasthSync = 0;
+ virtual void preCycle(){
+ if(!top->io_vga_vSync && lastvSync) {
+ y = 0;
+ refresh();
+ }
+ if(!top->io_vga_hSync && lasthSync && x != 0) {
+ incY();
+ x = 0;
+ }
+ if(top->io_vga_colorEn){
+ this->set((top->io_vga_color_r << 19) + (top->io_vga_color_g << 10) + (top->io_vga_color_b << 3));
+ incX();
+ }
+
+ lastvSync = top->io_vga_vSync;
+ lasthSync = top->io_vga_hSync;
+ }
+};
+
+class BrieyWorkspace : public Workspace<VBriey>{
+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,80000);
+ UartRx *uartRx = new UartRx(&top->io_uart_txd,1.0e12/115200);
+ timeProcesses.push_back(axiClk);
+ timeProcesses.push_back(vgaClk);
+ timeProcesses.push_back(asyncReset);
+ timeProcesses.push_back(jtag);
+ timeProcesses.push_back(uartRx);
+ top->io_uart_rxd = 1;
+
+
+ SdramConfig *sdramConfig = new SdramConfig(
+ 2, //byteCount
+ 4, //bankCount
+ 1 << 13, //rowSize
+ 1 << 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 = (CData*)&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
+
+ axiClk->add(new VexRiscvTracer(top->Briey->axi_core_cpu));
+
+ #ifdef VGA
+ Vga *vga = new Vga(top,640,480);
+ vgaClk->add(vga);
+ #endif
+
+ top->io_coreInterrupt = 0;
+ }
+
+
+ /*bool trigged = false;
+ uint32_t frameStartCounter = 0;
+ virtual void dump(uint64_t i){
+ if(!trigged) {
+ if(top->Briey->axi_vgaCtrl->vga_ctrl->io_frameStart) {
+ frameStartCounter++;
+ if(frameStartCounter < 3*32) cout << "**\n" << endl;
+ }
+ if(top->Briey->axi_vgaCtrl->vga_ctrl->io_error && frameStartCounter > 3*32) trigged = true;
+ }
+ if(trigged)Workspace::dump(i);
+ }*/
+
+
+};
+
+
+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();
+
+ BrieyWorkspace().run(1e9);
+
+ uint64_t duration = timer_end(startedAt);
+ cout << endl << "****************************************************************" << endl;
+
+
+ exit(0);
+}