1
0
mirror of https://github.com/aap/pdp6.git synced 2026-03-06 11:23:55 +00:00

implemented threads differently

This commit is contained in:
aap
2017-02-02 19:37:19 +01:00
parent a2de61d375
commit 0766d0216e
13 changed files with 376 additions and 414 deletions

View File

@@ -1,5 +1,8 @@
test.rim: main.rel tty.rel
ld6 -r 100 -o test.rim main.rel tty.rel
test.rim: main.rel tty.rel pt.rel
ld6 -o test.rim main.rel tty.rel pt.rel
test.sav: main.rel tty.rel pt.rel
ld6 -f sav -o test.sav main.rel tty.rel pt.rel
%.rel: %.s
as6 -o $@ $<

View File

@@ -8,8 +8,9 @@ PRS==4
PTP==100
EXTERNAL PUTC,PUTS
EXTERNAL GETCH,GETC
EXTERN PUTC,PUTS
EXTERN GETCH,GETC
EXTERN PTPUT
ENTRY: JRST START
@@ -18,11 +19,11 @@ SP: XWD -100,PDL-1
START: MOVE PDP,SP
UUO1 123
; UUO1 123
CONO CPA,2001
CONO PRS,2300
JRST .
; CONO CPA,2001
; CONO PRS,2300
; JRST .
MOVSI AC2,440700
HRRI AC2,MSG
@@ -35,11 +36,6 @@ START: MOVE PDP,SP
HALT
PTPUT: CONSZ PTP,20
JRST .-1
DATAO PTP,AC1
POPJ PDP,
MSG: ASCIZ /Hello, world!
yo! > /

View File

@@ -3,7 +3,7 @@ H=pdp6.h ../tools/pdp6common.h
# clang
#CFLAGS= -Wno-shift-op-parentheses -Wno-logical-op-parentheses \
# -Wno-bitwise-op-parentheses
CFLAGS= -g -fno-diagnostics-show-caret \
CFLAGS= -g -Wall -Wno-parentheses -fno-diagnostics-show-caret \
`sdl-config --cflags` `pkg-config SDL_image --cflags`
LIBS= `sdl-config --libs` `pkg-config SDL_image --libs` -lpthread

449
emu/apr.c
View File

