1
0
mirror of https://github.com/aap/pdp6.git synced 2026-01-11 23:53:31 +00:00

added network memory; some work on cmdline interface

This commit is contained in:
aap 2018-08-15 14:18:52 +02:00
parent 67fa30288e
commit 28cc63f3ba
16 changed files with 524 additions and 84 deletions

View File

@ -71,5 +71,5 @@ The TTY is connected to UART over GPIO pins 4 (RX) and 5 (TX)
- repeat and maint. switches
- test thoroughly!
- devices
- devices (test UT, implement 340)
- timing

View File

@ -1,3 +1,6 @@
sysgen.rim: sysgen.rel sysgen.lst
ld6 -o sysgen.rim sysgen.rel
test.rim: main.rel tty.rel pt.rel dt.rel
ld6 -o test.rim main.rel tty.rel pt.rel dt.rel

View File

@ -50,16 +50,74 @@ PDP-10 RIM10 LOADER:
MAC DECtape RIM loader:
000000 JFCL
000001 MOVSI (JFCL)
000002 CONO 635550
000003 CONO PI,11577
000004 CONO UTC,223110
000005 CONO DC,4010
000006 CONSO DC,1000
000007 JRST 6
000010 DATAI DC,13
000011 AOJGE 13,6
000012 TRNE 13,-1
000013 .
000014 JRST 6
00 255000 000000 JFCL / no-op, what for?
01 205000 255000 MOVSI (JFCL) / restore JFCL in 0
02 700200 635550 CONO 635550 / reset APR
03 700600 011577 CONO PI,11577 / reset PI
04 721200 223110 CONO UTC,223110 / read all forward
05 720200 004010 CONO DC,4010 / read
06 720340 001000 LUP%: CONSO DC,1000 / wait for word
07 254000 000006 JRST .-1
10 720040 000013 DATAI DC,A% / read word
11 345540 000006 AOJGE A%,LUP% / try next word if >= -1
12 602540 777777 TRNE A%,-1 / execute if RH!=0 (was -1)
13 000000 000013 A%: .
14 254000 000006 JRST LUP%
15
16
17
11: like AOBJP without incrementing left half
12: execute only if right half != 0
0 DATAI PTR,1
1 .
2 JRST 0
Written by RIM loader loader (part of MACDMP)
2 JRST 0
10 CONO 1000 / turn clock flag off
11 JFCL X
12 JFCL X
13 JFCL X
14 JFCL X
15 CONSZ 1000 / skip if clock flag off
16 JRST 10 / clock on, so still on repeat
17 SKIPA X / clock off, we're at full speed
20 CONO PTR,60
21 CONSO PTR,10
22 JRST 21
23 DATAI PTR,26
24 CONSO PTR,10
25 JRST 24
26 XCT 26
27 JRST 21
37 37176
PDP6 SBLK loader:
1 MOVE 1,15
2 JSP 17,30 / wait for ready
3 DATAI PTR,16 / get block header
4 MOVE 15,16 / save for checksum
5 JUMPG 16,16 / execute if not negative
6 JSP 17,30 / read block word
7 DATAI PTR,(16)
10 ROT 15,1
11 ADD 15,(16)
12 AOBJN 16,6
13 MOVEI 17,33
14 JRST 30
15 CONO PTR,60 / replaced by current checksum
16 / input word: header/aobjn pointer/checksum
17 / return address
30 CONSO PTR,10 / wait for word
31 JRST 30
32 JRST (17)
33 DATAI PTR,16 / get checksum word
34 CAMN 15,16
35 JRST 2 / go to next block if checksum ok
36 JRST 4,1

View File

@ -1,4 +1,4 @@
SRC=main.c cmd.c apr.c mem.c tty.c pt.c dc.c dt.c ../tools/pdp6common.c
SRC=main.c util.c cmd.c apr.c mem.c tty.c pt.c dc.c dt.c netmem.c ../tools/pdp6common.c
H=pdp6.h ../tools/pdp6common.h
# clang
#CFLAGS= -Wno-shift-op-parentheses -Wno-logical-op-parentheses \

View File

