mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-03 14:53:00 +00:00
430 lines
9.8 KiB
C++
430 lines
9.8 KiB
C++
#include <verilated.h> // Defines common routines
|
|
#include "Vbbc.h"
|
|
#include "verilated_vcd_c.h"
|
|
|
|
#include "edge.h"
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <cstdlib>
|
|
#include <cstdio>
|
|
#include <stdexcept>
|
|
#include <ctype.h>
|
|
#include <SDL/SDL.h>
|
|
|
|
Vbbc *uut; // Instantiation of module
|
|
SDL_Event event;
|
|
|
|
vluint64_t main_time = 0; // Current simulation time
|
|
// This is a 64-bit integer to reduce wrap over issues and
|
|
// allow modulus. You can also use a double, if you wish.
|
|
double sc_time_stamp () { // Called by $time in Verilog
|
|
return main_time; // converts to double, to match
|
|
// what SystemC does
|
|
}
|
|
|
|
void SetKeyState(int x, int y, bool state)
|
|
{
|
|
unsigned char b = 1<<y;
|
|
|
|
if (state)
|
|
{
|
|
uut->v__DOT__KEYB__DOT__keys[x] = uut->v__DOT__KEYB__DOT__keys[x] | b;
|
|
}
|
|
else
|
|
{
|
|
uut->v__DOT__KEYB__DOT__keys[x] = uut->v__DOT__KEYB__DOT__keys[x] & ~b;
|
|
}
|
|
|
|
}
|
|
|
|
void EmuKeyboard(SDLKey key, bool state)
|
|
{
|
|
int val = state ? 1 : 0;
|
|
//key = tolower(key);
|
|
std::cout << key << " " << state << std::endl;
|
|
switch (key)
|
|
{
|
|
case SDLK_LEFT:
|
|
SetKeyState(0,0, state);
|
|
break;
|
|
case SDLK_RIGHT:
|
|
SetKeyState(0,0, state);
|
|
break;
|
|
case SDLK_q:
|
|
SetKeyState(0,1, state);
|
|
break;
|
|
case SDLK_F10:
|
|
SetKeyState(0,2, state);
|
|
break;
|
|
case SDLK_1:
|
|
SetKeyState(0,3, state);
|
|
break;
|
|
case SDLK_CAPSLOCK:
|
|
SetKeyState(0,4, state);
|
|
break;
|
|
//case SDLK_LEFT: SetKeyState(0,5, state); break;
|
|
//case SDLK_RIGHT: SetKeyState(0,6, state); break;
|
|
case SDLK_ESCAPE:
|
|
SetKeyState(0,7, state);
|
|
break;
|
|
case SDLK_3:
|
|
SetKeyState(1,1, state);
|
|
break;
|
|
case SDLK_w:
|
|
SetKeyState(1,2, state);
|
|
break;
|
|
case SDLK_2:
|
|
SetKeyState(1,3, state);
|
|
break;
|
|
case SDLK_a:
|
|
SetKeyState(1,4, state);
|
|
break;
|
|
case SDLK_s:
|
|
SetKeyState(1,5, state);
|
|
break;
|
|
case SDLK_z:
|
|
SetKeyState(1,6, state);
|
|
break;
|
|
case SDLK_F1:
|
|
SetKeyState(1,7, state);
|
|
break;
|
|
case SDLK_4:
|
|
SetKeyState(2,1, state);
|
|
break;
|
|
case SDLK_e:
|
|
SetKeyState(2,2, state);
|
|
break;
|
|
case SDLK_d:
|
|
SetKeyState(2,3, state);
|
|
break;
|
|
case SDLK_x:
|
|
SetKeyState(2,4, state);
|
|
break;
|
|
case SDLK_c:
|
|
SetKeyState(2,5, state);
|
|
break;
|
|
case SDLK_SPACE:
|
|
SetKeyState(2,6, state);
|
|
break;
|
|
case SDLK_F2:
|
|
SetKeyState(2,7, state);
|
|
break;
|
|
case SDLK_5:
|
|
SetKeyState(3,1, state);
|
|
break;
|
|
case SDLK_t:
|
|
SetKeyState(3,2, state);
|
|
break;
|
|
case SDLK_r:
|
|
SetKeyState(3,3, state);
|
|
break;
|
|
case SDLK_f:
|
|
SetKeyState(3,4, state);
|
|
break;
|
|
case SDLK_g:
|
|
SetKeyState(3,5, state);
|
|
break;
|
|
case SDLK_v:
|
|
SetKeyState(3,6, state);
|
|
break;
|
|
case SDLK_F3:
|
|
SetKeyState(3,7, state);
|
|
break;
|
|
case SDLK_F4:
|
|
SetKeyState(4,1, state);
|
|
break;
|
|
case SDLK_7:
|
|
SetKeyState(4,2, state);
|
|
break;
|
|
case SDLK_6:
|
|
SetKeyState(4,3, state);
|
|
break;
|
|
case SDLK_y:
|
|
SetKeyState(4,4, state);
|
|
break;
|
|
case SDLK_h:
|
|
SetKeyState(4,5, state);
|
|
break;
|
|
case SDLK_b:
|
|
SetKeyState(4,6, state);
|
|
break;
|
|
case SDLK_F5:
|
|
SetKeyState(4,7, state);
|
|
break;
|
|
case SDLK_8:
|
|
SetKeyState(5,1, state);
|
|
break;
|
|
case SDLK_i:
|
|
SetKeyState(5,2, state);
|
|
break;
|
|
case SDLK_u:
|
|
SetKeyState(5,3, state);
|
|
break;
|
|
case SDLK_j:
|
|
SetKeyState(5,4, state);
|
|
break;
|
|
case SDLK_n:
|
|
SetKeyState(5,5, state);
|
|
break;
|
|
case SDLK_m:
|
|
SetKeyState(5,6, state);
|
|
break;
|
|
case SDLK_F6:
|
|
SetKeyState(5,7, state);
|
|
break;
|
|
case SDLK_F7:
|
|
SetKeyState(6,1, state);
|
|
break;
|
|
case SDLK_9:
|
|
SetKeyState(6,2, state);
|
|
break;
|
|
case SDLK_o:
|
|
SetKeyState(6,3, state);
|
|
break;
|
|
case SDLK_k:
|
|
SetKeyState(6,4, state);
|
|
break;
|
|
case SDLK_l:
|
|
SetKeyState(6,5, state);
|
|
break;
|
|
case SDLK_F8:
|
|
SetKeyState(6,7, state);
|
|
break;
|
|
case SDLK_0:
|
|
SetKeyState(7,2, state);
|
|
break;
|
|
case SDLK_p:
|
|
SetKeyState(7,3, state);
|
|
break;
|
|
case SDLK_F9:
|
|
SetKeyState(7,7, state);
|
|
break;
|
|
case SDLK_RETURN:
|
|
SetKeyState(9,4, state);
|
|
break;
|
|
case SDLK_BACKSPACE:
|
|
SetKeyState(9,5, state);
|
|
break;
|
|
case SDLK_PRINT:
|
|
uut->v__DOT__keyb_break = state;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
// SDL events
|
|
|
|
srand(12345);
|
|
|
|
char main_memory[65536];
|
|
|
|
bool vcdTrace = false;
|
|
VerilatedVcdC* tfp = NULL;
|
|
|
|
//The images
|
|
SDL_Surface* screen = NULL;
|
|
SDL_Init(SDL_INIT_VIDEO);
|
|
//Set up screen
|
|
screen = SDL_SetVideoMode( 800, 600, 32, SDL_SWSURFACE | SDL_RESIZABLE );
|
|
SDL_WM_SetCaption("BBC B Verilog Simulation - RGB Video Out" ,NULL);
|
|
SDL_EnableKeyRepeat(500, 750);
|
|
|
|
//Update Screen
|
|
SDL_Flip( screen );
|
|
|
|
// Check that the window was successfully made
|
|
if (screen == NULL)
|
|
{
|
|
// In the event that the window could not be made...
|
|
printf("Could not create window: %s\n", SDL_GetError());
|
|
return 1;
|
|
}
|
|
|
|
// simulate a monitor
|
|
int xcount = 0;
|
|
int ycount = 0;
|
|
|
|
Edge clk32m;
|
|
Edge clk24m;
|
|
|
|
Edge vsync;
|
|
Edge hsync;
|
|
|
|
|
|
std::string fileName = "bbc.rom";
|
|
|
|
if (argc > 1)
|
|
{
|
|
fileName = argv[1];
|
|
}
|
|
|
|
FILE *fp = fopen(fileName.c_str(), "r");
|
|
|
|
if (fp == NULL)
|
|
{
|
|
std::cerr << "failed to open file:" << fileName << std::endl;
|
|
exit(-1);
|
|
}
|
|
|
|
fseek(fp, 0L, SEEK_END);
|
|
size_t sz = ftell(fp);
|
|
fseek(fp, 0L, SEEK_SET);
|
|
|
|
std::cerr << fread((char *)(main_memory + 32768), sizeof(char), sz, fp) << std::endl;
|
|
fclose(fp);
|
|
|
|
Verilated::commandArgs(argc, argv); // Remember args
|
|
uut = new Vbbc; // Create instance
|
|
uut->eval();
|
|
|
|
if (vcdTrace)
|
|
{
|
|
Verilated::traceEverOn(true);
|
|
tfp = new VerilatedVcdC;
|
|
uut->trace(tfp, 99);
|
|
std::string vcdname = "bbc.vcd";
|
|
tfp->open(vcdname.c_str());
|
|
}
|
|
|
|
uut->RESET_I = 1;
|
|
uut->eval();
|
|
|
|
Uint8 *p = (Uint8 *)screen->pixels;
|
|
|
|
unsigned char mode = 7;
|
|
|
|
if (argc > 1)
|
|
{
|
|
mode = (unsigned char) atoi(argv[1]);
|
|
}
|
|
|
|
uut->DIP_SWITCH = 0x0;
|
|
|
|
while (!Verilated::gotFinish())
|
|
{
|
|
if (main_time > 32)
|
|
{
|
|
uut->RESET_I = 0; // Deassert reset
|
|
}
|
|
|
|
if ((main_time % 3) == 0)
|
|
{
|
|
uut->CLK32M_I = uut->CLK32M_I ? 0 : 1; // Toggle clock
|
|
}
|
|
|
|
if ((main_time % 4) == 0)
|
|
{
|
|
uut->CLK24M_I = uut->CLK24M_I ? 0 : 1; // Toggle clock
|
|
}
|
|
|
|
uut->eval(); // Evaluate model
|
|
|
|
if (tfp != NULL)
|
|
{
|
|
tfp->dump (main_time);
|
|
}
|
|
|
|
clk32m.Update(uut->CLK32M_I);
|
|
clk24m.Update(uut->CLK24M_I);
|
|
|
|
hsync.Update(uut->HSYNC);
|
|
vsync.Update(uut->VSYNC);
|
|
|
|
if (clk32m.PosEdge())
|
|
{
|
|
uut->MEM_DI = main_memory[uut->MEM_ADR];
|
|
uut->VID_DI = main_memory[uut->VID_ADR];
|
|
|
|
if (uut->MEM_WE)
|
|
{
|
|
main_memory[uut->MEM_ADR] = uut->MEM_DO;
|
|
}
|
|
}
|
|
|
|
|
|
if (vsync.PosEdge())
|
|
{
|
|
if (ycount > 2)
|
|
{
|
|
SDL_Flip( screen );
|
|
SDL_FillRect(screen, NULL, 0x000000);
|
|
std::cerr << ycount << std::endl;
|
|
}
|
|
|
|
p = (Uint8 *)screen->pixels;
|
|
// print out the number of lines processed.
|
|
ycount = 0;
|
|
xcount = 0;
|
|
}
|
|
else if (hsync.PosEdge())
|
|
{
|
|
while( SDL_PollEvent( &event ) )
|
|
{
|
|
/* We are only worried about SDL_KEYDOWN and SDL_KEYUP events */
|
|
switch( event.type )
|
|
{
|
|
case SDL_KEYDOWN:
|
|
|
|
EmuKeyboard(event.key.keysym.sym, true);
|
|
if (event.key.keysym.sym == SDLK_v)
|
|
{
|
|
//printVideoRegister();
|
|
}
|
|
break;
|
|
case SDL_KEYUP:
|
|
|
|
EmuKeyboard(event.key.keysym.sym, false);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
ycount++;
|
|
xcount = 0;
|
|
p = (Uint8 *)screen->pixels;
|
|
p+= ycount * screen->w *4;
|
|
}
|
|
else if (clk32m.PosEdge() && (bool) uut->VIDEO_CLKEN && (bool) !uut->HSYNC && (bool) !uut->VSYNC)
|
|
{
|
|
|
|
if ((ycount < screen->h) && (xcount <= screen->w))
|
|
{
|
|
if ((unsigned char)uut->VIDEO_R) *p++ = 0xFF;
|
|
else p++;
|
|
if ((unsigned char)uut->VIDEO_G) *p++ = 0xFF;
|
|
else p++;
|
|
if ((unsigned char)uut->VIDEO_B) *p++ = 0xFF;
|
|
else p++;
|
|
|
|
// *p++ = ((unsigned char)uut->VIDEO_R) ? 0xFFFF : 0; //<< 4 | (unsigned char)uut->video_b;
|
|
// *p++ = ((unsigned char)uut->VIDEO_G) ? 0xFFFF : 0; //<< 4 | (unsigned char)uut->video_g;
|
|
// *p++ = ((unsigned char)uut->VIDEO_B) ? 0xFFFF : 0; //<< 4 | (unsigned char)uut->video_r;
|
|
p++;
|
|
|
|
xcount++;
|
|
}
|
|
}
|
|
|
|
main_time++; // Time passes...
|
|
}
|
|
|
|
uut->final(); // Done simulating
|
|
|
|
if (tfp != NULL)
|
|
{
|
|
tfp->close();
|
|
delete tfp;
|
|
}
|
|
|
|
//Quit SDL
|
|
SDL_Quit();
|
|
|
|
delete uut;
|
|
}
|