summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Makefile18
-rwxr-xr-xasm.rb70
-rw-r--r--mem/fib.pal117
-rw-r--r--mem/hello.pal30
-rw-r--r--tool/p8bin2hex.c170
-rwxr-xr-xtool/pll.rb (renamed from pll.rb)0
6 files changed, 333 insertions, 72 deletions
diff --git a/Makefile b/Makefile
index 522a7d5..e180bc1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,26 @@
1SOURCES := $(shell find hdl sim -name \*.sv -o -name \*.cpp) 1SOURCES := $(shell find hdl sim -name \*.sv -o -name \*.cpp)
2HEADERS := $(shell find hdl -name \*.svh) 2HEADERS := $(shell find hdl -name \*.svh)
3MEMORIES := $(shell find mem -name \*.hex) 3MEMORIES := $(shell find mem -name \*.hex) $(addprefix build/, $(addsuffix .hex, $(basename $(shell find mem -name \*.pal))))
4QUARTUS := $(shell find altera tcl -name \*.cdf -o -name \*.sdc -o -name \*.tcl) 4QUARTUS := $(shell find altera tcl -name \*.cdf -o -name \*.sdc -o -name \*.tcl)
5 5
6OPTS ?= 6OPTS ?=
7 7
8sim: build/Vtop 8sim: build/Vtop $(MEMORIES)
9 $< 9 $<
10.PHONY: sim 10.PHONY: sim
11 11
12build/p8bin2hex: tool/p8bin2hex.c
13 @mkdir -p build
14 gcc -Wall -Werror -o $@ $<
15
16build/%.hex: build/%.bin build/p8bin2hex
17 build/p8bin2hex $< > $@
18
19build/%.bin: %.pal
20 @mkdir -p $(dir $@)
21 palbart $<
22 mv -f $*.bin $*.lst $(dir $@)
23
12build/Vtop: $(SOURCES) $(HEADERS) 24build/Vtop: $(SOURCES) $(HEADERS)
13 @rm -rf verilator 25 @rm -rf verilator
14 @mkdir -p build verilator 26 @mkdir -p build verilator
@@ -29,3 +41,5 @@ fpga: noncpu.sof
29clean: 41clean:
30 git clean -dfX 42 git clean -dfX
31.PHONY: clean 43.PHONY: clean
44
45.SECONDARY:
diff --git a/asm.rb b/asm.rb
deleted file mode 100755
index 6da40fb..0000000
--- a/asm.rb
+++ /dev/null
@@ -1,70 +0,0 @@
1#!/usr/bin/ruby -w
2
3OPCODES = {
4 "i" => 0x080,
5 "acc=" => 0x100,
6 "ladd" => 0x200,
7 "store" => 0x300,
8 "ifeq" => 0x400,
9 "jmp" => 0x500,
10 "ascii" => 0x600,
11 "cla" => 0x001,
12 "++acc" => 0x002,
13 "--acc" => 0x004,
14 "tx" => 0x040,
15 "rx" => 0x080,
16 "halt" => 0x000,
17 }
18
19Line = Struct.new(:opcode, :refs, :code)
20
21$labels = {}
22$code = []
23ARGF.each_line() do | line |
24 line.chomp!()
25 line.sub!(/^.*\/\/\s*/, "")
26 next unless line =~ /\S/
27 op = 0x000
28 refs = []
29 line.scan(/\S+/).each() do | word |
30 break if word =~ /^#/
31 if word =~ /^0(\d+)$/
32 op |= $1.to_i(8)
33 elsif word =~ /^-0(\d+)$/
34 op |= 0x100 - $1.to_i(8)
35 elsif word =~ /^(\d+)$/
36 op |= $1.to_i(10)
37 elsif word =~ /^-(\d+)$/
38 op |= 0x100 - $1.to_i(10)
39 elsif word =~ /^0x([0-9a-f]+)$/i
40 op |= $1.to_i(16)
41 elsif word =~ /^-0x([0-9a-f]+)$/i
42 op |= 0x100 - $1.to_i(16)
43 elsif OPCODES.key?(word)
44 op |= OPCODES[word]
45 elsif word =~ /^(.+):$/
46 $labels[$1] = $code.size()
47 else
48 refs << word
49 end
50 end
51 $code << Line.new(op, refs, line)
52end
53
54$code.each_with_index() do | line, i |
55 op = line.opcode
56 line.refs.each() do | ref |
57 if ref =~ /^@(.+)$/ and $labels.key?($1)
58 op |= $labels[$1]
59 elsif $labels.key?(ref)
60 target = $labels[ref] - (i + 1)
61 throw "Jump too far forward" if target > 0x7f
62 target += 0x80 if target < 0
63 throw "Jump too far backward" if target < 0
64 op |= target
65 else
66 throw "I don't understand #{ref.inspect()}"
67 end
68 end
69 $stdout.write("#{op.to_s(16).rjust(3, "0")} // #{line.code}\n")
70end
diff --git a/mem/fib.pal b/mem/fib.pal
new file mode 100644
index 0000000..6f56109
--- /dev/null
+++ b/mem/fib.pal
@@ -0,0 +1,117 @@
1 *200
2MAIN, CLA
3 TAD (-26)
4 DCA FIBN
5 DCA FIB0
6 IAC
7 DCA FIB1
8LOOP, CLA
9 TAD FIB0
10 JMS PUTN
11 CLA
12 TAD (054)
13 JMS PUTC
14 CLA
15 TAD FIB0
16 TAD FIB1
17 DCA FIB2
18 TAD FIB1
19 DCA FIB0
20 TAD FIB2
21 DCA FIB1
22 ISZ FIBN
23 JMP LOOP
24EXIT, HLT
25 CLA IAC
26 DCA FIB1
27 DCA FIB0
28 JMP MAIN
29PUTN, 0
30 JMS ITOA
31 CMA IAC
32 IAC
33 CMA IAC
34 DCA 10
35PUTNL, CLA
36 TAD I 10
37 SPA
38 JMP I PUTN
39 TAD (60)
40 JMS PUTC
41 JMP PUTNL
42PUTC, 0
43 TLS
44 TSF
45 JMP .-1
46 JMP I PUTC
47ITOA, 0
48 DCA ITOAV
49 DCA ITOAD
50 DCA ITOAD+1
51 DCA ITOAD+2
52 DCA ITOAD+3
53 TAD (-14)
54 DCA ITOAN
55ITOAL, CLL / LOOP OVER BINARY INPUT BITS
56 TAD ITOAD+3
57 JMS ITOA2X
58 DCA ITOAD+3
59 TAD ITOAD+2
60 JMS ITOA2X
61 DCA ITOAD+2
62 TAD ITOAD+1
63 JMS ITOA2X
64 DCA ITOAD+1
65 TAD ITOAD
66 JMS ITOA2X
67 DCA ITOAD
68 CLL
69 TAD ITOAV / SHIFT MSB OUT OF INPUT VALUE
70 RAL
71 DCA ITOAV
72 RAL
73 TAD ITOAD+3 / ADD SHIFTED-OUT MSB TO DECIMAL LSD
74 DCA ITOAD+3
75 ISZ ITOAN
76 JMP ITOAL / NEXT LOOP ITERATION
77 TAD (ITOAD)
78 DCA ITOAR
79ITOAJ, TAD I ITOAR
80 SZA
81 JMP ITOAX
82 ISZ ITOAR
83 TAD I ITOAR
84 SZA
85 JMP ITOAX
86 ISZ ITOAR
87 TAD I ITOAR
88 SZA
89 JMP ITOAX
90 ISZ ITOAR
91ITOAX, CLA
92 TAD ITOAR
93 JMP I ITOA
94ITOA2X, 0
95 RAL / PUTS 0 IN LINK
96 DCA ITOAT
97 TAD (-12)
98 TAD ITOAT / PUTS 1 IN LINK IF WRAPPED
99 SMA
100 DCA ITOAT
101 CLA
102 TAD ITOAT
103 JMP I ITOA2X
104FIB0, 0
105FIB1, 1
106FIB2, 0
107FIBN, -27
108ITOAD, 0 / OUTPUT DIGITS (MSD FIRST)
109 0
110 0
111 0
112 4000 / OUTPUT SENTINEL
113ITOAN, 0 / INPUT BITS LOOP COUNTER
114ITOAR, 0 / POINTER TO FIRST NONZERO DIGIT
115ITOAT, 0 / SCRATCHPAD FOR ITOA2X
116ITOAV, 0 / VALUE BEING CONVERTED (TEMPORARY)
117$
diff --git a/mem/hello.pal b/mem/hello.pal
new file mode 100644
index 0000000..437ccf9
--- /dev/null
+++ b/mem/hello.pal
@@ -0,0 +1,30 @@
1 *200
2START, CLA CLL
3 TAD HELLO
4 DCA 10
5LOOP, TAD I 10
6 SNA
7 JMP EXIT
8 TLS
9 TSF
10 JMP .-1
11 CLA
12 JMP LOOP
13EXIT, HLT
14 JMP START
15HELLO, .
16 "H
17 "e
18 "l
19 "l
20 "o
21 ",
22 "
23 "w
24 "o
25 "r
26 "l
27 "d
28 "!
29 0
30$
diff --git a/tool/p8bin2hex.c b/tool/p8bin2hex.c
new file mode 100644
index 0000000..8d28d19
--- /dev/null
+++ b/tool/p8bin2hex.c
@@ -0,0 +1,170 @@
1/*
2 * PDP-8 format converter.
3 *
4 * Usage: p8bin2hex tape.bin > tape.hex
5 *
6 * Assumes tape.bin is a SIMH-compatible paper tape image in "BIN" or "RIM"
7 * formats.
8 *
9 * RIM format:
10 * 10.000.000 leader/trailer (at least an inch of these)
11 * 01.aaa.aaa address hi (bits 5:0 contain address 11:6)
12 * 00.aaa.aaa address lo (bits 5:0 contain address 5:0)
13 * 00.xxx.xxx data hi (bits 5:0 contain data 11:6)
14 * 00.xxx.xxx data lo (bits 5:0 contain data 5:0)
15 * <repeat any number of [address, data] pairs>
16 *
17 * BIN format:
18 * 10.000.000 leader/trailer (at least an inch of these)
19 * 11.011.000 "field" (bits 6:4 specify address 14:12)
20 * 01.000.010 origin hi bits: bits 5:0 contain origin 11:6
21 * 00.011.100 origin lo bits: bits 5:0 contain origin 5:0
22 * 00.xxx.xxx data hi bits: bits 5:0 contain data word 11:6
23 * 00.xxx.xxx data lo bits: bits 5:0 contain data word 5:0
24 * <repeat any number of [origin, data+] sequences>
25 * 00.xxx.xxx chucksum hi - sum of all data and origin frames, but
26 * 00.xxx.xxx chucksum lo - excluding field and leader/trailer
27 *
28 * Some tapes may contain assembler error messages. These are are text
29 * delimited by 0377 bytes. The BIN loader ignores bytes from starting
30 * at any 0377 byte, until another 0377 byte is seen.
31 */
32
33#include <inttypes.h>
34#include <stdio.h>
35#include <stdlib.h>
36
37uint16_t mem[32768];
38
39int
40load(FILE *fp)
41{
42 enum { Addr, Data, Leader, Fetch, Skip , Start } s = Start;
43 int c = 0, n, v = 0;
44 uint16_t a = 0, d = 0, t = 0, u = 0;
45 for (n = 0; (c = getc(fp)) != EOF; ++n) {
46 switch (s) {
47 case Addr:
48 u += c;
49 a |= c;
50 fprintf(stderr, " %04o: address %06o\n", c, a & 077777);
51 s = Fetch;
52 break;
53 case Data:
54 u += c;
55 d |= 0x8000 | c;
56 /* fprintf(stderr, " %04o: data %05o\n", c, d & 07777); */
57 fprintf(stderr, " %04o", c);
58 s = Fetch;
59 break;
60 case Fetch:
61 fetch:
62 if (c == 0200) {
63 if ((d & 0x8000) != 0) {
64 if ((d & 07777) != (t & 07777))
65 fprintf(stderr, "\nbad checksum %05o\n", t & 07777);
66 else
67 v = 1, fprintf(stderr, "\nvalid checksum %05o\n", t & 07777);
68 }
69 fprintf(stderr, " %04o", c);
70 goto leadout;
71 }
72 t += u;
73 u = 0;
74 if (d & 0x8000) {
75 fprintf(stderr, ": mem[%06o]=%05o\n", a & 077777, d & 07777);
76 mem[a] = d & 07777;
77 a = (a & ~07777) | ((a + 1) & 07777);
78 d = 0;
79 }
80 fprintf(stderr, " %04o", c);
81 if ((c & 0300) == 0000) {
82 u = c;
83 d = (c & 077) << 6;
84 s = Data;
85 break;
86 }
87 if ((c & 0300) == 0100) {
88 u = c;
89 a = (a & ~07777) | (c & 077) << 6;
90 s = Addr;
91 break;
92 }
93 if ((c & 0307) == 0300) {
94 a = ((c & 0070) << 9) | (a & 07777);
95 fprintf(stderr, ": field %o address %06o\n", (c & 070) >> 3, a & 077777);
96 break;
97 }
98 if (c == 0377) {
99 fprintf(stderr, ": skipping: ");
100 s = Skip;
101 break;
102 }
103 fprintf(stderr, ": unknown byte at %d\n", n);
104 break;
105 case Leader:
106 leader:
107 if (c != 0200) {
108 fprintf(stderr, ": end leader\n");
109 s= Fetch;
110 goto fetch;
111 }
112 fprintf(stderr, " %04o", c);
113 break;
114 case Skip:
115 if (c == 0377) {
116 s = Fetch;
117 putchar('\n');
118 } else {
119 putchar(c);
120 }
121 break;
122 case Start:
123 if (c == 0200) {
124 s = Leader;
125 goto leader;
126 }
127 fprintf(stderr, " %04o", c);
128 break;
129 }
130 }
131 leadout:
132 while ((c = getc(fp)) != EOF)
133 fprintf(stderr, " %04o", c);
134 putchar('\n');
135 return v;
136}
137
138void
139dump()
140{
141 printf("// Generated by p8bin2hex");
142 unsigned int nextaddr = -1;
143 for (uint_fast32_t a = 0; a < 32768; ++a) {
144 if (mem[a] == 0) continue;
145 if (nextaddr != a)
146 printf("\n@%x", (unsigned int)a);
147 nextaddr = a + 1;
148 printf(" %03x", mem[a]);
149 }
150 printf("\n");
151}
152
153int
154main(int argc, char *argv[])
155{
156 if (argc != 2) {
157 fprintf(stderr, "usage: p8 filename.bin\n");
158 exit(EXIT_FAILURE);
159 }
160 FILE *fp = fopen(argv[1], "rb");
161 if (!fp) {
162 perror(argv[1]);
163 exit(EXIT_FAILURE);
164 }
165 if (!load(fp))
166 exit(EXIT_FAILURE);
167 fclose(fp);
168 dump();
169 exit(EXIT_SUCCESS);
170}
diff --git a/pll.rb b/tool/pll.rb
index 49464d4..49464d4 100755
--- a/pll.rb
+++ b/tool/pll.rb