@ -68,6 +68,38 @@ nextpulse(Apr *apr, Pulse *p)
apr->nlist[apr->nnextpulses++] = p;
}
// TODO This is WIP
#define EXDEPREGS \
X(ir)\
X(mi)\
X(data)\
X(pc)\
X(ma)\
X(mas)\
X(mb)\
X(ar)\
X(mq)
static word
ex_apr(Device *dev, const char *reg)
{
Apr *apr = (Apr*)dev;
#define X(name) if(strcmp(#name, reg) == 0) return apr->name;
EXDEPREGS
#undef X
return ~0;
}
static int
dep_apr(Device *dev, const char *reg, word data)
{
Apr *apr = (Apr*)dev;
#define X(name) if(strcmp(#name, reg) == 0) { apr->name = data; return 0; }
EXDEPREGS
#undef X
return 1;
}
Device*
makeapr(int argc, char *argv[])
{
@ -81,6 +113,8 @@ makeapr(int argc, char *argv[])
apr->dev.name = "";
apr->dev.attach = nil;
apr->dev.ioconnect = nil;
apr->dev.examine = ex_apr;
apr->dev.deposit = dep_apr;
apr->dev.next = nil;
apr->iobus.dev[CPA] = (Busdev){ apr, wake_cpa, 0 };

View File

@ -1,7 +1,7 @@
#define USED(x) ((void)x)
#define SET(x) ((x)=0)
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
#define ARGBEGIN for((void)(argv0||(argv0=*argv)),argv++,argc--;\
argv[0] && argv[0][0]=='-' && argv[0][1];\
argc--, argv++) {\
char *_args, *_argt;\

122
emu/cmd.c
View File

@ -213,6 +213,7 @@ DevDef definitions[] = {
{ DC_IDENT, makedc },
{ DT_IDENT, makedt },
{ DX_IDENT, makedx },
{ NETMEM_IDENT, makenetmem },
{ nil, nil }
};
@ -408,6 +409,79 @@ c_dep(int argc, char *argv[])
dep(start, fastmem, w);
}
/* parse "devname.reg".
* look up "devname" and return it.
* also remove "devname." from original string.
* if "devname." is missing, return last device.
* return apr if anything goes wrong */
Device*
getexdepdev(char *dev)
{
static Device *exdepdev;
char *s;
Device *d;
s = strchr(dev, '.');
if(s == nil){
if(exdepdev == nil)
exdepdev = &apr->dev;
return exdepdev;
}
*s++ = '\0';
d = getdevice(dev);
exdepdev = d ? d : &apr->dev;
while(*dev++ = *s++);
return exdepdev;
}
static void
c_xex(int argc, char *argv[])
{
int i;
Device *dev;
word w;
for(i = 1; i < argc; i++){
dev = getexdepdev(argv[i]);
if(dev->examine){
strtolower(argv[i]);
w = dev->examine(dev, argv[i]);
if(w == ~0)
printf("can't examine %s\n", argv[i]);
else
printf("%012lo\n", w);
}else
printf("no examine on %s\n", dev->type);
}
}
static void
c_xdep(int argc, char *argv[])
{
int i;
Device *dev;
word w;
if(argc < 3)
return;
w = parsen(&argv[argc-1]);
if(w == ~0)
return;
for(i = 1; i < argc-1; i++){
dev = getexdepdev(argv[i]);
if(dev->deposit){
strtolower(argv[i]);
if(dev->deposit(dev, argv[i], w))
printf("can't deposit %s\n", argv[i]);
}else
printf("no deposit on %s\n", dev->type);
}
void updatepanel(Apr *apr);
updatepanel(apr);
}
enum
{
FmtUnk, FmtSav
@ -475,23 +549,51 @@ c_quit(int argc, char *argv[])
quit(0);
}
static void c_help(int argc, char *argv[]);
struct {
char *cmd;
void (*f)(int, char **);
char *desc;
} cmdtab[] = {
{ "mkdev", c_mkdev },
{ "attach", c_attach },
{ "ioconnect", c_ioconnect },
{ "memconnect", c_memconnect },
{ "devconnect", c_devconnect },
{ "examine", c_ex },
{ "deposit", c_dep },
{ "load", c_load },
{ "show", c_show },
{ "quit", c_quit },
{ "mkdev", c_mkdev,
"make a device: mkdev name type [args]" },
{ "attach", c_attach,
"attach a file to a devie: attach name filename" },
{ "connectio", c_ioconnect,
"connect device to IO bus: connectio devname procname" },
{ "connectmem", c_memconnect,
"connect memory to mem bus: connectmem memname memport procname address/16k" },
{ "connectdev", c_devconnect,
"connect devices: connectdev dev1name dev2name [args]" },
{ "examine", c_ex,
"examine memory: examine [-sm] memrange" },
{ "deposit", c_dep,
"deposit memory: deposit [-s] memrange word" },
{ "xexamine", c_xex,
"examine device" },
{ "xdeposit", c_xdep,
"deposit device" },
{ "load", c_load,
"load file into memory: load [-s] filename" },
{ "show", c_show,
"show configuration" },
{ "quit", c_quit,
"quit emulator" },
{ "help", c_help,
"print help" },
{ "", nil}
};
static void
c_help(int argc, char *argv[])
{
int i;
for(i = 0; cmdtab[i].cmd[0]; i++)
printf(" %s:\t%s\n", cmdtab[i].cmd, cmdtab[i].desc);
}
void
commandline(char *line)
{

View File

@ -2,17 +2,21 @@ mkdev name type
creates a device and gives it a name
attach name path
attaches a file to a device
ioconnect name busdevname
connectio name busdevname
connects a device to the IO bus of a processor
memconnect name procnum busdevname addr
connectmem name procnum busdevname addr
connects a memory module to the memory bus of a processor
connectdev dev1name dev2name [args]
connects two devices in the appropriate way if possible
examine [-sm] address(range)
examines memory (s: shadow mode, m: mnemonic)
deposit [-sm] address(range) word
deposits word into memory (s: shadow mode, m: mnemonic)
load filename
load [-s] filename
loads file into memory (see source for which format)
show
shows device configuration
help
print help
quit
take a guess

View File

@ -11,21 +11,25 @@ mkdev cmem0 cmem161C mem_0
mkdev cmem1 cmem161C mem_1
mkdev cmem2 cmem161C mem_2
mkdev cmem3 cmem161C mem_3
#mkdev netmem netmem its.pdp10.se 10006
devconnect dc dt0
devconnect dt0 dx0 8
ioconnect tty apr
ioconnect ptr apr
ioconnect ptp apr
ioconnect dc apr
ioconnect dt0 apr
memconnect fmem 0 apr -1
memconnect cmem0 0 apr 0
memconnect cmem1 0 apr 1
memconnect cmem2 0 apr 2
memconnect cmem3 0 apr 3
connectdev dc dt0
connectdev dt0 dx0 8
connectio tty apr
connectio ptr apr
connectio ptp apr
connectio dc apr
connectio dt0 apr
connectmem fmem 0 apr -1
connectmem cmem0 0 apr 0
connectmem cmem1 0 apr 1
connectmem cmem2 0 apr 2
connectmem cmem3 0 apr 3
attach tty /tmp/6tty
attach ptr ../code/test.rim
#attach ptr ../code/test.rim
attach ptr ../code/sysgen.rim
#attach ptr ../lars_sysgen/sysgen.pt
attach ptp ../code/ptp.out
attach dx0 ../test/out.dt6
#attach dx0 ../test/out.dt6
attach dx0 ../test/test.dt6

View File

@ -80,20 +80,6 @@ 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)
{
@ -143,7 +129,7 @@ Element *extra_l;
#include "elements.inc"
void
setlights(word w, Element *l, int n)
setelements(word w, Element *l, int n)
{
int i;
for(i = 0; i < n; i++)
@ -151,7 +137,7 @@ setlights(word w, Element *l, int n)
}
word
getswitches(Element *sw, int n)
getelements(Element *sw, int n)
{
word w;
int i;
@ -163,6 +149,20 @@ getswitches(Element *sw, int n)
#define KEYPULSE(k) (apr->k && !oldapr.k)
/* Set panel from internal APR state */
void
updatepanel(Apr *apr)
{
setelements(apr->data, data_sw, 36);
setelements(apr->mas, ma_sw, 18);
extra_sw[0].state = apr->sw_rim_maint;
extra_sw[1].state = apr->sw_rpt_bypass;
extra_sw[2].state = apr->sw_art3_maint;
extra_sw[3].state = apr->sw_sct_maint;
extra_sw[4].state = apr->sw_spltcyc_override;
}
void
updateapr(Apr *apr, Ptr *ptr)
{
@ -171,13 +171,13 @@ updateapr(Apr *apr, Ptr *ptr)
if(apr == nil)
return;
oldapr = *apr;
setlights(apr->ir, ir_l, 18);
setlights(apr->mi, mi_l, 36);
setlights(apr->pc, pc_l, 18);
setlights(apr->ma, ma_l, 18);
setlights(apr->pih, pih_l, 7);
setlights(apr->pir, pir_l, 7);
setlights(apr->pio, pio_l, 7);
setelements(apr->ir, ir_l, 18);
setelements(apr->mi, mi_l, 36);
setelements(apr->pc, pc_l, 18);
setelements(apr->ma, ma_l, 18);
setelements(apr->pih, pih_l, 7);
setelements(apr->pir, pir_l, 7);
setelements(apr->pio, pio_l, 7);
misc_l[0].state = apr->pi_active;
misc_l[1].state = apr->mc_stop;
misc_l[2].state = apr->run;
@ -185,8 +185,8 @@ updateapr(Apr *apr, Ptr *ptr)
misc_l[4].state = apr->sw_addr_stop = misc_sw[1].state;
misc_l[5].state = apr->sw_power = misc_sw[2].state;
misc_l[6].state = apr->sw_mem_disable = misc_sw[3].state;
apr->data = getswitches(data_sw, 36);
apr->mas = getswitches(ma_sw, 18);
apr->data = getelements(data_sw, 36);
apr->mas = getelements(ma_sw, 18);
apr->sw_rim_maint = extra_sw[0].state;
if(apr->sw_rim_maint)
@ -229,9 +229,9 @@ updateapr(Apr *apr, Ptr *ptr)
}
}
setlights(apr->mb, mb_l, 36);
setlights(apr->ar, ar_l, 36);
setlights(apr->mq, mq_l, 36);
setelements(apr->mb, mb_l, 36);
setelements(apr->ar, ar_l, 36);
setelements(apr->mq, mq_l, 36);
ff_l[0].state = apr->key_ex_st;
ff_l[1].state = apr->key_ex_sync;
@ -314,9 +314,9 @@ updateapr(Apr *apr, Ptr *ptr)
ff_l[70].state = apr->uuo_f1;
ff_l[71].state = apr->cpa_pdl_ov;
setlights(apr->fe, &ff_l[72], 8);
setelements(apr->fe, &ff_l[72], 8);
setlights(apr->sc, &ff_l[80], 8);
setelements(apr->sc, &ff_l[80], 8);
ff_l[88].state = !apr->ex_user;
ff_l[89].state = apr->cpa_illeg_op;
@ -345,10 +345,10 @@ updateapr(Apr *apr, Ptr *ptr)
ff_l[110].state = !!(apr->cpa_pia&2);
ff_l[111].state = !!(apr->cpa_pia&1);
setlights(apr->pr, pr_l, 8);
setlights(apr->rlr, rlr_l, 8);
setlights(apr->rla, rla_l, 8);
setlights(apr->iobus.c12, iobus_l, 36);
setelements(apr->pr, pr_l, 8);
setelements(apr->rlr, rlr_l, 8);
setelements(apr->rla, rla_l, 8);
setelements(apr->iobus.c12, iobus_l, 36);
}
void
@ -359,8 +359,8 @@ updatetty(Tty *tty)
tty_l[1].state = tty->tti_flag;
tty_l[2].state = tty->tto_busy;
tty_l[3].state = tty->tto_flag;
setlights(tty->pia, &tty_l[4], 3);
setlights(tty->tti, ttibuf_l, 8);
setelements(tty->pia, &tty_l[4], 3);
setelements(tty->tti, ttibuf_l, 8);
}
}
@ -371,16 +371,16 @@ updatept(Ptp *ptp, Ptr *ptr)
ptp_l[0].state = ptp->b;
ptp_l[1].state = ptp->busy;
ptp_l[2].state = ptp->flag;
setlights(ptp->pia, &ptp_l[3], 3);
setlights(ptp->ptp, ptpbuf_l, 8);
setelements(ptp->pia, &ptp_l[3], 3);
setelements(ptp->ptp, ptpbuf_l, 8);
}
if(ptr){
ptr_l[0].state = ptr->b;
ptr_l[1].state = ptr->busy;
ptr_l[2].state = ptr->flag;
setlights(ptr->pia, &ptr_l[3], 3);
setlights(ptr->ptr, ptrbuf_l, 36);
setelements(ptr->pia, &ptr_l[3], 3);
setelements(ptr->ptr, ptrbuf_l, 36);
extra_l[0].state = ptr->motor_on;
}
@ -649,7 +649,6 @@ main(int argc, char *argv[])
Ptr *ptr;
Ptp *ptp;
Tty *tty;
Mem *mem;
outfile = "/dev/null";
ARGBEGIN{

View File

@ -101,6 +101,7 @@ wakecore(Mem *mem, Membus *bus)
/* read and send read restart */
if(core->cma_rd_rq){
core->cmb |= core->core[core->cma];
core->core[core->cma] = 0;
bus->c34 |= core->cmb & FW;
bus->c12 |= MEMBUS_MAI_RD_RS;
//trace(" sending RD RS\n");

125
emu/netmem.c Normal file
View File

@ -0,0 +1,125 @@
#include "pdp6.h"
#include <unistd.h>
char *netmem_ident = NETMEM_IDENT;
enum
{
WRRQ = 1,
RDRQ = 2,
ACK = 3,
ERR = 4,
};
static void
netmemcycle(void *dev)
{
Netmem *nm;
nm = (Netmem*)dev;
u8 buf[9], len;
word a, d, *p;
if(nm->fd < 0)
return;
if(!hasinput(nm->fd))
return;
if(readn(nm->fd, &len, 1)){
fprintf(stderr, "netmem fd closed\n");
nm->fd = -1;
return;
}
if(len > 9){
fprintf(stderr, "netmem botch, closing\n");
close(nm->fd);
nm->fd = -1;
}
memset(buf, 0, sizeof(buf));
readn(nm->fd, buf, len);
a = buf[1] | buf[2]<<8 | buf[3]<<16;
d = buf[4] | buf[5]<<8 | buf[6]<<16 |
(word)buf[7]<<24 | (word)buf[8]<<32;
a &= 0777777;
d &= 0777777777777;
switch(buf[0]){
case WRRQ:
p = getmemref(&nm->apr->membus, a, 0);
if(p == nil) goto err;
*p = d;
printf("write %06lo %012lo\n", a, d);
buf[0] = 1;
buf[1] = ACK;
writen(nm->fd, buf, buf[0]+1);
break;
case RDRQ:
p = getmemref(&nm->apr->membus, a, 0);
if(p == nil) goto err;
d = *p;
printf("read %06lo %012lo\n", a, d);
buf[0] = 6;
buf[1] = ACK;
buf[2] = d;
buf[3] = d>>8;
buf[4] = d>>16;
buf[5] = d>>24;
buf[6] = d>>32;
writen(nm->fd, buf, buf[0]+1);
break;
default:
fprintf(stderr, "unknown netmem message %d\n", buf[0]);
break;
}
return;
err:
printf("error address %06lo\n", a);
buf[0] = 1;
buf[1] = ERR;
writen(nm->fd, buf, buf[0]+1);
}
Device*
makenetmem(int argc, char *argv[])
{
const char *host;
int port;
Netmem *nm;
Device *apr;
Thread th;
nm = malloc(sizeof(Netmem));
memset(nm, 0, sizeof(Netmem));
nm->dev.type = netmem_ident;
nm->dev.name = "";
nm->dev.attach = nil;
nm->dev.ioconnect = nil;
nm->dev.next = nil;
// TODO: don't hardcode;
apr = getdevice("apr");
assert(apr);
assert(apr->type == apr_ident);
nm->apr = (Apr*)apr;
if(argc > 0)
host = argv[0];
else
host = "localhost";
if(argc > 1)
port = atoi(argv[1]);
else
port = 10006;
printf("connecting to %s %d\n", host, port);
nm->fd = dial(host, port);
if(nm->fd < 0)
printf("couldn't connect\n");
th = (Thread){ nil, netmemcycle, nm, 50, 0 };
addthread(th);
return &nm->dev;
}

View File

@ -25,7 +25,12 @@ void trace(char *fmt, ...);
void debug(char *fmt, ...);
void err(char *fmt, ...);
u32 getms(void);
void strtolower(char *s);
int hasinput(int fd);
int writen(int fd, void *data, int n);
int readn(int fd, void *data, int n);
int dial(const char *host, int port);
void quit(int code);
void cli(FILE *f);
@ -100,6 +105,8 @@ struct Device
void (*attach)(Device *dev, const char *path);
/* connect device to iobus */
void (*ioconnect)(Device *dev, IOBus *bus);
word (*examine)(Device *dev, const char *reg);
int (*deposit)(Device *dev, const char *reg, word data);
};
extern Device *devlist;
@ -588,3 +595,16 @@ void dtconn(Dc136 *dc, Dt551 *dt);
void dtcono(Dt551 *dt, word iob);
void dtcycle(Dt551 *dt);
*/
typedef struct Netmem Netmem;
struct Netmem
{
Device dev;
int fd;
// tmp?
Apr *apr;
};
#define NETMEM_IDENT "netmem"
extern char *netmem_ident;
Device *makenetmem(int argc, char *argv[]);

87
emu/util.c Normal file
View File

@ -0,0 +1,87 @@
#include "pdp6.h"
#include <unistd.h>
#include <netdb.h>
void
strtolower(char *s)
{
for(; *s != '\0'; s++)
*s = tolower(*s);
}
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;
}
int
writen(int fd, void *data, int n)
{
int m;
while(n > 0){
m = write(fd, data, n);
if(m == -1)
return -1;
data += m;
n -= m;
}
return 0;
}
int
readn(int fd, void *data, int n)
{
int m;
while(n > 0){
m = read(fd, data, n);
if(m == -1)
return -1;
data += m;
n -= m;
}
return 0;
}
int
dial(const char *host, int port)
{
char portstr[32];
int sockfd;
struct addrinfo *result, *rp, hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
snprintf(portstr, 32, "%d", port);
if(getaddrinfo(host, portstr, &hints, &result)){
perror("error: getaddrinfo");
return -1;
}
for(rp = result; rp; rp = rp->ai_next){
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(sockfd < 0)
continue;
if(connect(sockfd, rp->ai_addr, rp->ai_addrlen) >= 0)
goto win;
close(sockfd);
}
freeaddrinfo(result);
perror("error");
return -1;
win:
freeaddrinfo(result);
return sockfd;
}

View File

@ -68,6 +68,7 @@ readwrite(int ttyin, int ttyout, int ptyin, int ptyout)
if(n = read(ptyin, &c, 1), n <= 0)
return;
else{
//if(c == '\a') c = '.';
write(ttyout, &c, 1);
SLEEP;
}

View File

@ -3062,6 +3062,7 @@ module apr(
// requests coming from the bus
wire [1:7] iob_pi_req = iobus_pi_req | cpa_req;
// TODO: this can be simpler, same as in KA10 code
assign pi_ok[1] = pi_active;
genvar i;
generate
@ -3178,6 +3179,7 @@ module apr(
cpa_pc_chg_enable & ar_pc_chg_flag |
cpa_arov_enable & ar_ov_flag;
wire [1:7] cpa_req;
// TODO: improve this
genvar j;
generate
for(j = 1; j <= 7; j = j + 1) begin: cpa_req_gen