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