GE-115 Emulator
An Emulator of the General Electrics GE-115 computer
ge.c
Go to the documentation of this file.
1 #include <stdint.h>
2 #include <stddef.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include "ge.h"
6 #include "signals.h"
7 #include "msl.h"
8 #include "console_socket.h"
9 #include "peripherical.h"
10 #include "log.h"
11 
12 #define MAX_PROGRAM_STORAGE_WORDS 129
13 
14 void ge_init(struct ge *ge)
15 {
16  memset(ge, 0, sizeof(*ge));
17  ge->halted = 1;
18  ge->powered = 1;
20 
21  ge->ST3.name = "ST3";
22  ge->ST4.name = "ST4";
23 }
24 
25 void ge_clear(struct ge *ge)
26 {
27  ge->AINI = 0;
28  ge->ALAM = 0;
29  ge->PODI = 0;
30  ge->ADIR = 0;
31  ge->ACIC = 1;
32 
33  /* After the powering on of the machine the timing starts pressing the
34  * "CLEAR" switch (cpu fo. 99). */
35  ge->halted = 0;
36 
37  /* (One of) the possible set conditions (is): or with
38  * "CLEAR" and.. (cpu fo. 98) */
39  ge->ALTO = 1;
40 
41  /* By pressing "CLEAR" tje FF RC01, RC02, RC03 are reset and the FF
42  * RC00 is set. (cpu fo. 115) */
43  ge->RC00 = 1;
44  ge->RC01 = 0;
45  ge->RC02 = 0;
46  ge->RC03 = 0;
47 }
48 
49 int ge_load_program(struct ge *ge, uint8_t *program, uint8_t size)
50 {
51  if (program == NULL && size != 0)
52  return -1;
53 
54  if (size > MAX_PROGRAM_STORAGE_WORDS)
56 
57  /* simulate the loading for now */
58  memcpy(ge->mem, program, size);
59  return 0;
60 }
61 
62 void ge_load(struct ge *ge)
63 {
64  /* When pressing LOAD button, AINI is set. If AINI is set, the state 80
65  * (initialitiation) goes to state c8, starting the loading of the program
66  * (of max 129 words) from one of the peripherc unit. */
67 
68  /* set AINI FF to 1 (pag. 96) */
69  ge->AINI = 1;
70 }
71 
72 void ge_load_1(struct ge * ge)
73 {
74  /* It is possible to choose one between the two units thus prepared
75  * positioning the operating console switch LOAD1/LOAD2 (The possible
76  * choices are: Conn.2/Conn.3; Conn.4/Conn.3; Conn.2/Conn.4).
77  *
78  * (cpu fo. 43) */
79 
80  /* from the previous manual excerpt, ,i would have expected ALOI = 0t to
81  * be LOAD1 and ALOI = 1 to be LOAD2, but running the initial load tests,
82  * ALOI = 1 will result in the machine using the 0x80 unit name, which is
83  * connector 2, while ALOI = 0 results in a 0x00 unit name, which is
84  * connector 3. */
85 
86  ge->ALOI = 1;
87 }
88 
89 void ge_load_2(struct ge * ge)
90 {
91  ge->ALOI = 0;
92 }
93 
94 void ge_start(struct ge *ge)
95 {
96  /* according to the cpu documents, we should set the flipflop ARES here to
97  * implement the initial loading of 80 into SO, however with the current
98  * implementation it's not needed */
99 
100  ge->ALTO = 0; /* cpu fo. 97 */
101 }
102 
103 static void ge_print_well_known_states(uint8_t state) {
104  const char *name;
105  switch (state) {
106  case 0x00: name = "- Display sequence"; break;
107  case 0x08: name = "- Forcing sequence"; break;
108  case 0x64:
109  case 0x65: name = "- Beta Phase"; break;
110  case 0x80: name = "- Initialitiation"; break;
111  case 0xE2:
112  case 0xE3: name = "- Alpha Phase"; break;
113  case 0xF0: name = "- Interruption"; break;
114  default: name = "";
115  }
116 
117  ge_log(LOG_STATES, "Running state %02x %s\n", state, name);
118 }
119 
120 const char *ge_clock_name(enum clock c)
121 {
122  switch (c) {
123  #define X(name) case name : return #name ;
125  #undef X
126  }
127 
128  return "";
129 }
130 
132 {
133  if (ge_log_enabled(LOG_REGS_V)) return;
135  "SO: %02x SA: %02x PO: %04x RO: %04x BO: %04x FO: %04x - "
136  "V1: %04x V2: %04x V3: %04x V4: %04x - "
137  "L1: %04x L2: %04x L3 : %04x\n",
138  ge->rSO, ge->rSA, ge->rPO, ge->rRO, ge->rBO, ge->rFO,
139  ge->rV1, ge->rV2, ge->rV3, ge->rV4,
140  ge->rL1, ge->rL2, ge->rL3);
141 }
142 
144 {
146  "%s: "
147  "SO: %02x SA: %02x PO: %04x RO: %04x BO: %04x FO: %04x - "
148  "NO: %02x NI: %02x - "
149  "FA: %02x FI: %02x - "
150  "V1: %04x V2: %04x V3: %04x V4: %04x - "
151  "L1: %04x L2: %04x L3 : %04x\n",
153  ge->rSO, ge->rSA, ge->rPO, ge->rRO, ge->rBO, ge->rFO,
154  NO_knot(ge), NI_knot(ge),
155  ge->ffFA, ge->ffFI,
156  ge->rV1, ge->rV2, ge->rV3, ge->rV4,
157  ge->rL1, ge->rL2, ge->rL3);
158 }
159 
160 void ge_clock_increment(struct ge* ge)
161 {
162  ge->current_clock++;
163  if (ge->current_clock == END_OF_STATUS)
164  ge->current_clock = TO00;
165 }
166 
167 uint8_t ge_clock_is_first(struct ge* ge)
168 {
169  return ge->current_clock == TO00;
170 }
171 
172 uint8_t ge_clock_is_last(struct ge* ge)
173 {
174  return ge->current_clock == (END_OF_STATUS - 1);
175 }
176 
177 int ge_run_pulse(struct ge *ge)
178 {
179  int r;
180  struct msl_timing_state *state;
181 
182  if (ge_clock_is_first(ge)) {
183  r = ge_peri_on_clock(ge);
184  if (r != 0)
185  return r;
186 
187  /* poll the connectors and try to set up the cpu state.
188  * should this be here? */
190  }
191 
192  /* Execute common pulse machine logic */
193  pulse(ge);
194 
195  /* Execute peripherals pulse callbacks */
196  r = ge_peri_on_pulses(ge);
197  if (r != 0)
198  return r;
199 
200  /* Execute the commands from the timing charts */
201  state = msl_get_state(ge->rSA);
202 
203  /* The state to execute gets loaded in SA at TO10 */
204  if (ge->current_clock == TO10)
206 
207  if (!state) {
208  ge_log(LOG_ERR, "no timing charts found for state %02X\n", ge->rSA);
209  return 1;
210  }
211 
212  msl_run_state(ge, state);
213 
214  if (ge_clock_is_last(ge)) {
217  }
218 
220  return 0;
221 }
222 
223 int ge_run_cycle(struct ge *ge)
224 {
225  do {
226  int r = ge_run_pulse(ge);
227  if (r)
228  return r;
229  } while (!ge_clock_is_first(ge));
230 
231  return 0;
232 }
233 
234 int ge_deinit(struct ge *ge)
235 {
237  return 0;
238 }
239 
241 {
242  if (RA101(ge)) {
243  ge_log(LOG_READER, "RA101: signaling incoming data\n");
244  ge->RC01 = 1;
245  }
246 }
247 
248 void fsn_last_clock(struct ge *ge)
249 {
250  /* at the end of a cycle attributed to the CPU, provided RICI
251  * is not active and the rotary switch is in normal position,
252  * the future status network is stored in SO. (cpu fo. 127) */
253  if (ge->RIA0 && !ge->console_switches.RICI) {
254  ge_log(LOG_FUTURE, "last clock cpu, %02x in SO\n", ge->future_state);
255  ge->rSO = ge->future_state;
256  } else {
257  ge_log(LOG_FUTURE, "last clock cpu, not setting future state %02x in SO becuse RIA0 %d and !RICI %d\n", ge->future_state, ge->RIA0, !ge->console_switches.RICI);
258  }
259 
260  /* after the end of a cpu work cycle, (ALTO / ALS71=1) is set if
261  * the PAPA switch is inserted, or if the rotary switch is neither
262  * in the normal position, nor in position 8 for recording in
263  * memory ALSOA=0) (cpu fo. 98)
264  */
265  uint8_t is_papa = ge->console_switches.PAPA;
266  uint8_t is_norm = ge->register_selector == RS_NORM;
267  uint8_t is_scr = ge->register_selector == RS_V1_SCR;
268  ge_log(LOG_FUTURE, " papa: %d, norm: %d, scr: %d ==> %d\n", is_papa, is_norm, is_scr, ge->RIA0 && (is_papa || !(is_norm || is_scr)));
269 
270  if (ge->RIA0 && (is_papa || !(is_norm || is_scr)))
271  ge->ALTO = 1;
272 
273  /* after the execution of a channel 2 cycle, load the first
274  * 4 bits of the future status network in SI. (cpu fo. 127) */
275  if (ge->RIA2) {
276  ge_log(LOG_FUTURE, "last clock ch2, %02x in SI\n", ge->future_state);
277  ge->rSI = ge->future_state;
278  }
279 
280 }
@ RS_V1_SCR
Definition: console.h:16
@ RS_NORM
Definition: console.h:18
int ge_deinit(struct ge *ge)
Deinitialize the emulator.
Definition: ge.c:234
void ge_load_1(struct ge *ge)
Emulate the press of the "load 1" button in the console.
Definition: ge.c:72
void ge_print_registers_nonverbose(struct ge *ge)
Definition: ge.c:131
#define MAX_PROGRAM_STORAGE_WORDS
Definition: ge.c:12
static void ge_print_well_known_states(uint8_t state)
Definition: ge.c:103
void ge_clear(struct ge *ge)
Emulate the press of the "clear" button in the console.
Definition: ge.c:25
int ge_run_cycle(struct ge *ge)
Run all GE "mastri" clock periods until next clock cycle.
Definition: ge.c:223
void ge_clock_increment(struct ge *ge)
Definition: ge.c:160
uint8_t ge_clock_is_first(struct ge *ge)
Definition: ge.c:167
void ge_load_2(struct ge *ge)
Emulate the press of the "load 2" button in the console.
Definition: ge.c:89
uint8_t ge_clock_is_last(struct ge *ge)
Definition: ge.c:172
void ge_init(struct ge *ge)
Initialize the emulator.
Definition: ge.c:14
int ge_run_pulse(struct ge *ge)
Run a single pulse (i.e. a single GE "mastri" clock periods)
Definition: ge.c:177
void fsn_last_clock(struct ge *ge)
Commit the future state.
Definition: ge.c:248
void ge_print_registers_verbose(struct ge *ge)
Definition: ge.c:143
void ge_load(struct ge *ge)
Emulate the press of the "load" button in the console.
Definition: ge.c:62
int ge_load_program(struct ge *ge, uint8_t *program, uint8_t size)
Copy a program at the start of memory.
Definition: ge.c:49
const char * ge_clock_name(enum clock c)
The clock period name name.
Definition: ge.c:120
void connectors_first_clock(struct ge *ge)
Definition: ge.c:240
void ge_start(struct ge *ge)
Emulate the press of the "start" button in the console.
Definition: ge.c:94
void pulse(struct ge *ge)
Definition: pulse.c:180
clock
Definition: ge.h:36
@ ENUMERATE_CLOCKS
Definition: ge.h:38
static uint16_t NI_knot(struct ge *ge)
NI Knot.
Definition: signals.h:263
static uint16_t NO_knot(struct ge *ge)
Knot driven by P0, V1, V2, V4, L1, R1, V3 and L3.
Definition: signals.h:165
void ge_log(ge_log_type type, const char *format,...)
Log message.
Definition: log.c:31
uint8_t ge_log_enabled(ge_log_type type)
Check if a log type is enabled.
Definition: log.c:46
@ LOG_REGS_V
Register trace per pulse.
Definition: log.h:23
@ LOG_ERR
Emulator unrecoverable condition.
Definition: log.h:18
@ LOG_FUTURE
Future state network debug.
Definition: log.h:24
@ LOG_REGS
Register trace per cycle.
Definition: log.h:20
@ LOG_STATES
State trace.
Definition: log.h:21
@ LOG_READER
Integrated Reader.
Definition: log.h:28
void msl_run_state(struct ge *ge, struct msl_timing_state *state)
Runs a machine state.
Definition: msl.c:18
struct msl_timing_state * msl_get_state(uint8_t SO)
Gets timing state␐␐␐␐␐␐␐␐␐.
Definition: msl.c:9
int ge_peri_on_pulses(struct ge *ge)
Definition: peripherical.c:7
int ge_peri_deinit(struct ge *ge)
Definition: peripherical.c:37
int ge_peri_on_clock(struct ge *ge)
Definition: peripherical.c:22
Signals.
const char * name
Definition: reader.h:26
uint16_t RICI
Disables next status.
Definition: console.h:97
uint16_t PAPA
Step By Step execution.
Definition: console.h:81
The entire state of the emulated system, including registers, memory, peripherals and timings.
Definition: ge.h:94
uint8_t ALAM
Operator Call.
Definition: ge.h:308
uint8_t ALOI
Load connector selection.
Definition: ge.h:261
uint8_t AINI
Program Loading.
Definition: ge.h:254
struct ge_connector ST4
The I/O interface for the ST4 connector.
Definition: ge.h:545
uint8_t ALTO
Stops internal cycles.
Definition: ge.h:269
uint8_t ffFA
Special conditions register 2.
Definition: ge.h:239
uint16_t rPO
Program addresser.
Definition: ge.h:111
uint8_t future_state
Future state.
Definition: ge.h:508
uint8_t PODI
Slow delay line.
Definition: ge.h:277
enum ge_console_rotary register_selector
The current state of the console register rotary switch.
Definition: ge.h:513
uint8_t RIA0
Synchronous CPU Cycle Request.
Definition: ge.h:462
uint8_t RIA2
Synchronous Channel 2 Cycle Request.
Definition: ge.h:476
uint16_t rV1
Addresser for the first operand.
Definition: ge.h:113
uint8_t rSO
Main sequencer.
Definition: ge.h:196
uint8_t halted
Definition: ge.h:97
uint16_t rRO
Multipurpose 8+1 bit register.
Definition: ge.h:147
struct ge_console_switches console_switches
The current state of the console switches.
Definition: ge.h:518
struct ge_connector ST3
The I/O interface for the ST3 connector.
Definition: ge.h:540
uint8_t rL2
Auxiliary register.
Definition: ge.h:131
uint8_t powered
Definition: ge.h:98
uint8_t ffFI
Special conditions register 1.
Definition: ge.h:229
uint8_t RC00
Asynchronous CPU Cycle Request.
Definition: ge.h:407
uint16_t rBO
Default operator.
Definition: ge.h:164
uint8_t RC01
Asynchronous Channel 1 Cycle Request.
Definition: ge.h:420
uint8_t mem[MEM_SIZE]
The memory of the emulated system.
Definition: ge.h:528
uint16_t rV4
Addresser for external instructions using channel 2.
Definition: ge.h:116
uint16_t rL1
Length of the operand.
Definition: ge.h:130
uint8_t rSA
Future state configuration.
Definition: ge.h:218
uint16_t rV2
Addresser for the second operand.
Definition: ge.h:114
uint8_t RC02
Asynchronous Channel 2 Cycle Request.
Definition: ge.h:435
uint8_t ADIR
Disable Step By Step.
Definition: ge.h:327
uint8_t rSI
Peripheral unit sequencer.
Definition: ge.h:210
uint8_t RC03
Asynchronous Channel 3 Cycle Request.
Definition: ge.h:450
uint8_t ACIC
Recycle delay line.
Definition: ge.h:298
enum clock current_clock
Definition: ge.h:96
uint16_t rL3
Length of operands involving channel 3.
Definition: ge.h:132
uint16_t rV3
Addresser for external instructions using channel 3.
Definition: ge.h:115
uint8_t rFO
Current function code.
Definition: ge.h:171
Timing chart.
Definition: msl-timings.h:52