Skip to content

Commit 66f5076

Browse files
committed
remove old verilog code; implement shared memory for panel6; sblk output for ld6
1 parent 2286859 commit 66f5076

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+261
-30160
lines changed

README.md

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# PDP-6 Emulator and Verilog Simulation
1+
# PDP-6 Emulator
22

33
This project aims to revive the PDP-6 (and later PDP-10)
44
computers by DEC.
@@ -41,23 +41,6 @@ the data control and DECtape are implemented.
4141
The panel is missing the repeat delay knobs,
4242
but the functionality is implemented.
4343

44-
## Verilog Simulation
45-
46-
The verilog code is a very accurate transcription of the schematics as well.
47-
Since the real machine is asynchronous I had to pull some tricks to make it
48-
work on an FPGA.
49-
The real machine uses delays that are triggered by pulses and output another
50-
pulse after some time. Instead of pulses I use clock enables, and delays are
51-
implemented by a counter synchronized to the 50MHz system clock.
52-
53-
### FPGA
54-
55-
I'm using a DE0-Nano-SoC with has an ARM hps connected to the Cyclone V FPGA.
56-
On the ARM side runs fe6 (a DDT-like interface) which communicates with
57-
the FPGA through memory mapped IO registers.
58-
The quartus project is not yet part of this repo
59-
but the important modules are in the verilog directory.
60-
6144
## File tree
6245
NB: not up to date
6346

@@ -100,9 +83,6 @@ tools/test2.s
10083
tools/ptdump.c print a paper tape file in octal
10184
tools/dtdump.c print dtr DECtape
10285
103-
verilog
104-
verilog/... fpga stuff
105-
10686
code random code for the PDP-6, mostly testing
10787
code/bootstrap.txt a list of boot loaders
10888
code/dtboot.s loads the first block from a DECtape

emu/util.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
#include <string.h>
33
#include <ctype.h>
44

5+
#include <unistd.h>
6+
#include <fcntl.h>
7+
#include <sys/stat.h>
8+
#include <sys/mman.h>
59
#include <sys/socket.h>
610
#include <netinet/in.h>
711
#include <netinet/tcp.h>
@@ -135,3 +139,51 @@ nodelay(int fd)
135139
int flag = 1;
136140
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
137141
}
142+
143+
144+
void*
145+
createseg(const char *name, size_t sz)
146+
{
147+
int fd;
148+
void *p;
149+
150+
mode_t mask = umask(0);
151+
fd = open(name, O_RDWR|O_CREAT, 0666);
152+
umask(mask);
153+
// if we try to open a /tmp file owned by another user
154+
// with O_CREAT, the above will fail (even for root).
155+
// so try again without O_CREAT
156+
if(fd == -1)
157+
fd = open(name, O_RDWR);
158+
if(fd == -1) {
159+
fprintf(stderr, "couldn't open file %s\n", name);
160+
return NULL;
161+
}
162+
ftruncate(fd, sz);
163+
p = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
164+
if(p == MAP_FAILED) {
165+
fprintf(stderr, "couldn't mmap file\n");
166+
return NULL;
167+
}
168+
169+
return p;
170+
}
171+
void*
172+
attachseg(const char *name, size_t sz)
173+
{
174+
int fd;
175+
void *p;
176+
177+
fd = open(name, O_RDWR);
178+
if(fd == -1) {
179+
fprintf(stderr, "couldn't open file %s\n", name);
180+
return NULL;
181+
}
182+
p = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
183+
if(p == MAP_FAILED) {
184+
fprintf(stderr, "couldn't mmap file\n");
185+
return NULL;
186+
}
187+
188+
return p;
189+
}

emu/util.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ int readn(int fd, void *data, int n);
55
int dial(const char *host, int port);
66
void serve(int port, void (*handlecon)(int, void*), void *arg);
77
void nodelay(int fd);
8+
9+
void *createseg(const char *name, size_t sz);
10+
void *attachseg(const char *name, size_t sz);

panel/panel6.c

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ set36lights(uchar *b, Element *l)
161161
setlights(b[4], l+32, 4);
162162
}
163163

