summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Blake Kongslie2022-10-16 16:24:49 -0700
committerJulian Blake Kongslie2022-10-16 16:24:49 -0700
commita59407a215d6112c2e20b1a746b33742209e5f87 (patch)
tree64ba2fc875ad1985be10d7b8e6d23deb39d49b3e
parentStrip the leader from palbart output (diff)
downloadbiggolf-a59407a215d6112c2e20b1a746b33742209e5f87.tar.xz
Support for log-based event model
Diffstat (limited to '')
-rw-r--r--io/event.h18
-rw-r--r--io/model.cpp49
-rw-r--r--io/model.h15
-rw-r--r--isa/checker.cpp22
-rw-r--r--isa/checker.h6
-rw-r--r--isa/decode.cpp20
-rw-r--r--isa/isa.h12
-rw-r--r--main.cpp12
8 files changed, 126 insertions, 28 deletions
diff --git a/io/event.h b/io/event.h
new file mode 100644
index 0000000..02f3fab
--- /dev/null
+++ b/io/event.h
@@ -0,0 +1,18 @@
1#pragma once
2
3#include <map>
4
5#include "isa/isa.h"
6
7struct event {
8 ctlreg reg;
9 unsigned int mask;
10 unsigned int value;
11 event(ctlreg reg, unsigned int value, unsigned int mask=~0)
12 : reg(reg)
13 , mask(mask)
14 , value(value)
15 { }
16};
17
18typedef std::multimap<std::uint64_t, event> event_log;
diff --git a/io/model.cpp b/io/model.cpp
new file mode 100644
index 0000000..dd55ce6
--- /dev/null
+++ b/io/model.cpp
@@ -0,0 +1,49 @@
1#include <array>
2#include <cstdint>
3#include <iostream>
4#include <utility>
5
6#include "io/model.h"
7#include "isa/isa.h"
8
9bool iomodel::interact(std::array<unsigned int, NUM_CTLREGS> &ctlregs) {
10 auto [ebegin, eend] = log.equal_range(time);
11 for (auto e = ebegin; e != eend; ++e) {
12 auto &r = ctlregs[e->second.reg];
13 r &= ~e->second.mask;
14 r |= e->second.value;
15 }
16
17 ++time;
18
19 if (ctlregs[TT_OUTPUT] & 0x100) {
20 // PDP-8 doesn't really have support for 8-bit output, this is Jules' contribution
21 std::cout << (char)((ctlregs[TT_OUTPUT] & 0xff) ^ 0x80);
22 ctlregs[TT_OUTPUT] &= ~0x1ff;
23 log.emplace(time + TT_OUTPUT_DELAY, event(TT_OUTPUT, 0x200, 0));
24 }
25
26 bool interrupt = false;
27 if (ctlregs[INT_ENABLE] & 1) {
28 if (ctlregs[TT_INPUT_INT_ENABLE]) {
29 if (ctlregs[TT_INPUT] & 0x100)
30 interrupt = true;
31 }
32 if (ctlregs[TT_OUTPUT_INT_ENABLE]) {
33 if (!(ctlregs[TT_OUTPUT] & 0x400) && (ctlregs[TT_OUTPUT] & 0x200))
34 interrupt = true;
35 }
36 }
37
38 if (interrupt) {
39 ctlregs[DATA_INSTRUCTION_FIELD_SAVED] = ctlregs[DATA_INSTRUCTION_FIELD_BUFFER];
40 ctlregs[DATA_INSTRUCTION_FIELD_BUFFER] = 0;
41 ctlregs[HALTED] = 0;
42 ctlregs[INT_ENABLE] = 0;
43 ctlregs[TT_OUTPUT] = (ctlregs[TT_OUTPUT] & 0x200) * 3;
44 } else {
45 ctlregs[INT_ENABLE] = (ctlregs[INT_ENABLE] >> 1) * 3;
46 }
47
48 return interrupt;
49};
diff --git a/io/model.h b/io/model.h
new file mode 100644
index 0000000..86fb086
--- /dev/null
+++ b/io/model.h
@@ -0,0 +1,15 @@
1#pragma once
2
3#include <array>
4#include <cstdint>
5
6#include "io/event.h"
7#include "isa/isa.h"
8
9struct iomodel {
10 static constexpr unsigned int TT_OUTPUT_DELAY = 100;
11
12 event_log log;
13 std::uint64_t time = 0;
14 bool interact(std::array<unsigned int, NUM_CTLREGS> &ctlregs);
15};
diff --git a/isa/checker.cpp b/isa/checker.cpp
index 1919bd1..7bca5c9 100644
--- a/isa/checker.cpp
+++ b/isa/checker.cpp
@@ -4,16 +4,17 @@
4#include "isa/isa.h" 4#include "isa/isa.h"
5 5
6void checker::execute() { 6void checker::execute() {
7 assert(!halted); 7 bool interrupt = system.interact(ctlregs);
8 auto int_enable_delay = ctlregs[INT_ENABLE] >> 1; 8
9 if (ctlregs[INT_ENABLE] & 1) { 9 if (ctlregs[HALTED])
10 // check for interrupt 10 return;
11 } 11
12 ctlregs[INT_ENABLE] = (int_enable_delay << 1) | int_enable_delay;
13 inst = decode(ctlregs[DATA_INSTRUCTION_FIELD_BUFFER], 12 inst = decode(ctlregs[DATA_INSTRUCTION_FIELD_BUFFER],
14 pc, 13 pc,
15 mem.fetch(pc)); 14 mem.fetch(pc),
15 interrupt);
16 auto next_pc = inst.next_pc; 16 auto next_pc = inst.next_pc;
17
17 if (inst.need_indirect_load) { 18 if (inst.need_indirect_load) {
18 auto addr = mem.fetch(inst.init_address.value()); 19 auto addr = mem.fetch(inst.init_address.value());
19 if (inst.need_autoinc_store) 20 if (inst.need_autoinc_store)
@@ -22,8 +23,10 @@ void checker::execute() {
22 } else { 23 } else {
23 assert(!inst.need_autoinc_store); 24 assert(!inst.need_autoinc_store);
24 } 25 }
26
25 if (inst.need_exec_load) 27 if (inst.need_exec_load)
26 inst.data = mem.fetch(inst.final_address.value()); 28 inst.data = mem.fetch(inst.final_address.value());
29
27 if (inst.need_read_acc) 30 if (inst.need_read_acc)
28 inst.acc = acc; 31 inst.acc = acc;
29 if (inst.need_read_link) 32 if (inst.need_read_link)
@@ -32,7 +35,9 @@ void checker::execute() {
32 inst.mq = mq; 35 inst.mq = mq;
33 if (inst.read_ctlreg.has_value()) 36 if (inst.read_ctlreg.has_value())
34 inst.ctlval = ctlregs[*inst.read_ctlreg]; 37 inst.ctlval = ctlregs[*inst.read_ctlreg];
38
35 inst.execute(); 39 inst.execute();
40
36 if (inst.need_write_acc) 41 if (inst.need_write_acc)
37 acc = inst.acc.value(); 42 acc = inst.acc.value();
38 if (inst.need_write_link) 43 if (inst.need_write_link)
@@ -41,9 +46,10 @@ void checker::execute() {
41 mq = inst.mq.value(); 46 mq = inst.mq.value();
42 if (inst.write_ctlreg.has_value()) 47 if (inst.write_ctlreg.has_value())
43 ctlregs[*inst.write_ctlreg] = inst.ctlval.value(); 48 ctlregs[*inst.write_ctlreg] = inst.ctlval.value();
49
44 if (inst.need_exec_store) 50 if (inst.need_exec_store)
45 mem.store(inst.final_address.value(), inst.data.value()); 51 mem.store(inst.final_address.value(), inst.data.value());
52
46 assert(inst.next_pc == next_pc || inst.possibly_redirects); 53 assert(inst.next_pc == next_pc || inst.possibly_redirects);
47 pc = inst.next_pc; 54 pc = inst.next_pc;
48 halted = inst.halt;
49} 55}
diff --git a/isa/checker.h b/isa/checker.h
index d70997f..332c483 100644
--- a/isa/checker.h
+++ b/isa/checker.h
@@ -3,6 +3,7 @@
3#include <array> 3#include <array>
4#include <map> 4#include <map>
5 5
6#include "io/model.h"
6#include "isa/isa.h" 7#include "isa/isa.h"
7 8
8struct funcmem { 9struct funcmem {
@@ -41,10 +42,11 @@ struct checker {
41 unsigned int mq = 0; 42 unsigned int mq = 0;
42 unsigned int pc = 00200; 43 unsigned int pc = 00200;
43 std::array<unsigned int, NUM_CTLREGS> ctlregs; 44 std::array<unsigned int, NUM_CTLREGS> ctlregs;
45 iomodel &system;
44 instruction_context inst; 46 instruction_context inst;
45 bool halted = false;
46 funcmem mem; 47 funcmem mem;
47 checker() 48 checker(iomodel &system)
49 : system(system)
48 { 50 {
49 ctlregs.fill(0); 51 ctlregs.fill(0);
50 } 52 }
diff --git a/isa/decode.cpp b/isa/decode.cpp
index 1979982..d24632b 100644
--- a/isa/decode.cpp
+++ b/isa/decode.cpp
@@ -2,15 +2,21 @@
2 2
3#include "isa/isa.h" 3#include "isa/isa.h"
4 4
5instruction_context decode(unsigned int dfifb, unsigned int pc, unsigned int bits) 5instruction_context decode(unsigned int dfifb, unsigned int pc, unsigned int bits, bool interrupt)
6{ 6{
7 instruction_context inst;
8
9 auto df = dfifb >> 3; 7 auto df = dfifb >> 3;
10 auto ifb = dfifb & 00007; 8 auto ifb = dfifb & 00007;
11 9
10 instruction_context inst;
12 inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777); 11 inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777);
13 12
13 if (interrupt) {
14 bits = 04000;
15 assert(df == 0);
16 assert(ifb == 0);
17 inst.next_pc = pc;
18 }
19
14 switch (bits >> 9) { 20 switch (bits >> 9) {
15 case 0: // AND 21 case 0: // AND
16 inst.need_exec_load = true; 22 inst.need_exec_load = true;
@@ -121,6 +127,8 @@ instruction_context decode(unsigned int dfifb, unsigned int pc, unsigned int bit
121 inst.need_read_acc = sma || sza; 127 inst.need_read_acc = sma || sza;
122 inst.need_read_link = snl; 128 inst.need_read_link = snl;
123 inst.need_write_acc = cla; 129 inst.need_write_acc = cla;
130 if (hlt)
131 inst.write_ctlreg = HALTED;
124 inst.possibly_redirects = true; 132 inst.possibly_redirects = true;
125 inst.ef = [cla, sma, sza, snl, osr, hlt](auto &ctx) { 133 inst.ef = [cla, sma, sza, snl, osr, hlt](auto &ctx) {
126 bool skip = false; 134 bool skip = false;
@@ -129,7 +137,7 @@ instruction_context decode(unsigned int dfifb, unsigned int pc, unsigned int bit
129 if (snl && ctx.link.value()) skip = true; 137 if (snl && ctx.link.value()) skip = true;
130 if (cla) ctx.acc = 0; 138 if (cla) ctx.acc = 0;
131 assert(!osr); 139 assert(!osr);
132 if (hlt) ctx.halt = true; 140 if (hlt) ctx.ctlval = 1;
133 if (skip) 141 if (skip)
134 ctx.next_pc = (ctx.next_pc & 070000) | ((ctx.next_pc + 1) & 007777); 142 ctx.next_pc = (ctx.next_pc & 070000) | ((ctx.next_pc + 1) & 007777);
135 }; 143 };
@@ -143,6 +151,8 @@ instruction_context decode(unsigned int dfifb, unsigned int pc, unsigned int bit
143 inst.need_read_acc = spa || sna; 151 inst.need_read_acc = spa || sna;
144 inst.need_read_link = szl; 152 inst.need_read_link = szl;
145 inst.need_write_acc = cla; 153 inst.need_write_acc = cla;
154 if (hlt)
155 inst.write_ctlreg = HALTED;
146 inst.possibly_redirects = true; 156 inst.possibly_redirects = true;
147 inst.ef = [cla, spa, sna, szl, osr, hlt](auto &ctx) { 157 inst.ef = [cla, spa, sna, szl, osr, hlt](auto &ctx) {
148 bool skip = true; 158 bool skip = true;
@@ -151,7 +161,7 @@ instruction_context decode(unsigned int dfifb, unsigned int pc, unsigned int bit
151 if (szl && ctx.link.value()) skip = false; 161 if (szl && ctx.link.value()) skip = false;
152 if (cla) ctx.acc = 0; 162 if (cla) ctx.acc = 0;
153 assert(!osr); 163 assert(!osr);
154 if (hlt) ctx.halt = true; 164 if (hlt) ctx.ctlval = 1;
155 if (skip) 165 if (skip)
156 ctx.next_pc = (ctx.next_pc & 070000) | ((ctx.next_pc + 1) & 007777); 166 ctx.next_pc = (ctx.next_pc & 070000) | ((ctx.next_pc + 1) & 007777);
157 }; 167 };
diff --git a/isa/isa.h b/isa/isa.h
index 11a8db2..bea484e 100644
--- a/isa/isa.h
+++ b/isa/isa.h
@@ -3,19 +3,20 @@
3#include <functional> 3#include <functional>
4#include <optional> 4#include <optional>
5 5
6#include "infra/pipetrace.h"
7
8enum ctlreg { 6enum ctlreg {
9 DATA_INSTRUCTION_FIELD_BUFFER, // (df << 3) | if_buffer 7 DATA_INSTRUCTION_FIELD_BUFFER, // (df << 3) | if_buffer
10 DATA_INSTRUCTION_FIELD_SAVED, // (df_saved << 3) | if_saved 8 DATA_INSTRUCTION_FIELD_SAVED, // (df_saved << 3) | if_saved
9 HALTED,
11 INT_ENABLE, // (int_enable_delay << 1) | int_enable 10 INT_ENABLE, // (int_enable_delay << 1) | int_enable
11 TT_INPUT, // (tti_flag << 8) | tti_buffer
12 TT_INPUT_INT_ENABLE,
13 TT_OUTPUT, // {tto_flag_old, tto_flag, tto_tx, tto_data}
14 TT_OUTPUT_INT_ENABLE,
12 15
13 NUM_CTLREGS, 16 NUM_CTLREGS,
14}; 17};
15 18
16struct instruction_context { 19struct instruction_context {
17 infra::transaction transaction;
18
19 // Known statically at decode time 20 // Known statically at decode time
20 bool need_indirect_load = false; // final_address = mem[init_address] 21 bool need_indirect_load = false; // final_address = mem[init_address]
21 bool need_autoinc_store = false; // mem[init_address] += 1 22 bool need_autoinc_store = false; // mem[init_address] += 1
@@ -43,7 +44,6 @@ struct instruction_context {
43 std::optional<unsigned int> acc; 44 std::optional<unsigned int> acc;
44 std::optional<bool> link; 45 std::optional<bool> link;
45 std::optional<unsigned int> mq; 46 std::optional<unsigned int> mq;
46 bool halt = false;
47}; 47};
48 48
49instruction_context decode(unsigned int df, unsigned int pc, unsigned int bits); 49instruction_context decode(unsigned int df, unsigned int pc, unsigned int bits, bool interrupt);
diff --git a/main.cpp b/main.cpp
index 64d1a04..b587ce4 100644
--- a/main.cpp
+++ b/main.cpp
@@ -30,10 +30,8 @@ int load_program(checker &checker, const std::uint8_t *program) {
30 address = ((b1 & 0077) << 6) | *program++; 30 address = ((b1 & 0077) << 6) | *program++;
31 } else if ((b1 & 0300) == 0000) { 31 } else if ((b1 & 0300) == 0000) {
32 seen_non_leader = true; 32 seen_non_leader = true;
33 if (data.has_value()) { 33 if (data.has_value())
34 //std::cout << fmt::format("mem[{:06o}] = {:04o}\n", data->first, data->second);
35 checker.mem.store(data->first, data->second); 34 checker.mem.store(data->first, data->second);
36 }
37 auto a = field | address++; 35 auto a = field | address++;
38 auto d = ((b1 & 0077) << 6) | *program++; 36 auto d = ((b1 & 0077) << 6) | *program++;
39 data = std::make_pair(a, d); 37 data = std::make_pair(a, d);
@@ -58,7 +56,8 @@ int main(int argc, const char *argv[]) {
58 return 1; 56 return 1;
59 } 57 }
60 58
61 checker checker; 59 iomodel system;
60 checker checker(system);
62 61
63 for (--argc, ++argv; argc; --argc, ++argv) { 62 for (--argc, ++argv; argc; --argc, ++argv) {
64 auto program = programs.at(argv[0]); 63 auto program = programs.at(argv[0]);
@@ -66,10 +65,9 @@ int main(int argc, const char *argv[]) {
66 return err; 65 return err;
67 } 66 }
68 67
69 while (!checker.halted) { 68 while (true) {
70 std::cout << fmt::format("{:04o}: ", checker.pc); 69 std::cout << fmt::format("{:9} @{:04o} {:01o}:{:04o}:{:04o}\n", system.time, checker.pc, checker.link, checker.acc, checker.mq);
71 checker.execute(); 70 checker.execute();
72 std::cout << fmt::format("link={:01o} acc={:04o} mq={:04o}\n", checker.link, checker.acc, checker.mq);
73 } 71 }
74 72
75 return 0; 73 return 0;