Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
#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 "verilated_vcd_c.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);
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;
cout << "Had simulate " << workspaceCycles << " clock cycles in " << duration*1e-9 << " s (" << workspaceCycles / (duration*1e-9) << " Khz)" << endl;
cout << "****************************************************************" << endl << endl;
exit(0);
}
530554d19This file is pinned to the selected release. Download the original to open it in your design tool.