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 mgp_process_event ();
1549 # endif
1550 # if defined(WITH_NET_DEV)
1551 net_process_event ();
1552 # endif
1553 PNL (panel_process_event ());
1554 }
1555 #endif
1556
1557
1558
1559 void cpu_init (void)
1560 {
1561
1562
1563
1564 M = system_state->M;
1565 #if defined(M_SHARED)
1566 cpus = system_state->cpus;
1567 #endif
1568
1569 #if !defined(SPEED)
1570 (void)memset (& watch_bits, 0, sizeof (watch_bits));
1571 #endif
1572
1573 set_cpu_idx (0);
1574
1575 (void)memset (cpus, 0, sizeof (cpu_state_t) * N_CPU_UNITS_MAX);
1576
1577 #if !defined(PERF_STRIP)
1578 get_serial_number (_cpup);
1579
1580 ev_poll_loop = uv_default_loop ();
1581 uv_timer_init (ev_poll_loop, & ev_poll_handle);
1582
1583 unsigned int poll_interval = sys_opts.sys_poll_interval;
1584 uv_timer_start (& ev_poll_handle, ev_poll_cb, poll_interval, poll_interval);
1585 #endif
1586
1587
1588 cpu_state_t * cpup = _cpup;
1589
1590 cpu.instrCnt = 0;
1591 cpu.cycleCnt = 0;
1592 for (int i = 0; i < N_FAULTS; i ++)
1593 cpu.faultCnt [i] = 0;
1594
1595 #if defined(MATRIX)
1596 initializeTheMatrix ();
1597 #endif
1598 }
1599
1600 static void cpu_reset (void)
1601 {
1602 for (uint i = 0; i < N_CPU_UNITS_MAX; i ++)
1603 {
1604 cpu_reset_unit_idx (i, true);
1605 }
1606
1607 set_cpu_idx (0);
1608
1609 #if defined(TESTING)
1610 cpu_state_t * cpup = _cpup;
1611 sim_debug (DBG_INFO, & cpu_dev, "CPU reset: Running\r\n");
1612 #endif
1613 }
1614
1615 static t_stat sim_cpu_reset (UNUSED DEVICE *dptr)
1616 {
1617
1618
1619
1620
1621
1622 cpu_reset ();
1623 return SCPE_OK;
1624 }
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634 static t_stat cpu_ex (t_value *vptr, t_addr addr, UNUSED UNIT * uptr,
1635 UNUSED int32 sw)
1636 {
1637 if (addr>= MEMSIZE)
1638 return SCPE_NXM;
1639 if (vptr != NULL)
1640 {
1641 *vptr = M[addr] & DMASK;
1642 }
1643 return SCPE_OK;
1644 }
1645
1646
1647
1648 static t_stat cpu_dep (t_value val, t_addr addr, UNUSED UNIT * uptr,
1649 UNUSED int32 sw)
1650 {
1651 if (addr >= MEMSIZE) return SCPE_NXM;
1652 M[addr] = val & DMASK;
1653 return SCPE_OK;
1654 }
1655
1656
1657
1658
1659
1660 #if defined(M_SHARED)
1661
1662 static word18 dummy_IC;
1663 #endif
1664
1665 static REG cpu_reg[] =
1666 {
1667
1668 #if defined(M_SHARED)
1669 { ORDATA (IC, dummy_IC, VASIZE), 0, 0, 0 },
1670 #else
1671 { ORDATA (IC, cpus[0].PPR.IC, VASIZE), 0, 0, 0 },
1672 #endif
1673 { NULL, NULL, 0, 0, 0, 0, NULL, NULL, 0, 0, 0 }
1674 };
1675
1676
1677
1678
1679
1680 REG *sim_PC = & cpu_reg[0];
1681
1682
1683
1684 DEVICE cpu_dev =
1685 {
1686 "CPU",
1687 cpu_unit,
1688 cpu_reg,
1689 cpu_mod,
1690 N_CPU_UNITS,
1691 8,
1692 PASIZE,
1693 1,
1694 8,
1695 36,
1696 & cpu_ex,
1697 & cpu_dep,
1698 & sim_cpu_reset,
1699 & cpu_boot,
1700 NULL,
1701 NULL,
1702 NULL,
1703 DEV_DEBUG,
1704 0,
1705 cpu_dt,
1706 NULL,
1707 NULL,
1708 NULL,
1709 NULL,
1710 NULL,
1711 NULL,
1712 NULL
1713 };
1714
1715 #if defined(M_SHARED)
1716 cpu_state_t * cpus = NULL;
1717 #else
1718 cpu_state_t cpus [N_CPU_UNITS_MAX];
1719 #endif
1720 #if defined(THREADZ) || defined(LOCKLESS)
1721 __thread cpu_state_t * restrict _cpup;
1722 #else
1723 cpu_state_t * restrict _cpup;
1724 #endif
1725
1726
1727
1728
1729
1730
1731
1732 static uint get_highest_intr (cpu_state_t *cpup)
1733 {
1734 uint fp = 1;
1735 for (uint scu_unit_idx = 0; scu_unit_idx < N_SCU_UNITS_MAX; scu_unit_idx ++)
1736 {
1737 if (cpu.events.XIP [scu_unit_idx])
1738 {
1739 fp = scu_get_highest_intr (scu_unit_idx);
1740 if (fp != 1)
1741 break;
1742 }
1743 }
1744 return fp;
1745 }
1746
1747 bool sample_interrupts (cpu_state_t * cpup)
1748 {
1749 cpu.lufCounter = 0;
1750 for (uint scu_unit_idx = 0; scu_unit_idx < N_SCU_UNITS_MAX; scu_unit_idx ++)
1751 {
1752 if (cpu.events.XIP [scu_unit_idx])
1753 {
1754 return true;
1755 }
1756 }
1757 return false;
1758 }
1759
1760 t_stat simh_hooks (cpu_state_t * cpup)
1761 {
1762 int reason = 0;
1763
1764 if (breakEnable && stop_cpu)
1765 return STOP_STOP;
1766
1767 if (cpu.tweaks.isolts_mode == 0)
1768 {
1769
1770 if (sim_interval <= 0)
1771 {
1772 reason = sim_process_event ();
1773 if ((! breakEnable) && reason == SCPE_STOP)
1774 reason = SCPE_OK;
1775 if (reason)
1776 return reason;
1777 }
1778 }
1779
1780 sim_interval --;
1781
1782 #if !defined(THREADZ) && !defined(LOCKLESS)
1783
1784
1785
1786 if (sim_brk_summ &&
1787 sim_brk_test ((cpu.PPR.IC & 0777777) |
1788 ((((t_addr) cpu.PPR.PSR) & 037777) << 18),
1789 SWMASK ('E')))
1790 return STOP_BKPT;
1791 # if !defined(SPEED)
1792 if (sim_deb_break && cpu.cycleCnt >= sim_deb_break)
1793 return STOP_BKPT;
1794 # endif
1795 #endif
1796
1797 return reason;
1798 }
1799
1800 #if defined(PANEL68)
1801 static void panel_process_event (void)
1802 {
1803 cpu_state_t * cpup = _cpup;
1804
1805 if (cpu.panelInitialize && cpu.DATA_panel_s_trig_sw == 0)
1806 {
1807
1808 while (cpu.panelInitialize)
1809 ;
1810 if (cpu.DATA_panel_init_sw)
1811 cpu_reset_unit_idx (ASSUME0, true);
1812 else
1813 cpu_reset_unit_idx (ASSUME0, false);
1814
1815 do_boot ();
1816 }
1817
1818 if (cpu.DATA_panel_s_trig_sw == 0 &&
1819 cpu.DATA_panel_execute_sw &&
1820 cpu.DATA_panel_scope_sw &&
1821 cpu.DATA_panel_exec_sw == 0)
1822
1823 {
1824
1825 while (cpu.DATA_panel_execute_sw)
1826 ;
1827
1828 if (cpu.DATA_panel_exec_sw)
1829 {
1830 cpu_reset_unit_idx (ASSUME0, false);
1831 cpu.cu.IWB = cpu.switches.data_switches;
1832 set_cpu_cycle (cpup, EXEC_cycle);
1833 }
1834 else
1835 {
1836 setG7fault (current_running_cpu_idx, FAULT_EXF);
1837 }
1838 }
1839 }
1840 #endif
1841
1842 #if defined(THREADZ) || defined(LOCKLESS)
1843 bool bce_dis_called = false;
1844
1845
1846 t_stat sim_instr (void)
1847 {
1848 cpu_state_t * cpup = _cpup;
1849 t_stat reason = 0;
1850
1851
1852
1853
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 if (cpuThreadz[0].run == false)
1896 createCPUThread (0);
1897 do
1898 {
1899
1900 reason = simh_hooks (cpup);
1901 if (reason)
1902 {
1903 break;
1904 }
1905
1906
1907
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 if (bce_dis_called) {
1933
1934 reason = STOP_STOP;
1935 break;
1936 }
1937
1938 # if !defined(PERF_STRIP)
1939
1940
1941 # if defined(LOCKLESS)
1942 lock_iom();
1943 # endif
1944 lock_libuv ();
1945 uv_run (ev_poll_loop, UV_RUN_NOWAIT);
1946 unlock_libuv ();
1947 # if defined(LOCKLESS)
1948 unlock_iom();
1949 # endif
1950 PNL (panel_process_event ());
1951
1952 int con_unit_idx = check_attn_key ();
1953 if (con_unit_idx != -1)
1954 console_attn_idx (con_unit_idx);
1955 # endif
1956
1957 # if defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
1958 struct timespec next_time;
1959 clock_gettime (CLOCK_REALTIME, & next_time);
1960 next_time.tv_nsec += 1000l * 1000l;
1961 if (next_time.tv_nsec >= 1000l * 1000l *1000l)
1962 {
1963 next_time.tv_nsec -= 1000l * 1000l *1000l;
1964 next_time.tv_sec += (time_t) 1;
1965 }
1966 struct timespec new_time;
1967 do
1968 {
1969 pthread_mutex_lock (& iom_start_lock);
1970 pthread_cond_timedwait (& iomCond,
1971 & iom_start_lock,
1972 & next_time);
1973 pthread_mutex_unlock (& iom_start_lock);
1974 lock_iom();
1975 lock_libuv ();
1976
1977 iomProcess ();
1978
1979 unlock_libuv ();
1980 unlock_iom ();
1981
1982 clock_gettime (CLOCK_REALTIME, & new_time);
1983 }
1984 while ((next_time.tv_sec == new_time.tv_sec) ? (next_time.tv_nsec > new_time.tv_nsec) : \
1985 (next_time.tv_sec > new_time.tv_sec));
1986 # else
1987 sim_usleep (1000);
1988 # endif
1989 }
1990 while (reason == 0);
1991
1992 for (uint cpuNo = 0; cpuNo < N_CPU_UNITS_MAX; cpuNo ++) {
1993 cpuStats (cpuNo);
1994 }
1995
1996 # if defined(TESTING)
1997 HDBGPrint ();
1998 # endif
1999 return reason;
2000 }
2001 #endif
2002
2003 #if !defined(THREADZ) && !defined(LOCKLESS)
2004 static uint fast_queue_subsample = 0;
2005 #endif
2006
2007
2008
2009
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 #if defined(THREADZ) || defined(LOCKLESS)
2056 void * cpu_thread_main (void * arg)
2057 {
2058 int myid = * (int *) arg;
2059 set_cpu_idx ((uint) myid);
2060 unsigned char umyid = (unsigned char)toupper('a' + (int)myid);
2061 char thread_name[SIR_MAXPID] = {0};
2062 char temp_thread_name[SIR_MAXPID] = {0};
2063
2064 _cpup->thread_id = pthread_self();
2065
2066 if (realtime_ok) {
2067 set_realtime_priority (pthread_self(), realtime_max_priority() - 1);
2068 check_realtime_priority (pthread_self(), realtime_max_priority() - 1);
2069 } else {
2070 # if !defined(__QNX__)
2071 (void)sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
2072 # endif
2073 }
2074 _sir_snprintf_trunc(thread_name, SIR_MAXPID, "CPU %c", (unsigned int)umyid);
2075 if (!_sir_setthreadname(thread_name) || !_sir_getthreadname(temp_thread_name))
2076 (void)sir_info ("%s thread created (TID " SIR_TIDFORMAT ")",
2077 thread_name, PID_CAST _sir_gettid());
2078 else
2079 (void)sir_info ("Thread created (TID " SIR_TIDFORMAT ")",
2080 PID_CAST _sir_gettid());
2081 # if defined(TESTING) && defined(__APPLE__) && defined(__MACH__)
2082 (void)sir_info ("Mach thread ID: 0x%x", pthread_mach_thread_np(pthread_self()));
2083 # endif
2084 bool warned = false;
2085 if (realtime_ok) {
2086 if (myid + 2 > nprocs) {
2087 (void)sir_warn ("Total number of supervisor and CPU threads (%lu) exceeds available host parallelism (%lu)!",
2088 (unsigned long)(myid) + 2, (unsigned long)nprocs);
2089 warned = true;
2090 }
2091 if (!warned && nprocs >= 2 && ncores >= 1 && nprocs >= ncores && myid + 2 > ncores) {
2092 (void)sir_warn ("Total number of supervisor and CPU threads (%lu) exceeds physical host core count (%lu)!",
2093 (unsigned long)(myid) + 2, (unsigned long)ncores);
2094 }
2095 } else {
2096 if (myid + 1 > nprocs) {
2097 (void)sir_warn ("Total number of CPU threads (%lu) exceeds available host parallelism (%lu)!",
2098 (unsigned long)(myid) + 1, (unsigned long)nprocs);
2099 warned = true;
2100 }
2101 if (!warned && ncores >= 1 && nprocs >= ncores && myid + 1 > ncores) {
2102 (void)sir_warn ("Total number of CPU threads (%lu) exceeds physical host core count (%lu)!",
2103 (unsigned long)(myid) + 1, (unsigned long)ncores);
2104 }
2105 }
2106 setSignals ();
2107 threadz_sim_instr ();
2108 return NULL;
2109 }
2110 #endif
2111
2112 NO_RETURN
2113 static void do_LUF_fault (cpu_state_t * cpup)
2114 {
2115 CPT (cpt1U, 16);
2116 cpu.lufCounter = 0;
2117 cpu.lufOccurred = false;
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136 if (cpu.tweaks.isolts_mode)
2137 cpu.shadowTR = (word27) cpu.TR0 - (1024u << (is_priv_mode (cpup) ? 4 : cpu.CMR.luf));
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150 doFault (FAULT_LUF, fst_zero, "instruction cycle lockup");
2151 }
2152
2153 #if !defined(THREADZ) && !defined(LOCKLESS)
2154 # define threadz_sim_instr sim_instr
2155 #endif
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167 static void set_temporary_absolute_mode (cpu_state_t * cpup)
2168 {
2169 CPT (cpt1L, 20);
2170 cpu.secret_addressing_mode = true;
2171 cpu.cu.XSF = false;
2172 sim_debug (DBG_TRACEEXT, & cpu_dev, "set_temporary_absolute_mode bit 29 sets XSF to 0\r\n");
2173
2174 }
2175
2176 static bool clear_temporary_absolute_mode (cpu_state_t * cpup)
2177 {
2178 CPT (cpt1L, 21);
2179 cpu.secret_addressing_mode = false;
2180 return cpu.cu.XSF;
2181
2182 }
2183
2184 #if defined(THREADZ) || defined(LOCKLESS)
2185 static const int workAllocationQuantum = 64;
2186 static const int syncClockModePollRate = 64;
2187 static const int masterCycleCntlimit = 2048;
2188
2189 void becomeClockMaster (uint cpuNum) {
2190
2191 # ifdef SYNCTEST
2192 sim_printf ("CPU%c %s entry\r\n", cpuNum + 'A', __func__);
2193 allocCount = 0;
2194 # endif
2195
2196
2197
2198
2199 if (syncClockMode) {
2200
2201
2202
2203 return;
2204 }
2205
2206 syncClockModeMasterIdx = cpuNum;
2207 cpu_state_t * cpup = & cpus[cpuNum];
2208 cpu.syncClockModeMaster = true;
2209 cpu.masterCycleCnt = 0;
2210 cpu.syncClockModeCache = true;
2211 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
2212 if (i != cpuNum) {
2213 cpus[i].workAllocation = 0;
2214 __asm volatile ("");
2215 atomic_thread_fence (memory_order_seq_cst);
2216 if (cpus[i].inMultics && ! cpus[i].isSlave) {
2217 cpus[i].syncClockModePoll = 0;
2218 __asm volatile ("");
2219 atomic_thread_fence (memory_order_seq_cst);
2220 cpus[i].becomeSlave = true;
2221 __asm volatile ("");
2222 atomic_thread_fence (memory_order_seq_cst);
2223 }
2224 }
2225 }
2226
2227 __asm volatile ("");
2228 atomic_thread_fence (memory_order_seq_cst);
2229 syncClockMode = true;
2230
2231 __asm volatile ("");
2232 atomic_thread_fence (memory_order_seq_cst);
2233
2234 }
2235
2236 void giveupClockMaster (cpu_state_t * cpup) {
2237
2238 # ifdef SYNCTEST
2239
2240 sim_printf ("CPU%c %s entry\r\n", cpu.cpuIdx + 'A', __func__);
2241 sim_printf ("CPU%c Alloc count %d\r\n", cpu.cpuIdx + 'A', allocCount);
2242 # endif
2243 __asm volatile ("");
2244 cpu.syncClockModeMaster = false;
2245 __asm volatile ("");
2246 syncClockMode = false;
2247 __asm volatile ("");
2248 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
2249 cpus[i].syncClockModeCache = false;
2250 }
2251 __asm volatile ("");
2252 atomic_thread_fence (memory_order_seq_cst);
2253
2254 }
2255 #endif
2256
2257 t_stat threadz_sim_instr (void)
2258 {
2259 cpu_state_t * cpup = _cpup;
2260
2261
2262 #if !defined(SCHED_NEVER_YIELD)
2263 unsigned long long lockYieldAll = 0;
2264 #endif
2265 unsigned long long lockWaitMaxAll = 0;
2266 unsigned long long lockWaitAll = 0;
2267 unsigned long long lockImmediateAll = 0;
2268 unsigned long long lockCntAll = 0;
2269 unsigned long long instrCntAll = 0;
2270 unsigned long long cycleCntAll = 0;
2271
2272 t_stat reason = 0;
2273
2274 #if !defined(THREADZ) && !defined(LOCKLESS)
2275 set_cpu_idx (0);
2276 # if defined(M_SHARED)
2277
2278
2279
2280
2281 cpus [0].PPR.IC = dummy_IC;
2282 # endif
2283
2284 #endif
2285
2286
2287 int val = setjmp (cpu.jmpMain);
2288
2289 switch (val)
2290 {
2291 case JMP_ENTRY:
2292 case JMP_REENTRY:
2293 reason = 0;
2294 break;
2295 case JMP_SYNC_FAULT_RETURN:
2296 set_cpu_cycle (cpup, SYNC_FAULT_RTN_cycle);
2297 break;
2298 case JMP_STOP:
2299 reason = STOP_STOP;
2300 goto leave;
2301 case JMP_REFETCH:
2302
2303
2304
2305
2306
2307
2308
2309 cpu.wasXfer = false;
2310
2311 set_cpu_cycle (cpup, FETCH_cycle);
2312 break;
2313 case JMP_RESTART:
2314 set_cpu_cycle (cpup, EXEC_cycle);
2315 break;
2316 case JMP_FORCE_RESTART:
2317
2318
2319
2320
2321
2322
2323 cpu_reset_unit_idx (current_running_cpu_idx, false);
2324 #if defined(THREADZ) || defined(LOCKLESS)
2325
2326 if (syncClockMode && syncClockModeMasterIdx == current_running_cpu_idx)
2327 giveupClockMaster (cpup);
2328 #endif
2329 break;
2330 default:
2331 sim_warn ("longjmp value of %d unhandled\r\n", val);
2332 goto leave;
2333 }
2334
2335
2336
2337 DCDstruct * ci = & cpu.currentInstruction;
2338
2339 if (cpu.restart)
2340 {
2341 set_cpu_cycle (cpup, FAULT_cycle);
2342 }
2343
2344 #if defined(THREADZ) || defined(LOCKLESS)
2345
2346
2347
2348
2349 __asm volatile ("");
2350 cpu.executing = true;
2351 if (cpu.tweaks.isolts_mode) {
2352 ;
2353 } else {
2354 cpu.inMultics = true;
2355 }
2356 #endif
2357
2358 do
2359 {
2360
2361 reason = 0;
2362
2363 #if !defined(THREADZ) && !defined(LOCKLESS)
2364
2365 reason = simh_hooks (cpup);
2366 if (reason)
2367 {
2368 break;
2369 }
2370
2371
2372
2373
2374
2375
2376
2377
2378 if (fast_queue_subsample ++ > sys_opts.sys_poll_check_rate)
2379 {
2380 fast_queue_subsample = 0;
2381 # if defined(CONSOLE_FIX)
2382 # if defined(THREADZ) || defined(LOCKLESS)
2383 lock_libuv ();
2384 # endif
2385 # endif
2386 uv_run (ev_poll_loop, UV_RUN_NOWAIT);
2387 # if defined(CONSOLE_FIX)
2388 # if defined(THREADZ) || defined(LOCKLESS)
2389 unlock_libuv ();
2390 # endif
2391 # endif
2392 PNL (panel_process_event ());
2393 }
2394 #endif
2395
2396 cpu.cycleCnt ++;
2397
2398 #if defined(THREADZ)
2399
2400 unlock_mem_force ();
2401
2402
2403 cpuRunningWait ();
2404 #endif
2405 #if defined(LOCKLESS)
2406 core_unlock_all (cpup);
2407 #endif
2408
2409 #if !defined(LOCKLESS)
2410 int con_unit_idx = check_attn_key ();
2411 if (con_unit_idx != -1)
2412 console_attn_idx (con_unit_idx);
2413 #endif
2414
2415 #if !defined(THREADZ) && !defined(LOCKLESS)
2416 if (cpu.tweaks.isolts_mode)
2417 {
2418 if (cpu.cycle != FETCH_cycle)
2419 {
2420
2421 cpu.rTRlsb ++;
2422 if (cpu.rTRlsb >= 4)
2423 {
2424 cpu.rTRlsb = 0;
2425 cpu.shadowTR = (cpu.shadowTR - 1) & MASK27;
2426 if (cpu.shadowTR == 0)
2427 {
2428 if (cpu.tweaks.tro_enable)
2429 setG7fault (current_running_cpu_idx, FAULT_TRO);
2430 }
2431 }
2432 }
2433 }
2434 #endif
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448 # define TR_RATE 2
2449
2450
2451
2452 cpu.rTR = (word27) (((word27s) cpu.rTR) - (word27s) (cpu.rTRticks / TR_RATE));
2453 cpu.rTRticks %= TR_RATE;
2454
2455
2456
2457 if (cpu.rTR & ~MASK27)
2458 {
2459 cpu.rTR &= MASK27;
2460 if (cpu.tweaks.tro_enable) {
2461 setG7fault (current_running_cpu_idx, FAULT_TRO);
2462 }
2463 }
2464
2465 sim_debug (DBG_CYCLE, & cpu_dev, "Cycle is %s\r\n",
2466 cycle_str (cpu.cycle));
2467
2468 switch (cpu.cycle)
2469 {
2470 case INTERRUPT_cycle:
2471 {
2472 CPT (cpt1U, 0);
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484 uint intr_pair_addr = get_highest_intr (cpup);
2485 #if defined(TESTING)
2486 HDBGIntr (intr_pair_addr, "");
2487 #endif
2488 cpu.cu.FI_ADDR = (word5) (intr_pair_addr / 2);
2489 cu_safe_store (cpup);
2490
2491
2492
2493 CPT (cpt1U, 1);
2494
2495 set_temporary_absolute_mode (cpup);
2496
2497
2498 cpu.PPR.PRR = 0;
2499 cpu.TPR.TRR = 0;
2500
2501 sim_debug (DBG_INTR, & cpu_dev, "intr_pair_addr %u flag %d\r\n",
2502 intr_pair_addr, cpu.interrupt_flag);
2503 #if !defined(SPEED)
2504 if_sim_debug (DBG_INTR, & cpu_dev)
2505 traceInstruction (DBG_INTR);
2506 #endif
2507
2508 if (cpu.interrupt_flag)
2509 {
2510 CPT (cpt1U, 2);
2511
2512
2513
2514
2515
2516
2517 if (intr_pair_addr != 1)
2518 {
2519 CPT (cpt1U, 3);
2520
2521
2522 core_read2 (cpup, intr_pair_addr,
2523 & cpu.cu.IWB, & cpu.cu.IRODD, __func__);
2524 #if defined(TESTING)
2525 HDBGMRead (intr_pair_addr, cpu.cu.IWB, "intr even");
2526 HDBGMRead (intr_pair_addr + 1, cpu.cu.IRODD, "intr odd");
2527 #endif
2528 cpu.cu.xde = 1;
2529 cpu.cu.xdo = 1;
2530 cpu.isExec = true;
2531 cpu.isXED = true;
2532
2533 CPT (cpt1U, 4);
2534 cpu.interrupt_flag = false;
2535 set_cpu_cycle (cpup, INTERRUPT_EXEC_cycle);
2536 break;
2537 }
2538 }
2539
2540
2541
2542 CPT (cpt1U, 5);
2543 cpu.interrupt_flag = false;
2544 clear_temporary_absolute_mode (cpup);
2545
2546 cu_safe_restore (cpup);
2547
2548
2549 cpu.wasXfer = false;
2550
2551
2552 set_cpu_cycle (cpup, FETCH_cycle);
2553 }
2554 break;
2555
2556 case FETCH_cycle:
2557 #if defined(PANEL68)
2558 (void)memset (cpu.cpt, 0, sizeof (cpu.cpt));
2559 #endif
2560 CPT (cpt1U, 13);
2561
2562 PNL (L68_ (cpu.INS_FETCH = false;))
2563
2564
2565
2566
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 if (get_bar_mode (cpup))
2600 get_BAR_address (cpup, cpu.PPR.IC);
2601
2602
2603
2604
2605 bool tmp_priv_mode = is_priv_mode (cpup);
2606 bool is_dis = cpu.currentInstruction.opcode == 0616 &&
2607 cpu.currentInstruction.opcodeX == 0;
2608 bool noCheckTR = tmp_priv_mode &&
2609 !(is_dis && GET_I (cpu.cu.IWB) == 0);
2610
2611 if (is_dis)
2612 {
2613
2614
2615 cpu.interrupt_flag = sample_interrupts (cpup);
2616 cpu.g7_flag =
2617 noCheckTR ? bG7PendingNoTRO (cpup) : bG7Pending (cpup);
2618 }
2619 else if (! (cpu.cu.xde | cpu.cu.xdo |
2620 cpu.cu.rpt | cpu.cu.rd | cpu.cu.rl))
2621 {
2622 if ((!cpu.wasInhibited) &&
2623 (cpu.PPR.IC & 1) == 0 &&
2624 (! cpu.wasXfer))
2625 {
2626 CPT (cpt1U, 14);
2627 cpu.interrupt_flag = sample_interrupts (cpup);
2628 cpu.g7_flag =
2629 noCheckTR ? bG7PendingNoTRO (cpup) : bG7Pending (cpup);
2630 }
2631 cpu.wasInhibited = false;
2632 }
2633 else
2634 {
2635
2636
2637
2638
2639
2640 if ((cpu.PPR.IC & 1) == 1)
2641 {
2642 cpu.wasInhibited = true;
2643 }
2644 }
2645
2646
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 if (cpu.g7_flag)
2681 {
2682 cpu.g7_flag = false;
2683 cpu.interrupt_flag = false;
2684 sim_debug (DBG_CYCLE, & cpu_dev,
2685 "call doG7Fault (%d)\r\n", !noCheckTR);
2686 doG7Fault (cpup, !noCheckTR);
2687 }
2688 if (cpu.interrupt_flag)
2689 {
2690
2691
2692
2693 CPT (cpt1U, 15);
2694 set_cpu_cycle (cpup, INTERRUPT_cycle);
2695 break;
2696 }
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706 case PSEUDO_FETCH_cycle:
2707
2708 tmp_priv_mode = is_priv_mode (cpup);
2709 if (! (luf_flag && tmp_priv_mode))
2710 cpu.lufCounter ++;
2711
2712 if (cpu.lufCounter > luf_limits[cpu.CMR.luf])
2713 {
2714 if (tmp_priv_mode)
2715 {
2716
2717 cpu.lufOccurred = true;
2718 }
2719 else
2720 {
2721 do_LUF_fault (cpup);
2722 }
2723 }
2724
2725
2726 if (cpu.lufCounter > luf_limits[4])
2727 {
2728 do_LUF_fault (cpup);
2729 }
2730
2731
2732
2733 if (! tmp_priv_mode && cpu.lufOccurred)
2734 {
2735 do_LUF_fault (cpup);
2736 }
2737
2738
2739
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 if (cpu.cycle == PSEUDO_FETCH_cycle)
2770 {
2771 cpu.apu.lastCycle = INSTRUCTION_FETCH;
2772 cpu.cu.XSF = 0;
2773 cpu.cu.TSN_VALID [0] = 0;
2774 cpu.TPR.TSR = cpu.PPR.PSR;
2775 cpu.TPR.TRR = cpu.PPR.PRR;
2776 cpu.wasInhibited = false;
2777 }
2778 else
2779 {
2780 CPT (cpt1U, 20);
2781 cpu.isExec = false;
2782 cpu.isXED = false;
2783
2784
2785
2786 cpu.cu.XSF = 0;
2787 sim_debug (DBG_TRACEEXT, & cpu_dev, "fetchCycle bit 29 sets XSF to 0\r\n");
2788 cpu.cu.TSN_VALID [0] = 0;
2789 cpu.TPR.TSR = cpu.PPR.PSR;
2790 cpu.TPR.TRR = cpu.PPR.PRR;
2791 PNL (cpu.prepare_state = ps_PIA);
2792 PNL (L68_ (cpu.INS_FETCH = true;))
2793 fetchInstruction (cpup, cpu.PPR.IC);
2794 }
2795
2796 CPT (cpt1U, 21);
2797 advanceG7Faults (cpup);
2798 set_cpu_cycle (cpup, EXEC_cycle);
2799 break;
2800
2801 case EXEC_cycle:
2802 case FAULT_EXEC_cycle:
2803 case INTERRUPT_EXEC_cycle:
2804 {
2805 #if defined(THREADZ) || defined(LOCKLESS)
2806
2807
2808 if (UNLIKELY (cpu.becomeSlave)) {
2809 cpu.becomeSlave = false;
2810
2811 while (! syncClockMode) {
2812 sim_usleep (1);
2813 }
2814
2815 cpu.syncClockModePoll = 0;
2816 }
2817
2818
2819 if (cpu.syncClockModeCache || --cpu.syncClockModePoll <= 0) {
2820
2821 cpu.syncClockModePoll = cpu.tweaks.isolts_mode ? 1 : syncClockModePollRate;
2822
2823
2824 if (syncClockMode) {
2825
2826
2827 cpu.syncClockModeCache = true;
2828
2829
2830 if (syncClockModeMasterIdx == current_running_cpu_idx) {
2831
2832
2833 cpu.masterCycleCnt ++;
2834 if (cpu.masterCycleCnt > masterCycleCntlimit) {
2835 # ifdef SYNCTEST
2836 sim_printf ("too many cycles\r\n");
2837 # endif
2838 giveupClockMaster (cpup);
2839 goto bail;
2840 }
2841
2842
2843 if (cpu.workAllocation <= 0) {
2844 # ifdef SYNCTEST
2845 allocCount ++;
2846 # endif
2847
2848
2849
2850
2851
2852 int64_t waitTimeout = 100000;
2853
2854
2855 while (1) {
2856 bool alldone = true;
2857 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
2858 if (cpus[i].inMultics && cpus[i].workAllocation > 0) {
2859 wakeCPU (i);
2860 alldone = false;
2861
2862 }
2863 }
2864 if (alldone) {
2865
2866 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
2867 if (cpus[i].inMultics) {
2868 cpus[i].workAllocation += cpu.tweaks.isolts_mode ? 1 : workAllocationQuantum;
2869 wakeCPU (i);
2870 }
2871 }
2872 break;
2873 }
2874 if (waitTimeout-- < 0) {
2875
2876
2877 sim_printf ("Clock master CPU %c timed out\r\n", "ABCDEFGH"[current_running_cpu_idx]);
2878 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
2879 if (cpus[i].inMultics && cpus[i].workAllocation > 0) {
2880 sim_printf ("CPU %c remaining allocation: %ld\r\n", "ABCDEFGH"[i], cpus[i].workAllocation);
2881 }
2882 }
2883 sim_printf ("Conceding clock mastery...\r\n");
2884 cpu.syncClockModeCache = false;
2885 giveupClockMaster (cpup);
2886 goto bail;
2887 }
2888 sim_usleep (1);
2889 }
2890 }
2891
2892
2893
2894 } else {
2895
2896
2897
2898
2899 if (! cpu.isSlave) {
2900
2901 # ifdef SYNCTEST
2902 sim_printf ("CPU%c becoming slave\r\n", cpu.cpuIdx + 'A');
2903 # endif
2904 }
2905 cpu.isSlave = true;
2906
2907
2908 while (syncClockMode && cpu.workAllocation <= 0)
2909 sim_usleep (1);
2910
2911
2912
2913
2914 }
2915
2916 } else {
2917
2918 cpu.syncClockModeCache = false;
2919 if (cpu.isSlave) {
2920
2921 # ifdef SYNCTEST
2922 sim_printf ("CPU%c free; free at last\r\n", cpu.cpuIdx + 'A');
2923 # endif
2924 cpu.isSlave = false;
2925 }
2926 }
2927 }
2928 bail:
2929
2930 #endif
2931
2932 #if defined(THREADZ) || defined(LOCKLESS)
2933 if (LIKELY (! cpu.tweaks.isolts_mode) &&
2934 UNLIKELY (! cpu.inMultics)) {
2935 cpu.inMultics = true;
2936 }
2937 #endif
2938
2939 CPT (cpt1U, 22);
2940
2941 #if defined(LOCKLESS)
2942 if (stall_point_active)
2943 {
2944 for (int i = 0; i < N_STALL_POINTS; i ++)
2945 if (stall_points[i].segno && stall_points[i].segno == cpu.PPR.PSR &&
2946 stall_points[i].offset && stall_points[i].offset == cpu.PPR.IC)
2947 {
2948 # if defined(CTRACE)
2949 (void)fprintf (stderr, "%10lu %s stall %d\r\n", seqno (), cpunstr[current_running_cpu_idx], i);
2950 # endif
2951
2952 sim_usleep(stall_points[i].time);
2953 break;
2954 }
2955 }
2956 #endif
2957
2958
2959
2960
2961 if (GET_I (cpu.cu.IWB))
2962 cpu.wasInhibited = true;
2963
2964 t_stat ret = executeInstruction (cpup);
2965 DO_WORK_EXEC;
2966 CPT (cpt1U, 23);
2967
2968 if (cpu.tweaks.l68_mode)
2969 add_l68_CU_history (cpup);
2970 else
2971 add_dps8m_CU_history (cpup);
2972
2973 if (ret > 0)
2974 {
2975 reason = ret;
2976 break;
2977 }
2978
2979 if (ret == CONT_XEC)
2980 {
2981 CPT (cpt1U, 27);
2982 cpu.wasXfer = false;
2983 cpu.isExec = true;
2984 if (cpu.cu.xdo)
2985 cpu.isXED = true;
2986
2987 cpu.cu.XSF = 0;
2988 cpu.cu.TSN_VALID [0] = 0;
2989 cpu.TPR.TSR = cpu.PPR.PSR;
2990 cpu.TPR.TRR = cpu.PPR.PRR;
2991 break;
2992 }
2993
2994 if (ret == CONT_TRA || ret == CONT_RET)
2995 {
2996 CPT (cpt1U, 24);
2997 cpu.cu.xde = cpu.cu.xdo = 0;
2998 cpu.isExec = false;
2999 cpu.isXED = false;
3000
3001 cpu.wasXfer = true;
3002
3003 if (cpu.cycle != EXEC_cycle)
3004 {
3005 clearFaultCycle (cpup);
3006
3007
3008
3009
3010
3011 if (! (cpu.currentInstruction.opcode == 0715 &&
3012 cpu.currentInstruction.opcodeX == 0))
3013 {
3014 CPT (cpt1U, 9);
3015 SET_I_NBAR;
3016 }
3017
3018 if (!clear_temporary_absolute_mode (cpup))
3019 {
3020
3021 sim_debug (DBG_TRACEEXT, & cpu_dev,
3022 "setting ABS mode\r\n");
3023 CPT (cpt1U, 10);
3024 set_addr_mode (cpup, ABSOLUTE_mode);
3025 }
3026 else
3027 {
3028
3029 sim_debug (DBG_TRACEEXT, & cpu_dev,
3030 "not setting ABS mode\r\n");
3031 }
3032
3033 }
3034
3035
3036 if (TST_I_ABS && cpu.cu.XSF)
3037 {
3038 set_addr_mode (cpup, APPEND_mode);
3039 }
3040
3041 if (ret == CONT_TRA)
3042 {
3043
3044 cpu.wasXfer = false;
3045 set_cpu_cycle (cpup, PSEUDO_FETCH_cycle);
3046 }
3047 else
3048 set_cpu_cycle (cpup, FETCH_cycle);
3049 break;
3050 }
3051
3052 if (ret == CONT_DIS)
3053 {
3054 CPT (cpt1U, 25);
3055
3056 #if defined(THREADZ) || defined(LOCKLESS)
3057
3058 if (cpu.syncClockModeCache) {
3059 break;
3060 }
3061 #endif
3062
3063
3064
3065
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 #if defined(THREADZ) || defined(LOCKLESS)
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108 # if defined(NO_TIMEWAIT)
3109
3110 struct timespec req, rem;
3111 uint ms = sys_opts.sys_poll_interval;
3112 long int nsec = (long int) ms * 1000L * 1000L;
3113 req.tv_nsec = nsec;
3114 req.tv_sec += req.tv_nsec / 1000000000L;
3115 req.tv_nsec %= 1000000000L;
3116 int rc = nanosleep (& req, & rem);
3117
3118 if (rc == -1)
3119 {
3120 ms = (uint) (rem.tv_nsec / 1000 + req.tv_sec * 1000);
3121 }
3122 word27 ticks = ms * 512;
3123 if (cpu.rTR <= ticks)
3124 {
3125 if (cpu.tweaks.tro_enable) {
3126 setG7fault (current_running_cpu_idx, FAULT_TRO);
3127 }
3128 cpu.rTR = (cpu.rTR - ticks) & MASK27;
3129 }
3130 else
3131 cpu.rTR = (cpu.rTR - ticks) & MASK27;
3132
3133 if (cpu.rTR == 0)
3134 cpu.rTR = MASK27;
3135 # else
3136
3137
3138 unsigned long left = (unsigned long) ((uint64) (cpu.rTR) * 125u / 64u);
3139
3140
3141
3142
3143
3144
3145
3146
3147 unsigned long nowLeft = left;
3148 if (!sample_interrupts (cpup))
3149 {
3150 nowLeft = sleepCPU (left);
3151 }
3152 if (nowLeft)
3153 {
3154
3155
3156 if (nowLeft <= left) {
3157 cpu.rTR = (word27) (left * 64 / 125);
3158 }
3159 }
3160 else
3161 {
3162
3163 if (cpu.tweaks.tro_enable)
3164 {
3165 lock_scu ();
3166 setG7fault (current_running_cpu_idx, FAULT_TRO);
3167 unlock_scu ();
3168 }
3169 cpu.rTR = MASK27;
3170 }
3171 # endif
3172 cpu.rTRticks = 0;
3173 break;
3174 #else
3175
3176 sim_usleep (sys_opts.sys_poll_interval * 1000);
3177
3178 # if defined(CONSOLE_FIX)
3179 # if defined(THREADZ) || defined(LOCKLESS)
3180 lock_libuv ();
3181 # endif
3182 # endif
3183 uv_run (ev_poll_loop, UV_RUN_NOWAIT);
3184 # if defined(CONSOLE_FIX)
3185 # if defined(THREADZ) || defined(LOCKLESS)
3186 unlock_libuv ();
3187 # endif
3188 # endif
3189 fast_queue_subsample = 0;
3190
3191 sim_interval = 0;
3192
3193
3194
3195
3196 cpu.rTRticks = 0;
3197
3198
3199
3200
3201
3202
3203 if (cpu.rTR <= sys_opts.sys_poll_interval * 512)
3204 {
3205 if (cpu.tweaks.tro_enable) {
3206 setG7fault (current_running_cpu_idx, FAULT_TRO);
3207 }
3208 cpu.rTR = (cpu.rTR - sys_opts.sys_poll_interval * 512) & MASK27;
3209 }
3210 else
3211 cpu.rTR = (cpu.rTR - sys_opts.sys_poll_interval * 512) & MASK27;
3212 if (cpu.rTR == 0)
3213 cpu.rTR = MASK27;
3214 #endif
3215
3216 break;
3217 }
3218
3219 cpu.wasXfer = false;
3220
3221 if (ret < 0)
3222 {
3223 sim_warn ("executeInstruction returned %d?\r\n", ret);
3224 break;
3225 }
3226
3227 if ((! cpu.cu.repeat_first) &&
3228 (cpu.cu.rpt ||
3229 (cpu.cu.rd && (cpu.PPR.IC & 1)) ||
3230 cpu.cu.rl))
3231 {
3232 CPT (cpt1U, 26);
3233 if (cpu.cu.rd)
3234 -- cpu.PPR.IC;
3235 cpu.wasXfer = false;
3236 set_cpu_cycle (cpup, FETCH_cycle);
3237 break;
3238 }
3239
3240
3241 if (cpu.cycle == FAULT_EXEC_cycle &&
3242 !cpu.cu.xde && cpu.cu.xdo)
3243 {
3244 clear_temporary_absolute_mode (cpup);
3245 cu_safe_restore (cpup);
3246 CPT (cpt1U, 12);
3247 clearFaultCycle (cpup);
3248
3249
3250
3251 cpu.wasXfer = false;
3252 cpu.isExec = false;
3253 cpu.isXED = false;
3254
3255 cpu.PPR.IC += ci->info->ndes;
3256 cpu.PPR.IC ++;
3257
3258 set_cpu_cycle (cpup, FETCH_cycle);
3259 break;
3260 }
3261
3262
3263 if (cpu.cycle == INTERRUPT_EXEC_cycle &&
3264 !cpu.cu.xde && cpu.cu.xdo)
3265 {
3266 clear_temporary_absolute_mode (cpup);
3267 cu_safe_restore (cpup);
3268
3269
3270
3271 CPT (cpt1U, 12);
3272 cpu.wasXfer = false;
3273 cpu.isExec = false;
3274 cpu.isXED = false;
3275
3276 set_cpu_cycle (cpup, FETCH_cycle);
3277 break;
3278 }
3279
3280
3281 if (cpu.cu.xde && cpu.cu.xdo)
3282 {
3283
3284 cpu.cu.IWB = cpu.cu.IRODD;
3285 cpu.cu.xde = 0;
3286 cpu.isExec = true;
3287 cpu.isXED = true;
3288 cpu.cu.XSF = 0;
3289 cpu.cu.TSN_VALID [0] = 0;
3290 cpu.TPR.TSR = cpu.PPR.PSR;
3291 cpu.TPR.TRR = cpu.PPR.PRR;
3292 break;
3293 }
3294
3295 if (cpu.cu.xde || cpu.cu.xdo)
3296 {
3297 cpu.cu.xde = cpu.cu.xdo = 0;
3298 cpu.isExec = false;
3299 cpu.isXED = false;
3300 CPT (cpt1U, 27);
3301 cpu.wasXfer = false;
3302 cpu.PPR.IC ++;
3303 if (ci->info->ndes > 0)
3304 cpu.PPR.IC += ci->info->ndes;
3305 cpu.wasInhibited = true;
3306 set_cpu_cycle (cpup, FETCH_cycle);
3307 break;
3308 }
3309
3310
3311 if (cpu.cycle != EXEC_cycle)
3312 sim_warn ("expected EXEC_cycle (%d)\r\n", cpu.cycle);
3313
3314 cpu.cu.xde = cpu.cu.xdo = 0;
3315 cpu.isExec = false;
3316 cpu.isXED = false;
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327 if ((cpu.PPR.IC & 1) == 0 &&
3328 ci->info->ndes == 0 &&
3329 !cpu.cu.repeat_first && !cpu.cu.rpt && !cpu.cu.rd && !cpu.cu.rl &&
3330 !(cpu.currentInstruction.opcode == 0616 && cpu.currentInstruction.opcodeX == 0) &&
3331 (cpu.PPR.IC & ~3u) != (cpu.last_write & ~3u))
3332 {
3333 cpu.PPR.IC ++;
3334 cpu.wasXfer = false;
3335 cpu.cu.IWB = cpu.cu.IRODD;
3336 set_cpu_cycle (cpup, PSEUDO_FETCH_cycle);
3337 break;
3338 }
3339
3340 cpu.PPR.IC ++;
3341 if (ci->info->ndes > 0)
3342 cpu.PPR.IC += ci->info->ndes;
3343
3344 CPT (cpt1U, 28);
3345 cpu.wasXfer = false;
3346 set_cpu_cycle (cpup, FETCH_cycle);
3347 }
3348 break;
3349
3350 case SYNC_FAULT_RTN_cycle:
3351 {
3352 CPT (cpt1U, 29);
3353
3354
3355
3356
3357 cpu.PPR.IC += ci->info->ndes;
3358 cpu.PPR.IC ++;
3359 cpu.wasXfer = false;
3360 set_cpu_cycle (cpup, FETCH_cycle);
3361 }
3362 break;
3363
3364 case FAULT_cycle:
3365 {
3366 CPT (cpt1U, 30);
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388 if ((cpu.cu.APUCycleBits & 060) || cpu.secret_addressing_mode)
3389 set_apu_status (cpup, apuStatus_FABS);
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401 if (cpu.faultNumber != FAULT_TRB || cpu.cu.xde == 0)
3402 {
3403 cu_safe_store (cpup);
3404 }
3405 else
3406 {
3407 word36 tmpIRODD = cpu.scu_data[7];
3408 cu_safe_store (cpup);
3409 cpu.scu_data[7] = tmpIRODD;
3410 }
3411 CPT (cpt1U, 31);
3412
3413
3414 set_temporary_absolute_mode (cpup);
3415
3416
3417 cpu.PPR.PRR = 0;
3418 cpu.TPR.TRR = 0;
3419
3420
3421 uint fltAddress = (cpu.switches.FLT_BASE << 5) & 07740;
3422 L68_ (
3423 if (cpu.is_FFV)
3424 {
3425 cpu.is_FFV = false;
3426 CPTUR (cptUseMR);
3427
3428 fltAddress = (cpu.MR.FFV & MASK15) << 3;
3429 }
3430 )
3431
3432
3433 word24 addr = fltAddress + 2 * cpu.faultNumber;
3434
3435 if (cpu.restart)
3436 {
3437 cpu.restart = false;
3438 addr = cpu.restart_address;
3439 }
3440
3441 core_read2 (cpup, addr, & cpu.cu.IWB, & cpu.cu.IRODD, __func__);
3442 #if defined(TESTING)
3443 HDBGMRead (addr, cpu.cu.IWB, "fault even");
3444 HDBGMRead (addr + 1, cpu.cu.IRODD, "fault odd");
3445 #endif
3446 cpu.cu.xde = 1;
3447 cpu.cu.xdo = 1;
3448 cpu.isExec = true;
3449 cpu.isXED = true;
3450
3451 CPT (cpt1U, 33);
3452 set_cpu_cycle (cpup, FAULT_EXEC_cycle);
3453
3454 break;
3455 }
3456
3457 }
3458 }
3459 while (reason == 0);
3460
3461 leave:
3462 #if defined(THREADZ) || defined(LOCKLESS)
3463 cpu.executing = false;
3464 cpu.inMultics = false;
3465 #endif
3466 #if defined(TESTING)
3467 HDBGPrint ();
3468 #endif
3469
3470 for (unsigned short n = 0; n < N_CPU_UNITS_MAX; n++)
3471 {
3472 #if !defined(SCHED_NEVER_YIELD)
3473 lockYieldAll = lockYieldAll + (unsigned long long)cpus[n].coreLockState.lockYield;
3474 #endif
3475 lockWaitMaxAll = lockWaitMaxAll + (unsigned long long)cpus[n].coreLockState.lockWaitMax;
3476 lockWaitAll = lockWaitAll + (unsigned long long)cpus[n].coreLockState.lockWait;
3477 lockImmediateAll = lockImmediateAll + (unsigned long long)cpus[n].coreLockState.lockImmediate;
3478 lockCntAll = lockCntAll + (unsigned long long)cpus[n].coreLockState.lockCnt;
3479 instrCntAll = instrCntAll + (unsigned long long)cpus[n].instrCnt;
3480 cycleCntAll = cycleCntAll + (unsigned long long)cpus[n].cycleCnt;
3481 }
3482
3483 (void)fflush(stderr);
3484 (void)fflush(stdout);
3485
3486 # if !defined(PERF_STRIP)
3487 if (cycleCntAll > (unsigned long long)cpu.cycleCnt)
3488 {
3489 # endif
3490 sim_msg ("\r\n");
3491 sim_msg ("\r+---------------------------------+\r\n");
3492 sim_msg ("\r| Aggregate CPU Statistics |\r\n");
3493 sim_msg ("\r+---------------------------------+\r\n");
3494 (void)fflush(stderr);
3495 (void)fflush(stdout);
3496 # if defined(WIN_STDIO)
3497 sim_msg ("\r| cycles %15llu |\r\n", cycleCntAll);
3498 sim_msg ("\r| instructions %15llu |\r\n", instrCntAll);
3499 (void)fflush(stderr);
3500 (void)fflush(stdout);
3501 sim_msg ("\r+---------------------------------+\r\n");
3502 sim_msg ("\r| lockCnt %15llu |\r\n", lockCntAll);
3503 sim_msg ("\r| lockImmediate %15llu |\r\n", lockImmediateAll);
3504 (void)fflush(stderr);
3505 (void)fflush(stdout);
3506 sim_msg ("\r+---------------------------------+\r\n");
3507 sim_msg ("\r| lockWait %15llu |\r\n", lockWaitAll);
3508 sim_msg ("\r| lockWaitMax %15llu |\r\n", lockWaitMaxAll);
3509 (void)fflush(stderr);
3510 (void)fflush(stdout);
3511 # if !defined(SCHED_NEVER_YIELD)
3512 sim_msg ("\r| lockYield %15llu |\r\n", lockYieldAll);
3513 # else
3514 sim_msg ("\r| lockYield ---- |\r\n");
3515 # endif
3516 sim_msg ("\r+---------------------------------+\r\n");
3517 (void)fflush(stderr);
3518 (void)fflush(stdout);
3519 # else
3520 sim_msg ("\r| cycles %'15llu |\r\n", cycleCntAll);
3521 sim_msg ("\r| instructions %'15llu |\r\n", instrCntAll);
3522 (void)fflush(stderr);
3523 (void)fflush(stdout);
3524 sim_msg ("\r+---------------------------------+\r\n");
3525 sim_msg ("\r| lockCnt %'15llu |\r\n", lockCntAll);
3526 sim_msg ("\r| lockImmediate %'15llu |\r\n", lockImmediateAll);
3527 (void)fflush(stderr);
3528 (void)fflush(stdout);
3529 sim_msg ("\r+---------------------------------+\r\n");
3530 sim_msg ("\r| lockWait %'15llu |\r\n", lockWaitAll);
3531 sim_msg ("\r| lockWaitMax %'15llu |\r\n", lockWaitMaxAll);
3532 (void)fflush(stderr);
3533 (void)fflush(stdout);
3534 # if !defined(SCHED_NEVER_YIELD)
3535 sim_msg ("\r| lockYield %'15llu |\r\n", lockYieldAll);
3536 # else
3537 sim_msg ("\r| lockYield ---- |\r\n");
3538 # endif
3539 sim_msg ("\r+---------------------------------+\r\n");
3540 (void)fflush(stderr);
3541 (void)fflush(stdout);
3542 # endif
3543 # if !defined(PERF_STRIP)
3544 }
3545 # else
3546 sim_msg("\r\n");
3547 # endif
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559 #if defined(THREADZ) || defined(LOCKLESS)
3560 if (running_perf_test == false)
3561 sim_usleep(2000000);
3562 stopCPUThread();
3563 #endif
3564
3565 #if defined(M_SHARED)
3566
3567
3568
3569
3570 set_cpu_idx (0);
3571 dummy_IC = cpu.PPR.IC;
3572 #endif
3573
3574 return reason;
3575 }
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591 int operand_size (cpu_state_t * cpup)
3592 {
3593 DCDstruct * i = & cpu.currentInstruction;
3594 if (i->info->flags & (READ_OPERAND | STORE_OPERAND))
3595 return 1;
3596 else if (i->info->flags & (READ_YPAIR | STORE_YPAIR))
3597 return 2;
3598 else if (i->info->flags & (READ_YBLOCK8 | STORE_YBLOCK8))
3599 return 8;
3600 else if (i->info->flags & (READ_YBLOCK16 | STORE_YBLOCK16))
3601 return 16;
3602 else if (i->info->flags & (READ_YBLOCK32 | STORE_YBLOCK32))
3603 return 32;
3604 return 0;
3605 }
3606
3607
3608
3609 void readOperandRead (cpu_state_t * cpup, word18 addr) {
3610 CPT (cpt1L, 6);
3611
3612 #if defined(THREADZ)
3613 DCDstruct * i = & cpu.currentInstruction;
3614 if (RMWOP (i))
3615 lock_rmw ();
3616 #endif
3617
3618 switch (operand_size (cpup)) {
3619 case 1:
3620 CPT (cpt1L, 7);
3621 ReadOperandRead (cpup, addr, & cpu.CY);
3622 break;
3623 case 2:
3624 CPT (cpt1L, 8);
3625 addr &= 0777776;
3626 Read2OperandRead (cpup, addr, cpu.Ypair);
3627 break;
3628 case 8:
3629 CPT (cpt1L, 9);
3630 addr &= 0777770;
3631 Read8 (cpup, addr, cpu.Yblock8, cpu.currentInstruction.b29);
3632 break;
3633 case 16:
3634 CPT (cpt1L, 10);
3635 addr &= 0777770;
3636 Read16 (cpup, addr, cpu.Yblock16);
3637 break;
3638 case 32:
3639 CPT (cpt1L, 11);
3640 addr &= 0777740;
3641 for (uint j = 0 ; j < 32 ; j += 1)
3642 ReadOperandRead (cpup, addr + j, cpu.Yblock32 + j);
3643 break;
3644 }
3645 }
3646
3647 void readOperandRMW (cpu_state_t * cpup, word18 addr) {
3648 CPT (cpt1L, 6);
3649 switch (operand_size (cpup)) {
3650 case 1:
3651 CPT (cpt1L, 7);
3652 ReadOperandRMW (cpup, addr, & cpu.CY);
3653 break;
3654 case 2:
3655 CPT (cpt1L, 8);
3656 addr &= 0777776;
3657 Read2OperandRead (cpup, addr, cpu.Ypair);
3658 break;
3659 case 8:
3660 CPT (cpt1L, 9);
3661 addr &= 0777770;
3662 Read8 (cpup, addr, cpu.Yblock8, cpu.currentInstruction.b29);
3663 break;
3664 case 16:
3665 CPT (cpt1L, 10);
3666 addr &= 0777770;
3667 Read16 (cpup, addr, cpu.Yblock16);
3668 break;
3669 case 32:
3670 CPT (cpt1L, 11);
3671 addr &= 0777740;
3672 for (uint j = 0 ; j < 32 ; j += 1)
3673 ReadOperandRMW (cpup, addr + j, cpu.Yblock32 + j);
3674 break;
3675 }
3676 }
3677
3678
3679
3680 t_stat write_operand (cpu_state_t * cpup, word18 addr, UNUSED processor_cycle_type cyctyp)
3681 {
3682 switch (operand_size (cpup))
3683 {
3684 case 1:
3685 CPT (cpt1L, 12);
3686 WriteOperandStore (cpup, addr, cpu.CY);
3687 break;
3688 case 2:
3689 CPT (cpt1L, 13);
3690 addr &= 0777776;
3691 Write2OperandStore (cpup, addr + 0, cpu.Ypair);
3692 break;
3693 case 8:
3694 CPT (cpt1L, 14);
3695 addr &= 0777770;
3696 Write8 (cpup, addr, cpu.Yblock8, cpu.currentInstruction.b29);
3697 break;
3698 case 16:
3699 CPT (cpt1L, 15);
3700 addr &= 0777770;
3701 Write16 (cpup, addr, cpu.Yblock16);
3702 break;
3703 case 32:
3704 CPT (cpt1L, 16);
3705 addr &= 0777740;
3706
3707
3708 Write32 (cpup, addr, cpu.Yblock32);
3709 break;
3710 }
3711
3712 #if defined(THREADZ)
3713 if (cyctyp == OPERAND_STORE)
3714 {
3715 DCDstruct * i = & cpu.currentInstruction;
3716 if (RMWOP (i))
3717 unlock_mem ();
3718 }
3719 #endif
3720 return SCPE_OK;
3721
3722 }
3723
3724 #if !defined(SPEED)
3725 t_stat set_mem_watch (int32 arg, const char * buf)
3726 {
3727 if (strlen (buf) == 0)
3728 {
3729 if (arg)
3730 {
3731 sim_warn ("no argument to watch?\r\n");
3732 return SCPE_ARG;
3733 }
3734 sim_msg ("Clearing all watch points\r\n");
3735 (void)memset (& watch_bits, 0, sizeof (watch_bits));
3736 return SCPE_OK;
3737 }
3738 char * end;
3739 long int n = strtol (buf, & end, 0);
3740 if (* end || n < 0 || n >= MEMSIZE)
3741 {
3742 sim_warn ("Invalid argument to watch? %ld\r\n", (long) n);
3743 return SCPE_ARG;
3744 }
3745 watch_bits [n] = arg != 0;
3746 return SCPE_OK;
3747 }
3748 #endif
3749
3750
3751
3752
3753
3754 #if !defined(SPEED)
3755 static void nem_check (word24 addr, const char * context)
3756 {
3757 cpu_state_t * cpup = _cpup;
3758 if (lookup_cpu_mem_map (cpup, addr) < 0)
3759 {
3760 doFault (FAULT_STR, fst_str_nea, context);
3761 }
3762 }
3763 #endif
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776 #if !defined(SPEED) || !defined(INLINE_CORE)
3777 int core_read (cpu_state_t * cpup, word24 addr, word36 *data, const char * ctx)
3778 {
3779 PNL (cpu.portBusy = true;)
3780 SC_MAP_ADDR (addr, addr);
3781 # if !defined(LOCKLESS)
3782 if (M[addr] & MEM_UNINITIALIZED)
3783 {
3784 sim_debug (DBG_WARN, & cpu_dev,
3785 "Uninitialized memory accessed at address %08o; "
3786 "IC is 0%06o:0%06o (%s(\r\n",
3787 addr, cpu.PPR.PSR, cpu.PPR.IC, ctx);
3788 }
3789 # endif
3790 # if !defined(SPEED)
3791 if (watch_bits [addr])
3792 {
3793 sim_msg ("WATCH [%llu] %05o:%06o read %08o %012llo (%s)\r\n",
3794 (long long unsigned int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC, addr,
3795 (long long unsigned int)M [addr], ctx);
3796 traceInstruction (0);
3797 }
3798 # endif
3799 # if defined(LOCKLESS)
3800 # if !defined(SUNLINT)
3801 word36 v;
3802 LOAD_ACQ_CORE_WORD(v, addr);
3803 *data = v & DMASK;
3804 # endif
3805 # else
3806 *data = M[addr] & DMASK;
3807 # endif
3808
3809 DO_WORK_MEM;
3810 sim_debug (DBG_CORE, & cpu_dev,
3811 "core_read %08o %012"PRIo64" (%s)\r\n",
3812 addr, * data, ctx);
3813 PNL (trackport (addr, * data));
3814 return 0;
3815 }
3816 #endif
3817
3818 #if defined(LOCKLESS)
3819 int core_read_lock (cpu_state_t * cpup, word24 addr, word36 *data, UNUSED const char * ctx)
3820 {
3821 SC_MAP_ADDR (addr, addr);
3822 LOCK_CORE_WORD(addr, & cpu.coreLockState);
3823 if (cpu.coreLockState.locked_addr != 0) {
3824 sim_warn ("core_read_lock: locked %08o locked_addr %08o %c %05o:%06o\r\n",
3825 addr, cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
3826 cpu.PPR.PSR, cpu.PPR.IC);
3827 core_unlock_all (cpup);
3828 }
3829 cpu.coreLockState.locked_addr = addr;
3830 # if !defined(SUNLINT)
3831 word36 v;
3832 LOAD_ACQ_CORE_WORD(v, addr);
3833 * data = v & DMASK;
3834 # endif
3835 return 0;
3836 }
3837 #endif
3838
3839 #if !defined(SPEED) || !defined(INLINE_CORE)
3840 int core_write (cpu_state_t * cpup, word24 addr, word36 data, const char * ctx)
3841 {
3842 PNL (cpu.portBusy = true;)
3843 SC_MAP_ADDR (addr, addr);
3844 if (cpu.tweaks.isolts_mode)
3845 {
3846 if (cpu.MR.sdpap)
3847 {
3848 sim_warn ("failing to implement sdpap\r\n");
3849 cpu.MR.sdpap = 0;
3850 }
3851 if (cpu.MR.separ)
3852 {
3853 sim_warn ("failing to implement separ\r\n");
3854 cpu.MR.separ = 0;
3855 }
3856 }
3857 # if defined(LOCKLESS)
3858 LOCK_CORE_WORD(addr, & cpu.coreLockState);
3859 # if !defined(SUNLINT)
3860 STORE_REL_CORE_WORD(addr, data);
3861 # endif
3862 # else
3863 M[addr] = data & DMASK;
3864 # endif
3865 # if !defined(SPEED)
3866 if (watch_bits [addr])
3867 {
3868 sim_msg ("WATCH [%llu] %05o:%06o write %08llo %012llo (%s)\r\n",
3869 (long long unsigned int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
3870 (long long unsigned int)addr, (unsigned long long int)M [addr], ctx);
3871 traceInstruction (0);
3872 }
3873 # endif
3874 DO_WORK_MEM;
3875 sim_debug (DBG_CORE, & cpu_dev,
3876 "core_write %08o %012"PRIo64" (%s)\r\n",
3877 addr, data, ctx);
3878 PNL (trackport (addr, data));
3879 return 0;
3880 }
3881 #endif
3882
3883 #if defined(LOCKLESS)
3884 int core_write_unlock (cpu_state_t * cpup, word24 addr, word36 data, UNUSED const char * ctx)
3885 {
3886 SC_MAP_ADDR (addr, addr);
3887 if (cpu.coreLockState.locked_addr != addr)
3888 {
3889 sim_warn ("core_write_unlock: locked %08o locked_addr %08o %c %05o:%06o\r\n",
3890 addr, cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
3891 cpu.PPR.PSR, cpu.PPR.IC);
3892 core_unlock_all (cpup);
3893 }
3894
3895 # if !defined(SUNLINT)
3896 STORE_REL_CORE_WORD(addr, data);
3897 # endif
3898 cpu.coreLockState.locked_addr = 0;
3899 return 0;
3900 }
3901
3902 int core_unlock_all (cpu_state_t * cpup)
3903 {
3904 if (cpu.coreLockState.locked_addr != 0) {
3905 sim_warn ("core_unlock_all: locked %08o %c %05o:%06o\r\n",
3906 cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
3907 cpu.PPR.PSR, cpu.PPR.IC);
3908 # if !defined(SUNLINT)
3909 STORE_REL_CORE_WORD(cpu.coreLockState.locked_addr, M[cpu.coreLockState.locked_addr]);
3910 # endif
3911 cpu.coreLockState.locked_addr = 0;
3912 }
3913 return 0;
3914 }
3915 #endif
3916
3917 #if !defined(SPEED) || !defined(INLINE_CORE)
3918 int core_write_zone (cpu_state_t * cpup, word24 addr, word36 data, const char * ctx)
3919 {
3920 PNL (cpu.portBusy = true;)
3921 if (cpu.tweaks.isolts_mode)
3922 {
3923 if (cpu.MR.sdpap)
3924 {
3925 sim_warn ("failing to implement sdpap\r\n");
3926 cpu.MR.sdpap = 0;
3927 }
3928 if (cpu.MR.separ)
3929 {
3930 sim_warn ("failing to implement separ\r\n");
3931 cpu.MR.separ = 0;
3932 }
3933 }
3934 word24 mapAddr = 0;
3935 SC_MAP_ADDR (addr, mapAddr);
3936 # if defined(LOCKLESS)
3937 word36 v;
3938 core_read_lock(cpup, addr, &v, ctx);
3939 v = (v & ~cpu.zone) | (data & cpu.zone);
3940 core_write_unlock(cpup, addr, v, ctx);
3941 # else
3942 M[mapAddr] = (M[mapAddr] & ~cpu.zone) | (data & cpu.zone);
3943 # endif
3944 cpu.useZone = false;
3945 # if !defined(SPEED)
3946 if (watch_bits [mapAddr])
3947 {
3948 sim_msg ("WATCH [%llu] %05o:%06o writez %08llo %012llo (%s)\r\n",
3949 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
3950 (unsigned long long int)mapAddr, (unsigned long long int)M [mapAddr], ctx);
3951 traceInstruction (0);
3952 }
3953 # endif
3954 DO_WORK_MEM;
3955 sim_debug (DBG_CORE, & cpu_dev,
3956 "core_write_zone %08o %012"PRIo64" (%s)\r\n",
3957 mapAddr, data, ctx);
3958 PNL (trackport (mapAddr, data));
3959 return 0;
3960 }
3961 #endif
3962
3963 #if !defined(SPEED) || !defined(INLINE_CORE)
3964 int core_read2 (cpu_state_t * cpup, word24 addr, word36 *even, word36 *odd, const char * ctx)
3965 {
3966 PNL (cpu.portBusy = true;)
3967 # if defined(LOCKLESS)
3968
3969 word36 v;
3970 # endif
3971 if (addr & 1)
3972 {
3973 sim_debug (DBG_MSG, & cpu_dev,
3974 "warning: subtracting 1 from pair at %o in "
3975 "core_read2 (%s)\r\n", addr, ctx);
3976 addr &= (word24)~1;
3977 }
3978 SC_MAP_ADDR (addr, addr);
3979 # if !defined(LOCKLESS)
3980 if (M[addr] & MEM_UNINITIALIZED)
3981 {
3982 sim_debug (DBG_WARN, & cpu_dev,
3983 "Uninitialized memory accessed at address %08o; "
3984 "IC is 0%06o:0%06o (%s)\r\n",
3985 addr, cpu.PPR.PSR, cpu.PPR.IC, ctx);
3986 }
3987 # endif
3988 # if !defined(SPEED)
3989 if (watch_bits [addr])
3990 {
3991 sim_msg ("WATCH [%llu] %05o:%06o read2 %08llo %012llo (%s)\r\n",
3992 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
3993 (unsigned long long int)addr, (unsigned long long int)M [addr], ctx);
3994 traceInstruction (0);
3995 }
3996 # endif
3997 # if defined(LOCKLESS)
3998 # if !defined(SUNLINT)
3999 LOAD_ACQ_CORE_WORD(v, addr);
4000 if (v & MEM_LOCKED)
4001 sim_warn ("core_read2: even locked %08o locked_addr %08o %c %05o:%06o\r\n",
4002 addr, cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
4003 cpu.PPR.PSR, cpu.PPR.IC);
4004 *even = v & DMASK;
4005 addr++;
4006 # endif
4007 # else
4008 *even = M[addr++] & DMASK;
4009 # endif
4010 sim_debug (DBG_CORE, & cpu_dev,
4011 "core_read2 %08o %012"PRIo64" (%s)\r\n",
4012 addr - 1, * even, ctx);
4013
4014
4015
4016 # if !defined(LOCKLESS)
4017 if (M[addr] & MEM_UNINITIALIZED)
4018 {
4019 sim_debug (DBG_WARN, & cpu_dev,
4020 "Uninitialized memory accessed at address %08o; "
4021 "IC is 0%06o:0%06o (%s)\r\n",
4022 addr, cpu.PPR.PSR, cpu.PPR.IC, ctx);
4023 }
4024 # endif
4025 # if !defined(SPEED)
4026 if (watch_bits [addr])
4027 {
4028 sim_msg ("WATCH [%llu] %05o:%06o read2 %08llo %012llo (%s)\r\n",
4029 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
4030 (unsigned long long int)addr, (unsigned long long int)M [addr], ctx);
4031 traceInstruction (0);
4032 }
4033 # endif
4034 # if defined(LOCKLESS)
4035 # if !defined(SUNLINT)
4036 LOAD_ACQ_CORE_WORD(v, addr);
4037 if (v & MEM_LOCKED)
4038 sim_warn ("core_read2: odd locked %08o locked_addr %08o %c %05o:%06o\r\n",
4039 addr, cpu.coreLockState.locked_addr, current_running_cpu_idx + 'A',
4040 cpu.PPR.PSR, cpu.PPR.IC);
4041 *odd = v & DMASK;
4042 # endif
4043 # else
4044 *odd = M[addr] & DMASK;
4045 # endif
4046 sim_debug (DBG_CORE, & cpu_dev,
4047 "core_read2 %08o %012"PRIo64" (%s)\r\n",
4048 addr, * odd, ctx);
4049 DO_WORK_MEM;
4050 PNL (trackport (addr - 1, * even));
4051 return 0;
4052 }
4053 #endif
4054
4055 #if !defined(SPEED) || !defined(INLINE_CORE)
4056 int core_write2 (cpu_state_t * cpup, word24 addr, word36 even, word36 odd, const char * ctx) {
4057 PNL (cpu.portBusy = true;)
4058 if (addr & 1) {
4059 sim_debug (DBG_MSG, & cpu_dev,
4060 "warning: subtracting 1 from pair at %o in core_write2 " "(%s)\r\n",
4061 addr, ctx);
4062 addr &= (word24)~1;
4063 }
4064 SC_MAP_ADDR (addr, addr);
4065 if (cpu.tweaks.isolts_mode) {
4066 if (cpu.MR.sdpap) {
4067 sim_warn ("failing to implement sdpap\r\n");
4068 cpu.MR.sdpap = 0;
4069 }
4070 if (cpu.MR.separ) {
4071 sim_warn ("failing to implement separ\r\n");
4072 cpu.MR.separ = 0;
4073 }
4074 }
4075
4076 # if !defined(SPEED)
4077 if (watch_bits [addr]) {
4078 sim_msg ("WATCH [%llu] %05o:%06o write2 %08llo %012llo (%s)\r\n",
4079 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
4080 (unsigned long long int)addr, (unsigned long long int)even, ctx);
4081 traceInstruction (0);
4082 }
4083 # endif
4084 # if defined(LOCKLESS)
4085 LOCK_CORE_WORD(addr, & cpu.coreLockState);
4086 # if !defined(SUNLINT)
4087 STORE_REL_CORE_WORD(addr, even);
4088 # endif
4089 addr++;
4090 # else
4091 M[addr++] = even & DMASK;
4092 # endif
4093 sim_debug (DBG_CORE, & cpu_dev, "core_write2 %08o %012llo (%s)\r\n", addr - 1,
4094 (long long unsigned int)even, ctx);
4095
4096
4097
4098
4099 # if !defined(SPEED)
4100 if (watch_bits [addr]) {
4101 sim_msg ("WATCH [%llu] %05o:%06o write2 %08llo %012llo (%s)\r\n",
4102 (long long unsigned int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
4103 (long long unsigned int)addr, (long long unsigned int)odd, ctx);
4104 traceInstruction (0);
4105 }
4106 # endif
4107 # if defined(LOCKLESS)
4108 LOCK_CORE_WORD(addr, & cpu.coreLockState);
4109 # if !defined(SUNLINT)
4110 STORE_REL_CORE_WORD(addr, odd);
4111 # endif
4112 # else
4113 M[addr] = odd & DMASK;
4114 # endif
4115 DO_WORK_MEM;
4116 PNL (trackport (addr - 1, even));
4117 sim_debug (DBG_CORE, & cpu_dev, "core_write2 %08o %012"PRIo64" (%s)\r\n", addr, odd, ctx);
4118 return 0;
4119 }
4120 #endif
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131 void decode_instruction (cpu_state_t * cpup, word36 inst, DCDstruct * p)
4132 {
4133 CPT (cpt1L, 17);
4134 (void)memset (p, 0, sizeof (DCDstruct));
4135
4136 p->opcode = GET_OP (inst);
4137 p->opcodeX = GET_OPX(inst);
4138 p->opcode10 = p->opcode | (p->opcodeX ? 01000 : 0);
4139 p->address = GET_ADDR (inst);
4140 p->b29 = GET_A (inst);
4141 p->i = GET_I (inst);
4142 p->tag = GET_TAG (inst);
4143
4144 p->info = get_iwb_info (p);
4145
4146 if (p->info->flags & IGN_B29)
4147 p->b29 = 0;
4148
4149 if (p->info->ndes > 0)
4150 {
4151 p->b29 = 0;
4152 p->tag = 0;
4153 if (p->info->ndes > 1)
4154 {
4155 (void)memset (& cpu.currentEISinstruction, 0,
4156 sizeof (cpu.currentEISinstruction));
4157 }
4158 }
4159 }
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180 int is_priv_mode (cpu_state_t * cpup)
4181 {
4182
4183
4184
4185 if (get_bar_mode (cpup))
4186 return 0;
4187
4188
4189 if (get_addr_mode (cpup) == ABSOLUTE_mode)
4190 return 1;
4191 else if (cpu.PPR.P)
4192 return 1;
4193
4194 return 0;
4195 }
4196
4197
4198
4199
4200
4201
4202
4203
4204 bool get_bar_mode (cpu_state_t * cpup)
4205 {
4206 return ! (cpu.secret_addressing_mode || TST_I_NBAR);
4207 }
4208
4209 addr_modes_e get_addr_mode (cpu_state_t * cpup)
4210 {
4211 if (cpu.secret_addressing_mode)
4212 return ABSOLUTE_mode;
4213
4214
4215
4216
4217
4218
4219
4220 if (TST_I_ABS)
4221 {
4222 return ABSOLUTE_mode;
4223 }
4224 else
4225 {
4226 return APPEND_mode;
4227 }
4228 }
4229
4230
4231
4232
4233
4234
4235
4236
4237 void set_addr_mode (cpu_state_t * cpup, addr_modes_e mode)
4238 {
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249 cpu.secret_addressing_mode = false;
4250 if (mode == ABSOLUTE_mode)
4251 {
4252 CPT (cpt1L, 22);
4253 sim_debug (DBG_DEBUG, & cpu_dev, "APU: Setting absolute mode.\r\n");
4254
4255 SET_I_ABS;
4256 cpu.PPR.P = 1;
4257 }
4258 else if (mode == APPEND_mode)
4259 {
4260 CPT (cpt1L, 23);
4261 if (! TST_I_ABS && TST_I_NBAR)
4262 sim_debug (DBG_DEBUG, & cpu_dev, "APU: Keeping append mode.\r\n");
4263 else
4264 sim_debug (DBG_DEBUG, & cpu_dev, "APU: Setting append mode.\r\n");
4265
4266 CLR_I_ABS;
4267 }
4268 else
4269 {
4270 sim_debug (DBG_ERR, & cpu_dev,
4271 "APU: Unable to determine address mode.\r\n");
4272 sim_warn ("APU: Unable to determine address mode. Can't happen!\r\n");
4273 }
4274 }
4275
4276
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 word18 get_BAR_address (cpu_state_t * cpup, word18 addr)
4303 {
4304 if (cpu . BAR.BOUND == 0)
4305
4306 doFault (FAULT_STR, fst_str_oob, "BAR store fault; out of bounds");
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317 if (addr >= (((word18) cpu . BAR.BOUND) << 9))
4318
4319 doFault (FAULT_STR, fst_str_oob, "BAR store fault; out of bounds");
4320
4321 word18 barAddr = (addr + (((word18) cpu . BAR.BASE) << 9)) & 0777777;
4322 return barAddr;
4323 }
4324
4325
4326
4327 static void add_history (cpu_state_t * cpup, uint hset, word36 w0, word36 w1)
4328 {
4329
4330 {
4331 cpu.history [hset] [cpu.history_cyclic[hset]] [0] = w0;
4332 cpu.history [hset] [cpu.history_cyclic[hset]] [1] = w1;
4333 cpu.history_cyclic[hset] = (cpu.history_cyclic[hset] + 1) % N_MODEL_HIST_SIZE;
4334 }
4335 }
4336
4337 void add_history_force (cpu_state_t * cpup, uint hset, word36 w0, word36 w1)
4338 {
4339 cpu.history [hset] [cpu.history_cyclic[hset]] [0] = w0;
4340 cpu.history [hset] [cpu.history_cyclic[hset]] [1] = w1;
4341 cpu.history_cyclic[hset] = (cpu.history_cyclic[hset] + 1) % N_MODEL_HIST_SIZE;
4342 }
4343
4344 void add_dps8m_CU_history (cpu_state_t * cpup)
4345 {
4346 if (cpu.skip_cu_hist)
4347 return;
4348 if (! cpu.MR_cache.emr)
4349 return;
4350 if (! cpu.MR_cache.ihr)
4351 return;
4352 if (cpu.MR_cache.hrxfr && ! cpu.wasXfer)
4353 return;
4354
4355 word36 flags = 0;
4356 word5 proccmd = 0;
4357 word7 flags2 = 0;
4358 word36 w0 = 0, w1 = 0;
4359 w0 |= flags & 0777777000000;
4360 w0 |= IWB_IRODD & MASK18;
4361 w1 |= ((word36)(cpu.iefpFinalAddress & MASK24) << 12);
4362 w1 |= (proccmd & MASK5) << 7;
4363 w1 |= flags2 & 0176;
4364 add_history (cpup, CU_HIST_REG, w0, w1);
4365 }
4366
4367 #if !defined(QUIET_UNUSED)
4368 void add_dps8m_DU_OU_history (cpu_state_t * cpup, word36 flags, word18 ICT, word9 RS_REG, word9 flags2)
4369 {
4370 word36 w0 = flags, w1 = 0;
4371 w1 |= (ICT & MASK18) << 18;
4372 w1 |= (RS_REG & MASK9) << 9;
4373 w1 |= flags2 & MASK9;
4374 add_history (cpup, DPS8M_DU_OU_HIST_REG, w0, w1);
4375 }
4376
4377 void add_dps8m_APU_history (cpu_state_t * cpup, word15 ESN, word21 flags, word24 RMA, word3 RTRR, word9 flags2)
4378 {
4379 word36 w0 = 0, w1 = 0;
4380 w0 |= (ESN & MASK15) << 21;
4381 w0 |= flags & MASK21;
4382 w1 |= (RMA & MASK24) << 12;
4383 w1 |= (RTRR & MASK3) << 9;
4384 w1 |= flags2 & MASK9;
4385 add_history (cpu.tweaks.l68_mode ? L68_APU_HIST_REG : DPS8M_APU_HIST_REG, w0, w1);
4386 }
4387
4388 void add_dps8m_EAPU_history (word18 ZCA, word18 opcode)
4389 {
4390 word36 w0 = 0;
4391 w0 |= (ZCA & MASK18) << 18;
4392 w0 |= opcode & MASK18;
4393 add_history (DPS8M_EAPU_HIST_REG, w0, 0);
4394
4395
4396
4397
4398 }
4399 #endif
4400
4401
4402
4403
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 void add_l68_CU_history (cpu_state_t * cpup)
4436 {
4437 CPT (cpt1L, 24);
4438
4439 if (cpu.skip_cu_hist)
4440 return;
4441 if (! cpu.MR_cache.emr)
4442 return;
4443 if (! cpu.MR_cache.ihr)
4444 return;
4445
4446 word36 w0 = 0, w1 = 0;
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456 PNL (putbits36_8 (& w0, 0, cpu.prepare_state);)
4457
4458 putbits36_1 (& w0, 8, cpu.wasXfer);
4459
4460 putbits36_1 (& w0, 9, cpu.cu.xde);
4461
4462 putbits36_1 (& w0, 10, cpu.cu.xdo);
4463
4464 putbits36_1 (& w0, 11, USE_IRODD?1:0);
4465
4466 putbits36_1 (& w0, 12, cpu.cu.rpt);
4467
4468
4469 PNL (putbits36_1 (& w0, 14, cpu.AR_F_E);)
4470
4471 putbits36_1 (& w0, 15, cpu.cycle != INTERRUPT_cycle?1:0);
4472
4473 putbits36_1 (& w0, 16, cpu.cycle != FAULT_cycle?1:0);
4474
4475 putbits36_1 (& w0, 17, TSTF (cpu.cu.IR, I_NBAR)?1:0);
4476
4477 putbits36_18 (& w0, 18, (word18) (IWB_IRODD & MASK18));
4478
4479
4480 putbits36_18 (& w1, 0, cpu.TPR.CA);
4481
4482
4483 PNL (putbits36_1 (& w1, 59-36, (cpu.portSelect == 0)?1:0);)
4484 PNL (putbits36_1 (& w1, 60-36, (cpu.portSelect == 1)?1:0);)
4485 PNL (putbits36_1 (& w1, 61-36, (cpu.portSelect == 2)?1:0);)
4486 PNL (putbits36_1 (& w1, 62-36, (cpu.portSelect == 3)?1:0);)
4487
4488 putbits36_1 (& w1, 63-36, cpu.interrupt_flag?1:0);
4489
4490 PNL (putbits36_1 (& w1, 64-36, cpu.INS_FETCH?1:0);)
4491
4492
4493
4494
4495
4496
4497
4498
4499 add_history (cpup, CU_HIST_REG, w0, w1);
4500
4501
4502 CPTUR (cptUseMR);
4503 if (cpu.MR.hrhlt && cpu.history_cyclic[CU_HIST_REG] == 0)
4504 {
4505
4506 if (cpu.MR.ihrrs)
4507 {
4508 cpu.MR.ihr = 0;
4509 }
4510 set_FFV_fault (cpup, 4);
4511 return;
4512 }
4513 }
4514
4515
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 void add_l68_DU_history (cpu_state_t * cpup)
4554 {
4555 CPT (cpt1L, 25);
4556 PNL (add_history (cpup, L68_DU_HIST_REG, cpu.du.cycle1, cpu.du.cycle2);)
4557 }
4558
4559 void add_l68_OU_history (cpu_state_t * cpup)
4560 {
4561 CPT (cpt1L, 26);
4562 word36 w0 = 0, w1 = 0;
4563
4564
4565
4566 PNL (putbits36_9 (& w0, 0, cpu.ou.RS);)
4567
4568
4569 putbits36_1 (& w0, 9, cpu.ou.characterOperandSize ? 1 : 0);
4570
4571
4572 putbits36_3 (& w0, 10, cpu.ou.characterOperandOffset);
4573
4574
4575 putbits36_1 (& w0, 13, cpu.ou.crflag);
4576
4577
4578 putbits36_1 (& w0, 14, cpu.ou.directOperandFlag ? 1 : 0);
4579
4580
4581 putbits36_2 (& w0, 15, cpu.ou.eac);
4582
4583
4584
4585 PNL (putbits36_9 (& w0, 18, cpu.ou.RS);)
4586
4587
4588 putbits36_1 (& w0, 27, cpu.ou.RB1_FULL);
4589
4590
4591 putbits36_1 (& w0, 28, cpu.ou.RP_FULL);
4592
4593
4594 putbits36_1 (& w0, 29, cpu.ou.RS_FULL);
4595
4596
4597 putbits36_6 (& w0, 30, (word6) (cpu.ou.cycle >> 3));
4598
4599
4600 putbits36_3 (& w1, 36-36, (word3) cpu.ou.cycle);
4601
4602
4603 putbits36_1 (& w1, 39-36, cpu.ou.STR_OP);
4604
4605
4606
4607
4608 PNL (putbits36_10 (& w1, 41-36,
4609 (word10) ~opcodes10 [cpu.ou.RS].reg_use);)
4610
4611
4612
4613
4614 putbits36_18 (& w1, 54 - 36, cpu.PPR.IC);
4615
4616 add_history (cpup, L68_OU_HIST_REG, w0, w1);
4617 }
4618
4619
4620
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 void add_l68_APU_history (cpu_state_t * cpup, enum APUH_e op)
4669 {
4670 CPT (cpt1L, 28);
4671 word36 w0 = 0, w1 = 0;
4672
4673 w0 = op;
4674
4675
4676 putbits36_15 (& w0, 0, cpu.TPR.TSR);
4677
4678 PNL (putbits36_1 (& w0, 15, (cpu.apu.state & apu_ESN_SNR) ? 1 : 0);)
4679 PNL (putbits36_1 (& w0, 16, (cpu.apu.state & apu_ESN_TSR) ? 1 : 0);)
4680
4681 putbits36_1 (& w0, 25, cpu.cu.SDWAMM);
4682
4683 putbits36_4 (& w0, 26, (word4) cpu.SDWAMR);
4684
4685 putbits36_1 (& w0, 30, cpu.cu.PTWAMM);
4686
4687 putbits36_4 (& w0, 31, (word4) cpu.PTWAMR);
4688
4689 PNL (putbits36_1 (& w0, 35, (cpu.apu.state & apu_FLT) ? 1 : 0);)
4690
4691
4692 PNL (putbits36_24 (& w1, 0, cpu.APUMemAddr);)
4693
4694 putbits36_3 (& w1, 24, cpu.TPR.TRR);
4695
4696
4697 putbits36_1 (& w1, 34, cpu.SDW0.C);
4698
4699
4700 add_history (cpup, L68_APU_HIST_REG, w0, w1);
4701 }
4702
4703 #if defined(THREADZ) || defined(LOCKLESS)
4704
4705
4706 static const char * get_dbg_verb (uint32 dbits, DEVICE * dptr)
4707 {
4708 static const char * debtab_none = "DEBTAB_ISNULL";
4709 static const char * debtab_nomatch = "DEBTAB_NOMATCH";
4710 const char * some_match = NULL;
4711 int32 offset = 0;
4712
4713 if (dptr->debflags == 0)
4714 return debtab_none;
4715
4716 dbits &= dptr->dctrl;
4717
4718
4719 while ((offset < 32) && dptr->debflags[offset].name)
4720 {
4721 if (dptr->debflags[offset].mask == dbits)
4722 return dptr->debflags[offset].name;
4723 if (dptr->debflags[offset].mask & dbits)
4724 some_match = dptr->debflags[offset].name;
4725 offset ++;
4726 }
4727 return some_match ? some_match : debtab_nomatch;
4728 }
4729
4730 void dps8_sim_debug (uint32 dbits, DEVICE * dptr, unsigned long long cnt, const char* fmt, ...)
4731 {
4732
4733 if (sim_deb && dptr && (dptr->dctrl & dbits))
4734 {
4735 const char * debug_type = get_dbg_verb (dbits, dptr);
4736 char stackbuf[STACKBUFSIZE];
4737 int32 bufsize = sizeof (stackbuf);
4738 char * buf = stackbuf;
4739 va_list arglist;
4740 int32 i, j, len;
4741 struct timespec t;
4742 clock_gettime(CLOCK_REALTIME, &t);
4743
4744 buf [bufsize-1] = '\0';
4745
4746 while (1)
4747 {
4748 va_start (arglist, fmt);
4749 len = vsnprintf (buf, (int)((unsigned long)(bufsize)-1), fmt, arglist);
4750 va_end (arglist);
4751
4752
4753
4754 if ((len < 0) || (len >= bufsize-1))
4755 {
4756 if (buf != stackbuf)
4757 FREE (buf);
4758 if (bufsize >= (INT_MAX / 2))
4759 return;
4760 bufsize = bufsize * 2;
4761 if (bufsize < len + 2)
4762 bufsize = len + 2;
4763 buf = (char *) malloc ((unsigned long) bufsize);
4764 if (buf == NULL)
4765 return;
4766 buf[bufsize-1] = '\0';
4767 continue;
4768 }
4769 break;
4770 }
4771
4772
4773
4774 for (i = j = 0; i < len; ++i)
4775 {
4776 if ('\n' == buf[i])
4777 {
4778 if (i >= j)
4779 {
4780 if ((i != j) || (i == 0))
4781 {
4782 (void)fprintf (sim_deb, "%lld.%06ld: DBG(%lld) %o: %s %s %.*s\r\n",
4783 (long long)t.tv_sec, t.tv_nsec/1000, cnt,
4784 current_running_cpu_idx, dptr->name, debug_type, i-j, &buf[j]);
4785 }
4786 }
4787 j = i + 1;
4788 }
4789 }
4790
4791
4792 if (buf != stackbuf)
4793 FREE (buf);
4794 }
4795
4796 }
4797 #endif
4798
4799 void setupPROM (uint cpuNo, unsigned char * PROM) {
4800
4801
4802
4803
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 word36 rsw2 = 0;
4840
4841
4842
4843
4844
4845
4846
4847 putbits36_4 (& rsw2, 0, 0);
4848
4849 putbits36_2 (& rsw2, 4, 001);
4850
4851 putbits36_7 (& rsw2, 6, 2);
4852
4853 putbits36_1 (& rsw2, 13, 1);
4854
4855 putbits36_5 (& rsw2, 14, 0);
4856
4857 putbits36_1 (& rsw2, 19, 1);
4858
4859 putbits36_1 (& rsw2, 20, cpus[cpuNo].options.cache_installed ? 1 : 0);
4860
4861 putbits36_2 (& rsw2, 21, 0);
4862
4863 putbits36_1 (& rsw2, 23, 1);
4864
4865 putbits36_1 (& rsw2, 24, 0);
4866
4867 putbits36_4 (& rsw2, 25, 0);
4868
4869 putbits36_4 (& rsw2, 29, cpus[cpuNo].options.proc_speed & 017LL);
4870
4871 putbits36_3 (& rsw2, 33, cpus[cpuNo].switches.cpu_num & 07LL);
4872
4873 word4 rsw2Ext = 0;
4874 if (cpus[cpuNo].options.hex_mode_installed)
4875 rsw2Ext |= 010;
4876 if (cpus[cpuNo].options.clock_slave_installed)
4877 rsw2Ext |= 004;
4878
4879
4880 char serial[12];
4881 (void)sprintf (serial, "%-11u", cpus[cpuNo].switches.serno);
4882
4883 #if defined(VER_H_PROM_SHIP)
4884 char * ship = VER_H_PROM_SHIP;
4885 #else
4886 char * ship = "200101";
4887 #endif
4888
4889 #if !defined(VER_H_PROM_MAJOR_VER)
4890 # define VER_H_PROM_MAJOR_VER "999"
4891 #endif
4892
4893 #if !defined(VER_H_PROM_MINOR_VER)
4894 # define VER_H_PROM_MINOR_VER "999"
4895 #endif
4896
4897 #if !defined(VER_H_PROM_PATCH_VER)
4898 # define VER_H_PROM_PATCH_VER "999"
4899 #endif
4900
4901 #if !defined(VER_H_PROM_OTHER_VER)
4902 # define VER_H_PROM_OTHER_VER "999"
4903 #endif
4904
4905 #if !defined(VER_H_GIT_RELT)
4906 # define VER_H_GIT_RELT "X"
4907 #endif
4908
4909 #if !defined(VER_H_PROM_VER_TEXT)
4910 # define VER_H_PROM_VER_TEXT "Unknown "
4911 #endif
4912
4913 #if defined(BUILD_PROM_OSA_TEXT)
4914 # define BURN_PROM_OSA_TEXT BUILD_PROM_OSA_TEXT
4915 #else
4916 # if !defined(VER_H_PROM_OSA_TEXT)
4917 # define BURN_PROM_OSA_TEXT "Unknown Build Op Sys"
4918 # else
4919 # define BURN_PROM_OSA_TEXT VER_H_PROM_OSA_TEXT
4920 # endif
4921 #endif
4922
4923 #if defined(BUILD_PROM_OSV_TEXT)
4924 # define BURN_PROM_OSV_TEXT BUILD_PROM_OSV_TEXT
4925 #else
4926 # if !defined(VER_H_PROM_OSV_TEXT)
4927 # define BURN_PROM_OSV_TEXT "Unknown Build Arch. "
4928 # else
4929 # define BURN_PROM_OSV_TEXT VER_H_PROM_OSV_TEXT
4930 # endif
4931 #endif
4932
4933 #if defined(BUILD_PROM_TSA_TEXT)
4934 # define BURN_PROM_TSA_TEXT BUILD_PROM_TSA_TEXT
4935 #else
4936 # if defined(_M_X64) || defined(_M_AMD64) || defined(__amd64__) || defined(__x86_64__) || defined(__AMD64)
4937 # define VER_H_PROM_TSA_TEXT "Intel x86_64 (AMD64)"
4938 # elif defined(_M_IX86) || defined(__i386) || defined(__i486) || defined(__i586) || defined(__i686) || defined(__ix86)
4939 # define VER_H_PROM_TSA_TEXT "Intel ix86 (32-bit) "
4940 # elif defined(_M_ARM64) || defined(__aarch64__) || defined(__arm64__)
4941 # define VER_H_PROM_TSA_TEXT "AArch64/ARM64/64-bit"
4942 # elif defined(_M_ARM) || defined(__arm__)
4943 # define VER_H_PROM_TSA_TEXT "AArch32/ARM32/32-bit"
4944 # elif defined(__ia64__) || defined(_M_IA64) || defined(__itanium__)
4945 # define VER_H_PROM_TSA_TEXT "Intel Itanium (IA64)"
4946 # elif defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__) || defined(__powerpc64__) || \
4947 defined(__POWERPC64__) || \
4948 defined(_M_PPC64) || \
4949 defined(__PPC64) || \
4950 defined(_ARCH_PPC64)
4951 # define VER_H_PROM_TSA_TEXT "Power ISA (64-bit) "
4952 # elif defined(__ppc__) || defined(__PPC__) || defined(__powerpc__) || defined(__POWERPC__) || defined(_M_PPC) || \
4953 defined(__PPC) || \
4954 defined(__ppc32__) || \
4955 defined(__PPC32__) || \
4956 defined(__powerpc32__) || \
4957 defined(__POWERPC32__) || \
4958 defined(_M_PPC32) || \
4959 defined(__PPC32)
4960 # define VER_H_PROM_TSA_TEXT "PowerPC ISA (32-bit)"
4961 # elif defined(__s390x__)
4962 # define VER_H_PROM_TSA_TEXT "IBM z/Architecture "
4963 # elif defined(__s390__)
4964 # define VER_H_PROM_TSA_TEXT "IBM ESA System/390 "
4965 # elif defined(__J2__) || defined(__J2P__) || defined(__j2__) || defined(__j2p__)
4966 # define VER_H_PROM_TSA_TEXT "J-Core J2 Open CPU "
4967 # elif defined(__SH4__) || defined(__sh4__) || defined(__SH4) || defined(__sh4)
4968 # define VER_H_PROM_TSA_TEXT "Hitachi/Renesas SH-4"
4969 # elif defined(__SH2__) || defined(__sh2__) || defined(__SH2) || defined(__sh2)
4970 # define VER_H_PROM_TSA_TEXT "Hitachi/Renesas SH-2"
4971 # elif defined(__alpha__)
4972 # define VER_H_PROM_TSA_TEXT "Alpha AXP "
4973 # elif defined(__hppa__) || defined(__HPPA__) || defined(__PARISC__) || defined(__parisc__)
4974 # define VER_H_PROM_TSA_TEXT "HP PA-RISC "
4975 # elif defined(__ICE9__) || defined(__ice9__) || defined(__ICE9) || defined(__ice9)
4976 # define VER_H_PROM_TSA_TEXT "SiCortex ICE-9 "
4977 # elif defined(mips64) || defined(__mips64__) || defined(MIPS64) || defined(_MIPS64_) || defined(__mips64)
4978 # define VER_H_PROM_TSA_TEXT "MIPS64 "
4979 # elif defined(mips) || defined(__mips__) || defined(MIPS) || defined(_MIPS_) || defined(__mips)
4980 # define VER_H_PROM_TSA_TEXT "MIPS "
4981 # elif defined(__OpenRISC__) || defined(__OPENRISC__) || defined(__openrisc__) || defined(__OR1K__) || defined(__OPENRISC1K__)
4982 # define VER_H_PROM_TSA_TEXT "OpenRISC "
4983 # elif defined(__sparc64) || defined(__SPARC64) || defined(__SPARC64__) || defined(__sparc64__)
4984 # define VER_H_PROM_TSA_TEXT "SPARC64 "
4985 # elif defined(__sparc) || defined(__SPARC) || defined(__SPARC__) || defined(__sparc__)
4986 # define VER_H_PROM_TSA_TEXT "SPARC "
4987 # elif defined(__riscv) || defined(__riscv__)
4988 # define VER_H_PROM_TSA_TEXT "RISC-V "
4989 # elif defined(__e2k__) || defined(__E2K__) || defined(__elbrus64__) || defined(__elbrus__) || defined(__ELBRUS__) || defined(__e2k64__)
4990 # if defined(__iset__)
4991 # if __iset__ > 0
4992 # if __iset__ == 1
4993 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v1 "
4994 # elif __iset__ == 2
4995 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v2 "
4996 # elif __iset__ == 3
4997 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v3 "
4998 # elif __iset__ == 4
4999 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v4 "
5000 # elif __iset__ == 5
5001 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v5 "
5002 # elif __iset__ == 6
5003 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v6 "
5004 # elif __iset__ == 7
5005 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v7 "
5006 # elif __iset__ == 8
5007 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v8 "
5008 # elif __iset__ == 9
5009 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v9 "
5010 # elif __iset__ == 10
5011 # define VER_H_PROM_TSA_TEXT "MCST Elbrus v10 "
5012 # else
5013 # define VER_H_PROM_TSA_TEXT "MCST Elbrus "
5014 # endif
5015 # else
5016 # define VER_H_PROM_TSA_TEXT "MCST Elbrus "
5017 # endif
5018 # else
5019 # define VER_H_PROM_TSA_TEXT "MCST Elbrus "
5020 # endif
5021 # elif defined(__myriad2__)
5022 # define VER_H_PROM_TSA_TEXT "Myriad2 "
5023 # elif defined(__loongarch64) || defined(__loongarch__)
5024 # define VER_H_PROM_TSA_TEXT "LoongArch "
5025 # elif defined(_m68851) || defined(__m68k__) || defined(__m68000__) || defined(__M68K)
5026 # define VER_H_PROM_TSA_TEXT "Motorola m68k "
5027 # elif defined(__m88k__) || defined(__m88000__) || defined(__M88K)
5028 # define VER_H_PROM_TSA_TEXT "Motorola m88k "
5029 # elif defined(__VAX__) || defined(__vax__)
5030 # define VER_H_PROM_TSA_TEXT "VAX "
5031 # elif defined(__NIOS2__) || defined(__nios2__)
5032 # define VER_H_PROM_TSA_TEXT "Altera Nios II "
5033 # elif defined(__MICROBLAZE__) || defined(__microblaze__)
5034 # define VER_H_PROM_TSA_TEXT "Xilinx MicroBlaze "
5035 # elif defined(__kvx__) || defined(__KVX__) || defined(__KVX_64__)
5036 # define VER_H_PROM_TSA_TEXT "Kalray KVX "
5037 # endif
5038 # if !defined(VER_H_PROM_TSA_TEXT)
5039 # define BURN_PROM_TSA_TEXT "Unknown Target Arch."
5040 # else
5041 # define BURN_PROM_TSA_TEXT VER_H_PROM_TSA_TEXT
5042 # endif
5043 #endif
5044
5045 #if (defined(__WIN__) || defined(_WIN32) || defined(IS_WINDOWS) || defined(_MSC_VER) || defined(__MINGW32__) || \
5046 defined(__MINGW64__) || defined(CROSS_MINGW32) || defined(CROSS_MINGW64)) && !defined(__CYGWIN__)
5047 # define DC_IS_WINDOWS 1
5048 #else
5049 # define DC_IS_WINDOWS 0
5050 #endif
5051
5052 #if defined(BUILD_PROM_TSV_TEXT)
5053 # define BURN_PROM_TSV_TEXT BUILD_PROM_TSV_TEXT
5054 #else
5055 # if DC_IS_WINDOWS
5056 # define VER_H_PROM_TSV_TEXT "Microsoft Windows "
5057 # elif defined(__CYGWIN__)
5058 # define VER_H_PROM_TSV_TEXT "Windows/Cygwin "
5059 # elif (defined(__sunos) || defined(__sun) || defined(__sun__)) && (defined(SYSV) || defined(__SVR4) || defined(__SVR4__) || \
5060 defined(__svr4__))
5061 # if defined(__illumos__)
5062 # define VER_H_PROM_TSV_TEXT "illumos "
5063 # else
5064 # define VER_H_PROM_TSV_TEXT "Solaris "
5065 # endif
5066 # elif defined(__APPLE__) && defined(__MACH__)
5067 # define VER_H_PROM_TSV_TEXT "Apple macOS "
5068 # elif defined(__GNU__) && !defined(__linux__)
5069 # define VER_H_PROM_TSV_TEXT "GNU/Hurd "
5070 # elif defined(__ANDROID__) && defined(__ANDROID_API__)
5071 # if defined(__linux__)
5072 # define VER_H_PROM_TSV_TEXT "Android/Linux "
5073 # else
5074 # define VER_H_PROM_TSV_TEXT "Android "
5075 # endif
5076 # elif defined(__lynxOS__) || defined(__LYNXOS__) || defined(LynxOS) || defined(LYNXOS)
5077 # define VER_H_PROM_TSV_TEXT "LynxOS "
5078 # elif defined(__HELENOS__)
5079 # define VER_H_PROM_TSV_TEXT "HelenOS "
5080 # elif defined(__linux__)
5081 # if defined(__BIONIC__)
5082 # define VER_H_PROM_TSV_TEXT "Linux/Bionic-libc "
5083 # elif defined(__UCLIBC__) || defined(UCLIBC)
5084 # define VER_H_PROM_TSV_TEXT "Linux/uClibc "
5085 # elif defined(__NEWLIB__)
5086 # define VER_H_PROM_TSV_TEXT "Linux/Newlib "
5087 # elif defined(__dietlibc__)
5088 # define VER_H_PROM_TSV_TEXT "Linux/Diet-libc "
5089 # elif defined(__GLIBC__)
5090 # define VER_H_PROM_TSV_TEXT "GNU/Linux "
5091 # else
5092 # define VER_H_PROM_TSV_TEXT "Linux "
5093 # endif
5094 # elif defined(__HAIKU__)
5095 # define VER_H_PROM_TSV_TEXT "Haiku "
5096 # elif defined(__serenity__)
5097 # define VER_H_PROM_TSV_TEXT "SerenityOS "
5098 # elif defined(__FreeBSD__)
5099 # define VER_H_PROM_TSV_TEXT "FreeBSD "
5100 # elif defined(__NetBSD__)
5101 # define VER_H_PROM_TSV_TEXT "NetBSD "
5102 # elif defined(__OpenBSD__)
5103 # define VER_H_PROM_TSV_TEXT "OpenBSD "
5104 # elif defined(__DragonFly__)
5105 # define VER_H_PROM_TSV_TEXT "DragonFly BSD "
5106 # elif defined(_AIX)
5107 # if !defined(__PASE__)
5108 # define VER_H_PROM_TSV_TEXT "IBM AIX "
5109 # else
5110 # define VER_H_PROM_TSV_TEXT "IBM OS/400 (PASE) "
5111 # endif
5112 # elif defined(__VXWORKS__) || defined(__VXWORKS) || defined(__vxworks) || defined(__vxworks__) || defined(_VxWorks)
5113 # if !defined(__RTP__)
5114 # define VER_H_PROM_TSV_TEXT "VxWorks "
5115 # else
5116 # define VER_H_PROM_TSV_TEXT "VxWorks RTP "
5117 # endif
5118 # elif defined(__rtems__)
5119 # if defined(__FreeBSD_version)
5120 # define VER_H_PROM_TSV_TEXT "RTEMS/LibBSD "
5121 # else
5122 # define VER_H_PROM_TSV_TEXT "RTEMS "
5123 # endif
5124 # elif defined(__ZEPHYR__)
5125 # define VER_H_PROM_TSV_TEXT "Zephyr "
5126 # elif defined(ti_sysbios_BIOS___VERS) || defined(ti_sysbios_BIOS__top__)
5127 # define VER_H_PROM_TSV_TEXT "TI-RTOS (SYS/BIOS) "
5128 # elif defined(__OSV__)
5129 # define VER_H_PROM_TSV_TEXT "OSv "
5130 # elif defined(MINIX) || defined(MINIX3) || defined(MINIX315) || defined(__minix__) || defined(__minix3__) || defined(__minix315__)
5131 # define VER_H_PROM_TSV_TEXT "Minix "
5132 # elif defined(__QNX__)
5133 # if defined(__QNXNTO__)
5134 # define VER_H_PROM_TSV_TEXT "QNX Neutrino "
5135 # else
5136 # define VER_H_PROM_TSV_TEXT "QNX "
5137 # endif
5138 # elif defined(__managarm__)
5139 # define VER_H_PROM_TSV_TEXT "Managarm "
5140 # endif
5141 # if !defined(VER_H_PROM_TSV_TEXT)
5142 # define BURN_PROM_TSV_TEXT "Unknown Target OpSys"
5143 # else
5144 # define BURN_PROM_TSV_TEXT VER_H_PROM_TSV_TEXT
5145 # endif
5146 #endif
5147
5148 #if !defined(VER_H_GIT_DATE_SHORT)
5149 # define VER_H_GIT_DATE_SHORT "2021-01-01"
5150 #endif
5151
5152 #if !defined(BURN_PROM_BUILD_NUM)
5153 # define BURN_PROM_BUILD_NUM " "
5154 #endif
5155
5156 #define BURN(offset, length, string) memcpy ((char *) PROM + (offset), string, length)
5157 #define BURN1(offset, byte) PROM[offset] = (char) (byte)
5158
5159 (void)memset (PROM, 255, 1024);
5160
5161
5162 BURN ( 00, 11, "DPS 8/SIM M");
5163 BURN (013, 11, serial);
5164 BURN (026, 6, ship);
5165 BURN1 (034, getbits36_8 (rsw2, 0));
5166 BURN1 (035, getbits36_8 (rsw2, 8));
5167 BURN1 (036, getbits36_8 (rsw2, 16));
5168 BURN1 (037, getbits36_8 (rsw2, 24));
5169 BURN1 (040, ((getbits36_4 (rsw2, 32) << 4) \
5170 | rsw2Ext));
5171
5172
5173 BURN ( 60, 1, "2");
5174 BURN ( 70, 10, VER_H_GIT_DATE_SHORT);
5175 BURN ( 80, 3, VER_H_PROM_MAJOR_VER);
5176 BURN ( 83, 3, VER_H_PROM_MINOR_VER);
5177 BURN ( 86, 3, VER_H_PROM_PATCH_VER);
5178 BURN ( 89, 3, VER_H_PROM_OTHER_VER);
5179 BURN ( 92, 8, BURN_PROM_BUILD_NUM);
5180 BURN (100, 1, VER_H_GIT_RELT);
5181 BURN (101, 29, VER_H_PROM_VER_TEXT);
5182 BURN (130, 20, BURN_PROM_OSA_TEXT);
5183 BURN (150, 20, BURN_PROM_OSV_TEXT);
5184 BURN (170, 20, BURN_PROM_TSA_TEXT);
5185 BURN (190, 20, BURN_PROM_TSV_TEXT);
5186 }
5187
5188 void cpuStats (uint cpuNo) {
5189 if (! cpus[cpuNo].cycleCnt)
5190 return;
5191
5192
5193 #if defined(__HAIKU__)
5194 # if HAS_INCLUDE(<syscall_clock_info.h>)
5195 # include <syscall_clock_info.h>
5196 # endif
5197 # if !defined(_SYSTEM_SYSCALL_CLOCK_INFO_H)
5198 # if !defined(HAIKU_NO_PTHREAD_GETCPUCLOCKID)
5199 # define HAIKU_NO_PTHREAD_GETCPUCLOCKID
5200 # endif
5201 # endif
5202 #endif
5203
5204
5205
5206 #if defined(__sun) || defined(__sun__)
5207 # if !defined(__illumos__)
5208 # if HAS_INCLUDE(<sys/sysevent.h>)
5209 # include <sys/sysevent.h>
5210 # endif
5211 # if defined(ILLUMOS_VENDOR) || defined(ILLUMOS_KERN_PUB)
5212 # define __illumos__
5213 # endif
5214 # endif
5215 #endif
5216
5217 double cpu_seconds = 0;
5218 int cpu_millis = 0;
5219 char cpu_ftime[64] = {0};
5220 #if (defined(THREADZ) || defined(LOCKLESS))
5221 # if !defined(HAIKU_NO_PTHREAD_GETCPUCLOCKID) && !defined(__illumos__) && \
5222 !defined(__APPLE__) && !defined(__PASE__) && !defined(__serenity__)
5223 struct timespec cpu_time;
5224 clockid_t clock_id;
5225 if (pthread_getcpuclockid (cpus[cpuNo].thread_id, &clock_id) == 0) {
5226 if (clock_gettime (clock_id, &cpu_time) == 0) {
5227 cpu_seconds = (double)cpu_time.tv_sec + cpu_time.tv_nsec / 1e9;
5228 }
5229 }
5230 # endif
5231 #endif
5232
5233 if (cpu_seconds > 0 && cpus[cpuNo].instrCnt > 0) {
5234 int cpu_hours = (int)(cpu_seconds / 3600);
5235 int cpu_minutes = (int)((cpu_seconds - cpu_hours * 3600) / 60);
5236 int cpu_secs = (int)(cpu_seconds - (cpu_hours * 3600) - (cpu_minutes * 60));
5237 struct tm cpu_tm = {0};
5238 cpu_tm.tm_hour = cpu_hours;
5239 cpu_tm.tm_min = cpu_minutes;
5240 cpu_tm.tm_sec = cpu_secs;
5241 strftime(cpu_ftime, sizeof(cpu_ftime), "%H:%M:%S", &cpu_tm);
5242 cpu_millis = (int)((cpu_seconds - (cpu_hours * 3600) - (cpu_minutes * 60) - cpu_secs) * 1000);
5243 }
5244
5245 (void)fflush(stderr);
5246 (void)fflush(stdout);
5247 sim_msg ("\r\n");
5248 (void)fflush(stdout);
5249 (void)fflush(stderr);
5250 sim_msg ("\r+---------------------------------+\r\n");
5251 sim_msg ("\r| CPU %c Statistics |\r\n", 'A' + cpuNo);
5252 sim_msg ("\r+---------------------------------+\r\n");
5253 if (cpu_seconds > 0 && cpus[cpuNo].instrCnt > 0) {
5254 sim_msg ("\r| CPU Time Used %11s.%03d |\r\n", cpu_ftime, cpu_millis);
5255 sim_msg ("\r+---------------------------------+\r\n");
5256 }
5257 (void)fflush(stdout);
5258 (void)fflush(stderr);
5259 #if defined(_AIX) && !defined(__PASE__)
5260 struct rusage rusage;
5261 if (!pthread_getrusage_np(cpus[cpuNo].thread_id, &rusage, PTHRDSINFO_RUSAGE_COLLECT)) {
5262 sim_msg ("\r| Volun. CtxtSw %'15llu |\r\n", (unsigned long long)rusage.ru_nvcsw);
5263 sim_msg ("\r| Invol. CtxtSw %'15llu |\r\n", (unsigned long long)rusage.ru_nivcsw);
5264 sim_msg ("\r+---------------------------------+\r\n");
5265 }
5266 #endif
5267 #if defined(WIN_STDIO)
5268 sim_msg ("\r| cycles %15llu |\r\n", (unsigned long long)cpus[cpuNo].cycleCnt);
5269 sim_msg ("\r| instructions %15llu |\r\n", (unsigned long long)cpus[cpuNo].instrCnt);
5270 (void)fflush(stdout);
5271 (void)fflush(stderr);
5272 sim_msg ("\r+---------------------------------+\r\n");
5273 sim_msg ("\r| lockCnt %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockCnt);
5274 sim_msg ("\r| lockImmediate %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockImmediate);
5275 (void)fflush(stdout);
5276 (void)fflush(stderr);
5277 sim_msg ("\r+---------------------------------+\r\n");
5278 sim_msg ("\r| lockWait %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockWait);
5279 sim_msg ("\r| lockWaitMax %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockWaitMax);
5280 (void)fflush(stdout);
5281 (void)fflush(stderr);
5282 # if !defined(SCHED_NEVER_YIELD)
5283 sim_msg ("\r| lockYield %15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockYield);
5284 (void)fflush(stdout);
5285 (void)fflush(stderr);
5286 # else
5287 sim_msg ("\r| lockYield ---- |\r\n");
5288 (void)fflush(stdout);
5289 (void)fflush(stderr);
5290 # endif
5291 sim_msg ("\r+---------------------------------+");
5292 (void)fflush(stdout);
5293 (void)fflush(stderr);
5294 # if !defined(UCACHE)
5295 # if !defined(UCACHE_STATS)
5296 sim_msg ("\r\n");
5297 # endif
5298 # endif
5299 (void)fflush(stdout);
5300 (void)fflush(stderr);
5301 #else
5302 sim_msg ("\r| cycles %'15llu |\r\n", (unsigned long long)cpus[cpuNo].cycleCnt);
5303 sim_msg ("\r| instructions %'15llu |\r\n", (unsigned long long)cpus[cpuNo].instrCnt);
5304 (void)fflush(stdout);
5305 (void)fflush(stderr);
5306 sim_msg ("\r+---------------------------------+\r\n");
5307 sim_msg ("\r| lockCnt %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockCnt);
5308 sim_msg ("\r| lockImmediate %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockImmediate);
5309 (void)fflush(stdout);
5310 (void)fflush(stderr);
5311 sim_msg ("\r+---------------------------------+\r\n");
5312 sim_msg ("\r| lockWait %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockWait);
5313 sim_msg ("\r| lockWaitMax %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockWaitMax);
5314 (void)fflush(stdout);
5315 (void)fflush(stderr);
5316 # if !defined(SCHED_NEVER_YIELD)
5317 sim_msg ("\r| lockYield %'15llu |\r\n", (unsigned long long)cpus[cpuNo].coreLockState.lockYield);
5318 (void)fflush(stdout);
5319 (void)fflush(stderr);
5320 # else
5321 sim_msg ("\r| lockYield ---- |\r\n");
5322 (void)fflush(stdout);
5323 (void)fflush(stderr);
5324 # endif
5325 sim_msg ("\r+---------------------------------+");
5326 (void)fflush(stdout);
5327 (void)fflush(stderr);
5328 # if !defined(UCACHE)
5329 # if !defined(UCACHE_STATS)
5330 sim_msg ("\r\n");
5331 # endif
5332 # endif
5333 (void)fflush(stderr);
5334 (void)fflush(stdout);
5335 #endif
5336
5337 #if defined(UCACHE_STATS)
5338 ucacheStats (cpuNo);
5339 #endif
5340
5341
5342
5343
5344
5345
5346
5347 }
5348
5349 bool running_perf_test;
5350
5351 #if defined(THREADZ) || defined(LOCKLESS)
5352 # include <locale.h>
5353 # include "segldr.h"
5354
5355 void perfTest (char * testName) {
5356 running_perf_test = true;
5357
5358 if (testName == NULL)
5359 testName = "strip.mem";
5360
5361 # if !defined(NO_LOCALE)
5362 (void) setlocale(LC_NUMERIC, "");
5363 # endif
5364
5365
5366 # if !defined(_AIX)
5367 system_state = aligned_malloc (sizeof (struct system_state_s));
5368 # else
5369 system_state = malloc (sizeof (struct system_state_s));
5370 # endif
5371 if (!system_state)
5372 {
5373 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
5374 __func__, __FILE__, __LINE__);
5375 # if defined(USE_BACKTRACE)
5376 # if defined(SIGUSR2)
5377 (void)raise(SIGUSR2);
5378
5379 # endif
5380 # endif
5381 abort();
5382 }
5383 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) && !defined(__PASE__)
5384 if (0 == sim_free_memory || sim_free_memory >= 192000000) {
5385 if (mlock(system_state, sizeof(struct system_state_s)) == -1) {
5386 mlock_failure = true;
5387 }
5388 } else {
5389 # if defined(TESTING)
5390 sim_warn ("Low memory - no memory locking attempted.\r\n");
5391 # else
5392 (void)system_state;
5393 # endif
5394 }
5395 # endif
5396 M = system_state->M;
5397 # if defined(M_SHARED)
5398 cpus = system_state->cpus;
5399 # endif
5400 (void) memset (cpus, 0, sizeof (cpu_state_t) * N_CPU_UNITS_MAX);
5401 for (int i = 0; i < N_CPU_UNITS_MAX; i ++) {
5402 cpus[i].switches.FLT_BASE = 2;
5403 cpus[i].instrCnt = 0;
5404 cpus[i].cycleCnt = 0;
5405 for (int j = 0; j < N_FAULTS; j ++)
5406 cpus[i].faultCnt [j] = 0;
5407 }
5408
5409 cpus[0].tweaks.enable_emcall = 1;
5410 opc_dev.numunits = 1;
5411 cpu_reset_unit_idx (0, false);
5412 set_cpu_cycle (& cpus[0], FETCH_cycle);
5413 mrestore (testName);
5414 _cpup = & cpus[0];
5415 threadz_sim_instr ();
5416 }
5417 #endif