1
0
mirror of https://github.com/livingcomputermuseum/cpus-pdp8.git synced 2026-01-13 07:29:24 +00:00
This commit is contained in:
brad 2010-10-23 23:29:25 +00:00
parent 0622c1c3a8
commit ae67233303
4 changed files with 741 additions and 0 deletions

294
verilator/ide.cpp Normal file
View File

@ -0,0 +1,294 @@
#include "svdpi.h"
#include "Vtest__Dpi.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* simple IDE/ATA drive bus level emulation
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#ifdef unix
#include <unistd.h>
#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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC);
s->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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC) | (1<<IDE_STATUS_DRQ);
}
static void
do_ide_write(struct state_s *s)
{
s->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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC) | (1<<IDE_STATUS_DRQ);
}
static void
do_ide_write_done(struct state_s *s)
{
int ret;
printf("dpi_ide: %d (lba %d), seccnt %d (write)\n",
s->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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC);
}
/*
*
*/
void dpi_ide(int data_in, int* data_out, int dior, int diow, int cs, int da)
{
struct state_s *s;
int read_start, read_stop, write_start, write_stop;
s = &state;
if (!s->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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC);
}
break;
case ATA_STATUS:
*data_out = last_read = s->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:
*/

294
verilator/ide.cpp.1 Normal file
View File

@ -0,0 +1,294 @@
#include "svdpi.h"
#include "Vtest__Dpi.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* simple IDE/ATA drive bus level emulation
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#ifdef unix
#include <unistd.h>
#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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC);
s->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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC) | (1<<IDE_STATUS_DRQ);
}
static void
do_ide_write(struct state_s *s)
{
s->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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC) | (1<<IDE_STATUS_DRQ);
}
static void
do_ide_write_done(struct state_s *s)
{
int ret;
printf("dpi_ide: %d (lba %d), seccnt %d (write)\n",
s->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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC);
}
/*
*
*/
void dpi_ide(int data_in, int* data_out, int dior, int diow, int cs, int da)
{
struct state_s *s;
int read_start, read_stop, write_start, write_stop;
s = &state;
if (!s->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<<IDE_STATUS_DRDY)|(1<<IDE_STATUS_DSC);
}
break;
case ATA_STATUS:
*data_out = last_read = s->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:
*/

45
verilator/ram.cpp Normal file
View File

@ -0,0 +1,45 @@
#include "svdpi.h"
#include "Vtest_top__Dpi.h"
#include <stdio.h>
#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

108
verilator/test.cpp Normal file
View File

@ -0,0 +1,108 @@
//
// test.cpp
//
//
#include <verilated.h>
#include <verilated_vcd_c.h>
#include "Vtest.h"
#include <iostream>
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();
}