164+
164165
uchar
165166
getswitches(Element *sw, int n, int state)
166167
{
@@ -183,6 +184,25 @@ getswitches_(Element *sw, int n, int state)
183184
return b;
184185
}
185186

187+
void
188+
setnlights(int b, Element *l, int n, int bit)
189+
{
190+
int i;
191+
for(i = 0; i < n; i++, bit >>= 1)
192+
l[i].state = !!(b & bit);
193+
}
194+
195+
int
196+
getnswitches(Element *sw, int bit, int n, int state)
197+
{
198+
int b, i;
199+
b = 0;
200+
for(i = 0; i < n; i++, bit >>= 1)
201+
if(sw[i].state == state)
202+
b |= bit;
203+
return b;
204+
}
205+
186206

187207
uchar
188208
get18switches(uchar *b, Element *sw)
@@ -472,6 +492,81 @@ servethread(void *x)
472492
serve(2000, handlenetwork, nil);
473493
}
474494

495+
#include "panel6.h"
496+
497+
void*
498+
shmthread(void *x)
499+
{
500+
int key = 666;
501+
int id;
502+
Panel6 *p;
503+
int sw;
504+
505+
p = createseg("/tmp/pdp6_panel", sizeof(Panel6));
506+
if(p == nil)
507+
exit(1);
508+
509+
// set switches from previous state
510+
setnlights(p->sw0, data_sw+18, 18, 0400000);
511+
setnlights(p->sw1, data_sw, 18, 0400000);
512+
setnlights(p->sw2, ma_sw, 18, 0400000);
513+
misc_sw[0].state = !!(p->sw3 & SW_REPEAT);
514+
misc_sw[1].state = !!(p->sw3 & SW_ADDR_STOP);
515+
misc_sw[2].state = !!(p->sw3 & SW_POWER);
516+
misc_sw[3].state = !!(p->sw3 & SW_MEM_DISABLE);
517+
518+
for(;;) {
519+
p->sw0 = getnswitches(data_sw+18, 0400000, 18, 1);
520+
p->sw1 = getnswitches(data_sw, 0400000, 18, 1);
521+
p->sw2 = getnswitches(ma_sw, 0400000, 18, 1);
522+
sw = 0;
523+
if(keys[0].state == 1) sw |= KEY_START;
524+
if(keys[0].state == 2) sw |= KEY_READIN;
525+
if(keys[1].state == 1) sw |= KEY_INST_CONT;
526+
if(keys[1].state == 2) sw |= KEY_MEM_CONT;
527+
if(keys[2].state == 1) sw |= KEY_INST_STOP;
528+
if(keys[2].state == 2) sw |= KEY_MEM_STOP;
529+
if(keys[3].state == 1) sw |= KEY_IO_RESET;
530+
if(keys[3].state == 2) sw |= KEY_EXEC;
531+
if(keys[4].state == 1) sw |= KEY_DEP;
532+
if(keys[4].state == 2) sw |= KEY_DEP_NXT;
533+
if(keys[5].state == 1) sw |= KEY_EX;
534+
if(keys[5].state == 2) sw |= KEY_EX_NXT;
535+
if(misc_sw[0].state == 1) sw |= SW_REPEAT;
536+
if(misc_sw[1].state == 1) sw |= SW_ADDR_STOP;
537+
if(misc_sw[2].state == 1) sw |= SW_POWER;
538+
if(misc_sw[3].state == 1) sw |= SW_MEM_DISABLE;
539+
p->sw3 = sw;
540+
541+
sw = 0;
542+
if(keys[6].state == 1) sw |= KEY_MOTOR_OFF;
543+
if(keys[6].state == 2) sw |= KEY_MOTOR_ON;
544+
if(keys[7].state == 1) sw |= KEY_PTP_FEED;
545+
if(keys[7].state == 2) sw |= KEY_PTR_FEED;
546+
p->sw4 = sw;
547+
548+
setnlights(p->lights0, mi_l+18, 18, 0400000);
549+
setnlights(p->lights1, mi_l, 18, 0400000);
550+
setnlights(p->lights2, ma_l, 18, 0400000);
551+
setnlights(p->lights3, ir_l, 18, 0400000);
552+
setnlights(p->lights4, pc_l, 18, 0400000);
553+
554+
misc_l[0].state = !!(p->lights5 & L5_PI_ON);
555+
misc_l[1].state = !!(p->lights5 & L5_MC_STOP);
556+
misc_l[2].state = !!(p->lights5 & L5_RUN);
557+
misc_l[3].state = !!(p->lights5 & L5_REPEAT);
558+
misc_l[4].state = !!(p->lights5 & L5_ADDR_STOP);
559+
misc_l[5].state = !!(p->lights5 & L5_POWER);
560+
misc_l[6].state = !!(p->lights5 & L5_MEM_DISABLE);
561+
setnlights(p->lights5, pio_l, 7, 0100);
562+
563+
setnlights(p->lights6, pir_l, 7, 0100);
564+
setnlights(p->lights6, pih_l, 7, 020000);
565+
566+
usleep(30);
567+
}
568+
}
569+
475570
void*
476571
openserial(void *x)
477572
{
@@ -677,8 +772,9 @@ main(int argc, char *argv[])
677772
extra_l = e; e += 1;
678773

679774
// pthread_create(&comthread, nil, talki2c, nil);
680-
pthread_create(&comthread, nil, servethread, nil);
775+
// pthread_create(&comthread, nil, servethread, nil);
681776
// pthread_create(&comthread, nil, talkserial, nil);
777+
pthread_create(&comthread, nil, shmthread, nil);
682778

683779
for(;;){
684780
while(SDL_PollEvent(&ev))
@@ -714,6 +810,7 @@ main(int argc, char *argv[])
714810
drawelement(renderer, e, 1);
715811

716812
SDL_RenderPresent(renderer);
813+
SDL_Delay(30);
717814
}
718815
return 0;
719816
}

