This source file includes following definitions.
- cpu_show_config
- cpu_set_config
- cpu_show_nunits
- cpu_set_nunits
- cpu_show_kips
- cpu_set_kips
- cpu_show_stall
- cpu_set_stall
- setCPUConfigL68
- setCPUConfigDPS8M
- cycle_str
- set_cpu_cycle
- set_cpu_idx
- cpu_reset_unit_idx
- simh_cpu_reset_and_clear_unit
- simh_cpu_reset_unit
- str_SDW0
- cpu_boot
- scu_phys_bank
- setup_scbank_map_tandd
- sc_port_for_addr
- tandd_scu_for_addr
- consume_parity_bits
- ia_priority
- sdpap_store
- sc_command_parity
- bad_parity_mark
- bad_parity_clear
- bad_parity_marked
- bad_parity_read
- sc_lockout_wait
- sc_fine_map
- tandd_set_nea_port
- setup_scbank_map
- tandd_io_mode
- lookup_cpu_mem_map
- get_serial_number
- do_stats
- ev_poll_cb
- cpu_init
- cpu_stop_poll_timer
- cpu_reset
- sim_cpu_reset
- cpu_ex
- cpu_dep
- get_highest_intr
- disDiagEnabled
- disDiagEnter
- disDiagInterruptSet
- disDiagWake
- sample_interrupts
- simh_hooks
- panel_process_event
- sim_instr
- cpu_thread_main
- do_LUF_fault
- set_temporary_absolute_mode
- clear_temporary_absolute_mode
- becomeClockMaster
- giveupClockMaster
- threadz_sim_instr
- operand_size
- readOperandRead
- readOperandRMW
- write_operand
- set_mem_watch
- nem_check
- core_read
- core_read_lock
- core_write
- core_write_unlock
- core_unlock_all
- core_write_zone
- core_read2
- core_write2
- decode_instruction
- is_priv_mode
- get_bar_mode
- get_addr_mode
- set_addr_mode
- get_BAR_address
- add_history
- add_history_force
- add_dps8m_CU_history
- add_dps8m_DU_OU_history
- add_dps8m_APU_history
- add_dps8m_EAPU_history
- add_l68_CU_history_entry
- add_l68_CU_history
- add_l68_CU_fetch_history
- add_l68_DU_history
- add_l68_OU_history
- add_l68_APU_history
- get_dbg_verb
- dps8_sim_debug
- setupPROM
- cpuStats
- perfTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <ctype.h>
36
37 #if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
38 # include <sys/mman.h>
39 #endif
40
41 #include "dps8.h"
42 #include "dps8_sys.h"
43 #include "dps8_iom.h"
44 #include "dps8_cable.h"
45 #include "dps8_cpu.h"
46 #include "dps8_rt.h"
47 #include "dps8_priv.h"
48 #include "dps8_addrmods.h"
49 #include "dps8_faults.h"
50 #include "dps8_scu.h"
51 #include "dps8_append.h"
52 #include "dps8_ins.h"
53 #include "dps8_state.h"
54 #include "dps8_math.h"
55 #include "dps8_iefp.h"
56 #include "dps8_console.h"
57 #include "dps8_fnp2.h"
58 #include "dps8_socket_dev.h"
59 #include "dps8_crdrdr.h"
60 #include "dps8_absi.h"
61 #include "dps8_mgp.h"
62 #include "dps8_net.h"
63 #include "dps8_utils.h"
64 #include "dps8_memalign.h"
65
66 #if defined(M_SHARED)
67 # include "shm.h"
68 #endif
69
70 #include "dps8_opcodetable.h"
71 #include "../simh/sim_defs.h"
72 #include "../simh/sim_os_mem.h"
73
74 #if defined(THREADZ) || defined(LOCKLESS)
75 # include "threadz.h"
76 __thread uint current_running_cpu_idx;
77 #endif
78
79 #include "ver.h"
80
81 #if defined(_AIX) && !defined(__PASE__)
82 # include <pthread.h>
83 # include <sys/resource.h>
84 #endif
85
86 #if defined(NO_LOCALE)
87 # define xstrerror_l strerror
88 #endif
89
90 #define DBG_CTR cpu.cycleCnt
91
92 #define ASSUME0 0
93
94 #define FREE(p) do \
95 { \
96 free((p)); \
97 (p) = NULL; \
98 } while(0)
99
100
101
102 static UNIT cpu_unit [N_CPU_UNITS_MAX] = {
103 #if defined(NO_C_ELLIPSIS)
104 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
105 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
106 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
107 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
108 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
109 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
110 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
111 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
112 #else
113 [0 ... N_CPU_UNITS_MAX - 1] = {
114 UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
115 }
116 #endif
117 };
118
119 #define UNIT_IDX(uptr) ((uptr) - cpu_unit)
120
121
122 #define LOCKUP_KIPS 1000
123 static uint64 kips = LOCKUP_KIPS;
124
125
126
127 #define LUF_OVER(n) (cpu.tweaks.tandd_mode ? \
128 cpu.lufTicks >= (1024u << (n)) : \
129 cpu.lufCounter > luf_limits[n])
130
131 static uint64 luf_limits[] =
132 {
133 2000*LOCKUP_KIPS/1000,
134 4000*LOCKUP_KIPS/1000,
135 8000*LOCKUP_KIPS/1000,
136 16000*LOCKUP_KIPS/1000,
137 32000*LOCKUP_KIPS/1000
138 };
139
140 struct stall_point_s stall_points [N_STALL_POINTS];
141 bool stall_point_active = false;
142
143 #if defined(PANEL68)
144 static void panel_process_event (void);
145 #endif
146
147 static t_stat simh_cpu_reset_and_clear_unit (UNIT * uptr,
148 UNUSED int32 value,
149 UNUSED const char * cptr,
150 UNUSED void * desc);
151 char * cycle_str (cycles_e cycle);
152
153 static t_stat cpu_show_config (UNUSED FILE * st, UNIT * uptr,
154 UNUSED int val, UNUSED const void * desc)
155 {
156 long cpu_unit_idx = UNIT_IDX (uptr);
157 if (cpu_unit_idx < 0 || cpu_unit_idx >= N_CPU_UNITS_MAX)
158 {
159 sim_warn ("error: Invalid unit number %ld\r\n", (long) cpu_unit_idx);
160 return SCPE_ARG;
161 }
162
163 #define PFC_INT8 "%c%c%c%c%c%c%c%c"
164
165 #define PBI_8(i) \
166 ( ((i) & 0x80ll) ? '1' : '0' ), \
167 ( ((i) & 0x40ll) ? '1' : '0' ), \
168 ( ((i) & 0x20ll) ? '1' : '0' ), \
169 ( ((i) & 0x10ll) ? '1' : '0' ), \
170 ( ((i) & 0x08ll) ? '1' : '0' ), \
171 ( ((i) & 0x04ll) ? '1' : '0' ), \
172 ( ((i) & 0x02ll) ? '1' : '0' ), \
173 ( ((i) & 0x01ll) ? '1' : '0' )
174
175 #define PFC_INT16 PFC_INT8 PFC_INT8
176 #define PFC_INT32 PFC_INT16 PFC_INT16
177 #define PFC_INT64 PFC_INT32 PFC_INT32
178
179 #define PBI_16(i) PBI_8((i) >> 8), PBI_8(i)
180 #define PBI_32(i) PBI_16((i) >> 16), PBI_16(i)
181 #define PBI_64(i) PBI_32((i) >> 32), PBI_32(i)
182
183 char dsbin[66], adbin[34];
184
185 sim_msg ("CPU unit number %ld\r\n", (long) cpu_unit_idx);
186
187 sim_msg ("Fault base: %03o(8)\r\n",
188 cpus[cpu_unit_idx].switches.FLT_BASE);
189 sim_msg ("CPU number: %01o(8)\r\n",
190 cpus[cpu_unit_idx].switches.cpu_num);
191 sim_msg ("Data switches: %012llo(8)\r\n",
192 (unsigned long long)cpus[cpu_unit_idx].switches.data_switches);
193 (void)snprintf (dsbin, 65, PFC_INT64,
194 PBI_64((unsigned long long)cpus[cpu_unit_idx].switches.data_switches));
195 sim_msg (" %36s(2)\r\n",
196 dsbin + strlen(dsbin) - 36);
197 sim_msg ("Address switches: %06o(8)\r\n",
198 cpus[cpu_unit_idx].switches.addr_switches);
199 (void)snprintf (adbin, 33, PFC_INT32,
200 PBI_32(cpus[cpu_unit_idx].switches.addr_switches));
201 sim_msg (" %18s(2)\r\n",
202 adbin + strlen(adbin) - 18);
203 for (int i = 0; i < (cpus[cpu_unit_idx].tweaks.l68_mode ? N_L68_CPU_PORTS : N_DPS8M_CPU_PORTS); i ++)
204 {
205 sim_msg ("Port%c enable: %01o(8)\r\n",
206 'A' + i, cpus[cpu_unit_idx].switches.enable [i]);
207 sim_msg ("Port%c init enable: %01o(8)\r\n",
208 'A' + i, cpus[cpu_unit_idx].switches.init_enable [i]);
209 sim_msg ("Port%c assignment: %01o(8)\r\n",
210 'A' + i, cpus[cpu_unit_idx].switches.assignment [i]);
211 sim_msg ("Port%c interlace: %01o(8)\r\n",
212 'A' + i, cpus[cpu_unit_idx].switches.interlace [i]);
213 sim_msg ("Port%c store size: %01o(8)\r\n",
214 'A' + i, cpus[cpu_unit_idx].switches.store_size [i]);
215 }
216 sim_msg ("Processor mode: %s [%o]\r\n",
217 cpus[cpu_unit_idx].switches.procMode == \
218 procModeMultics ? "Multics" : cpus[cpu_unit_idx].switches.procMode == procModeGCOS ? "GCOS" : "???",
219 cpus[cpu_unit_idx].switches.procMode);
220 sim_msg ("8K Cache: %s\r\n",
221 cpus[cpu_unit_idx].switches.enable_cache ? "Enabled" : "Disabled");
222 sim_msg ("SDWAM: %s\r\n",
223 cpus[cpu_unit_idx].switches.sdwam_enable ? "Enabled" : "Disabled");
224 sim_msg ("PTWAM: %s\r\n",
225 cpus[cpu_unit_idx].switches.ptwam_enable ? "Enabled" : "Disabled");
226
227 sim_msg ("Processor speed: %02o(8)\r\n",
228 cpus[cpu_unit_idx].options.proc_speed);
229 sim_msg ("DIS enable: %01o(8)\r\n",
230 cpus[cpu_unit_idx].tweaks.dis_enable);
231 sim_msg ("Steady clock: %01o(8)\r\n",
232 scu [0].steady_clock);
233 sim_msg ("Halt on unimplemented: %01o(8)\r\n",
234 cpus[cpu_unit_idx].tweaks.halt_on_unimp);
235 sim_msg ("Enable simulated SDWAM/PTWAM: %01o(8)\r\n",
236 cpus[cpu_unit_idx].tweaks.enable_wam);
237 sim_msg ("Report faults: %01o(8)\r\n",
238 cpus[cpu_unit_idx].tweaks.report_faults);
239 sim_msg ("TRO faults enabled: %01o(8)\r\n",
240 cpus[cpu_unit_idx].tweaks.tro_enable);
241 sim_msg ("drl fatal enabled: %01o(8)\r\n",
242 cpus[cpu_unit_idx].tweaks.drl_fatal);
243 sim_msg ("useMap: %d\r\n",
244 cpus[cpu_unit_idx].tweaks.useMap);
245 sim_msg ("PROM installed: %01o(8)\r\n",
246 cpus[cpu_unit_idx].options.prom_installed);
247 sim_msg ("Hex mode installed: %01o(8)\r\n",
248 cpus[cpu_unit_idx].options.hex_mode_installed);
249 sim_msg ("8K cache installed: %01o(8)\r\n",
250 cpus[cpu_unit_idx].options.cache_installed);
251 sim_msg ("Clock slave installed: %01o(8)\r\n",
252 cpus[cpu_unit_idx].options.clock_slave_installed);
253 #if defined(AFFINITY)
254 if (cpus[cpu_unit_idx].set_affinity)
255 sim_msg ("CPU affinity: %d\r\n", cpus[cpu_unit_idx].affinity);
256 else
257 sim_msg ("CPU affinity: not set\r\n");
258 #endif
259 sim_msg ("ISOLTS mode: %01o(8)\r\n", cpus[cpu_unit_idx].tweaks.isolts_mode);
260 sim_msg ("T&D mode: %01o(8)\r\n", cpus[cpu_unit_idx].tweaks.tandd_mode);
261 sim_msg ("NODIS mode: %01o(8)\r\n", cpus[cpu_unit_idx].tweaks.nodis);
262 sim_msg ("6180 mode: %01o(8) [%s]\r\n",
263 cpus[cpu_unit_idx].tweaks.l68_mode, cpus[cpu_unit_idx].tweaks.l68_mode ? "6180" : "DPS8/M");
264 return SCPE_OK;
265 }
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291 static config_value_list_t cfg_multics_fault_base [] =
292 {
293 { "multics", 2 },
294 { NULL, 0 }
295 };
296
297 static config_value_list_t cfg_on_off [] =
298 {
299 { "off", 0 },
300 { "on", 1 },
301 { "disable", 0 },
302 { "enable", 1 },
303 { NULL, 0 }
304 };
305
306 static config_value_list_t cfg_l68_mode [] = {
307 { "dps8/m", 0 },
308 { "dps8m", 0 },
309 { "dps8", 0 },
310 { "l68", 1 },
311 { "l6180", 1 },
312 { "6180", 1 },
313 };
314
315 static config_value_list_t cfg_cpu_mode [] =
316 {
317 { "gcos", 0 },
318 { "multics", 1 },
319 { NULL, 0 }
320 };
321
322 static config_value_list_t cfg_port_letter [] =
323 {
324 { "a", 0 },
325 { "b", 1 },
326 { "c", 2 },
327 { "d", 3 },
328 { "e", 4 },
329 { "f", 5 },
330 { "g", 6 },
331 { "h", 7 },
332 { NULL, 0 }
333 };
334
335 static config_value_list_t cfg_interlace [] =
336 {
337 { "off", 0 },
338 { "2", 2 },
339 { "4", 4 },
340 { NULL, 0 }
341 };
342
343 #if defined(AFFINITY)
344 static config_value_list_t cfg_affinity [] =
345 {
346 { "off", -1 },
347 { NULL, 0 }
348 };
349 #endif
350
351 static config_value_list_t cfg_size_list [] =
352 {
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415 { "32", 8 },
416 { "32K", 8 },
417 { "64", 9 },
418 { "64K", 9 },
419 { "128", 10 },
420 { "128K", 10 },
421 { "256", 11 },
422 { "256K", 11 },
423 { "512", 12 },
424 { "512K", 12 },
425 { "1024", 13 },
426 { "1024K", 13 },
427 { "1M", 13 },
428 { "2048", 14 },
429 { "2048K", 14 },
430 { "2M", 14 },
431 { "4096", 15 },
432 { "4096K", 15 },
433 { "4M", 15 },
434 { NULL, 0 }
435 };
436
437 static config_list_t cpu_config_list [] =
438 {
439 { "faultbase", 0, 0177, cfg_multics_fault_base },
440 { "num", 0, 07, NULL },
441 { "data", 0, 0777777777777, NULL },
442 { "stopnum", 0, 999999, NULL },
443 { "mode", 0, 01, cfg_cpu_mode },
444 { "speed", 0, 017, NULL },
445 { "port", 0, N_CPU_PORTS - 1, cfg_port_letter },
446 { "assignment", 0, 7, NULL },
447 { "interlace", 0, 1, cfg_interlace },
448 { "enable", 0, 1, cfg_on_off },
449 { "init_enable", 0, 1, cfg_on_off },
450 { "store_size", 0, 7, cfg_size_list },
451 { "enable_cache", 0, 1, cfg_on_off },
452 { "sdwam", 0, 1, cfg_on_off },
453 { "ptwam", 0, 1, cfg_on_off },
454
455
456 { "dis_enable", 0, 1, cfg_on_off },
457
458 { "steady_clock", 0, 1, cfg_on_off },
459 { "halt_on_unimplemented", 0, 1, cfg_on_off },
460 { "enable_wam", 0, 1, cfg_on_off },
461 { "report_faults", 0, 1, cfg_on_off },
462 { "tro_enable", 0, 1, cfg_on_off },
463 { "drl_fatal", 0, 1, cfg_on_off },
464 { "useMap", 0, 1, cfg_on_off },
465 { "address", 0, 0777777, NULL },
466 { "prom_installed", 0, 1, cfg_on_off },
467 { "hex_mode_installed", 0, 1, cfg_on_off },
468 { "cache_installed", 0, 1, cfg_on_off },
469 { "clock_slave_installed", 0, 1, cfg_on_off },
470 { "enable_emcall", 0, 1, cfg_on_off },
471
472
473 #if defined(AFFINITY)
474 { "affinity", -1, 32767, cfg_affinity },
475 #endif
476 { "isolts_mode", 0, 1, cfg_on_off },
477 { "tandd_mode", 0, 1, cfg_on_off },
478 { "nodis", 0, 1, cfg_on_off },
479 { "l68_mode", 0, 1, cfg_l68_mode },
480 { NULL, 0, 0, NULL }
481 };
482
483 static t_stat cpu_set_config (UNIT * uptr, UNUSED int32 value,
484 const char * cptr, UNUSED void * desc)
485 {
486 long cpu_unit_idx = UNIT_IDX (uptr);
487 if (cpu_unit_idx < 0 || cpu_unit_idx >= N_CPU_UNITS_MAX)
488 {
489 sim_warn ("error: cpu_set_config: Invalid unit number %ld\r\n",
490 (long) cpu_unit_idx);
491 return SCPE_ARG;
492 }
493
494 static int port_num = 0;
495
496 config_state_t cfg_state = { NULL, NULL };
497
498 for (;;)
499 {
500 int64_t v;
501 int rc = cfg_parse (__func__, cptr, cpu_config_list,
502 & cfg_state, & v);
503 if (rc == -1)
504 {
505 break;
506 }
507 if (rc == -2)
508 {
509 cfg_parse_done (& cfg_state);
510 return SCPE_ARG;
511 }
512
513 const char * p = cpu_config_list [rc] . name;
514 if (strcmp (p, "faultbase") == 0)
515 cpus[cpu_unit_idx].switches.FLT_BASE = (uint) v;
516 else if (strcmp (p, "num") == 0)
517 cpus[cpu_unit_idx].switches.cpu_num = (uint) v;
518 else if (strcmp (p, "data") == 0)
519 cpus[cpu_unit_idx].switches.data_switches = (word36) v;
520 else if (strcmp (p, "stopnum") == 0)
521 {
522
523
524 int64_t d1 = (v / 1000) % 10;
525 int64_t d2 = (v / 100) % 10;
526 int64_t d3 = (v / 10) % 10;
527 int64_t d4 = (v / 1) % 10;
528 word36 d = 0123000000000;
529 putbits36_6 (& d, 9, (word4) d1);
530 putbits36_6 (& d, 15, (word4) d2);
531 putbits36_6 (& d, 21, (word4) d3);
532 putbits36_6 (& d, 27, (word4) d4);
533 cpus[cpu_unit_idx].switches.data_switches = d;
534 }
535 else if (strcmp (p, "address") == 0)
536 cpus[cpu_unit_idx].switches.addr_switches = (word18) v;
537 else if (strcmp (p, "mode") == 0)
538 cpus[cpu_unit_idx].switches.procMode = v ? procModeMultics : procModeGCOS;
539 else if (strcmp (p, "speed") == 0)
540 cpus[cpu_unit_idx].options.proc_speed = (uint) v;
541 else if (strcmp (p, "port") == 0) {
542 if ((! cpus[cpu_unit_idx].tweaks.l68_mode) && (int) v > 3) {
543 cfg_parse_done (& cfg_state);
544 return SCPE_ARG;
545 }
546 port_num = (int) v;
547 }
548 else if (strcmp (p, "assignment") == 0)
549 cpus[cpu_unit_idx].switches.assignment [port_num] = (uint) v;
550 else if (strcmp (p, "interlace") == 0)
551 cpus[cpu_unit_idx].switches.interlace [port_num] = (uint) v;
552 else if (strcmp (p, "enable") == 0)
553 cpus[cpu_unit_idx].switches.enable [port_num] = (uint) v;
554 else if (strcmp (p, "init_enable") == 0)
555 cpus[cpu_unit_idx].switches.init_enable [port_num] = (uint) v;
556 else if (strcmp (p, "store_size") == 0) {
557 if (v > 7) {
558 if (cpus[cpu_unit_idx].tweaks.l68_mode) {
559 switch (v) {
560 case 8: v = 0; break;
561 case 9: v = 1; break;
562 case 10: v = 3; break;
563 case 11: v = 7; break;
564 case 12: v = 4; break;
565 case 13: v = 5; break;
566 case 14: v = 6; break;
567 case 15: v = 2; break;
568 }
569 } else {
570 switch (v) {
571 case 8: v = 0; break;
572 case 9: v = 1; break;
573 case 10: v = 2; break;
574 case 11: v = 3; break;
575 case 12: v = 4; break;
576 case 13: v = 5; break;
577 case 14: v = 6; break;
578 case 15: v = 7; break;
579 }
580 }
581 }
582 cpus[cpu_unit_idx].switches.store_size [port_num] = (uint) v;
583 }
584 else if (strcmp (p, "enable_cache") == 0)
585 cpus[cpu_unit_idx].switches.enable_cache = (uint) v ? true : false;
586 else if (strcmp (p, "sdwam") == 0)
587 cpus[cpu_unit_idx].switches.sdwam_enable = (uint) v ? true : false;
588 else if (strcmp (p, "ptwam") == 0)
589 cpus[cpu_unit_idx].switches.ptwam_enable = (uint) v ? true : false;
590 else if (strcmp (p, "dis_enable") == 0)
591 cpus[cpu_unit_idx].tweaks.dis_enable = (uint) v;
592 else if (strcmp (p, "steady_clock") == 0)
593 scu [0].steady_clock = (uint) v;
594 else if (strcmp (p, "halt_on_unimplemented") == 0)
595 cpus[cpu_unit_idx].tweaks.halt_on_unimp = (uint) v;
596 else if (strcmp (p, "enable_wam") == 0)
597 cpus[cpu_unit_idx].tweaks.enable_wam = (uint) v;
598 else if (strcmp (p, "report_faults") == 0)
599 cpus[cpu_unit_idx].tweaks.report_faults = (uint) v;
600 else if (strcmp (p, "tro_enable") == 0)
601 cpus[cpu_unit_idx].tweaks.tro_enable = (uint) v;
602 else if (strcmp (p, "drl_fatal") == 0)
603 cpus[cpu_unit_idx].tweaks.drl_fatal = (uint) v;
604 else if (strcmp (p, "useMap") == 0)
605 cpus[cpu_unit_idx].tweaks.useMap = v;
606 else if (strcmp (p, "prom_installed") == 0)
607 cpus[cpu_unit_idx].options.prom_installed = v;
608 else if (strcmp (p, "hex_mode_installed") == 0)
609 cpus[cpu_unit_idx].options.hex_mode_installed = v;
610 else if (strcmp (p, "cache_installed") == 0)
611 cpus[cpu_unit_idx].options.cache_installed = v;
612 else if (strcmp (p, "clock_slave_installed") == 0)
613 cpus[cpu_unit_idx].options.clock_slave_installed = v;
614 else if (strcmp (p, "enable_emcall") == 0)
615 cpus[cpu_unit_idx].tweaks.enable_emcall = v;
616 #if defined(AFFINITY)
617 else if (strcmp (p, "affinity") == 0)
618 if (v < 0)
619 {
620 cpus[cpu_unit_idx].set_affinity = false;
621 }
622 else
623 {
624 cpus[cpu_unit_idx].set_affinity = true;
625 cpus[cpu_unit_idx].affinity = (uint) v;
626 }
627 #endif
628 else if (strcmp (p, "tandd_mode") == 0)
629 cpus[cpu_unit_idx].tweaks.tandd_mode = v ? true : false;
630 else if (strcmp (p, "isolts_mode") == 0)
631 {
632 bool was = cpus[cpu_unit_idx].tweaks.isolts_mode;
633 cpus[cpu_unit_idx].tweaks.isolts_mode = v;
634 if (v && ! was) {
635 uint store_sz;
636 if (cpus[cpu_unit_idx].tweaks.l68_mode)
637 store_sz = 3;
638 else
639 store_sz = 2;
640 cpus[cpu_unit_idx].isolts_switches_save = cpus[cpu_unit_idx].switches;
641
642 cpus[cpu_unit_idx].switches.data_switches = 00000030714000;
643 cpus[cpu_unit_idx].switches.addr_switches = 0100150;
644 cpus[cpu_unit_idx].tweaks.useMap = true;
645 cpus[cpu_unit_idx].tweaks.enable_wam = true;
646 cpus[cpu_unit_idx].switches.assignment [0] = 0;
647 cpus[cpu_unit_idx].switches.interlace [0] = false;
648 cpus[cpu_unit_idx].switches.enable [0] = false;
649 cpus[cpu_unit_idx].switches.init_enable [0] = false;
650 cpus[cpu_unit_idx].switches.store_size [0] = store_sz;
651
652 cpus[cpu_unit_idx].switches.assignment [1] = 0;
653 cpus[cpu_unit_idx].switches.interlace [1] = false;
654 cpus[cpu_unit_idx].switches.enable [1] = true;
655 cpus[cpu_unit_idx].switches.init_enable [1] = false;
656 cpus[cpu_unit_idx].switches.store_size [1] = store_sz;
657
658 cpus[cpu_unit_idx].switches.assignment [2] = 0;
659 cpus[cpu_unit_idx].switches.interlace [2] = false;
660 cpus[cpu_unit_idx].switches.enable [2] = false;
661 cpus[cpu_unit_idx].switches.init_enable [2] = false;
662 cpus[cpu_unit_idx].switches.store_size [2] = store_sz;
663
664 cpus[cpu_unit_idx].switches.assignment [3] = 0;
665 cpus[cpu_unit_idx].switches.interlace [3] = false;
666 cpus[cpu_unit_idx].switches.enable [3] = false;
667 cpus[cpu_unit_idx].switches.init_enable [3] = false;
668 cpus[cpu_unit_idx].switches.store_size [3] = store_sz;
669
670 if (cpus[cpu_unit_idx].tweaks.l68_mode) {
671 cpus[cpu_unit_idx].switches.assignment [4] = 0;
672 cpus[cpu_unit_idx].switches.interlace [4] = false;
673 cpus[cpu_unit_idx].switches.enable [4] = false;
674 cpus[cpu_unit_idx].switches.init_enable [4] = false;
675 cpus[cpu_unit_idx].switches.store_size [4] = 3;
676
677 cpus[cpu_unit_idx].switches.assignment [5] = 0;
678 cpus[cpu_unit_idx].switches.interlace [5] = false;
679 cpus[cpu_unit_idx].switches.enable [5] = false;
680 cpus[cpu_unit_idx].switches.init_enable [5] = false;
681 cpus[cpu_unit_idx].switches.store_size [5] = 3;
682
683 cpus[cpu_unit_idx].switches.assignment [6] = 0;
684 cpus[cpu_unit_idx].switches.interlace [6] = false;
685 cpus[cpu_unit_idx].switches.enable [6] = false;
686 cpus[cpu_unit_idx].switches.init_enable [6] = false;
687 cpus[cpu_unit_idx].switches.store_size [6] = 3;
688
689 cpus[cpu_unit_idx].switches.assignment [7] = 0;
690 cpus[cpu_unit_idx].switches.interlace [7] = false;
691 cpus[cpu_unit_idx].switches.enable [7] = false;
692 cpus[cpu_unit_idx].switches.init_enable [7] = false;
693 cpus[cpu_unit_idx].switches.store_size [7] = 3;
694 }
695 cpus[cpu_unit_idx].switches.enable [1] = true;
696
697 #if defined(THREADZ) || defined(LOCKLESS)
698 if (cpus[cpu_unit_idx].executing) {
699 cpus[cpu_unit_idx].forceRestart = true;
700 wakeCPU (cpu_unit_idx);
701 } else {
702 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
703
704 }
705 #else
706 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
707 simh_cpu_reset_and_clear_unit (cpu_unit + cpu_unit_idx, 0, NULL, NULL);
708 #endif
709
710 } else if (was && !v) {
711 cpus[cpu_unit_idx].switches = cpus[cpu_unit_idx].isolts_switches_save;
712
713 #if defined(THREADZ) || defined(LOCKLESS)
714 if (cpus[cpu_unit_idx].executing) {
715 cpus[cpu_unit_idx].forceRestart = true;
716 wakeCPU (cpu_unit_idx);
717 } else {
718 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
719
720 }
721 #else
722 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
723 simh_cpu_reset_and_clear_unit (cpu_unit + cpu_unit_idx, 0, NULL, NULL);
724 #endif
725
726 }
727 }
728 else if (strcmp (p, "nodis") == 0)
729 cpus[cpu_unit_idx].tweaks.nodis = v;
730 else if (strcmp (p, "l68_mode") == 0)
731 cpus[cpu_unit_idx].tweaks.l68_mode = v;
732 else
733 {
734 sim_warn ("error: cpu_set_config: Invalid cfg_parse rc <%ld>\r\n",
735 (long) rc);
736 cfg_parse_done (& cfg_state);
737 return SCPE_ARG;
738 }
739 }
740 cfg_parse_done (& cfg_state);
741
742 return SCPE_OK;
743 }
744
745 static t_stat cpu_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr,
746 UNUSED int val, UNUSED const void * desc)
747 {
748 sim_msg ("Number of CPUs in system is %d\r\n", cpu_dev.numunits);
749 return SCPE_OK;
750 }
751
752 static t_stat cpu_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value,
753 const char * cptr, UNUSED void * desc)
754 {
755 if (! cptr)
756 return SCPE_ARG;
757 int n = atoi (cptr);
758 if (n < 1 || n > N_CPU_UNITS_MAX)
759 return SCPE_ARG;
760 cpu_dev.numunits = (uint32) n;
761 return SCPE_OK;
762 }
763
764 static t_stat cpu_show_kips (UNUSED FILE * st, UNUSED UNIT * uptr,
765 UNUSED int val, UNUSED const void * desc)
766 {
767 sim_msg ("CPU KIPS %lu\r\n", (unsigned long)kips);
768 return SCPE_OK;
769 }
770
771 static t_stat cpu_set_kips (UNUSED UNIT * uptr, UNUSED int32 value,
772 const char * cptr, UNUSED void * desc)
773 {
774 if (! cptr)
775 return SCPE_ARG;
776 long n = atol (cptr);
777 if (n < 1 || n > 4000000)
778 return SCPE_ARG;
779 kips = (uint64) n;
780 luf_limits[0] = 2000*kips/1000;
781 luf_limits[1] = 4000*kips/1000;
782 luf_limits[2] = 8000*kips/1000;
783 luf_limits[3] = 16000*kips/1000;
784 luf_limits[4] = 32000*kips/1000;
785 return SCPE_OK;
786 }
787
788 static t_stat cpu_show_stall (UNUSED FILE * st, UNUSED UNIT * uptr,
789 UNUSED int val, UNUSED const void * desc)
790 {
791 if (! stall_point_active)
792 {
793 sim_printf ("No stall points\r\n");
794 return SCPE_OK;
795 }
796
797 sim_printf ("Stall points\r\n");
798 for (int i = 0; i < N_STALL_POINTS; i ++)
799 if (stall_points[i].segno || stall_points[i].offset)
800 {
801 #if defined(WIN_STDIO)
802 sim_printf ("%2ld %05o:%06o %10lu\r\n",
803 #else
804 sim_printf ("%2ld %05o:%06o %'10lu\r\n",
805 #endif
806 (long)i, stall_points[i].segno, stall_points[i].offset,
807 (unsigned long)stall_points[i].time);
808 }
809 return SCPE_OK;
810 }
811
812
813
814
815
816
817
818 static t_stat cpu_set_stall (UNUSED UNIT * uptr, UNUSED int32 value,
819 const char * cptr, UNUSED void * desc)
820 {
821 if (! cptr)
822 return SCPE_ARG;
823
824 long n, s, o, t;
825
826 char * end;
827 n = strtol (cptr, & end, 0);
828 if (* end != '=')
829 return SCPE_ARG;
830 if (n < 0 || n >= N_STALL_POINTS)
831 return SCPE_ARG;
832
833 s = strtol (end + 1, & end, 8);
834 if (* end != ':')
835 return SCPE_ARG;
836 if (s < 0 || s > MASK15)
837 return SCPE_ARG;
838
839 o = strtol (end + 1, & end, 8);
840 if (* end != '=')
841 return SCPE_ARG;
842 if (o < 0 || o > MASK18)
843 return SCPE_ARG;
844
845 t = strtol (end + 1, & end, 0);
846 if (* end != 0)
847 return SCPE_ARG;
848 if (t < 0 || t > 30000000)
849 return SCPE_ARG;
850
851 stall_points[n].segno = (word15) s;
852 stall_points[n].offset = (word18) o;
853 stall_points[n].time = (unsigned int) t;
854 stall_point_active = false;
855
856 for (int i = 0; i < N_STALL_POINTS; i ++)
857 if (stall_points[n].segno && stall_points[n].offset)
858 stall_point_active = true;
859
860 return SCPE_OK;
861 }
862
863 static t_stat setCPUConfigL68 (UNIT * uptr, UNUSED int32 value, UNUSED const char * cptr, UNUSED void * desc) {
864 long cpuUnitIdx = UNIT_IDX (uptr);
865 if (cpuUnitIdx < 0 || cpuUnitIdx >= N_CPU_UNITS_MAX)
866 return SCPE_ARG;
867 cpu_state_t * cpun = cpus + cpuUnitIdx;
868
869 cpun->tweaks.l68_mode = 1;
870 cpun->options.hex_mode_installed = 0;
871 for (uint port_num = 0; port_num < N_DPS8M_CPU_PORTS; port_num ++) {
872 cpun->switches.assignment[port_num] = port_num;
873 cpun->switches.interlace[port_num] = 0;
874 cpun->switches.store_size[port_num] = 2;
875 cpun->switches.enable[port_num] = 1;
876 cpun->switches.init_enable[port_num] = 1;
877 }
878 for (uint port_num = N_DPS8M_CPU_PORTS; port_num < N_L68_CPU_PORTS; port_num ++) {
879 cpun->switches.assignment[port_num] = 0;
880 cpun->switches.interlace[port_num] = 0;
881 cpun->switches.store_size[port_num] = 0;
882 cpun->switches.enable[port_num] = 0;
883 cpun->switches.init_enable[port_num] = 0;
884 }
885 return SCPE_OK;
886 }
887
888 static t_stat setCPUConfigDPS8M (UNIT * uptr, UNUSED int32 value, UNUSED const char * cptr, UNUSED void * desc) {
889 long cpuUnitIdx = UNIT_IDX (uptr);
890 if (cpuUnitIdx < 0 || cpuUnitIdx >= N_CPU_UNITS_MAX)
891 return SCPE_ARG;
892 cpu_state_t * cpun = cpus + cpuUnitIdx;
893
894 cpun->tweaks.l68_mode = 0;
895 cpun->options.hex_mode_installed = 0;
896 for (uint port_num = 0; port_num < N_DPS8M_CPU_PORTS; port_num ++) {
897 cpun->switches.assignment[port_num] = port_num;
898 cpun->switches.interlace[port_num] = 0;
899 cpun->switches.store_size[port_num] = 7;
900 cpun->switches.enable[port_num] = 1;
901 cpun->switches.init_enable[port_num] = 1;
902 }
903 for (uint port_num = N_DPS8M_CPU_PORTS; port_num < N_L68_CPU_PORTS; port_num ++) {
904 cpun->switches.assignment[port_num] = 0;
905 cpun->switches.interlace[port_num] = 0;
906 cpun->switches.store_size[port_num] = 0;
907 cpun->switches.enable[port_num] = 0;
908 cpun->switches.init_enable[port_num] = 0;
909 }
910 return SCPE_OK;
911 }
912
913 char * cycle_str (cycles_e cycle)
914 {
915 switch (cycle)
916 {
917
918
919 case FAULT_cycle:
920 return "FAULT_cycle";
921 case EXEC_cycle:
922 return "EXEC_cycle";
923 case FAULT_EXEC_cycle:
924 return "FAULT_EXEC_cycle";
925 case INTERRUPT_cycle:
926 return "INTERRUPT_cycle";
927 case INTERRUPT_EXEC_cycle:
928 return "INTERRUPT_EXEC_cycle";
929 case FETCH_cycle:
930 return "FETCH_cycle";
931 case PSEUDO_FETCH_cycle:
932 return "PSEUDO_FETCH_cycle";
933 case SYNC_FAULT_RTN_cycle:
934 return "SYNC_FAULT_RTN_cycle";
935 default:
936 return "unknown cycle";
937 }
938 }
939
940 static void set_cpu_cycle (cpu_state_t * cpup, cycles_e cycle)
941 {
942 sim_debug (DBG_CYCLE, & cpu_dev, "Setting cycle to %s\r\n",
943 cycle_str (cycle));
944 cpu.cycle = cycle;
945 }
946
947
948
949 #define MEM_UNINITIALIZED (1LLU<<62)
950
951 uint set_cpu_idx (UNUSED uint cpu_idx)
952 {
953 uint prev = current_running_cpu_idx;
954 #if defined(THREADZ) || defined(LOCKLESS)
955 current_running_cpu_idx = cpu_idx;
956 #endif
957 _cpup = & cpus [current_running_cpu_idx];
958 return prev;
959 }
960
961 void cpu_reset_unit_idx (UNUSED uint cpun, bool clear_mem)
962 {
963 uint save = set_cpu_idx (cpun);
964 cpu_state_t * cpup = _cpup;
965 if (clear_mem)
966 {
967 for (uint i = 0; i < MEMSIZE; i ++)
968 {
969
970 #if defined(LOCKLESS)
971 M[i] = (M[i] & ~(MASK36 | MEM_LOCKED)) | MEM_UNINITIALIZED;
972 #else
973 M[i] = (M[i] & ~(MASK36)) | MEM_UNINITIALIZED;
974 #endif
975 }
976 }
977 cpu.rA = 0;
978 cpu.rQ = 0;
979
980 cpu.PPR.IC = 0;
981 cpu.PPR.PRR = 0;
982 cpu.PPR.PSR = 0;
983 cpu.PPR.P = 1;
984 cpu.RSDWH_R1 = 0;
985 cpu.rTR = MASK27;
986
987 if (cpu.tweaks.isolts_mode)
988 {
989 cpu.shadowTR = 0;
990 cpu.rTRlsb = 0;
991 }
992 cpu.rTRticks = 0;
993
994 set_addr_mode (cpup, ABSOLUTE_mode);
995 SET_I_NBAR;
996
997 cpu.CMR.luf = 3;
998 cpu.cu.SD_ON = cpu.switches.sdwam_enable ? 1 : 0;
999 cpu.cu.PT_ON = cpu.switches.ptwam_enable ? 1 : 0;
1000
1001 if (cpu.tweaks.nodis) {
1002 set_cpu_cycle (cpup, FETCH_cycle);
1003 } else {
1004 set_cpu_cycle (cpup, EXEC_cycle);
1005 cpu.cu.IWB = 0000000616200;
1006 }
1007 #if defined(PERF_STRIP)
1008 set_cpu_cycle (cpup, FETCH_cycle);
1009 #endif
1010 cpu.wasXfer = false;
1011 cpu.wasInhibited = false;
1012
1013 cpu.interrupt_flag = false;
1014 cpu.g7_flag = false;
1015
1016 cpu.faultRegister [0] = 0;
1017 cpu.faultRegister [1] = 0;
1018
1019 #if defined(RAPRx)
1020 cpu.apu.lastCycle = UNKNOWN_CYCLE;
1021 #endif
1022
1023 (void)memset (& cpu.PPR, 0, sizeof (struct ppr_s));
1024
1025 setup_scbank_map (cpup);
1026
1027 tidy_cu (cpup);
1028 set_cpu_idx (save);
1029 }
1030
1031 static t_stat simh_cpu_reset_and_clear_unit (UNIT * uptr,
1032 UNUSED int32 value,
1033 UNUSED const char * cptr,
1034 UNUSED void * desc)
1035 {
1036 long cpu_unit_idx = UNIT_IDX (uptr);
1037 cpu_state_t * cpun = cpus + cpu_unit_idx;
1038 if (cpun->tweaks.isolts_mode)
1039 {
1040
1041 if (cpun->tweaks.useMap)
1042 {
1043 for (uint pgnum = 0; pgnum < N_SCBANKS; pgnum ++)
1044 {
1045 int base = cpun->sc_addr_map [pgnum];
1046 if (base < 0)
1047 continue;
1048 for (uint addr = 0; addr < SCBANK_SZ; addr ++)
1049 M [addr + (uint) base] = MEM_UNINITIALIZED;
1050 }
1051 }
1052 }
1053
1054 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
1055 return SCPE_OK;
1056 }
1057
1058 static t_stat simh_cpu_reset_unit (UNIT * uptr,
1059 UNUSED int32 value,
1060 UNUSED const char * cptr,
1061 UNUSED void * desc)
1062 {
1063 long cpu_unit_idx = UNIT_IDX (uptr);
1064 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
1065 return SCPE_OK;
1066 }
1067
1068 #if !defined(PERF_STRIP)
1069 static uv_loop_t * ev_poll_loop;
1070 static uv_timer_t ev_poll_handle;
1071 #endif
1072
1073 static MTAB cpu_mod[] =
1074 {
1075 {
1076 MTAB_unit_value,
1077 0,
1078 "CONFIG",
1079 "CONFIG",
1080 cpu_set_config,
1081 cpu_show_config,
1082 NULL,
1083 NULL
1084 },
1085
1086
1087
1088 {
1089 MTAB_unit_value,
1090 0,
1091 "RESET",
1092 "RESET",
1093 simh_cpu_reset_unit,
1094 NULL,
1095 NULL,
1096 NULL
1097 },
1098
1099 {
1100 MTAB_unit_value,
1101 0,
1102 "INITIALIZE",
1103 "INITIALIZE",
1104 simh_cpu_reset_unit,
1105 NULL,
1106 NULL,
1107 NULL
1108 },
1109
1110
1111
1112 {
1113 MTAB_unit_value,
1114 0,
1115 "INITIALIZEANDCLEAR",
1116 "INITIALIZEANDCLEAR",
1117 simh_cpu_reset_and_clear_unit,
1118 NULL,
1119 NULL,
1120 NULL
1121 },
1122
1123 {
1124 MTAB_unit_value,
1125 0,
1126 "IAC",
1127 "IAC",
1128 simh_cpu_reset_and_clear_unit,
1129 NULL,
1130 NULL,
1131 NULL
1132 },
1133
1134 {
1135 MTAB_dev_value,
1136 0,
1137 "NUNITS",
1138 "NUNITS",
1139 cpu_set_nunits,
1140 cpu_show_nunits,
1141 NULL,
1142 NULL
1143 },
1144
1145 {
1146 MTAB_dev_value,
1147 0,
1148 "KIPS",
1149 "KIPS",
1150 cpu_set_kips,
1151 cpu_show_kips,
1152 NULL,
1153 NULL
1154 },
1155
1156 {
1157 MTAB_dev_value,
1158 0,
1159 "STALL",
1160 "STALL",
1161 cpu_set_stall,
1162 cpu_show_stall,
1163 NULL,
1164 NULL
1165 },
1166
1167 {
1168 MTAB_unit_value,
1169 0,
1170 "DPS8M",
1171 "DPS8M",
1172 setCPUConfigDPS8M,
1173 NULL,
1174 NULL,
1175 NULL
1176 },
1177
1178 {
1179 MTAB_unit_value,
1180 0,
1181 "L68",
1182 "L68",
1183 setCPUConfigL68,
1184 NULL,
1185 NULL,
1186 NULL
1187 },
1188
1189 { 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }
1190 };
1191
1192 static DEBTAB cpu_dt[] =
1193 {
1194 { "TRACE", DBG_TRACE, NULL },
1195 { "TRACEEXT", DBG_TRACEEXT, NULL },
1196 { "MESSAGES", DBG_MSG, NULL },
1197
1198 { "REGDUMPAQI", DBG_REGDUMPAQI, NULL },
1199 { "REGDUMPIDX", DBG_REGDUMPIDX, NULL },
1200 { "REGDUMPPR", DBG_REGDUMPPR, NULL },
1201 { "REGDUMPPPR", DBG_REGDUMPPPR, NULL },
1202 { "REGDUMPDSBR", DBG_REGDUMPDSBR, NULL },
1203 { "REGDUMPFLT", DBG_REGDUMPFLT, NULL },
1204 { "REGDUMP", DBG_REGDUMP, NULL },
1205
1206 { "ADDRMOD", DBG_ADDRMOD, NULL },
1207 { "APPENDING", DBG_APPENDING, NULL },
1208
1209 { "NOTIFY", DBG_NOTIFY, NULL },
1210 { "INFO", DBG_INFO, NULL },
1211 { "ERR", DBG_ERR, NULL },
1212 { "WARN", DBG_WARN, NULL },
1213 { "DEBUG", DBG_DEBUG, NULL },
1214 { "ALL", DBG_ALL, NULL },
1215
1216 { "FAULT", DBG_FAULT, NULL },
1217 { "INTR", DBG_INTR, NULL },
1218 { "CORE", DBG_CORE, NULL },
1219 { "CYCLE", DBG_CYCLE, NULL },
1220 { "CAC", DBG_CAC, NULL },
1221 { "FINAL", DBG_FINAL, NULL },
1222 { "AVC", DBG_AVC, NULL },
1223 { NULL, 0, NULL }
1224 };
1225
1226
1227 const char *sim_stop_messages[] =
1228 {
1229 "Unknown error",
1230 "Simulation stop",
1231 "Breakpoint",
1232 };
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262 #if !defined(SPEED)
1263 static bool watch_bits [MEMSIZE];
1264 #endif
1265
1266 char * str_SDW0 (char * buf, sdw0_s * SDW)
1267 {
1268 (void)sprintf (buf, "ADDR=%06o R1=%o R2=%o R3=%o F=%o FC=%o BOUND=%o R=%o "
1269 "E=%o W=%o P=%o U=%o G=%o C=%o EB=%o",
1270 SDW->ADDR, SDW->R1, SDW->R2, SDW->R3, SDW->DF,
1271 SDW->FC, SDW->BOUND, SDW->R, SDW->E, SDW->W,
1272 SDW->P, SDW->U, SDW->G, SDW->C, SDW->EB);
1273 return buf;
1274 }
1275
1276 static t_stat cpu_boot (UNUSED int32 cpu_unit_idx, UNUSED DEVICE * dptr)
1277 {
1278 sim_warn ("Try 'BOOT IOMn'\r\n");
1279 return SCPE_ARG;
1280 }
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304 #define ZONE_SZ (MEM_SIZE_MAX / 4)
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329 static int scu_phys_bank (uint scu_bank, int offset, uint scu_base_bks)
1330 {
1331 int n_bks = (int) ((4u << 20) / SCBANK_SZ);
1332 int b = ((int) scu_bank + offset - (int) scu_base_bks) % n_bks;
1333 return b < 0 ? b + n_bks : b;
1334 }
1335
1336 static void setup_scbank_map_tandd (cpu_state_t * cpup)
1337 {
1338 for (uint pg = 0; pg < N_SCBANKS; pg ++)
1339 {
1340 cpu.sc_addr_map [pg] = -1;
1341 cpu.sc_scu_map [pg] = -1;
1342 }
1343 for (uint u = 0; u < N_SCU_UNITS_MAX; u ++)
1344 cpu.sc_num_banks[u] = 0;
1345 for (uint p = 0; p < N_SCU_PORTS; p ++)
1346 cpu.sc_fine_port[p] = false;
1347 cpu.sc_fine = false;
1348
1349 uint dps8m_store_table [8] =
1350 { 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304 };
1351 uint l68_store_table [8] =
1352 { 32768, 65536, 4194304, 131072, 524288, 1048576, 2097152, 262144 };
1353
1354 int n_ports = cpu.tweaks.l68_mode ? N_L68_CPU_PORTS : N_DPS8M_CPU_PORTS;
1355 for (int port_num = 0; port_num < n_ports; port_num ++)
1356 {
1357 if (! cpu.switches.enable [port_num])
1358 continue;
1359 if (! cables->cpu_to_scu[current_running_cpu_idx][port_num].in_use)
1360 continue;
1361
1362 uint store_size = cpu.switches.store_size [port_num];
1363
1364
1365
1366
1367 uint sz_wds = cpu.tweaks.l68_mode ?
1368 (cpu.tweaks.isolts_mode && store_size == 3 ?
1369 65536 : l68_store_table [store_size]) :
1370 dps8m_store_table [store_size];
1371 uint base_addr_bks = (sz_wds * cpu.switches.assignment[port_num]) / SCBANK_SZ;
1372 uint port_banks = sz_wds / SCBANK_SZ;
1373
1374 uint scu_unit_idx = cables->cpu_to_scu[current_running_cpu_idx][port_num].scu_unit_idx;
1375 scu_t * up = scu + scu_unit_idx;
1376
1377
1378
1379
1380
1381
1382
1383 uint lower_wds = (1u << up->lower_store_size) * 32768u;
1384 uint half_wds = lower_wds >= 65536u ? lower_wds / 2 : lower_wds;
1385 bool a_on = (up->onl >> 3) & 1;
1386 bool a1_on = (up->onl >> 2) & 1;
1387 bool b_on = (up->onl >> 1) & 1;
1388 bool b1_on = (up->onl >> 0) & 1;
1389
1390 bool sub_enable[4];
1391 if (up->lwr)
1392 {
1393 sub_enable[0] = b_on; sub_enable[1] = b1_on;
1394 sub_enable[2] = a_on; sub_enable[3] = a1_on;
1395 }
1396 else
1397 {
1398 sub_enable[0] = a_on; sub_enable[1] = a1_on;
1399 sub_enable[2] = b_on; sub_enable[3] = b1_on;
1400 }
1401
1402
1403
1404 uint upper_wds = (up->lwr ? a_on : b_on) ? lower_wds : 0;
1405
1406
1407 bool nea_enabled = (up->nea >> 7) & 1;
1408 uint nea_wds = nea_enabled ? (up->nea & 0177u) << 15 : (4u << 20);
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419 uint base_wds = sz_wds * cpu.switches.assignment[port_num];
1420 uint scu_base_wds = base_wds % (4u << 20);
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436 uint stride_wds = lower_wds;
1437 if (up->interlace && stride_wds > (2u << 20))
1438 stride_wds = 2u << 20;
1439
1440
1441
1442 bool fine = up->interlace ||
1443 lower_wds < 2 * SCBANK_SZ ||
1444 nea_wds % SCBANK_SZ != 0 ||
1445 sz_wds % SCBANK_SZ != 0 ||
1446 base_wds % SCBANK_SZ != 0;
1447
1448 cpu.sc_num_banks[port_num] = (lower_wds + upper_wds) / SCBANK_SZ;
1449 if (cpu.sc_num_banks[port_num] > port_banks)
1450 cpu.sc_num_banks[port_num] = port_banks;
1451
1452 if (fine)
1453 {
1454 cpu.sc_fine_port[port_num] = true;
1455 cpu.sc_fine_interlace[port_num] = up->interlace != 0;
1456 cpu.sc_fine_base[port_num] = base_wds;
1457 cpu.sc_fine_window[port_num] = sz_wds;
1458 cpu.sc_fine_scu_base[port_num] = scu_base_wds;
1459 cpu.sc_fine_lower_wds[port_num] = lower_wds;
1460 cpu.sc_fine_upper_wds[port_num] = upper_wds;
1461 cpu.sc_fine_nea_wds[port_num] = nea_wds;
1462 cpu.sc_fine = true;
1463 for (uint slot = 0; slot < 2; slot ++)
1464 for (uint unit = 0; unit < SC_FINE_UNITS; unit ++)
1465 {
1466 cpu.sc_fine_phys[port_num][slot][unit] = -1;
1467 uint local_wd = unit * SC_FINE_UNIT;
1468 if (local_wd >= (slot ? upper_wds : lower_wds))
1469 continue;
1470 if (! sub_enable[slot * 2 + (local_wd >= half_wds ? 1 : 0)])
1471 continue;
1472 uint home_store = up->lwr ? 1 - slot : slot;
1473 uint home = home_store * stride_wds + local_wd;
1474 uint rel = (home + (4u << 20) - scu_base_wds) % (4u << 20);
1475 cpu.sc_fine_phys[port_num][slot][unit] =
1476 (int) port_num * (int) ZONE_SZ + (int) rel;
1477 }
1478
1479
1480
1481 continue;
1482 }
1483
1484
1485
1486 uint scu_base_bks = scu_base_wds / SCBANK_SZ;
1487 for (uint n_bank = 0; n_bank < port_banks; n_bank ++)
1488 {
1489 uint scu_wd = scu_base_wds + n_bank * SCBANK_SZ;
1490 if (scu_wd >= lower_wds + upper_wds || scu_wd >= nea_wds)
1491 continue;
1492 uint slot = scu_wd >= lower_wds ? 1 : 0;
1493 uint local_wd = scu_wd - slot * lower_wds;
1494 if (! sub_enable[slot * 2 + (local_wd >= half_wds ? 1 : 0)])
1495 continue;
1496 uint addr_bks = base_addr_bks + n_bank;
1497 if (addr_bks >= N_SCBANKS)
1498 continue;
1499 if (cpu.sc_addr_map [addr_bks] != -1)
1500 continue;
1501 uint home_store = up->lwr ? 1 - slot : slot;
1502 uint home_bks = (home_store * stride_wds + local_wd) / SCBANK_SZ;
1503 int phys_bank = scu_phys_bank (home_bks, 0, scu_base_bks);
1504 cpu.sc_addr_map[addr_bks] = (int) port_num * (int) ZONE_SZ + phys_bank * (int) SCBANK_SZ;
1505 cpu.sc_scu_map[addr_bks] = port_num;
1506 }
1507 }
1508 }
1509
1510
1511
1512
1513
1514
1515 int sc_port_for_addr (cpu_state_t * cpup, word24 addr)
1516 {
1517 if (cpu.sc_fine)
1518 for (uint port_num = 0; port_num < N_SCU_PORTS; port_num ++)
1519 {
1520 if (! cpu.sc_fine_port[port_num])
1521 continue;
1522 uint base = cpu.sc_fine_base[port_num];
1523 if (addr >= base && addr - base < cpu.sc_fine_window[port_num])
1524 return (int) port_num;
1525 }
1526 uint pg = addr / SCBANK_SZ;
1527 if (pg >= N_SCBANKS)
1528 return -1;
1529 return cpu.sc_scu_map[pg];
1530 }
1531
1532
1533
1534 int tandd_scu_for_addr (cpu_state_t * cpup, word24 addr)
1535 {
1536 int port = sc_port_for_addr (cpup, addr);
1537 if (port < 0)
1538 return -1;
1539 return (int) cables->cpu_to_scu[current_running_cpu_idx][port].scu_unit_idx;
1540 }
1541
1542
1543
1544
1545
1546 static bool consume_parity_bits (cpu_state_t * cpup)
1547 {
1548 bool zac = cpu.MR.separ;
1549 cpu.MR.separ = 0;
1550 cpu.MR.sdpap = 0;
1551 putbits36_1 (& cpu.MR.r, 20, 0);
1552 putbits36_1 (& cpu.MR.r, 21, 0);
1553 return zac;
1554 }
1555
1556
1557
1558 static int ia_priority (uint ia)
1559 {
1560 static const int prio [16] = { 99, 99, 5, 1, 99, 12, 11, 10, 4, 13, 3, 7, 2, 6, 8, 9 };
1561 return prio [ia & 017];
1562 }
1563
1564
1565
1566
1567
1568
1569
1570 bool sdpap_store (cpu_state_t * cpup, word24 addr, word36 * data, uint nWords)
1571 {
1572 if (! cpu.tweaks.tandd_mode)
1573 return false;
1574 bool notReady = scuGoInhibitMask && scuStoreNotReady (cpup, addr);
1575 bool parity = cpu.MR.separ || cpu.MR.sdpap;
1576 if (! (notReady || parity))
1577 return false;
1578 bool zac = false, doStore = ! notReady, keepBadParity = false;
1579 uint ia = 0;
1580 if (parity)
1581 {
1582
1583 zac = consume_parity_bits (cpup);
1584 bool parityStore;
1585 ia = scuStoreParityIA (cpup, addr, zac, & parityStore, & keepBadParity);
1586 doStore = doStore && parityStore;
1587 }
1588
1589 if (notReady && (! ia || ia_priority (013) < ia_priority (ia)))
1590 {
1591 tandd_set_nea_port (cpup, addr);
1592 doFault (FAULT_STR, (_fault_subtype) {.fault_str_subtype=flt_str_nrdy}, "store unit not ready");
1593 }
1594 if (doStore)
1595 {
1596 if (cpu.useZone)
1597 core_write_zone (cpup, addr, * data, "PARITY_STORE");
1598 else
1599 core_writeN (cpup, addr, data, nWords, "PARITY_STORE");
1600 if (keepBadParity && ! zac)
1601 for (uint i = 0; i < nWords; i ++)
1602 bad_parity_mark (addr + i);
1603 }
1604 if (ia)
1605 {
1606 tandd_set_nea_port (cpup, addr);
1607 SETF (cpu.cu.IR, I_PERR);
1608 if (! TST_I_PMASK)
1609 doFault (FAULT_PAR, (_fault_subtype) {.bits=ia}, zac ? "separ" : "sdpap");
1610 }
1611 return true;
1612 }
1613
1614
1615
1616
1617
1618 bool sc_command_parity (cpu_state_t * cpup, uint scuUnitIdx, uint cpuPortNum)
1619 {
1620 if (! cpu.tweaks.tandd_mode || ! (cpu.MR.separ || cpu.MR.sdpap))
1621 return false;
1622 bool zac = consume_parity_bits (cpup);
1623 uint ia = scuCommandParityIA (scuUnitIdx, zac);
1624 if (! ia)
1625 return false;
1626 cpu.neaPort = (word3) cpuPortNum;
1627 SETF (cpu.cu.IR, I_PERR);
1628 if (! TST_I_PMASK)
1629 doFault (FAULT_PAR, (_fault_subtype) {.bits=ia}, zac ? "separ command" : "sdpap command");
1630 return true;
1631 }
1632
1633
1634
1635
1636 #define N_BAD_PARITY 16
1637 uint nBadParity = 0;
1638 static word24 badParity[N_BAD_PARITY];
1639
1640 void bad_parity_mark (word24 addr)
1641 {
1642 for (uint i = 0; i < nBadParity; i ++)
1643 if (badParity[i] == addr)
1644 return;
1645 if (nBadParity < N_BAD_PARITY)
1646 badParity[nBadParity ++] = addr;
1647 }
1648
1649 void bad_parity_clear (word24 addr)
1650 {
1651 for (uint i = 0; i < nBadParity; i ++)
1652 if (badParity[i] == addr)
1653 {
1654 badParity[i] = badParity[-- nBadParity];
1655 return;
1656 }
1657 }
1658
1659 bool bad_parity_marked (word24 addr)
1660 {
1661 for (uint i = 0; i < nBadParity; i ++)
1662 if (badParity[i] == addr)
1663 return true;
1664 return false;
1665 }
1666
1667
1668
1669
1670
1671
1672
1673 void bad_parity_read (cpu_state_t * cpup, word24 addr)
1674 {
1675 if (! cpu.tweaks.tandd_mode)
1676 return;
1677 bool upper = bad_parity_marked (addr & ~1u);
1678 bool lower = bad_parity_marked (addr | 1u);
1679 if (addr & 1)
1680 {
1681 if (! lower)
1682 return;
1683 upper = true;
1684 }
1685 else if (! (upper || lower))
1686 return;
1687 word24 badAddr = (addr & 1) ? addr : (bad_parity_marked (addr) ? addr : (addr | 1u));
1688 uint ia = scuReadParityIA (cpup, badAddr);
1689 SETF (cpu.cu.IR, I_PERR);
1690 if (TST_I_PMASK)
1691 return;
1692 tandd_set_nea_port (cpup, badAddr);
1693 doFault (FAULT_PAR,
1694 (_fault_subtype) {.bits=(upper ? 0100u : 0u) | (lower ? 0200u : 0u) | ia},
1695 "bad parity read");
1696 }
1697
1698
1699
1700
1701 void sc_lockout_wait (cpu_state_t * cpup)
1702 {
1703 if (cpu.cycle == FETCH_cycle)
1704 return;
1705 cpu.scLockedOut = false;
1706 cpu.rTR = (cpu.rTR - 16u) & MASK27;
1707 cpu.lufTicks += 16;
1708 cpu.tanddTRTicks += 16;
1709 }
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721 bool sc_fine_map (cpu_state_t * cpup, word24 addr, uint * realp)
1722 {
1723 for (uint port_num = 0; port_num < N_SCU_PORTS; port_num ++)
1724 {
1725 if (! cpu.sc_fine_port[port_num])
1726 continue;
1727 uint base = cpu.sc_fine_base[port_num];
1728 if (addr < base || addr - base >= cpu.sc_fine_window[port_num])
1729 continue;
1730 uint scu = cpu.sc_fine_scu_base[port_num] + (addr - base);
1731 uint lower = cpu.sc_fine_lower_wds[port_num];
1732 uint upper = cpu.sc_fine_upper_wds[port_num];
1733 uint store, word;
1734 bool present = true;
1735 if (cpu.sc_fine_interlace[port_num])
1736 {
1737 if (scu >= 2 * lower)
1738 present = false;
1739 store = (scu >> 1) & 1;
1740 word = ((scu >> 2) << 1) | (scu & 1);
1741
1742
1743
1744 if (present && store && ! upper)
1745 {
1746 tandd_set_nea_port (cpup, addr);
1747 doFault (FAULT_STR, (_fault_subtype) {.fault_str_subtype=flt_str_nrdy},
1748 "interlace: store not present");
1749 }
1750 }
1751 else
1752 {
1753 store = scu >= lower ? 1 : 0;
1754 word = scu - store * lower;
1755 if (word >= (store ? upper : lower))
1756 present = false;
1757 }
1758
1759
1760 int phys = -1;
1761 if (present && scu < cpu.sc_fine_nea_wds[port_num] && word < (4u << 20))
1762 phys = cpu.sc_fine_phys[port_num][store][word / SC_FINE_UNIT];
1763 if (phys < 0)
1764 {
1765 tandd_set_nea_port (cpup, addr);
1766 doFault (FAULT_STR, fst_str_nea, "nonexistent address");
1767 }
1768 * realp = (uint) phys + word % SC_FINE_UNIT;
1769 return true;
1770 }
1771 return false;
1772 }
1773
1774
1775
1776 void tandd_set_nea_port (cpu_state_t * cpup, word24 addr)
1777 {
1778 uint dps8m_store_table [8] =
1779 { 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304 };
1780 uint l68_store_table [8] =
1781 { 32768, 65536, 4194304, 131072, 524288, 1048576, 2097152, 262144 };
1782 cpu.neaPort = 0;
1783 cpu.neaNoPort = true;
1784 int n_ports = cpu.tweaks.l68_mode ? N_L68_CPU_PORTS : N_DPS8M_CPU_PORTS;
1785 for (int port_num = 0; port_num < n_ports; port_num ++)
1786 {
1787 if (! cpu.switches.enable [port_num])
1788 continue;
1789 uint store_size = cpu.switches.store_size [port_num];
1790
1791
1792
1793
1794 uint sz_wds = cpu.tweaks.l68_mode ?
1795 (cpu.tweaks.isolts_mode && store_size == 3 ?
1796 65536 : l68_store_table [store_size]) :
1797 dps8m_store_table [store_size];
1798 uint base = sz_wds * cpu.switches.assignment[port_num];
1799 if (addr >= base && addr - base < sz_wds)
1800 {
1801 cpu.neaPort = (word3) port_num;
1802 cpu.neaNoPort = false;
1803 return;
1804 }
1805 }
1806 }
1807
1808 void setup_scbank_map (cpu_state_t * cpup)
1809 {
1810
1811
1812
1813 cpu.sc_fine = false;
1814 for (uint p = 0; p < N_SCU_PORTS; p ++)
1815 cpu.sc_fine_port[p] = false;
1816
1817 if (cpu.tweaks.tandd_mode)
1818 {
1819 setup_scbank_map_tandd (cpup);
1820 return;
1821 }
1822
1823
1824 for (uint pg = 0; pg < N_SCBANKS; pg ++)
1825 {
1826 cpu.sc_addr_map [pg] = -1;
1827 cpu.sc_scu_map [pg] = -1;
1828 }
1829 for (uint u = 0; u < N_SCU_UNITS_MAX; u ++)
1830 cpu.sc_num_banks[u] = 0;
1831
1832
1833 for (int port_num = 0; port_num < (cpu.tweaks.l68_mode ? N_L68_CPU_PORTS : N_DPS8M_CPU_PORTS); port_num ++)
1834 {
1835
1836 if (! cpu.switches.enable [port_num])
1837 continue;
1838
1839
1840
1841
1842 if (! cables->cpu_to_scu[current_running_cpu_idx][port_num].in_use)
1843 {
1844 continue;
1845 }
1846
1847
1848 uint store_size = cpu.switches.store_size [port_num];
1849 uint dps8m_store_table [8] =
1850 { 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304 };
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865 uint l68_store_table [8] =
1866 { 32768, 65536, 4194304, 131072, 524288, 1048576, 2097152, 262144 };
1867 uint l68_isolts_store_table [8] =
1868 { 32768, 65536, 4194304, 65536, 524288, 1048576, 2097152, 262144 };
1869
1870 uint sz_wds =
1871 cpu.tweaks.l68_mode ?
1872 cpu.tweaks.isolts_mode ?
1873 l68_isolts_store_table [store_size] :
1874 l68_store_table [store_size] :
1875 dps8m_store_table [store_size];
1876
1877
1878 uint base_addr_wds = sz_wds * cpu.switches.assignment[port_num];
1879
1880
1881 uint num_banks = sz_wds / SCBANK_SZ;
1882 cpu.sc_num_banks[port_num] = num_banks;
1883 uint base_addr_bks = base_addr_wds / SCBANK_SZ;
1884
1885
1886 for (uint pg = 0; pg < num_banks; pg ++)
1887 {
1888
1889 uint addr_bks = base_addr_bks + pg;
1890
1891 if (addr_bks < N_SCBANKS)
1892 {
1893
1894 if (cpu.sc_addr_map [addr_bks] != -1)
1895 {
1896 sim_warn ("scbank overlap addr_bks %d (%o) old port %d "
1897 "newport %d\r\n",
1898 addr_bks, addr_bks, cpu.sc_addr_map [addr_bks], port_num);
1899 }
1900 else
1901 {
1902
1903 cpu.sc_addr_map[addr_bks] = (int)((int)port_num * (int)ZONE_SZ + (int)pg * (int)SCBANK_SZ);
1904 cpu.sc_scu_map[addr_bks] = port_num;
1905 }
1906 }
1907 else
1908 {
1909 sim_warn ("addr_bks too big port %d addr_bks %d (%o), "
1910 "limit %d (%o)\r\n",
1911 port_num, addr_bks, addr_bks, N_SCBANKS, N_SCBANKS);
1912 }
1913 }
1914
1915 }
1916
1917
1918
1919 }
1920
1921
1922
1923
1924
1925
1926
1927 bool tandd_io_mode (void)
1928 {
1929 return sys_opts.tandd_io;
1930 }
1931
1932 int lookup_cpu_mem_map (cpu_state_t * cpup, word24 addr)
1933 {
1934 return sc_port_for_addr (cpup, addr);
1935 }
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945 #if !defined(PERF_STRIP)
1946 static void get_serial_number (cpu_state_t * cpup)
1947 {
1948 bool havesn = false;
1949 FILE * fp = fopen ("./serial.txt", "r");
1950 while (fp && ! feof (fp))
1951 {
1952 char buffer [81] = "";
1953 # if !defined(__clang_analyzer__)
1954 char * checksn = fgets (buffer, sizeof (buffer), fp);
1955 (void)checksn;
1956 # endif
1957 uint cpun, sn;
1958 if (sscanf (buffer, "sn: %u", & sn) == 1)
1959 {
1960 if (cpu.switches.serno)
1961 sim_msg ("\r\nReplacing CPU serial number:\r\n");
1962 cpu.switches.serno = sn;
1963 if (!sim_quiet)
1964 {
1965 sim_msg ("%s CPU serial number: %u\r\n", sim_name, cpu.switches.serno);
1966 }
1967 havesn = true;
1968 }
1969 else if (sscanf (buffer, "sn%u: %u", & cpun, & sn) == 2)
1970 {
1971 if (cpun < N_CPU_UNITS_MAX)
1972 {
1973 if (cpus[cpun].switches.serno)
1974 sim_msg ("\r\nReplacing CPU %u serial number:\r\n", cpun);
1975 cpus[cpun].switches.serno = sn;
1976 if (!sim_quiet)
1977 {
1978 sim_msg ("%s CPU %u serial number: %u\r\n",
1979 sim_name, cpun, cpus[cpun].switches.serno);
1980 }
1981 havesn = true;
1982 }
1983 }
1984 }
1985 if (!havesn)
1986 {
1987 if (!sim_quiet)
1988 {
1989 sim_msg ("\r\nPlease register your system at https://dps8m.gitlab.io/register/\r\n");
1990 sim_msg ("or create the file 'serial.txt' containing the line 'sn: 0'.\r\n\r\n");
1991 }
1992 }
1993 if (fp)
1994 fclose (fp);
1995 }
1996 #endif
1997
1998 #if defined(STATS)
1999 static void do_stats (void)
2000 {
2001 static struct timespec stats_time;
2002 static bool first = true;
2003 if (first)
2004 {
2005 first = false;
2006 clock_gettime (CLOCK_BOOTTIME, & stats_time);
2007 sim_msg ("stats started\r\n");
2008 }
2009 else
2010 {
2011 struct timespec now, delta;
2012 clock_gettime (CLOCK_BOOTTIME, & now);
2013 timespec_diff (& stats_time, & now, & delta);
2014 stats_time = now;
2015 sim_msg ("stats %6ld.%02ld\r\n", delta.tv_sec,
2016 delta.tv_nsec / 10000000);
2017
2018 sim_msg ("Instruction counts\r\n");
2019 for (uint i = 0; i < 8; i ++)
2020 {
2021 # if defined(WIN_STDIO)
2022 sim_msg (" %9lld\r\n", (long long int) cpus[i].instrCnt);
2023 # else
2024 sim_msg (" %'9lld\r\n", (long long int) cpus[i].instrCnt);
2025 # endif
2026 cpus[i].instrCnt = 0;
2027 }
2028 sim_msg ("\r\n");
2029 }
2030 }
2031 #endif
2032
2033
2034
2035 #if !defined(PERF_STRIP)
2036 static void ev_poll_cb (UNUSED uv_timer_t * handle)
2037 {
2038 cpu_state_t * cpup = _cpup;
2039
2040
2041 static uint oneHz = 0;
2042 if (oneHz ++ >= sys_opts.sys_slow_poll_interval)
2043 {
2044 oneHz = 0;
2045 rdrProcessEvent ();
2046 # if defined(STATS)
2047 do_stats ();
2048 # endif
2049 cpu.instrCntT0 = cpu.instrCntT1;
2050 cpu.instrCntT1 = cpu.instrCnt;
2051 }
2052 fnpProcessEvent ();
2053 # if defined(WITH_SOCKET_DEV)
2054 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
2055 sk_process_event ();
2056 # endif
2057 # endif
2058 consoleProcess ();
2059 # if defined(IO_ASYNC_PAYLOAD_CHAN)
2060 iomProcess ();
2061 # endif
2062 # if defined(WITH_ABSI_DEV)
2063 # if !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
2064 absi_process_event ();
2065 # endif
2066 # endif
2067 # if defined(WITH_MGP_DEV)
2068 mgp_process_event ();
2069 # endif
2070 # if defined(WITH_NET_DEV)
2071 net_process_event ();
2072 # endif
2073 PNL (panel_process_event ());
2074 }
2075 #endif
2076
2077
2078
2079 void cpu_init (void)
2080 {
2081
2082
2083
2084 M = system_state->M;
2085 #if defined(M_SHARED)
2086 cpus = system_state->cpus;
2087 #endif
2088
2089 #if !defined(SPEED)
2090 (void)memset (& watch_bits, 0, sizeof (watch_bits));
2091 #endif
2092
2093 set_cpu_idx (0);
2094
2095 (void)memset (cpus, 0, sizeof (cpu_state_t) * N_CPU_UNITS_MAX);
2096
2097 #if !defined(PERF_STRIP)
2098 get_serial_number (_cpup);
2099
2100 ev_poll_loop = uv_default_loop ();
2101 uv_timer_init (ev_poll_loop, & ev_poll_handle);
2102
2103 unsigned int poll_interval = sys_opts.sys_poll_interval;
2104 uv_timer_start (& ev_poll_handle, ev_poll_cb, poll_interval, poll_interval);
2105 #endif
2106
2107
2108 cpu_state_t * cpup = _cpup;
2109
2110 cpu.instrCnt = 0;
2111 cpu.cycleCnt = 0;
2112 for (int i = 0; i < N_FAULTS; i ++)
2113 cpu.faultCnt [i] = 0;
2114
2115 #if defined(MATRIX)
2116 initializeTheMatrix ();
2117 #endif
2118 }
2119
2120 void cpu_stop_poll_timer (void)
2121 {
2122 #if !defined(PERF_STRIP)
2123 if (ev_poll_loop && !uv_is_closing ((uv_handle_t *) & ev_poll_handle))
2124 {
2125 (void)uv_timer_stop (& ev_poll_handle);
2126 uv_close ((uv_handle_t *) & ev_poll_handle, NULL);
2127 }
2128 #endif
2129 }
2130
2131 static void cpu_reset (void)
2132 {
2133 for (uint i = 0; i < N_CPU_UNITS_MAX; i ++)
2134 {
2135 cpu_reset_unit_idx (i, true);
2136 }
2137
2138 set_cpu_idx (0);
2139
2140 #if defined(TESTING)
2141 cpu_state_t * cpup = _cpup;
2142 sim_debug (DBG_INFO, & cpu_dev, "CPU reset: Running\r\n");
2143 #endif
2144 }
2145
2146 static t_stat sim_cpu_reset (UNUSED DEVICE *dptr)
2147 {
2148
2149
2150
2151
2152
2153 cpu_reset ();
2154 return SCPE_OK;
2155 }
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165 static t_stat cpu_ex (t_value *vptr, t_addr addr, UNUSED UNIT * uptr,
2166 UNUSED int32 sw)
2167 {
2168 if (addr>= MEMSIZE)
2169 return SCPE_NXM;
2170 if (vptr != NULL)
2171 {
2172 *vptr = M[addr] & DMASK;
2173 }
2174 return SCPE_OK;
2175 }
2176
2177
2178
2179 static t_stat cpu_dep (t_value val, t_addr addr, UNUSED UNIT * uptr,
2180 UNUSED int32 sw)
2181 {
2182 if (addr >= MEMSIZE) return SCPE_NXM;
2183 M[addr] = val & DMASK;
2184 return SCPE_OK;
2185 }
2186
2187
2188
2189
2190
2191 #if defined(M_SHARED)
2192
2193 static word18 dummy_IC;
2194 #endif
2195
2196 static REG cpu_reg[] =
2197 {
2198
2199 #if defined(M_SHARED)
2200 { ORDATA (IC, dummy_IC, VASIZE), 0, 0, 0 },
2201 #else
2202 { ORDATA (IC, cpus[0].PPR.IC, VASIZE), 0, 0, 0 },
2203 #endif
2204 { NULL, NULL, 0, 0, 0, 0, NULL, NULL, 0, 0, 0 }
2205 };
2206
2207
2208
2209
2210
2211 REG *sim_PC = & cpu_reg[0];
2212
2213
2214
2215 DEVICE cpu_dev =
2216 {
2217 "CPU",
2218 cpu_unit,
2219 cpu_reg,
2220 cpu_mod,
2221 N_CPU_UNITS,
2222 8,
2223 PASIZE,
2224 1,
2225 8,
2226 36,
2227 & cpu_ex,
2228 & cpu_dep,
2229 & sim_cpu_reset,
2230 & cpu_boot,
2231 NULL,
2232 NULL,
2233 NULL,
2234 DEV_DEBUG,
2235 0,
2236 cpu_dt,
2237 NULL,
2238 NULL,
2239 NULL,
2240 NULL,
2241 NULL,
2242 NULL,
2243 NULL
2244 };
2245
2246 #if defined(M_SHARED)
2247 cpu_state_t * cpus = NULL;
2248 #else
2249 cpu_state_t cpus [N_CPU_UNITS_MAX];
2250 #endif
2251 #if defined(THREADZ) || defined(LOCKLESS)
2252 __thread cpu_state_t * restrict _cpup;
2253 #else
2254 cpu_state_t * restrict _cpup;
2255 #endif
2256
2257
2258
2259
2260
2261
2262
2263 static uint get_highest_intr (cpu_state_t *cpup)
2264 {
2265 uint fp = 1;
2266 for (uint scu_unit_idx = 0; scu_unit_idx < N_SCU_UNITS_MAX; scu_unit_idx ++)
2267 {
2268 if (cpu.events.XIP [scu_unit_idx])
2269 {
2270 fp = scu_get_highest_intr (scu_unit_idx);
2271 if (fp != 1)
2272 break;
2273 }
2274 }
2275 return fp;
2276 }
2277
2278
2279
2280
2281
2282 static int disDiagOn = -1;
2283 static uint32 disDiagStart[N_CPU_UNITS_MAX];
2284 static uint32 disDiagXip[N_CPU_UNITS_MAX];
2285
2286 static bool disDiagEnabled (void)
2287 {
2288 if (disDiagOn < 0)
2289 disDiagOn = getenv ("DPS8_DIS_DIAG") != NULL;
2290 return disDiagOn;
2291 }
2292
2293 void disDiagEnter (cpu_state_t * cpup)
2294 {
2295 uint i = (uint) current_running_cpu_idx;
2296 #if defined(THREADZ) || defined(LOCKLESS)
2297 if (cpu.inMultics)
2298 return;
2299 #else
2300 (void) cpup;
2301 #endif
2302 if (! disDiagEnabled () || i >= N_CPU_UNITS_MAX)
2303 return;
2304 if (disDiagStart[i] == 0)
2305 {
2306 disDiagStart[i] = sim_os_msec () | 1;
2307 disDiagXip[i] = 0;
2308 }
2309 }
2310
2311 void disDiagInterruptSet (uint i)
2312 {
2313 if (! disDiagEnabled () || i >= N_CPU_UNITS_MAX)
2314 return;
2315 if (disDiagStart[i] != 0 && disDiagXip[i] == 0)
2316 disDiagXip[i] = sim_os_msec () | 1;
2317 }
2318
2319 void disDiagWake (cpu_state_t * cpup)
2320 {
2321 uint i = (uint) current_running_cpu_idx;
2322 if (! disDiagEnabled () || i >= N_CPU_UNITS_MAX || disDiagStart[i] == 0)
2323 return;
2324 uint32 now = sim_os_msec ();
2325
2326 uint32 total = now > disDiagStart[i] ? now - disDiagStart[i] : 0;
2327 if (total > 3000)
2328 {
2329 if (disDiagXip[i])
2330 sim_printf ("DISDIAG CPU %c DIS at %06o: %u ms; interrupt set after %u ms, "
2331 "noticed %u ms later\r\n", 'A' + i, cpu.PPR.IC, total,
2332 disDiagXip[i] > disDiagStart[i] ? disDiagXip[i] - disDiagStart[i] : 0,
2333 now > disDiagXip[i] ? now - disDiagXip[i] : 0);
2334 else
2335 sim_printf ("DISDIAG CPU %c DIS at %06o: %u ms; no interrupt seen being set\r\n",
2336 'A' + i, cpu.PPR.IC, total);
2337 }
2338 disDiagStart[i] = 0;
2339 disDiagXip[i] = 0;
2340 }
2341
2342 bool sample_interrupts (cpu_state_t * cpup)
2343 {
2344 cpu.lufCounter = 0;
2345 cpu.lufTicks = 0;
2346 for (uint scu_unit_idx = 0; scu_unit_idx < N_SCU_UNITS_MAX; scu_unit_idx ++)
2347 {
2348 if (cpu.events.XIP [scu_unit_idx])
2349 {
2350 return true;
2351 }
2352 }
2353 return false;
2354 }
2355
2356 t_stat simh_hooks (cpu_state_t * cpup)
2357 {
2358 int reason = 0;
2359
2360 if (breakEnable && stop_cpu)
2361 return STOP_STOP;
2362
2363 if (cpu.tweaks.isolts_mode == 0)
2364 {
2365
2366 if (sim_interval <= 0)
2367 {
2368 reason = sim_process_event ();
2369 if ((! breakEnable) && reason == SCPE_STOP)
2370 reason = SCPE_OK;
2371 if (reason)
2372 return reason;
2373 }
2374 }
2375
2376 sim_interval --;
2377
2378 #if !defined(THREADZ) && !defined(LOCKLESS)
2379
2380
2381
2382 if (sim_brk_summ &&
2383 sim_brk_test ((cpu.PPR.IC & 0777777) |
2384 ((((t_addr) cpu.PPR.PSR) & 037777) << 18),
2385 SWMASK ('E')))
2386 return STOP_BKPT;
2387 # if !defined(SPEED)
2388 if (sim_deb_break && cpu.cycleCnt >= sim_deb_break)
2389 return STOP_BKPT;
2390 # endif
2391 #endif
2392
2393 return reason;
2394 }
2395
2396 #if defined(PANEL68)
2397 static void panel_process_event (void)
2398 {
2399 cpu_state_t * cpup = _cpup;
2400
2401 if (cpu.panelInitialize && cpu.DATA_panel_s_trig_sw == 0)
2402 {
2403
2404 while (cpu.panelInitialize)
2405 ;
2406 if (cpu.DATA_panel_init_sw)
2407 cpu_reset_unit_idx (ASSUME0, true);
2408 else
2409 cpu_reset_unit_idx (ASSUME0, false);
2410
2411 do_boot ();
2412 }
2413
2414 if (cpu.DATA_panel_s_trig_sw == 0 &&
2415 cpu.DATA_panel_execute_sw &&
2416 cpu.DATA_panel_scope_sw &&
2417 cpu.DATA_panel_exec_sw == 0)
2418
2419 {
2420
2421 while (cpu.DATA_panel_execute_sw)
2422 ;
2423
2424 if (cpu.DATA_panel_exec_sw)
2425 {
2426 cpu_reset_unit_idx (ASSUME0, false);
2427 cpu.cu.IWB = cpu.switches.data_switches;
2428 set_cpu_cycle (cpup, EXEC_cycle);
2429 }
2430 else
2431 {
2432 setG7fault (current_running_cpu_idx, FAULT_EXF);
2433 }
2434 }
2435 }
2436 #endif
2437
2438 #if defined(THREADZ) || defined(LOCKLESS)
2439 bool bce_dis_called = false;
2440
2441
2442 t_stat sim_instr (void)
2443 {
2444 cpu_state_t * cpup = _cpup;
2445 t_stat reason = 0;
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491 if (cpuThreadz[0].run == false)
2492 createCPUThread (0);
2493 do
2494 {
2495
2496 reason = simh_hooks (cpup);
2497 if (reason)
2498 {
2499 break;
2500 }
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528 if (bce_dis_called) {
2529
2530 reason = STOP_STOP;
2531 break;
2532 }
2533
2534 # if !defined(PERF_STRIP)
2535
2536
2537 # if defined(LOCKLESS)
2538 lock_iom();
2539 # endif
2540 lock_libuv ();
2541 uv_run (ev_poll_loop, UV_RUN_NOWAIT);
2542 unlock_libuv ();
2543 # if defined(LOCKLESS)
2544 unlock_iom();
2545 # endif
2546 PNL (panel_process_event ());
2547
2548 int con_unit_idx = check_attn_key ();
2549 if (con_unit_idx != -1)
2550 console_attn_idx (con_unit_idx);
2551 # endif
2552
2553 # if defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
2554 struct timespec next_time;
2555 clock_gettime (CLOCK_REALTIME, & next_time);
2556 next_time.tv_nsec += 1000l * 1000l;
2557 if (next_time.tv_nsec >= 1000l * 1000l *1000l)
2558 {
2559 next_time.tv_nsec -= 1000l * 1000l *1000l;
2560 next_time.tv_sec += (time_t) 1;
2561 }
2562 struct timespec new_time;
2563 do
2564 {
2565 pthread_mutex_lock (& iom_start_lock);
2566 pthread_cond_timedwait (& iomCond,
2567 & iom_start_lock,
2568 & next_time);
2569 pthread_mutex_unlock (& iom_start_lock);
2570 lock_iom();
2571 lock_libuv ();
2572
2573 iomProcess ();
2574
2575 unlock_libuv ();
2576 unlock_iom ();
2577
2578 clock_gettime (CLOCK_REALTIME, & new_time);
2579 }
2580 while ((next_time.tv_sec == new_time.tv_sec) ? (next_time.tv_nsec > new_time.tv_nsec) : \
2581 (next_time.tv_sec > new_time.tv_sec));
2582 # else
2583 sim_usleep (1000);
2584 # endif
2585 }
2586 while (reason == 0);
2587
2588 for (uint cpuNo = 0; cpuNo < N_CPU_UNITS_MAX; cpuNo ++) {
2589 cpuStats (cpuNo);
2590 }
2591
2592 # if defined(TESTING)
2593 HDBGPrint ();
2594 # endif
2595 return reason;
2596 }
2597 #endif
2598
2599 #if !defined(THREADZ) && !defined(LOCKLESS)
2600 static uint fast_queue_subsample = 0;
2601 #endif
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651 #if defined(THREADZ) || defined(LOCKLESS)
2652 void * cpu_thread_main (void * arg)
2653 {
2654 int myid = * (int *) arg;
2655 set_cpu_idx ((uint) myid);
2656 unsigned char umyid = (unsigned char)toupper('a' + (int)myid);
2657 char thread_name[SIR_MAXPID] = {0};
2658 char temp_thread_name[SIR_MAXPID] = {0};
2659
2660 _cpup->thread_id = pthread_self();
2661
2662 if (realtime_ok) {
2663 set_realtime_priority (pthread_self(), realtime_max_priority() - 1);
2664 check_realtime_priority (pthread_self(), realtime_max_priority() - 1);
2665 } else {
2666 # if !defined(__QNX__)
2667 (void)sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
2668 # endif
2669 }
2670 _sir_snprintf_trunc(thread_name, SIR_MAXPID, "CPU %c", (unsigned int)umyid);
2671 if (!_sir_setthreadname(thread_name) || !_sir_getthreadname(temp_thread_name))
2672 (void)sir_info ("%s thread created (TID " SIR_TIDFORMAT ")",
2673 thread_name, PID_CAST _sir_gettid());
2674 else
2675 (void)sir_info ("Thread created (TID " SIR_TIDFORMAT ")",
2676 PID_CAST _sir_gettid());
2677 # if defined(TESTING) && defined(__APPLE__) && defined(__MACH__)
2678 (void)sir_info ("Mach thread ID: 0x%x", pthread_mach_thread_np(pthread_self()));
2679 # endif
2680 bool warned = false;
2681 if (realtime_ok) {
2682 if (myid + 2 > nprocs) {
2683 (void)sir_warn ("Total number of supervisor and CPU threads (%lu) exceeds available host parallelism (%lu)!",
2684 (unsigned long)(myid) + 2, (unsigned long)nprocs);
2685 warned = true;
2686 }
2687 if (!warned && nprocs >= 2 && ncores >= 1 && nprocs >= ncores && myid + 2 > ncores) {
2688 (void)sir_warn ("Total number of supervisor and CPU threads (%lu) exceeds physical host core count (%lu)!",
2689 (unsigned long)(myid) + 2, (unsigned long)ncores);
2690 }
2691 } else {
2692 if (myid + 1 > nprocs) {
2693 (void)sir_warn ("Total number of CPU threads (%lu) exceeds available host parallelism (%lu)!",
2694 (unsigned long)(myid) + 1, (unsigned long)nprocs);
2695 warned = true;
2696 }
2697 if (!warned && ncores >= 1 && nprocs >= ncores && myid + 1 > ncores) {
2698 (void)sir_warn ("Total number of CPU threads (%lu) exceeds physical host core count (%lu)!",
2699 (unsigned long)(myid) + 1, (unsigned long)ncores);
2700 }
2701 }
2702 setSignals ();
2703 threadz_sim_instr ();
2704 return NULL;
2705 }
2706 #endif
2707
2708 NO_RETURN
2709 static void do_LUF_fault (cpu_state_t * cpup)
2710 {
2711
2712
2713
2714
2715
2716 if ((cpu.tweaks.tandd_mode || cpu.tweaks.isolts_mode) &&
2717 ! cpu.tweaks.l68_mode &&
2718 cpu.cycle == PSEUDO_FETCH_cycle && cpu.lufAfterXfer)
2719 {
2720 cpu.PPR.IC = cpu.lufXferIC;
2721 cpu.lufRFI = true;
2722 }
2723 CPT (cpt1U, 16);
2724 cpu.lufTicks = 0;
2725 cpu.lufCounter = 0;
2726 cpu.lufOccurred = false;
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748 if (cpu.tweaks.isolts_mode && ! cpu.tweaks.tandd_mode)
2749 cpu.shadowTR = (word27) cpu.TR0 - (1024u << (is_priv_mode (cpup) ? 4 : cpu.CMR.luf));
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762 doFault (FAULT_LUF, fst_zero, "instruction cycle lockup");
2763 }
2764
2765 #if !defined(THREADZ) && !defined(LOCKLESS)
2766 # define threadz_sim_instr sim_instr
2767 #endif
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779 static void set_temporary_absolute_mode (cpu_state_t * cpup)
2780 {
2781 CPT (cpt1L, 20);
2782 cpu.secret_addressing_mode = true;
2783 cpu.cu.XSF = false;
2784 sim_debug (DBG_TRACEEXT, & cpu_dev, "set_temporary_absolute_mode bit 29 sets XSF to 0\r\n");
2785
2786 }
2787
2788 static bool clear_temporary_absolute_mode (cpu_state_t * cpup)
2789 {
2790 CPT (cpt1L, 21);
2791 cpu.secret_addressing_mode = false;
2792 return cpu.cu.XSF;
2793
2794 }
2795
2796 #if defined(THREADZ) || defined(LOCKLESS)
2797 static const int workAllocationQuantum = 64;
2798 static const int syncClockModePollRate = 64;
2799 static const int masterCycleCntlimit = 2048;
2800
2801
2802
2803
2804
2805
2806 static const uint32 slaveWaitLimitMs = 10000;
2807 static const uint32 slaveStartLimitMs = 10;
2808
2809 void becomeClockMaster (uint cpuNum) {
2810
2811 # ifdef SYNCTEST
2812 sim_printf ("CPU%c %s entry\r\n", cpuNum + 'A', __func__);
2813 allocCount = 0;
2814 # endif
2815
2816
2817
2818
2819 if (syncClockMode) {
2820
2821
2822
2823 return;
2824 }
2825
2826 syncClockModeMasterIdx = cpuNum;
2827 cpu_state_t * cpup = & cpus[cpuNum];
2828 cpu.syncClockModeMaster = true;
2829 cpu.masterCycleCnt = 0;
2830 cpu.syncClockModeCache = true;
2831 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
2832 if (i != cpuNum) {
2833 cpus[i].workAllocation = 0;
2834 __asm volatile ("");
2835 atomic_thread_fence (memory_order_seq_cst);
2836 if (cpus[i].inMultics && ! cpus[i].isSlave) {
2837 cpus[i].syncClockModePoll = 0;
2838 __asm volatile ("");
2839 atomic_thread_fence (memory_order_seq_cst);
2840 cpus[i].becomeSlave = true;
2841 __asm volatile ("");
2842 atomic_thread_fence (memory_order_seq_cst);
2843 }
2844 }
2845 }
2846
2847 __asm volatile ("");
2848 atomic_thread_fence (memory_order_seq_cst);
2849 syncClockMode = true;
2850
2851 __asm volatile ("");
2852 atomic_thread_fence (memory_order_seq_cst);
2853
2854 }
2855
2856 void giveupClockMaster (cpu_state_t * cpup) {
2857
2858 # ifdef SYNCTEST
2859
2860 sim_printf ("CPU%c %s entry\r\n", cpu.cpuIdx + 'A', __func__);
2861 sim_printf ("CPU%c Alloc count %d\r\n", cpu.cpuIdx + 'A', allocCount);
2862 # endif
2863 __asm volatile ("");
2864 cpu.syncClockModeMaster = false;
2865 __asm volatile ("");
2866 syncClockMode = false;
2867 __asm volatile ("");
2868 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
2869 cpus[i].syncClockModeCache = false;
2870 }
2871 __asm volatile ("");
2872 atomic_thread_fence (memory_order_seq_cst);
2873
2874 }
2875 #endif
2876
2877 t_stat threadz_sim_instr (void)
2878 {
2879 cpu_state_t * cpup = _cpup;
2880
2881
2882 #if !defined(SCHED_NEVER_YIELD)
2883 unsigned long long lockYieldAll = 0;
2884 #endif
2885 unsigned long long lockWaitMaxAll = 0;
2886 unsigned long long lockWaitAll = 0;
2887 unsigned long long lockImmediateAll = 0;
2888 unsigned long long lockCntAll = 0;
2889 unsigned long long instrCntAll = 0;
2890 unsigned long long cycleCntAll = 0;
2891
2892 t_stat reason = 0;
2893
2894 #if !defined(THREADZ) && !defined(LOCKLESS)
2895 set_cpu_idx (0);
2896 # if defined(M_SHARED)
2897
2898
2899
2900
2901 cpus [0].PPR.IC = dummy_IC;
2902 # endif
2903
2904 #endif
2905
2906
2907 int val = setjmp (cpu.jmpMain);
2908
2909 switch (val)
2910 {
2911 case JMP_ENTRY:
2912 case JMP_REENTRY:
2913 reason = 0;
2914 break;
2915 case JMP_SYNC_FAULT_RETURN:
2916 set_cpu_cycle (cpup, SYNC_FAULT_RTN_cycle);
2917 break;
2918 case JMP_STOP:
2919 reason = STOP_STOP;
2920 goto leave;
2921 case JMP_REFETCH:
2922
2923
2924
2925
2926
2927
2928
2929 cpu.wasXfer = false;
2930
2931 set_cpu_cycle (cpup, FETCH_cycle);
2932 break;
2933 case JMP_RESTART:
2934 set_cpu_cycle (cpup, EXEC_cycle);
2935 break;
2936 case JMP_FORCE_RESTART:
2937
2938
2939
2940
2941
2942
2943 cpu_reset_unit_idx (current_running_cpu_idx, false);
2944 #if defined(THREADZ) || defined(LOCKLESS)
2945
2946 if (syncClockMode && syncClockModeMasterIdx == current_running_cpu_idx)
2947 giveupClockMaster (cpup);
2948 #endif
2949 break;
2950 default:
2951 sim_warn ("longjmp value of %d unhandled\r\n", val);
2952 goto leave;
2953 }
2954
2955
2956
2957 DCDstruct * ci = & cpu.currentInstruction;
2958
2959 if (cpu.restart)
2960 {
2961 set_cpu_cycle (cpup, FAULT_cycle);
2962 }
2963
2964 #if defined(THREADZ) || defined(LOCKLESS)
2965
2966
2967
2968
2969 __asm volatile ("");
2970 cpu.executing = true;
2971 if (cpu.tweaks.isolts_mode) {
2972 ;
2973 } else {
2974 cpu.inMultics = true;
2975 }
2976 #endif
2977
2978 do
2979 {
2980
2981 reason = 0;
2982
2983 #if !defined(THREADZ) && !defined(LOCKLESS)
2984
2985 reason = simh_hooks (cpup);
2986 if (reason)
2987 {
2988 break;
2989 }
2990
2991
2992
2993
2994
2995
2996
2997
2998 if (fast_queue_subsample ++ > sys_opts.sys_poll_check_rate)
2999 {
3000 fast_queue_subsample = 0;
3001 # if defined(CONSOLE_FIX)
3002 # if defined(THREADZ) || defined(LOCKLESS)
3003 lock_libuv ();
3004 # endif
3005 # endif
3006 uv_run (ev_poll_loop, UV_RUN_NOWAIT);
3007 # if defined(CONSOLE_FIX)
3008 # if defined(THREADZ) || defined(LOCKLESS)
3009 unlock_libuv ();
3010 # endif
3011 # endif
3012 PNL (panel_process_event ());
3013 }
3014 #endif
3015
3016 cpu.cycleCnt ++;
3017
3018 #if defined(THREADZ)
3019
3020 unlock_mem_force ();
3021
3022
3023 cpuRunningWait ();
3024 #endif
3025 #if defined(LOCKLESS)
3026 core_unlock_all (cpup);
3027 #endif
3028
3029 #if !defined(LOCKLESS)
3030 int con_unit_idx = check_attn_key ();
3031 if (con_unit_idx != -1)
3032 console_attn_idx (con_unit_idx);
3033 #endif
3034
3035 #if !defined(THREADZ) && !defined(LOCKLESS)
3036 if (cpu.tweaks.isolts_mode)
3037 {
3038 if (cpu.cycle != FETCH_cycle)
3039 {
3040
3041 cpu.rTRlsb ++;
3042 if (cpu.rTRlsb >= 4)
3043 {
3044 cpu.rTRlsb = 0;
3045 cpu.shadowTR = (cpu.shadowTR - 1) & MASK27;
3046 if (cpu.shadowTR == 0)
3047 {
3048 if (cpu.tweaks.tro_enable)
3049 setG7fault (current_running_cpu_idx, FAULT_TRO);
3050 }
3051 }
3052 }
3053 }
3054 #endif
3055
3056
3057
3058
3059
3060
3061
3062
3063 if (cpu.tweaks.tandd_mode)
3064 {
3065
3066
3067
3068 cpu.rTRticks = 0;
3069 if (++ cpu.rTRlsb >= 4)
3070 {
3071 cpu.rTRlsb = 0;
3072 cpu.rTR --;
3073 cpu.lufTicks ++;
3074 cpu.tanddTRTicks ++;
3075 }
3076 }
3077 else
3078 {
3079
3080
3081
3082
3083
3084 # define TR_RATE 2
3085
3086
3087
3088 cpu.rTR = (word27) (((word27s) cpu.rTR) - (word27s) (cpu.rTRticks / TR_RATE));
3089 cpu.rTRticks %= TR_RATE;
3090
3091
3092 }
3093
3094 if (cpu.rTR & ~MASK27)
3095 {
3096 cpu.rTR &= MASK27;
3097 if (cpu.tweaks.tro_enable) {
3098 setG7fault (current_running_cpu_idx, FAULT_TRO);
3099 }
3100 }
3101
3102 sim_debug (DBG_CYCLE, & cpu_dev, "Cycle is %s\r\n",
3103 cycle_str (cpu.cycle));
3104
3105 switch (cpu.cycle)
3106 {
3107 case INTERRUPT_cycle:
3108 {
3109 CPT (cpt1U, 0);
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121 uint intr_pair_addr = get_highest_intr (cpup);
3122 #if defined(TESTING)
3123 HDBGIntr (intr_pair_addr, "");
3124 #endif
3125 cpu.cu.FI_ADDR = (word5) (intr_pair_addr / 2);
3126 cu_safe_store (cpup);
3127
3128
3129 if (cpu.tanddFetchIntr)
3130 {
3131 cpu.scu_data[7] = cpu.tanddIRODD;
3132 putbits36_1 (& cpu.scu_data[0], 19, 0);
3133 putbits36_1 (& cpu.scu_data[5], 27, 1);
3134 putbits36_1 (& cpu.scu_data[5], 29, 1);
3135 }
3136
3137
3138
3139 CPT (cpt1U, 1);
3140
3141 set_temporary_absolute_mode (cpup);
3142
3143
3144 cpu.PPR.PRR = 0;
3145 cpu.TPR.TRR = 0;
3146
3147 sim_debug (DBG_INTR, & cpu_dev, "intr_pair_addr %u flag %d\r\n",
3148 intr_pair_addr, cpu.interrupt_flag);
3149 #if !defined(SPEED)
3150 if_sim_debug (DBG_INTR, & cpu_dev)
3151 traceInstruction (DBG_INTR);
3152 #endif
3153
3154 if (cpu.interrupt_flag)
3155 {
3156 CPT (cpt1U, 2);
3157
3158
3159
3160
3161
3162
3163 if (intr_pair_addr != 1)
3164 {
3165 CPT (cpt1U, 3);
3166
3167
3168 core_read2 (cpup, intr_pair_addr,
3169 & cpu.cu.IWB, & cpu.cu.IRODD, __func__);
3170 #if defined(TESTING)
3171 HDBGMRead (intr_pair_addr, cpu.cu.IWB, "intr even");
3172 HDBGMRead (intr_pair_addr + 1, cpu.cu.IRODD, "intr odd");
3173 #endif
3174 cpu.cu.xde = 1;
3175 cpu.cu.xdo = 1;
3176 cpu.isExec = true;
3177 cpu.isXED = true;
3178
3179 CPT (cpt1U, 4);
3180 cpu.interrupt_flag = false;
3181 cpu.tanddFetchIntr = false;
3182 set_cpu_cycle (cpup, INTERRUPT_EXEC_cycle);
3183 break;
3184 }
3185 }
3186
3187
3188
3189 CPT (cpt1U, 5);
3190 cpu.interrupt_flag = false;
3191 clear_temporary_absolute_mode (cpup);
3192
3193 cu_safe_restore (cpup);
3194 if (cpu.tanddFetchIntr)
3195 {
3196 cpu.cu.rfi = 0;
3197 cpu.cu.FIF = 0;
3198 cpu.tanddFetchIntr = false;
3199 }
3200
3201
3202 cpu.wasXfer = false;
3203
3204
3205 set_cpu_cycle (cpup, FETCH_cycle);
3206 }
3207 break;
3208
3209 case FETCH_cycle:
3210 #if defined(PANEL68)
3211 (void)memset (cpu.cpt, 0, sizeof (cpu.cpt));
3212 #endif
3213 CPT (cpt1U, 13);
3214
3215
3216
3217
3218 if (UNLIKELY (cpu.execSwitchesReq))
3219 {
3220 cpu.execSwitchesReq = false;
3221 cpu.execSwitches = true;
3222 cpu.faultNumber = FAULT_EXF;
3223 set_cpu_cycle (cpup, FAULT_cycle);
3224 break;
3225 }
3226
3227 PNL (L68_ (cpu.INS_FETCH = false;))
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264 if (get_bar_mode (cpup))
3265 get_BAR_address (cpup, cpu.PPR.IC);
3266
3267
3268
3269
3270
3271
3272
3273 cpu.tanddFetched = false;
3274 cpu.g7FetchFault = false;
3275 word36 tanddIRODD = cpu.cu.IRODD;
3276 if (cpu.tweaks.tandd_mode)
3277 {
3278 cpu.isExec = false;
3279 cpu.isXED = false;
3280 cpu.cu.XSF = 0;
3281 cpu.cu.TSN_VALID [0] = 0;
3282 cpu.TPR.TSR = cpu.PPR.PSR;
3283 cpu.TPR.TRR = cpu.PPR.PRR;
3284 PNL (cpu.prepare_state = ps_PIA);
3285 PNL (L68_ (cpu.INS_FETCH = true;))
3286 fetchInstruction (cpup, cpu.PPR.IC);
3287 cpu.tanddFetched = true;
3288 }
3289
3290
3291
3292
3293 bool tmp_priv_mode = is_priv_mode (cpup);
3294 bool is_dis = cpu.tanddFetched ?
3295 (IWB_IRODD & 0000000777400) == 0000000616000 :
3296 (cpu.currentInstruction.opcode == 0616 &&
3297 cpu.currentInstruction.opcodeX == 0);
3298 bool noCheckTR = tmp_priv_mode &&
3299 !(is_dis && GET_I (cpu.cu.IWB) == 0);
3300
3301 if (is_dis)
3302 {
3303
3304
3305 cpu.interrupt_flag = sample_interrupts (cpup);
3306 cpu.g7_flag =
3307 noCheckTR ? bG7PendingNoTRO (cpup) : bG7Pending (cpup);
3308 }
3309 else if (! (cpu.cu.xde | cpu.cu.xdo |
3310 cpu.cu.rpt | cpu.cu.rd | cpu.cu.rl))
3311 {
3312 if ((!cpu.wasInhibited) &&
3313 ! (cpu.tanddFetched && GET_I (IWB_IRODD)) &&
3314 (cpu.PPR.IC & 1) == 0 &&
3315 (! cpu.wasXfer))
3316 {
3317 CPT (cpt1U, 14);
3318 cpu.interrupt_flag = sample_interrupts (cpup);
3319 cpu.g7_flag =
3320 noCheckTR ? bG7PendingNoTRO (cpup) : bG7Pending (cpup);
3321 }
3322 cpu.wasInhibited = false;
3323 }
3324 else
3325 {
3326
3327
3328
3329
3330
3331 if ((cpu.PPR.IC & 1) == 1)
3332 {
3333 cpu.wasInhibited = true;
3334 }
3335 }
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371 if (cpu.g7_flag)
3372 {
3373 cpu.g7_flag = false;
3374 cpu.interrupt_flag = false;
3375
3376
3377
3378
3379 if (cpu.tanddFetched)
3380 {
3381 cpu.cu.IRODD = tanddIRODD;
3382 cpu.cu.XSF = 0;
3383 cpu.lufRFI = true;
3384 cpu.tanddFetchFault = true;
3385 }
3386
3387
3388
3389
3390 cpu.g7FetchFault = ! is_dis;
3391 sim_debug (DBG_CYCLE, & cpu_dev,
3392 "call doG7Fault (%d)\r\n", !noCheckTR);
3393 doG7Fault (cpup, !noCheckTR);
3394 }
3395 if (cpu.interrupt_flag)
3396 {
3397
3398
3399
3400 CPT (cpt1U, 15);
3401
3402 cpu.tanddFetchIntr = cpu.tanddFetched;
3403 cpu.tanddIRODD = tanddIRODD;
3404 set_cpu_cycle (cpup, INTERRUPT_cycle);
3405 break;
3406 }
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416 case PSEUDO_FETCH_cycle:
3417
3418 tmp_priv_mode = is_priv_mode (cpup);
3419 if (! (luf_flag && tmp_priv_mode))
3420 cpu.lufCounter ++;
3421
3422 if (LUF_OVER (cpu.CMR.luf))
3423 {
3424 if (tmp_priv_mode)
3425 {
3426
3427 cpu.lufOccurred = true;
3428 }
3429 else
3430 {
3431 do_LUF_fault (cpup);
3432 }
3433 }
3434
3435
3436 if (LUF_OVER (4))
3437 {
3438 do_LUF_fault (cpup);
3439 }
3440
3441
3442
3443 if (! tmp_priv_mode && cpu.lufOccurred)
3444 {
3445 do_LUF_fault (cpup);
3446 }
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479 if (cpu.cycle == PSEUDO_FETCH_cycle)
3480 {
3481 cpu.apu.lastCycle = INSTRUCTION_FETCH;
3482 cpu.cu.XSF = 0;
3483 cpu.cu.TSN_VALID [0] = 0;
3484 cpu.TPR.TSR = cpu.PPR.PSR;
3485 cpu.TPR.TRR = cpu.PPR.PRR;
3486 cpu.wasInhibited = false;
3487 }
3488 else if (cpu.tanddFetched)
3489 {
3490 cpu.tanddFetched = false;
3491 }
3492 else
3493 {
3494 CPT (cpt1U, 20);
3495 cpu.isExec = false;
3496 cpu.isXED = false;
3497
3498
3499
3500 cpu.cu.XSF = 0;
3501 sim_debug (DBG_TRACEEXT, & cpu_dev, "fetchCycle bit 29 sets XSF to 0\r\n");
3502 cpu.cu.TSN_VALID [0] = 0;
3503 cpu.TPR.TSR = cpu.PPR.PSR;
3504 cpu.TPR.TRR = cpu.PPR.PRR;
3505 PNL (cpu.prepare_state = ps_PIA);
3506 PNL (L68_ (cpu.INS_FETCH = true;))
3507 fetchInstruction (cpup, cpu.PPR.IC);
3508 }
3509
3510 CPT (cpt1U, 21);
3511 advanceG7Faults (cpup);
3512 set_cpu_cycle (cpup, EXEC_cycle);
3513 break;
3514
3515 case EXEC_cycle:
3516 case FAULT_EXEC_cycle:
3517 case INTERRUPT_EXEC_cycle:
3518 {
3519 #if defined(THREADZ) || defined(LOCKLESS)
3520
3521
3522 if (UNLIKELY (cpu.becomeSlave)) {
3523 cpu.becomeSlave = false;
3524
3525
3526
3527
3528
3529 uint32 startMs = sim_os_msec ();
3530 while (! syncClockMode &&
3531 sim_os_msec () - startMs < slaveStartLimitMs) {
3532 sim_usleep (1);
3533 }
3534
3535 cpu.syncClockModePoll = 0;
3536 }
3537
3538
3539 if (cpu.syncClockModeCache || --cpu.syncClockModePoll <= 0) {
3540
3541 cpu.syncClockModePoll = cpu.tweaks.isolts_mode ? 1 : syncClockModePollRate;
3542
3543
3544 if (syncClockMode) {
3545
3546
3547 cpu.syncClockModeCache = true;
3548
3549
3550 if (syncClockModeMasterIdx == current_running_cpu_idx) {
3551
3552
3553 cpu.masterCycleCnt ++;
3554 if (cpu.masterCycleCnt > masterCycleCntlimit) {
3555 # ifdef SYNCTEST
3556 sim_printf ("too many cycles\r\n");
3557 # endif
3558 giveupClockMaster (cpup);
3559 goto bail;
3560 }
3561
3562
3563 if (cpu.workAllocation <= 0) {
3564 # ifdef SYNCTEST
3565 allocCount ++;
3566 # endif
3567
3568
3569
3570
3571
3572 int64_t waitTimeout = 100000;
3573
3574
3575 while (1) {
3576 bool alldone = true;
3577 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
3578 if (cpus[i].inMultics && cpus[i].workAllocation > 0) {
3579 wakeCPU (i);
3580 alldone = false;
3581
3582 }
3583 }
3584 if (alldone) {
3585
3586 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
3587 if (cpus[i].inMultics) {
3588 cpus[i].workAllocation += cpu.tweaks.isolts_mode ? 1 : workAllocationQuantum;
3589 wakeCPU (i);
3590 }
3591 }
3592 break;
3593 }
3594 if (waitTimeout-- < 0) {
3595
3596
3597 sim_printf ("Clock master CPU %c timed out\r\n", "ABCDEFGH"[current_running_cpu_idx]);
3598 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
3599 if (cpus[i].inMultics && cpus[i].workAllocation > 0) {
3600 sim_printf ("CPU %c remaining allocation: %ld\r\n", "ABCDEFGH"[i], cpus[i].workAllocation);
3601 }
3602 }
3603 sim_printf ("Conceding clock mastery...\r\n");
3604 cpu.syncClockModeCache = false;
3605 giveupClockMaster (cpup);
3606 goto bail;
3607 }
3608 sim_usleep (1);
3609 }
3610 }
3611
3612
3613
3614 } else {
3615
3616
3617
3618
3619 if (! cpu.isSlave) {
3620
3621 # ifdef SYNCTEST
3622 sim_printf ("CPU%c becoming slave\r\n", cpu.cpuIdx + 'A');
3623 # endif
3624 }
3625 cpu.isSlave = true;
3626
3627
3628 uint32 waitStartMs = sim_os_msec ();
3629 while (syncClockMode && cpu.workAllocation <= 0) {
3630 if (sim_os_msec () - waitStartMs >= slaveWaitLimitMs) {
3631 uint masterIdx = syncClockModeMasterIdx;
3632 sim_printf ("Clock slave CPU %c: no work allocation from clock master CPU %c "
3633 "for %u s; ending clock sync\r\n",
3634 "ABCDEFGH"[current_running_cpu_idx], "ABCDEFGH"[masterIdx],
3635 (unsigned) (slaveWaitLimitMs / 1000));
3636 if (syncClockMode && masterIdx < N_CPU_UNITS_MAX)
3637 giveupClockMaster (& cpus[masterIdx]);
3638 break;
3639 }
3640 sim_usleep (1);
3641 }
3642
3643
3644
3645
3646 }
3647
3648 } else {
3649
3650 cpu.syncClockModeCache = false;
3651 if (cpu.isSlave) {
3652
3653 # ifdef SYNCTEST
3654 sim_printf ("CPU%c free; free at last\r\n", cpu.cpuIdx + 'A');
3655 # endif
3656 cpu.isSlave = false;
3657 }
3658 }
3659 }
3660 bail:
3661
3662 #endif
3663
3664 #if defined(THREADZ) || defined(LOCKLESS)
3665 if (LIKELY (! cpu.tweaks.isolts_mode) &&
3666 UNLIKELY (! cpu.inMultics)) {
3667 cpu.inMultics = true;
3668 }
3669 #endif
3670
3671 CPT (cpt1U, 22);
3672
3673 #if defined(LOCKLESS)
3674 if (stall_point_active)
3675 {
3676 for (int i = 0; i < N_STALL_POINTS; i ++)
3677 if (stall_points[i].segno && stall_points[i].segno == cpu.PPR.PSR &&
3678 stall_points[i].offset && stall_points[i].offset == cpu.PPR.IC)
3679 {
3680 # if defined(CTRACE)
3681 (void)fprintf (stderr, "%10lu %s stall %d\r\n", seqno (), cpunstr[current_running_cpu_idx], i);
3682 # endif
3683
3684 sim_usleep(stall_points[i].time);
3685 break;
3686 }
3687 }
3688 #endif
3689
3690
3691
3692
3693 if (GET_I (cpu.cu.IWB))
3694 cpu.wasInhibited = true;
3695
3696 cpu.lufExecIC = cpu.PPR.IC;
3697 cpu.lufAfterXfer = false;
3698 t_stat ret = executeInstruction (cpup);
3699 DO_WORK_EXEC;
3700 CPT (cpt1U, 23);
3701 cpu.lastTag = ci->tag;
3702 cpu.rptXnSaved = false;
3703
3704 if (cpu.tweaks.l68_mode)
3705 {
3706 add_l68_CU_history (cpup);
3707 if (cpu.adr_trap_lock)
3708 {
3709 cpu.adr_trap_lock = false;
3710 if (cpu.MR.ihrrs)
3711 cpu.MR.ihr = 0;
3712 }
3713 }
3714 else
3715 add_dps8m_CU_history (cpup);
3716
3717 if (ret > 0)
3718 {
3719 reason = ret;
3720 break;
3721 }
3722
3723 if (ret == CONT_XEC)
3724 {
3725 CPT (cpt1U, 27);
3726 cpu.wasXfer = false;
3727 cpu.isExec = true;
3728 if (cpu.cu.xdo)
3729 cpu.isXED = true;
3730
3731 cpu.cu.XSF = 0;
3732 cpu.cu.TSN_VALID [0] = 0;
3733 cpu.TPR.TSR = cpu.PPR.PSR;
3734 cpu.TPR.TRR = cpu.PPR.PRR;
3735 break;
3736 }
3737
3738 if (ret == CONT_TRA || ret == CONT_RET)
3739 {
3740 CPT (cpt1U, 24);
3741 cpu.cu.xde = cpu.cu.xdo = 0;
3742 cpu.isExec = false;
3743 cpu.isXED = false;
3744
3745 cpu.wasXfer = true;
3746
3747 if (cpu.cycle != EXEC_cycle)
3748 {
3749 clearFaultCycle (cpup);
3750
3751
3752
3753
3754
3755 if (! (cpu.currentInstruction.opcode == 0715 &&
3756 cpu.currentInstruction.opcodeX == 0))
3757 {
3758 CPT (cpt1U, 9);
3759 SET_I_NBAR;
3760 }
3761
3762 if (!clear_temporary_absolute_mode (cpup))
3763 {
3764
3765 sim_debug (DBG_TRACEEXT, & cpu_dev,
3766 "setting ABS mode\r\n");
3767 CPT (cpt1U, 10);
3768 set_addr_mode (cpup, ABSOLUTE_mode);
3769 }
3770 else
3771 {
3772
3773 sim_debug (DBG_TRACEEXT, & cpu_dev,
3774 "not setting ABS mode\r\n");
3775 }
3776
3777 }
3778
3779
3780 if (TST_I_ABS && cpu.cu.XSF)
3781 {
3782 set_addr_mode (cpup, APPEND_mode);
3783 }
3784
3785 if (ret == CONT_TRA)
3786 {
3787
3788 cpu.wasXfer = false;
3789 cpu.lufXferIC = cpu.lufExecIC;
3790 cpu.lufAfterXfer = true;
3791 set_cpu_cycle (cpup, PSEUDO_FETCH_cycle);
3792 }
3793 else
3794 set_cpu_cycle (cpup, FETCH_cycle);
3795 break;
3796 }
3797
3798 if (ret == CONT_DIS)
3799 {
3800 CPT (cpt1U, 25);
3801
3802 #if defined(THREADZ) || defined(LOCKLESS)
3803
3804 if (cpu.syncClockModeCache) {
3805 break;
3806 }
3807 #endif
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844 #if defined(THREADZ) || defined(LOCKLESS)
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854 # if defined(NO_TIMEWAIT)
3855
3856 struct timespec req, rem;
3857 uint ms = sys_opts.sys_poll_interval;
3858 long int nsec = (long int) ms * 1000L * 1000L;
3859 req.tv_nsec = nsec;
3860 req.tv_sec += req.tv_nsec / 1000000000L;
3861 req.tv_nsec %= 1000000000L;
3862 int rc = nanosleep (& req, & rem);
3863
3864 if (rc == -1)
3865 {
3866 ms = (uint) (rem.tv_nsec / 1000 + req.tv_sec * 1000);
3867 }
3868 word27 ticks = ms * 512;
3869 if (cpu.rTR <= ticks)
3870 {
3871 if (cpu.tweaks.tro_enable) {
3872 setG7fault (current_running_cpu_idx, FAULT_TRO);
3873 }
3874 cpu.rTR = (cpu.rTR - ticks) & MASK27;
3875 }
3876 else
3877 cpu.rTR = (cpu.rTR - ticks) & MASK27;
3878
3879 if (cpu.rTR == 0)
3880 cpu.rTR = MASK27;
3881 # else
3882
3883
3884 unsigned long left = (unsigned long) ((uint64) (cpu.rTR) * 125u / 64u);
3885
3886
3887
3888
3889
3890
3891
3892
3893 unsigned long nowLeft = left;
3894 if (!sample_interrupts (cpup))
3895 {
3896 nowLeft = sleepCPU (left);
3897 }
3898 if (nowLeft)
3899 {
3900
3901
3902 if (nowLeft <= left) {
3903 cpu.rTR = (word27) (left * 64 / 125);
3904 }
3905 }
3906 else
3907 {
3908
3909 if (cpu.tweaks.tro_enable)
3910 {
3911 lock_scu ();
3912 setG7fault (current_running_cpu_idx, FAULT_TRO);
3913 unlock_scu ();
3914 }
3915 cpu.rTR = MASK27;
3916 }
3917 # endif
3918 cpu.rTRticks = 0;
3919 break;
3920 #else
3921
3922 sim_usleep (sys_opts.sys_poll_interval * 1000);
3923
3924 # if defined(CONSOLE_FIX)
3925 # if defined(THREADZ) || defined(LOCKLESS)
3926 lock_libuv ();
3927 # endif
3928 # endif
3929 uv_run (ev_poll_loop, UV_RUN_NOWAIT);
3930 # if defined(CONSOLE_FIX)
3931 # if defined(THREADZ) || defined(LOCKLESS)
3932 unlock_libuv ();
3933 # endif
3934 # endif
3935 fast_queue_subsample = 0;
3936
3937 sim_interval = 0;
3938
3939
3940
3941
3942 cpu.rTRticks = 0;
3943
3944
3945
3946
3947
3948
3949 if (cpu.rTR <= sys_opts.sys_poll_interval * 512)
3950 {
3951 if (cpu.tweaks.tro_enable) {
3952 setG7fault (current_running_cpu_idx, FAULT_TRO);
3953 }
3954 cpu.rTR = (cpu.rTR - sys_opts.sys_poll_interval * 512) & MASK27;
3955 }
3956 else
3957 cpu.rTR = (cpu.rTR - sys_opts.sys_poll_interval * 512) & MASK27;
3958 if (cpu.rTR == 0)
3959 cpu.rTR = MASK27;
3960 #endif
3961
3962 break;
3963 }
3964
3965 cpu.wasXfer = false;
3966
3967 if (ret < 0)
3968 {
3969 sim_warn ("executeInstruction returned %d?\r\n", ret);
3970 break;
3971 }
3972
3973 if ((! cpu.cu.repeat_first) &&
3974 (cpu.cu.rpt ||
3975 (cpu.cu.rd && (cpu.PPR.IC & 1)) ||
3976 cpu.cu.rl))
3977 {
3978 CPT (cpt1U, 26);
3979 if (cpu.cu.rd)
3980 -- cpu.PPR.IC;
3981 cpu.wasXfer = false;
3982 set_cpu_cycle (cpup, FETCH_cycle);
3983 break;
3984 }
3985
3986
3987 if (cpu.cycle == FAULT_EXEC_cycle &&
3988 !cpu.cu.xde && cpu.cu.xdo)
3989 {
3990 clear_temporary_absolute_mode (cpup);
3991 cu_safe_restore (cpup);
3992 CPT (cpt1U, 12);
3993 clearFaultCycle (cpup);
3994
3995
3996
3997 cpu.wasXfer = false;
3998 cpu.isExec = false;
3999 cpu.isXED = false;
4000
4001 if (cpu.g7FetchFault)
4002 cpu.g7FetchFault = false;
4003 else
4004 {
4005 cpu.PPR.IC += ci->info->ndes;
4006 cpu.PPR.IC ++;
4007 }
4008
4009 set_cpu_cycle (cpup, FETCH_cycle);
4010 break;
4011 }
4012
4013
4014 if (cpu.cycle == INTERRUPT_EXEC_cycle &&
4015 !cpu.cu.xde && cpu.cu.xdo)
4016 {
4017 clear_temporary_absolute_mode (cpup);
4018 cu_safe_restore (cpup);
4019
4020
4021
4022 CPT (cpt1U, 12);
4023 cpu.wasXfer = false;
4024 cpu.isExec = false;
4025 cpu.isXED = false;
4026
4027 set_cpu_cycle (cpup, FETCH_cycle);
4028 break;
4029 }
4030
4031
4032 if (cpu.cu.xde && cpu.cu.xdo)
4033 {
4034
4035 cpu.cu.IWB = cpu.cu.IRODD;
4036 cpu.cu.xde = 0;
4037 cpu.isExec = true;
4038 cpu.isXED = true;
4039 cpu.cu.XSF = 0;
4040 cpu.cu.TSN_VALID [0] = 0;
4041 cpu.TPR.TSR = cpu.PPR.PSR;
4042 cpu.TPR.TRR = cpu.PPR.PRR;
4043 break;
4044 }
4045
4046 if (cpu.cu.xde || cpu.cu.xdo)
4047 {
4048 cpu.cu.xde = cpu.cu.xdo = 0;
4049 cpu.isExec = false;
4050 cpu.isXED = false;
4051 CPT (cpt1U, 27);
4052 cpu.wasXfer = false;
4053 cpu.PPR.IC ++;
4054 if (ci->info->ndes > 0)
4055 cpu.PPR.IC += ci->info->ndes;
4056 cpu.wasInhibited = true;
4057 set_cpu_cycle (cpup, FETCH_cycle);
4058 break;
4059 }
4060
4061
4062 if (cpu.cycle != EXEC_cycle)
4063 sim_warn ("expected EXEC_cycle (%d)\r\n", cpu.cycle);
4064
4065 cpu.cu.xde = cpu.cu.xdo = 0;
4066 cpu.isExec = false;
4067 cpu.isXED = false;
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078 if ((cpu.PPR.IC & 1) == 0 &&
4079 ci->info->ndes == 0 &&
4080 !cpu.cu.repeat_first && !cpu.cu.rpt && !cpu.cu.rd && !cpu.cu.rl &&
4081 !(cpu.currentInstruction.opcode == 0616 && cpu.currentInstruction.opcodeX == 0) &&
4082 (cpu.PPR.IC & ~3u) != (cpu.last_write & ~3u))
4083 {
4084 cpu.PPR.IC ++;
4085 cpu.wasXfer = false;
4086 cpu.cu.IWB = cpu.cu.IRODD;
4087 set_cpu_cycle (cpup, PSEUDO_FETCH_cycle);
4088 break;
4089 }
4090
4091 cpu.PPR.IC ++;
4092 if (ci->info->ndes > 0)
4093 cpu.PPR.IC += ci->info->ndes;
4094
4095 CPT (cpt1U, 28);
4096 cpu.wasXfer = false;
4097 set_cpu_cycle (cpup, FETCH_cycle);
4098 }
4099 break;
4100
4101 case SYNC_FAULT_RTN_cycle:
4102 {
4103 CPT (cpt1U, 29);
4104
4105
4106
4107
4108 cpu.PPR.IC += ci->info->ndes;
4109 cpu.PPR.IC ++;
4110 cpu.wasXfer = false;
4111 set_cpu_cycle (cpup, FETCH_cycle);
4112 }
4113 break;
4114
4115 case FAULT_cycle:
4116 {
4117 CPT (cpt1U, 30);
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146 if (((cpu.cu.APUCycleBits & 060) || cpu.secret_addressing_mode) &&
4147 ! cpu.tanddFetchFault && cpu.faultNumber != FAULT_STR &&
4148 ! cpu.tweaks.l68_mode)
4149 set_apu_status (cpup, apuStatus_FABS);
4150 cpu.tanddFetchFault = false;
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162 if (cpu.faultNumber != FAULT_TRB || cpu.cu.xde == 0)
4163 {
4164 cu_safe_store (cpup);
4165 }
4166 else
4167 {
4168 word36 tmpIRODD = cpu.scu_data[7];
4169 cu_safe_store (cpup);
4170 cpu.scu_data[7] = tmpIRODD;
4171 }
4172 if (cpu.scuRFI)
4173 putbits36_1 (& cpu.scu_data[5], 27, 1);
4174 cpu.scuRFI = false;
4175
4176 if (cpu.l68OddFault && (cpu.l68PairAddr & 01777) <= 01775)
4177 core_read (cpup, cpu.l68PairAddr + 3, & cpu.scu_data[7], __func__);
4178 cpu.l68OddFault = false;
4179 CPT (cpt1U, 31);
4180
4181
4182 set_temporary_absolute_mode (cpup);
4183
4184
4185 cpu.PPR.PRR = 0;
4186 cpu.TPR.TRR = 0;
4187
4188
4189 uint fltAddress = (cpu.switches.FLT_BASE << 5) & 07740;
4190 L68_ (
4191 if (cpu.is_FFV)
4192 {
4193 cpu.is_FFV = false;
4194 CPTUR (cptUseMR);
4195
4196 fltAddress = (cpu.MR.FFV & MASK15) << 3;
4197 }
4198 )
4199
4200
4201 word24 addr = fltAddress + 2 * cpu.faultNumber;
4202
4203 if (cpu.restart)
4204 {
4205 cpu.restart = false;
4206 addr = cpu.restart_address;
4207 }
4208
4209
4210
4211 bool switches = cpu.execSwitches;
4212 word36 sw = cpu.switches.data_switches;
4213 cpu.execSwitches = false;
4214 if (switches && ((sw >> 8) & 01777) == (0717u << 1))
4215 {
4216 addr = (word24) GETHI (sw);
4217 switches = false;
4218 }
4219 if (switches)
4220 {
4221 cpu.cu.IWB = sw;
4222 cpu.cu.IRODD = 0000000011000;
4223 }
4224 else
4225 core_read2 (cpup, addr, & cpu.cu.IWB, & cpu.cu.IRODD, __func__);
4226 #if defined(TESTING)
4227 HDBGMRead (addr, cpu.cu.IWB, "fault even");
4228 HDBGMRead (addr + 1, cpu.cu.IRODD, "fault odd");
4229 #endif
4230 cpu.cu.xde = 1;
4231 cpu.cu.xdo = 1;
4232 cpu.isExec = true;
4233 cpu.isXED = true;
4234
4235 CPT (cpt1U, 33);
4236 set_cpu_cycle (cpup, FAULT_EXEC_cycle);
4237
4238 break;
4239 }
4240
4241 }
4242 }
4243 while (reason == 0);
4244
4245 leave:
4246 #if defined(THREADZ) || defined(LOCKLESS)
4247 cpu.executing = false;
4248 cpu.inMultics = false;
4249 #endif
4250 #if defined(TESTING)
4251 HDBGPrint ();
4252 #endif
4253
4254 for (unsigned short n = 0; n < N_CPU_UNITS_MAX; n++)
4255 {
4256 #if !defined(SCHED_NEVER_YIELD)
4257 lockYieldAll = lockYieldAll + (unsigned long long)cpus[n].coreLockState.lockYield;
4258 #endif
4259 lockWaitMaxAll = lockWaitMaxAll + (unsigned long long)cpus[n].coreLockState.lockWaitMax;
4260 lockWaitAll = lockWaitAll + (unsigned long long)cpus[n].coreLockState.lockWait;
4261 lockImmediateAll = lockImmediateAll + (unsigned long long)cpus[n].coreLockState.lockImmediate;
4262 lockCntAll = lockCntAll + (unsigned long long)cpus[n].coreLockState.lockCnt;
4263 instrCntAll = instrCntAll + (unsigned long long)cpus[n].instrCnt;
4264 cycleCntAll = cycleCntAll + (unsigned long long)cpus[n].cycleCnt;
4265 }
4266
4267 (void)fflush(stderr);
4268 (void)fflush(stdout);
4269
4270 # if !defined(PERF_STRIP)
4271 if (cycleCntAll > (unsigned long long)cpu.cycleCnt)
4272 {
4273 # endif
4274 sim_msg ("\r\n");
4275 sim_msg ("\r+---------------------------------+\r\n");
4276 sim_msg ("\r| Aggregate CPU Statistics |\r\n");
4277 sim_msg ("\r+---------------------------------+\r\n");
4278 (void)fflush(stderr);
4279 (void)fflush(stdout);
4280 # if defined(WIN_STDIO)
4281 sim_msg ("\r| cycles %15llu |\r\n", cycleCntAll);
4282 sim_msg ("\r| instructions %15llu |\r\n", instrCntAll);
4283 (void)fflush(stderr);
4284 (void)fflush(stdout);
4285 sim_msg ("\r+---------------------------------+\r\n");
4286 sim_msg ("\r| lockCnt %15llu |\r\n", lockCntAll);
4287 sim_msg ("\r| lockImmediate %15llu |\r\n", lockImmediateAll);
4288 (void)fflush(stderr);
4289 (void)fflush(stdout);
4290 sim_msg ("\r+---------------------------------+\r\n");
4291 sim_msg ("\r| lockWait %15llu |\r\n", lockWaitAll);
4292 sim_msg ("\r| lockWaitMax %15llu |\r\n", lockWaitMaxAll);
4293 (void)fflush(stderr);
4294 (void)fflush(stdout);
4295 # if !defined(SCHED_NEVER_YIELD)
4296 sim_msg ("\r| lockYield %15llu |\r\n", lockYieldAll);
4297 # else
4298 sim_msg ("\r| lockYield ---- |\r\n");
4299 # endif
4300 sim_msg ("\r+---------------------------------+\r\n");
4301 (void)fflush(stderr);
4302 (void)fflush(stdout);
4303 # else
4304 sim_msg ("\r| cycles %'15llu |\r\n", cycleCntAll);
4305 sim_msg ("\r| instructions %'15llu |\r\n", instrCntAll);
4306 (void)fflush(stderr);
4307 (void)fflush(stdout);
4308 sim_msg ("\r+---------------------------------+\r\n");
4309 sim_msg ("\r| lockCnt %'15llu |\r\n", lockCntAll);
4310 sim_msg ("\r| lockImmediate %'15llu |\r\n", lockImmediateAll);
4311 (void)fflush(stderr);
4312 (void)fflush(stdout);
4313 sim_msg ("\r+---------------------------------+\r\n");
4314 sim_msg ("\r| lockWait %'15llu |\r\n", lockWaitAll);
4315 sim_msg ("\r| lockWaitMax %'15llu |\r\n", lockWaitMaxAll);
4316 (void)fflush(stderr);
4317 (void)fflush(stdout);
4318 # if !defined(SCHED_NEVER_YIELD)
4319 sim_msg ("\r| lockYield %'15llu |\r\n", lockYieldAll);
4320 # else
4321 sim_msg ("\r| lockYield ---- |\r\n");
4322 # endif
4323 sim_msg ("\r+---------------------------------+\r\n");
4324 (void)fflush(stderr);
4325 (void)fflush(stdout);
4326 # endif
4327 # if !defined(PERF_STRIP)
4328 }
4329 # else
4330 sim_msg("\r\n");
4331 # endif
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343 #if defined(THREADZ) || defined(LOCKLESS)
4344 if (running_perf_test == false)
4345 sim_usleep(2000000);
4346 stopCPUThread();
4347 #endif
4348
4349 #if defined(M_SHARED)
4350
4351
4352
4353
4354 set_cpu_idx (0);
4355 dummy_IC = cpu.PPR.IC;
4356 #endif
4357
4358 return reason;
4359 }
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375 int operand_size (cpu_state_t * cpup)
4376 {
4377 DCDstruct * i = & cpu.currentInstruction;
4378 if (i->info->flags & (READ_OPERAND | STORE_OPERAND))
4379 return 1;
4380 else if (i->info->flags & (READ_YPAIR | STORE_YPAIR))
4381 return 2;
4382 else if (i->info->flags & (READ_YBLOCK8 | STORE_YBLOCK8))
4383 return 8;
4384 else if (i->info->flags & (READ_YBLOCK16 | STORE_YBLOCK16))
4385 return 16;
4386 else if (i->info->flags & (READ_YBLOCK32 | STORE_YBLOCK32))
4387 return 32;
4388 return 0;
4389 }
4390
4391
4392
4393 void readOperandRead (cpu_state_t * cpup, word18 addr) {
4394 CPT (cpt1L, 6);
4395
4396 #if defined(THREADZ)
4397 DCDstruct * i = & cpu.currentInstruction;
4398 if (RMWOP (i))
4399 lock_rmw ();
4400 #endif
4401
4402 switch (operand_size (cpup)) {
4403 case 1:
4404 CPT (cpt1L, 7);
4405 ReadOperandRead (cpup, addr, & cpu.CY);
4406 break;
4407 case 2:
4408 CPT (cpt1L, 8);
4409 addr &= 0777776;
4410 Read2OperandRead (cpup, addr, cpu.Ypair);
4411 break;
4412 case 8:
4413 CPT (cpt1L, 9);
4414 addr &= 0777770;
4415 Read8 (cpup, addr, cpu.Yblock8, cpu.currentInstruction.b29);
4416 break;
4417 case 16:
4418 CPT (cpt1L, 10);
4419 addr &= 0777770;
4420 Read16 (cpup, addr, cpu.Yblock16);
4421 break;
4422 case 32:
4423 CPT (cpt1L, 11);
4424 addr &= 0777740;
4425 for (uint j = 0 ; j < 32 ; j += 1)
4426 ReadOperandRead (cpup, addr + j, cpu.Yblock32 + j);
4427 break;
4428 }
4429 }
4430
4431 void readOperandRMW (cpu_state_t * cpup, word18 addr) {
4432 CPT (cpt1L, 6);
4433 switch (operand_size (cpup)) {
4434 case 1:
4435 CPT (cpt1L, 7);
4436 ReadOperandRMW (cpup, addr, & cpu.CY);
4437 break;
4438 case 2:
4439 CPT (cpt1L, 8);
4440 addr &= 0777776;
4441 Read2OperandRead (cpup, addr, cpu.Ypair);
4442 break;
4443 case 8:
4444 CPT (cpt1L, 9);
4445 addr &= 0777770;
4446 Read8 (cpup, addr, cpu.Yblock8, cpu.currentInstruction.b29);
4447 break;
4448 case 16:
4449 CPT (cpt1L, 10);
4450 addr &= 0777770;
4451 Read16 (cpup, addr, cpu.Yblock16);
4452 break;
4453 case 32:
4454 CPT (cpt1L, 11);
4455 addr &= 0777740;
4456 for (uint j = 0 ; j < 32 ; j += 1)
4457 ReadOperandRMW (cpup, addr + j, cpu.Yblock32 + j);
4458 break;
4459 }
4460 }
4461
4462
4463
4464 t_stat write_operand (cpu_state_t * cpup, word18 addr, UNUSED processor_cycle_type cyctyp)
4465 {
4466 switch (operand_size (cpup))
4467 {
4468 case 1:
4469 CPT (cpt1L, 12);
4470 WriteOperandStore (cpup, addr, cpu.CY);
4471 break;
4472 case 2:
4473 CPT (cpt1L, 13);
4474 addr &= 0777776;
4475 Write2OperandStore (cpup, addr + 0, cpu.Ypair);
4476 break;
4477 case 8:
4478 CPT (cpt1L, 14);
4479 addr &= 0777770;
4480 Write8 (cpup, addr, cpu.Yblock8, cpu.currentInstruction.b29);
4481 break;
4482 case 16:
4483 CPT (cpt1L, 15);
4484 addr &= 0777770;
4485 Write16 (cpup, addr, cpu.Yblock16);
4486 break;
4487 case 32:
4488 CPT (cpt1L, 16);
4489 addr &= 0777740;
4490
4491
4492 Write32 (cpup, addr, cpu.Yblock32);
4493 break;
4494 }
4495
4496 #if defined(THREADZ)
4497 if (cyctyp == OPERAND_STORE)
4498 {
4499 DCDstruct * i = & cpu.currentInstruction;
4500 if (RMWOP (i))
4501 unlock_mem ();
4502 }
4503 #endif
4504 return SCPE_OK;
4505
4506 }
4507
4508 #if !defined(SPEED)
4509 t_stat set_mem_watch (int32 arg, const char * buf)
4510 {
4511 if (strlen (buf) == 0)
4512 {
4513 if (arg)
4514 {
4515 sim_warn ("no argument to watch?\r\n");
4516 return SCPE_ARG;
4517 }
4518 sim_msg ("Clearing all watch points\r\n");
4519 (void)memset (& watch_bits, 0, sizeof (watch_bits));
4520 return SCPE_OK;
4521 }
4522 char * end;
4523 long int n = strtol (buf, & end, 0);
4524 if (* end || n < 0 || n >= MEMSIZE)
4525 {
4526 sim_warn ("Invalid argument to watch? %ld\r\n", (long) n);
4527 return SCPE_ARG;
4528 }
4529 watch_bits [n] = arg != 0;
4530 return SCPE_OK;
4531 }
4532 #endif
4533
4534
4535
4536
4537
4538 #if !defined(SPEED)
4539 static void nem_check (word24 addr, const char * context)
4540 {
4541 cpu_state_t * cpup = _cpup;
4542 if (lookup_cpu_mem_map (cpup, addr) < 0)
4543 {
4544 doFault (FAULT_STR, fst_str_nea, context);
4545 }
4546 }
4547 #endif
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560 #if !defined(SPEED) || !defined(INLINE_CORE)
4561 int core_read (cpu_state_t * cpup, word24 addr, word36 *data, const char * ctx)
4562 {
4563 SC_LOCKOUT_WAIT ();
4564 BAD_PARITY_READ (addr);
4565 PNL (cpu.portBusy = true;)
4566 SC_MAP_ADDR (addr, addr);
4567 # if !defined(LOCKLESS)
4568 if (M[addr] & MEM_UNINITIALIZED)
4569 {
4570 sim_debug (DBG_WARN, & cpu_dev,
4571 "Uninitialized memory accessed at address %08o; "
4572 "IC is 0%06o:0%06o (%s(\r\n",
4573 addr, cpu.PPR.PSR, cpu.PPR.IC, ctx);
4574 }
4575 # endif
4576 # if !defined(SPEED)
4577 if (watch_bits [addr])
4578 {
4579 sim_msg ("WATCH [%llu] %05o:%06o read %08o %012llo (%s)\r\n",
4580 (long long unsigned int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC, addr,
4581 (long long unsigned int)M [addr], ctx);
4582 traceInstruction (0);
4583 }
4584 # endif
4585 # if defined(LOCKLESS)
4586 # if !defined(SUNLINT)
4587 word36 v;
4588 LOAD_ACQ_CORE_WORD(v, addr);
4589 *data = v & DMASK;
4590 # endif
4591 # else
4592 *data = M[addr] & DMASK;
4593 # endif
4594
4595 DO_WORK_MEM;
4596 sim_debug (DBG_CORE, & cpu_dev,
4597 "core_read %08o %012"PRIo64" (%s)\r\n",
4598 addr, * data, ctx);
4599 PNL (trackport (addr, * data));
4600 return 0;
4601 }
4602 #endif
4603
4604 #if defined(LOCKLESS)
4605 int core_read_lock (cpu_state_t * cpup, word24 addr, word36 *data, UNUSED const char * ctx)
4606 {
4607 if (nBadParity && cpu.tweaks.tandd_mode && bad_parity_marked (addr))
4608 cpu.scLockedOut = true;
4609 BAD_PARITY_READ (addr);
4610 SC_MAP_ADDR (addr, addr);
4611 LOCK_CORE_WORD(addr, & cpu.coreLockState);
4612 if (cpu.coreLockState.locked_addr != 0) {
4613 sim_warn ("core_read_lock: locked %08o locked_addr %08o %c %05o:%06o\r\n",
4614 addr, cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
4615 cpu.PPR.PSR, cpu.PPR.IC);
4616 core_unlock_all (cpup);
4617 }
4618 cpu.coreLockState.locked_addr = addr;
4619 # if !defined(SUNLINT)
4620 word36 v;
4621 LOAD_ACQ_CORE_WORD(v, addr);
4622 * data = v & DMASK;
4623 # endif
4624 return 0;
4625 }
4626 #endif
4627
4628 #if !defined(SPEED) || !defined(INLINE_CORE)
4629 int core_write (cpu_state_t * cpup, word24 addr, word36 data, const char * ctx)
4630 {
4631 SC_LOCKOUT_WAIT ();
4632 BAD_PARITY_WRITE (addr);
4633 PNL (cpu.portBusy = true;)
4634 SC_MAP_ADDR (addr, addr);
4635 if (cpu.tweaks.isolts_mode)
4636 {
4637 if (cpu.MR.sdpap)
4638 {
4639 sim_warn ("failing to implement sdpap\r\n");
4640 cpu.MR.sdpap = 0;
4641 }
4642 if (cpu.MR.separ)
4643 {
4644 sim_warn ("failing to implement separ\r\n");
4645 cpu.MR.separ = 0;
4646 }
4647 }
4648 # if defined(LOCKLESS)
4649 LOCK_CORE_WORD(addr, & cpu.coreLockState);
4650 # if !defined(SUNLINT)
4651 STORE_REL_CORE_WORD(addr, data);
4652 # endif
4653 # else
4654 M[addr] = data & DMASK;
4655 # endif
4656 # if !defined(SPEED)
4657 if (watch_bits [addr])
4658 {
4659 sim_msg ("WATCH [%llu] %05o:%06o write %08llo %012llo (%s)\r\n",
4660 (long long unsigned int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
4661 (long long unsigned int)addr, (unsigned long long int)M [addr], ctx);
4662 traceInstruction (0);
4663 }
4664 # endif
4665 DO_WORK_MEM;
4666 sim_debug (DBG_CORE, & cpu_dev,
4667 "core_write %08o %012"PRIo64" (%s)\r\n",
4668 addr, data, ctx);
4669 PNL (trackport (addr, data));
4670 return 0;
4671 }
4672 #endif
4673
4674 #if defined(LOCKLESS)
4675 int core_write_unlock (cpu_state_t * cpup, word24 addr, word36 data, UNUSED const char * ctx)
4676 {
4677 BAD_PARITY_WRITE (addr);
4678 SC_MAP_ADDR (addr, addr);
4679 if (cpu.coreLockState.locked_addr != addr)
4680 {
4681 sim_warn ("core_write_unlock: locked %08o locked_addr %08o %c %05o:%06o\r\n",
4682 addr, cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
4683 cpu.PPR.PSR, cpu.PPR.IC);
4684 core_unlock_all (cpup);
4685 }
4686
4687 # if !defined(SUNLINT)
4688 STORE_REL_CORE_WORD(addr, data);
4689 # endif
4690 cpu.coreLockState.locked_addr = 0;
4691 return 0;
4692 }
4693
4694 int core_unlock_all (cpu_state_t * cpup)
4695 {
4696 if (cpu.coreLockState.locked_addr != 0) {
4697 sim_warn ("core_unlock_all: locked %08o %c %05o:%06o\r\n",
4698 cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
4699 cpu.PPR.PSR, cpu.PPR.IC);
4700 # if !defined(SUNLINT)
4701 STORE_REL_CORE_WORD(cpu.coreLockState.locked_addr, M[cpu.coreLockState.locked_addr]);
4702 # endif
4703 cpu.coreLockState.locked_addr = 0;
4704 }
4705 return 0;
4706 }
4707 #endif
4708
4709 #if !defined(SPEED) || !defined(INLINE_CORE)
4710 int core_write_zone (cpu_state_t * cpup, word24 addr, word36 data, const char * ctx)
4711 {
4712 SC_LOCKOUT_WAIT ();
4713 BAD_PARITY_WRITE (addr);
4714 PNL (cpu.portBusy = true;)
4715 if (cpu.tweaks.isolts_mode)
4716 {
4717 if (cpu.MR.sdpap)
4718 {
4719 sim_warn ("failing to implement sdpap\r\n");
4720 cpu.MR.sdpap = 0;
4721 }
4722 if (cpu.MR.separ)
4723 {
4724 sim_warn ("failing to implement separ\r\n");
4725 cpu.MR.separ = 0;
4726 }
4727 }
4728 word24 mapAddr = 0;
4729 SC_MAP_ADDR (addr, mapAddr);
4730 # if defined(LOCKLESS)
4731 word36 v;
4732 core_read_lock(cpup, addr, &v, ctx);
4733 v = (v & ~cpu.zone) | (data & cpu.zone);
4734 core_write_unlock(cpup, addr, v, ctx);
4735 # else
4736 M[mapAddr] = (M[mapAddr] & ~cpu.zone) | (data & cpu.zone);
4737 # endif
4738 cpu.useZone = false;
4739 # if !defined(SPEED)
4740 if (watch_bits [mapAddr])
4741 {
4742 sim_msg ("WATCH [%llu] %05o:%06o writez %08llo %012llo (%s)\r\n",
4743 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
4744 (unsigned long long int)mapAddr, (unsigned long long int)M [mapAddr], ctx);
4745 traceInstruction (0);
4746 }
4747 # endif
4748 DO_WORK_MEM;
4749 sim_debug (DBG_CORE, & cpu_dev,
4750 "core_write_zone %08o %012"PRIo64" (%s)\r\n",
4751 mapAddr, data, ctx);
4752 PNL (trackport (mapAddr, data));
4753 return 0;
4754 }
4755 #endif
4756
4757 #if !defined(SPEED) || !defined(INLINE_CORE)
4758 int core_read2 (cpu_state_t * cpup, word24 addr, word36 *even, word36 *odd, const char * ctx)
4759 {
4760 SC_LOCKOUT_WAIT ();
4761 BAD_PARITY_READ (addr & ~1u);
4762 BAD_PARITY_READ (addr | 1u);
4763 PNL (cpu.portBusy = true;)
4764 # if defined(LOCKLESS)
4765
4766 word36 v;
4767 # endif
4768 if (addr & 1)
4769 {
4770 sim_debug (DBG_MSG, & cpu_dev,
4771 "warning: subtracting 1 from pair at %o in "
4772 "core_read2 (%s)\r\n", addr, ctx);
4773 addr &= (word24)~1;
4774 }
4775 SC_MAP_ADDR (addr, addr);
4776 # if !defined(LOCKLESS)
4777 if (M[addr] & MEM_UNINITIALIZED)
4778 {
4779 sim_debug (DBG_WARN, & cpu_dev,
4780 "Uninitialized memory accessed at address %08o; "
4781 "IC is 0%06o:0%06o (%s)\r\n",
4782 addr, cpu.PPR.PSR, cpu.PPR.IC, ctx);
4783 }
4784 # endif
4785 # if !defined(SPEED)
4786 if (watch_bits [addr])
4787 {
4788 sim_msg ("WATCH [%llu] %05o:%06o read2 %08llo %012llo (%s)\r\n",
4789 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
4790 (unsigned long long int)addr, (unsigned long long int)M [addr], ctx);
4791 traceInstruction (0);
4792 }
4793 # endif
4794 # if defined(LOCKLESS)
4795 # if !defined(SUNLINT)
4796 LOAD_ACQ_CORE_WORD(v, addr);
4797 if (v & MEM_LOCKED)
4798 sim_warn ("core_read2: even locked %08o locked_addr %08o %c %05o:%06o\r\n",
4799 addr, cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
4800 cpu.PPR.PSR, cpu.PPR.IC);
4801 *even = v & DMASK;
4802 addr++;
4803 # endif
4804 # else
4805 *even = M[addr++] & DMASK;
4806 # endif
4807 sim_debug (DBG_CORE, & cpu_dev,
4808 "core_read2 %08o %012"PRIo64" (%s)\r\n",
4809 addr - 1, * even, ctx);
4810
4811
4812
4813 # if !defined(LOCKLESS)
4814 if (M[addr] & MEM_UNINITIALIZED)
4815 {
4816 sim_debug (DBG_WARN, & cpu_dev,
4817 "Uninitialized memory accessed at address %08o; "
4818 "IC is 0%06o:0%06o (%s)\r\n",
4819 addr, cpu.PPR.PSR, cpu.PPR.IC, ctx);
4820 }
4821 # endif
4822 # if !defined(SPEED)
4823 if (watch_bits [addr])
4824 {
4825 sim_msg ("WATCH [%llu] %05o:%06o read2 %08llo %012llo (%s)\r\n",
4826 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
4827 (unsigned long long int)addr, (unsigned long long int)M [addr], ctx);
4828 traceInstruction (0);
4829 }
4830 # endif
4831 # if defined(LOCKLESS)
4832 # if !defined(SUNLINT)
4833 LOAD_ACQ_CORE_WORD(v, addr);
4834 if (v & MEM_LOCKED)
4835 sim_warn ("core_read2: odd locked %08o locked_addr %08o %c %05o:%06o\r\n",
4836 addr, cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
4837 cpu.PPR.PSR, cpu.PPR.IC);
4838 *odd = v & DMASK;
4839 # endif
4840 # else
4841 *odd = M[addr] & DMASK;
4842 # endif
4843 sim_debug (DBG_CORE, & cpu_dev,
4844 "core_read2 %08o %012"PRIo64" (%s)\r\n",
4845 addr, * odd, ctx);
4846 DO_WORK_MEM;
4847 PNL (trackport (addr - 1, * even));
4848 return 0;
4849 }
4850 #endif
4851
4852 #if !defined(SPEED) || !defined(INLINE_CORE)
4853 int core_write2 (cpu_state_t * cpup, word24 addr, word36 even, word36 odd, const char * ctx) {
4854 SC_LOCKOUT_WAIT ();
4855 BAD_PARITY_WRITE (addr & ~1u);
4856 BAD_PARITY_WRITE (addr | 1u);
4857 PNL (cpu.portBusy = true;)
4858 if (addr & 1) {
4859 sim_debug (DBG_MSG, & cpu_dev,
4860 "warning: subtracting 1 from pair at %o in core_write2 " "(%s)\r\n",
4861 addr, ctx);
4862 addr &= (word24)~1;
4863 }
4864 SC_MAP_ADDR (addr, addr);
4865 if (cpu.tweaks.isolts_mode) {
4866 if (cpu.MR.sdpap) {
4867 sim_warn ("failing to implement sdpap\r\n");
4868 cpu.MR.sdpap = 0;
4869 }
4870 if (cpu.MR.separ) {
4871 sim_warn ("failing to implement separ\r\n");
4872 cpu.MR.separ = 0;
4873 }
4874 }
4875
4876 # if !defined(SPEED)
4877 if (watch_bits [addr]) {
4878 sim_msg ("WATCH [%llu] %05o:%06o write2 %08llo %012llo (%s)\r\n",
4879 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
4880 (unsigned long long int)addr, (unsigned long long int)even, ctx);
4881 traceInstruction (0);
4882 }
4883 # endif
4884 # if defined(LOCKLESS)
4885 LOCK_CORE_WORD(addr, & cpu.coreLockState);
4886 # if !defined(SUNLINT)
4887 STORE_REL_CORE_WORD(addr, even);
4888 # endif
4889 addr++;
4890 # else
4891 M[addr++] = even & DMASK;
4892 # endif
4893 sim_debug (DBG_CORE, & cpu_dev, "core_write2 %08o %012llo (%s)\r\n", addr - 1,
4894 (long long unsigned int)even, ctx);
4895
4896
4897
4898
4899 # if !defined(SPEED)
4900 if (watch_bits [addr]) {
4901 sim_msg ("WATCH [%llu] %05o:%06o write2 %08llo %012llo (%s)\r\n",
4902 (long long unsigned int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
4903 (long long unsigned int)addr, (long long unsigned int)odd, ctx);
4904 traceInstruction (0);
4905 }
4906 # endif
4907 # if defined(LOCKLESS)
4908 LOCK_CORE_WORD(addr, & cpu.coreLockState);
4909 # if !defined(SUNLINT)
4910 STORE_REL_CORE_WORD(addr, odd);
4911 # endif
4912 # else
4913 M[addr] = odd & DMASK;
4914 # endif
4915 DO_WORK_MEM;
4916 PNL (trackport (addr - 1, even));
4917 sim_debug (DBG_CORE, & cpu_dev, "core_write2 %08o %012"PRIo64" (%s)\r\n", addr, odd, ctx);
4918 return 0;
4919 }
4920 #endif
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931 void decode_instruction (cpu_state_t * cpup, word36 inst, DCDstruct * p)
4932 {
4933 CPT (cpt1L, 17);
4934
4935
4936
4937 p->stiTally = false;
4938 p->restart = false;
4939
4940 p->opcode = GET_OP (inst);
4941 p->opcodeX = GET_OPX(inst);
4942 p->opcode10 = p->opcode | (p->opcodeX ? 01000 : 0);
4943 p->address = GET_ADDR (inst);
4944 p->b29 = GET_A (inst);
4945 p->i = GET_I (inst);
4946 p->tag = GET_TAG (inst);
4947
4948 p->info = get_iwb_info (p);
4949
4950 if (p->info->flags & IGN_B29)
4951 p->b29 = 0;
4952
4953 if (p->info->ndes > 0)
4954 {
4955 p->b29 = 0;
4956 p->tag = 0;
4957 if (p->info->ndes > 1)
4958 {
4959 (void)memset (& cpu.currentEISinstruction, 0,
4960 sizeof (cpu.currentEISinstruction));
4961 }
4962 }
4963 }
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984 int is_priv_mode (cpu_state_t * cpup)
4985 {
4986
4987
4988
4989 if (get_bar_mode (cpup))
4990 return 0;
4991
4992
4993 if (get_addr_mode (cpup) == ABSOLUTE_mode)
4994 return 1;
4995 else if (cpu.PPR.P)
4996 return 1;
4997
4998 return 0;
4999 }
5000
5001
5002
5003
5004
5005
5006
5007
5008 bool get_bar_mode (cpu_state_t * cpup)
5009 {
5010 return ! (cpu.secret_addressing_mode || TST_I_NBAR);
5011 }
5012
5013 addr_modes_e get_addr_mode (cpu_state_t * cpup)
5014 {
5015 if (cpu.secret_addressing_mode)
5016 return ABSOLUTE_mode;
5017
5018
5019
5020
5021
5022
5023
5024 if (TST_I_ABS)
5025 {
5026 return ABSOLUTE_mode;
5027 }
5028 else
5029 {
5030 return APPEND_mode;
5031 }
5032 }
5033
5034
5035
5036
5037
5038
5039
5040
5041 void set_addr_mode (cpu_state_t * cpup, addr_modes_e mode)
5042 {
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053 cpu.secret_addressing_mode = false;
5054 if (mode == ABSOLUTE_mode)
5055 {
5056 CPT (cpt1L, 22);
5057 sim_debug (DBG_DEBUG, & cpu_dev, "APU: Setting absolute mode.\r\n");
5058
5059 SET_I_ABS;
5060 cpu.PPR.P = 1;
5061 }
5062 else if (mode == APPEND_mode)
5063 {
5064 CPT (cpt1L, 23);
5065 if (! TST_I_ABS && TST_I_NBAR)
5066 sim_debug (DBG_DEBUG, & cpu_dev, "APU: Keeping append mode.\r\n");
5067 else
5068 sim_debug (DBG_DEBUG, & cpu_dev, "APU: Setting append mode.\r\n");
5069
5070 CLR_I_ABS;
5071 }
5072 else
5073 {
5074 sim_debug (DBG_ERR, & cpu_dev,
5075 "APU: Unable to determine address mode.\r\n");
5076 sim_warn ("APU: Unable to determine address mode. Can't happen!\r\n");
5077 }
5078 }
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106 word18 get_BAR_address (cpu_state_t * cpup, word18 addr)
5107 {
5108 if (cpu . BAR.BOUND == 0)
5109
5110 doFault (FAULT_STR, fst_str_oob, "BAR store fault; out of bounds");
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121 if (addr >= (((word18) cpu . BAR.BOUND) << 9))
5122
5123 doFault (FAULT_STR, fst_str_oob, "BAR store fault; out of bounds");
5124
5125 word18 barAddr = (addr + (((word18) cpu . BAR.BASE) << 9)) & 0777777;
5126 return barAddr;
5127 }
5128
5129
5130
5131 static void add_history (cpu_state_t * cpup, uint hset, word36 w0, word36 w1)
5132 {
5133
5134 {
5135 cpu.history [hset] [cpu.history_cyclic[hset]] [0] = w0;
5136 cpu.history [hset] [cpu.history_cyclic[hset]] [1] = w1;
5137 cpu.history_cyclic[hset] = (cpu.history_cyclic[hset] + 1) % N_MODEL_HIST_SIZE;
5138 }
5139 }
5140
5141 void add_history_force (cpu_state_t * cpup, uint hset, word36 w0, word36 w1)
5142 {
5143 cpu.history [hset] [cpu.history_cyclic[hset]] [0] = w0;
5144 cpu.history [hset] [cpu.history_cyclic[hset]] [1] = w1;
5145 cpu.history_cyclic[hset] = (cpu.history_cyclic[hset] + 1) % N_MODEL_HIST_SIZE;
5146 }
5147
5148 void add_dps8m_CU_history (cpu_state_t * cpup)
5149 {
5150 if (cpu.skip_cu_hist)
5151 return;
5152 if (! cpu.MR_cache.emr)
5153 return;
5154 if (! cpu.MR_cache.ihr)
5155 return;
5156 if (cpu.MR_cache.hrxfr && ! cpu.wasXfer)
5157 return;
5158
5159 word36 flags = 0;
5160 word5 proccmd = 0;
5161 word7 flags2 = 0;
5162 word36 w0 = 0, w1 = 0;
5163 w0 |= flags & 0777777000000;
5164 w0 |= IWB_IRODD & MASK18;
5165 w1 |= ((word36)(cpu.iefpFinalAddress & MASK24) << 12);
5166 w1 |= (proccmd & MASK5) << 7;
5167 w1 |= flags2 & 0176;
5168 add_history (cpup, CU_HIST_REG, w0, w1);
5169 }
5170
5171 #if !defined(QUIET_UNUSED)
5172 void add_dps8m_DU_OU_history (cpu_state_t * cpup, word36 flags, word18 ICT, word9 RS_REG, word9 flags2)
5173 {
5174 word36 w0 = flags, w1 = 0;
5175 w1 |= (ICT & MASK18) << 18;
5176 w1 |= (RS_REG & MASK9) << 9;
5177 w1 |= flags2 & MASK9;
5178 add_history (cpup, DPS8M_DU_OU_HIST_REG, w0, w1);
5179 }
5180
5181 void add_dps8m_APU_history (cpu_state_t * cpup, word15 ESN, word21 flags, word24 RMA, word3 RTRR, word9 flags2)
5182 {
5183 word36 w0 = 0, w1 = 0;
5184 w0 |= (ESN & MASK15) << 21;
5185 w0 |= flags & MASK21;
5186 w1 |= (RMA & MASK24) << 12;
5187 w1 |= (RTRR & MASK3) << 9;
5188 w1 |= flags2 & MASK9;
5189 add_history (cpu.tweaks.l68_mode ? L68_APU_HIST_REG : DPS8M_APU_HIST_REG, w0, w1);
5190 }
5191
5192 void add_dps8m_EAPU_history (word18 ZCA, word18 opcode)
5193 {
5194 word36 w0 = 0;
5195 w0 |= (ZCA & MASK18) << 18;
5196 w0 |= opcode & MASK18;
5197 add_history (DPS8M_EAPU_HIST_REG, w0, 0);
5198
5199
5200
5201
5202 }
5203 #endif
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244 static void add_l68_CU_history_entry (cpu_state_t * cpup, bool ins_fetch)
5245 {
5246 CPT (cpt1L, 24);
5247 if (cpu.skip_cu_hist)
5248 return;
5249 if (! cpu.MR_cache.emr)
5250 return;
5251 if (! cpu.MR_cache.ihr)
5252 return;
5253
5254
5255 if (getbits36_1 (cpu.MR_cache.r, 29) &&
5256 (ins_fetch ||
5257 cpu.currentInstruction.opcode != getbits36_9 (cpu.MR_cache.r, 18) ||
5258 (cpu.currentInstruction.opcodeX ? 1u : 0u) != getbits36_1 (cpu.MR_cache.r, 27)))
5259 return;
5260
5261 word36 w0 = 0, w1 = 0;
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271 PNL (putbits36_8 (& w0, 0, cpu.prepare_state);)
5272
5273 putbits36_1 (& w0, 8, cpu.wasXfer);
5274
5275 putbits36_1 (& w0, 9, cpu.cu.xde);
5276
5277 putbits36_1 (& w0, 10, cpu.cu.xdo);
5278
5279 putbits36_1 (& w0, 11, USE_IRODD?1:0);
5280
5281 putbits36_1 (& w0, 12, cpu.cu.rpt);
5282
5283
5284 PNL (putbits36_1 (& w0, 14, cpu.AR_F_E);)
5285
5286 putbits36_1 (& w0, 15, cpu.cycle != INTERRUPT_cycle?1:0);
5287
5288 putbits36_1 (& w0, 16, cpu.cycle != FAULT_cycle?1:0);
5289
5290 putbits36_1 (& w0, 17, TSTF (cpu.cu.IR, I_NBAR)?1:0);
5291
5292 putbits36_18 (& w0, 18, (word18) (IWB_IRODD & MASK18));
5293
5294
5295 putbits36_18 (& w1, 0, cpu.TPR.CA);
5296
5297
5298 PNL (putbits36_1 (& w1, 59-36, (cpu.portSelect == 0)?1:0);)
5299 PNL (putbits36_1 (& w1, 60-36, (cpu.portSelect == 1)?1:0);)
5300 PNL (putbits36_1 (& w1, 61-36, (cpu.portSelect == 2)?1:0);)
5301 PNL (putbits36_1 (& w1, 62-36, (cpu.portSelect == 3)?1:0);)
5302
5303 putbits36_1 (& w1, 63-36, cpu.interrupt_flag?1:0);
5304
5305 putbits36_1 (& w1, 64-36, ins_fetch?1:0);
5306
5307
5308
5309
5310
5311
5312
5313
5314 add_history (cpup, CU_HIST_REG, w0, w1);
5315
5316
5317 CPTUR (cptUseMR);
5318 if (cpu.MR.hrhlt && cpu.history_cyclic[CU_HIST_REG] == 0)
5319 {
5320
5321 if (cpu.MR.ihrrs)
5322 {
5323 cpu.MR.ihr = 0;
5324 }
5325 set_FFV_fault (cpup, 4);
5326 return;
5327 }
5328 }
5329
5330 void add_l68_CU_history (cpu_state_t * cpup)
5331 {
5332 add_l68_CU_history_entry (cpup, false);
5333 }
5334
5335 void add_l68_CU_fetch_history (cpu_state_t * cpup)
5336 {
5337 add_l68_CU_history_entry (cpup, true);
5338 }
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378 void add_l68_DU_history (cpu_state_t * cpup)
5379 {
5380 CPT (cpt1L, 25);
5381 PNL (add_history (cpup, L68_DU_HIST_REG, cpu.du.cycle1, cpu.du.cycle2);)
5382 }
5383
5384 void add_l68_OU_history (cpu_state_t * cpup)
5385 {
5386 CPT (cpt1L, 26);
5387 word36 w0 = 0, w1 = 0;
5388
5389
5390
5391 putbits36_9 (& w0, 0, cpu.ou.RS);
5392
5393
5394 putbits36_1 (& w0, 9, cpu.ou.characterOperandSize ? 1 : 0);
5395
5396
5397 putbits36_3 (& w0, 10, cpu.ou.characterOperandOffset);
5398
5399
5400 putbits36_1 (& w0, 13, cpu.ou.crflag);
5401
5402
5403 putbits36_1 (& w0, 14, cpu.ou.directOperandFlag ? 1 : 0);
5404
5405
5406 putbits36_2 (& w0, 15, cpu.ou.eac);
5407
5408
5409
5410 putbits36_9 (& w0, 18, cpu.ou.RS);
5411
5412
5413 putbits36_1 (& w0, 27, cpu.ou.RB1_FULL);
5414
5415
5416 putbits36_1 (& w0, 28, cpu.ou.RP_FULL);
5417
5418
5419 putbits36_1 (& w0, 29, cpu.ou.RS_FULL);
5420
5421
5422 putbits36_6 (& w0, 30, (word6) (cpu.ou.cycle >> 3));
5423
5424
5425 putbits36_3 (& w1, 36-36, (word3) cpu.ou.cycle);
5426
5427
5428 putbits36_1 (& w1, 39-36, cpu.ou.STR_OP);
5429
5430
5431
5432
5433 putbits36_10 (& w1, 41-36,
5434 (word10) ~opcodes10 [cpu.ou.RS].reg_use);
5435
5436
5437
5438
5439 putbits36_18 (& w1, 54 - 36, cpu.PPR.IC);
5440
5441 add_history (cpup, L68_OU_HIST_REG, w0, w1);
5442 }
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493 void add_l68_APU_history (cpu_state_t * cpup, enum APUH_e op)
5494 {
5495 CPT (cpt1L, 28);
5496 word36 w0 = 0, w1 = 0;
5497
5498 w0 = op;
5499
5500
5501 putbits36_15 (& w0, 0, cpu.TPR.TSR);
5502
5503 PNL (putbits36_1 (& w0, 15, (cpu.apu.state & apu_ESN_SNR) ? 1 : 0);)
5504 PNL (putbits36_1 (& w0, 16, (cpu.apu.state & apu_ESN_TSR) ? 1 : 0);)
5505
5506 putbits36_1 (& w0, 25, cpu.cu.SDWAMM);
5507
5508 putbits36_4 (& w0, 26, (word4) cpu.SDWAMR);
5509
5510 putbits36_1 (& w0, 30, cpu.cu.PTWAMM);
5511
5512 putbits36_4 (& w0, 31, (word4) cpu.PTWAMR);
5513
5514 PNL (putbits36_1 (& w0, 35, (cpu.apu.state & apu_FLT) ? 1 : 0);)
5515
5516
5517 PNL (putbits36_24 (& w1, 0, cpu.APUMemAddr);)
5518
5519 putbits36_3 (& w1, 24, cpu.TPR.TRR);
5520
5521
5522 putbits36_1 (& w1, 34, cpu.SDW0.C);
5523
5524
5525 add_history (cpup, L68_APU_HIST_REG, w0, w1);
5526 }
5527
5528 #if defined(THREADZ) || defined(LOCKLESS)
5529
5530
5531 static const char * get_dbg_verb (uint32 dbits, DEVICE * dptr)
5532 {
5533 static const char * debtab_none = "DEBTAB_ISNULL";
5534 static const char * debtab_nomatch = "DEBTAB_NOMATCH";
5535 const char * some_match = NULL;
5536 int32 offset = 0;
5537
5538 if (dptr->debflags == 0)
5539 return debtab_none;
5540
5541 dbits &= dptr->dctrl;
5542
5543
5544 while ((offset < 32) && dptr->debflags[offset].name)
5545 {
5546 if (dptr->debflags[offset].mask == dbits)
5547 return dptr->debflags[offset].name;
5548 if (dptr->debflags[offset].mask & dbits)
5549 some_match = dptr->debflags[offset].name;
5550 offset ++;
5551 }
5552 return some_match ? some_match : debtab_nomatch;
5553 }
5554
5555 void dps8_sim_debug (uint32 dbits, DEVICE * dptr, unsigned long long cnt, const char* fmt, ...)
5556 {
5557
5558 if (sim_deb && dptr && (dptr->dctrl & dbits))
5559 {
5560 const char * debug_type = get_dbg_verb (dbits, dptr);
5561 char stackbuf[STACKBUFSIZE];
5562 int32 bufsize = sizeof (stackbuf);
5563 char * buf = stackbuf;
5564 va_list arglist;
5565 int32 i, j, len;
5566 struct timespec t;
5567 clock_gettime(CLOCK_REALTIME, &t);
5568
5569 buf [bufsize-1] = '\0';
5570
5571 while (1)
5572 {
5573 va_start (arglist, fmt);
5574 len = vsnprintf (buf, (int)((unsigned long)(bufsize)-1), fmt, arglist);
5575 va_end (arglist);
5576
5577
5578
5579 if ((len < 0) || (len >= bufsize-1))
5580 {
5581 if (buf != stackbuf)
5582 FREE (buf);
5583 if (bufsize >= (INT_MAX / 2))
5584 return;
5585 bufsize = bufsize * 2;
5586 if (bufsize < len + 2)
5587 bufsize = len + 2;
5588 buf = (char *) malloc ((unsigned long) bufsize);
5589 if (buf == NULL)
5590 return;
5591 buf[bufsize-1] = '\0';
5592 continue;
5593 }
5594 break;
5595 }
5596
5597
5598
5599 for (i = j = 0; i < len; ++i)
5600 {
5601 if ('\n' == buf[i])
5602 {
5603 if (i >= j)
5604 {
5605 if ((i != j) || (i == 0))
5606 {
5607 (void)fprintf (sim_deb, "%lld.%06ld: DBG(%lld) %o: %s %s %.*s\r\n",
5608 (long long)t.tv_sec, t.tv_nsec/1000, cnt,
5609 current_running_cpu_idx, dptr->name, debug_type, i-j, &buf[j]);
5610 }
5611 }
5612 j = i + 1;
5613 }
5614 }
5615
5616
5617 if (buf != stackbuf)
5618 FREE (buf);
5619 }
5620
5621 }
5622 #endif
5623
5624 void setupPROM (uint cpuNo, unsigned char * PROM) {
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664 word36 rsw2 = 0;
5665
5666
5667
5668
5669
5670
5671
5672 putbits36_4 (& rsw2, 0, 0);
5673
5674 putbits36_2 (& rsw2, 4, 001);
5675
5676 putbits36_7 (& rsw2, 6, 2);
5677
5678 putbits36_1 (& rsw2, 13, 1);
5679
5680 putbits36_5 (& rsw2, 14, 0);
5681
5682 putbits36_1 (& rsw2, 19, 1);
5683
5684 putbits36_1 (& rsw2, 20, cpus[cpuNo].options.cache_installed ? 1 : 0);
5685
5686 putbits36_2 (& rsw2, 21, 0);
5687
5688 putbits36_1 (& rsw2, 23, 1);
5689
5690 putbits36_1 (& rsw2, 24, 0);
5691
5692 putbits36_4 (& rsw2, 25, 0);
5693
5694 putbits36_4 (& rsw2, 29, cpus[cpuNo].options.proc_speed & 017LL);
5695
5696 putbits36_3 (& rsw2, 33, cpus[cpuNo].switches.cpu_num & 07LL);
5697
5698 word4 rsw2Ext = 0;
5699 if (cpus[cpuNo].options.hex_mode_installed)
5700 rsw2Ext |= 010;
5701 if (cpus[cpuNo].options.clock_slave_installed)
5702 rsw2Ext |= 004;
5703
5704
5705 char serial[12];
5706 (void)sprintf (serial, "%-11u", cpus[cpuNo].switches.serno);
5707
5708 #if defined(VER_H_PROM_SHIP)
5709 char * ship = VER_H_PROM_SHIP;
5710 #else
5711 char * ship = "200101";
5712 #endif
5713
5714 #if !defined(VER_H_PROM_MAJOR_VER)
5715 # define VER_H_PROM_MAJOR_VER "999"
5716 #endif
5717
5718 #if !defined(VER_H_PROM_MINOR_VER)
5719 # define VER_H_PROM_MINOR_VER "999"
5720 #endif
5721
5722 #if !defined(VER_H_PROM_PATCH_VER)
5723 # define VER_H_PROM_PATCH_VER "999"
5724 #endif
5725
5726 #if !defined(VER_H_PROM_OTHER_VER)
5727 # define VER_H_PROM_OTHER_VER "999"
5728 #endif
5729
5730 #if !defined(VER_H_GIT_RELT)
5731 # define VER_H_GIT_RELT "X"
5732 #endif
5733
5734 #if !defined(VER_H_PROM_VER_TEXT)
5735 # define VER_H_PROM_VER_TEXT "Unknown "
5736 #endif
5737
5738 #if defined(BUILD_PROM_OSA_TEXT)
5739 # define BURN_PROM_OSA_TEXT BUILD_PROM_OSA_TEXT
5740 #else
5741 # if !defined(VER_H_PROM_OSA_TEXT)
5742 # define BURN_PROM_OSA_TEXT "Unknown Build Op Sys"
5743 # else
5744 # define BURN_PROM_OSA_TEXT VER_H_PROM_OSA_TEXT
5745 # endif
5746 #endif
5747
5748 #if defined(BUILD_PROM_OSV_TEXT)
5749 # define BURN_PROM_OSV_TEXT BUILD_PROM_OSV_TEXT
5750 #else
5751 # if !defined(VER_H_PROM_OSV_TEXT)
5752 # define BURN_PROM_OSV_TEXT "Unknown Build Arch. "
5753 # else
5754 # define BURN_PROM_OSV_TEXT VER_H_PROM_OSV_TEXT
5755 # endif
5756 #endif
5757
5758 #if defined(BUILD_PROM_TSA_TEXT)
5759 # define BURN_PROM_TSA_TEXT BUILD_PROM_TSA_TEXT
5760 #else
5761 # if defined(_M_X64) || defined(_M_AMD64) || defined(__amd64__) || defined(__x86_64__) || defined(__AMD64)
5762 # define VER_H_PROM_TSA_TEXT "Intel x86_64 (AMD64)"
5763 # elif defined(_M_IX86) || defined(__i386) || defined(__i486) || defined(__i586) || defined(__i686) || defined(__ix86)
5764 # define VER_H_PROM_TSA_TEXT "Intel ix86 (32-bit) "
5765 # elif defined(_M_ARM64) || defined(__aarch64__) || defined(__arm64__)
5766 # define VER_H_PROM_TSA_TEXT "AArch64/ARM64/64-bit"
5767 # elif defined(_M_ARM) || defined(__arm__)
5768 # define VER_H_PROM_TSA_TEXT "AArch32/ARM32/32-bit"
5769 # elif defined(__ia64__) || defined(_M_IA64) || defined(__itanium__)
5770 # define VER_H_PROM_TSA_TEXT "Intel Itanium (IA64)"
5771 # elif defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__) || defined(__powerpc64__) || \
5772 defined(__POWERPC64__) || \
5773 defined(_M_PPC64) || \
5774 defined(__PPC64) || \
5775 defined(_ARCH_PPC64)
5776 # define VER_H_PROM_TSA_TEXT "Power ISA (64-bit) "
5777 # elif defined(__ppc__) || defined(__PPC__) || defined(__powerpc__) || defined(__POWERPC__) || defined(_M_PPC) || \
5778 defined(__PPC) || \
5779 defined(__ppc32__) || \
5780 defined(__PPC32__) || \
5781 defined(__powerpc32__) || \
5782 defined(__POWERPC32__) || \
5783 defined(_M_PPC32) || \
5784 defined(__PPC32)
5785 # define VER_H_PROM_TSA_TEXT "PowerPC ISA (32-bit)"
5786 # elif defined(__s390x__)
5787 # define VER_H_PROM_TSA_TEXT "IBM z/Architecture "
5788 # elif defined(__s390__)
5789 # define VER_H_PROM_TSA_TEXT "IBM ESA System/390 "
5790 # elif defined(__J2__) || defined(__J2P__) || defined(__j2__) || defined(__j2p__)
5791 # define VER_H_PROM_TSA_TEXT "J-Core J2 Open CPU "
5792 # elif defined(__SH4__) || defined(__sh4__) || defined(__SH4) || defined(__sh4)
5793 # define VER_H_PROM_TSA_TEXT "Hitachi/Renesas SH-4"
5794 # elif defined(__SH2__) || defined(__sh2__) || defined(__SH2) || defined(__sh2)
5795 # define VER_H_PROM_TSA_TEXT "Hitachi/Renesas SH-2"
5796 # elif defined(__alpha__)
5797 # define VER_H_PROM_TSA_TEXT "Alpha AXP "
5798 # elif defined(__hppa__) || defined(__HPPA__) || defined(__PARISC__) || defined(__parisc__)
5799 # define VER_H_PROM_TSA_TEXT "HP PA-RISC "
5800 # elif defined(__ICE9__) || defined(__ice9__) || defined(__ICE9) || defined(__ice9)
5801 # define VER_H_PROM_TSA_TEXT "SiCortex ICE-9 "
5802 # elif defined(mips64) || defined(__mips64__) || defined(MIPS64) || defined(_MIPS64_) || defined(__mips64)
5803 # define VER_H_PROM_TSA_TEXT "MIPS64 "
5804 # elif defined(mips) || defined(__mips__) || defined(MIPS) || defined(_MIPS_) || defined(__mips)
5805 # define VER_H_PROM_TSA_TEXT "MIPS "
5806 # elif defined(__OpenRISC__) || defined(__OPENRISC__) || defined(__openrisc__) || defined(__OR1K__) || defined(__OPENRISC1K__)
5807 # define VER_H_PROM_TSA_TEXT "OpenRISC "
5808 # elif defined(__sparc64) || defined(__SPARC64) || defined(__SPARC64__) || defined(__sparc64__)
5809 # define VER_H_PROM_TSA_TEXT "SPARC64 "
5810 # elif defined(__sparc) || defined(__SPARC) || defined(__SPARC__) || defined(__sparc__)
5811 # define VER_H_PROM_TSA_TEXT "SPARC "
5812 # elif defined(__riscv) || defined(__riscv__)
5813 # define VER_H_PROM_TSA_TEXT "RISC-V "
5814 # elif defined(__e2k__) || defined(__E2K__) || defined(__elbrus64__) || defined(__elbrus__) || defined(__ELBRUS__) || defined(__e2k64__)
5815 # if defined(__iset__)
5816 # if __iset__ > 0
5817 # if __iset__ == 1
5818 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v1 "
5819 # elif __iset__ == 2
5820 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v2 "
5821 # elif __iset__ == 3
5822 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v3 "
5823 # elif __iset__ == 4
5824 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v4 "
5825 # elif __iset__ == 5
5826 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v5 "
5827 # elif __iset__ == 6
5828 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v6 "
5829 # elif __iset__ == 7
5830 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v7 "
5831 # elif __iset__ == 8
5832 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v8 "
5833 # elif __iset__ == 9
5834 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v9 "
5835 # elif __iset__ == 10
5836 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v10 "
5837 # else
5838 # define VER_H_PROM_TSA_TEXT "MCST Elbrus "
5839 # endif
5840 # else
5841 # define VER_H_PROM_TSA_TEXT "MCST Elbrus "
5842 # endif
5843 # else
5844 # define VER_H_PROM_TSA_TEXT "MCST Elbrus "
5845 # endif
5846 # elif defined(__myriad2__)
5847 # define VER_H_PROM_TSA_TEXT "Myriad2 "
5848 # elif defined(__loongarch64) || defined(__loongarch__)
5849 # define VER_H_PROM_TSA_TEXT "LoongArch "
5850 # elif defined(_m68851) || defined(__m68k__) || defined(__m68000__) || defined(__M68K)
5851 # define VER_H_PROM_TSA_TEXT "Motorola m68k "
5852 # elif defined(__m88k__) || defined(__m88000__) || defined(__M88K)
5853 # define VER_H_PROM_TSA_TEXT "Motorola m88k "
5854 # elif defined(__VAX__) || defined(__vax__)
5855 # define VER_H_PROM_TSA_TEXT "VAX "
5856 # elif defined(__NIOS2__) || defined(__nios2__)
5857 # define VER_H_PROM_TSA_TEXT "Altera Nios II "
5858 # elif defined(__MICROBLAZE__) || defined(__microblaze__)
5859 # define VER_H_PROM_TSA_TEXT "Xilinx MicroBlaze "
5860 # elif defined(__kvx__) || defined(__KVX__) || defined(__KVX_64__)
5861 # define VER_H_PROM_TSA_TEXT "Kalray KVX "
5862 # endif
5863 # if !defined(VER_H_PROM_TSA_TEXT)
5864 # define BURN_PROM_TSA_TEXT "Unknown Target Arch."
5865 # else
5866 # define BURN_PROM_TSA_TEXT VER_H_PROM_TSA_TEXT
5867 # endif
5868 #endif
5869
5870 #if (defined(__WIN__) || defined(_WIN32) || defined(IS_WINDOWS) || defined(_MSC_VER) || defined(__MINGW32__) || \
5871 defined(__MINGW64__) || defined(CROSS_MINGW32) || defined(CROSS_MINGW64)) && !defined(__CYGWIN__)
5872 # define DC_IS_WINDOWS 1
5873 #else
5874 # define DC_IS_WINDOWS 0
5875 #endif
5876
5877 #if defined(BUILD_PROM_TSV_TEXT)
5878 # define BURN_PROM_TSV_TEXT BUILD_PROM_TSV_TEXT
5879 #else
5880 # if DC_IS_WINDOWS
5881 # define VER_H_PROM_TSV_TEXT "Microsoft Windows "
5882 # elif defined(__CYGWIN__)
5883 # define VER_H_PROM_TSV_TEXT "Windows/Cygwin "
5884 # elif (defined(__sunos) || defined(__sun) || defined(__sun__)) && (defined(SYSV) || defined(__SVR4) || defined(__SVR4__) || \
5885 defined(__svr4__))
5886 # if defined(__illumos__)
5887 # define VER_H_PROM_TSV_TEXT "illumos "
5888 # else
5889 # define VER_H_PROM_TSV_TEXT "Solaris "
5890 # endif
5891 # elif defined(__APPLE__) && defined(__MACH__)
5892 # define VER_H_PROM_TSV_TEXT "Apple macOS "
5893 # elif defined(__GNU__) && !defined(__linux__)
5894 # define VER_H_PROM_TSV_TEXT "GNU/Hurd "
5895 # elif defined(__ANDROID__) && defined(__ANDROID_API__)
5896 # if defined(__linux__)
5897 # define VER_H_PROM_TSV_TEXT "Android/Linux "
5898 # else
5899 # define VER_H_PROM_TSV_TEXT "Android "
5900 # endif
5901 # elif defined(__lynxOS__) || defined(__LYNXOS__) || defined(LynxOS) || defined(LYNXOS)
5902 # define VER_H_PROM_TSV_TEXT "LynxOS "
5903 # elif defined(__HELENOS__)
5904 # define VER_H_PROM_TSV_TEXT "HelenOS "
5905 # elif defined(__linux__)
5906 # if defined(__BIONIC__)
5907 # define VER_H_PROM_TSV_TEXT "Linux/Bionic-libc "
5908 # elif defined(__UCLIBC__) || defined(UCLIBC)
5909 # define VER_H_PROM_TSV_TEXT "Linux/uClibc "
5910 # elif defined(__NEWLIB__)
5911 # define VER_H_PROM_TSV_TEXT "Linux/Newlib "
5912 # elif defined(__dietlibc__)
5913 # define VER_H_PROM_TSV_TEXT "Linux/Diet-libc "
5914 # elif defined(__GLIBC__)
5915 # define VER_H_PROM_TSV_TEXT "GNU/Linux "
5916 # else
5917 # define VER_H_PROM_TSV_TEXT "Linux "
5918 # endif
5919 # elif defined(__HAIKU__)
5920 # define VER_H_PROM_TSV_TEXT "Haiku "
5921 # elif defined(__serenity__)
5922 # define VER_H_PROM_TSV_TEXT "SerenityOS "
5923 # elif defined(__FreeBSD__)
5924 # define VER_H_PROM_TSV_TEXT "FreeBSD "
5925 # elif defined(__NetBSD__)
5926 # define VER_H_PROM_TSV_TEXT "NetBSD "
5927 # elif defined(__OpenBSD__)
5928 # define VER_H_PROM_TSV_TEXT "OpenBSD "
5929 # elif defined(__DragonFly__)
5930 # define VER_H_PROM_TSV_TEXT "DragonFly BSD "
5931 # elif defined(_AIX)
5932 # if !defined(__PASE__)
5933 # define VER_H_PROM_TSV_TEXT "IBM AIX "
5934 # else
5935 # define VER_H_PROM_TSV_TEXT "IBM OS/400 (PASE) "
5936 # endif
5937 # elif defined(__VXWORKS__) || defined(__VXWORKS) || defined(__vxworks) || defined(__vxworks__) || defined(_VxWorks)
5938 # if !defined(__RTP__)
5939 # define VER_H_PROM_TSV_TEXT "VxWorks "
5940 # else
5941 # define VER_H_PROM_TSV_TEXT "VxWorks RTP "
5942 # endif
5943 # elif defined(__rtems__)
5944 # if defined(__FreeBSD_version)
5945 # define VER_H_PROM_TSV_TEXT "RTEMS/LibBSD "
5946 # else
5947 # define VER_H_PROM_TSV_TEXT "RTEMS "
5948 # endif
5949 # elif defined(__ZEPHYR__)
5950 # define VER_H_PROM_TSV_TEXT "Zephyr "
5951 # elif defined(ti_sysbios_BIOS___VERS) || defined(ti_sysbios_BIOS__top__)
5952 # define VER_H_PROM_TSV_TEXT "TI-RTOS (SYS/BIOS) "
5953 # elif defined(__OSV__)
5954 # define VER_H_PROM_TSV_TEXT "OSv "
5955 # elif defined(MINIX) || defined(MINIX3) || defined(MINIX315) || defined(__minix__) || defined(__minix3__) || defined(__minix315__)
5956 # define VER_H_PROM_TSV_TEXT "Minix "
5957 # elif defined(__QNX__)
5958 # if defined(__QNXNTO__)
5959 # define VER_H_PROM_TSV_TEXT "QNX Neutrino "
5960 # else
5961 # define VER_H_PROM_TSV_TEXT "QNX "
5962 # endif
5963 # elif defined(__managarm__)
5964 # define VER_H_PROM_TSV_TEXT "Managarm "
5965 # endif
5966 # if !defined(VER_H_PROM_TSV_TEXT)
5967 # define BURN_PROM_TSV_TEXT "Unknown Target OpSys"
5968 # else
5969 # define BURN_PROM_TSV_TEXT VER_H_PROM_TSV_TEXT
5970 # endif
5971 #endif
5972
5973 #if !defined(VER_H_GIT_DATE_SHORT)
5974 # define VER_H_GIT_DATE_SHORT "2021-01-01"
5975 #endif
5976
5977 #if !defined(BURN_PROM_BUILD_NUM)
5978 # define BURN_PROM_BUILD_NUM " "
5979 #endif
5980
5981 #define BURN(offset, length, string) memcpy ((char *) PROM + (offset), string, length)
5982 #define BURN1(offset, byte) PROM[offset] = (char) (byte)
5983
5984 (void)memset (PROM, 255, 1024);
5985
5986
5987 BURN ( 00, 11, "DPS 8/SIM M");
5988 BURN (013, 11, serial);
5989 BURN (026, 6, ship);
5990 BURN1 (034, getbits36_8 (rsw2, 0));
5991 BURN1 (035, getbits36_8 (rsw2, 8));
5992 BURN1 (036, getbits36_8 (rsw2, 16));
5993 BURN1 (037, getbits36_8 (rsw2, 24));
5994 BURN1 (040, ((getbits36_4 (rsw2, 32) << 4) \
5995 | rsw2Ext));
5996
5997
5998 BURN ( 60, 1, "2");
5999 BURN ( 70, 10, VER_H_GIT_DATE_SHORT);
6000 BURN ( 80, 3, VER_H_PROM_MAJOR_VER);
6001 BURN ( 83, 3, VER_H_PROM_MINOR_VER);
6002 BURN ( 86, 3, VER_H_PROM_PATCH_VER);
6003 BURN ( 89, 3, VER_H_PROM_OTHER_VER);
6004 BURN ( 92, 8, BURN_PROM_BUILD_NUM);
6005 BURN (100, 1, VER_H_GIT_RELT);
6006 BURN (101, 29, VER_H_PROM_VER_TEXT);
6007 BURN (130, 20, BURN_PROM_OSA_TEXT);
6008 BURN (150, 20, BURN_PROM_OSV_TEXT);
6009 BURN (170, 20, BURN_PROM_TSA_TEXT);
6010 BURN (190, 20, BURN_PROM_TSV_TEXT);
6011 }
6012
6013 void cpuStats (uint cpuNo) {
6014 if (! cpus[cpuNo].cycleCnt)
6015 return;
6016
6017
6018 #if defined(__HAIKU__)
6019 # if HAS_INCLUDE(<syscall_clock_info.h>)
6020 # include <syscall_clock_info.h>
6021 # endif
6022 # if !defined(_SYSTEM_SYSCALL_CLOCK_INFO_H)
6023 # if !defined(HAIKU_NO_PTHREAD_GETCPUCLOCKID)
6024 # define HAIKU_NO_PTHREAD_GETCPUCLOCKID
6025 # endif
6026 # endif
6027 #endif
6028
6029
6030
6031 #if defined(__sun) || defined(__sun__)
6032 # if !defined(__illumos__)
6033 # if HAS_INCLUDE(<sys/sysevent.h>)
6034 # include <sys/sysevent.h>
6035 # endif
6036 # if defined(ILLUMOS_VENDOR) || defined(ILLUMOS_KERN_PUB)
6037 # define __illumos__
6038 # endif
6039 # endif
6040 #endif
6041
6042 double cpu_seconds = 0;
6043 int cpu_millis = 0;
6044 char cpu_ftime[64] = {0};
6045 #if (defined(THREADZ) || defined(LOCKLESS))
6046 # if !defined(HAIKU_NO_PTHREAD_GETCPUCLOCKID) && !defined(__illumos__) && \
6047 !defined(__APPLE__) && !defined(__PASE__) && !defined(__serenity__)
6048 struct timespec cpu_time;
6049 clockid_t clock_id;
6050 if (pthread_getcpuclockid (cpus[cpuNo].thread_id, &clock_id) == 0) {
6051 if (clock_gettime (clock_id, &cpu_time) == 0) {
6052 cpu_seconds = (double)cpu_time.tv_sec + cpu_time.tv_nsec / 1e9;
6053 }
6054 }
6055 # endif
6056 #endif
6057
6058 if (cpu_seconds > 0 && cpus[cpuNo].instrCnt > 0) {
6059 int cpu_hours = (int)(cpu_seconds / 3600);
6060 int cpu_minutes = (int)((cpu_seconds - cpu_hours * 3600) / 60);
6061 int cpu_secs = (int)(cpu_seconds - (cpu_hours * 3600) - (cpu_minutes * 60));
6062 struct tm cpu_tm = {0};
6063 cpu_tm.tm_hour = cpu_hours;
6064 cpu_tm.tm_min = cpu_minutes;
6065 cpu_tm.tm_sec = cpu_secs;
6066 strftime(cpu_ftime, sizeof(cpu_ftime), "%H:%M:%S", &cpu_tm);
6067 cpu_millis = (int)((cpu_seconds - (cpu_hours * 3600) - (cpu_minutes * 60) - cpu_secs) * 1000);
6068 }
6069
6070 (void)fflush(stderr);
6071 (void)fflush(stdout);
6072 sim_msg ("\r\n");
6073 (void)fflush(stdout);
6074 (void)fflush(stderr);
6075 sim_msg ("\r+---------------------------------+\r\n");
6076 sim_msg ("\r| CPU %c Statistics |\r\n", 'A' + cpuNo);
6077 sim_msg ("\r+---------------------------------+\r\n");
6078 if (cpu_seconds > 0 && cpus[cpuNo].instrCnt > 0) {
6079 sim_msg ("\r| CPU Time Used %11s.%03d |\r\n", cpu_ftime, cpu_millis);
6080 sim_msg ("\r+---------------------------------+\r\n");
6081 }
6082 (void)fflush(stdout);
6083 (void)fflush(stderr);
6084 #if defined(_AIX) && !defined(__PASE__)
6085 struct rusage rusage;
6086 if (!pthread_getrusage_np(cpus[cpuNo].thread_id, &rusage, PTHRDSINFO_RUSAGE_COLLECT)) {
6087 sim_msg ("\r| Volun. CtxtSw %'15llu |\r\n", (unsigned long long)rusage.ru_nvcsw);
6088 sim_msg ("\r| Invol. CtxtSw %'15llu |\r\n", (unsigned long long)rusage.ru_nivcsw);
6089 sim_msg ("\r+---------------------------------+\r\n");
6090 }
6091 #endif
6092 #if defined(WIN_STDIO)
6093 sim_msg ("\r| cycles %15llu |\r\n", (unsigned long long)cpus[cpuNo].cycleCnt);
6094 sim_msg ("\r| instructions %15llu |\r\n", (unsigned long long)cpus[cpuNo].instrCnt);
6095 (void)fflush(stdout);
6096 (void)fflush(stderr);
6097 sim_msg ("\r+---------------------------------+\r\n");
6098 sim_msg ("\r| lockCnt %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockCnt);
6099 sim_msg ("\r| lockImmediate %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockImmediate);
6100 (void)fflush(stdout);
6101 (void)fflush(stderr);
6102 sim_msg ("\r+---------------------------------+\r\n");
6103 sim_msg ("\r| lockWait %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockWait);
6104 sim_msg ("\r| lockWaitMax %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockWaitMax);
6105 (void)fflush(stdout);
6106 (void)fflush(stderr);
6107 # if !defined(SCHED_NEVER_YIELD)
6108 sim_msg ("\r| lockYield %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockYield);
6109 (void)fflush(stdout);
6110 (void)fflush(stderr);
6111 # else
6112 sim_msg ("\r| lockYield ---- |\r\n");
6113 (void)fflush(stdout);
6114 (void)fflush(stderr);
6115 # endif
6116 sim_msg ("\r+---------------------------------+");
6117 (void)fflush(stdout);
6118 (void)fflush(stderr);
6119 # if !defined(UCACHE)
6120 # if !defined(UCACHE_STATS)
6121 sim_msg ("\r\n");
6122 # endif
6123 # endif
6124 (void)fflush(stdout);
6125 (void)fflush(stderr);
6126 #else
6127 sim_msg ("\r| cycles %'15llu |\r\n", (unsigned long long)cpus[cpuNo].cycleCnt);
6128 sim_msg ("\r| instructions %'15llu |\r\n", (unsigned long long)cpus[cpuNo].instrCnt);
6129 (void)fflush(stdout);
6130 (void)fflush(stderr);
6131 sim_msg ("\r+---------------------------------+\r\n");
6132 sim_msg ("\r| lockCnt %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockCnt);
6133 sim_msg ("\r| lockImmediate %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockImmediate);
6134 (void)fflush(stdout);
6135 (void)fflush(stderr);
6136 sim_msg ("\r+---------------------------------+\r\n");
6137 sim_msg ("\r| lockWait %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockWait);
6138 sim_msg ("\r| lockWaitMax %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockWaitMax);
6139 (void)fflush(stdout);
6140 (void)fflush(stderr);
6141 # if !defined(SCHED_NEVER_YIELD)
6142 sim_msg ("\r| lockYield %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockYield);
6143 (void)fflush(stdout);
6144 (void)fflush(stderr);
6145 # else
6146 sim_msg ("\r| lockYield ---- |\r\n");
6147 (void)fflush(stdout);
6148 (void)fflush(stderr);
6149 # endif
6150 sim_msg ("\r+---------------------------------+");
6151 (void)fflush(stdout);
6152 (void)fflush(stderr);
6153 # if !defined(UCACHE)
6154 # if !defined(UCACHE_STATS)
6155 sim_msg ("\r\n");
6156 # endif
6157 # endif
6158 (void)fflush(stderr);
6159 (void)fflush(stdout);
6160 #endif
6161
6162 #if defined(UCACHE_STATS)
6163 ucacheStats (cpuNo);
6164 #endif
6165
6166
6167
6168
6169
6170
6171
6172 }
6173
6174 bool running_perf_test;
6175
6176 #if defined(THREADZ) || defined(LOCKLESS)
6177 # include <locale.h>
6178 # include "segldr.h"
6179
6180 void perfTest (char * testName) {
6181 running_perf_test = true;
6182
6183 if (testName == NULL)
6184 testName = "strip.mem";
6185
6186 # if !defined(NO_LOCALE)
6187 (void) setlocale(LC_NUMERIC, "");
6188 # endif
6189
6190
6191 # if !defined(_AIX)
6192 system_state = aligned_malloc (sizeof (struct system_state_s));
6193 # else
6194 system_state = malloc (sizeof (struct system_state_s));
6195 # endif
6196 if (!system_state)
6197 {
6198 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
6199 __func__, __FILE__, __LINE__);
6200 # if defined(USE_BACKTRACE)
6201 # if defined(SIGUSR2)
6202 (void)raise(SIGUSR2);
6203
6204 # endif
6205 # endif
6206 abort();
6207 }
6208 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) && !defined(__PASE__)
6209 if (0 == sim_free_memory || sim_free_memory >= 192000000) {
6210 if (mlock(system_state, sizeof(struct system_state_s)) == -1) {
6211 mlock_failure = true;
6212 }
6213 } else {
6214 # if defined(TESTING)
6215 sim_warn ("Low memory - no memory locking attempted.\r\n");
6216 # else
6217 (void)system_state;
6218 # endif
6219 }
6220 # endif
6221 M = system_state->M;
6222 # if defined(M_SHARED)
6223 cpus = system_state->cpus;
6224 # endif
6225 (void) memset (cpus, 0, sizeof (cpu_state_t) * N_CPU_UNITS_MAX);
6226 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
6227 cpus[i].switches.FLT_BASE = 2;
6228 cpus[i].instrCnt = 0;
6229 cpus[i].cycleCnt = 0;
6230 for (int j = 0; j < N_FAULTS; j ++)
6231 cpus[i].faultCnt [j] = 0;
6232 }
6233
6234 cpus[0].tweaks.enable_emcall = 1;
6235 opc_dev.numunits = 1;
6236 cpu_reset_unit_idx (0, false);
6237 set_cpu_cycle (& cpus[0], FETCH_cycle);
6238 mrestore (testName);
6239 _cpup = & cpus[0];
6240 threadz_sim_instr ();
6241 }
6242 #endif