diff --git a/verilator/ide.cpp b/verilator/ide.cpp new file mode 100644 index 0000000..8e0d58a --- /dev/null +++ b/verilator/ide.cpp @@ -0,0 +1,294 @@ +#include "svdpi.h" +#include "Vtest__Dpi.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * simple IDE/ATA drive bus level emulation + */ + +#include +#include +#include +#include + +#ifdef unix +#include +#endif + +#ifdef _WIN32 +typedef int off_t; +#endif + +int last_evh; + +char last_dior_bit; +char last_diow_bit; +unsigned short last_read; + +int running_cver; + +static struct state_s { + unsigned short reg_seccnt, reg_secnum, reg_cyllow, reg_cylhigh, reg_drvhead; + unsigned short status; + + int fifo_rd; + int fifo_wr; + int fifo_depth; + unsigned short fifo[256 * 128]; + + int file_inited; + int file_fd; + + unsigned int lba; +} state; + +#define ATA_ALTER 0x0e +#define ATA_DEVCTRL 0x1e +#define ATA_DATA 0x10 +#define ATA_ERROR 0x11 +#define ATA_FEATURE 0x11 +#define ATA_SECCNT 0x12 +#define ATA_SECNUM 0x13 +#define ATA_CYLLOW 0x14 +#define ATA_CYLHIGH 0x15 +#define ATA_DRVHEAD 0x16 +#define ATA_STATUS 0x17 +#define ATA_COMMAND 0x17 + +#define IDE_STATUS_BSY 7 +#define IDE_STATUS_DRDY 6 +#define IDE_STATUS_DWF 5 +#define IDE_STATUS_DSC 4 +#define IDE_STATUS_DRQ 3 +#define IDE_STATUS_CORR 2 +#define IDE_STATUS_IDX 1 +#define IDE_STATUS_ERR 0 + +#define ATA_CMD_READ 0x0020 +#define ATA_CMD_WRITE 0x0030 + + +static void +do_ide_setup(struct state_s *s) +{ + s->file_fd = open("rf.dsk", O_RDWR); + + s->status = (1<fifo_depth = 0; + s->fifo_rd = 0; + s->fifo_wr = 0; +} + +static void +do_ide_read(struct state_s *s) +{ + int ret; + + s->lba = + ((s->reg_drvhead & 0x0f) << 24) | + ((s->reg_cylhigh & 0xff) << 16) | + ((s->reg_cyllow & 0xff) << 8) | + (s->reg_secnum & 0xff); + + printf("dpi_ide: %d (lba %d), seccnt %d (read)\n", + s->lba*512, s->lba, s->reg_seccnt); + + ret = lseek(s->file_fd, (off_t)s->lba*512, SEEK_SET); + ret = read(s->file_fd, (char *)s->fifo, 512 * s->reg_seccnt); + if (ret < 0) + perror("read"); + + printf("dpi_ide: buffer %06o %06o %06o %06o\n", + s->fifo[0], s->fifo[1], s->fifo[2], s->fifo[3]); + + s->fifo_depth = (512 * s->reg_seccnt) / 2; + s->fifo_rd = 0; + s->fifo_wr = 0; + + s->status = (1<lba = + ((s->reg_drvhead & 0x0f) << 24) | + ((s->reg_cylhigh & 0xff) << 16) | + ((s->reg_cyllow & 0xff) << 8) | + (s->reg_secnum & 0xff); + + if (0) printf("dpi_ide: %d (lba %d), seccnt %d (write)\n", + s->lba*512, s->lba, s->reg_seccnt); + + printf("dpi_ide: write prep\n"); + + s->fifo_depth = (512 * s->reg_seccnt) / 2; + s->fifo_rd = 0; + s->fifo_wr = 0; + + s->status = (1<lba*512, s->lba, s->reg_seccnt); + + ret = lseek(s->file_fd, (off_t)s->lba*512, SEEK_SET); + ret = write(s->file_fd, (char *)s->fifo, 512 * s->reg_seccnt); + if (ret < 0) + perror("write"); + + s->status = (1<file_inited) { + s->file_inited = 1; + do_ide_setup(s); + } + + /* */ + read_start = 0; + read_stop = 0; + write_start = 0; + write_stop = 0; + + if (dior != last_dior_bit) { + if (dior == 0) read_start = 1; + if (dior == 1) read_stop = 1; + } + + if (diow != last_diow_bit) { + if (diow == 0) write_start = 1; + if (diow == 1) write_stop = 1; + } + + last_dior_bit = dior; + last_diow_bit = diow; + + if (0) { + if (read_start) printf("dpi_ide: read start\n"); + if (read_stop) printf("dpi_ide: read stop\n"); + if (write_start) printf("dpi_ide: write start\n"); + if (write_stop) printf("dpi_ide: write stop\n"); + } + + /* */ + if (write_start) { + if (0) printf("dpi_ide: write %x %x %d\n", cs, da, da); + + switch (cs << 3 | da) { + case ATA_ALTER: + case ATA_DEVCTRL: + break; + case ATA_FEATURE: + break; + + case ATA_SECCNT: s->reg_seccnt = data_in; break; + case ATA_SECNUM: s->reg_secnum = data_in; break; + case ATA_CYLLOW: + if (0) printf("dpi_ide: cyllow %04x\n", data_in); + s->reg_cyllow = data_in; + break; + case ATA_CYLHIGH: + if (0) printf("dpi_ide: cylhigh %04x\n", data_in); + s->reg_cylhigh = data_in; + break; + case ATA_DRVHEAD: + if (0) printf("dpi_ide: drvhead %04x\n", data_in); + s->reg_drvhead = data_in; + break; + + case ATA_DATA: + s->fifo[s->fifo_wr] = data_in; + + if (0) printf("dpi_ide: write data [%d/%d] %o\n", + s->fifo_wr, s->fifo_depth, data_in); + + if (s->fifo_wr < s->fifo_depth) + s->fifo_wr++; + + if (s->fifo_wr >= s->fifo_depth) { + do_ide_write_done(s); + } + break; + + case ATA_COMMAND: + printf("dpi_ide: command %04x\n", data_in); + switch (data_in) { + case 0x0020: + printf("dpi_ide: XXX READ\n"); + do_ide_read(s); + break; + case 0x0030: + printf("dpi_ide: XXX WRITE\n"); + do_ide_write(s); + break; + } + break; + } + } + + if (read_start) { + if (0) printf("dpi_ide: read cs=%x da=%x %d\n", cs, da, da); + + switch (cs << 3 | da) { + case ATA_DATA: + *data_out = last_read = s->fifo[s->fifo_rd]; + if (0) printf("dpi_ide: read data [%d/%d] %o\n", + s->fifo_rd, s->fifo_depth, *data_out); + if (s->fifo_rd < s->fifo_depth) + s->fifo_rd++; + + if (s->fifo_rd >= s->fifo_depth) { + printf("dpi_ide: fifo empty\n"); + s->status = (1<status; + if (1) printf("dpi_ide: read status %04x\n", *data_out); + break; + } + } + + if (!read_start && !write_start && dior == 0) { + if (0) printf("dpi_ide: read %04x\n", last_read); + *data_out = last_read; + } + + if (read_stop) { + } +} + +#ifdef __cplusplus +} +#endif + + +/* + * Local Variables: + * indent-tabs-mode:nil + * c-basic-offset:4 + * End: +*/ + diff --git a/verilator/ide.cpp.1 b/verilator/ide.cpp.1 new file mode 100644 index 0000000..8e0d58a --- /dev/null +++ b/verilator/ide.cpp.1 @@ -0,0 +1,294 @@ +#include "svdpi.h" +#include "Vtest__Dpi.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * simple IDE/ATA drive bus level emulation + */ + +#include +#include +#include +#include + +#ifdef unix +#include +#endif + +#ifdef _WIN32 +typedef int off_t; +#endif + +int last_evh; + +char last_dior_bit; +char last_diow_bit; +unsigned short last_read; + +int running_cver; + +static struct state_s { + unsigned short reg_seccnt, reg_secnum, reg_cyllow, reg_cylhigh, reg_drvhead; + unsigned short status; + + int fifo_rd; + int fifo_wr; + int fifo_depth; + unsigned short fifo[256 * 128]; + + int file_inited; + int file_fd; + + unsigned int lba; +} state; + +#define ATA_ALTER 0x0e +#define ATA_DEVCTRL 0x1e +#define ATA_DATA 0x10 +#define ATA_ERROR 0x11 +#define ATA_FEATURE 0x11 +#define ATA_SECCNT 0x12 +#define ATA_SECNUM 0x13 +#define ATA_CYLLOW 0x14 +#define ATA_CYLHIGH 0x15 +#define ATA_DRVHEAD 0x16 +#define ATA_STATUS 0x17 +#define ATA_COMMAND 0x17 + +#define IDE_STATUS_BSY 7 +#define IDE_STATUS_DRDY 6 +#define IDE_STATUS_DWF 5 +#define IDE_STATUS_DSC 4 +#define IDE_STATUS_DRQ 3 +#define IDE_STATUS_CORR 2 +#define IDE_STATUS_IDX 1 +#define IDE_STATUS_ERR 0 + +#define ATA_CMD_READ 0x0020 +#define ATA_CMD_WRITE 0x0030 + + +static void +do_ide_setup(struct state_s *s) +{ + s->file_fd = open("rf.dsk", O_RDWR); + + s->status = (1<fifo_depth = 0; + s->fifo_rd = 0; + s->fifo_wr = 0; +} + +static void +do_ide_read(struct state_s *s) +{ + int ret; + + s->lba = + ((s->reg_drvhead & 0x0f) << 24) | + ((s->reg_cylhigh & 0xff) << 16) | + ((s->reg_cyllow & 0xff) << 8) | + (s->reg_secnum & 0xff); + + printf("dpi_ide: %d (lba %d), seccnt %d (read)\n", + s->lba*512, s->lba, s->reg_seccnt); + + ret = lseek(s->file_fd, (off_t)s->lba*512, SEEK_SET); + ret = read(s->file_fd, (char *)s->fifo, 512 * s->reg_seccnt); + if (ret < 0) + perror("read"); + + printf("dpi_ide: buffer %06o %06o %06o %06o\n", + s->fifo[0], s->fifo[1], s->fifo[2], s->fifo[3]); + + s->fifo_depth = (512 * s->reg_seccnt) / 2; + s->fifo_rd = 0; + s->fifo_wr = 0; + + s->status = (1<lba = + ((s->reg_drvhead & 0x0f) << 24) | + ((s->reg_cylhigh & 0xff) << 16) | + ((s->reg_cyllow & 0xff) << 8) | + (s->reg_secnum & 0xff); + + if (0) printf("dpi_ide: %d (lba %d), seccnt %d (write)\n", + s->lba*512, s->lba, s->reg_seccnt); + + printf("dpi_ide: write prep\n"); + + s->fifo_depth = (512 * s->reg_seccnt) / 2; + s->fifo_rd = 0; + s->fifo_wr = 0; + + s->status = (1<lba*512, s->lba, s->reg_seccnt); + + ret = lseek(s->file_fd, (off_t)s->lba*512, SEEK_SET); + ret = write(s->file_fd, (char *)s->fifo, 512 * s->reg_seccnt); + if (ret < 0) + perror("write"); + + s->status = (1<file_inited) { + s->file_inited = 1; + do_ide_setup(s); + } + + /* */ + read_start = 0; + read_stop = 0; + write_start = 0; + write_stop = 0; + + if (dior != last_dior_bit) { + if (dior == 0) read_start = 1; + if (dior == 1) read_stop = 1; + } + + if (diow != last_diow_bit) { + if (diow == 0) write_start = 1; + if (diow == 1) write_stop = 1; + } + + last_dior_bit = dior; + last_diow_bit = diow; + + if (0) { + if (read_start) printf("dpi_ide: read start\n"); + if (read_stop) printf("dpi_ide: read stop\n"); + if (write_start) printf("dpi_ide: write start\n"); + if (write_stop) printf("dpi_ide: write stop\n"); + } + + /* */ + if (write_start) { + if (0) printf("dpi_ide: write %x %x %d\n", cs, da, da); + + switch (cs << 3 | da) { + case ATA_ALTER: + case ATA_DEVCTRL: + break; + case ATA_FEATURE: + break; + + case ATA_SECCNT: s->reg_seccnt = data_in; break; + case ATA_SECNUM: s->reg_secnum = data_in; break; + case ATA_CYLLOW: + if (0) printf("dpi_ide: cyllow %04x\n", data_in); + s->reg_cyllow = data_in; + break; + case ATA_CYLHIGH: + if (0) printf("dpi_ide: cylhigh %04x\n", data_in); + s->reg_cylhigh = data_in; + break; + case ATA_DRVHEAD: + if (0) printf("dpi_ide: drvhead %04x\n", data_in); + s->reg_drvhead = data_in; + break; + + case ATA_DATA: + s->fifo[s->fifo_wr] = data_in; + + if (0) printf("dpi_ide: write data [%d/%d] %o\n", + s->fifo_wr, s->fifo_depth, data_in); + + if (s->fifo_wr < s->fifo_depth) + s->fifo_wr++; + + if (s->fifo_wr >= s->fifo_depth) { + do_ide_write_done(s); + } + break; + + case ATA_COMMAND: + printf("dpi_ide: command %04x\n", data_in); + switch (data_in) { + case 0x0020: + printf("dpi_ide: XXX READ\n"); + do_ide_read(s); + break; + case 0x0030: + printf("dpi_ide: XXX WRITE\n"); + do_ide_write(s); + break; + } + break; + } + } + + if (read_start) { + if (0) printf("dpi_ide: read cs=%x da=%x %d\n", cs, da, da); + + switch (cs << 3 | da) { + case ATA_DATA: + *data_out = last_read = s->fifo[s->fifo_rd]; + if (0) printf("dpi_ide: read data [%d/%d] %o\n", + s->fifo_rd, s->fifo_depth, *data_out); + if (s->fifo_rd < s->fifo_depth) + s->fifo_rd++; + + if (s->fifo_rd >= s->fifo_depth) { + printf("dpi_ide: fifo empty\n"); + s->status = (1<status; + if (1) printf("dpi_ide: read status %04x\n", *data_out); + break; + } + } + + if (!read_start && !write_start && dior == 0) { + if (0) printf("dpi_ide: read %04x\n", last_read); + *data_out = last_read; + } + + if (read_stop) { + } +} + +#ifdef __cplusplus +} +#endif + + +/* + * Local Variables: + * indent-tabs-mode:nil + * c-basic-offset:4 + * End: +*/ + diff --git a/verilator/ram.cpp b/verilator/ram.cpp new file mode 100644 index 0000000..babd989 --- /dev/null +++ b/verilator/ram.cpp @@ -0,0 +1,45 @@ +#include "svdpi.h" +#include "Vtest_top__Dpi.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned char ram_h[262144]; +unsigned char ram_l[262144]; + +static int last_r; +static int last_w; + +void dpi_ram (int a, int r, int w, int u, int l, int in, int* out) +{ + int o; + int assert_r, assert_w; + + assert_r = r && !last_r; + assert_w = w && !last_w; + + last_r = r; + last_w = w; + + o = 0; + if (r) { + if (u) o |= ram_h[a] << 8; + if (l) o |= ram_l[a]; + if (assert_r) printf("dpi_ram: read [%o] -> %o\n", a, o); + } + *out = o; + + if (w) { + if (u) ram_h[a] = in >> 8; + if (l) ram_l[a] = in; + if (assert_w) printf("dpi_ram: write [%o] -> %o\n", a, in); + } +} + + +#ifdef __cplusplus +} +#endif diff --git a/verilator/test.cpp b/verilator/test.cpp new file mode 100644 index 0000000..156548e --- /dev/null +++ b/verilator/test.cpp @@ -0,0 +1,108 @@ +// +// test.cpp +// +// + +#include +#include +#include "Vtest.h" + +#include + +Vtest *top; // Instantiation of module + +unsigned int main_time = 0; // Current simulation time + +double sc_time_stamp () { // Called by $time in Verilog + return main_time; +} + +int main(int argc, char** argv) +{ + VerilatedVcdC* tfp = NULL; + Verilated::commandArgs(argc, argv); // Remember args + + top = new Vtest; // Create instance + +#ifdef VM_TRACE + if (0) { + Verilated::traceEverOn(true); + VL_PRINTF("Enabling waves...\n"); + tfp = new VerilatedVcdC; + top->trace(tfp, 99); // Trace 99 levels of hierarchy + tfp->open("test.vcd"); // Open the dump file + } +#endif + + top->v__DOT__io__DOT__rf__DOT__buffer__DOT__ram_debug = 1; + top->v__DOT__sysclk = 0; + + while (!Verilated::gotFinish()) { + + // Resets + if (main_time < 500) { + if (main_time == 20) { + VL_PRINTF("reset on\n"); + top->v__DOT__reset = 1; + top->v__DOT__initial_pc = 07400; + } + if (main_time == 50) { + VL_PRINTF("reset off\n"); + top->v__DOT__reset = 0; + } + } + + // Toggle clock + top->v__DOT__sysclk = ~top->v__DOT__sysclk; + + // Evaluate model + top->eval(); + + //if (top->v__DOT__sysclk) { + //printf("state %d\n", top->v__DOT__state); + //} + + if (top->v__DOT__sysclk && + top->v__DOT__state == 1) + { + VL_PRINTF("pc %o ir %o l%d ac %o ion %o " + "(IF%o DF%o UF%o SF%o IB%o UB%o) state %d\n", + top->v__DOT__cpu__DOT__pc, + top->v__DOT__mb, + top->v__DOT__cpu__DOT__l, + top->v__DOT__cpu__DOT__ac, + top->v__DOT__cpu__DOT__interrupt_enable, + top->v__DOT__cpu__DOT__IF, + top->v__DOT__cpu__DOT__DF, + top->v__DOT__cpu__DOT__UF, + top->v__DOT__cpu__DOT__SF, + top->v__DOT__cpu__DOT__IB, + top->v__DOT__cpu__DOT__UB, + top->v__DOT__state); + } + +#ifdef VM_TRACE +//#define MIN_TIME 0 +//#define MAX_TIME 100000 + +#define MIN_TIME 5196000 +#define MAX_TIME 5313000 + + + if (tfp) { + if (main_time > MIN_TIME) + tfp->dump(main_time); + + if (main_time > MAX_TIME) + vl_finish("test.cpp",__LINE__,""); + } +#endif + + main_time += 10; + } + + top->final(); + + if (tfp) + tfp->close(); +}