GE-115 Emulator
An Emulator of the General Electrics GE-115 computer
pulse.c
Go to the documentation of this file.
1#include <stddef.h>
2#include <stdlib.h>
3#include <string.h>
4#include "ge.h"
5#include "signals.h"
6#include "log.h"
7
15static inline uint8_t odd_parity(uint8_t data)
16{
17 /* __builtin_popcount gives the number of set bits; if it's already
18 * odd we need parity=0; if even we need parity=1. */
19 return (__builtin_popcount(data) & 1) ? 0 : 1;
20}
21
22static void on_TO00(struct ge *ge) {
23 /* cpu fo. 115 */
24 ge->RIA0 = ge->RC00 && !ge->ALTO;
25 ge->RESI = ge->RC01;
26 ge->RIA2 = ge->RC02;
27 ge->RIA3 = ge->RC03;
28
29 ge->RETO = RES01(ge);
30
31 /* TODO: a "counter" with RAMO, RAMI should condition RIA0 */
32
33 ge_log(LOG_CYCLE, " async: RC00: %d RC01: %d RC02: %d RC03: %d ALTO: %d\n",
34 ge->RC00, ge->RC01, ge->RC02, ge->RC03, ge->ALTO);
35
36 ge_log(LOG_CYCLE, " sync: RIA0: %d RESI: %d RIA2: %d RIA3: %d\n",
37 ge->RIA0, ge->RESI, ge->RIA2, ge->RIA3);
38
39 ge_log(LOG_CYCLE, " -> RIUC: %d RES0: %d RES2: %d RES3: %d\n",
40 RIUC(ge), RES0(ge), RES2(ge), RES3(ge));
41
42 /* set NI to output the counting network.
43 * ("this occoursr alwas during the 1st phase", cpu fo.125) */
44
45 ge->kNI.ni1 = NS_CN1;
46 ge->kNI.ni2 = NS_CN2;
47 ge->kNI.ni3 = NS_CN3;
48 ge->kNI.ni4 = NS_CN4;
49
50 /* CO41 used to set from_zero is issued in TO10, so this looks
51 * like a reasonable place to reset this. CO40 (decreasing) must be reset
52 * here too, otherwise a stale "decreasing" from one decrement turns every
53 * later +1 advance into a -1 (now that the counting network honours it). */
56}
57
58static void on_TO10(struct ge *ge) {
59 ge->ffFA = ge->ffFI; /* cpu fo. 129 */
60 ge->rSA = NA_knot(ge); /* cpu fo. 128 */
61
62 /* save SA to emulate the future state network */
64
65 /* TODO: a "counter" with RAMO, RAMI should count (cpu fo. 115) */
66}
67
68static void on_TO11(struct ge *ge) {}
69static void on_TO15(struct ge *ge) {}
70
71static void on_TO19(struct ge *ge) {
72 /* intermediate fo. 9 B1*/
73 ge->RECE = 0;
74}
75
76static void on_TO20(struct ge *ge) {
77 ge->rBO = NO_knot(ge); /* cpu fo. 142, 126 */
78 ge->rVO = NO_knot(ge); /* cpu fo. 124, 125 */
79
80 ge->kNO.forcings = 0;
81 ge->kNO.force_mode = KNOT_FORCING_NONE;
82
83 ge->ACIC = 0; /* cpu fo. 99 */
84 ge->rRO = 0; /* cpu fo. 142 */
85}
86
87static void on_TO25(struct ge *ge) {}
88static void on_TO30(struct ge *ge) {}
89
90static void on_TO40(struct ge *ge) {
91 /* stub */
93 ge->kNI.ni1 = NS_CN1;
94 ge->kNI.ni2 = NS_CN2;
95 ge->kNI.ni3 = NS_CN3;
96 ge->kNI.ni4 = NS_CN4;
97 }
98}
99
100static void on_TO50(struct ge *ge) {
101 if (ge->PEC1_pending) {
102 ge->PEC1 = 1;
103 ge->PEC1_pending = 0;
104 }
105
106 /* not sure about the timing of memory ops
107 * read was previously done in TO65 with write, but
108 * it didn't work to implement the state CC for PERI.
109 * reading here seems to work in all known cases */
110 if (ge->memory_command == MC_READ) {
111 uint32_t size = ge->mem_size ? ge->mem_size : MEM_SIZE;
112
113 if (ge->rVO >= size) {
114 /* Address outside installed memory: raise INV ADD fault */
115 ge->inv_add = 1;
116 ge_log(LOG_STATES, "memory read: INV ADD rVO=%x >= size=%x\n",
117 ge->rVO, size);
118 } else {
119 ge->rRO = ge->mem[ge->rVO];
120 ge_log(LOG_STATES, "memory read: RO = mem[VO] = mem[%x] = %x\n",
121 ge->rVO, ge->rRO);
122
123 /* Parity check: only for locations that have been written.
124 * Cleared/uninitialised locations are not checked to avoid
125 * false MEM CHECK on startup. */
126 if (ge->mem_written[ge->rVO]) {
127 if (odd_parity(ge->mem[ge->rVO]) != ge->mem_parity[ge->rVO]) {
128 ge->mem_check = 1;
130 "memory read: MEM CHECK parity error at %x\n",
131 ge->rVO);
132 }
133 }
134 }
135
136 ge->memory_command = MC_NONE;
137 }
138}
139
140static void on_TO50_1(struct ge *ge) {
142 /* timing chart js1-js2-jie-ecc, fo. 32,
143 * also, display, fo. 17 */
144 ge->rBO = NO_knot(ge);
145 }
146
148
149 ge->kNO.forcings = 0;
150 ge->kNO.force_mode = KNOT_FORCING_NONE;
151}
152
153static void on_TO60(struct ge *ge) {}
154static void on_TO64(struct ge *ge) {}
155
156static void on_TO65(struct ge *ge) {
157 /* not sure about the timing of memory ops
158 * in cpu fo. 145, "write" seems to be at around TO65,
159 * and the "test k" fails if it's in TO50. */
160
161 if (ge->memory_command == MC_WRITE) {
162 uint32_t size = ge->mem_size ? ge->mem_size : MEM_SIZE;
163
164 if (ge->rVO >= size) {
165 /* Address outside installed memory: raise INV ADD fault, skip store */
166 ge->inv_add = 1;
167 ge_log(LOG_STATES, "memory write: INV ADD rVO=%x >= size=%x\n",
168 ge->rVO, size);
169 } else {
170 uint8_t parity = odd_parity(ge->rRO);
171
172 /* Console check-bit forcing: during a storage forcing from the
173 * console (rotary pos 8, RS_V1_SCR) with INCE inserted, AM08 is
174 * stored as the parity bit and the normal parity generation for
175 * AM07-00 is inhibited. This lets the operator key in a wrong
176 * check bit to exercise MEM CHECK detection. (CPU[4] ยง4.2, fo.36-37) */
178 parity = (ge->console_switches.AM >> 8) & 1;
179
180 ge->mem[ge->rVO] = ge->rRO;
181 ge->mem_parity[ge->rVO] = parity;
182 ge->mem_written[ge->rVO] = 1;
183 ge_log(LOG_STATES, "memory write: mem[VO] = RO = mem[%x] = %x (parity %d)\n",
184 ge->rVO, ge->rRO, parity);
185 }
186
187 ge->memory_command = MC_NONE;
188 }
189
190 /* "enables the second phase commands for count selection"
191 * (cpu fo. 142), not sure this is what it means */
194}
195
196static void on_TO70(struct ge *ge) {
197 if (ge->PEC1)
198 ge->RASI = 0;
199}
200
201static void on_TO80(struct ge *ge) {}
202
203static void on_TO89(struct ge *ge) {
204 ge->PEC1 = 0;
205 ge->PEC1_pending = 0;
206}
207
208static void on_TO90(struct ge *ge) {
209 /* TODO: check if ! is correct: PODIB should be PODI negated */
210 if (!ge->PODI)
211 ge->ACIC = 1; /* cpu fo. 99 */
212}
213
214static void on_TI05(struct ge *ge) {
215 /* TODO: check if ! is correct: PODIB should be PODI negated */
216 if (ge->PODI)
217 ge->ACIC = 1; /* cpu fo. 99 */
218}
219
220static void on_TI06(struct ge *ge) {}
221static void on_TI10(struct ge *ge) {}
222
223static on_pulse_cb pulse_cb[END_OF_STATUS] = {
224 on_TO00,
225 on_TO10,
226 on_TO11,
227 on_TO15,
228 on_TO19,
229 on_TO20,
230 on_TO25,
231 on_TO30,
232 on_TO40,
233 on_TO50,
234 on_TO50_1,
235 on_TO60,
236 on_TO64,
237 on_TO65,
238 on_TO70,
239 on_TO80,
240 on_TO89,
241 on_TO90,
242 on_TI05,
243 on_TI06,
244 on_TI10,
245};
246
247
248void pulse(struct ge *ge)
249{
250 if (pulse_cb[ge->current_clock]) {
252 }
253}
@ RS_V1_SCR
Definition console.h:16
#define MEM_SIZE
Definition ge.h:12
@ NS_CN1
Definition ge.h:75
@ NS_CN2
Definition ge.h:76
@ NS_CN4
Definition ge.h:78
@ NS_CN3
Definition ge.h:77
void(* on_pulse_cb)(struct ge *)
Definition ge.h:722
static uint16_t NO_knot(struct ge *ge)
Knot driven by P0, V1, V2, V4, L1, R1, V3 and L3.
Definition signals.h:170
static uint8_t NA_knot(struct ge *ge)
Knot driven by SO or SI.
Definition signals.h:239
void ge_log(ge_log_type type, const char *format,...)
Log message.
Definition log.c:122
@ LOG_STATES
State trace.
Definition log.h:21
@ LOG_CYCLE
Cycle attribution debug.
Definition log.h:25
static void on_TO70(struct ge *ge)
Definition pulse.c:196
static void on_TO90(struct ge *ge)
Definition pulse.c:208
static void on_TO89(struct ge *ge)
Definition pulse.c:203
static void on_TO50(struct ge *ge)
Definition pulse.c:100
static void on_TO20(struct ge *ge)
Definition pulse.c:76
static void on_TI10(struct ge *ge)
Definition pulse.c:221
static uint8_t odd_parity(uint8_t data)
Compute the odd-parity bit for an 8-bit data value.
Definition pulse.c:15
static void on_TO10(struct ge *ge)
Definition pulse.c:58
static void on_TO50_1(struct ge *ge)
Definition pulse.c:140
static void on_TI06(struct ge *ge)
Definition pulse.c:220
static void on_TO19(struct ge *ge)
Definition pulse.c:71
static void on_TO11(struct ge *ge)
Definition pulse.c:68
static void on_TI05(struct ge *ge)
Definition pulse.c:214
static on_pulse_cb pulse_cb[END_OF_STATUS]
Definition pulse.c:223
static void on_TO65(struct ge *ge)
Definition pulse.c:156
static void on_TO40(struct ge *ge)
Definition pulse.c:90
static void on_TO80(struct ge *ge)
Definition pulse.c:201
static void on_TO60(struct ge *ge)
Definition pulse.c:153
static void on_TO25(struct ge *ge)
Definition pulse.c:87
static void on_TO30(struct ge *ge)
Definition pulse.c:88
static void on_TO64(struct ge *ge)
Definition pulse.c:154
void pulse(struct ge *ge)
Definition pulse.c:248
static void on_TO00(struct ge *ge)
Definition pulse.c:22
static void on_TO15(struct ge *ge)
Definition pulse.c:69
Signals.
uint16_t INCE
Do not error-correct external units input.
Definition console.h:136
uint16_t AM
Forcing bits.
Definition console.h:155
struct ge_counting_network::cmds cmds
enum knot_ni_source ni4
Definition ge.h:89
enum knot_ni_source ni2
Definition ge.h:87
enum knot_ni_source ni1
Definition ge.h:86
enum knot_ni_source ni3
Definition ge.h:88
uint8_t forcings
Definition ge.h:52
enum ge_knot_no::@1 force_mode
The entire state of the emulated system, including registers, memory, peripherals and timings.
Definition ge.h:96
uint8_t ALTO
Stops internal cycles.
Definition ge.h:293
uint8_t ffFA
Special conditions register 2.
Definition ge.h:263
uint8_t future_state
Future state.
Definition ge.h:546
uint8_t inv_add
Invalid-address fault flag: set when rVO >= installed memory size.
Definition ge.h:581
uint8_t PODI
Slow delay line.
Definition ge.h:301
uint8_t mem_written[MEM_SIZE]
1 once a location has been written; prevents false MEM CHECK on cleared memory
Definition ge.h:572
enum ge_console_rotary register_selector
The current state of the console register rotary switch.
Definition ge.h:551
uint8_t RIA0
Synchronous CPU Cycle Request.
Definition ge.h:500
uint32_t mem_size
Installed memory size; 0 is treated as MEM_SIZE (full address space)
Definition ge.h:575
uint8_t RIA2
Synchronous Channel 2 Cycle Request.
Definition ge.h:514
uint8_t PEC1
Definition ge.h:420
uint8_t mem_check
Parity fault flag: set when a READ finds a parity mismatch on a previously-written location.
Definition ge.h:578
uint16_t rRO
Multipurpose 8+1 bit register.
Definition ge.h:171
struct ge_counting_network counting_network
Definition ge.h:590
struct ge_console_switches console_switches
The current state of the console switches.
Definition ge.h:556
uint8_t RIA3
Synchronous Channel 3 Cycle Request.
Definition ge.h:521
uint8_t ffFI
Special conditions register 1.
Definition ge.h:253
uint8_t RC00
Asynchronous CPU Cycle Request.
Definition ge.h:445
uint16_t rBO
Default operator.
Definition ge.h:188
uint8_t RC01
Asynchronous Channel 1 Cycle Request.
Definition ge.h:458
enum ge::@3 memory_command
uint8_t RECE
Selection Check Byte.
Definition ge.h:524
struct ge_knot_ni kNI
Knot driven by counting network, or by the UA to store the result of the operation.
Definition ge.h:164
uint8_t mem[MEM_SIZE]
The memory of the emulated system.
Definition ge.h:566
uint8_t RASI
Channel 1 in transfer.
Definition ge.h:404
uint8_t rSA
Future state configuration.
Definition ge.h:242
uint8_t PEC1_pending
Definition ge.h:421
uint8_t RC02
Asynchronous Channel 2 Cycle Request.
Definition ge.h:473
uint8_t RESI
Synchronous Channel 1 Cycle Request.
Definition ge.h:507
uint16_t rVO
Default memory addresser.
Definition ge.h:179
uint8_t RC03
Asynchronous Channel 3 Cycle Request.
Definition ge.h:488
uint8_t ACIC
Recycle delay line.
Definition ge.h:322
enum clock current_clock
Definition ge.h:98
uint8_t mem_parity[MEM_SIZE]
Stored odd-parity bit (1 bit per location) written alongside mem[].
Definition ge.h:569
uint8_t RETO
Definition ge.h:269
uint8_t TO50_did_CI32_or_CI33
Workaround for pulse TO50.
Definition ge.h:667
struct ge_knot_no kNO
Definition ge.h:158