Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / ui_cmds.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: ui_cmds.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/* icq
22SELECT - input multiplexing
23DONE - done replies to the sync-server
24*/
25/*
26 * Copyright (C) 1996, 2001, 2005 Sun Microsystems, Inc.
27 * All rights reserved.
28 */
29#pragma ident "%%1.119 07/01/09 %%"
30
31// "ui_cmds.cc"
32//
33// handles UI input multiplexing (stdin, sync socket, back door, script file)
34// and command parsing, lookup, and calling of registered function for command
35//
36//
37// public functions:
38//
39// preinit_ui lame excuse for poor programming
40// UI_register_cmd add a command string to the lookup list
41// UI_invalidate_cmd delete a command string from the lookup list
42//
43// init_ui starts up the UI thread
44// UI_exec_cmd inserts a command into the back-door queue
45//
46//
47// public variables:
48// -- none !!! --
49//
50// extraneous junk:
51//
52// send_diskinfo_to_fakeprom called from scsi_ctrl, fc_ctrl. Yeuch!
53//
54
55
56/* standard C includes */
57#include <stdio.h>
58#include <thread.h>
59#include <stdlib.h>
60#include <string.h>
61#include <assert.h>
62#include <stdio.h>
63#include <unistd.h>
64#include <ctype.h>
65
66/* solaris includes */
67#include <signal.h>
68#include <sys/types.h>
69#include <sys/exec.h>
70#include <sys/stat.h>
71#include <sys/time.h>
72#include <sys/resource.h>
73#include <sys/procfs.h>
74#include <sys/socket.h>
75#include <netinet/in.h>
76#include <arpa/inet.h>
77#include <fcntl.h>
78#include <netdb.h>
79#include <stropts.h>
80
81#include <dlfcn.h>
82
83/* project includes */
84#include "mmi.h"
85// FlexConfig: needs this
86#include "serial_mod.h"
87
88#include "ui.h"
89#include "types.h"
90#include "blaze_globals.h"
91#include "system.h"
92#include "mem.h"
93typedef void* TM_OPAQUE_DATA;
94#include "tracemod.h"
95#include "ui_utils.h"
96#include "sim_cmd_struct.h"
97#include "ui_cmds.h"
98#include "blaze_globals.h"
99#include "ui_cmd_struct.h"
100#include "ui_cmds.h"
101#include "ui_elfsym.h"
102#include "blz_runtime.h"
103#include "macrolib.h"
104#include "netsim.h"
105#include "cpu_interface.h"
106#include "stracer.h"
107#include "workerthread.h"
108#include "command_opts.h"
109#include "spix_sparc.h"
110
111#include "readline/readline.h"
112#include "readline/history.h"
113
114extern uint32_t boot_ctrl_id;
115extern uint32_t boot_target_id;
116extern uint32_t boot_part_id;
117extern uint32_t boot_disk_id;
118
119char bootpath[256];
120
121// global cpu_id set by pselect command
122int pselect_cpu_id = 0;
123
124extern int eventque_ui_cmds (void*, int argc, char **argv);
125
126
127// ============================================================================
128//
129// public data
130//
131
132volatile bool_t cpu_enabled[MAX_MP]; /* init'd in main.cc */
133volatile bool_t cpu_enable_changed; /* init'd in main.cc */
134
135
136extern int blaze_debug; /* lives in main.cc */
137extern int blaze_option; /* lives in main.cc */
138
139
140
141
142// ============================================================================
143//
144// private functions
145//
146
147int exec_cmd (char *s_cmd);
148
149static int version_ui_cmd (void*, int argc, char **argv);
150static int conf_ui_cmd (void*, int argc, char **argv);
151static int mips_ui_cmd (void*, int argc, char **argv);
152static int file_ui_cmd (void*, int argc, char **argv);
153static int write_ui_cmd (void*, int argc, char **argv);
154static int cs_ui_cmd (void*, int argc, char **argv);
155static int load_ui_cmd (void*, int argc, char **argv);
156static int setreg_ui_cmd (void*, int argc, char **argv);
157static int stop_ui_cmd (void*, int argc, char **argv);
158static int stepim_ui_cmd (void*, int argc, char **argv);
159static int stept_ui_cmd (void*, int argc, char **argv);
160static int sync_ui_cmd (void*, int argc, char **argv);
161static int resume_ui_cmd (void*, int argc, char **argv);
162static int on_ui_cmd (void*, int argc, char **argv);
163static int rdt_ui_cmd (void*, int argc, char **argv);
164static int diskdelay_ui_cmd (void*, int argc, char **argv);
165static int perf_ui_cmd (void*, int argc, char **argv);
166static int help_ui_cmd (void*, int argc, char **argv);
167static int debug_ui_cmd (void*, int argc, char **argv);
168static int option_ui_cmd (void*, int argc, char **argv);
169static int alias_ui_cmd (void*, int argc, char **argv);
170static int unalias_ui_cmd (void*, int argc, char **argv);
171static int quit_ui_cmd (void*, int argc, char **argv);
172static int break_ui_cmd (void*, int argc, char **argv);
173static int list_breakpoints_ui_cmd (void*, int argc, char **argv);
174static int dbreak_ui_cmd (void*, int argc, char **argv);
175static int delete_ui_cmd (void*, int argc, char **argv);
176static int pty_display (void *, int argc, char **argv);
177static int penable_ui_cmd (void *, int argc, char **argv);
178static int pdisable_ui_cmd (void *, int argc, char **argv);
179static int tlbs_ui_cmd (void *, int argc, char **argv);
180static int vdebug_ui_cmd (void *, int argc, char **argv);
181static int loglev_ui_cmd (void*, int argc, char**argv);
182static int devmap_ui_cmd (void*, int argc, char**argv);
183static int pselect_ui_cmd (void*, int argc, char**argv);
184static int translate_ui_cmd(void*, int argc, char **argv);
185static int get_ui_cmd(void*, int argc, char **argv);
186static int set_ui_cmd(void*, int argc, char **argv);
187static int disassemble_ui_cmd(void*, int argc, char **argv);
188static int run_python_file_ui_cmd(void*, int argc, char **argv);
189static int echo_ui_cmd(void*, int argc, char **argv);
190static int run_ui_cmd (void*, int argc, char **argv);
191static int stepi_ui_cmd (void*, int argc, char **argv);
192static int stepc_ui_cmd (void*, int argc, char **argv);
193static int read_asi_ui_cmd (void*, int argc, char **argv);
194static int write_asi_ui_cmd (void*, int argc, char **argv);
195
196
197
198static void init_sync ();
199
200
201static Vcpu * get_vcpu_by_name ( char *name );
202
203// ======================= GLOBAL VARIABLES ===================================
204
205Ui_cmd ui_cmd_list [] =
206{
207 {"version","\n", 0, version_ui_cmd, NULL, NULL},
208 {"run", "run <mode>\n", 0, run_ui_cmd, NULL, NULL},
209 {"file", "file <script file name>\n", 0, file_ui_cmd, NULL, NULL},
210 {"run-cmd-file", "run-cmd-file <script file name>\n", 0, file_ui_cmd, NULL, NULL},
211 {"stop", "just stop SAM\n", 0, stop_ui_cmd, NULL, NULL},
212 {"conf", "conf <name> <value>\n", 0, conf_ui_cmd, NULL, NULL},
213 {"mips", "mips \n", 0, mips_ui_cmd, NULL, NULL},
214 {"write", "write <pa> <file> <va> \n", 0, write_ui_cmd, NULL, NULL},
215 {"load", "load <mode> <addr> <value>\n", 0, load_ui_cmd, NULL, NULL},
216 {"setreg", "setreg <regname> <value> \n", 0, setreg_ui_cmd, NULL, NULL},
217#ifdef V5_FAKEPROM
218 {"console-send", "console-send <string> \n",FUI_STRING, cs_ui_cmd, NULL, NULL},
219#endif
220 {"quit", "quit SAM\n", 0, quit_ui_cmd, NULL, NULL},
221 {"help", "help <command>", 0, help_ui_cmd, NULL, NULL},
222 {"debug", "debug [N]", 0, debug_ui_cmd, NULL, NULL},
223 {"option", "option [N]", 0, option_ui_cmd, NULL, NULL},
224 {"events", "events", 0, eventque_ui_cmds, NULL, NULL},
225 {"stepi", "stepi <N>", 0, stepi_ui_cmd, NULL, NULL},
226 {"stepc", "stepc <N>", 0, stepc_ui_cmd, NULL, NULL},
227 {"stepim", "stepim <N>", 0, stepim_ui_cmd, NULL, NULL},
228 {"stept", "stept <usecs>", 0, stept_ui_cmd, NULL, NULL},
229 {"on", "on STOP <command>", 0, on_ui_cmd, NULL, NULL},
230 {"rdt", "rdt [<FILE>]", 0, rdt_ui_cmd, NULL, NULL},
231 {"diskdelay", "diskdelay [ddelay[/wrddelay]] [start_cycle]", 0, diskdelay_ui_cmd, NULL, NULL},
232 {"perf", "perf # | off", 0, perf_ui_cmd, NULL, NULL},
233 {"sync", "on|off", 0, sync_ui_cmd, NULL, NULL},
234 {"resume", "back to prev sync mode", 0, resume_ui_cmd, NULL, NULL},
235 {"alias", "alias [<old cmd>] [<new cmd>] ",0, alias_ui_cmd, NULL, NULL},
236 {"unalias", "unalias <alias cmd>" ,0, unalias_ui_cmd, NULL, NULL},
237 {"penable","penable [-all | <thN>]", 0, penable_ui_cmd, NULL, NULL},
238 {"pdisable", "pdisable [-all | <thN>]", 0, pdisable_ui_cmd, NULL, NULL},
239 {"pty", "pty", 0, pty_display, NULL, NULL},
240 {"break", "set a breakpoint \n", 0, break_ui_cmd, NULL, NULL},
241 {"list-breakpoints", "list breakpoints \n", 0, list_breakpoints_ui_cmd, NULL, NULL},
242 {"dbreak", "delete a breakpoint <bp_id>\n", 0, dbreak_ui_cmd, NULL, NULL},
243 {"delete", "delete breakpoints [all|<bp_id>...]\n", 0, delete_ui_cmd, NULL, NULL},
244 {"vdebug", "debug tracer on|off\n", 0, vdebug_ui_cmd, NULL, NULL},
245 {"load_symbols","load symbol table\n", 0, load_sym_ui_cmd, NULL, NULL},
246 {"unload_symbols","uload symbol table\n", 0, unload_sym_ui_cmd, NULL, NULL},
247 {"sym", "display symbol table\n", 0, symbols_ui_cmd, NULL, NULL},
248 {"where", "display call stack\n", 0, where_ui_cmd, NULL, NULL},
249 {"tlbs", "display tlb entries\n", 0, tlbs_ui_cmd, NULL, NULL},
250 {"loglev", "loglev [1|2|3]\n", 0, loglev_ui_cmd, NULL, NULL},
251 {"devmap", "show internal device id map\n", 0, devmap_ui_cmd, NULL, NULL},
252 {"pselect", "pselect cpu_id\n", 0, pselect_ui_cmd, NULL, NULL},
253 {"translate", "translate address\n", 0, translate_ui_cmd, NULL, NULL},
254 {"get", "get memory\n", 0, get_ui_cmd, NULL, NULL},
255 {"set", "set memory\n", 0, set_ui_cmd, NULL, NULL},
256 {"disassemble", "disassemble memory\n", 0, disassemble_ui_cmd, NULL, NULL},
257 {"echo", "echo [(\"string\"|integer|float)]\n", 0, echo_ui_cmd, NULL, NULL},
258 {"run-python-file", "py execfile\n", 0, run_python_file_ui_cmd, NULL, NULL},
259 {"read-asi", "read non-translating asi\n", 0, read_asi_ui_cmd, NULL, NULL},
260 {"write-asi", "write non-translating asi\n",0, write_asi_ui_cmd, NULL, NULL}
261};
262static Ui_cmd * plast = NULL;
263
264
265// ------------ ui-misc globals ------------
266//
267static Ui_misc the_misc = {0};
268static Ui_misc *pui_misc = &the_misc;
269
270static uint32_t diskdelay, wrdiskdelay ;
271static uint64_t ddelay_start_cycle = 0;
272
273int& CpuSet::max_cpu_ndx = g_vcpu_id_max;
274
275
276// ------------- UI-thread globals -------------
277//
278static volatile int sync_fd = -1;
279static volatile int sync_on = 0;
280
281static thread_t ui_sync_tid;
282
283// ============================ end globals ===================================
284
285
286// --------------------------- some forward decls --------------------------
287
288int arbitrary_ui_cmd (char * s);
289
290 // these are in "main.cc"
291typedef int (*ui_cmd_fn) (char *);
292extern void fe_register_ui_action (ui_cmd_fn foo) ;
293extern char* fe_get_sofile ();
294extern void* fe_get_sohandle ();
295
296
297extern char *pty_dev_a, *pty_dev_b;
298extern char *pty_dev_c, *pty_dev_d;
299
300// the pointers are set to point to real impl. if the py module is loaded to
301// add/delete the dynamically created SAM UI commands
302typedef void (*Py_Intf_fn)(const char *);
303Py_Intf_fn addPycmd = 0;
304Py_Intf_fn delPycmd = 0;
305bool python_UI = false;
306
307
308
309
310
311/////////////////////////////////////////////////
312//
313//
314//
315void linkup (Ui_cmd * pc)
316{
317 int i;
318 if (!plast) {
319 for (i = 0; i < (sizeof(ui_cmd_list) / sizeof(Ui_cmd)) - 1; i++) {
320 ui_cmd_list[i].next = &ui_cmd_list[i+1];
321 }
322 plast = &ui_cmd_list[i];
323 }
324 plast->next = pc;
325 plast = pc;
326}
327
328
329
330/////////////////////////////////////////////////
331void preinit_ui ()
332{
333 int i;
334 if (!plast) {
335 for (i = 0; i < (sizeof(ui_cmd_list) / sizeof(Ui_cmd)) - 1; i++) {
336 ui_cmd_list[i].next = &ui_cmd_list[i+1];
337 }
338 plast = &ui_cmd_list[i];
339 }
340
341
342}
343
344
345
346///////////////////////////////////////////////
347//
348// These functions below register new UI commands
349//
350void UI_register_cmd_1 (char * name, char *help,
351 ui_cmd_exe_handler efn, ui_cmd_help_handler hfn)
352{
353
354 Ui_cmd *pcmd = (Ui_cmd*) calloc (1, sizeof(Ui_cmd));
355 if (pcmd == NULL) {
356 ui->error("UI_register can not malloc\n");
357 return;
358 }
359 pcmd->name = (char*) strdup(name);
360 pcmd->help = (char*) strdup(help);
361 pcmd->cmd_exe_func = efn;
362 pcmd->cmd_help_func = hfn;
363
364 pcmd->flags = FUI_STRING; /* _1 */
365 pcmd->alias_argc = 1;
366
367 linkup (pcmd);
368
369 if(addPycmd) (*addPycmd)(name);
370}
371//
372//
373void UI_register_cmd_2 (char * name, char *help,
374 ui_cmd_exe_handler efn, ui_cmd_help_handler hfn)
375{
376
377 Ui_cmd *pcmd = (Ui_cmd*) calloc (1, sizeof(Ui_cmd));
378 if (pcmd == NULL) {
379 ui->error("UI_register can not malloc\n");
380 return;
381 }
382 pcmd->name = (char*) strdup(name);
383 pcmd->help = (char*) strdup(help);
384 pcmd->cmd_exe_func = efn;
385 pcmd->cmd_help_func = hfn;
386
387 pcmd->flags = 0; /* _2 */
388 pcmd->alias_argc = 1;
389
390 linkup (pcmd);
391
392 if(addPycmd) (*addPycmd)(name);
393}
394//
395//
396void UI_register_cmd_3 (char * name, char *help,
397 ui_cmd_exe_handler efn, ui_cmd_help_handler hfn, uint32_t flags)
398{
399 Ui_cmd *pcmd = (Ui_cmd*) calloc (1, sizeof(Ui_cmd));
400 if (pcmd == NULL) {
401 ui->error("UI_register can not malloc\n");
402 return;
403 }
404 pcmd->name = (char*) strdup(name);
405 pcmd->help = (char*) strdup(help);
406 pcmd->cmd_exe_func = efn;
407 pcmd->cmd_help_func = hfn;
408
409 pcmd->flags = flags; /* _3 */
410 pcmd->alias_argc = 1;
411
412 linkup (pcmd);
413
414 if(addPycmd) (*addPycmd)(name);
415
416}
417
418///////////////////////////////////////////////
419//
420// this command un-registers a UI command
421//
422void UI_invalidate_cmd (char *name)
423{
424 Ui_cmd *pcmd;
425 bool_t done = FALSE;
426
427 for (pcmd = &ui_cmd_list[0]; pcmd;pcmd = pcmd->next) {
428 if (strcmp(pcmd->name, name) == NULL) {
429
430 pcmd->flags |= FUI_INVALID;
431
432 done = TRUE;
433 }
434 }
435
436 if (done == FALSE)
437 ui->error("unable to find <%s> command", name);
438
439 // delete the command with the PY UI if present
440 if(delPycmd) (*delPycmd)(name);
441}
442
443
444
445
446
447///////////////////////////////////////////////
448
449static const int max_cmd_length = 2048;
450
451static int fdgets (char * sss, int fd)
452{
453 char * s = sss;
454 int n = 0;
455 while (1) {
456 if (read (fd, sss, 1) != 1)
457 return 0; // convention for closed socket
458 ++n;
459 if (*sss == '\n') {
460 *++sss = '\0';
461 return n;
462 }
463 if (*sss == '\0')
464 return n;
465 ++sss;
466 if (n>= max_cmd_length) {
467 ui->error("UI command too long (limit %d characters)\n", max_cmd_length);
468 *s = 0;
469 return 0;
470 }
471 }
472}
473
474
475sint64_t perf_ui_interval = 0, // all in "hrtime" units of nanosecs
476 perf_ui_start = 0,
477 next_perf_ui_time = 0,
478 perf_now = 0,
479 perf_tmp = 0,
480 last_perf_globaltick = 0;
481
482
483
484// ============================ UI SYNC THREAD ================================
485//
486// the purpose of this thread is to enable concurrent input from
487// sync_fd (is the global-time-sync socket) and to deal with the
488// perf command
489
490extern "C" void * ui_sync_thread (void *arg)
491{
492 char sss[max_cmd_length];
493
494 fd_set read_set;
495 int selrc;
496 struct timeval timeout, *tvp;
497
498 // Open a fake input so that select below works ok
499 // when there is no sync_fd.
500 int fake_fd = open("/dev/null",O_RDONLY,0);
501
502 for (;;) {
503
504 FD_ZERO (&read_set);
505 FD_SET (fake_fd,&read_set);
506
507 if (sync_fd >= 0) {
508 if (IN_SYNC_STATE(blaze_run_state))
509 FD_SET (sync_fd, &read_set);
510 }
511
512 if (perf_ui_interval != 0) {
513 sint64_t tmp = (next_perf_ui_time - gethrtime());
514 if (tmp > 0) {
515 timeout.tv_sec = tmp / 1000000000;
516 timeout.tv_usec = (tmp - 1000000000 * timeout.tv_sec) / 1000;
517 } else {
518 timeout.tv_sec = timeout.tv_usec = 0;
519 }
520 tvp = &timeout;
521 } else
522 tvp = NULL;
523
524 selrc = select (FD_SETSIZE, &read_set, 0, 0, tvp); /* SELECT */
525
526 if (perf_ui_interval != 0
527 && (perf_now = gethrtime()) > next_perf_ui_time) {
528 perf_tmp = SYSTEM_get_ticks ();
529 ui->output(" %6.1f %6.3f MIPS \n",
530 (double)(perf_now - perf_ui_start) / 1000000000.0,
531 (double)(perf_tmp - last_perf_globaltick)
532 / (perf_ui_interval / 1000.0));
533 next_perf_ui_time += perf_ui_interval;
534 last_perf_globaltick = perf_tmp;
535
536 }
537
538 if (selrc < 0) {
539 /* @@@ what about EINTR (for keyboard ctrl-C ?) */
540 ui->perror ("ui select: ");
541 }
542
543 if (sync_fd >= 0 && FD_ISSET (sync_fd, &read_set)) { /*SYNC*/
544 sss[0] = '\0';
545 if (fdgets(sss, sync_fd)) {
546
547 if (sync_on) {
548 if (strncmp (sss, "stept ", 6) == 0) {
549 UI_exec_cmd (sss);
550 } else {
551 ui->error("###sync cmd \"%s\", ignored.\n", sss);
552 }
553 } else {
554 write (sync_fd, "done\n", 5); /*quick DONE*/
555 }
556 } else { // the socket closed ...
557
558 UI_exec_cmd ("sync off\n");
559 UI_exec_cmd ("sync disconnect\n");
560 if (IN_SYNC_STATE(blaze_run_state)) {
561 UI_exec_cmd ("stop\n");
562 }
563 }
564 }
565 }
566 return NULL;
567}
568
569
570////////////////////////////////////////////////////////
571//
572// read user command input
573//
574void ui_readline ()
575{
576 while(1)
577 {
578 char *line, *help; // read line buffer
579 const char* prompt = "sam: ";
580 switch (blaze_run_state)
581 {
582 case e_BLAZE_STOP: prompt = "stop: "; break;
583 case e_BLAZE_STEP: prompt = "step: "; break;
584 case e_BLAZE_RUN: prompt = "run: "; break;
585 case e_BLAZE_GTSTEP: prompt = "gtstep:"; break;
586 case e_BLAZE_GTWAIT: prompt = "gtwait:"; break;
587 default: prompt = "???"; break;
588 }
589
590 // Read a line from input. An EOF results in a NULL
591 // pointer. We simply exit on EOF.
592
593 ui->input(prompt);
594 ui->flush();
595
596 line = readline(prompt);
597
598 if (line)
599 {
600 ui->input(line);
601 ui->input("\n");
602 UI_exec_cmd(line);
603
604 // Only add non blank lines to the history.
605
606 for (help = line; *help && isspace(*help); ++help)
607 ;
608 if (*help)
609 add_history(line);
610
611 free(line);
612 }
613 else
614 break; // eof hit, exit
615 }
616
617 if (IN_RUN_STATE (blaze_run_state))
618 UI_exec_cmd("stop\n");
619
620 SYSTEM_quit_UI ();
621}
622
623// ============================ UI THREAD INIT ================================
624//
625//
626void init_ui (char *rc, bool_t notused)
627{
628
629 pui_misc->rcfile = (rc) ? (char*) strdup(rc) : NULL;
630 pui_misc->redirect_fd = (-1);
631
632
633 init_sync (); // connect to global-time-sync if server specified
634
635 thr_create (NULL, NULL, ui_sync_thread, (void*)0, THR_BOUND, &ui_sync_tid);
636}
637
638
639
640// ================================ EXEC_CMD ==================================
641//
642//
643//
644//
645
646static void clear_invalid_aliases()
647{
648 for (Ui_cmd* pcmd = &ui_cmd_list[0]; pcmd; pcmd = pcmd->next)
649 if ((pcmd->flags & (FUI_ALIAS|FUI_INVALID)) ==
650 (FUI_ALIAS|FUI_INVALID))
651 pcmd->flags &= ~FUI_INVALID;
652}
653
654int exec_cmd (char *s_cmd)
655{
656 static char lastCommand [max_cmd_length] = "";
657
658 char * ps = NULL, *ps1 = NULL, *ps2 = NULL, **argv = NULL;
659 int argc = 16;
660 bool quoted = false;
661 Ui_cmd *pcmd = NULL;
662AGAIN:
663 ps = s_cmd;
664 while (isspace(*ps)) {
665 ++ps;
666 }
667
668 if ((*ps == '\0') || (*ps == '#'))
669 return 0;
670
671 //check if the cmd is well double-quoted.
672 if (ps1 = strchr(ps, '"')) {
673 int count = 0;
674 bool appear = false;
675 while ( *ps1 != '\0' ) {
676 //only when '"' is not escaped by '\', it will be regarded as a valid double-quoted sign.
677 if (((*ps1 == '"') && ((*(ps1-1) != '\\')) || (ps1 == ps))) {
678 count++;
679 }
680 if (*ps1 == '#') {
681 appear = true;
682 }
683 ps1++;
684 }
685 //when the number of valid double-quoted sign is even, the cmd is well quoted.
686 if ((!(count%2))&&appear) {
687 quoted = true;
688 }
689 }
690
691 //when the cmd is not well double-quoted, '#' is regarded as a comment. Or, keep the '#' when it is put into a
692 //well double-quoted cmd.
693 if (!quoted) {
694 if (ps2 = strchr(ps, '#')) {
695 *ps2 = '\0';
696 }
697 }
698
699 if ( strcmp(ps, "!!") == NULL )
700 {
701 strcpy(s_cmd, lastCommand);
702 goto AGAIN;
703 }
704 else
705 {
706 strcpy(lastCommand, s_cmd); // save last command
707 }
708
709 if (*ps == '%') // register read
710 return cpu_read_register_name (ps+1);
711
712 argv = ui_argv_argc_parse (ps, &argc);
713 if (argv == NULL) {
714 ui->error("cmd format error <%s>", ps);
715 return 1;
716 }
717
718 bool saw_alias = false;
719
720 retry:
721 for (pcmd = &ui_cmd_list[0]; pcmd;pcmd = pcmd->next) {
722
723 if (pcmd->flags & FUI_INVALID)
724 continue;
725 if (strcmp(argv[0], pcmd->name) == NULL) {
726 if (pcmd->flags & FUI_ALIAS) {
727 int new_argc = argc + pcmd->alias_argc - 1;
728 free(argv[0]);
729 argv = (char**) realloc(argv,
730 sizeof(const char*) * new_argc);
731 memmove(argv + pcmd->alias_argc, argv + 1,
732 sizeof(char**) * (argc - 1));
733 memmove(argv, pcmd->alias_argv, sizeof(char**) * pcmd->alias_argc);
734 for (int ndx = 0; ndx < pcmd->alias_argc; ++ndx)
735 {
736 char *p = argv[ndx];
737 argv[ndx] = strdup(p);
738 if (argv[ndx] == NULL) {
739 ui->error("cannot strdup <%s>", p);
740 return 1;
741 }
742 }
743 argc = new_argc;
744 pcmd->flags |= FUI_INVALID;
745 saw_alias = true;
746 goto retry;
747 }
748 if (pcmd->flags & FUI_STRING) {
749 char *pw0;
750 char *str = ui_parsew(s_cmd, &pw0);
751 argc = 2;
752
753 argv[1] = (char*) strdup (str);
754 }
755 if (pcmd->cmd_exe_func) { /*******/
756 if (saw_alias)
757 clear_invalid_aliases();
758 int rv = (pcmd->cmd_exe_func (NULL, argc, argv)); /*DO IT*/
759
760 ui_argv_free(argc, argv);
761 return rv;
762 } /*******/
763 }
764 }
765
766 if (saw_alias)
767 clear_invalid_aliases();
768 ui_argv_free(argc, argv);
769
770 ui->error("unknown command <%s>\n", ps);
771 return 1;
772}
773
774
775//==============================================================================
776// ====================== locally implemented ui functions ====================
777
778
779/////////////////////////////////////////////
780//
781// RUN
782//
783static int run_ui_cmd (void*, int argc, char **argv)
784{
785
786 if (!IN_STOP_STATE (blaze_run_state))
787 {
788 ui->error("not in stop state, use stop command first\n");
789 return 1;
790 }
791 if (argc != 1) {
792 ui->output("usage: run\nUse stepi <instruction count> to single step\n");
793 return 1;
794 }
795 SYSTEM_run_UI (); /* kicks off async running of cpu-sim threads */
796 return 1;
797}
798
799
800///////////////////////////////////////////////
801//
802// STOP
803//
804static int stop_ui_cmd (void*, int argc, char **argv)
805{
806 // we intentionally leave sync_on alone for now...
807 // that way "resume" can decide which way to go...
808
809 SYSTEM_stop_UI ();
810 return 1;
811}
812
813
814////////////////////////////////////////////
815//
816// STEPI <ninstrs>
817//
818// Step for n instructions all cpu's,
819// optionally show trace for vcpu: cpuid
820//
821// stepi [<nsteps>] [-t [<cpuid>]]
822//
823static int stepi_ui_cmd (void*, int argc, char **argv)
824{
825 int64_t ni = 1;
826
827 if (SYSTEM_in_execution_driven_mode()) {
828 ui->error("cannot do stepi in exec-driven mode\n");
829 return 1;
830 }
831
832 if (!IN_STOP_STATE (blaze_run_state)) {
833 ui->error("not in stop state\n");
834 return 1;
835 }
836
837 if ((argc > 1) && isdigit(argv[1][0]))
838 {
839 sscanf(argv[1], "%lli", &ni);
840 ni = strtoll(argv[1], NULL, 0);
841 if (ni == 0 ) ni = 1;
842 }
843
844 for (int i=1; i<argc; i++)
845 {
846 if ((strcmp(argv[i], "-t")==0) || (strcmp(argv[i], "-o")==0))
847 {
848 ui->error("to enable debug tracer use vdebug command\n");
849 return 1;
850 }
851 else if(strcmp(argv[i], "?")==0)
852 {
853 ui->output("usage: stepi [<ninstr>]\n");
854 return 1;
855 }
856 }
857
858 SYSTEM_stepi_UI (ni);
859 return 0;
860}
861
862
863static int stepc_ui_cmd(void *, int argc, char **argv)
864{
865 if (!SYSTEM_in_execution_driven_mode()) {
866 ui->error("stepc only supported in exec-driven mode\n");
867 return 1;
868 }
869
870 if (!IN_STOP_STATE(blaze_run_state))
871 {
872 ui->error("not in stop state, use stop command first\n");
873 return 1;
874 }
875 int64_t nc=1;
876 int i = 1;
877 while(i<argc) {
878 if (argv[i][0] == '?') {
879 ui->output("usage: stepc [<ncycles>]\n");
880 return 1;
881 } else {
882 errno = 0;
883 nc = strtoll(argv[i], NULL, 0);
884 if (errno) {
885 ui->error("invalid argument %s\n", argv[i]);
886 return 1;
887 }
888 i++;
889 if (!nc) nc = 1;
890 }
891 }
892
893 SYSTEM_stepc_UI(nc);
894 return 0;
895}
896
897
898///////////////////////////////////////////////
899//
900// STEPIM <ninstrs>
901//
902int stepim_ui_cmd (void*, int argc, char **argv)
903{
904 int64_t ni = 1;
905 if (argc > 1) sscanf(argv[1], "%lli", &ni);
906
907 struct timeval btime, etime;
908 gettimeofday ((struct timeval*)&btime, NULL);
909
910 stepi_ui_cmd (NULL, argc, argv);
911
912 gettimeofday ((struct timeval*)&etime, NULL);
913
914 {
915 uint64_t elapsed_usecs = etime.tv_sec * 1000000 + etime.tv_usec -
916 (btime.tv_sec * 1000000 + btime.tv_usec);
917 uint64_t icount = ni * the_arch.numcpus;
918
919 double instr_per_sec = (double)(icount) /
920 ((double)elapsed_usecs / 1000000.0);
921 ui->output("ic = %lld, usecs = %lld : %.4f \n",
922 icount, elapsed_usecs, instr_per_sec);
923 }
924 return 0;
925}
926
927
928
929///////////////////////////////////////////////////
930//
931// STEPT <usecs> <seqnum>
932//
933
934static volatile int64_t stept_usecs = 1;
935static volatile int64_t stept_seqnum = -1; /* most recent request */
936static volatile int64_t done_seqnum = -1; /* most recent reply */
937
938extern "C" {
939static void stept_done_callback (void * x)
940{
941 int res;
942 char buf[max_cmd_length];
943
944 if (sync_fd != -1 && sync_on) {
945 if (stept_seqnum != -1) {
946 sprintf (buf, "done %lld\n", stept_seqnum);
947 } else {
948 sprintf (buf, "done\n");
949 }
950 res = write (sync_fd, buf, strlen(buf)); /*DONE*/
951
952 if (res != strlen(buf)) {
953 ui->perror ("sync-done writemsg error:");
954 }
955 done_seqnum = stept_seqnum;
956 }
957}
958};
959
960static int SYNCDEBUG = 0;
961
962int stept_ui_cmd (void*, int argc, char **argv)
963{
964
965 if (!IN_GTWAIT_STATE(blaze_run_state)) {
966 ui->error("not in sync-mode\n");
967 return 1;
968 }
969
970 if (argc > 1) sscanf(argv[1], "%lli", &stept_usecs);
971 if (argc > 2) sscanf(argv[2], "%lli", &stept_seqnum);
972 else stept_seqnum = -1;
973
974 if (SYNCDEBUG)
975 ui->output("sync[%lld]: for %lld-usecs, now=%lld\n",
976 stept_seqnum, stept_usecs, SYSTEM_get_time());
977
978 SYSTEM_stept_UI (stept_usecs, stept_seqnum, stept_done_callback);
979
980 return 0;
981}
982
983
984/////////////////////////////////////////////
985//
986// RESUME
987//
988static int resume_ui_cmd (void*, int argc, char **argv)
989{
990 if (!IN_STOP_STATE (blaze_run_state))
991 {
992 ui->error("not in stop state, use stop command first\n");
993 return 1;
994 }
995 if (sync_on) {
996 SYSTEM_syncon_UI ();
997 } else {
998 SYSTEM_run_UI ();
999 }
1000 return 0;
1001}
1002
1003
1004///////////////////////////////////////////////
1005//
1006// QUIT
1007//
1008static int quit_ui_cmd (void*, int argc, char **argv)
1009{
1010 if (IN_RUN_STATE (blaze_run_state))
1011 stop_ui_cmd (NULL, 0, NULL);
1012 SYSTEM_quit_UI ();
1013 return 0;
1014}
1015
1016
1017///////////////////////////////////////////////
1018//
1019// LOAD <pa> <filename> <va> // was totally simplified by Tycho
1020//
1021
1022extern void load_elf64 (char *filename, uint64_t base_pa, uint64_t base_va);
1023
1024extern void schizo_ext_init (uint64_t , uint64_t);
1025
1026static int load_ui_cmd (void*, int argc, char **argv)
1027{
1028 char *filename;
1029 uint64_t base_pa, addr, size, seg_size;
1030 uint64_t base_va;
1031 int ret, zero_pad = 0, create_lbl = 0;
1032 bool_t load_image = FALSE;
1033
1034 if (mm1 == NULL)
1035 {
1036 ui->error("RAM object is not ready yet!\n");
1037 return 1;
1038 }
1039
1040 if (BLAZE_restore_from_checkpoint())
1041 {
1042 // don't load the image again, it should be in mem dump already
1043 if (argc>=2)
1044 ui->error("<%s> image should be already in memory \n", argv[2]);
1045 return 1;
1046 }
1047
1048 if ((argc == 3) && (strcmp(argv[1], "image") == NULL))
1049 {
1050 load_image = TRUE;
1051 if (mm1->load(argv[2]) !=0 )
1052 {
1053 ui->error("Error in <%s> memory image\n ", argv[2]);
1054 return 1;
1055 }
1056 else
1057 {
1058 return 1;
1059 }
1060 }
1061
1062 // Format will be 'load bin file_name start_addr'
1063 if ((argc == 4) && (strcmp(argv[1], "bin") == NULL))
1064 {
1065 ret = sscanf (argv[3], "%llx", &addr);
1066 if (mm1->load_bin(argv[2], addr) !=0 )
1067 {
1068 ui->error("Error in <%s> bin image\n ", argv[2]);
1069 return 1;
1070 }
1071 return 1;
1072 }
1073
1074 if (argc < 4) {
1075 ui->error("check LOAD command format\n");
1076 return 1;
1077 }
1078
1079 ret = sscanf (argv[1], "%lli", &base_pa);
1080 if (ret != 1) {
1081 ui->error("check PA arg <%s>\n", argv[1]);
1082 return 1;
1083 }
1084
1085 ret = sscanf (argv[3], "%lli", &base_va);
1086 if (ret != 1) {
1087 ui->error("check VA arg <%s>\n", argv[3]);
1088 return 1;
1089 }
1090
1091 filename = (char*)malloc (strlen(argv[2]) + 16);
1092 sscanf (argv[2], "%s", filename);
1093
1094 load_elf64(filename, base_pa, base_va);
1095 return 1;
1096
1097}
1098
1099
1100///////////////////////////////////////////////
1101//
1102// FILE <filename>
1103//
1104
1105static int file_ui_cmd (void*, int argc, char **argv)
1106{
1107 if (argc != 2) {
1108 ui->error("UI (file): format error");
1109 return 1;
1110 }
1111
1112 FILE* fp = fopen(argv[1],"r");
1113 if (!fp) {
1114 ui->error("Can't open <%s>", argv[1]);
1115 return 1;
1116 }
1117
1118 char line[max_cmd_length];
1119
1120 while (fgets(line,max_cmd_length,fp))
1121 exec_cmd(line);
1122
1123 fclose(fp);
1124
1125 return 0;
1126}
1127
1128
1129///////////////////////////////////////////////
1130//
1131// CONF <name> <value>
1132//
1133//
1134
1135extern void complete_cfg ();
1136extern uint8_t get_platform_index (char *s);
1137
1138static void print_new_cpi ()
1139{
1140 if (g_vcpu[0] != NULL)
1141 {
1142 for (int i=0; i<=g_vcpu_id_max; i++)
1143 {
1144 Vcpu *vcpu = get_vcpu(i);
1145 if (!vcpu)
1146 continue;
1147
1148 vcpu->config.cpi = ((double)(vcpu->config.stickincr)) * (vcpu->config.cpufreq)
1149 / (vcpu->config.loopticks) / (vcpu->config.stickfreq);
1150 ui->output("%s new cpi (=stinc*cpufq/ltick/sysfq) = %6.3f\n",
1151 vcpu->config.name, vcpu->config.cpi);
1152 }
1153 }
1154}
1155
1156
1157static int conf_ui_cmd (void*, int argc, char **argv)
1158{
1159 uint8_t idx_to_plist;
1160 char s[max_cmd_length];
1161 uint64_t pa;
1162 char *default_s = (char*)"sun4u";
1163
1164 static bool numcores_initialized = FALSE;
1165 static bool numcpus_initialized = FALSE;
1166
1167 if (argc == 1)
1168 {
1169 if (the_arch.cmp_mode) {
1170 ui->output("CMP mode: %s\n", the_arch.cmp_mode?"true":"false");
1171 ui->output("Number of cores: %d\n", the_arch.numcores);
1172 ui->output("CPUs per core: %d\n", the_arch.cpus_per_core);
1173 }
1174#if defined (CHPLUS_OBP) || defined(CHPLUS) || defined(CHEETAH_OBP) || defined(CHEETAH)
1175 ui->output("mmutype: %s\n", the_arch.mmutype);
1176 ui->output("flags: 0x%x \n", the_arch.arch_flags);
1177#endif
1178 ui->output("numcpu: %d \n", the_arch.numcpus);
1179 ui->output("ramsize: 0x%llx bytes (%lld MB) \n",
1180 the_arch.ramsize, the_arch.ramsize >> 20);
1181 ui->output("cpu per thread: %d\n", the_arch.cpus_per_thread);
1182 if (the_arch.umips == the_arch.mips && the_arch.kmips == the_arch.mips)
1183 ui->output("mips: %lld\n\n", the_arch.mips);
1184 else
1185 ui->output("umips: %lld\n"
1186 "kmips: %lld\n\n", the_arch.umips, the_arch.kmips);
1187 ui->output("cpufreq: %llu\n", the_arch.cpu_freq);
1188 ui->output("stickfreq: %llu\n", the_arch.stick_freq);
1189
1190 ui->output("conf numthreads = %d\n", the_arch.numthreads);
1191 ui->output("conf roundrobin = %d\n", the_arch.roundrobin);
1192 }
1193 else if (strcmp (argv[1], "ramsize") == NULL)
1194 {
1195 if (argc == 2)
1196 {
1197 ui->output ("ramsize: 0x%llx bytes (%lld MB) \n",
1198 the_arch.ramsize, the_arch.ramsize >> 20);
1199 return 1;
1200 }
1201 char *mfile_name = NULL;
1202 if (argc > 2)
1203 {
1204 char *p;
1205 uint64_t lval = strtoll (argv[2], &p, 0);
1206 if (*p == 'K')
1207 lval <<= 10;
1208 if (*p == 'M')
1209 lval <<= 20;
1210 the_arch.ramsize = lval;
1211 the_arch.ramsizeS = (char*)strdup(argv[2]);
1212 }
1213
1214 if ((argc > 3) && !BLAZE_restore_from_checkpoint())
1215 {
1216 mfile_name = argv[3];
1217 }
1218
1219 // mem object is global for entire system
1220 if (mm1)
1221 {
1222 ui->error("RAM object is already created !!");
1223 return 0;
1224 }
1225 else
1226 {
1227 mm1 = new SMemory (the_arch.ramsize);
1228 }
1229
1230 if ( !mm1 || !mm1->init(mfile_name) )
1231 {
1232 ui->error("cannot allocate mem object size of %llx\n",the_arch.ramsize );
1233 quit_simulation();
1234 }
1235
1236 if (!BLAZE_restore_from_checkpoint())
1237 {
1238 pa = 0x1c;
1239 LO_W(pa) &= ~7;
1240#ifdef V5_FAKEPROM
1241 memwrite64s_nl(mm1, pa, the_arch.ramsize);
1242#endif
1243 }
1244 the_arch.arch_flags |= FA_RAMSIZE;
1245 // TO DO: why do we need these flags?
1246 the_arch.arch_flags |= FA_STICKINCR|FA_TLBSIZE|FA_PLATFORM;
1247
1248 }
1249#ifdef MEMORY_SEGMENTED
1250 else if (strcmp (argv[1], "memseg") == NULL)
1251 {
1252 assert(argc >= 5 && argc <= 6);
1253 char *mfile_name = NULL;
1254 const char * name = argv[2];
1255 uint64_t base = strtoll(argv[3],0,0);
1256 uint64_t size;
1257 {
1258 char *p;
1259 char q[128];
1260 size = strtoll (argv[4], &p, 0);
1261 if (*p == 'K')
1262 size <<= 10;
1263 if (*p == 'M')
1264 size <<= 20;
1265 the_arch.ramsize += size;
1266 the_arch.ramsizeS = strdup(ulltostr(the_arch.ramsize,q));
1267 }
1268
1269 if ((argc > 5) && !BLAZE_restore_from_checkpoint())
1270 {
1271 mfile_name = argv[5];
1272 }
1273
1274 if(!mm1)
1275 mm1 = new SMemory ();
1276 if (!mm1->addMem(name,base,size,mfile_name) )
1277 {
1278 ui->error("memseg: cannot allocate mem object size of %llx\n",size );
1279 quit_simulation();
1280 }
1281 if (!BLAZE_restore_from_checkpoint())
1282 {
1283 pa = 0x1c;
1284 LO_W(pa) &= ~7;
1285#ifdef V5_FAKEPROM
1286 memwrite64s_nl(mm1, pa, the_arch.ramsize);
1287#endif
1288 }
1289 the_arch.arch_flags |= FA_RAMSIZE;
1290 // TO DO: why do we need these flags?
1291 the_arch.arch_flags |= FA_STICKINCR|FA_TLBSIZE|FA_PLATFORM;
1292
1293 }
1294#endif
1295 else if (strcmp(argv[1], "mips") == 0)
1296 {
1297 if (argc > 2) {
1298 sscanf (argv[2], "%lld", &the_arch.mips);
1299 the_arch.kmips = the_arch.mips;
1300 the_arch.umips = the_arch.mips;
1301 }
1302 else {
1303 if (the_arch.umips == the_arch.kmips)
1304 ui->output("mips: %lld\n\n", the_arch.umips);
1305 else
1306 ui->output("kmips: %lld, umips: %lld\n\n",
1307 the_arch.kmips, the_arch.umips);
1308 }
1309 }
1310 else if (strcmp(argv[1], "kmips") == 0)
1311 {
1312 if (argc > 2)
1313 sscanf (argv[2], "%lld", &the_arch.kmips);
1314 ui->output("conf kmips = %lld\n", the_arch.kmips);
1315 }
1316 else if (strcmp(argv[1], "umips") == 0)
1317 {
1318 if (argc > 2)
1319 sscanf (argv[2], "%lld", &the_arch.umips);
1320 ui->output("conf umips = %lld\n", the_arch.umips);
1321 }
1322 else if (strcmp(argv[1], "cmips") == 0)
1323 {
1324 if (argc > 2)
1325 sscanf (argv[2], "%lld", &the_arch_cmips);
1326 if (argc > 3)
1327 sscanf (argv[3], "%d", &the_arch_ccntx);
1328 if (the_arch_ccntx)
1329 ui->output("conf cmips = %lld for context %d\n",
1330 the_arch_cmips, the_arch_ccntx);
1331 else
1332 ui->output("conf cmips is ineffective when context is zero\n");
1333 }
1334
1335 else if (strcmp (argv[1], "cpu_per_thread") == 0)
1336 {
1337 if (argc > 2) {
1338 sscanf (argv[2], "%d", &the_arch.cpus_per_thread);
1339 cpu_enable_changed = true;
1340 if (g_nvcpu)
1341 the_arch.numthreads = g_nvcpu / the_arch.cpus_per_thread;
1342 }
1343 if (g_nvcpu) {
1344 ui->output ("conf cpu_per_thread = %d (numthreads = %d)\n",
1345 the_arch.cpus_per_thread, the_arch.numthreads);
1346 } else
1347 ui->output ("conf cpu_per_thread = %d\n", the_arch.cpus_per_thread);
1348 }
1349 else if (strcmp (argv[1], "numthreads") == 0)
1350 {
1351 if (argc > 2) {
1352 sscanf (argv[2], "%d", &the_arch.numthreads);
1353 cpu_enable_changed = true;
1354 if (g_nvcpu)
1355 the_arch.cpus_per_thread = g_nvcpu / the_arch.numthreads;
1356 }
1357 if (g_nvcpu) {
1358 ui->output ("conf numthreads = %d (cpu_per_thread = %d)\n",
1359 the_arch.numthreads, the_arch.cpus_per_thread);
1360 } else
1361 ui->output ("conf numthreads = %d\n", the_arch.numthreads);
1362 }
1363
1364
1365
1366
1367
1368 else if (strcmp (argv[1], "roundrobin") == 0)
1369 {
1370 if (argc > 2)
1371 sscanf (argv[2], "%d", &the_arch.roundrobin);
1372 ui->output ("conf roundrobin = %d\n", the_arch.roundrobin);
1373 }
1374
1375
1376
1377
1378
1379 else if (argc == 4)
1380 {
1381 uint32_t id, ret;
1382 double fv;
1383 float ffv;
1384#if defined (CHPLUS_OBP) || defined(CHPLUS) || defined(CHEETAH_OBP) || defined(CHEETAH)
1385 if (strcmp (argv[1], "loopticks") == NULL)
1386 {
1387 ui->warning("loopticks has been dpecrecated. Use conf mips\n");
1388 Vcpu *vcpu = get_vcpu_by_name ( argv[3] );
1389 if (vcpu != NULL)
1390 {
1391 int temp;
1392 sscanf (argv[2], "%i", &temp);
1393 if (temp >= vcpu->config.stickincr)
1394 {
1395 vcpu->config.loopticks = temp;
1396 print_new_cpi ();
1397 }
1398 else
1399 {
1400 ui->error("Ignored: loopticks >= stickincr, limitation\n");
1401 }
1402 }
1403 else
1404 {
1405 ui->error("Ignored: unknow cpu instance. \n");
1406 }
1407 }
1408 else if (strcmp (argv[1], "stickincr") == NULL)
1409 {
1410 ui->warning("stickincr has been dpecrecated. Use conf mips\n");
1411 Vcpu *vcpu = get_vcpu_by_name ( argv[3] );
1412 if (vcpu != NULL)
1413 {
1414 int temp;
1415 sscanf (argv[2], "%i", &temp );
1416 vcpu->config.stickincr = temp;
1417 print_new_cpi ();
1418 }
1419 else
1420 {
1421 ui->error("Ignored: unknow cpu instance. \n");
1422 }
1423
1424 }
1425 else if (strcmp(argv[1], "cpi") == NULL)
1426 {
1427 // conf cpi N xx.xx
1428
1429 ui->error("SAM-GTSync doesn't support cpi feature \n");
1430 if (g_vcpu[0] == NULL)
1431 {
1432 ui->error("conf cpi: move this line to be after cpu is created.\n");
1433 exit (1);
1434 }
1435 ret = sscanf (argv[2], "%i", &id);
1436 if ( (ret != 1) )
1437 {
1438 ui->error("wrong cpu id argument <%s>\n", argv[2]);
1439 return 0;
1440 }
1441 Vcpu * vcpu = get_vcpu(id);
1442 if(!vcpu){
1443 ui->error("wrong cpu id argument <%s>\n", argv[2]);
1444 return 0;
1445 }
1446 ret = sscanf (argv[3], "%f", &ffv);
1447 fv = ffv;
1448 if (ret != 1)
1449 {
1450 ui->error("wrong cpi argument <%s>\n", argv[3]);
1451 return 0;
1452 }
1453 ui->output("cpu%d cpi=%f \n", id, fv);
1454
1455 vcpu->config.cpi = fv;
1456 the_arch.cpi = TRUE;
1457
1458 }
1459 else
1460 {
1461 ui->error("Ignored: wrong parameter\n");
1462 }
1463#endif
1464 }
1465 else if (argc == 3)
1466 {
1467 // TO DO: why do we need these flags?
1468 the_arch.arch_flags |= FA_STICKINCR|FA_TLBSIZE|FA_PLATFORM;
1469
1470
1471 //
1472 // TODO : some of these arguments should be written into thw memory after
1473 // LOAD fakeprom ufsboot
1474 // Not necessarily. All these arguments should be put into 0 page
1475 // so it can be done right in instant way
1476
1477 if (strcmp (argv[1], "numcores") == NULL)
1478 {
1479 int rv = sscanf(argv[2], "%i", &the_arch.numcores);
1480 if (rv != 1 || !the_arch.numcores)
1481 {
1482 ui->error("conf command: invalid arg %s\n", argv[2]);
1483 exit(1);
1484 }
1485 the_arch.cmp_mode = true;
1486 if (numcpus_initialized)
1487 {
1488 the_arch.cpus_per_core = the_arch.numcpus/the_arch.numcores;
1489 // assume divisible
1490 if (the_arch.numcpus % the_arch.numcores)
1491 {
1492 ui->error("numcpus %d not divisible by numcores %d\n", the_arch.numcpus, the_arch.numcores);
1493 exit(1);
1494 }
1495 }
1496 numcores_initialized = TRUE;
1497 }
1498 else if (strcmp (argv[1], "numcpu") == NULL)
1499 {
1500 sscanf (argv[2], "%i", &the_arch.numcpus);
1501
1502 pa = 0x14;
1503 LO_W(pa) &= ~3;
1504#ifdef V5_FAKEPROM
1505 memwrite32u_nl(mm1, pa, the_arch.numcpus);
1506#endif
1507
1508 the_arch.arch_flags |= FA_NCPU;
1509 if (numcores_initialized)
1510 {
1511 the_arch.cpus_per_core = the_arch.numcpus/the_arch.numcores;
1512 // assume divisible
1513 if (the_arch.numcpus % the_arch.numcores)
1514 {
1515 ui->error("numcpus %d not divisible by numcores %d\n", the_arch.numcpus, the_arch.numcores);
1516 exit(1);
1517 }
1518 }
1519 numcpus_initialized = TRUE;
1520
1521 }
1522 else if (strcmp (argv[1], "nwins") == NULL)
1523 {
1524 sscanf (argv[2], "%i", &the_arch.nwins);
1525 the_arch.arch_flags |= FA_NWINS;
1526 }
1527 else if (strcmp (argv[1], "mmutype") == NULL)
1528 {
1529 sscanf (argv[2], "%s", s);
1530 the_arch.mmutype = (char*)strdup(s);
1531 the_arch.arch_flags |= FA_MMUTYPE;
1532 }
1533 else if (strcmp (argv[1], "cputype") == NULL)
1534 {
1535 sscanf (argv[2], "%s", s);
1536 the_arch.mmutype = (char*)strdup(s);
1537 the_arch.arch_flags |= FA_MMUTYPE;
1538 }
1539 else if (strcmp (argv[1], "tlbsize") == NULL)
1540 {
1541 sscanf (argv[2], "%i", &the_arch.tlbsize);
1542 the_arch.arch_flags |= FA_TLBSIZE;
1543 }
1544#if defined (CHPLUS_OBP) || defined(CHPLUS) || defined(CHEETAH_OBP) || defined(CHEETAH)
1545 else if (strcmp (argv[1], "loopticks") == NULL)
1546 {
1547 ui->warning("loopticks has been dpecrecated in favor of mips\n");
1548
1549 int temp;
1550 sscanf (argv[2], "%i", &temp);
1551
1552 // set loopticks for all vcpu's
1553 if (g_vcpu[0] != NULL)
1554 {
1555 if (temp >= the_arch.stickincr)
1556 {
1557 for (int i=0; i<=g_vcpu_id_max; i++)
1558 {
1559 Vcpu *vcpu = get_vcpu(i);
1560 if (!vcpu)
1561 continue;
1562 vcpu->config.loopticks = temp;
1563 }
1564
1565 the_arch.loopticks = temp;
1566 the_arch.loopticks_cp = the_arch.loopticks;
1567
1568 print_new_cpi ();
1569 } else {
1570 ui->error("Ignored: loopticks >= stickincr, limitation\n");
1571 }
1572 }
1573 }
1574 else if (strcmp (argv[1], "stickincr") == NULL)
1575 {
1576 ui->warning("stickincr has been dpecrecated in favor of mips\n");
1577
1578 int temp;
1579 sscanf (argv[2], "%i", &temp);
1580
1581 // set stickincr for all vcpu's
1582 if (g_vcpu[0] != NULL)
1583 {
1584 for (int i=0; i<=g_vcpu_id_max; i++)
1585 {
1586 Vcpu *vcpu = get_vcpu(i);
1587 if (!vcpu)
1588 continue;
1589 vcpu->config.stickincr = temp;
1590 }
1591
1592 the_arch.stickincr = temp;
1593
1594 print_new_cpi ();
1595 }
1596 }
1597#endif
1598 else if (strcmp (argv[1], "cpufreq") == NULL)
1599 {
1600 if ((the_arch.arch_flags & FA_FREQ) == 0)
1601 {
1602 sscanf (argv[2], "%llu", &the_arch.cpu_freq);
1603 pa = 0x24;
1604 LO_W(pa) &= ~7;
1605#ifdef V5_FAKEPROM
1606 memwrite64s_nl(mm1, pa, the_arch.cpu_freq);
1607#endif
1608 the_arch.arch_flags |= FA_FREQ;
1609 print_new_cpi ();
1610 }
1611 else
1612 {
1613 ui->error("cannot change cpufreq \n");
1614 }
1615 }
1616 else if (strcmp (argv[1], "stickfreq") == NULL)
1617 {
1618 if ((the_arch.arch_flags & FA_SFREQ) == 0)
1619 {
1620 sscanf (argv[2], "%llu", &the_arch.stick_freq);
1621 pa = 0x28;
1622 LO_W(pa) &= ~7;
1623#ifdef V5_FAKEPROM
1624 memwrite64s_nl(mm1, pa, the_arch.stick_freq);
1625#endif
1626 the_arch.arch_flags |= FA_SFREQ;
1627 print_new_cpi ();
1628 }
1629 else
1630 {
1631 // allow end user to change the stick freq. The reason
1632 // this may be useful is when we want to reach a particular
1633 // simulation state fast. Higher stick frequency(than what is
1634 // known to Solaris) would result in time moving faster from
1635 // Solaris's perspective, making timeouts faster. Another
1636 // sideeffect would be that CPI would change by a factor
1637 // of sam_stick/solaris_stick.
1638 ui->warning("changing stickfreq \n"
1639 "stick freq in simulated Solaris(prtconf -pv), should be same as in SAM\n"
1640 "cpi observed from Solaris will change to old_cpi*sam_stickfreq/sol_stickfreq\n");
1641 sscanf (argv[2], "%llu", &the_arch.stick_freq);
1642 for(int i = 0; i <= g_vcpu_id_max; i++)
1643 {
1644 Vcpu *vcpu = get_vcpu(i);
1645 if (!vcpu)
1646 continue;
1647
1648 vcpu->config.stickfreq = the_arch.stick_freq;
1649 }
1650 }
1651 }
1652 else if (strcmp (argv[1], "skipmp") == NULL)
1653 {
1654 ui->warning("skipmp has been dpecrecated. Value will be ignored \n");
1655 sscanf (argv[2], "%i", &the_arch.skip_mp);
1656 }
1657 else if (strcmp (argv[1], "blockmp") == NULL)
1658 {
1659 ui->warning("blockmp has been dpecrecated. Value will be ignored \n");
1660 sscanf (argv[2], "%i", &the_arch.block_mp);
1661 }
1662#ifdef V5_FAKEPROM
1663 else if (strcmp (argv[1], "platform") == NULL)
1664 {
1665 sscanf (argv[2], "%s", s);
1666 the_arch.platform= (char *) strdup(s);
1667 // convert platform to index to pass down to fakeprom
1668 idx_to_plist = get_platform_index(the_arch.platform);
1669 pa = 0x30;
1670 memwrite8u_nl(mm1, pa, idx_to_plist);
1671 the_arch.arch_flags |= FA_PLATFORM;
1672 }
1673#endif
1674
1675#ifdef V5_FAKEPROM
1676 else if (strcmp (argv[1], "bootpath") == NULL)
1677 {
1678 strcpy (bootpath, argv[2]);
1679 int boot_aid,boot_dev,boot_bus;
1680 char boot_part[3];
1681 boot_disk_id = 0; //lun of scsi disk. always 0.
1682 // boot_ctrl_id set from parse_arg on sysconf scsi line
1683 // fakeprom doesn;t need it.
1684 // boot path is of this form - /pci@aid,[6|7]00000/scsi@dev/disk@targ,lun:slice
1685 int result = sscanf(argv[2], "/pci@%x,%d/scsi@%d/disk@%x,0:%s",
1686 &boot_aid,&boot_bus, &boot_dev, &boot_target_id, boot_part);
1687 if (result != 5) {
1688 ui->error("unknown parameter <%s> for boot path", argv[2]);
1689 exit(1);
1690 }
1691 boot_bus = (boot_bus == 7000000) ? 1:0;
1692 boot_part_id = boot_part[0] - 'a';
1693 // the pa used below comes from struct fkparam in fakeprom.h
1694 pa = 0x33;
1695 memwrite8u_nl(mm1, pa, (uint8_t)boot_dev);//pci device number of scsi hba on sysconf line
1696 pa = 0x34;
1697 memwrite8u_nl(mm1, pa, (uint8_t)boot_target_id);//scsi disk target id, specified from scsidisk.init
1698 pa = 0x35;
1699 memwrite8u_nl(mm1, pa, (uint8_t)boot_part_id);//parition id of scsi disk, from scsidisk.init
1700 pa = 0x36;
1701 memwrite8u_nl(mm1, pa, (uint8_t)boot_disk_id);//lun of scsi disk. always 0 for our supported disks, redundant info currently
1702 pa = 0x4a;
1703 memwrite8u_nl(mm1, pa, (uint8_t)boot_aid);//aid of schizo, to which scsi hba connects to
1704 pa = 0x4b;
1705 memwrite8u_nl(mm1, pa, (uint8_t)boot_bus);//busA=0 busB=1. to help fakeprom decide whether boot path prefix is
1706 // pci@<aid>,600000 or pci@<aid>,700000
1707 }
1708#endif
1709 else if (strcmp (argv[1], "DC") == NULL)
1710 {
1711 sscanf (argv[2], "%i", &the_arch.numDCs);
1712 ui->output("%d DC on board \n", the_arch.numDCs);
1713 }
1714 else if (strcmp (argv[1], "NIC") == NULL)
1715 {
1716 sscanf (argv[2], "%i", &the_arch.numNICs);
1717 pa = 0x48;
1718#ifdef V5_FAKEPROM
1719 memwrite8u_nl(mm1, pa, the_arch.numNICs);
1720#endif
1721 }
1722 else if (strcmp (argv[2], "done") == NULL)
1723 {
1724 if (strcmp (argv[1], "cpu") == NULL) {
1725 ui->error("unknown parameter <%s> ", argv[1]);
1726 return 1;
1727 }
1728 }
1729 else
1730 {
1731 ui->error("unknown parameter <%s> ", argv[1]);
1732 }
1733
1734 } /*end-if-argc*/
1735
1736 if (the_arch.platform == NULL)
1737 // set the_arch.platform to sun4u as default
1738 the_arch.platform = strdup(default_s);
1739
1740 return 1;
1741}
1742
1743
1744/*
1745 * instrumentation to see if simulator U/K sync-intervals ratio matches
1746 * the actual U/K instructions ratio.
1747 * also calculates the simulated mips using simulated time (stick-interrupts).
1748 */
1749
1750static int mips_ui_cmd (void*, int argc, char **argv)
1751{
1752 int ncpus = SYSTEM_get_ncpu(), n = 0;
1753 int64_t instrs, Uinstrs, Kinstrs;
1754 int64_t intervals, Uintervals, Kintervals;
1755 int64_t stIntrpts;
1756
1757 ui->output("\n");
1758
1759
1760 // total instructions simulated, all cpus
1761 //
1762 Uinstrs = atomic_and_64 (& WorkerThread::u_instrs, 0);
1763 Kinstrs = atomic_and_64 (& WorkerThread::k_instrs, 0);
1764 instrs = Uinstrs + Kinstrs;
1765 if (instrs == 0)
1766 ui->output("instructions: %12d\n", 0);
1767 else
1768 ui->output(
1769 "instructions: %12lld, %12lld-Usr, %12lld-Ker; (%d/%d)\n",
1770 (Uinstrs+Kinstrs)/ncpus, Uinstrs/ncpus, Kinstrs/ncpus,
1771 (int)((Uinstrs*100+50)/instrs),
1772 (int)((Kinstrs*100+50)/instrs));
1773
1774
1775 // total 1-usec time sync intervals, all cpus
1776 //
1777 Uintervals = atomic_and_64 (& WorkerThread::u_intervals, 0);
1778 Kintervals = atomic_and_64 (& WorkerThread::k_intervals, 0);
1779 intervals = Uintervals + Kintervals;
1780 if (intervals == 0)
1781 ui->output("sync-intervals: %12d\n", 0);
1782 else
1783 ui->output(
1784 "sync-intervals: %12lld, %12lld-Usr, %12lld-Ker; (%d/%d)\n",
1785 intervals/ncpus, Uintervals/ncpus, Kintervals/ncpus,
1786 (int)((Uintervals*100+50)/intervals),
1787 (int)((Kintervals*100+50)/intervals));
1788
1789
1790 // average per-cpu mips, in simulated time not wall clock time
1791 //
1792 if (intervals == 0)
1793 ui->output("effective-mips: %12d\n", 0);
1794 else
1795 ui->output("effective-mips: %12lld\n",
1796 instrs / intervals);
1797
1798
1799 ui->output("\n");
1800 return 1;
1801}
1802
1803
1804// this function is called by:
1805// fc_mod.cc
1806// scsi_mod.cc
1807//
1808uint8_t send_diskinfo_to_fakeprom()
1809{
1810 uint64_t pa;
1811#ifdef V5_FAKEPROM
1812 pa = 0x31;
1813 memwrite8u_nl(mm1, pa, (uint8_t)SYSTEM_get_scsi_disk_enable_flag()
1814 | (uint8_t)SYSTEM_get_fc_disk_enable_flag() <<1);
1815
1816 pa = 0x32;
1817 memwrite8u_nl(mm1, pa, (uint8_t)SYSTEM_get_scsi_boot_enable_flag()
1818 | (uint8_t)SYSTEM_get_fc_boot_enable_flag() <<1);
1819
1820 pa = 0x49;
1821 memwrite8u_nl(mm1, pa, (uint8_t)SYSTEM_get_ce_enable_flag());
1822#endif
1823 return 0;
1824}
1825
1826
1827// added for platform support, to pass down to fakeprom
1828const char *os_platform_lists[] = { // fakeprom must have the same table
1829 "sun4u", // default settting
1830 "FJSV,GPUU",
1831 "NATE,s-Note_737S",
1832 "NATE,s-Note_747S",
1833 "NATE,s-Note_777S",
1834 "sun4u",
1835 "SUNW,Netra-T12",
1836 "SUNW,Netra-T4",
1837 "SUNW,Sun-Blade-100",
1838 "SUNW,Sun-Blade-1000",
1839 "SUNW,Sun-Fire",
1840 "SUNW,Sun-Fire-15000",
1841 "SUNW,Sun-Fire-280R",
1842 "SUNW,Sun-Fire-480R",
1843 "SUNW,Sun-Fire-880",
1844 "SUNW,Ultra-1",
1845 "SUNW,Ultra-1-Engine",
1846 "SUNW,Ultra-2",
1847 "SUNW,Ultra-250",
1848 "SUNW,Ultra-30",
1849 "SUNW,Ultra-4",
1850 "SUNW,Ultra-5_10",
1851 "SUNW,Ultra-60",
1852 "SUNW,Ultra-80",
1853 "SUNW,UltraAX-e",
1854 "SUNW,UltraAX-e2",
1855 "SUNW,UltraAX-i2",
1856 "SUNW,UltraAX-MP",
1857 "SUNW,Ultra-Enterprise",
1858 "SUNW,Ultra-Enterprise-10000",
1859 "SUNW,UltraSPARCengine_CP-20",
1860 "SUNW,UltraSPARCengine_CP-40",
1861 "SUNW,UltraSPARCengine_CP-60",
1862 "SUNW,Sun-Fire-V440",
1863 "nomore", // no found
1864};
1865
1866uint8_t get_platform_index(char *s)
1867{
1868 int retval = 0;
1869 while (strcmp (s, os_platform_lists[retval]) != NULL) {
1870 if (strcmp (os_platform_lists[retval], "nomore") == NULL)
1871 return 0; // if not found, set to default "sun4u"
1872 retval++;
1873 }
1874
1875 return retval;
1876}
1877
1878
1879///////////////////////////////////////////////
1880//
1881// WRITE <> <>
1882//
1883static int write_ui_cmd (void*, int argc, char **argv)
1884{
1885 uint64_t paddr, value;
1886 int ret;
1887
1888 if (argc != 4) {
1889 ui->error("Check command format");
1890 return(0);
1891 }
1892
1893 ret = sscanf (argv[2], "%lli", &paddr);
1894 if (ret != 1) {
1895 ui->error("wrong address");
1896 return 0;
1897 }
1898 ret = sscanf (argv[3], "%lli", &value);
1899 if (ret != 1) {
1900 ui->error("wrong value");
1901 return 0;
1902 }
1903
1904 if (mm1 == NULL) {
1905 ui->error("RAM object is not ready yet!");
1906 return 0;
1907 }
1908
1909 if (strcmp(argv[1], "word") == 0) {
1910 LO_W(paddr) &= ~3;
1911 memwrite32u_nl(mm1, paddr, value);
1912 } else if (strcmp(argv[1], "lword") == 0) {
1913 LO_W(paddr) &= ~7;
1914 memwrite64s_nl(mm1, paddr, value);
1915 } else if (strcmp(argv[1], "hword") == 0) {
1916 LO_W(paddr) &= ~1;
1917 memwrite16u_nl(mm1, paddr, value);
1918 } else if (strcmp(argv[1], "byte") == 0) {
1919 memwrite8u_nl(mm1, paddr, value);
1920 } else {
1921 ui->error("wrong format (size)");
1922 return 0;
1923 }
1924 return 1;
1925}
1926
1927
1928///////////////////////////////////////////////
1929//
1930// CONSOLE SEND "string"
1931//
1932//typedef void (*serial_send)(void *, char *);
1933
1934extern serialInterface * systemConsole;
1935
1936#ifdef V5_FAKEPROM
1937int static cs_ui_cmd (void*, int argc, char **argv)
1938{
1939 char *str = NULL;
1940 if (argc < 2) {
1941 ui->error("command format error!\n");
1942 return 0;
1943 }
1944
1945 if(systemConsole == 0){
1946 ui->error("system console not yet initialized\n");
1947 return 0;
1948 }
1949
1950 str = extract_string(argv[1]);
1951
1952 systemConsole->chars_send(str,systemConsole->portH);
1953 free(str);
1954 return 1;
1955}
1956#endif
1957
1958
1959///////////////////////////////////////////////
1960//
1961// RDT <filename> # redirect stdout
1962//
1963//
1964/*static?*/ int rdt_ui_cmd (void*, int argc, char **argv)
1965{
1966
1967 if (argc == 1) {
1968 // redirect back (FILE->stdout)
1969 redirect_back ();
1970 }
1971 else if (argc == 2) {
1972 FILE * fp = fopen (argv[1], "w");
1973 if (fp == NULL) {
1974 ui->perror (argv[1]);
1975 return 0;
1976 }
1977 if (redirect_stdout (fileno(fp))) {
1978 ui->output("STDOUT redirected to <%s>\n", argv[1]);
1979 }
1980 }
1981 else {
1982 ui->error("wrong RDT command format\n");
1983 }
1984 return 1;
1985}
1986
1987
1988///////////////////////////////////////////////
1989//
1990// ON STOP <string>
1991//
1992/*static?*/ int on_ui_cmd (void*, int argc, char **argv)
1993{
1994 if (argc <= 2) {
1995 ui->error("wrong format ON command\n");
1996 return 0;
1997 }
1998 if (strcmp(argv[1], "stop") == NULL) {
1999 int ii, len = 0;
2000 char * str;
2001 for (ii = 2; ii < argc; ii++) {
2002 len += (int)strlen(argv[ii]);
2003 }
2004 len += argc + 4; // just in case :-)
2005 str = (char*) malloc (len);
2006 strcpy(str, argv[2]);
2007 strcat(str, " ");
2008 for (ii = 3; ii < argc; ii++) {
2009 strcat(str, " ");
2010 strcat (str, argv[ii]);
2011 }
2012
2013 if (strcmp(argv[2], "discard") == NULL) {
2014 Ui_blcmd *pcmd = pui_misc->stop_list, *next;
2015 for (;pcmd;) {
2016 next = pcmd->next;
2017 free (pcmd->cmd_str);
2018 free ((char*)pcmd);
2019 pui_misc->stop_list = pcmd = next;
2020 }
2021 return 1;
2022 }
2023
2024 add_to_stop_list (str);
2025 }
2026 return 1;
2027}
2028
2029
2030///////////////////////////////////////////////
2031//
2032// SETREG <reg> <value>
2033//
2034int static setreg_ui_cmd (void*, int argc, char **argv)
2035{
2036
2037 uint64_t value;
2038 int ret;
2039
2040 if (argc < 3) {
2041 ui->error("wrong number of arguments : %d\n", argc);
2042 return 0;
2043 }
2044
2045 if (g_vcpu[0] == NULL) {
2046 ui->error("Move this line to be after CPU is created ...\n");
2047 exit (1);
2048 }
2049
2050 if (argc == 3) {
2051 ret = sscanf (argv[2], "%lli", &value);
2052 if (ret != 1) {
2053 ui->error("wrong VALUE argument <%s>\n", argv[2]);
2054 return 0;
2055 }
2056
2057 if (strcmp(argv[1], "pc") == NULL) {
2058
2059 for (uint32_t id = 0; id <= g_vcpu_id_max; id++) {
2060 Vcpu *vcpu = get_vcpu(id);
2061 if (!vcpu) continue;
2062 g_vcpu[id]->set_reg(VCPU_ASR_PC, value);
2063 }
2064
2065 }
2066 else if (strcmp(argv[1], "npc") == NULL) {
2067
2068 for (uint32_t id = 0; id <= g_vcpu_id_max; id++) {
2069 Vcpu *vcpu = get_vcpu(id);
2070 if (!vcpu) continue;
2071 g_vcpu[id]->set_reg(VCPU_ASR_NPC, value);
2072 }
2073 }
2074 else {
2075 ui->error("unsupported register <%s>\n", argv[1]);
2076 return 0;
2077 }
2078 }
2079 else if (argc == 4) {
2080 uint32_t id ;
2081 Vcpu * vcpu = 0;
2082 ret = sscanf (argv[1], "%i", &id);
2083 if ( ret != 1 ) {
2084 ui->error("wrong cpu id argument <%s>\n", argv[2]);
2085 return 0;
2086 }
2087 vcpu = get_vcpu(id);
2088 if(!vcpu){
2089 ui->error("wrong cpu id argument <%s>\n", argv[2]);
2090 return 0;
2091 }
2092 ret = sscanf (argv[3], "%lli", &value);
2093 if (ret != 1) {
2094 ui->error("wrong value argument <%s>\n", argv[3]);
2095 return 0;
2096 }
2097
2098 if (strcmp(argv[2], "pc") == NULL) {
2099 vcpu->set_reg(VCPU_ASR_PC, value);
2100 }
2101 else if (strcmp(argv[2], "npc") == NULL) {
2102 vcpu->set_reg(VCPU_ASR_NPC, value);
2103
2104 }
2105 else {
2106 ui->error("unknown reg NAME <%s>\n", argv[2]);
2107 return 0;
2108 }
2109 }
2110 return 1;
2111}
2112
2113
2114///////////////////////////////////////////////
2115//
2116// ALIAS <newname> <cmd>
2117//
2118int static alias_ui_cmd (void*, int argc, char **argv)
2119{
2120 if (argc == 1) {
2121
2122 Ui_cmd *pcmd = NULL;
2123 for (pcmd = &ui_cmd_list[0]; pcmd;pcmd = pcmd->next) {
2124 if (pcmd->flags & FUI_ALIAS) {
2125 ui->output("<%s> --> ", pcmd->name);
2126 for (int32_t ndx = 0; ndx < pcmd->alias_argc; ++ndx)
2127 ui->output("%s ", pcmd->alias_argv[ndx]);
2128 ui->output("\n");
2129 }
2130 }
2131 return 1;
2132 }
2133 else if (argc == 2){
2134 Ui_cmd *pcmd = NULL;
2135 for (pcmd = &ui_cmd_list[0]; pcmd;pcmd = pcmd->next) {
2136 if (strcmp(argv[1], pcmd->name) == NULL)
2137 break;
2138 }
2139
2140 if (pcmd == NULL) {
2141 ui->error("command <%s> not found \n", argv[1]);
2142 return 0;
2143 }
2144
2145 if (!(pcmd->flags & FUI_ALIAS)) {
2146 ui->error("command <%s> is not an alias \n", argv[1]);
2147 return 0;
2148 }
2149
2150 ui->output("<%s> --> ", pcmd->name);
2151 for (int32_t ndx = 0; ndx < pcmd->alias_argc; ++ndx)
2152 ui->output("%s ", pcmd->alias_argv[ndx]);
2153 ui->output("\n");
2154 return 1;
2155 }
2156
2157 // handle "alias new old ..."
2158
2159 // limit aliases to C-style identifiers i.e. alphanumeric and '_';
2160 // no leading digits
2161
2162 char* const alias_name = argv[1];
2163 for (int ndx = 0; alias_name[ndx] != '\0'; ++ndx) {
2164 if (!isalpha(alias_name[ndx]) && alias_name[ndx] != '_') {
2165 if (ndx == 0 || !isdigit(alias_name[ndx])) {
2166 ui->error("illegal alias name <%s>\n", alias_name);
2167 return 0;
2168 }
2169 }
2170 }
2171
2172 Ui_cmd *pcmd = NULL;
2173 Ui_cmd *prev_cmd = NULL;
2174 for (pcmd = &ui_cmd_list[0];
2175 pcmd;
2176 prev_cmd = pcmd, pcmd = pcmd->next) {
2177 if (strcmp(alias_name, pcmd->name) == NULL) {
2178 if ((pcmd->flags & FUI_ALIAS) == 0)
2179 {
2180 ui->error("command <%s> cannot be aliased\n", alias_name);
2181 return 0;
2182 }
2183 free((void*)pcmd->name);
2184 free((void*)pcmd->help);
2185 while (pcmd->alias_argc)
2186 free((void*)pcmd->alias_argv[pcmd->alias_argc--]);
2187 free((void*)pcmd->alias_argv);
2188 prev_cmd->next = pcmd->next;
2189 break;
2190 }
2191 }
2192
2193 if (pcmd == NULL)
2194 pcmd = (Ui_cmd*) calloc (1, sizeof(Ui_cmd));
2195
2196 if (pcmd == NULL) {
2197 ui->error("register: cant malloc\n");
2198 return 0;
2199 }
2200 pcmd->name = (char*) strdup(alias_name);
2201 char buf[1000];
2202 sprintf(buf, "alias for %s", pcmd->name);
2203 pcmd->help = (char*) strdup(buf);
2204 pcmd->cmd_exe_func = NULL;
2205 pcmd->cmd_help_func = NULL;
2206 pcmd->flags = FUI_ALIAS;
2207 pcmd->alias_argc = argc - 2;
2208 pcmd->alias_argv =
2209 (const char**)malloc((argc-2) * sizeof(const char*));
2210
2211 if (pcmd->alias_argv == NULL) {
2212 ui->error("register: cant malloc\n");
2213 return 0;
2214 }
2215
2216 for (int ndx = 0; ndx < argc - 2; ++ndx)
2217 {
2218 pcmd->alias_argv[ndx] = strdup(argv[ndx + 2]);
2219 if (pcmd->alias_argv[ndx] == NULL) {
2220 ui->error("register: cant strdup %x\n", argv[ndx + 2]);
2221 return 0;
2222 }
2223 }
2224
2225 Ui_cmd* pc = &ui_cmd_list[0];
2226 for ( ;pc->next; pc = pc->next)
2227 ;
2228 pc->next = pcmd;
2229
2230 return 1;
2231}
2232
2233
2234///////////////////////////////////////////////
2235//
2236// UNALIAS <cmd>
2237//
2238int static unalias_ui_cmd (void*, int argc, char **argv)
2239{
2240 if (argc == 2) {
2241
2242 Ui_cmd *pcmd = NULL;
2243 Ui_cmd *prev_cmd = NULL;
2244 for (pcmd = &ui_cmd_list[0];
2245 pcmd;
2246 prev_cmd = pcmd, pcmd = pcmd->next) {
2247 if (strcmp(argv[1], pcmd->name) == NULL) {
2248 if ((pcmd->flags & FUI_ALIAS) == 0)
2249 {
2250 ui->error("command <%s> cannot be aliased\n", argv[1]);
2251 return 0;
2252 }
2253 free((void*)pcmd->name);
2254 free((void*)pcmd->help);
2255 while (pcmd->alias_argc)
2256 free((void*)pcmd->alias_argv[pcmd->alias_argc--]);
2257 free((void*)pcmd->alias_argv);
2258 prev_cmd->next = pcmd->next;
2259 free(pcmd);
2260 return 1;
2261 }
2262 }
2263
2264 ui->error("cannot find alias <%s>\n",
2265 argv[1]);
2266 return 0;
2267 }
2268
2269 ui->error("usage: unalias <alias cmd>\n");
2270 return 0;
2271}
2272
2273
2274///////////////////////////////////////////////
2275//
2276// MIPS [#|off] # compute blaze MIPS
2277//
2278//
2279
2280static int
2281perf_ui_cmd (void*, int argc, char**argv)
2282{
2283 float tmp;
2284
2285 if ((argc == 2 && strcmp (argv[1], "off") == 0) || argc == 1) {
2286 perf_ui_interval = 0;
2287 return 1;
2288 }
2289 if (argc == 2 && sscanf (argv[1], "%f", &tmp) == 1) {
2290 perf_ui_interval = tmp * 1000000000; /* cvt to nano-secs for hr time*/
2291 perf_ui_start = gethrtime();
2292 next_perf_ui_time = perf_ui_start + perf_ui_interval;
2293 last_perf_globaltick = SYSTEM_get_ticks ();
2294 return 1;
2295 }
2296
2297 ui->error("usage : perf # | off \n");
2298 return 1;
2299}
2300
2301
2302///////////////////////////////////////////////
2303//
2304// DEBUG, and OPTION settings
2305//
2306
2307int static debug_ui_cmd (void*, int argc, char **argv)
2308{
2309 if (argc == 2) {
2310 blaze_debug = strtoul((const char*)argv[1], (char**)NULL, 0);
2311 }
2312 ui->output("blaze_debug = %d \n", blaze_debug);
2313 return 1;
2314}
2315
2316int static option_ui_cmd (void*, int argc, char **argv)
2317{
2318 if (argc == 2) {
2319 blaze_option = strtoul((const char*)argv[1], (char**)NULL, 0);
2320 }
2321 ui->output("blaze_option = %d \n", blaze_option);
2322 return 1;
2323}
2324
2325
2326///////////////////////////////////////////////
2327//
2328// VERSION
2329//
2330int static version_ui_cmd (void*, int argc, char **argv)
2331{
2332 ui->output("SAM VERSION %s\n", BLAZEVERSION_STRING);
2333 ui->output("BUILT ON %s, AT %s, IN %s\n", __DATE__,__TIME__,__CWD__);
2334 return 1;
2335}
2336
2337
2338///////////////////////////////////////////////
2339//
2340// HELP
2341//
2342int static help_ui_cmd (void*, int argc, char **argv)
2343{
2344
2345 Ui_cmd *pcmd;
2346 if (argc == 1) {
2347 ui->output("SAM now supports UI commands: \n\n");
2348 for (pcmd = &ui_cmd_list[0]; pcmd; pcmd = pcmd->next) {
2349 if (pcmd->flags & FUI_INVALID)
2350 continue;
2351 ui->output("%s\n", pcmd->name);
2352 }
2353 return 1;
2354 }
2355
2356 if (strcmp(argv[1], "all") == NULL) {
2357 for (pcmd = &ui_cmd_list[0]; pcmd; pcmd = pcmd->next) {
2358 if (pcmd->flags & FUI_INVALID)
2359 continue;
2360 if (pcmd->help)
2361 ui->output ("%s : %s\n", pcmd->name, pcmd->help);
2362 }
2363 return 1;
2364 }
2365
2366 for (pcmd = &ui_cmd_list[0]; pcmd; pcmd = pcmd->next) {
2367 if (pcmd->flags & FUI_INVALID)
2368 continue;
2369 if (strcmp(pcmd->name, argv[1]) == NULL) {
2370 if (pcmd->help) {
2371 ui->output("%s\n", pcmd->help);
2372 break;
2373 }
2374 }
2375 }
2376 return 1;
2377}
2378
2379
2380///////////////////////////////////////////////
2381// The interface for UI commands
2382//
2383void UI_exec_cmd (char *cmd)
2384{
2385 SYSTEM_lock_UI();
2386
2387 exec_cmd(cmd);
2388
2389 SYSTEM_unlock_UI();
2390}
2391
2392
2393///////////////////////////////////////////////
2394
2395void store_stdout_fd (int fd)
2396{
2397 pui_misc->redirect_fd = fd;
2398}
2399
2400///////////////////////////////////////////////
2401
2402int get_stdout_fd()
2403{
2404 return pui_misc->redirect_fd;
2405}
2406
2407///////////////////////////////////////////////
2408
2409void add_to_stop_list (char * cmd_str)
2410{
2411 Ui_blcmd *pcmd = (Ui_blcmd*) calloc (1, sizeof(Ui_blcmd));
2412 if (pcmd == NULL) {
2413 ui->error("unable to deffer <%s> command \n", cmd_str);
2414 return;
2415 }
2416 pcmd->cmd_str = cmd_str;
2417 if (pui_misc->stop_list == NULL) {
2418 pui_misc->stop_list = pcmd;
2419 }
2420 else {
2421 Ui_blcmd *prev_cmd = pui_misc->stop_list;
2422 while (prev_cmd->next != NULL) {
2423 prev_cmd = prev_cmd->next;
2424 }
2425 prev_cmd->next = pcmd;
2426 }
2427}
2428
2429
2430
2431///////////////////////////////////////////////
2432//
2433// DISKDELAY ...
2434//
2435
2436uint64_t
2437get_disk_ddelay_start_cycle(void)
2438{
2439 return ddelay_start_cycle;
2440}
2441
2442int
2443get_diskdelay(void)
2444{
2445 return diskdelay;
2446}
2447
2448int
2449get_wrdiskdelay(void)
2450{
2451 return wrdiskdelay;
2452}
2453static int diskdelay_ui_cmd (void*, int argc, char **argv)
2454{
2455 if (argc > 1) {
2456
2457 diskdelay = atoi((const char*)argv[1]);
2458 wrdiskdelay = diskdelay;
2459 ddelay_start_cycle = 0;
2460
2461 if (strchr(argv[1], '/') != NULL) {
2462 if (sscanf(argv[1], "%d/%d", &diskdelay, &wrdiskdelay) != 2) {
2463 ui->error("diskdelay format error !\n");
2464 return 1;
2465 }
2466 }
2467 if (argc > 2) {
2468 ddelay_start_cycle = strtoul((const char*)argv[2], (char**)NULL, 0);
2469 } else {
2470 ddelay_start_cycle = SYSTEM_get_ticks ();
2471 }
2472 ui->output("DISK : ddelay = %d, wrddelay = %d, start_cycle = %lld\n",
2473 diskdelay, wrdiskdelay, ddelay_start_cycle);
2474 }
2475 else if (argc == 1) {
2476 ui->output("DISK : ddelay = %d, wrddelay = %d, start_cycle = %lld\n",
2477 diskdelay, wrdiskdelay, ddelay_start_cycle);
2478 }
2479 return 0;
2480}
2481
2482
2483// ================================== SYNC-UI =================================
2484//
2485//
2486
2487// volatile int sync_fd = -1; moved up above to ui-thread,
2488// volatile int sync_on = 0; ditto,
2489// along with stept_usecs, stept_seqnum, done_seqnum.
2490
2491
2492typedef volatile struct sync_s {
2493 char *switchname;
2494} syncT;
2495static syncT sync_obj = {0};
2496static volatile syncT * sync1 = &sync_obj;
2497
2498
2499static int sync_ui_cmd (void*, int argc, char **argv);
2500static void sync_ui_usage ();
2501static void sync_connect (syncT * msp, const char * switchname);
2502static void sync_disconnect (syncT * msp);
2503
2504
2505static void init_sync ()
2506{
2507 syncT * msp = sync1;
2508
2509 //
2510 // attempt an initial connection if a server name is specified
2511 //
2512 const char * name = SYSTEM_get_hostconfig ("sync.host");
2513 if (!name) name = SYSTEM_get_hostconfig ("switch.host");
2514 if (name) {
2515 char buf[1024];
2516 sprintf (buf, "sync:%s", name);
2517
2518 sync1->switchname = strdup (buf);
2519 sync_fd = netsim_connect (sync1->switchname);
2520 }
2521
2522 sync1 = msp;
2523}
2524
2525
2526/*
2527 * sync UI commands
2528 *
2529 */
2530static int sync_ui_cmd (void*, int argc, char * argv[])
2531{
2532 syncT * msp = sync1;
2533
2534 if (argc == 2 && strcmp (argv[1], "on") == 0) { // "sync on" <--
2535
2536 if (sync_on) {
2537 ui->error("already in time-sync mode\n");
2538 }
2539 else if (!IN_STOP_STATE (blaze_run_state)) {
2540 ui->error("not in stop state, use stop command first\n");
2541 return 1;
2542 }
2543
2544 if (sync_fd == -1) {
2545 ui->error("time-sync not connected\n");
2546 } else
2547 write (sync_fd, "conn\n", 5); // Inform Sync-Master !!
2548
2549 SYSTEM_syncon_UI (); // transition !!!
2550 sync_on = 1;
2551
2552 return 1;
2553 }
2554
2555 if (argc == 2 && strcmp (argv[1], "off") == 0) { // "sync off" <-
2556
2557
2558 if (!sync_on)
2559 {
2560 ui->error("not in time-sync mode\n");
2561 // return 1;
2562 }
2563
2564 if (sync_fd == -1) {
2565 ui->error("time-sync not connected\n");
2566 } else
2567 write (sync_fd, "disconn\n", 8); // Inform Sync-Master !!!
2568
2569 SYSTEM_syncoff_UI (); // transition !!!
2570 sync_on = 0;
2571
2572 return 1;
2573 }
2574
2575
2576
2577 // ------------------ remote connection state ----------------------
2578
2579 if (argc == 1 // ""
2580 || (argc == 2 && strcmp (argv[1], "print") == 0)) { // "print"
2581
2582 if (sync_fd != -1) {
2583 ui->output("\tsync1: %s", msp->switchname);
2584 if (stept_seqnum != -1) {
2585 if (IN_GTSTEP_STATE(blaze_run_state))
2586 ui->output("\t %s, %lld *\n",
2587 "gtstep", stept_seqnum);
2588 else if (IN_GTWAIT_STATE(blaze_run_state))
2589 ui->output("\t %s, %lld \n",
2590 "gtwait", done_seqnum);
2591 else
2592 ui->output("\t %s, %lld \n",
2593 (sync_on ? "on" : "off"), done_seqnum);
2594 } else
2595 ui->output("\t %s \n", (sync_on ? "on" : "off"));
2596 } else
2597 ui->output("\tsync1: disconnected\n");
2598 return 1;
2599 }
2600 if (argc == 2 && strcmp (argv[1], "disconnect") == 0) { // "disconnect"
2601 sync_disconnect (msp);
2602 return 1;
2603 }
2604 if (argc == 2 && strcmp (argv[1], "connect") == 0) { // "connect"
2605 sync_connect (msp, msp->switchname);
2606 return 1;
2607 }
2608 if (argc == 3 && strcmp (argv[1], "connect") == 0) { // "connect host"
2609 sync_connect (msp, argv[2]);
2610 return 1;
2611 }
2612
2613 // --------------------------- stuff ----------------------------
2614
2615 if (argc >= 2 && strcmp (argv[1], "debug") == 0) { // "debug"
2616 if (argc == 2)
2617 ui->output("sync debug level is %d\n", SYNCDEBUG);
2618 else
2619 SYNCDEBUG = atoi (argv[2]);
2620 return 1;
2621 }
2622
2623 sync_ui_usage (); /* if we haven't already returned... */
2624 return 1;
2625}
2626
2627
2628
2629// see also sync_thread_main for handling of disconnect by other end of socket
2630//
2631static void sync_disconnect (syncT * msp)
2632{
2633 void * thd_status;
2634
2635 if (sync_fd == -1) {
2636 ui->error("sync already disconnected\n");
2637 return;
2638 }
2639 close (sync_fd);
2640 sync_fd = -1; /* <--- ui-thread will see this <--- */
2641 sync_on = 0;
2642}
2643
2644
2645static void sync_connect (syncT * msp, const char * switchname)
2646{
2647 int fd;
2648 char buf[1024];
2649
2650 if (sync_fd != -1) {
2651 ui->error("sync already connected\n");
2652 return;
2653 } else if (switchname == NULL) {
2654 ui->error("sync no switchname\n");
2655 return;
2656 }
2657
2658 if (SYNCDEBUG)
2659 ui->output("sync reconnecting\n");
2660
2661 sprintf(buf,"sync:%s", switchname);
2662 if ((fd = netsim_connect (buf)) >= 0) {
2663
2664 sync_fd = fd;
2665 sync_on = 0;
2666 msp->switchname = strdup (switchname);
2667
2668 } else {
2669 ui->error("connection failed\n");
2670 }
2671}
2672
2673static void sync_ui_usage ()
2674{
2675 ui->output("usage: \n");
2676 ui->output(" sync on|off\n");
2677 ui->output(" sync connect [hostname[/portnum]]\n");
2678 ui->output(" sync disconnect\n");
2679 ui->output(" sync print|stats|reset|debug\n");
2680}
2681
2682////////////////////////////////////////////////////////////////
2683
2684class PenableDisableOptions : public CommandOptions
2685{
2686 public:
2687
2688 PenableDisableOptions(const std::string& cmd_)
2689 :
2690 cmd(cmd_),
2691 cpu_opt(CpuSet().clear_all(), CpuOption::MULTITUDE)
2692 {
2693 add(cpu_opt);
2694 }
2695
2696 virtual ~PenableDisableOptions() {}
2697
2698 std::string get_cmd() const { return cmd; }
2699
2700 CpuOption cpu_opt;
2701
2702 int usage()
2703 {
2704 std::string fmt =
2705 "" + cmd + " command usage:\n"
2706 "\t" + cmd + "\n"
2707 "\t" + cmd + " -cpu <cpu set>\n"
2708 "\t" + cmd + " <cpu mask>\n";
2709
2710 ui->error(fmt.c_str());
2711 return 1;
2712 }
2713
2714 private:
2715 std::string cmd;
2716};
2717
2718
2719
2720static int penable_disable_ui_cmd (void *, int argc, char **argv,
2721 bool new_state, PenableDisableOptions& options)
2722{
2723 int i;
2724 Vcpu * vcpu = 0;
2725
2726 if (argc == 1) {
2727 for (i = 0; i < the_arch.numcpus; i++)
2728 {
2729 int sid = get_vcpu(i)->id();
2730 ui->output("cpuid %d %s\n", sid, cpu_enabled[sid] ? "enabled" : "disabled");
2731 }
2732 return 1;
2733 }
2734
2735 CpuSet cpu_set;
2736 std::vector<std::string> pos_args;
2737 bool result = options.parse(argc-1, (const char**)&argv[1], pos_args);
2738 if (result) {
2739 if (options.cpu_opt.is_on()) {
2740 if (!pos_args.empty()) {
2741 options.usage();
2742 return 0;
2743 }
2744 cpu_set = options.cpu_opt.get_value();
2745 }
2746 else {
2747 if (pos_args.size() != 1) {
2748 options.usage();
2749 return 0;
2750 }
2751 uint64_t cpu_mask;
2752 std::string error_msg;
2753 if (!UnsignedOption::parse_number(pos_args[0], cpu_mask, error_msg)) {
2754 std::string fmt = "UI " + options.get_cmd() + ": Bad cpu mask: %s\n";
2755 ui->error(fmt.c_str(), pos_args[0].c_str());
2756 return 0;
2757 }
2758 bool out_of_bounds = false;
2759 cpu_set.insert_mask(cpu_mask, &out_of_bounds);
2760 if (out_of_bounds)
2761 ui->warning("cpu mask (%s) out of range\n",
2762 pos_args[0].c_str());
2763 }
2764
2765 for (CpuSet::iterator iter = cpu_set.begin();
2766 iter != cpu_set.end();
2767 ++iter) {
2768 i = *iter;
2769
2770 if (get_vcpu(i) != NULL)
2771 cpu_enabled[i] = new_state;
2772 }
2773 cpu_enable_changed = true;
2774 return 1;
2775 }
2776
2777 std::string fmt = "UI " + options.get_cmd() + ": Syntax error\n\t%s\n";
2778 ui->error(fmt.c_str(),options.get_error_msg().c_str());
2779 return 0;
2780}
2781
2782static int penable_ui_cmd (void *, int argc, char **argv)
2783{
2784 PenableDisableOptions options("penable");
2785 return penable_disable_ui_cmd(NULL, argc, argv, true, options);
2786}
2787
2788static int pdisable_ui_cmd (void *, int argc, char **argv)
2789{
2790 PenableDisableOptions options("pdisable");
2791 return penable_disable_ui_cmd(NULL, argc, argv, false, options);
2792}
2793
2794
2795
2796
2797//////////////////////////////////////////////////////////////
2798//
2799//
2800//
2801int static pty_display (void *, int argc, char **argv)
2802{
2803
2804 if (pty_dev_a)
2805 ui->output("SAM: Serial port A (pty device) for TIP connection is %s\n", pty_dev_a);
2806 if (pty_dev_b)
2807 ui->output("SAM: Serial port B (pty device) for TIP connection is %s\n", pty_dev_b);
2808 if (pty_dev_c)
2809 ui->output("SAM: Serial port C (pty device) for TIP connection is %s\n", pty_dev_c);
2810 if (pty_dev_d)
2811 ui->output("SAM: Serial port D (pty device) for TIP connection is %s\n", pty_dev_d);
2812
2813 return (1);
2814}
2815
2816
2817//////////////////////////////////////////////////////////////
2818//
2819// breakpoints
2820//
2821// command :
2822//
2823// break [?|cpu=[<cpu_id>|all]]
2824// [iaddr=<value>|opcode=<value>|data_read_addr=<value>|data_write_addr=<value>]
2825// [mask=<value>]
2826//
2827
2828int bp_action ( int bp_id, int vcpu_id )
2829{
2830 ui->output("cpu %i hit breakpoint %i, stop... \n", vcpu_id, bp_id );
2831
2832 // request simulation stop
2833 BLAZE_STOP(blaze_stop_request);
2834
2835 //sinal stop to remote debug client if any
2836 update_remote_ui();
2837 return 0;
2838}
2839
2840
2841class BreakOptions : public CommandOptions
2842{
2843 public:
2844
2845 BreakOptions()
2846 :
2847 cpu_opt(CpuSet().insert_all(), CpuOption::MULTITUDE),
2848 trap_opt("trap", 0),
2849 red_opt("red")
2850 {
2851 add(cpu_opt);
2852 add(trap_opt);
2853 add(red_opt);
2854
2855 // -trap qutiand -red are mutual exclusive
2856 excl_opts.add(trap_opt).add(red_opt);
2857 }
2858
2859 virtual ~BreakOptions() {}
2860
2861 CpuOption cpu_opt;
2862 UnsignedOption trap_opt;
2863 Option red_opt;
2864
2865 static int usage()
2866 {
2867 ui->output("set breakpoint command usage:\n");
2868 ui->output("\tbreak\n");
2869 ui->output("\tbreak pc_va\n");
2870 ui->output("\tbreak pc_va cpu_id\n");
2871 ui->output("\tbreak -cpu [cpu_id|all] pc_va\n");
2872 ui->output("\tbreak -cpu [cpu_id|all] -trap trap_type\n");
2873 ui->output("\tbreak -cpu [cpu_id|all] -red\n");
2874 return 1;
2875 }
2876
2877 private:
2878
2879 ExclusiveOptions excl_opts;
2880};
2881
2882int break_ui_cmd (void*, int argc, char **argv)
2883{
2884 if (!IN_STOP_STATE (blaze_run_state))
2885 {
2886 ui->error("not in stop state, use stop command first\n");
2887 return 1;
2888 }
2889
2890 BreakOptions options;
2891
2892 std::vector<std::string> pos_args;
2893 bool result = options.parse(argc-1, (const char**)&argv[1], pos_args);
2894 if (result)
2895 {
2896 CpuSet cpu_set = options.cpu_opt.get_value();
2897
2898 int bp_id;
2899 uint64_t bp_value;
2900 VCPU_BpType bp_type;
2901 uint64_t bp_mask;
2902
2903 if (argc == 1)
2904 {
2905 // break
2906 // printout all existing breakpoints
2907 for (int i=0; i<=g_vcpu_id_max; i++)
2908 {
2909 if (g_vcpu[i])
2910 {
2911 g_vcpu[i]->print_breakpoints(ui->get_output_file());
2912 if (ui->get_log_file())
2913 g_vcpu[i]->print_breakpoints(ui->get_log_file());
2914 }
2915 }
2916 return 0;
2917 }
2918 // break on trap
2919 // break -cpu [cpu_id|all] -trap trap_type
2920 if (options.trap_opt.is_on())
2921 {
2922 if (pos_args.size() == 0)
2923 {
2924 bp_type = VCPU_BP_TRAP;
2925 bp_value = options.trap_opt.get_value();
2926 }
2927 else
2928 {
2929 ui->error("break on trap does not take any arguments\n");
2930 return 1;
2931 }
2932 }
2933 // break on red state
2934 // break -cpu [cpu_id|all] -red
2935 else if (options.red_opt.is_on())
2936 {
2937 if (pos_args.size() == 0)
2938 bp_type = VCPU_BP_RED;
2939 else
2940 {
2941 ui->error("break on red does not take arguments\n");
2942 return 1;
2943 }
2944 }
2945 else if (options.cpu_opt.is_on())
2946 {
2947 // break on pc
2948 // break -cpu [cpu_id|all] pc_va
2949 bp_type = VCPU_BP_INSTR_ADDR;
2950 if (pos_args.size() > 0)
2951 {
2952 std::string error_msg;
2953 if (!UnsignedOption::parse_number(pos_args[0], bp_value, error_msg))
2954 {
2955 error_msg += "pc-value";
2956 ui->error("%s\n", error_msg.c_str());
2957 return 1;
2958 }
2959 }
2960 else
2961 {
2962 ui->error("break on PC requires a PC value\n");
2963 return 1;
2964 }
2965 }
2966 else
2967 {
2968 // break pc_va
2969 // break pc_va [cpu_id]
2970 bp_type = VCPU_BP_INSTR_ADDR;
2971 if (pos_args.size() >= 1)
2972 {
2973 // set on all valid cpus
2974 std::string error_msg;
2975 if (!UnsignedOption::parse_number(pos_args[0], bp_value, error_msg))
2976 {
2977 error_msg += "pc-value";
2978 ui->error("%s\n", error_msg.c_str());
2979 return 1;
2980 }
2981 }
2982 if (pos_args.size() == 2)
2983 {
2984 // set on the specified cpu
2985 uint64_t cpu_id;
2986 std::string error_msg;
2987 if (!UnsignedOption::parse_number(pos_args[1], cpu_id, error_msg))
2988 {
2989 error_msg += "cpu-id";
2990 ui->error("%s\n", error_msg.c_str());
2991 return 1;
2992 }
2993 bool out_of_bounds = false;
2994 cpu_set.clear_all();
2995 cpu_set.insert(cpu_id, &out_of_bounds);
2996 if (out_of_bounds)
2997 {
2998 ui->error("Cpu number %d is out of range\n", cpu_id);
2999 return 1;
3000 }
3001 }
3002 }
3003 // set breakpoints on all valid cpus
3004 for (CpuSet::iterator iter = cpu_set.begin();
3005 iter != cpu_set.end();
3006 ++iter)
3007 {
3008 uint32_t i = *iter;
3009 if (i > g_vcpu_id_max)
3010 {
3011 ui->fatal("internal error: break_ui_cmd: cpu 0x%lx out of range\n",i);
3012 exit(-1);
3013 }
3014 if (g_vcpu[i] &&
3015 g_vcpu[i]->set_breakpoint(&bp_id, bp_type, bp_value,
3016 bp_action, bp_mask )== 0)
3017 ui->output("set breakpoint %i, for cpu %i \n", bp_id, g_vcpu[i]->id());
3018 }
3019 return 0;
3020 }
3021 else
3022 {
3023 ui->error("break command parsing failed: %s\n",
3024 options.get_error_msg().c_str());
3025 return 1;
3026 }
3027}
3028
3029int break_ui_cmd_OLD (void*, int argc, char **argv)
3030{
3031
3032
3033 int cpu_all = false;
3034 int cpu_id = -1;
3035 Vcpu * vcpu = 0;
3036
3037 int bp_id;
3038 uint64_t bp_value;
3039 VCPU_BpType bp_type;
3040 uint64_t bp_mask;
3041
3042 char *name;
3043 char *param;
3044
3045 if (!IN_STOP_STATE (blaze_run_state))
3046 {
3047 ui->error("not in stop state, use stop command first\n");
3048 return 0;
3049 }
3050
3051
3052 if ((argc < 2) || (argc > 4))
3053 return BreakOptions::usage();
3054
3055 if (strcmp(argv[1], "?")==0) // print info for all
3056 {
3057 // printout all existing breakpoints
3058 for (int i=0; i<=g_vcpu_id_max; i++)
3059 {
3060 if (g_vcpu[i])
3061 {
3062 g_vcpu[i]->print_breakpoints(ui->get_output_file());
3063 if (ui->get_log_file())
3064 g_vcpu[i]->print_breakpoints(ui->get_log_file());
3065 }
3066 }
3067 return 1;
3068 }
3069
3070 // read second argument as cpu=id
3071 name = strtok ( argv[1], " =" );
3072 param = strtok ( NULL, "\0" );
3073
3074 if( !name || !param || (strcmp(name, "cpu") != 0) )
3075 {
3076 ui->error("missing cpu id \n");
3077 return BreakOptions::usage();
3078 }
3079
3080 if ( strcmp(param, "all") == 0)
3081 {
3082 cpu_all = true;
3083 }
3084 else
3085 {
3086 cpu_id = (int)strtol(param, NULL, 0);
3087
3088 if ((cpu_id <0) || ( ( vcpu = get_vcpu(cpu_id) ) == 0) )
3089 {
3090 ui->error("bad cpu id[%d] \n", cpu_id);
3091 return BreakOptions::usage();
3092 }
3093 }
3094
3095 if (argc <3)
3096 {
3097 ui->error("incomplete list of breakpoint parameters \n");
3098 return BreakOptions::usage();
3099 }
3100
3101
3102 // read third argument as <type=value>
3103 name = strtok ( argv[2], " =" );
3104 param = strtok ( NULL, "\0" );
3105
3106 if (!name || !param)
3107 {
3108 ui->error("missing breakpoint type \n");
3109 return BreakOptions::usage();
3110 }
3111
3112 bp_value = strtoull(param, NULL, 0);
3113
3114 bp_type = VCPU_BP_INSTR_ADDR;
3115 if (strcmp(name, "pc" ) == 0 ) bp_type = VCPU_BP_INSTR_ADDR;
3116 else if (strcmp(name, "opcode") == 0 ) bp_type = VCPU_BP_OPCODE;
3117 else if (strcmp(name, "dread" ) == 0 ) bp_type = VCPU_BP_DATA_READ_ADDR;
3118 else if (strcmp(name, "dwrite") == 0 ) bp_type = VCPU_BP_DATA_WRITE_ADDR;
3119 else
3120 {
3121 ui->error("breakpoint type should be: iaddr | opcode | data_read | data_write \n");
3122 return BreakOptions::usage();
3123 }
3124
3125 bp_mask = ~uint64_t(0);
3126 if (argc == 4)
3127 {
3128 // read bp mask
3129 name = strtok ( argv[3], " =" );
3130 param = strtok ( NULL, "\0" );
3131
3132 if (!name || !param)
3133 {
3134 ui->error("missing breakpoint mask \n");
3135 return BreakOptions::usage();
3136 }
3137
3138 bp_mask = strtoull(param, NULL, 0);
3139 if (bp_mask ==0)
3140 {
3141 ui->error("incorrect breakpoint mask\n");
3142 return BreakOptions::usage();
3143 }
3144 }
3145
3146 // set the breakpoint
3147
3148 if (cpu_all)
3149 {
3150 for (int i=0; i<=g_vcpu_id_max; i++)
3151 {
3152 if (g_vcpu[i] &&
3153 g_vcpu[i]->set_breakpoint(&bp_id, bp_type, bp_value,
3154 bp_action, bp_mask )== 0)
3155 {
3156 ui->output("set breakpoint %i for cpu %i \n", bp_id, g_vcpu[i]->id());
3157 }
3158 }
3159 return 1;
3160 }
3161 else
3162 {
3163 if (
3164 vcpu->set_breakpoint(&bp_id, bp_type, bp_value,
3165 bp_action, bp_mask )==0)
3166 {
3167 ui->output("set breakpoint %i for cpu %i \n", bp_id, cpu_id);
3168 }
3169 return 1;
3170 }
3171
3172 return BreakOptions::usage();
3173}
3174
3175////////////////////////////////////////////////////
3176//
3177// remove breakpoint
3178//
3179// command: dbreak cpu=[<cpu_id>|all] bp_id
3180//
3181
3182static int print_dbreak_usage()
3183{
3184 ui->output("delete breakpoint command usage:\n dbreak cpu=[<cpu_id>|all]"
3185 " [bp_id=<id>]\n");
3186 return 0;
3187}
3188
3189
3190int dbreak_ui_cmd (void*, int argc, char **argv)
3191{
3192 int cpu_all = false;
3193 int cpu_id = -1;
3194 int bp_id = -1;
3195 Vcpu * vcpu = 0;
3196
3197 char *name;
3198 char *param;
3199
3200
3201 if (!IN_STOP_STATE (blaze_run_state))
3202 {
3203 ui->error("not in stop state, use stop command first\n");
3204 return 0;
3205 }
3206
3207 if ( argc > 3)
3208 return print_dbreak_usage();
3209
3210 if (argc == 1)
3211 {
3212 cpu_all = true;
3213 }
3214
3215 if (argc > 1)
3216 {
3217 // read second argument as cpu=id
3218 name = strtok ( argv[1], " =" );
3219 param = strtok ( NULL, "\0" );
3220
3221 if( !name || !param || (strcmp(name, "cpu") != 0) )
3222 {
3223 ui->error("break: missing cpu id \n");
3224 return print_dbreak_usage();
3225 }
3226
3227 if ( strcmp(param, "all") == 0)
3228 {
3229 cpu_all = true;
3230 }
3231 else
3232 {
3233 cpu_id = (int)strtol(param, NULL, 0);
3234
3235 if ((cpu_id <0) || ( ( vcpu = get_vcpu(cpu_id) ) == 0) )
3236 {
3237 ui->error("bad cpu id[%d] \n", cpu_id);
3238 return print_dbreak_usage();
3239 }
3240 }
3241 }
3242 if (argc > 2)
3243 {
3244 // read bp id
3245 name = strtok ( argv[2], " =" );
3246 param = strtok ( NULL, "\0" );
3247
3248 if (!name || !param || (strcmp(name, "bp_id") != 0))
3249 {
3250 ui->error("missing breakpoint id \n");
3251 return print_dbreak_usage();
3252 }
3253
3254 bp_id = strtol(param, NULL, 0);
3255
3256 }
3257
3258 // remove breakpoint
3259 if (cpu_all)
3260 {
3261 for (int i=0; i<=g_vcpu_id_max; i++)
3262 {
3263 if (g_vcpu[i] &&
3264 g_vcpu[i]->delete_breakpoint(-1)== 0)
3265 {
3266 ui->output("delete breakpoint %i for cpu %i \n", bp_id, g_vcpu[i]->id());
3267 }
3268 }
3269 return 1;
3270 }
3271 else
3272 {
3273 if (
3274 vcpu->delete_breakpoint(bp_id)==0)
3275 {
3276 ui->output("delete breakpoint %i for cpu %i \n", bp_id, cpu_id);
3277 }
3278 return 1;
3279 }
3280
3281}
3282
3283
3284////////////////////////////////////////////////////
3285//
3286// Delete breakpoint
3287//
3288// command: delete [-all] [<bp_id> ... ]
3289//
3290
3291class DeleteOptions : public CommandOptions
3292{
3293 public:
3294
3295 DeleteOptions()
3296 :
3297 all_opt("all")
3298 {
3299 add(all_opt);
3300 }
3301
3302 virtual ~DeleteOptions() {}
3303
3304 Option all_opt;
3305
3306 static int usage()
3307 {
3308 ui->output("usage: delete [-all] [<bp_id> ... ]\n");
3309 return 1;
3310 }
3311};
3312
3313int delete_ui_cmd (void*, int argc, char **argv)
3314{
3315 Vcpu * vcpu = 0;
3316
3317 char *name;
3318 char *param;
3319
3320
3321 if (!IN_STOP_STATE (blaze_run_state))
3322 {
3323 ui->error(" not in stop state, use stop command first\n");
3324 return 0;
3325 }
3326
3327 DeleteOptions options;
3328
3329 std::vector<std::string> pos_args;
3330 bool result = options.parse(argc-1, (const char**)&argv[1], pos_args);
3331
3332 if (!result)
3333 {
3334 DeleteOptions::usage();
3335 return 0;
3336 }
3337
3338 // remove all breakpoints
3339 if (options.all_opt.is_on())
3340 {
3341 ui->output("deleting all breakpoints\n");
3342
3343 for (int i=0; i<=g_vcpu_id_max; i++)
3344 if (g_vcpu[i])
3345 g_vcpu[i]->delete_breakpoint(-1);
3346 return 1;
3347 }
3348
3349 for (std::vector<std::string>::iterator iter = pos_args.begin();
3350 iter != pos_args.end();
3351 ++iter)
3352 {
3353 uint64_t bp_id;
3354 std::string err_msg;
3355
3356 if (!UnsignedOption::parse_number(*iter, bp_id, err_msg))
3357 {
3358 err_msg += "breakpoint id\n";
3359 ui->error(err_msg.c_str());
3360 return 0;
3361 }
3362
3363 int i = 0;
3364 for (i=0; i<=g_vcpu_id_max; i++)
3365 if (g_vcpu[i] && g_vcpu[i]->delete_breakpoint(bp_id) == 0) {
3366 ui->output("deleting breakpoint %d\n", bp_id);
3367 break;
3368 }
3369
3370 if (i > g_vcpu_id_max)
3371 ui->error("Unknown breakpoint %d\n", bp_id);
3372 }
3373
3374 return 1;
3375}
3376
3377
3378
3379///////////////////////////////////////////////////////
3380//
3381// set debug tracer on/off
3382//
3383static int print_vdebug_usage()
3384{
3385 ui->output("debug tracer usage:\n vdebug [-cpu <cpu_set>][-o <file_name>] on|off\n");
3386 return 0;
3387}
3388static int vdebug_ui_cmd (void*, int argc, char **argv)
3389{
3390 if (ANY_RUNNING_STATE (blaze_run_state))
3391 {
3392 ui->error(" not in stop state, use stop command first\n");
3393 return 0;
3394 }
3395
3396 // check command options
3397 if ( argc == 1) // show status
3398 {
3399 return tracer_cmd (STRACER_STATUS);
3400 }
3401 if ( argc < 2 )
3402 return print_vdebug_usage();
3403
3404 bool on = false;
3405 char *cmd = "vdebug";
3406
3407 CommandOptions option;
3408 CpuOption cpu_option(pselect_cpu_id,CpuOption::MULTITUDE);
3409 StringOption out_option("o");
3410 option.add(cpu_option);
3411 option.add(out_option);
3412
3413 std::vector<std::string> args;
3414 if (!option.parse(argc-1,(const char**)&argv[1],args))
3415 {
3416 fprintf(stderr, "ERROR: %s command parsing failed: %s\n",cmd,option.get_error_msg().c_str());
3417 return 0;
3418 }
3419 if (args.size() != 1)
3420 {
3421 fprintf(stderr, "ERROR: %s requires 1 positional argument - on|off.\n",cmd);
3422 return 0;
3423 }
3424 else // parse on/off flag
3425 {
3426 if (args[0]=="on")
3427 on = true;
3428 else if (args[0]=="off")
3429 on = false;
3430 else
3431 return print_vdebug_usage();
3432 }
3433
3434 bool separate_files = false;
3435 int tprev = -1;
3436 int sid[NCPU_MAX]; // cpu id's that need to be traced
3437 for (int i=0; i<NCPU_MAX; i++) sid[i] = 0;
3438
3439 // check which vcpus need debug tracing
3440 CpuSet& cpu_set = cpu_option.get_value();
3441 for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i)
3442 {
3443 uint32_t cpu_id = *i;
3444 Vcpu* vcpu = g_vcpu[cpu_id];
3445 if (vcpu == 0)
3446 {
3447 ui->error("cpu[%d] is not available\n", cpu_id);
3448 return print_vdebug_usage();
3449 }
3450
3451 if (SYSTEM_get_ncpu() > SYSTEM_get_cpus_per_thread())
3452 {
3453 // check if specified cpu's belong to the same worker thread
3454 int vid = 0; // get a "sequential id"
3455 for ( ;vid < g_nvcpu; vid++)
3456 if (get_vcpu(vid) == vcpu)
3457 break;
3458
3459 // check worker thread id
3460 int tid = vid / SYSTEM_get_cpus_per_thread();
3461 if (tprev < 0 ) tprev = tid;
3462 else if ( tprev != tid ) separate_files = true;
3463 }
3464 // set a flag to enable tracer for this cpu id
3465 sid[cpu_id] = 1;
3466 }
3467
3468 const char *file_name = out_option.is_on() ? out_option.get_value().c_str() : NULL;
3469 return tracer_cmd ( trace_cmd_t(on), sid, file_name, separate_files );
3470}
3471
3472
3473///////////////////////////////////////////////////////
3474//
3475// print all tlb entries
3476//
3477static int tlbs_ui_cmd (void*, int argc, char **argv)
3478{
3479 if (ANY_RUNNING_STATE (blaze_run_state))
3480 {
3481 ui->error("not in stop state, use stop command first\n");
3482 return 1;
3483 }
3484
3485 if (argc < 2 || argc > 3)
3486 {
3487 ui->error("print all valid TTEs, usage: tlbs <cpuid> [<outfile>]\n");
3488 return 1;
3489 }
3490
3491 int cpu_id = strtol(argv[1], NULL, 0);
3492
3493 Vcpu* vcpu = get_vcpu(cpu_id);
3494 if (vcpu == 0)
3495 {
3496 ui->error("SAM: There is no vcpu %i instance \n", cpu_id);
3497 return 1;
3498 }
3499
3500 if(argc == 3)
3501 {
3502 char * fname = argv[2];
3503 FILE* stream = fopen (fname, "w");
3504 ui->output("print tlb entries to %s\n", fname);
3505 vcpu->print_tlbs(stream);
3506 fclose(stream);
3507 }
3508 else
3509 {
3510 vcpu->print_tlbs(ui->get_output_file());
3511 if (ui->get_log_file())
3512 vcpu->print_tlbs(ui->get_log_file());
3513 }
3514
3515 return 0;
3516}
3517
3518
3519///////////////////////////////////////////////////////
3520//
3521// set the log level
3522//
3523static int
3524loglev_ui_cmd (void*, int argc, char**argv)
3525{
3526 int tmp;
3527
3528 if (argc == 1) {
3529 }
3530 else if (argc == 2 && sscanf (argv[1], "%d", &tmp) == 1 &&
3531 tmp >= 1 && tmp <= 3) {
3532 }
3533 else {
3534 ui->error("usage: loglev [1|2|3] \n");
3535 return 1;
3536 }
3537
3538 return 0;
3539}
3540
3541
3542static int
3543devmap_ui_cmd (void*, int argc, char**argv)
3544{
3545 int tmp;
3546
3547 if(argc > 1){
3548 ui->error("no arguments are allowed\n");
3549 }
3550
3551 extern devRegistry * samDevs;
3552 if (ui->get_log_file())
3553 samDevs->dump(ui->get_log_file());
3554
3555 return 1;
3556}
3557
3558
3559// find a vcpu pointer by cpu instance name
3560static Vcpu * get_vcpu_by_name ( char *name )
3561{
3562 Vcpu *vcpu = NULL;
3563
3564 for (int i=0; i<g_nvcpu; i++)
3565 {
3566 if ( strcmp ( name, g_vcpu[i]->config.name ) == 0 )
3567 {
3568 vcpu = g_vcpu[i]; // found a matching name
3569 break;
3570 }
3571 }
3572
3573 return vcpu;
3574}
3575
3576
3577///////////////////////////////////////////////////
3578//
3579// run-python-file command
3580//
3581
3582int (*py_source)( int argc, char** argv );
3583
3584static int run_python_file_ui_cmd(void*, int argc, char **argv)
3585{
3586 if (!IN_STOP_STATE (blaze_run_state))
3587 {
3588 ui->error("not in stop state, use stop command first\n");
3589 return 0;
3590 }
3591 if (argc < 2)
3592 {
3593 ui->error("usage: run-python-file <file_name> \n");
3594 return 0;
3595 }
3596
3597 // check if py module was loaded already
3598 if (!python_UI)
3599 {
3600 char* sam_py_argv[1];
3601 exec_cmd("mod load py py.so\n");
3602 sam_py_argv[0] = "$SAM/pfe/sam.py";
3603 if (py_source)
3604 (py_source)(1,sam_py_argv);
3605 }
3606
3607 if (!py_source)
3608 ui->fatal("internal error with python module.\n");
3609
3610 return (py_source)(argc - 1,argv + 1);
3611}
3612
3613
3614
3615static int print_pselect_usage()
3616{
3617 ui->output("select cpu command usage:\n");
3618 ui->output("\tpselect\n");
3619 ui->output("\tpselect cpu_id\n");
3620 return 0;
3621}
3622
3623int pselect_ui_cmd (void*, int argc, char **argv)
3624{
3625 if (!IN_STOP_STATE (blaze_run_state))
3626 {
3627 ui->error("not in stop state, use stop command first\n");
3628 return 1;
3629 }
3630
3631 CommandOptions cmd_options;
3632
3633 std::vector<std::string> pos_args;
3634 bool result = cmd_options.parse(argc-1, (const char**)&argv[1], pos_args);
3635 if (result)
3636 {
3637 if (argc == 1)
3638 {
3639 // pselect
3640 ui->error("cpu %d is currently selected\n", pselect_cpu_id);
3641 return 0;
3642 }
3643 else
3644 {
3645 // pselect cpu_id
3646 uint64_t cpu_id;
3647 std::string error_msg;
3648
3649 if (!UnsignedOption::parse_number(pos_args[0], cpu_id, error_msg))
3650 {
3651 error_msg += "cpu number";
3652 ui->error("%s\n", error_msg.c_str());
3653 }
3654
3655 if (cpu_id <=g_vcpu_id_max && g_vcpu[cpu_id])
3656 {
3657 pselect_cpu_id = cpu_id;
3658 }
3659 else
3660 {
3661 ui->error("No cpu matching cpu number: %lld\n", cpu_id);
3662 return 1;
3663 }
3664 }
3665 return 0;
3666 }
3667 else
3668 {
3669 ui->error("pselect command parsing failed: %s\n", cmd_options.get_error_msg().c_str());
3670 return 1;
3671 }
3672}
3673
3674
3675//////////////////////////////////////////////////////////////////////
3676// t r a n s l a t e
3677//////////////////////////////////////////////////////////////////////
3678
3679class TranslateOptions : public CommandOptions
3680{
3681 public:
3682 TranslateOptions( int cpu_id )
3683 :
3684 cpu(cpu_id,CpuOption::MULTITUDE),
3685 addressing(AddressingOptions::VA)
3686 {
3687 add(cpu);
3688 add(addressing);
3689 }
3690
3691 CpuOption cpu;
3692 AddressingOptions addressing;
3693
3694 static int usage()
3695 {
3696 // We need to get this from the Options class
3697 // CommandOptions::usage('translate');
3698 return 1;
3699 }
3700};
3701
3702int translate_ui_cmd( void*, int argc, char** argv )
3703{
3704 static const char* cmd = "translate";
3705
3706 if (!IN_STOP_STATE (blaze_run_state))
3707 {
3708 ui->error("not in stop state, use stop command first\n");
3709 return 1;
3710 }
3711
3712 TranslateOptions options(pselect_cpu_id);
3713 std::vector<std::string> args;
3714
3715 if (!options.parse(argc-1,(const char**)&argv[1],args))
3716 {
3717 ui->error("%s command parsing failed: %s\n",cmd,options.get_error_msg().c_str());
3718 return 1;
3719 }
3720 if (args.size() != 1)
3721 {
3722 ui->error("%s requires 1 positional argument; the address to translate.\n",cmd);
3723 return 1;
3724 }
3725
3726 Vcpu::TranslateMode mode = options.addressing.translate_mode();
3727 uint64_t ctx = options.addressing.context_id.get_value();
3728 uint64_t pid = options.addressing.partition_id.get_value();
3729 uint64_t pa;
3730 uint64_t ea = strtoull(args[0].c_str(), NULL, 0);
3731 CpuSet& cpu_set = options.cpu.get_value();
3732
3733 for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i)
3734 {
3735 uint32_t cpu_id = *i;
3736 ui->output("%d: ",cpu_id);
3737 Vcpu* vcpu = g_vcpu[cpu_id];
3738 if (vcpu == 0)
3739 ui->output("not available\n");
3740 else if (vcpu->translate(mode,ea,ctx,pid,&pa) != Vcpu::TRANSLATE_OK)
3741 ui->output("no mapping available\n");
3742 else
3743 ui->output("pa = 0x%llx\n",pa);
3744 }
3745
3746 return 0;
3747}
3748
3749
3750//////////////////////////////////////////////////////////////////////
3751// g e t
3752//////////////////////////////////////////////////////////////////////
3753
3754class GetOptions : public CommandOptions
3755{
3756 public:
3757 GetOptions( int cpu_id )
3758 :
3759 cpu(cpu_id),
3760 addressing(AddressingOptions::PA),
3761 count("count",1),
3762 size("size",4)
3763 {
3764 add(cpu);
3765 add(addressing);
3766 add(size);
3767 add(count);
3768 }
3769
3770 CpuOption cpu;
3771 AddressingOptions addressing;
3772 UnsignedOption size;
3773 UnsignedOption count;
3774
3775 static int usage()
3776 {
3777 // We need to get this from the Options class
3778 // CommandOptions::usage('get');
3779 return 1;
3780 }
3781};
3782
3783int get_ui_cmd( void*, int argc, char** argv )
3784{
3785 static const char* cmd = "get";
3786
3787 if (!IN_STOP_STATE (blaze_run_state))
3788 {
3789 ui->error("not in stop state, use stop command first\n");
3790 return 1;
3791 }
3792
3793 GetOptions options(pselect_cpu_id);
3794 std::vector<std::string> args;
3795
3796 if (!options.parse(argc-1,(const char**)&argv[1],args))
3797 {
3798 ui->error("%s command parsing failed: %s\n",cmd,options.get_error_msg().c_str());
3799 return 1;
3800 }
3801
3802 uint32_t size;
3803 uint32_t count;
3804
3805 switch (args.size())
3806 {
3807 case 2:
3808 if (options.size.is_on())
3809 {
3810 ui->error("%s used with confusing arguments: both positional "
3811 "size argument and -size option given: use -size and -count.\n",cmd);
3812 return 1;
3813 }
3814 if (options.count.is_on())
3815 {
3816 ui->error("%s used with confusing arguments: both positional "
3817 "size argument and -count option given: use -size and -count.\n",cmd);
3818 return 1;
3819 }
3820 ui->warning("%s use -size and -count options as [size] positional "
3821 "argument is deprecated.\n",cmd);
3822 size = strtoull(args[1].c_str(),NULL,0);
3823 count = (size > 8) ? ((size + 7) / 8) : 1;
3824 break;
3825 case 1:
3826 size = options.size.get_value();
3827 count = options.count.get_value();
3828 break;
3829 case 0:
3830 default:
3831 ui->error("%s requires address positional argument.\n",cmd);
3832 return 1;
3833 }
3834
3835 if ((size == 0) || ((size != 1) && (size != 2) && (size != 4) && (size != 8)))
3836 {
3837 if (options.size.is_on() || (size < 8))
3838 {
3839 ui->error("%s requires size to be 1, 2, 4, or 8.\n",cmd);
3840 return 1;
3841 }
3842 else
3843 {
3844 if (size & 7)
3845 ui->warning("%s rounded size up to nearest multiple of 8.\n",cmd);
3846 size = 8;
3847 }
3848 }
3849
3850 Vcpu::TranslateMode mode = options.addressing.translate_mode();
3851 uint64_t ctx = options.addressing.context_id.get_value();
3852 uint64_t pid = options.addressing.partition_id.get_value();
3853 uint64_t pa;
3854 uint64_t ea = strtoull(args[0].c_str(),NULL,0);
3855 uint32_t cpu_id = *options.cpu.get_value().find(0);
3856
3857 Vcpu* vcpu = g_vcpu[cpu_id];
3858 if (vcpu == 0)
3859 ui->error("cpu %d not available\n",cpu_id);
3860 else if (vcpu->translate(mode,ea,ctx,pid,&pa) != Vcpu::TRANSLATE_OK)
3861 ui->warning("cpu %d has no mapping available for 0x%llx\n",cpu_id,ea);
3862 else
3863 {
3864 uint8_t data8;
3865 uint16_t data16;
3866 uint32_t data32;
3867 uint64_t data64;
3868
3869 uint_t n;
3870
3871 for (n = 0; count--; ++n, ea += size, pa += size)
3872 {
3873 if (((ea & 0x1fff) == 0) // At the begin of every 8KByte page
3874 && vcpu->translate(mode,ea,ctx,pid,&pa) != Vcpu::TRANSLATE_OK)
3875 {
3876 ui->warning("cpu %d has no mapping available for 0x%llx\n",cpu_id,ea);
3877 break;
3878 }
3879
3880 if ((n % (32 / size)) == 0)
3881 ui->output("0x%016llx: ",pa);
3882
3883 switch (size)
3884 {
3885 case 1:
3886 mmi_memread(pa,(uint8_t*)&data8,1);
3887 ui->output("0x%02llx ",data8);
3888 break;
3889 case 2:
3890 mmi_memread(pa,(uint8_t*)&data16,2);
3891 ui->output("0x%04llx ",data16);
3892 break;
3893 case 4:
3894 mmi_memread(pa,(uint8_t*)&data32,4);
3895 ui->output("0x%08llx ",data32);
3896 break;
3897 case 8:
3898 mmi_memread(pa,(uint8_t*)&data64,8);
3899 ui->output("0x%016llx ",data64);
3900 break;
3901 }
3902
3903 if (((n + 1) % (32 / size)) == 0)
3904 ui->output("\n");
3905 }
3906
3907 if (n % (32 / size))
3908 ui->output("\n");
3909 }
3910
3911 return 0;
3912}
3913
3914//////////////////////////////////////////////////////////////////////
3915// s e t
3916//////////////////////////////////////////////////////////////////////
3917
3918class SetOptions : public CommandOptions
3919{
3920 public:
3921 SetOptions( int cpu_id )
3922 :
3923 cpu(cpu_id),
3924 addressing(AddressingOptions::PA),
3925 size("size",4),
3926 count("count",1)
3927 {
3928 add(cpu);
3929 add(addressing);
3930 add(size);
3931 add(count);
3932 }
3933
3934 CpuOption cpu;
3935 AddressingOptions addressing;
3936 UnsignedOption size;
3937 UnsignedOption count;
3938
3939 static int usage()
3940 {
3941 // We need to get this from the Options class
3942 // CommandOptions::usage('set');
3943 return 1;
3944 }
3945};
3946
3947int set_ui_cmd( void*, int argc, char** argv )
3948{
3949 static const char* cmd = "set";
3950
3951 if (!IN_STOP_STATE (blaze_run_state))
3952 {
3953 ui->error("not in stop state, use stop command first\n");
3954 return 1;
3955 }
3956
3957 SetOptions options(pselect_cpu_id);
3958 std::vector<std::string> args;
3959
3960 if (!options.parse(argc-1,(const char**)&argv[1],args))
3961 {
3962 ui->error("%s command parsing failed: %s\n",cmd,options.get_error_msg().c_str());
3963 return 1;
3964 }
3965
3966 uint32_t size;
3967 uint32_t count;
3968
3969 switch (args.size())
3970 {
3971 case 3:
3972 if (options.size.is_on())
3973 {
3974 ui->error("%s used with confusing arguments: both positional "
3975 "size argument and -size option given: use -size and -count.\n",cmd);
3976 return 1;
3977 }
3978 if (options.count.is_on())
3979 {
3980 ui->error("%s used with confusing arguments: both positional "
3981 "size argument and -count option given: use -size and -count.\n",cmd);
3982 return 1;
3983 }
3984 ui->warning("%s use -size and -count options as [size] positional "
3985 "argument is deprecated.\n",cmd);
3986 size = strtoull(args[2].c_str(),NULL,0);
3987 count = (size > 8) ? ((size + 7) / 8) : 1;
3988 break;
3989 case 2:
3990 size = options.size.get_value();
3991 count = options.count.get_value();
3992 break;
3993 case 0:
3994 default:
3995 ui->error("%s requires address [size] positional arguments.\n",cmd);
3996 return 1;
3997 }
3998
3999 if ((size == 0) || ((size != 1) && (size != 2) && (size != 4) && (size != 8)))
4000 {
4001 if (options.size.is_on() || (size < 8))
4002 {
4003 ui->error("%s requires size to be 1, 2, 4, or 8.\n",cmd);
4004 return 1;
4005 }
4006 else
4007 {
4008 if (size & 7)
4009 ui->warning("%s rounded size up to nearest multiple of 8.\n",cmd);
4010 size = 8;
4011 }
4012 }
4013
4014 Vcpu::TranslateMode mode = options.addressing.translate_mode();
4015 uint64_t ctx = options.addressing.context_id.get_value();
4016 uint64_t pid = options.addressing.partition_id.get_value();
4017 uint64_t pa;
4018 uint64_t ea = strtoull(args[0].c_str(),NULL,0);
4019 uint32_t cpu_id = *options.cpu.get_value().find(0);
4020
4021 Vcpu* vcpu = g_vcpu[cpu_id];
4022 if (vcpu == 0)
4023 ui->error("cpu %d not available\n",cpu_id);
4024 else if (vcpu->translate(mode,ea,ctx,pid,&pa) != Vcpu::TRANSLATE_OK)
4025 ui->output("cpu %d has no mapping available for 0x%llx\n",cpu_id,ea);
4026 else
4027 {
4028 uint64_t data64 = strtoull(args[1].c_str(),NULL,0);
4029 uint32_t data32 = data64;
4030 uint16_t data16 = data64;
4031 uint8_t data8 = data64;
4032
4033 for (uint_t n = 0; count--; ++n, ea += size, pa += size)
4034 {
4035 if (((ea & 0x1fff) == 0) // At the begin of every 8KByte page
4036 && vcpu->translate(mode,ea,ctx,pid,&pa) != Vcpu::TRANSLATE_OK)
4037 {
4038 ui->output("cpu %d has no mapping available for 0x%llx\n",cpu_id,ea);
4039 break;
4040 }
4041 switch (size)
4042 {
4043 case 1: mmi_memwrite(pa,(uint8_t*)&data8, 1); break;
4044 case 2: mmi_memwrite(pa,(uint8_t*)&data16,2); break;
4045 case 4: mmi_memwrite(pa,(uint8_t*)&data32,4); break;
4046 case 8: mmi_memwrite(pa,(uint8_t*)&data64,8); break;
4047 }
4048 }
4049 }
4050
4051 return 0;
4052}
4053
4054//////////////////////////////////////////////////////////////////////
4055// d i s a s s e m b l e
4056//////////////////////////////////////////////////////////////////////
4057
4058class DisassembleOptions : public CommandOptions
4059{
4060 public:
4061 DisassembleOptions( int cpu_id )
4062 :
4063 cpu(cpu_id),
4064 addressing(AddressingOptions::VA),
4065 count("count",1)
4066 {
4067 add(cpu);
4068 add(addressing);
4069 add(count);
4070 }
4071
4072 CpuOption cpu;
4073 AddressingOptions addressing;
4074 UnsignedOption count;
4075
4076 static int usage()
4077 {
4078 // We need to get this from the Options class
4079 // CommandOptions::usage('disassemble');
4080 return 1;
4081 }
4082};
4083
4084int disassemble_ui_cmd( void*, int argc, char** argv )
4085{
4086 static const char* cmd = "disassemble";
4087
4088 if (!IN_STOP_STATE (blaze_run_state))
4089 {
4090 ui->error("not in stop state, use stop command first\n");
4091 return 1;
4092 }
4093
4094 DisassembleOptions options(pselect_cpu_id);
4095 std::vector<std::string> args;
4096
4097 if (!options.parse(argc-1,(const char**)&argv[1],args))
4098 {
4099 ui->error("%s command parsing failed: %s\n",cmd,options.get_error_msg().c_str());
4100 return 1;
4101 }
4102
4103 uint64_t ea;
4104 uint32_t cpu_id = *options.cpu.get_value().begin();
4105 uint32_t count;
4106 Vcpu* vcpu = g_vcpu[cpu_id];
4107
4108 if (vcpu == 0)
4109 {
4110 ui->error("cpu %d not available\n",cpu_id);
4111 return 0;
4112 }
4113
4114 switch (args.size())
4115 {
4116 case 2:
4117 if (options.count.is_on())
4118 {
4119 ui->error("%s used with confusing arguments: both positional "
4120 "count argument and -count option given: use -count.\n",cmd);
4121 return 1;
4122 }
4123 ui->warning("%s use -count option as [count] positional "
4124 "argument is deprecated.\n",cmd);
4125 ea = strtoull(args[0].c_str(),NULL,0);
4126 count = strtoull(args[1].c_str(),NULL,0);
4127 break;
4128
4129 case 1:
4130 ea = strtoull(args[0].c_str(),NULL,0);
4131 count = options.count.get_value();
4132 break;
4133
4134 case 0:
4135#if TO_BE_IMPLEMENTED
4136 vcpu->get_reg(VCPU_ASR_PC,&ea);
4137 count = options.count.get_value();
4138 break;
4139#endif
4140 default:
4141 ui->error("%s requires address positional arguments.\n",cmd);
4142 return 1;
4143 }
4144
4145 Vcpu::TranslateMode mode = options.addressing.translate_mode();
4146 uint64_t ctx = options.addressing.context_id.get_value();
4147 uint64_t pid = options.addressing.partition_id.get_value();
4148 uint64_t pa;
4149
4150 if (ea & 3)
4151 {
4152 ui->warning("%s likes the address argument to be 4 byte aligned\n",cmd);
4153 ea &= ~3ull;
4154 }
4155
4156 if (vcpu->translate(mode,ea,ctx,pid,&pa) != Vcpu::TRANSLATE_OK)
4157 ui->error("cpu %d has no mapping available for 0x%llx\n",cpu_id,ea);
4158 else
4159 {
4160 for (; count--; ea += 4, pa += 4)
4161 {
4162 if (((ea & 0x1fff) == 0) // At the begin of every 8KByte page
4163 && vcpu->translate(mode,ea,ctx,pid,&pa) != Vcpu::TRANSLATE_OK)
4164 {
4165 ui->output("cpu %d has no mapping available for 0x%llx\n",cpu_id,ea);
4166 break;
4167 }
4168
4169 char inst[256];
4170 uint32_t data;
4171 mmi_memread(pa,(uint8_t*)&data,4);
4172
4173 spix_sparc_dis(inst,256,spix_sparc_iop(SPIX_SPARC_V9,&data),&data,ea);
4174 ui->output("%d: %llx %llx [%08x] %s\n",cpu_id,ea,pa,data,inst);
4175 }
4176 }
4177
4178 return 0;
4179}
4180
4181//////////////////////////////////////////////////////////////////////
4182// r e a d - a s i
4183//////////////////////////////////////////////////////////////////////
4184
4185class ReadAsiOptions : public CommandOptions
4186{
4187 public:
4188 ReadAsiOptions( int cpu_id )
4189 :
4190 cpu(cpu_id)
4191 {
4192 add(cpu);
4193 }
4194
4195 CpuOption cpu;
4196
4197 static int usage()
4198 {
4199 // We need to get this from the Options class
4200 // CommandOptions::usage('disassemble');
4201 return 1;
4202 }
4203};
4204
4205int read_asi_ui_cmd( void*, int argc, char** argv )
4206{
4207 static const char* cmd = "read-asi";
4208
4209 if (!IN_STOP_STATE (blaze_run_state))
4210 {
4211 ui->error("not in stop state, use stop command first\n");
4212 return 1;
4213 }
4214
4215 ReadAsiOptions options(pselect_cpu_id);
4216 std::vector<std::string> args;
4217
4218 if (!options.parse(argc-1,(const char**)&argv[1],args))
4219 {
4220 ui->error("%s command parsing failed: %s\n",cmd,options.get_error_msg().c_str());
4221 return 1;
4222 }
4223
4224 if (args.size() != 2)
4225 {
4226 ui->error("%s requires <asi> <address> positional arguments.\n",cmd);
4227 return 1;
4228 }
4229
4230 uint64_t asi = strtoull(args[0].c_str(),NULL,0);
4231 int64_t va = strtoll(args[1].c_str(),NULL,0); // va is signed
4232 uint32_t cpu_id = *options.cpu.get_value().begin();
4233
4234 if (asi > 0xff)
4235 {
4236 ui->error("valid non-translating asi values range from 0 to 0xff\n",cmd);
4237 return 1;
4238 }
4239
4240 if (va & 7)
4241 {
4242 ui->warning("%s requires the address argument to be 8 byte aligned\n",cmd);
4243 va &= ~7ull;
4244 }
4245
4246 Vcpu* vcpu = g_vcpu[cpu_id];
4247 if (vcpu == 0)
4248 {
4249 ui->error("cpu %d not available\n",cpu_id);
4250 return 1;
4251 }
4252
4253 uint64_t data;
4254 int fail = vcpu->get_asi(asi,va,data);
4255
4256 if (fail)
4257 {
4258 ui->error("0x%02llx:0x%llx is not a valid non-translating asi:va pair\n",asi,va);
4259 return 1;
4260 }
4261
4262 ui->output("0x%02llx:0x%llx = 0x%llx\n",asi,va,data);
4263
4264 return 0;
4265}
4266
4267
4268//////////////////////////////////////////////////////////////////////
4269// w r i t e - a s i
4270//////////////////////////////////////////////////////////////////////
4271
4272class WriteAsiOptions : public CommandOptions
4273{
4274 public:
4275 WriteAsiOptions( int cpu_id )
4276 :
4277 cpu(cpu_id)
4278 {
4279 add(cpu);
4280 }
4281
4282 CpuOption cpu;
4283
4284 static int usage()
4285 {
4286 // We need to get this from the Options class
4287 // CommandOptions::usage('disassemble');
4288 return 1;
4289 }
4290};
4291
4292int write_asi_ui_cmd( void*, int argc, char** argv )
4293{
4294 static const char* cmd = "write-asi";
4295
4296 if (!IN_STOP_STATE (blaze_run_state))
4297 {
4298 ui->error("not in stop state, use stop command first\n");
4299 return 1;
4300 }
4301
4302 WriteAsiOptions options(pselect_cpu_id);
4303 std::vector<std::string> args;
4304
4305 if (!options.parse(argc-1,(const char**)&argv[1],args))
4306 {
4307 ui->error("%s command parsing failed: %s\n",cmd,options.get_error_msg().c_str());
4308 return 1;
4309 }
4310
4311 if (args.size() != 3)
4312 {
4313 ui->error("%s requires <asi> <address> <value> positional arguments.\n",cmd);
4314 return 1;
4315 }
4316
4317 uint64_t asi = strtoull(args[0].c_str(),NULL,0);
4318 int64_t va = strtoll(args[1].c_str(),NULL,0); // va is signed
4319 uint64_t data = strtoull(args[2].c_str(),NULL,0);
4320 uint32_t cpu_id = *options.cpu.get_value().begin();
4321
4322 if (asi > 0xff)
4323 {
4324 ui->error("valid non-translating asi values range from 0 to 0xff\n",cmd);
4325 return 1;
4326 }
4327
4328 if (va & 7)
4329 {
4330 ui->warning("%s requires the address argument to be 8 byte aligned\n",cmd);
4331 va &= ~7ull;
4332 }
4333
4334 Vcpu* vcpu = g_vcpu[cpu_id];
4335 if (vcpu == 0)
4336 {
4337 ui->error("cpu %d not available\n",cpu_id);
4338 return 1;
4339 }
4340
4341 int fail = vcpu->set_asi(asi,va,data);
4342
4343 if (fail)
4344 {
4345 ui->error("0x%02llx:0x%llx is not a valid non-translating asi:va pair\n",asi,va);
4346 return 1;
4347 }
4348
4349 return 0;
4350}
4351
4352///////////////////////////////////////////////
4353//
4354// ECHO
4355//
4356int static echo_ui_cmd (void*, int argc, char **argv)
4357{
4358 for (int i = 1; i < argc; ++i)
4359 {
4360 const char* arg = argv[i];
4361 if (arg[0] == '"')
4362 {
4363 int len = strlen(arg);
4364 if (len > 2 && arg[len-1] == '"')
4365 {
4366 ui->output("%.*s ", len-2, &arg[1]);
4367 continue;
4368 }
4369 }
4370 ui->output("%s ", arg);
4371 }
4372 ui->output("\n");
4373 return 0;
4374}
4375
4376///////////////////////////////////////////////
4377//
4378// LIST-BREAKPOINTS
4379//
4380int static list_breakpoints_ui_cmd (void*, int argc, char **argv)
4381{
4382 // printout all existing breakpoints
4383 for (int i=0; i<=g_vcpu_id_max; i++)
4384 {
4385 if (g_vcpu[i])
4386 {
4387 g_vcpu[i]->print_breakpoints(ui->get_output_file());
4388 if (ui->get_log_file())
4389 g_vcpu[i]->print_breakpoints(ui->get_log_file());
4390 }
4391 }
4392 return 0;
4393}
4394
4395