1
0
mirror of https://github.com/aap/pdp6.git synced 2026-02-26 17:03:52 +00:00

emu: tweaked and fixed the DC, wrote some simple tests

This commit is contained in:
aap
2019-02-08 00:37:40 +01:00
parent 3f8f51ffbb
commit c2ff6849e9
5 changed files with 324 additions and 76 deletions

View File

@@ -3,12 +3,14 @@ H=pdp6.h ../tools/pdp6common.h
# clang
#CFLAGS= -Wno-shift-op-parentheses -Wno-logical-op-parentheses \
# -Wno-bitwise-op-parentheses
CFLAGS= -g -Wall -Wno-parentheses -fno-diagnostics-show-caret \
`sdl-config --cflags` `pkg-config SDL_image --cflags`
CFLAGS= -g -Wall -Wno-parentheses -fno-diagnostics-show-caret
SDLFLAGS=`sdl-config --cflags` `pkg-config SDL_image --cflags`
LIBS= `sdl-config --libs` `pkg-config SDL_image --libs` -lpthread
LIBS=`sdl-config --libs` `pkg-config SDL_image --libs` -lpthread
pdp6: $(SRC) $(H)
$(CC) $(CFLAGS) $(SRC) $(LIBS) -o pdp6
$(CC) -o $@ $(CFLAGS) $(SDLFLAGS) $(SRC) $(LIBS)
test_dc: test_dc.c dc.c $(H)
$(CC) -o $@ $(CFLAGS) test_dc.c dc.c

154
emu/dc.c
View File

