diff options
author | Friedrich Beckmann <friedrich.beckmann@hs-augsburg.de> | 2022-07-25 17:55:39 +0200 |
---|---|---|
committer | Friedrich Beckmann <friedrich.beckmann@hs-augsburg.de> | 2022-07-25 17:55:39 +0200 |
commit | 3fff6023602822531efdae30bc8ebf862967f1ef (patch) | |
tree | 16028102b8d850f8ab3115d28a8539ca6bc5f51d /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.cpp | 472 |
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); +} |