@@ -1,6 +1,49 @@
#include "pdp6.h"
#include <unistd.h>
static void aprcycle(void *p);
static void wake_cpa(void *dev);
static void wake_pi(void *dev);
void
curpulse(Apr *apr, Pulse *p)
{
if(apr->ncurpulses >= MAXPULSE){
fprint(stderr, "error: too many current pulses\n");
exit(1);
}
apr->clist[apr->ncurpulses++] = p;
}
void
nextpulse(Apr *apr, Pulse *p)
{
if(apr->nnextpulses >= MAXPULSE){
fprint(stderr, "error: too many next pulses\n");
exit(1);
}
apr->nlist[apr->nnextpulses++] = p;
}
Apr*
makeapr(void)
{
Apr *apr;
Thread th;
apr = malloc(sizeof(Apr));
memset(apr, 0, sizeof(Apr));
apr->iobus.dev[CPA] = (Busdev){ apr, wake_cpa, 0 };
apr->iobus.dev[PI] = (Busdev){ apr, wake_pi, 0 };
th = (Thread){ nil, aprcycle, apr, 1, 0 };
addthread(th);
return apr;
}
#define DBG_AR debug("AR: %012llo\n", apr->ar)
#define DBG_MB debug("MB: %012llo\n", apr->mb)
#define DBG_MQ debug("MQ: %012llo\n", apr->mq)
@@ -655,7 +698,7 @@ pulse(mr_pwr_clr){
/* CPA and PI devices */
void
static void
wake_cpa(void *dev)
{
Apr *apr;
@@ -708,7 +751,7 @@ wake_cpa(void *dev)
ex_set(apr);
}
void
static void
wake_pi(void *dev)
{
Apr *apr;
@@ -2487,9 +2530,9 @@ pulse(et0a){
trace("ET0A\n");
debug("%o: ", apr->pc);
if((apr->inst & 0700) != 0700)
debug("%s\n", names[apr->inst]);
debug("%s\n", mnemonics[apr->inst]);
else
debug("%s\n", ionames[apr->io_inst>>5 & 7]);
debug("%s\n", iomnemonics[apr->io_inst>>5 & 7]);
if(PI_HOLD)
set_pih(apr, apr->pi_req); // 8-3, 8-4
@@ -3014,36 +3057,6 @@ pulse(key_manual){
nextpulse(apr, kt0); // 5-2
}
void
curpulse(Apr *apr, Pulse *p)
{
if(apr->ncurpulses >= MAXPULSE){
fprint(stderr, "error: too many current pulses\n");
exit(1);
}
apr->clist[apr->ncurpulses++] = p;
}
void
nextpulse(Apr *apr, Pulse *p)
{
if(apr->nnextpulses >= MAXPULSE){
fprint(stderr, "error: too many next pulses\n");
exit(1);
}
apr->nlist[apr->nnextpulses++] = p;
}
Apr*
makeapr(void)
{
Apr *apr;
apr = malloc(sizeof(Apr));
memset(apr, 0, sizeof(Apr));
apr->iobus.dev[CPA] = (Busdev){ apr, wake_cpa, 0 };
apr->iobus.dev[PI] = (Busdev){ apr, wake_pi, 0 };
return apr;
}
/* find out which bits were turned on */
void
@@ -3057,16 +3070,10 @@ updatebus(void *bus)
#define TIMESTEP (1000.0/60.0)
void*
aprmain(void *p)
void
aprstart(Apr *apr)
{
Apr *apr;
Busdev *dev;
Pulse **tmp;
int i, devcode;
double lasttick, tick;
apr = (Apr*)p;
printf("[aprstart]\n");
apr->clist = apr->pulses1;
apr->nlist = apr->pulses2;
apr->ncurpulses = 0;
@@ -3080,262 +3087,144 @@ aprmain(void *p)
apr->membus.c34 = 0;
apr->iobus.c12 = 0;
apr->iobus.c34 = 0;
if(apr->membus.fmem)
apr->membus.fmem->poweron(apr->membus.fmem);
for(i = 0; i < 16; i++)
if(apr->membus.cmem[i])
apr->membus.cmem[i]->poweron(apr->membus.cmem[i]);
nextpulse(apr, mr_pwr_clr);
lasttick = getms();
while(apr->sw_power){
apr->ncurpulses = apr->nnextpulses;
apr->nnextpulses = 0;
tmp = apr->clist; apr->clist = apr->nlist; apr->nlist = tmp;
apr->lasttick = getms();
apr->powered = 1;
}
if(apr->pulsestepping){
int c;
while(c = getchar(), c != EOF && c != '\n')
if(c == 'x')
apr->pulsestepping = 0;
}
static void
aprcycle(void *p)
{
Apr *apr;
Busdev *dev;
Pulse **tmp;
int i, devcode;
tick = getms();
if(tick-lasttick >= TIMESTEP){
lasttick = lasttick+TIMESTEP;
apr->cpa_clock_flag = 1;
recalc_cpa_req(apr);
}
apr = p;
apr->iobus.c12_prev = apr->iobus.c12;
apr->iobus.c34_prev = apr->iobus.c34;
apr->membus.c12_prev = apr->membus.c12;
apr->membus.c34_prev = apr->membus.c34;
if(!apr->sw_power){
apr->powered = 0;
return;
}else if(!apr->powered)
aprstart(apr);
for(i = 0; i < apr->ncurpulses; i++)
apr->clist[i](apr);
apr->ncurpulses = apr->nnextpulses;
apr->nnextpulses = 0;
tmp = apr->clist; apr->clist = apr->nlist; apr->nlist = tmp;
updatebus(&apr->iobus);
updatebus(&apr->membus);
if(apr->pulsestepping){
int c;
while(c = getchar(), c != EOF && c != '\n')
if(c == 'x')
apr->pulsestepping = 0;
}
/* This is simplified, we have no IOT RESET,
* IOT INIT SET UP or IOT FINAL SETUP really.
* normally we'd have to wait for IOT RESET to clear here */
if(apr->iot_go)
nextpulse(apr, iot_t2);
apr->tick = getms();
if(apr->tick-apr->lasttick >= TIMESTEP){
apr->lasttick = apr->lasttick+TIMESTEP;
apr->cpa_clock_flag = 1;
recalc_cpa_req(apr);
}
apr->iobus.c12_prev = apr->iobus.c12;
apr->iobus.c34_prev = apr->iobus.c34;
apr->membus.c12_prev = apr->membus.c12;
apr->membus.c34_prev = apr->membus.c34;
for(i = 0; i < apr->ncurpulses; i++)
apr->clist[i](apr);
updatebus(&apr->iobus);
updatebus(&apr->membus);
/* This is simplified, we have no IOT RESET,
* IOT INIT SET UP or IOT FINAL SETUP really.
* normally we'd have to wait for IOT RESET to clear here */
if(apr->iot_go)
nextpulse(apr, iot_t2);
/* Key pulses */
if(apr->extpulse & EXT_KEY_MANUAL){
apr->extpulse &= ~EXT_KEY_MANUAL;
nextpulse(apr, key_manual);
}
if(apr->extpulse & EXT_KEY_INST_STOP){
apr->extpulse &= ~EXT_KEY_INST_STOP;
apr->run = 0;
// hack: cleared when the pulse list was empty
apr->ia_inh = 1;
}
/* Key pulses */
if(apr->extpulse & EXT_KEY_MANUAL){
apr->extpulse &= ~EXT_KEY_MANUAL;
nextpulse(apr, key_manual);
}
if(apr->extpulse & EXT_KEY_INST_STOP){
apr->extpulse &= ~EXT_KEY_INST_STOP;
apr->run = 0;
// hack: cleared when the pulse list was empty
apr->ia_inh = 1;
}
/* Pulses and signals through IO bus */
apr->iobus.devcode = -1;
if(apr->iobus.c34_pulse & (IOBUS_PULSES | IOBUS_IOB_STATUS | IOBUS_IOB_DATAI)){
devcode = 0;
if(apr->iobus.c34 & IOBUS_IOS3_1) devcode |= 0100;
if(apr->iobus.c34 & IOBUS_IOS4_1) devcode |= 0040;
if(apr->iobus.c34 & IOBUS_IOS5_1) devcode |= 0020;
if(apr->iobus.c34 & IOBUS_IOS6_1) devcode |= 0010;
if(apr->iobus.c34 & IOBUS_IOS7_1) devcode |= 0004;
if(apr->iobus.c34 & IOBUS_IOS8_1) devcode |= 0002;
if(apr->iobus.c34 & IOBUS_IOS9_1) devcode |= 0001;
apr->iobus.devcode = devcode;
dev = &apr->iobus.dev[devcode];
/* Pulses and signals through IO bus */
apr->iobus.devcode = -1;
if(apr->iobus.c34_pulse & (IOBUS_PULSES | IOBUS_IOB_STATUS | IOBUS_IOB_DATAI)){
devcode = 0;
if(apr->iobus.c34 & IOBUS_IOS3_1) devcode |= 0100;
if(apr->iobus.c34 & IOBUS_IOS4_1) devcode |= 0040;
if(apr->iobus.c34 & IOBUS_IOS5_1) devcode |= 0020;
if(apr->iobus.c34 & IOBUS_IOS6_1) devcode |= 0010;
if(apr->iobus.c34 & IOBUS_IOS7_1) devcode |= 0004;
if(apr->iobus.c34 & IOBUS_IOS8_1) devcode |= 0002;
if(apr->iobus.c34 & IOBUS_IOS9_1) devcode |= 0001;
apr->iobus.devcode = devcode;
dev = &apr->iobus.dev[devcode];
if(dev->wake)
dev->wake(dev->dev);
}
if(apr->iobus.c34_pulse & IOBUS_IOB_RESET){
int d;
for(d = 0; d < 128; d++){
dev = &apr->iobus.dev[d];
if(dev->wake)
dev->wake(dev->dev);
}
if(apr->iobus.c34_pulse & IOBUS_IOB_RESET){
int d;
for(d = 0; d < 128; d++){
dev = &apr->iobus.dev[d];
if(dev->wake)
dev->wake(dev->dev);
}
}
apr->iobus.c34 &= ~(IOBUS_PULSES | IOBUS_IOB_RESET);
/* Pulses to memory */
if(apr->membus.c12_pulse & (MEMBUS_WR_RS | MEMBUS_RQ_CYC)){
wakemem(&apr->membus);
apr->membus.c12 &= ~MEMBUS_WR_RS;
}
/* Pulses from memory */
if(apr->membus.c12 & MEMBUS_MAI_ADDR_ACK){
apr->membus.c12 &= ~MEMBUS_MAI_ADDR_ACK;
apr->extpulse &= ~EXT_NONEXIT_MEM;
nextpulse(apr, mai_addr_ack);
}
if(apr->membus.c12 & MEMBUS_MAI_RD_RS){
apr->membus.c12 &= ~MEMBUS_MAI_RD_RS;
nextpulse(apr, mai_rd_rs);
}
if(apr->mc_rd && apr->membus.c34){
/* 7-6, 7-9 */
apr->mb |= apr->membus.c34;
apr->membus.c34 = 0;
}
/* TODO: do this differently because the
* memory might have been busy. */
if(apr->extpulse & EXT_NONEXIT_MEM){
apr->extpulse &= ~EXT_NONEXIT_MEM;
if(apr->mc_rq && !apr->mc_stop)
nextpulse(apr, mc_non_exist_mem); // 7-9
}
if(i)
trace("--------------\n");
else
/* no longer needed */
apr->ia_inh = 0;
}
debug("power off\n");
return nil;
apr->iobus.c34 &= ~(IOBUS_PULSES | IOBUS_IOB_RESET);
/* Pulses to memory */
if(apr->membus.c12_pulse & (MEMBUS_WR_RS | MEMBUS_RQ_CYC)){
wakemem(&apr->membus);
apr->membus.c12 &= ~MEMBUS_WR_RS;
}
/* Pulses from memory */
if(apr->membus.c12 & MEMBUS_MAI_ADDR_ACK){
apr->membus.c12 &= ~MEMBUS_MAI_ADDR_ACK;
apr->extpulse &= ~EXT_NONEXIT_MEM;
nextpulse(apr, mai_addr_ack);
}
if(apr->membus.c12 & MEMBUS_MAI_RD_RS){
apr->membus.c12 &= ~MEMBUS_MAI_RD_RS;
nextpulse(apr, mai_rd_rs);
}
if(apr->mc_rd && apr->membus.c34){
/* 7-6, 7-9 */
apr->mb |= apr->membus.c34;
apr->membus.c34 = 0;
}
/* TODO: do this differently because the
* memory might have been busy. */
if(apr->extpulse & EXT_NONEXIT_MEM){
apr->extpulse &= ~EXT_NONEXIT_MEM;
if(apr->mc_rq && !apr->mc_stop)
nextpulse(apr, mc_non_exist_mem); // 7-9
}
if(i)
trace("--------------\n");
else
/* no longer needed */
apr->ia_inh = 0;
}
char *names[0700] = {
"UUO00", "UUO01", "UUO02", "UUO03",
"UUO04", "UUO05", "UUO06", "UUO07",
"UUO10", "UUO11", "UUO12", "UUO13",
"UUO14", "UUO15", "UUO16", "UUO17",
"UUO20", "UUO21", "UUO22", "UUO23",
"UUO24", "UUO25", "UUO26", "UUO27",
"UUO30", "UUO31", "UUO32", "UUO33",
"UUO34", "UUO35", "UUO36", "UUO37",
"UUO40", "UUO41", "UUO42", "UUO43",
"UUO44", "UUO45", "UUO46", "UUO47",
"UUO50", "UUO51", "UUO52", "UUO53",
"UUO54", "UUO55", "UUO56", "UUO57",
"UUO60", "UUO61", "UUO62", "UUO63",
"UUO64", "UUO65", "UUO66", "UUO67",
"UUO70", "UUO71", "UUO72", "UUO73",
"UUO74", "UUO75", "UUO76", "UUO77",
"XX100", "XX101", "XX102", "XX103",
"XX104", "XX105", "XX106", "XX107",
"XX110", "XX111", "XX112", "XX113",
"XX114", "XX115", "XX116", "XX117",
"XX120", "XX121", "XX122", "XX123",
"XX124", "XX125", "XX126", "XX127",
"XX130", "XX131", "FSC", "CAO",
"LDCI", "LDC", "DPCI", "DPC",
"FAD", "FADL", "FADM", "FADB",
"FADR", "FADLR", "FADMR", "FADBR",
"FSB", "FSBL", "FSBM", "FSBB",
"FSBR", "FSBLR", "FSBMR", "FSBBR",
"FMP", "FMPL", "FMPM", "FMPB",
"FMPR", "FMPLR", "FMPMR", "FMPBR",
"FDV", "FDVL", "FDVM", "FDVB",
"FDVR", "FDVLR", "FDVMR", "FDVBR",
"MOVE", "MOVEI", "MOVEM", "MOVES",
"MOVS", "MOVSI", "MOVSM", "MOVSS",
"MOVN", "MOVNI", "MOVNM", "MOVNS",
"MOVM", "MOVMI", "MOVMM", "MOVMS",
"IMUL", "IMULI", "IMULM", "IMULB",
"MUL", "MULI", "MULM", "MULB",
"IDIV", "IDIVI", "IDIVM", "IDIVB",
"DIV", "DIVI", "DIVM", "DIVB",
"ASH", "ROT", "LSH", "XX243",
"ASHC", "ROTC", "LSHC", "XX247",
"EXCH", "BLT", "AOBJP", "AOBJN",
"JRST", "JFCL", "XCT", "XX257",
"PUSHJ", "PUSH", "POP", "POPJ",
"JSR", "JSP", "JSA", "JRA",
"ADD", "ADDI", "ADDM", "ADDB",
"SUB", "SUBI", "SUBM", "SUBB",
"CAI", "CAIL", "CAIE", "CAILE",
"CAIA", "CAIGE", "CAIN", "CAIG",
"CAM", "CAML", "CAME", "CAMLE",
"CAMA", "CAMGE", "CAMN", "CAMG",
"JUMP", "JUMPL", "JUMPE", "JUMPLE",
"JUMPA", "JUMPGE", "JUMPN", "JUMPG",
"SKIP", "SKIPL", "SKIPE", "SKIPLE",
"SKIPA", "SKIPGE", "SKIPN", "SKIPG",
"AOJ", "AOJL", "AOJE", "AOJLE",
"AOJA", "AOJGE", "AOJN", "AOJG",
"AOS", "AOSL", "AOSE", "AOSLE",
"AOSA", "AOSGE", "AOSN", "AOSG",
"SOJ", "SOJL", "SOJE", "SOJLE",
"SOJA", "SOJGE", "SOJN", "SOJG",
"SOS", "SOSL", "SOSE", "SOSLE",
"SOSA", "SOSGE", "SOSN", "SOSG",
"SETZ", "SETZI", "SETZM", "SETZB",
"AND", "ANDI", "ANDM", "ANDB",
"ANDCA", "ANDCAI", "ANDCAM", "ANDCAB",
"SETM", "SETMI", "SETMM", "SETMB",
"ANDCM", "ANDCMI", "ANDCMM", "ANDCMB",
"SETA", "SETAI", "SETAM", "SETAB",
"XOR", "XORI", "XORM", "XORB",
"IOR", "IORI", "IORM", "IORB",
"ANDCB", "ANDCBI", "ANDCBM", "ANDCBB",
"EQV", "EQVI", "EQVM", "EQVB",
"SETCA", "SETCAI", "SETCAM", "SETCAB",
"ORCA", "ORCAI", "ORCAM", "ORCAB",
"SETCM", "SETCMI", "SETCMM", "SETCMB",
"ORCM", "ORCMI", "ORCMM", "ORCMB",
"ORCB", "ORCBI", "ORCBM", "ORCBB",
"SETO", "SETOI", "SETOM", "SETOB",
"HLL", "HLLI", "HLLM", "HLLS",
"HRL", "HRLI", "HRLM", "HRLS",
"HLLZ", "HLLZI", "HLLZM", "HLLZS",
"HRLZ", "HRLZI", "HRLZM", "HRLZS",
"HLLO", "HLLOI", "HLLOM", "HLLOS",
"HRLO", "HRLOI", "HRLOM", "HRLOS",
"HLLE", "HLLEI", "HLLEM", "HLLES",
"HRLE", "HRLEI", "HRLEM", "HRLES",
"HRR", "HRRI", "HRRM", "HRRS",
"HLR", "HLRI", "HLRM", "HLRS",
"HRRZ", "HRRZI", "HRRZM", "HRRZS",
"HLRZ", "HLRZI", "HLRZM", "HLRZS",
"HRRO", "HRROI", "HRROM", "HRROS",
"HLRO", "HLROI", "HLROM", "HLROS",
"HRRE", "HRREI", "HRREM", "HRRES",
"HLRE", "HLREI", "HLREM", "HLRES",
"TRN", "TLN", "TRNE", "TLNE",
"TRNA", "TLNA", "TRNN", "TLNN",
"TDN", "TSN", "TDNE", "TSNE",
"TDNA", "TSNA", "TDNN", "TSNN",
"TRZ", "TLZ", "TRZE", "TLZE",
"TRZA", "TLZA", "TRZN", "TLZN",
"TDZ", "TSZ", "TDZE", "TSZE",
"TDZA", "TSZA", "TDZN", "TSZN",
"TRC", "TLC", "TRCE", "TLCE",
"TRCA", "TLCA", "TRCN", "TLCN",
"TDC", "TSC", "TDCE", "TSCE",
"TDCA", "TSCA", "TDCN", "TSCN",
"TRO", "TLO", "TROE", "TLOE",
"TROA", "TLOA", "TRON", "TLON",
"TDO", "TSO", "TDOE", "TSOE",
"TDOA", "TSOA", "TDON", "TSON",
};
char *ionames[] = {
"BLKI",
"DATAI",
"BLKO",
"DATAO",
"CONO",
"CONI",
"CONSZ",
"CONSO"
};
void
testinst(Apr *apr)
@@ -3346,7 +3235,7 @@ testinst(Apr *apr)
// for(inst = 0140; inst < 0141; inst++){
apr->ir = inst << 9 | 1 << 5;
decodeir(apr);
debug("%06o %6s ", apr->ir, names[inst]);
debug("%06o %6s ", apr->ir, mnemonics[inst]);
/*
debug("%s ", FAC_INH ? "FAC_INH" : " ");
debug("%s ", FAC2 ? "FAC2" : " ");
@@ -3360,8 +3249,8 @@ testinst(Apr *apr)
debug("%s ", SAC2 ? "SAC2" : " ");
debug("\n");
// FC_E_PSE
//debug("FC_E_PSE: %d %d %d %d %d %d %d %d %d %d\n", apr->hwt_10 , apr->hwt_11 , apr->fwt_11 , \
// IOT_BLK , apr->inst == EXCH , CH_DEP , CH_INC_OP , \
//debug("FC_E_PSE: %d %d %d %d %d %d %d %d %d %d\n", apr->hwt_10 , apr->hwt_11 , apr->fwt_11 ,
// IOT_BLK , apr->inst == EXCH , CH_DEP , CH_INC_OP ,
// MEMAC_MEM , apr->boole_as_10 , apr->boole_as_11);
//debug("CH: %d %d %d %d %d\n", CH_INC, CH_INC_OP, CH_N_INC_OP, CH_LOAD, CH_DEP);
//debug("FAC_INH: %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",

View File

@@ -200,7 +200,7 @@ dep(word addr, int fastmem, word w)
static void
c_ex(int argc, char *argv[])
{
char *argv0;
char *argv0 = nil;
word start, end;
int format, fastmem;
@@ -225,7 +225,7 @@ c_ex(int argc, char *argv[])
static void
c_dep(int argc, char *argv[])
{
char *argv0;
char *argv0 = nil;
word start, end;
word w;
int fastmem;
@@ -276,6 +276,7 @@ loadsav(FILE *fp)
static void
c_load(int argc, char *argv[])
{
char *argv0 = nil;
FILE *fp;
int fmt;

View File

@@ -74,6 +74,26 @@ err(char *fmt, ...)
exit(1);
}
u32
getms(void)
{
return SDL_GetTicks();
}
int
hasinput(int fd)
{
fd_set fds;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(fd, &fds);
return select(fd+1, &fds, NULL, NULL, &timeout) > 0;
}
SDL_Surface*
mustloadimg(const char *path)
{
@@ -141,14 +161,6 @@ getswitches(Element *sw, int n)
return w;
}
void
poweron(Apr *apr)
{
pthread_t apr_thread;
apr->sw_power = 1;
pthread_create(&apr_thread, nil, aprmain, apr);
}
#define KEYPULSE(k) (apr->k && !oldapr.k)
void
@@ -170,8 +182,6 @@ updateapr(Apr *apr, Ptr *ptr)
misc_l[3].state = apr->sw_repeat = misc_sw[0].state;
misc_l[4].state = apr->sw_addr_stop = misc_sw[1].state;
misc_l[5].state = apr->sw_power = misc_sw[2].state;
if(apr->sw_power && !oldapr.sw_power)
poweron(apr);
misc_l[6].state = apr->sw_mem_disable = misc_sw[3].state;
apr->data = getswitches(data_sw, 36);
apr->mas = getswitches(ma_sw, 18);
@@ -528,12 +538,38 @@ findlayout(int *w, int *h)
*h = oppanel.pos.y + oppanel.surf->h;
}
u32
getms(void)
Thread *threads;
void
addthread(Thread th)
{
return SDL_GetTicks();
Thread *p;
p = malloc(sizeof(Thread));
*p = th;
p->next = threads;
threads = p;
}
void*
simthread(void *p)
{
Thread *th;
printf("[simthread] start\n");
for(;;)
for(th = threads; th; th = th->next){
th->cnt++;
if(th->cnt == th->freq){
th->cnt = 0;
th->f(th->arg);
}
}
err("can't happen");
return nil;
}
void
quit(int code)
{
@@ -550,7 +586,6 @@ usage(void)
}
Apr *aprs[4];
Mem *coremems[4];
int
main(int argc, char *argv[])
@@ -560,17 +595,17 @@ main(int argc, char *argv[])
SDL_MouseButtonEvent *mbev;
SDL_MouseMotionEvent *mmev;
Element *e;
Uint32 start, end;
int delay;
int i;
int w, h;
pthread_t cmd_thread;
pthread_t cmd_thread, sim_thread;
const char *outfile, *ttyfile;
Apr *apr;
Ptr *ptr;
Ptp *ptp;
Tty *tty;
Mem *coremems[4];
Mem *fastmem;
outfile = "/dev/null";
ttyfile = "/tmp/6tty";
@@ -681,12 +716,14 @@ main(int argc, char *argv[])
extra_l = e; e += 1;
aprs[0] = apr = makeapr();
fastmem = makefastmem(0);
coremems[0] = makecoremem("mem_0");
coremems[1] = makecoremem("mem_1");
coremems[2] = makecoremem("mem_2");
coremems[3] = makecoremem("mem_3");
attachmem(makefastmem(0), 0, &apr->membus, -1);
aprs[0] = apr = makeapr();
attachmem(fastmem, 0, &apr->membus, -1);
attachmem(coremems[0], 0, &apr->membus, 0);
attachmem(coremems[1], 0, &apr->membus, 1);
attachmem(coremems[2], 0, &apr->membus, 2);
@@ -697,10 +734,18 @@ main(int argc, char *argv[])
if(ttyfile)
attachdevtty(tty, ttyfile);
/* Power on memory */
// TODO: maybe do that somewhere else?
fastmem->poweron(fastmem);
coremems[0]->poweron(coremems[0]);
coremems[1]->poweron(coremems[1]);
coremems[2]->poweron(coremems[2]);
coremems[3]->poweron(coremems[3]);
pthread_create(&sim_thread, nil, simthread, apr);
pthread_create(&cmd_thread, nil, cmdthread, nil);
for(;;){
start = SDL_GetTicks();
while(SDL_PollEvent(&ev))
switch(ev.type){
case SDL_MOUSEMOTION:
@@ -744,10 +789,6 @@ main(int argc, char *argv[])
// SDL_UnlockSurface(screen);
SDL_Flip(screen);
end = SDL_GetTicks();
delay = (1000 / 30) - (end-start);
// if(delay > 0)
// SDL_Delay(delay);
}
return 0;
}

View File

@@ -46,7 +46,6 @@ wakecore(Mem *mem, Membus *bus)
* Lower numbers have higher priority but proc 2 and 3 have
* the same priority and requests are alternated between them.
* If no request is made, we should already be connected to a bus */
pthread_mutex_lock(&core->mutex);
if(core->cmc_p_act < 0){
if(mem->bus[0]->c12 & MEMBUS_RQ_CYC)
core->cmc_p_act = 0;
@@ -65,18 +64,16 @@ wakecore(Mem *mem, Membus *bus)
core->cmc_p_act = 2;
else if(p3)
core->cmc_p_act = 3;
else{
pthread_mutex_unlock(&core->mutex);
else
return 1; /* no request at all? */
}
}
core->cmc_last_proc = core->cmc_p_act;
}
}
pthread_mutex_unlock(&core->mutex);
/* The executing thread can only service requests from its own processor
* due to synchronization with the processor's pulse cycle. */
/* TODO: is this still true after the removal of pthreads? */
if(bus != mem->bus[core->cmc_p_act])
return 1;
@@ -135,6 +132,7 @@ powercore(Mem *mem)
{
CMem *core;
printf("[powercore]\n");
core = mem->module;
readmem(core->filename, core->core, 040000);
core->cmc_aw_rq = 1;
@@ -200,6 +198,7 @@ powerff(Mem *mem)
{
FMem *ff;
printf("[powerff]\n");
ff = mem->module;
ff->fmc_act = 0;
ff->fmc_wr = 0;
@@ -241,7 +240,6 @@ makecoremem(const char *file)
core = malloc(sizeof(CMem));
memset(core, 0, sizeof(CMem));
core->filename = file;
pthread_mutex_init(&core->mutex, nil);
mem = malloc(sizeof(Mem));
mem->module = core;

View File

@@ -5,7 +5,6 @@
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <pthread.h>
#include "../tools/pdp6common.h"
#define nelem(a) (sizeof(a)/sizeof(a[0]))
@@ -24,6 +23,9 @@ extern FILE *debugfp;
extern int dotrace;
void trace(char *fmt, ...);
void debug(char *fmt, ...);
void err(char *fmt, ...);
u32 getms(void);
int hasinput(int fd);
void quit(int code);
void *cmdthread(void *);
@@ -65,6 +67,20 @@ enum FullwordBits {
F33 = 0000000000004, F34 = 0000000000002, F35 = 0000000000001
};
typedef struct Thread Thread;
struct Thread
{
Thread *next; /* link to next thread */
void (*f)(void*);
void *arg;
int freq; /* how often the thread is serviced */
int cnt;
};
extern Thread *threads;
void addthread(Thread th);
/* external pulses, bits of Apr.extpulse */
enum Extpulse {
EXT_KEY_MANUAL = 1,
@@ -121,8 +137,6 @@ typedef struct Busdev Busdev;
typedef struct IOBus IOBus;
typedef struct Apr Apr;
u32 getms(void);
/*
* Memory
@@ -190,7 +204,6 @@ Mem *makefastmem(int p);
struct CMem
{
const char *filename;
pthread_mutex_t mutex;
word core[040000];
word cmb;
@@ -294,6 +307,7 @@ struct Apr
{
IOBus iobus;
Membus membus;
int powered;
hword ir;
word mi;
@@ -391,6 +405,7 @@ struct Apr
bool pc_set;
/* needed for the emulation */
double lasttick, tick;
int extpulse;
bool ia_inh; // this is asserted for some time
int pulsestepping;
@@ -401,9 +416,6 @@ struct Apr
};
extern Apr *aprs[4];
Apr *makeapr(void);
void curpulse(Apr *apr, Pulse *p);
void nextpulse(Apr *apr, Pulse *p);
void *aprmain(void *p);
/* Paper tape punch 761 */
@@ -416,7 +428,7 @@ struct Ptp
bool busy, flag, b;
int pia;
FILE *fp;
int fd;
int waitdatao;
};
Ptp *makeptp(IOBus *bus);
@@ -434,7 +446,7 @@ struct Ptr
bool busy, flag, b;
int pia;
FILE *fp;
int fd;
};
Ptr *makeptr(IOBus *bus);
void ptr_setmotor(Ptr *ptr, int m);
@@ -454,9 +466,3 @@ struct Tty
};
Tty *maketty(IOBus *bus);
void attachdevtty(Tty *tty, const char *path);
// for debugging
char *names[0700];
char *ionames[010];

112
emu/pt.c
View File

@@ -1,10 +1,10 @@
#include "pdp6.h"
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <poll.h>
/* TODO? implement motor delays */
@@ -24,66 +24,61 @@ recalc_ptr_req(Ptr *ptr)
/* We have to punch after DATAO SET has happened. But BUSY is set by
* DATAO CLEAR. So we use waitdatao to record when SET has happened */
static void*
ptpthread(void *dev)
static void
ptpcycle(void *p)
{
Ptp *ptp;
uchar c;
ptp = dev;
for(;;){
if(ptp->busy && ptp->waitdatao){
if(ptp->fp){
if(ptp->b)
putc((ptp->ptp & 077) | 0200, ptp->fp);
else
putc(ptp->ptp, ptp->fp);
fflush(ptp->fp);
}
ptp->busy = 0;
ptp->flag = 1;
recalc_ptp_req(ptp);
ptp = p;
if(ptp->busy && ptp->waitdatao){
if(ptp->fd >= 0){
if(ptp->b)
c = (ptp->ptp & 077) | 0200;
else
c = ptp->ptp;
write(ptp->fd, &c, 1);
}
ptp->busy = 0;
ptp->flag = 1;
recalc_ptp_req(ptp);
}
return nil;
}
static void*
ptrthread(void *dev)
static void
ptrcycle(void *p)
{
Ptr *ptr;
int c;
uchar c;
ptr = dev;
for(;;){
if(ptr->busy && ptr->motor_on){
// PTR CLR
ptr->sr = 0;
ptr->ptr = 0;
next:
if(ptr->fp)
c = getc(ptr->fp);
else
c = 0;
if(c == EOF)
c = 0;
if(!ptr->b || c & 0200){
// PTR STROBE
ptr->sr <<= 1;
ptr->ptr <<= 6;
ptr->sr |= 1;
ptr->ptr |= c & 077;
if(!ptr->b)
ptr->ptr |= c & 0300;
}
if(!ptr->b || ptr->sr & 040){
ptr->busy = 0;
ptr->flag = 1;
}else
goto next;
recalc_ptr_req(ptr);
}
ptr = p;
if(!ptr->busy || !ptr->motor_on)
return;
// PTR CLR
ptr->sr = 0;
ptr->ptr = 0;
next:
if(ptr->fd >= 0 && hasinput(ptr->fd)){
if(read(ptr->fd, &c, 1) != 1)
c = 0;
}else
c = 0;
if(!ptr->b || c & 0200){
// PTR STROBE
ptr->sr <<= 1;
ptr->ptr <<= 6;
ptr->sr |= 1;
ptr->ptr |= c & 077;
if(!ptr->b)
ptr->ptr |= c & 0300;
}
return nil;
if(!ptr->b || ptr->sr & 040){
ptr->busy = 0;
ptr->flag = 1;
}else
goto next;
recalc_ptr_req(ptr);
}
static void
@@ -193,30 +188,35 @@ ptr_setmotor(Ptr *ptr, int m)
Ptp*
makeptp(IOBus *bus)
{
pthread_t thread_id;
Ptp *ptp;
Thread th;
ptp = malloc(sizeof(Ptp));
memset(ptp, 0, sizeof(Ptp));
ptp->bus = bus;
bus->dev[PTP] = (Busdev){ ptp, wake_ptp, 0 };
pthread_create(&thread_id, nil, ptpthread, ptp);
ptp->fp = fopen("../code/ptp.out", "wb");
th = (Thread){ nil, ptpcycle, ptp, 1, 0 };
addthread(th);
ptp->fd = open("../code/ptp.out", O_WRONLY | O_CREAT, 0666);
return ptp;
}
Ptr*
makeptr(IOBus *bus)
{
pthread_t thread_id;
Ptr *ptr;
Thread th;
ptr = malloc(sizeof(Ptr));
memset(ptr, 0, sizeof(Ptr));
ptr->bus = bus;
bus->dev[PTR] = (Busdev){ ptr, wake_ptr, 0 };
pthread_create(&thread_id, nil, ptrthread, ptr);
ptr->fp = fopen("../code/test.rim", "rb");
th = (Thread){ nil, ptrcycle, ptr, 1, 0 };
addthread(th);
ptr->fd = open("../code/test.rim", O_RDONLY);
return ptr;
}

View File

@@ -2,7 +2,6 @@
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <pthread.h>
#include <poll.h>
static void
@@ -11,23 +10,23 @@ recalc_tty_req(Tty *tty)
setreq(tty->bus, TTY, tty->tto_flag || tty->tti_flag ? tty->pia : 0);
}
/* TODO: implement some kind of sleep if no tty is attached */
static void*
ttythread(void *dev)
static void
ttycycle(void *p)
{
Tty *tty;
int n;
char c;
Tty *tty;
tty = dev;
for(;;){
while(tty->fd >= 0 && (n = read(tty->fd, &c, 1)) > 0){
tty->tti_busy = 1;
tty->tti = c|0200;
tty->tti_busy = 0;
tty->tti_flag = 1;
recalc_tty_req(tty);
}
tty = p;
if(tty->fd >= 0 && hasinput(tty->fd)){
tty->tti_busy = 1;
n = read(tty->fd, &c, 1);
tty->tti = c|0200;
tty->tti_busy = 0;
if(n < 0)
return;
tty->tti_flag = 1;
recalc_tty_req(tty);
}
}
@@ -123,14 +122,17 @@ fail:
Tty*
maketty(IOBus *bus)
{
pthread_t thread_id;
Tty *tty;
Thread th;
tty = malloc(sizeof(Tty));
memset(tty, 0, sizeof(Tty));
tty->fd = -1;
tty->bus = bus;
bus->dev[TTY] = (Busdev){ tty, wake_tty, 0 };
pthread_create(&thread_id, nil, ttythread, tty);
th = (Thread){ nil, ttycycle, tty, 1, 0 };
addthread(th);
return tty;
}

24
tools/args.h Normal file
View File

@@ -0,0 +1,24 @@
extern char *argv0;
#define USED(x) ((void)x)
#define SET(x) ((x)=0)
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
argv[0] && argv[0][0]=='-' && argv[0][1];\
argc--, argv++) {\
char *_args, *_argt;\
char _argc;\
_args = &argv[0][1];\
if(_args[0]=='-' && _args[1]==0){\
argc--; argv++; break;\
}\
_argc = 0;\
while(*_args && (_argc = *_args++))\
switch(_argc)
#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
#define ARGF() (_argt=_args, _args=(char*)"",\
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
#define EARGF(x) (_argt=_args, _args=(char*)"",\
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
#define ARGC() _argc

View File

@@ -42,7 +42,6 @@ readw(FILE *fp)
void
writewbak(word w, FILE *fp)
{
unsigned char c;
putc((w >> 29) & 0177, fp);
putc((w >> 22) & 0177, fp);
putc((w >> 15) & 0177, fp);

View File

@@ -28,3 +28,6 @@ int issixbit(char c);
word sixbit(const char *s);
void unsixbit(word sx, char *s);
char *disasm(word w);
extern char *mnemonics[448];
extern char *iomnemonics[8];