panel/panel6.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
enum {
3+
// sw0 data right
4+
// sw1 data left
5+
// sw2 addr
6+
// sw3
7+
KEY_START = 01,
8+
KEY_READIN = 02,
9+
KEY_INST_CONT = 04,
10+
KEY_MEM_CONT = 010,
11+
KEY_INST_STOP = 020,
12+
KEY_MEM_STOP = 040,
13+
KEY_IO_RESET = 0100,
14+
KEY_EXEC = 0200,
15+
KEY_DEP = 0400,
16+
KEY_DEP_NXT = 01000,
17+
KEY_EX = 02000,
18+
KEY_EX_NXT = 04000,
19+
20+
SW_POWER = 0400000,
21+
SW_REPEAT = 0200000,
22+
SW_MEM_DISABLE = 0100000,
23+
SW_ADDR_STOP = 040000,
24+
25+
// sw4
26+
KEY_MOTOR_ON = 01,
27+
KEY_MOTOR_OFF = 02,
28+
KEY_PTR_FEED = 04,
29+
KEY_PTP_FEED = 010,
30+
31+
// l0 MI right
32+
// l1 MI left
33+
// l2 MA
34+
// l3 IR
35+
// l4 PC
36+
// l5
37+
L5_POWER = 0400000,
38+
L5_REPEAT = 0200000,
39+
L5_MEM_DISABLE = 0100000,
40+
L5_ADDR_STOP = 0040000,
41+
L5_RUN = 0010000,
42+
L5_MC_STOP = 0004000,
43+
L5_PI_ON = 0002000,
44+
// pio 000177
45+
// l6
46+
// pih 037600
47+
// pir 000177
48+
};
49+
50+
typedef struct Panel6 Panel6;
51+
struct Panel6
52+
{
53+
int sw0;
54+
int sw1;
55+
int sw2;
56+
int sw3;
57+
int sw4;
58+
int lights0;
59+
int lights1;
60+
int lights2;
61+
int lights3;
62+
int lights4;
63+
int lights5;
64+
int lights6;
65+
};

0 commit comments

Comments
 (0)