@@ -9,13 +9,17 @@ char *dc_ident = DC_IDENT;
* 18 1 1 3 2
* 36 0 1 0 1
*/
#define NSHIFT ((0x70 >> (dc->ch_mode*2)) & 03)
#define NSHIFT ((0xE0 >> (dc->ch_mode*2)) & 03)
#define NCHARS ((02316 >> (dc->ch_mode*3)) & 07)
#define DC_SCT_DONE (dc->sct == NSHIFT)
#define DC_CCT_DONE (dc->cct == NCHARS-1)
//#define DC_CCT_CONT (DC_SCT_DONE && !(DC_CCT_DONE))
//#define DC_SCT_CONT (!(DC_SCT_DONE) && !(DC_CCT_DONE))
#define DB_JM_DA (dc->db = dc->da), dc->da = 0
#define DA_JM_DB (dc->da = dc->db)
#define DB_CLR dc->db = dc->db_rq = 0
static void
recalc_dc_req(Dc136 *dc)
{
@@ -23,18 +27,38 @@ recalc_dc_req(Dc136 *dc)
}
static void
dbdamove(Dc136 *dc)
db_da_swap(Dc136 *dc)
{
dc->da_rq = 0;
dc->dbda_move = 0;
dc->db_rq = 1;
if(dc->inout)
dc->da = dc->db; // out
else{
dc->db = dc->da; // in
dc->da = 0;
}
DA_JM_DB; // out
else
DB_JM_DA; // in
}
/* TODO: maybe make these two a bit nicer?? */
static void
set_da_rq(Dc136 *dc)
{
int prev;
prev = dc->da_rq && dc->dbda_move;
dc->da_rq = 1;
if(!prev && dc->da_rq && dc->dbda_move)
db_da_swap(dc);
}
static void
set_dbda_move(Dc136 *dc)
{
int prev;
prev = dc->da_rq && dc->dbda_move;
dc->dbda_move = 1;
if(!prev && dc->da_rq && dc->dbda_move)
db_da_swap(dc);
}
static void
@@ -45,39 +69,37 @@ cp0:
if(dc->da_rq)
dc->data_clbd = 1;
// 1ms delay
// DASH CP1
if(DC_CCT_DONE){
//printf("Full DA: %012lo\n", dc->da);
dc->cct = 0;
if(dc->da_rq == 0){
dc->da_rq = 1;
if(dc->dbda_move)
dbdamove(dc);
}else
dc->da_rq = 1;
set_da_rq(dc);
}else if(DC_SCT_DONE){
// CCT CONT
dc->sct = 0;
dc->cct = (dc->cct+1) & 7;
}else{
if(DC_SCT_DONE){
// CCT CONT
dc->cct++;
// this shouldn't be under the !CCT_DONE branch
// but the flow diagram FD1 does it too
dc->sct = 0;
}else{
// SCT CONT
dc->sct++;
// SCT CONT
dc->sct = (dc->sct+1) & 3;
// DASH LT
dc->da <<= 6;
goto cp0;
}
// DASH LT
dc->da = (dc->da << 6) & FW;
goto cp0;
}
}
/* Give TO DC, this is the TK signal in the DC.
* NB: for dev 5/6 give only the lower N bits. */
void
dcgv(Dc136 *dc, int n, word c, int rev)
{
//printf("DC Taking %06lo from dev %d\n", c, n);
switch(n){
if(n != dc->device)
return;
switch(dc->device){
case 1: case 2:
if(rev)
dc->da = (dc->da >> 6 | (c&077)<<30) & FW;
@@ -97,11 +119,16 @@ dcgv(Dc136 *dc, int n, word c, int rev)
recalc_dc_req(dc);
}
/* Take FROM DC, this is the GV signal in the DC.
* NB: for dev 5/6 read only the upper N bits. */
word
dctk(Dc136 *dc, int n, int rev)
{
word c;
switch(n){
if(n != dc->device)
return 0;
switch(dc->device){
case 1: case 2:
if(rev){
c = dc->da & 077;
@@ -127,36 +154,38 @@ dctk(Dc136 *dc, int n, int rev)
return c;
}
static void
ic_clr(Dc136 *dc)
{
DB_JM_DA;
dc->cct = 0;
dc->sct = 0;
dc->data_clbd = 0;
dc->dbda_move = 0;
dc->da_rq = 0;
dc->db_rq = 0;
dc->inout = 0;
dc->ch_mode = 0;
dc->device = 0;
dc->pia = 0;
}
static void
wake_dc(void *dev)
{
Dc136 *dc;
IOBus *bus;
int dbda_move_old, da_rq_old;
dc = dev;
bus = dc->bus;
if(IOB_RESET){
dc->db = 0;
dc->da = 0;
dc->cct = 0;
dc->sct = 0;
dc->data_clbd = 0;
dc->dbda_move = 0;
dc->da_rq = 0;
dc->db_rq = 0;
dc->inout = 0;
dc->ch_mode = 0;
dc->device = 0;
dc->pia = 0;
ic_clr(dc);
DB_CLR;
}
if(bus->devcode == DC){
dbda_move_old = dc->dbda_move;
da_rq_old = dc->da_rq;
if(IOB_STATUS){
bus->c12 |= (dc->cct&7) << 13;
if(dc->data_clbd) bus->c12 |= F23;
@@ -171,46 +200,27 @@ wake_dc(void *dev)
if(IOB_DATAI){
bus->c12 |= dc->db;
dc->db_rq = 0;
dc->dbda_move = 1;
}
if(IOB_CONO_CLEAR){
dc->db = dc->da;
dc->da = 0;
dc->cct = 0;
dc->sct = 0;
dc->data_clbd = 0;
dc->dbda_move = 0;
dc->da_rq = 0;
dc->db_rq = 0;
dc->inout = 0;
dc->ch_mode = 0;
dc->device = 0;
dc->pia = 0;
set_dbda_move(dc);
}
if(IOB_CONO_CLEAR)
ic_clr(dc);
if(IOB_CONO_SET){
if(bus->c12 & F23) dc->data_clbd = 1;
if(bus->c12 & F24) dc->dbda_move = 1;
if(bus->c12 & F25) dc->da_rq = 1;
if(bus->c12 & F24) set_dbda_move(dc);
if(bus->c12 & F25) set_da_rq(dc);
if(bus->c12 & F26) dc->db_rq = 1;
if(bus->c12 & F27) dc->inout = 1;
dc->ch_mode |= bus->c12>>6 & 03;
dc->device |= bus->c12>>3 & 07;
dc->pia |= bus->c12 & 07;
}
if(IOB_DATAO_CLEAR){
dc->db = 0;
dc->db_rq = 0;
}
if(IOB_DATAO_CLEAR)
DB_CLR;
if(IOB_DATAO_SET){
dc->db |= bus->c12;
dc->dbda_move = 1;
set_dbda_move(dc);
}
if(dc->dbda_move && dc->da_rq &&
!(dbda_move_old && da_rq_old))
dbdamove(dc);
recalc_dc_req(dc);
}
}

View File

@@ -12,6 +12,7 @@ mkdev cmem1 cmem161C mem_1
mkdev cmem2 cmem161C mem_2
mkdev cmem3 cmem161C mem_3
#mkdev netmem netmem its.pdp10.se 10006
mkdev netmem netmem localhost 10006
connectdev dc dt0
connectdev dt0 dx0 8

View File

@@ -120,6 +120,7 @@ makenetmem(int argc, char *argv[])
nm->fd = dial(host, port);
if(nm->fd < 0)
printf("couldn't connect\n");
printf("netmem fd: %d\n", nm->fd);
th = (Thread){ nil, netmemcycle, nm, 50, 0 };
addthread(th);

234
emu/test_dc.c Normal file
View File

@@ -0,0 +1,234 @@
#include "pdp6.h"
Dc136 *dc;
IOBus iobus;
IOBus *bus = &iobus;
int pireq;
void
setreq(IOBus *bus, int dev, u8 pia)
{
pireq = pia;
}
void
wakedev(IOBus *bus, int d)
{
Busdev *dev;
bus->devcode = d;
dev = &bus->dev[d];
if(dev->wake)
dev->wake(dev->dev);
}
void
bus_reset(IOBus *bus)
{
int d;
bus->c34 |= IOBUS_IOB_RESET;
for(d = 0; d < 128; d++)
wakedev(bus, d);
bus->c34 &= ~IOBUS_IOB_RESET;
}
void
cono(IOBus *bus, int d, hword w)
{
bus->c34 |= IOBUS_CONO_CLEAR;
wakedev(bus, d);
bus->c34 &= ~IOBUS_CONO_CLEAR;
bus->c34 |= IOBUS_CONO_SET;
bus->c12 = w;
wakedev(bus, d);
bus->c34 &= ~IOBUS_CONO_SET;
bus->c12 = 0;
}
void
datao(IOBus *bus, int d, word w)
{
bus->c34 |= IOBUS_DATAO_CLEAR;
wakedev(bus, d);
bus->c34 &= ~IOBUS_DATAO_CLEAR;
bus->c34 |= IOBUS_DATAO_SET;
bus->c12 = w;
wakedev(bus, d);
bus->c34 &= ~IOBUS_DATAO_SET;
bus->c12 = 0;
}
word
coni(IOBus *bus, int d)
{
word w;
bus->c34 |= IOBUS_IOB_STATUS;
wakedev(bus, d);
bus->c34 &= ~IOBUS_IOB_STATUS;
w = bus->c12;
bus->c12 = 0;
return w;
}
word
datai(IOBus *bus, int d)
{
word w;
bus->c34 |= IOBUS_IOB_DATAI;
wakedev(bus, d);
bus->c34 &= ~IOBUS_IOB_DATAI;
w = bus->c12;
bus->c12 = 0;
return w;
}
void
printdc(Dc136 *dc)
{
printf("DB/%012lo DA/%012lo CCT/%o SCT/%o CHMOD/%o\n",
dc->db, dc->da, dc->cct, dc->sct, dc->ch_mode);
printf(" CLBD/%o DBDAMOVE/%o DARQ/%o DBRQ/%o INOUT/%o DEV/%o PIA/%o\n",
dc->data_clbd, dc->dbda_move, dc->da_rq, dc->db_rq,
dc->inout, dc->device, dc->pia);
}
enum {
CLBD = 010000,
DBDAMOVE = 04000,
DARQ = 02000,
DBRQ = 01000,
IN = 0000,
OUT = 0400,
CHMOD_6 = 0000,
CHMOD_36 = 0100,
CHMOD_12 = 0200,
CHMOD_18 = 0300,
DEV1 = 010,
DEV2 = 020,
DEV3 = 030,
DEV4 = 040,
DEV5 = 050,
DEV6 = 060,
};
/*
* output:
* DARQ: DA empty, need new data
* DBRQ: DB empty, need new data
* DBDA MOVE: DB waiting to send data to DA
* input:
* DARQ: DA full, need to empty
* DBRQ: DB full, need to empty
* DBDA MOVE: DB waiting to get data from DA
*/
int
main()
{
dc = (Dc136*)makedc(0, nil);
dc->dev.ioconnect((Device*)dc, bus);
bus_reset(bus);
assert(coni(bus, DC) == 0);
// output test
cono(bus, DC, DARQ|DBRQ|OUT|CHMOD_6|DEV1|7); // 3417
assert(pireq == 7);
printdc(dc);
datao(bus, DC, 0123456000001);
assert(pireq == 7);
printdc(dc);
datao(bus, DC, 0123456000002);
assert(pireq == 0);
printdc(dc);
assert(dctk(dc, 1, 0) == 012);
assert(pireq == 0);
printdc(dc);
assert(dctk(dc, 1, 0) == 034);
assert(pireq == 0);
printdc(dc);
assert(dctk(dc, 1, 0) == 056);
assert(pireq == 0);
printdc(dc);
assert(dctk(dc, 1, 0) == 000);
assert(pireq == 0);
printdc(dc);
assert(dctk(dc, 1, 0) == 000);
assert(pireq == 0);
printdc(dc);
assert(dctk(dc, 1, 0) == 001);
assert(pireq == 7);
printdc(dc);
printf("\n\n");
cono(bus, DC, DARQ|DBRQ|OUT|CHMOD_12|DEV5|7); // 3657
assert(pireq == 7);
printdc(dc);
datao(bus, DC, 0123456112233);
assert(pireq == 7);
printdc(dc);
datao(bus, DC, 0123456445566);
assert(pireq == 0);
printdc(dc);
assert((dctk(dc, 5, 0)&0777700000000) == 0123400000000);
assert(pireq == 0);
printdc(dc);
assert((dctk(dc, 5, 0)&0777700000000) == 0561100000000);
assert(pireq == 0);
printdc(dc);
assert((dctk(dc, 5, 0)&0777700000000) == 0223300000000);
assert(pireq == 7);
printdc(dc);
printf("\n\n");
// input test
cono(bus, DC, DBDAMOVE|IN|CHMOD_6|DEV1|7); // 4017
assert(pireq == 0);
printdc(dc);
dcgv(dc, 1, 012, 0);
assert(pireq == 0);
printdc(dc);
dcgv(dc, 1, 034, 0);
assert(pireq == 0);
printdc(dc);
dcgv(dc, 1, 056, 0);
assert(pireq == 0);
printdc(dc);
dcgv(dc, 1, 011, 0);
assert(pireq == 0);
printdc(dc);
dcgv(dc, 1, 022, 0);
assert(pireq == 0);
printdc(dc);
dcgv(dc, 1, 033, 0);
assert(pireq == 7);
printdc(dc);
assert(datai(bus, DC) == 0123456112233);
printdc(dc);
printf("\n\n");
cono(bus, DC, DBDAMOVE|IN|CHMOD_12|DEV5|7); // 4017
assert(pireq == 0);
printdc(dc);
dcgv(dc, 5, 01234, 0);
assert(pireq == 0);
printdc(dc);
dcgv(dc, 5, 05611, 0);
assert(pireq == 0);
printdc(dc);
dcgv(dc, 5, 02233, 0);
assert(pireq == 7);
printdc(dc);
return 0;
}