From a04447387a8429948540ab6d50b4685a2c1ce9e5 Mon Sep 17 00:00:00 2001 From: brad Date: Tue, 13 Apr 2010 14:02:34 +0000 Subject: [PATCH] added pli code --- pli/ide/Makefile | 20 + pli/ide/pli_ide.c | 406 +++++++++++++++++ pli/ide/win32.bat | 6 + pli/rf/Makefile | 25 ++ pli/rf/pli_ram.c | 279 ++++++++++++ pli/rf/pli_rf.c | 1080 +++++++++++++++++++++++++++++++++++++++++++++ pli/rf/win32.bat | 7 + 7 files changed, 1823 insertions(+) create mode 100644 pli/ide/Makefile create mode 100644 pli/ide/pli_ide.c create mode 100644 pli/ide/win32.bat create mode 100644 pli/rf/Makefile create mode 100644 pli/rf/pli_ram.c create mode 100644 pli/rf/pli_rf.c create mode 100644 pli/rf/win32.bat diff --git a/pli/ide/Makefile b/pli/ide/Makefile new file mode 100644 index 0000000..b46d0d1 --- /dev/null +++ b/pli/ide/Makefile @@ -0,0 +1,20 @@ +# + +INCS = -I../../cver/gplcver-2.12a.src/pli_incs + +CFLAGS= -fPIC -Wall -g $(INCS) -D__CVER__ +LFLAGS= -G -shared -export-dynamic + +all: pli_ide.so pli_ide.vpi + +pli_ide.o: pli_ide.c + $(CC) $(CFLAGS) -c pli_ide.c + +pli_ide.so: pli_ide.o + $(LD) $(LFLAGS) pli_ide.o -o pli_ide.so + +pli_ide.vpi: pli_ide.o + $(LD) $(LFLAGS) pli_ide.o -o pli_ide.vpi + +clean: + rm -f *.o *.so *.vpi diff --git a/pli/ide/pli_ide.c b/pli/ide/pli_ide.c new file mode 100644 index 0000000..f30222e --- /dev/null +++ b/pli/ide/pli_ide.c @@ -0,0 +1,406 @@ +/* pli_ide.c */ +/* + * simple IDE/ATA drive bus level emulation + */ + +#include +#include +#include +#include + +#ifdef unix +#include +#endif + +#ifdef _WIN32 +typedef int off_t; +#endif + +#include "vpi_user.h" + +#ifdef __CVER__ +#include "cv_vpi_user.h" +#endif + +#ifdef __MODELSIM__ +#include "veriuser.h" +#endif + +PLI_INT32 pli_ide(void); +extern void register_my_systfs(void); +extern void register_my_systfs(void); + +char *instnam_tab[10]; +int last_evh; + +char last_dior_bit; +char last_diow_bit; + +static struct state_s { + vpiHandle bus_aref; + 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 * 64]; + + int file_inited; + int file_fd; + + unsigned int lba; +} state[10]; + +static int getadd_inst_id(vpiHandle mhref) +{ + register int i; + char *chp; + + chp = vpi_get_str(vpiFullName, mhref); + //vpi_printf("getadd_inst_id() %s\n", chp); + + for (i = 1; i <= last_evh; i++) { + if (strcmp(instnam_tab[i], chp) == 0) + return(i); + } + + instnam_tab[++last_evh] = malloc(strlen(chp) + 1); + strcpy(instnam_tab[last_evh], chp); + + //vpi_printf("getadd_inst_id() done %d\n", last_evh); + return(last_evh); +} + +#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); + + vpi_printf("pli_ide: lba %08x (%d), seccnt %d\n", + s->lba, s->lba*512,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"); + + s->fifo_depth = (512 * s->reg_seccnt) / 2; + s->fifo_rd = 0; + s->fifo_wr = 0; + + s->status = (1<file_inited) { + s->file_inited = 1; + do_ide_setup(s); + } + + iter = vpi_iterate(vpiArgument, href); + + numargs = vpi_get(vpiSize, iter); + + /* data_bus[15:0], ide_dior, ide_diow, ide_cs[1:0], ide_da[2:0] */ + busref = vpi_scan(iter); + diorref = vpi_scan(iter); + diowref = vpi_scan(iter); + csref = vpi_scan(iter); + daref = vpi_scan(iter); + + if (busref == NULL || diorref == NULL || diowref == NULL || + csref == NULL || daref == NULL) + { + vpi_printf("**ERR: $pli_ide bad args\n"); + return(0); + } + + tmpval.format = vpiBinStrVal; + vpi_get_value(busref, &tmpval); + strcpy(bus_bits, tmpval.value.str); + + tmpval.format = vpiIntVal; + vpi_get_value(busref, &tmpval); + bus = tmpval.value.integer; + + tmpval.format = vpiBinStrVal; + vpi_get_value(csref, &tmpval); + strcpy(cs_bits, tmpval.value.str); + + tmpval.format = vpiIntVal; + vpi_get_value(csref, &tmpval); + cs = tmpval.value.integer; + + tmpval.format = vpiBinStrVal; + vpi_get_value(daref, &tmpval); + strcpy(da_bits, tmpval.value.str); + + tmpval.format = vpiIntVal; + vpi_get_value(daref, &tmpval); + da = tmpval.value.integer; + + tmpval.format = vpiBinStrVal; + vpi_get_value(diorref, &tmpval); + dior_bit = tmpval.value.str[0]; + + tmpval.format = vpiBinStrVal; + vpi_get_value(diowref, &tmpval); + diow_bit = tmpval.value.str[0]; + + /* */ + read_start = 0; + read_stop = 0; + write_start = 0; + write_stop = 0; + + if (dior_bit != last_dior_bit) { + if (dior_bit == '0') read_start = 1; + if (dior_bit == '1') read_stop = 1; + } + + if (diow_bit != last_diow_bit) { + if (diow_bit == '0') write_start = 1; + if (diow_bit == '1') write_stop = 1; + } + + last_dior_bit = dior_bit; + last_diow_bit = diow_bit; + + if (0) { + if (read_start) vpi_printf("pli_ide: read start\n"); + if (read_stop) vpi_printf("pli_ide: read stop\n"); + if (write_start) vpi_printf("pli_ide: write start\n"); + if (write_stop) vpi_printf("pli_ide: write stop\n"); + } + + /* */ + if (write_start) { + if (0) vpi_printf("pli_ide: write %s %s %d\n", cs_bits, da_bits, da); + + switch (cs << 3 | da) { + case ATA_ALTER: + case ATA_DEVCTRL: + break; + case ATA_FEATURE: + break; + + case ATA_SECCNT: s->reg_seccnt = bus; break; + case ATA_SECNUM: s->reg_secnum = bus; break; + case ATA_CYLLOW: + if (0) vpi_printf("pli_ide: cyllow %04x %s\n", bus, bus_bits); + s->reg_cyllow = bus; + break; + case ATA_CYLHIGH: + if (0) vpi_printf("pli_ide: cylhigh %04x %s\n", bus, bus_bits); + s->reg_cylhigh = bus; + break; + case ATA_DRVHEAD: + if (0) vpi_printf("pli_ide: drvhead %04x %s\n", bus, bus_bits); + s->reg_drvhead = bus; + break; + + case ATA_DATA: + if (1) vpi_printf("pli_ide: write data %04x %s\n", bus, bus_bits); + break; + + case ATA_COMMAND: + vpi_printf("pli_ide: command %04x %s\n", bus, bus_bits); + switch (bus) { + case 0x0020: + vpi_printf("pli_ide: XXX READ\n"); + do_ide_read(s); + break; + case 0x0030: + vpi_printf("pli_ide: XXX WRITE\n"); + break; + } + break; + } + } + + if (read_start) { + if (0) vpi_printf("pli_ide: read %s %s %d\n", cs_bits, da_bits, da); + + switch (cs << 3 | da) { + case ATA_DATA: + bus = s->fifo[s->fifo_rd]; + if (0) vpi_printf("pli_ide: read data [%d/%d] %04o\n", + s->fifo_rd, s->fifo_depth, bus); + if (s->fifo_rd < s->fifo_depth) + s->fifo_rd++; + + if (s->fifo_rd >= s->fifo_depth) { + vpi_printf("pli_ide: fifo empty\n"); + s->status = (1<status; + vpi_printf("pli_ide: read status %04x\n", bus); + break; + } + +#ifdef __CVER__ + if (s->bus_aref == 0) + s->bus_aref = vpi_put_value(busref, NULL, NULL, vpiAddDriver); +#else + s->bus_aref = busref; +#endif + + outval.format = vpiIntVal; + outval.value.integer = bus; + vpi_put_value(s->bus_aref, &outval, NULL, vpiNoDelay); + } + + if (read_stop) { + outval.format = vpiBinStrVal; + outval.value.str = "zzzzzzzzzzzzzzzz"; +// outval.value.str = "0000000000000000"; + if (s->bus_aref) + vpi_put_value(s->bus_aref, &outval, NULL, vpiNoDelay); + } + + return(0); +} + +/* + * register all vpi_ PLI 2.0 style user system tasks and functions + */ +void register_my_systfs(void) +{ + p_vpi_systf_data systf_data_p; + + /* use predefined table form - could fill systf_data_list dynamically */ + static s_vpi_systf_data systf_data_list[] = { + { vpiSysTask, 0, "$pli_ide", pli_ide, NULL, NULL, NULL }, + { 0, 0, NULL, NULL, NULL, NULL, NULL } + }; + + systf_data_p = &(systf_data_list[0]); + while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++); +} + +#ifdef __CVER__ +static void (*ide_vlog_startup_routines[]) () = +{ + register_my_systfs, + 0 +}; + +/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */ +/* in standard PLI vlog_startup_routines table */ +void ide_vpi_compat_bootstrap(void) +{ + int i; + + for (i = 0;; i++) + { + if (ide_vlog_startup_routines[i] == NULL) break; + ide_vlog_startup_routines[i](); + } +} + +void vpi_compat_bootstrap(void) +{ + ide_vpi_compat_bootstrap(); +} + +void __stack_chk_fail_local(void) {} +#endif + +#ifdef __MODELSIM__ +static void (*vlog_startup_routines[]) () = +{ + register_my_systfs, + 0 +}; +#endif + + +/* + * Local Variables: + * indent-tabs-mode:nil + * c-basic-offset:4 + * End: +*/ diff --git a/pli/ide/win32.bat b/pli/ide/win32.bat new file mode 100644 index 0000000..c9e3b5c --- /dev/null +++ b/pli/ide/win32.bat @@ -0,0 +1,6 @@ +rem c:\program files\microsoft visual studio\vcvars32.bat + +set MTI_HOME=c:\Modeltech_6.2g + +cl -c -I%MTI_HOME%\include -D__MODELSIM__ pli_ide.c +link -dll -export:vlog_startup_routines pli_ide.obj %MTI_HOME%\win32\mtipli.lib diff --git a/pli/rf/Makefile b/pli/rf/Makefile new file mode 100644 index 0000000..73b7c80 --- /dev/null +++ b/pli/rf/Makefile @@ -0,0 +1,25 @@ +# + +INCS = -I../../cver/gplcver-2.12a.src/pli_incs + +CFLAGS= -fPIC -Wall -g $(INCS) -D__CVER__ +LFLAGS= -G -shared -export-dynamic + +all: pli_rf.so pli_rf.vpi + +pli_rf.o: pli_rf.c + $(CC) $(CFLAGS) -c pli_rf.c + +pli_ram.o: pli_ram.c + $(CC) $(CFLAGS) -c pli_ram.c + +pli_rf.so: pli_rf.o pli_ram.o + $(LD) $(LFLAGS) pli_rf.o pli_ram.o -o pli_rf.so + +pli_rf.vpi: pli_rf.o pli_ram.o + $(LD) $(LFLAGS) pli_rf.o pli_ram.o -o pli_rf.vpi + + +clean: + rm -f *.o *.so *.vpi + diff --git a/pli/rf/pli_ram.c b/pli/rf/pli_ram.c new file mode 100644 index 0000000..554e929 --- /dev/null +++ b/pli/rf/pli_ram.c @@ -0,0 +1,279 @@ +/* pli_ram.c */ + +#include +#include +#include +#include + +#ifdef unix +#include +#endif + +#include "vpi_user.h" + +#ifdef __CVER__ +#include "cv_vpi_user.h" +#endif + +#ifdef __MODELSIM__ +#include "veriuser.h" +#endif + +typedef unsigned short u16; + +static char last_ce_bit; +static char last_we_bit; +static unsigned last_addr; + +static vpiHandle do_aref; +static int mem_init; +u16 *M; + +static char *instnam_tab[10]; +static int last_evh; + +void do_mem_preload(char *fn) +{ + FILE *f; + f = fopen(fn, "r"); + if (f) { + unsigned int a, v; + while (fscanf(f, "%o %o\n", &a, &v) == 2) { + vpi_printf("[%06o] <- %06o\n", a, v); + M[a] = v; + } + fclose(f); + } +} +void do_mem_init(void) +{ + int i; + + vpi_printf("pli_ram: allocate memory array\n"); + + M = (u16 *)malloc(1024*32); + mem_init = 1; + + for (i = 0; i < 32768; i++) + M[i] = 0; + + if (0) do_mem_preload("test1.mem"); +} + +static int getadd_inst_id(vpiHandle mhref) +{ + register int i; + char *chp; + + chp = vpi_get_str(vpiFullName, mhref); + //vpi_printf("getadd_inst_id() %s\n", chp); + + for (i = 1; i <= last_evh; i++) { + if (strcmp(instnam_tab[i], chp) == 0) + return(i); + } + + vpi_printf("pli_ram: adding instance %d, %s\n", last_evh+1, chp); + + instnam_tab[++last_evh] = malloc(strlen(chp) + 1); + strcpy(instnam_tab[last_evh], chp); + + return(last_evh); +} + +PLI_INT32 pli_ram(void) +{ + vpiHandle href, iter, mhref; + vpiHandle clkref, resetref, aref, diref, doref, ceref, weref; + s_vpi_value tmpval, outval; + int numargs, inst_id; + + char clk_bit, reset_bit; + char di_bits[17], do_bits[17]; + char ce_bit, we_bit; + unsigned int a, datai; + + int read_start, read_stop, write_start, write_stop, addr_change; + + if (M == 0/*!mem_init*/) { + do_mem_init(); + } + + href = vpi_handle(vpiSysTfCall, NULL); + if (href == NULL) { + vpi_printf("** ERR: $pli_ram PLI 2.0 can't get systf call handle\n"); + return(0); + } + +#if 0 + mhref = vpi_handle(vpiScope, href); + + if (vpi_get(vpiType, mhref) != vpiModule) { + vpiHandle old_mhref = mhref; + mhref = vpi_handle(vpiModule, mhref); +// vpi_free_object(old_mhref); + } + + inst_id = getadd_inst_id(mhref); +#else + inst_id = 1; +#endif + + //vpi_printf("pli_ram: inst_id %d\n", inst_id); + + iter = vpi_iterate(vpiArgument, href); + + numargs = vpi_get(vpiSize, iter); + + /* clk, reset, a, di, do, ce, we */ + clkref = vpi_scan(iter); + resetref = vpi_scan(iter); + aref = vpi_scan(iter); + diref = vpi_scan(iter); + doref = vpi_scan(iter); + ceref = vpi_scan(iter); + weref = vpi_scan(iter); + + vpi_free_object(iter); + vpi_free_object(href); + + if (clkref == NULL || resetref == NULL || aref == NULL || + diref == NULL || doref == NULL || ceref == NULL || + weref == NULL) + { + vpi_printf("**ERR: $pli_ram bad args\n"); + return(0); + } + + /* */ + tmpval.format = vpiBinStrVal; + vpi_get_value(clkref, &tmpval); + clk_bit = tmpval.value.str[0]; + + tmpval.format = vpiBinStrVal; + vpi_get_value(resetref, &tmpval); + reset_bit = tmpval.value.str[0]; + + tmpval.format = vpiIntVal; + vpi_get_value(aref, &tmpval); + a = tmpval.value.integer; + + tmpval.format = vpiBinStrVal; + vpi_get_value(diref, &tmpval); + strcpy(di_bits, tmpval.value.str); + + tmpval.format = vpiIntVal; + vpi_get_value(diref, &tmpval); + datai = tmpval.value.integer; + + tmpval.format = vpiBinStrVal; + vpi_get_value(doref, &tmpval); + strcpy(do_bits, tmpval.value.str); + + tmpval.format = vpiBinStrVal; + vpi_get_value(ceref, &tmpval); + ce_bit = tmpval.value.str[0]; + + tmpval.format = vpiBinStrVal; + vpi_get_value(weref, &tmpval); + we_bit = tmpval.value.str[0]; + + /* */ + read_start = 0; + read_stop = 0; + write_start = 0; + write_stop = 0; + addr_change = 0; + + if (a != last_addr) + addr_change = 1; + + if (we_bit != last_we_bit || addr_change) { + if (we_bit == '0') write_start = 1; + if (we_bit == '1') write_stop = 1; + } + + if (ce_bit != last_ce_bit || write_stop || addr_change) { + if (ce_bit == '0') read_start = 1; + if (ce_bit == '1') read_stop = 1; + } + + last_ce_bit = ce_bit; + last_we_bit = we_bit; + last_addr = a; + + if (0) vpi_printf("pli_ram: clk %c ce %c we %c\n", clk_bit, ce_bit, we_bit); + + if (reset_bit == '1') vpi_printf("pli_ram: reset\n"); + + if (0) { + if (read_start) vpi_printf("pli_ram: read start\n"); + if (read_stop) vpi_printf("pli_ram: read stop\n"); + if (write_start) vpi_printf("pli_ram: write start\n"); + if (write_stop) vpi_printf("pli_ram: write stop\n"); + } + + /* */ + if (write_start) { + //vpi_printf("pli_ram: write %o <- %o\n", a, datai); + + if (a > 1024*1024) { + vpi_printf("pli_ram: write, address error %x\n", a); + while (1); + } + + M[a] = datai; + } + + if (read_start) { + u16 value; + + if (a > 1024*32) { + vpi_printf("pli_ram: write, address error %x\n", a); + while (1); + } + + value = M[a]; + + //vpi_printf("pli_ram: read %o -> %o\n", a, value); + +#ifdef __CVER__ + if (do_aref == 0) + do_aref = vpi_put_value(doref, NULL, NULL, vpiAddDriver); +#else + do_aref = doref; +#endif + + outval.format = vpiIntVal; + outval.value.integer = value; + + vpi_put_value(do_aref, &outval, NULL, vpiNoDelay); + } + + if (read_stop) { + outval.format = vpiBinStrVal; +// outval.value.str = "16'bzzzzzzzzzzzzzzzz"; + outval.value.str = "16'b0000000000000000"; + if (do_aref) + vpi_put_value(do_aref, &outval, NULL, vpiNoDelay); + } + + vpi_free_object(clkref); + vpi_free_object(resetref); + vpi_free_object(aref); + vpi_free_object(diref); + vpi_free_object(doref); + vpi_free_object(ceref); + vpi_free_object(weref); + + return(0); +} + + + +/* + * Local Variables: + * indent-tabs-mode:nil + * c-basic-offset:4 + * End: +*/ diff --git a/pli/rf/pli_rf.c b/pli/rf/pli_rf.c new file mode 100644 index 0000000..a042a29 --- /dev/null +++ b/pli/rf/pli_rf.c @@ -0,0 +1,1080 @@ +/* pli_rf.c */ +/* + * minimal implementation of rf08 disk controller, + * designed to be shared by the rtl simulation and simh + * so they both operate the same way + * (to facilitate comparisons of cpu flow) + */ + +#include +#include +#include +#include + +#ifdef unix +#include +#endif + +#ifdef _WIN32 +#endif + +#include "vpi_user.h" + +#ifdef __CVER__ +#include "cv_vpi_user.h" +#endif + +#ifdef __MODELSIM__ +#include "veriuser.h" +#endif + +#define USE_DMA + +//typedef int int32; +typedef unsigned short u16; +typedef unsigned int u22; + +extern PLI_INT32 pli_ram(void); +PLI_INT32 pli_rk(void); + +static char *instnam_tab[10]; +static int last_evh; + +static char last_iopr_bit; +static char last_iopw_bit; +static char last_dma_ack_bit; + +static int io_rk_debug = 0; +static int rk_debug = 0; + +static struct rk_context_s { + u16 rkds; + u16 rkcs; + u16 rkda; + u16 rkwc; + u16 rkba; + u16 rker; + + int rk_write_prot; + int rk_func; + int rk_fd; + + int track; + int sect; + int cyl; + int rkintq; + + int has_init; + + int dma_cycle; + int dma_write; + int dma_read; + int dma_wc; + u22 dma_addr; + int dma_index; + + u16 rkxb[256*256]; + +} rk_context[10]; + +#ifndef CSR_GO +#define CSR_GO (1 << 0) +#define CSR_IE (1 << 6) +#define CSR_DONE (1 << 7) +#define CSR_BUSY (1 << 11) +#endif + +/* RKDS */ + +#define RKDS_SC 0000017 /* sector counter */ +#define RKDS_ON_SC 0000020 /* on sector */ +#define RKDS_WLK 0000040 /* write locked */ +#define RKDS_RWS 0000100 /* rd/wr/seek ready */ +#define RKDS_RDY 0000200 /* drive ready */ +#define RKDS_SC_OK 0000400 /* SC valid */ +#define RKDS_INC 0001000 /* seek incomplete */ +#define RKDS_UNSAFE 0002000 /* unsafe */ +#define RKDS_RK05 0004000 /* RK05 */ +#define RKDS_PWR 0010000 /* power low */ +#define RKDS_ID 0160000 /* drive ID */ + + +#define RKER_WCE 0000001 /* write check */ +#define RKER_CSE 0000002 /* checksum */ +#define RKER_NXS 0000040 /* nx sector */ +#define RKER_NXC 0000100 /* nx cylinder */ +#define RKER_NXD 0000200 /* nx drive */ +#define RKER_TE 0000400 /* timing error */ +#define RKER_DLT 0001000 /* data late */ +#define RKER_NXM 0002000 /* nx memory */ +#define RKER_PGE 0004000 /* programming error */ +#define RKER_SKE 0010000 /* seek error */ +#define RKER_WLK 0020000 /* write lock */ +#define RKER_OVR 0040000 /* overrun */ +#define RKER_DRE 0100000 /* drive error */ + +#define RKER_SOFT (RKER_WCE+RKER_CSE) /* soft errors */ +#define RKER_HARD 0177740 /* hard errors */ + +#define RKCS_CTLRESET 0 +#define RKCS_WRITE 1 +#define RKCS_READ 2 +#define RKCS_WCHK 3 +#define RKCS_SEEK 4 +#define RKCS_RCHK 5 +#define RKCS_DRVRESET 6 +#define RKCS_WLK 7 +#define RKCS_MEX 0000060 /* memory extension */ +#define RKCS_SSE 0000400 /* stop on soft err */ +#define RKCS_FMT 0002000 /* format */ +#define RKCS_INH 0004000 /* inhibit increment */ +#define RKCS_SCP 0020000 /* search complete */ +#define RKCS_HERR 0040000 /* hard error */ +#define RKCS_ERR 0100000 /* error */ +#define RKCS_RW 0006576 /* read/write */ + +static struct { + int ord; + char *name; + int preset; + vpiHandle ref; + vpiHandle aref; + char bits[32]; + unsigned int value; +} argl[] = { + { 1, "clk", 0 }, + { 2, "reset", 0 }, + { 3, "iopage_addr", 0 }, + { 4, "data_in", 0 }, + { 5, "data_out", 1 }, + { 6, "decode", 1 }, + { 7, "iopage_rd", 0 }, + { 8, "iopage_wr", 0 }, + { 9, "iopage_byte_op", 0 }, + { 10, "interrupt", 1 }, + { 11, "int_ack", 0 }, + { 12, "vector", 1 }, + { 13, "ide_data_bus", 1 }, + { 14, "ide_dior", 1 }, + { 15, "ide_diow", 1 }, + { 16, "ide_cs", 1 }, + { 17, "ide_da", 1 }, + { 18, "dma_req", 1 }, + { 19, "dma_ack", 0 }, + { 20, "dma_addr", 1 }, + { 21, "dma_data_in", 1 }, + { 22, "dma_data_out", 0 }, + { 23, "dma_rd", 1 }, + { 24, "dma_wr", 1 }, + { 0, NULL, 0 } +}; +#define A_RESET (2-1) +#define A_IOPAGE_ADDR (3-1) +#define A_DATA_IN (4-1) +#define A_DATA_OUT (5-1) +#define A_DECODE (6-1) +#define A_IOPAGE_RD (7-1) +#define A_IOPAGE_WR (8-1) +#define A_IOPAGE_BYTE_OP (9-1) +#define A_INTERRUPT (10-1) +#define A_INT_ACK (11-1) +#define A_VECTOR (12-1) +#define A_DMA_REQ (18-1) +#define A_DMA_ACK (19-1) +#define A_DMA_ADDR (20-1) +#define A_DMA_DATA_IN (21-1) +#define A_DMA_DATA_OUT (22-1) +#define A_DMA_RD (23-1) +#define A_DMA_WR (24-1) + +/* ----------------- */ + +void rk_raw_write_memory(struct rk_context_s *rk, int ma, u16 data) +{ + extern u16 *M; + vpi_printf("dma %06o <- %06o\n", ma, data); + + if (ma > 1024*1024) { + vpi_printf("pli_rk: dma write, address error %x\n", ma); + while (1); + } + + M[ma >> 1] = data; +} + +u16 rk_raw_read_memory(struct rk_context_s *rk, int ma) +{ + extern u16 *M; + + if (ma > 1024*1024) { + vpi_printf("pli_rk: dma read, address error %x\n", ma); + while (1); + } + + return M[ma >> 1]; +} + +/* ----------------- */ + +static void set_output_str(int ord, char *str) +{ + s_vpi_value outval; + +#ifdef __CVER__ + if (argl[ord].aref == 0) + argl[ord].aref = vpi_put_value(argl[ord].ref, NULL, NULL, vpiAddDriver); +#else + argl[ord].aref = argl[ord].ref; +#endif + + outval.format = vpiBinStrVal; + outval.value.str = str; + + if (0) vpi_printf("rk: set output %s %s\n", argl[ord].name, str); + + vpi_put_value(argl[ord].aref, &outval, NULL, vpiNoDelay); +} + +static void set_output_int(int ord, int val) +{ + s_vpi_value outval; + +#ifdef __CVER__ + if (argl[ord].aref == 0) + argl[ord].aref = vpi_put_value(argl[ord].ref, NULL, NULL, vpiAddDriver); +#else + argl[ord].aref = argl[ord].ref; +#endif + + outval.format = vpiIntVal; + outval.value.integer = val; + + if (0) vpi_printf("rk: set output %s %d\n", argl[ord].name, val); + + vpi_put_value(argl[ord].aref, &outval, NULL, vpiNoDelay); +} + +#ifdef USE_DMA +static void dma_start_write(struct rk_context_s *rk, + unsigned int ma, unsigned int wc) +{ + vpi_printf("rk: dma start write ma=%o, wc=%o\n", ma, wc); + rk->dma_cycle++; + rk->dma_addr = ma; + rk->dma_write = 1; + rk->dma_wc = wc; + rk->dma_index = 0; + + set_output_int(A_DMA_DATA_OUT, rk->rkxb[rk->dma_index]); + set_output_int(A_DMA_ADDR, rk->dma_addr); + set_output_str(A_DMA_WR, "1"); + set_output_str(A_DMA_REQ, "1"); +} + +static void dma_start_read(struct rk_context_s *rk, + unsigned int ma, unsigned int wc) +{ + vpi_printf("rk: dma start read ma=%o, wc=%o\n", ma, wc); + rk->dma_cycle++; + rk->dma_addr = ma; + rk->dma_read = 1; + rk->dma_wc = wc; + + set_output_int(A_DMA_ADDR, rk->dma_addr); + set_output_str(A_DMA_RD, "1"); + set_output_str(A_DMA_REQ, "1"); +} + +static void dma_next(struct rk_context_s *rk) +{ + if (rk_debug > 1) + vpi_printf("rk: dma next dma_addr=%o, dma_wc=%o\n", + rk->dma_addr, rk->dma_wc); + + if (!(rk->rkcs & RKCS_INH)) + rk->dma_addr += 2; + + if (rk->dma_read) { + if (rk->rk_func == RKCS_WCHK) { + if (rk->rkxb[rk->dma_index] != argl[A_DMA_DATA_IN].value) { + rk->rker |= 1; + } + } else { + rk->rkxb[rk->dma_index] = argl[A_DMA_DATA_IN].value; + } + } + + rk->dma_wc--; + rk->dma_index++; + + if (rk->dma_write) { + set_output_int(A_DMA_DATA_OUT, rk->rkxb[rk->dma_index]); + } + + set_output_int(A_DMA_ADDR, rk->dma_addr); + + if (rk->dma_read) { + set_output_str(A_DMA_RD, "1"); + } + if (rk->dma_write) { + set_output_str(A_DMA_WR, "1"); + } + + set_output_str(A_DMA_REQ, "1"); +} + +static void rk_set_done(struct rk_context_s *rk, int error); + +static void dma_done(struct rk_context_s *rk) +{ + int wc, track, sector, da; + + vpi_printf("rk: XXX dma done\n"); + + wc = 0200000 - rk->rkwc; + + track = (rk->rkda >> 4) & 0777; + sector = rk->rkda & 017; + da = ((track * 12) + sector) * 256; + + rk->rkwc = 0; + rk->rkba = rk->dma_addr & 0xffff; + rk->rkcs = (rk->rkcs & ~RKCS_MEX) | ((rk->dma_addr >> (16 - 4)) & RKCS_MEX); + + if ((rk->rk_func == RKCS_READ) && (rk->rkcs & RKCS_FMT)) + da = da + (wc * 256); + else + da = da + wc + (256 - 1); + + rk->track = (da / 256) / 12; + rk->sect = (da / 256) % 12; + + rk->rkda = (rk->track << 4) | rk->sect; + + rk_set_done(rk, 0); + + rk->dma_cycle = 0; + rk->dma_read = 0; + rk->dma_write = 0; + set_output_str(A_DMA_REQ, "0"); +} +#endif + +void +io_rk_reset(struct rk_context_s *rk) +{ + rk->rkcs = CSR_DONE; + + if (rk->rk_fd) { + close(rk->rk_fd); + rk->rk_fd = 0; + } + + vpi_printf("io_rk_reset() opening file\n"); + + rk->rk_fd = open("rk.dsk", O_RDONLY); + rk->has_init = 1; +} + +void io_rk_cpu_int_set(struct rk_context_s *rk) +{ + vpi_printf("io_rk_cpu_int_set() intset seek\n"); + + set_output_str(A_INTERRUPT, "1"); + set_output_int(A_VECTOR, 0220); +} + +void io_rk_cpu_int_clear(struct rk_context_s *rk) +{ + vpi_printf("io_rk_cpu_int_clear() intset seek\n"); + + set_output_str(A_INTERRUPT, "0"); + set_output_int(A_VECTOR, 0); +} + +u16 _io_rk_read(struct rk_context_s *rk, u22 addr) +{ + if (io_rk_debug) + vpi_printf("io_rk_read %o decode %o\n", addr, ((addr >> 1) & 07)); + + switch ((addr >> 1) & 07) { /* decode PA<3:1> */ + + case 0: /* RKDS: read only */ + rk->rkds = (rk->rkds & RKDS_ID) | RKDS_RK05 | RKDS_SC_OK; + return rk->rkds; + + case 1: /* RKER: read only */ + return rk->rker; + + case 2: /* RKCS */ + if (rk->rker) rk->rkcs |= RKCS_ERR; + if (rk->rker & RKER_HARD) rk->rkcs |= RKCS_HERR; + return rk->rkcs; + + case 3: /* RKWC */ + return rk->rkwc; + + case 4: /* RKBA */ + return rk->rkba; + + case 5: /* RKDA */ + return rk->rkda; + + default: + return 0; + } +} + +static void rk_set_done(struct rk_context_s *rk, int error) +{ + if (1) vpi_printf("rk: done; error %o seek\n", error); + + rk->rkcs |= CSR_DONE; + if (error != 0) { + rk->rker |= error; + if (rk->rker) + rk->rkcs |= RKCS_ERR; + if (rk->rker & RKER_HARD) + rk->rkcs |= RKCS_HERR; + } + + if (rk->rkcs & CSR_IE) { + rk->rkintq |= 1; + io_rk_cpu_int_set(rk); + } else { + rk->rkintq = 0; + io_rk_cpu_int_clear(rk); + } +} + +static void rk_clr_done(struct rk_context_s *rk) +{ + if (rk_debug > 1) vpi_printf("rk: not done\n"); + + rk->rkcs &= ~CSR_DONE; + rk->rkintq &= ~1; + io_rk_cpu_int_clear(rk); +} + +void rk_service(struct rk_context_s *rk) +{ + int i, err, wc, cda; + int da, cyl, track, sector; + unsigned int ma; + +#ifndef USE_DMA + int awc, cma, ret; + unsigned short comp; +#endif + + vpi_printf("rk_service; func %o\n", rk->rk_func); + + if (rk->rk_func == RKCS_SEEK) { + rk->rkcs |= RKCS_SCP; + if (rk->rkcs & CSR_IE) { + rk->rkintq |= 2; + if (rk->rkcs & CSR_DONE) + io_rk_cpu_int_set(rk); + } else { + rk->rkintq = 0; + io_rk_cpu_int_clear(rk); + } + + return; + } + + cyl = (rk->rkda >> 5) & 0377; + track = (rk->rkda >> 4) & 0777; + sector = rk->rkda & 017; + + ma = ((rk->rkcs & RKCS_MEX) << (16 - 4)) | rk->rkba; + + if (sector >= 12) { + rk_set_done(rk, RKER_NXS); + return; + } + + if (cyl >= 203) { + rk_set_done(rk, RKER_NXC); + return; + } + + da = ((track * 12) + sector) * 256; + wc = 0200000 - rk->rkwc; + + vpi_printf("rk: seek %d (read %d)\n", da * sizeof(short), wc*2); + + err = lseek(rk->rk_fd, da * sizeof(short), SEEK_SET); + if (wc && (err >= 0)) { + err = 0; + + switch (rk->rk_func) { + + case RKCS_READ: + if (rk->rkcs & RKCS_FMT) { + for (i = 0, cda = da; i < wc; i++) { + rk->rkxb[i] = (cda / 256) / (2 * 12); + cda = cda + 256; + } + } else { + vpi_printf("rk: read() wc %d\n", wc); + i = read(rk->rk_fd, rk->rkxb, sizeof(short)*wc); + + vpi_printf("rk: read() ret %d\n", i); + if (i >= 0 && i < sizeof(short)*wc) { + i /= 2; + for (; i < wc; i++) + rk->rkxb[i] = 0; + } + } + +#ifdef USE_DMA + vpi_printf("rk: read(), dma ma=%o, wc=%d\n", ma, wc); + vpi_printf("rk: buffer %06o %06o %06o %06o\n", + rk->rkxb[0], rk->rkxb[1], rk->rkxb[2], rk->rkxb[3]); + dma_start_write(rk, ma, wc); + return; +#else + if (rk->rkcs & RKCS_INH) { + rk_raw_write_memory(rk, ma, rk->rkxb[wc - 1]); + } else { + //int oldma = ma; + vpi_printf("rk: read(), dma wc=%d, ma=%o\n", wc, ma); + vpi_printf("rk: buffer %06o %06o %06o %06o\n", + rk->rkxb[0], rk->rkxb[1], rk->rkxb[2], rk->rkxb[3]); + for (i = 0; i < wc; i++) { + rk_raw_write_memory(rk, ma, rk->rkxb[i]); + ma += 2; + } + //show(oldma); + } +#endif + break; + + case RKCS_WRITE: +#ifdef USE_DMA + if (rk->rkcs & RKCS_INH) { + dma_start_read(rk, ma, 1); + } else { + dma_start_read(rk, ma, wc); + } + return; +#else + if (rk->rkcs & RKCS_INH) { + comp = rk_raw_read_memory(rk, ma); + for (i = 0; i < wc; i++) + rk->rkxb[i] = comp; + } else { + for (i = 0; i < wc; i++) { + rk->rkxb[i] = rk_raw_read_memory(rk, ma); + ma += 2; + } + } + + awc = (wc + (256 - 1)) & ~(256 - 1); + vpi_printf("rk: write(), wc=%d\n", awc*2); + ret = write(rk->rk_fd, rk->rkxb, awc*2); +#endif + break; + + case RKCS_WCHK: + i = read(rk->rk_fd, rk->rkxb, sizeof(short)*wc); + if (i < 0) { + wc = 0; + break; + } + + if (i >= 0 && i < sizeof(short)*wc) { + i /= 2; + for (; i < wc; i++) + rk->rkxb[i] = 0; + } + +#ifdef USE_DMA + dma_start_read(rk, 0, wc); + return; +#else + awc = wc; + for (wc = 0, cma = ma; wc < awc; wc++) { + comp = rk_raw_read_memory(rk, cma); + if (comp != rk->rkxb[wc]) { + rk->rker |= rk->rker; + if (rk->rkcs & RKCS_SSE) + break; + } + if (!(rk->rkcs & RKCS_INH)) + cma += 2; + } +#endif + break; + + default: + break; + } + } + + rk->rkwc = (rk->rkwc + wc) & 0177777; + if (!(rk->rkcs & RKCS_INH)) + ma = ma + (wc << 1); + + rk->rkba = ma & 0xffff; + rk->rkcs = (rk->rkcs & ~RKCS_MEX) | ((ma >> (16 - 4)) & RKCS_MEX); + + if ((rk->rk_func == RKCS_READ) && (rk->rkcs & RKCS_FMT)) + da = da + (wc * 256); + else + da = da + wc + (256 - 1); + + rk->track = (da / 256) / 12; + rk->sect = (da / 256) % 12; + + rk->rkda = (rk->track << 4) | rk->sect; + rk_set_done(rk, 0); + + if (err != 0) { + vpi_printf("RK I/O error\n"); + } +} + +static void rk_go(struct rk_context_s *rk) +{ + if (rk_debug > 1) vpi_printf("rk_go!\n"); + + rk->rk_func = (rk->rkcs >> 1) & 7; + if (rk->rk_func == RKCS_CTLRESET) { + rk->rker = 0; + rk->rkda = 0; + rk->rkba = 0; + rk->rkcs = CSR_DONE; + rk->rkintq = 0; + io_rk_cpu_int_clear(rk); + return; + } + + rk->rker &= ~RKER_SOFT; + if (rk->rker == 0) + rk->rkcs &= ~RKCS_ERR; + + rk->rkcs &= ~RKCS_SCP; + rk_clr_done(rk); + + if ((rk->rkcs & RKCS_FMT) && + (rk->rk_func != RKCS_READ) && (rk->rk_func != RKCS_WRITE)) { + rk_set_done(rk, RKER_PGE); + return; + } + + if ((rk->rk_func == RKCS_WRITE) && rk->rk_write_prot) { + rk_set_done(rk, RKER_WLK); + return; + } + + if (rk->rk_func == RKCS_WLK) { + rk_set_done(rk, 0); + return; + } + + if (rk->rk_func == RKCS_DRVRESET) { + rk->cyl = 0; + rk->sect = 0; + rk->rk_func = RKCS_SEEK; + } else { + rk->sect = rk->rkda & 017; + rk->cyl = (rk->rkda >> 5) & 0377; + } + + if (rk->sect >= 12) { + rk_set_done(rk, RKER_NXS); + return; + } + + if (rk->cyl >= 203) { + rk_set_done(rk, RKER_NXC); + return; + } + + if (rk->rk_func == RKCS_SEEK) { + rk_set_done(rk, 0); + } + + rk_service(rk); +} + +void _io_rk_write(struct rk_context_s *rk, u22 addr, u16 data, int writeb) +{ + if (0) vpi_printf("_io_rk_write %o %d decode %o\n", + addr, writeb, ((addr >> 1) & 07)); + + switch ((addr >> 1) & 07) { /* decode PA<3:1> */ + + case 2: /* RKCS */ + vpi_printf("rk: rkcs <- %o\n", data); + if (writeb) { + data = (addr & 1)? (rk->rkcs & 0377) | + (data << 8): (rk->rkcs & ~0377) | data; + } + if ((data & CSR_IE) == 0) { /* int disable? */ + rk->rkintq = 0; /* clr int queue */ + io_rk_cpu_int_clear(rk); + } else + if ((rk->rkcs & (CSR_DONE | CSR_IE)) == CSR_DONE) { + rk->rkintq |= 1; + io_rk_cpu_int_set(rk); + } + + rk->rkcs = (rk->rkcs & ~RKCS_RW) | (data & RKCS_RW); + vpi_printf("rk: rkcs %o\n", rk->rkcs); + + if ((rk->rkcs & CSR_DONE) && (data & CSR_GO)) + rk_go(rk); + return; + + case 3: /* RKWC */ + if (writeb) { + data = (addr & 1) ? + (rk->rkwc & 0377) | (data << 8) : + (rk->rkwc & ~0377) | data; + } + rk->rkwc = data; + vpi_printf("rk: rkwc <- %o\n", rk->rkwc); + return; + + case 4: /* RKBA */ + if (writeb) { + data = (addr & 1)? + (rk->rkba & 0377) | (data << 8) : + (rk->rkba & ~0377) | data; + } + rk->rkba = data; + vpi_printf("rk: rkba <- %o\n", rk->rkba); + return; + + case 5: /* RKDA */ + if ((rk->rkcs & CSR_DONE) == 0) + return; + if (writeb) { + data = (addr & 1) ? + (rk->rkda & 0377) | (data << 8) : + (rk->rkda & ~0377) | data; + } + rk->rkda = data; + vpi_printf("rk: XXX rkda <- %o\n", rk->rkda); + return; + + default: + vpi_printf("rk: ??\n"); + return; + } +} + +/* ------------------------------------------------------ */ + +static int getadd_inst_id(vpiHandle mhref) +{ + register int i; + char *chp; + + chp = vpi_get_str(vpiFullName, mhref); + + for (i = 1; i <= last_evh; i++) { + if (strcmp(instnam_tab[i], chp) == 0) + return(i); + } + + vpi_printf("pli_rk: adding instance %d, %s\n", last_evh+1, chp); + + instnam_tab[++last_evh] = malloc(strlen(chp) + 1); + strcpy(instnam_tab[last_evh], chp); + + return(last_evh); +} + +/* + * + */ +PLI_INT32 pli_rk(void) +{ + vpiHandle href, iter, mhref; + int numargs, inst_id; + s_vpi_value tmpval; + int i, badarg; + char iopr_bit, iopw_bit, dma_ack_bit; + struct rk_context_s *rk; + unsigned int addr, decode; + + int read_start, read_stop, write_start, write_stop; + int dma_ack_start, dma_ack_stop; + + //vpi_printf("pli_rk:\n"); + + href = vpi_handle(vpiSysTfCall, NULL); + if (href == NULL) { + vpi_printf("** ERR: $pli_rk PLI 2.0 can't get systf call handle\n"); + return(0); + } + +#if 0 + mhref = vpi_handle(vpiScope, href); + + if (vpi_get(vpiType, mhref) != vpiModule) { + vpiHandle old_mhref = mhref; + mhref = vpi_handle(vpiModule, mhref); +// vpi_free_object(old_mhref); + } + + inst_id = getadd_inst_id(mhref); +#else + inst_id = 1; +#endif + rk = &rk_context[inst_id]; + + //vpi_printf("pli_rk: inst_id %d\n", inst_id); + + iter = vpi_iterate(vpiArgument, href); + + numargs = vpi_get(vpiSize, iter); + + badarg = 0; + for (i = 0; argl[i].ord; i++) { + argl[i].ref = vpi_scan(iter); + if (argl[i].ref == NULL) + badarg++; + else { + tmpval.format = vpiBinStrVal; + vpi_get_value(argl[i].ref, &tmpval); + strcpy(argl[i].bits, tmpval.value.str); + + tmpval.format = vpiIntVal; + vpi_get_value(argl[i].ref, &tmpval); + argl[i].value = tmpval.value.integer; + } + } + + vpi_free_object(iter); + vpi_free_object(href); + + if (badarg) + { + vpi_printf("**ERR: $pli_rk bad args\n"); + return(0); + } + + if (!rk->has_init) { + io_rk_reset(rk); + + for (i = 0; argl[i].ord; i++) { + if (argl[i].preset) { + if (0) vpi_printf("pli_rk: preset %s\n", argl[i].name); + set_output_str(i, "0"); + } + } + } + + /* */ + read_start = 0; + read_stop = 0; + write_start = 0; + write_stop = 0; + dma_ack_start = 0; + dma_ack_stop = 0; + + iopr_bit = argl[A_IOPAGE_RD].bits[0]; + iopw_bit = argl[A_IOPAGE_WR].bits[0]; + dma_ack_bit = argl[A_DMA_ACK].bits[0]; + + if (iopr_bit != last_iopr_bit) { + if (iopr_bit == '1') read_start = 1; + if (iopr_bit == '0') read_stop = 1; + } + + if (iopw_bit != last_iopw_bit) { + if (iopw_bit == '1') write_start = 1; + if (iopw_bit == '0') write_stop = 1; + } + + if (dma_ack_bit != last_dma_ack_bit) { + if (dma_ack_bit == '1') dma_ack_start = 1; + if (dma_ack_bit == '0') dma_ack_stop = 1; + } + + last_iopr_bit = iopr_bit; + last_iopw_bit = iopw_bit; + last_dma_ack_bit = dma_ack_bit; + + addr = argl[A_IOPAGE_ADDR].value; + decode = 017400 <= addr && addr <= 017412; + if (0) vpi_printf("pli_rk: decode %o %d\n", addr, decode); + + if (0) { + if (read_start) vpi_printf("pli_rk: read start\n"); + if (read_stop) vpi_printf("pli_rk: read stop\n"); + if (write_start) vpi_printf("pli_rk: write start\n"); + if (write_stop) vpi_printf("pli_rk: write stop\n"); + if (dma_ack_start) vpi_printf("pli_rk: dma_ack start\n"); + if (dma_ack_stop) vpi_printf("pli_rk: dma_ack stop\n"); + } + + /* */ + if (argl[A_RESET].value == 1) { + vpi_printf("pli_rk: reset\n"); + io_rk_reset(rk); + } + + if (argl[A_INT_ACK].value == 1) { + vpi_printf("pli_rk: intack\n"); + io_rk_cpu_int_clear(rk); + } + +#ifdef USE_DMA + if (!dma_ack_start && !dma_ack_stop) { + if (0) vpi_printf("pli_rk: dma waiting\n"); + } + + if (dma_ack_stop) { + if (rk_debug > 1) + vpi_printf("pli_rk: dma ack stop (func=%o)\n", rk->rk_func); + + if (rk->dma_read) { + + switch (rk->rk_func) { + case RKCS_WRITE: + dma_next(rk); + + if (rk->dma_wc == 0) { + int wc, awc, ret; + wc = 0200000 - rk->rkwc; + awc = (wc + (256 - 1)) & ~(256 - 1); + vpi_printf("rk: XXX wc=0, write() %d\n", awc*2); + ret = write(rk->rk_fd, rk->rkxb, awc*2); + } + break; + + case RKCS_WCHK: + dma_next(rk); + break; + } + } + + if (rk->dma_write) { + dma_next(rk); + } + + if (rk->dma_wc == 0) { + dma_done(rk); + } + } +#endif + + set_output_str(A_DECODE, decode ? "1" : "0"); + + if (write_start && decode) { + unsigned data, writeb; + + data = argl[A_DATA_IN].value; + writeb = argl[A_IOPAGE_BYTE_OP].value; + + vpi_printf("pli_rk: write %o <- %o (b%d)\n", addr, data, writeb); + + _io_rk_write(rk, addr, data, writeb); + } + + if (read_start && decode) { + unsigned value; + + addr = argl[A_IOPAGE_ADDR].value; + + if (rk_debug > 1) vpi_printf("pli_rk: read %o\n", addr); + + value = _io_rk_read(rk, addr); + + set_output_int(A_DATA_OUT, value); + } + + if (read_stop && decode) { +// set_output_str(A_DATA_OUT, "16'bzzzzzzzzzzzzzzzz"); + set_output_str(A_DATA_OUT, "16'b0000000000000000"); + } + + /* free argument handles */ + for (i = 0; argl[i].ord; i++) { + if (argl[i].ref != NULL) + vpi_free_object(argl[i].ref); + argl[i].ref = NULL; + argl[i].aref = NULL; + } + + return(0); +} + +/* + * register all vpi_ PLI 2.0 style user system tasks and functions + */ +static void register_my_systfs(void) +{ + p_vpi_systf_data systf_data_p; + + /* use predefined table form - could fill systf_data_list dynamically */ + static s_vpi_systf_data systf_data_list[] = { + { vpiSysTask, 0, "$pli_rk", pli_rk, NULL, NULL, NULL }, + { vpiSysTask, 0, "$pli_ram", pli_ram, NULL, NULL, NULL }, + { 0, 0, NULL, NULL, NULL, NULL, NULL } + }; + + systf_data_p = &(systf_data_list[0]); + while (systf_data_p->type != 0) { + vpi_register_systf(systf_data_p++); + } +} + +#ifdef unix +/* all routines are called to register system tasks */ +/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */ +/* before source is read */ +static void (*rk_vlog_startup_routines[]) () = +{ + register_my_systfs, + 0 +}; + +/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */ +/* in standard PLI vlog_startup_routines table */ +void rk_vpi_compat_bootstrap(void) +{ + int i; + + io_rk_debug = 0; + rk_debug = 1; + + for (i = 0;; i++) { + if (rk_vlog_startup_routines[i] == NULL) + break; + rk_vlog_startup_routines[i](); + } +} + +void vpi_compat_bootstrap(void) +{ + rk_vpi_compat_bootstrap(); +} + +#ifndef BUILD_ALL +void __stack_chk_fail_local() {} +#endif + +#endif + +#ifdef __MODELSIM__ +static void (*vlog_startup_routines[]) () = +{ + register_my_systfs, + 0 +}; +#endif + + +/* + * Local Variables: + * indent-tabs-mode:nil + * c-basic-offset:4 + * End: +*/ diff --git a/pli/rf/win32.bat b/pli/rf/win32.bat new file mode 100644 index 0000000..4852d1d --- /dev/null +++ b/pli/rf/win32.bat @@ -0,0 +1,7 @@ +rem c:\program files\microsoft visual studio\vcvars32.bat + +set MTI_HOME=c:\Modeltech_6.2g + +cl -c -I%MTI_HOME%\include -D__MODELSIM__ pli_rf.c +cl -c -I%MTI_HOME%\include -D__MODELSIM__ pli_ram.c +link -dll -export:vlog_startup_routines pli_rf.obj pli_ram.obj %MTI_HOME%\win32\mtipli.lib