Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / cpu_interface.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: cpu_interface.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////////////////////////////////////////////////////////////
22//
23// File: cpu_interface.cc
24//
25// Copyright (C) 2005 Sun Microsystems, Inc.
26// All rights reserved.
27//
28
29#include <dlfcn.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <ctype.h>
33#include "types.h"
34#include "blaze_globals.h"
35#include "cpu_interface.h"
36#include "spix_sparc.h"
37#include "system.h"
38#include "ui.h"
39#include "command_opts.h"
40
41
42// This file implements C++ interface for the
43// cpu shared library
44
45
46void *cpu_lib_handle = NULL;
47char cpu_lib_name[160] = "lib.unknown.cpu.type";
48
49// global vcpu table
50Vcpu *g_vcpu[NCPU_MAX];
51int g_nvcpu = 0; // total number of vcpu's
52int g_vcpu_id_max = 0; // max id of the vcpu
53
54VCPU_ExInterface g_cpu_ex_intf;
55
56extern int pselect_cpu_id;
57
58// parameter names
59#define INST_NAME "name"
60#define CPU_TYPE "cpu-type"
61#define MMU_TYPE "mmu-type"
62#define DTLB_SIZE "dtlb-entries"
63#define ITLB_SIZE "itlb-entries"
64#define CLOCK "clock-frequency"
65#define SCLOCK "system-frequency"
66#define LOOPTICKS "cpu-loopticks"
67#define STICKINCR "cpu-stickincr"
68#define NWINS "cpu-nwins"
69#define TLMAX "cpu-tlmax"
70#define CPU_ID "id"
71
72// cpu ui commands
73static int pregs_ui_cmd (void *, int argc, char **argv);
74static int fpregs_ui_cmd (void *, int argc, char **argv);
75static int cmpregs_ui_cmd (void *, int argc, char **argv);
76static int read_reg_ui_cmd (void *, int argc, char **argv);
77static int set_pc_ui_cmd (void *, int argc, char **argv);
78static int write_reg_ui_cmd (void *, int argc, char **argv);
79static int regs_ui_cmd (void *, int argc, char **argv);
80static int pc_ui_cmd (void *, int argc, char **argv);
81static int cpuregs_ui_cmd (void *, int argc, char **argv);
82
83
84static int pregs_cmd_usage ();
85static int fpregs_cmd_usage ();
86static int cmpregs_cmd_usage ();
87static int read_reg_cmd_usage ();
88static int set_pc_cmd_usage ();
89static int write_reg_cmd_usage();
90static int print_reg_cmd_usage();
91static int cpuregs_cmd_usage ();
92
93//////////////////////////////////////////////////////////////
94//
95// set configuration parameter
96//
97// Configuration informaion is encoded in
98// name=<value> pairs
99//
100
101
102int set_param
103(
104 char * name_value, // parameter name=value string
105 VCPU_Config *config // set value in this sructure
106)
107{
108 // get param name
109 char *name = strtok ( name_value, " =" );
110 if (name == NULL)
111 {
112 ui->error("cannot read cpu param name %s\n", name_value);
113 return 1;
114 }
115
116 // get param value
117 char *param = strtok ( NULL, "\0" );
118 if (param == NULL)
119 {
120 ui->error("cannot read cpu param value %s\n", name_value);
121 return 1;
122 }
123
124
125 if (strcmp ( name, CPU_TYPE) == 0 )
126 {
127 config->type = strdup ( param ) ;
128 }
129 else if (strcmp ( name, INST_NAME) == 0 )
130 {
131 config->name = strdup ( param ) ;
132 }
133 else if (strcmp ( name, MMU_TYPE) == 0 )
134 {
135 config->mmu_type = strdup ( param ) ;
136 }
137 else if (strcmp ( name, NWINS) == 0 )
138 {
139 config->reg_wins = (int)strtol(param, NULL, 0);
140 }
141 else if (strcmp ( name, TLMAX ) == 0 )
142 {
143 config->tl_max = (int)strtol(param, NULL, 0);
144 }
145 else if (strcmp ( name, DTLB_SIZE ) == 0 )
146 {
147 config->dtlb_size = (int)strtol(param, NULL, 0);
148 }
149 else if (strcmp ( name, ITLB_SIZE ) == 0 )
150 {
151 config->itlb_size = (int)strtol(param, NULL, 0);
152 }
153 else if (strcmp ( name, CLOCK ) == 0 )
154 {
155 config->cpufreq = (unsigned long long)strtoull(param, NULL, 0);
156 }
157 else if (strcmp ( name, SCLOCK ) == 0 )
158 {
159 ui->warning("param %s %s is not supported \n", name, param);
160 }
161 else if (strcmp ( name, STICKINCR ) == 0 )
162 {
163 config->stickincr = (int)strtol(param, NULL, 0);
164 }
165 else if (strcmp ( name, LOOPTICKS ) == 0 )
166 {
167 config->loopticks = (int)strtol(param, NULL, 0);
168 }
169 else if(strcmp(name ,CPU_ID) == 0)
170 {
171 config->id = (int)strtol(param,NULL,0);
172 if (config->id >= NCPU_MAX)
173 {
174 ui->error("cpu id %d cannot exceed %d\n", config->id, NCPU_MAX );
175 return 1;
176 }
177 }
178 else
179 {
180 ui->error("unknown cpu param: %s\n", name);
181 return 1;
182 }
183
184 return 0;
185}
186
187///////////////////////////////////////////////////////////
188//
189// get cpu config parameter string based on param name
190//
191static char *get_param ( char *name, VCPU_Config *config )
192{
193 static char param_value[40];
194
195 sprintf ( param_value, "unknown parameter" );
196
197 if (strcmp ( name, CPU_TYPE ) == 0 )
198 {
199 sprintf ( param_value, "%s", config->type );
200 }
201 else if (strcmp ( name, INST_NAME) == 0 )
202 {
203 sprintf ( param_value, "%s", config->name );
204 }
205 else if (strcmp ( name, MMU_TYPE) == 0 )
206 {
207 sprintf ( param_value, "%s", config->mmu_type );
208 }
209 else if (strcmp ( name, NWINS) == 0 )
210 {
211 sprintf ( param_value, "%i", config->reg_wins );
212 }
213 else if (strcmp ( name, TLMAX ) == 0 )
214 {
215 sprintf ( param_value, "%i", config->tl_max );
216 }
217 else if (strcmp ( name, DTLB_SIZE ) == 0 )
218 {
219 sprintf ( param_value, "%i", config->dtlb_size );
220 }
221 else if (strcmp ( name, ITLB_SIZE ) == 0 )
222 {
223 sprintf ( param_value, "%i", config->itlb_size );
224 }
225 else if (strcmp ( name, SCLOCK ) == 0 )
226 {
227 sprintf ( param_value, "%i", config->stickfreq );
228 }
229 else if (strcmp ( name, CLOCK ) == 0 )
230 {
231 sprintf ( param_value, "%llu", config->cpufreq );
232 }
233 else if (strcmp ( name, STICKINCR ) == 0 )
234 {
235 sprintf ( param_value, "%i", config->stickincr );
236 }
237 else if (strcmp ( name, LOOPTICKS ) == 0 )
238 {
239 sprintf ( param_value, "%i", config->loopticks );
240 }
241 else if(strcmp(name ,CPU_ID) == 0)
242 {
243 sprintf ( param_value, "%i", config->id );
244 }
245 return param_value;
246}
247
248void set_default ( VCPU_Config &config )
249{
250 // set defaullt values
251 config.name = NULL;
252 config.type = NULL; //strdup("SUNW,UltraSPARC-II");
253 config.mmu_type = NULL;
254 config.cpu_type = VCPU_IMPL_VER_NONE; // encoded cpu impl version
255 config.reg_wins = 8; // number of reg windows
256 config.tl_max = 7; // trap level max
257 config.itlb_size = 64; // number of tlb entries
258 config.dtlb_size = 64;
259 config.stickincr= 1; // the amount stick has to be incremented
260
261 // a person doing simulation ought to know these values
262 // have to be initialized in the rc file ... Sreenivas
263///* not to break the regression without changes available in rc file
264 config.loopticks= 25; // number of instruction per one update of stick
265 config.cpufreq = 1000000; // cpu clock
266 config.stickfreq= 10000; // system clock
267//*/
268 config.cpi = 1; // cycles per instruction
269 config.delay = 0; // delay this number of instructions
270 config.mode = 1; // all cpu's on separate threads
271 config.trace_on = 0; // tracing is off
272 config.id = -1;
273
274 config.execution_driven = 0;
275}
276
277//////////////////////////////////////////////////////////////
278//
279// parse config string
280//
281static int process_config_cmd
282(
283 char *config_cmd, // config string: name=value pairs
284 VCPU_Config *config // return config structure
285)
286{
287
288 char param_delimiter[] = " \0";
289
290 // make a copy because strtok() will write the termination chars
291 char *cmd = strdup ( config_cmd );
292
293 int n_param = 0; // param counter
294 int status = 0;
295
296 for (
297 char *name_value = strtok ( cmd, param_delimiter );
298 name_value != NULL;
299 name_value = strtok ( NULL, param_delimiter )
300 )
301 {
302 if ( set_param ( name_value, config ) != 0 )
303 {
304 ui->error("cannot set cpu param %s\n", name_value);
305 status++;
306 break;
307 }
308
309 n_param++;
310 }
311
312 free (cmd);
313
314 if (n_param ==0)
315 {
316 ui->error("there are no cpu config params\n");
317 return 1;
318 }
319
320
321 return status;
322
323}
324
325
326int deprecated_read_cmd (void *, int argc, char **argv)
327{
328 ui->error("This command is deprecated, use read-reg command instead.\n");
329 return 0;
330}
331
332int deprecated_write_cmd (void *, int argc, char **argv)
333{
334 ui->error("This command is deprecated, use write-reg command instead.\n");
335 return 0;
336}
337
338
339//////////////////////////////////////////////////////////////
340//
341// Create a new cpu instance
342//
343Vcpu* create_cpu
344(
345 char *path, // library path
346 char *pconfig, // config line with name=value pairs
347 VCPU_ImpIntf *intf, // cpu imported interface
348 int version // cpu lib version number
349)
350{
351 VCPU_Config config_info;
352
353 // process cpu config command
354 // fill out config_info structure
355 if ( process_config_cmd (pconfig, &config_info) != 0 )
356 {
357 ui->error("Invalid Cpu config information \n");
358 exit (1);
359 }
360
361
362 return create_cpu ( path, config_info, intf, version );
363
364}
365
366//////////////////
367Vcpu* create_cpu
368(
369 char *path, // library path
370 VCPU_Config &config_info, // cpu config params
371 VCPU_ImpIntf *intf, // cpu imported interface
372 int version // cpu lib version number
373)
374{
375 static bool id_from_sysconf = true; // expect id from sysconf
376
377 if ( config_info.type == NULL )
378 {
379 ui->error("missing cpu type information \n");
380 exit (1);
381 }
382
383 // either id is present on all lines, or its not present on any
384 // sysconf line. no intermixing is allowed
385 if(config_info.id == -1){
386 // sid is not provided on sysconf line. assign sid = vid
387 config_info.id = g_nvcpu;
388 if(g_nvcpu == 0) // first vcpu
389 id_from_sysconf = false;
390 if(id_from_sysconf){
391 ui->error("cpu id is being assigned implicitly. sysconf file error\n");
392 exit(1);
393 }
394 }else{
395 if(!id_from_sysconf){
396 ui->error("cpu id missing. sysconf file error\n");
397 exit(1);
398 }
399 }
400
401 if (!cpu_lib_handle) // first cpu
402 {
403 // register cpu related ui commands
404 UI_register_cmd_2 ("cpuregs", "print cpu register names", cpuregs_ui_cmd, cpuregs_cmd_usage );
405 UI_register_cmd_2 ("pregs", "print cpu architecture registers", pregs_ui_cmd, pregs_cmd_usage);
406 UI_register_cmd_2 ("fpregs", "print floating-point registers", fpregs_ui_cmd, fpregs_cmd_usage);
407 UI_register_cmd_2 ("cmpregs", "print cmp registers", cmpregs_ui_cmd, cmpregs_cmd_usage);
408 UI_register_cmd_2 ("read-reg", "read a register by name", read_reg_ui_cmd, read_reg_cmd_usage);
409 UI_register_cmd_2 ("write-reg","write value to a register", write_reg_ui_cmd, write_reg_cmd_usage);
410 UI_register_cmd_2 ("set-pc", "set pc for current cpu", set_pc_ui_cmd, set_pc_cmd_usage);
411 UI_register_cmd_2 ("pc", "print current pc for all cpus", pc_ui_cmd, NULL);
412 UI_register_cmd_2 ("r", "print cpu regs", regs_ui_cmd, print_reg_cmd_usage);
413
414 UI_register_cmd_2 ("read-fp-reg-i", "print floating point single register as integer", deprecated_read_cmd, NULL);
415 UI_register_cmd_2 ("read-fp-reg-x", "print floating point double register as integer", deprecated_read_cmd, NULL);
416 UI_register_cmd_2 ("read-th-ctl-reg", "print a control register value of a strand" , deprecated_read_cmd, NULL);
417 UI_register_cmd_2 ("read-th-fp-reg-i", "print a single fp register value of a strand" , deprecated_read_cmd, NULL);
418 UI_register_cmd_2 ("read-th-fp-reg-x", "print a double fp register value of a strand" , deprecated_read_cmd, NULL);
419 UI_register_cmd_2 ("read-th-reg", "print an integer register value of a strand" , deprecated_read_cmd, NULL);
420
421 UI_register_cmd_2 ("write-fp-reg-i", "write floating point single register as integer", deprecated_write_cmd, NULL);
422 UI_register_cmd_2 ("write-fp-reg-x", "write floating point double register as integer", deprecated_write_cmd, NULL);
423 UI_register_cmd_2 ("write-th-ctl-reg", "write a control register value of a strand" , deprecated_write_cmd, NULL);
424 UI_register_cmd_2 ("write-th-fp-reg-i","write floating point single register as integer", deprecated_write_cmd, NULL);
425 UI_register_cmd_2 ("write-th-fp-reg-x","write double fp register value of a strand" , deprecated_write_cmd, NULL);
426 UI_register_cmd_2 ("write-th-reg", "write integer register value of a strand" , deprecated_write_cmd, NULL);
427
428 }
429
430
431 // generate cpu library name from the config info
432 char lib_name[160];
433 sprintf(lib_name,"lib%s.so", config_info.type );
434
435
436 if (strcmp(lib_name, cpu_lib_name)!=0) // library was not loaded yet
437 {
438 // open shared library;
439 extern void * mod_dlopen (char * pathp, char * name, int flags);
440 cpu_lib_handle = mod_dlopen (path, lib_name, RTLD_LAZY|RTLD_GLOBAL|RTLD_PARENT);
441
442
443 // remember last opened cpu library
444 strlcpy ( cpu_lib_name, lib_name, 160 );
445 }
446
447 if ( cpu_lib_handle == NULL )
448 {
449 ui->error("Cannot find cpu library %s \n", lib_name );
450 exit (1);
451 }
452
453 // extract lib exported interface
454 VCPU_GetIntfFn get_interface = (VCPU_GetIntfFn)dlsym ( cpu_lib_handle, "get_ex_interface" );
455
456 if (get_interface == NULL)
457 {
458 ui->error("Cannot find cpu exported interface \n");
459 exit (1);
460 }
461
462 // obtain cpu interface
463 get_interface ( &g_cpu_ex_intf);
464
465
466
467 // create cpu instance
468 Vcpu * vcpu = (Vcpu*)g_cpu_ex_intf.create( &config_info, intf );
469 if ( vcpu == NULL )
470 {
471 ui->error("Cannot create Cpu %s \n", config_info.name);
472 exit (1);
473 }
474
475 int sid = vcpu->config.id;
476 g_vcpu[sid] = vcpu;
477
478 // total number of vcpu's
479 g_nvcpu ++;
480
481 // max id of the vcpu
482 if (g_vcpu_id_max < sid)
483 g_vcpu_id_max = sid;
484
485
486 return vcpu;
487
488}
489
490
491
492// cofiguration parameters
493int set_param ( int cpu_id, char *param_name )
494{
495 Vcpu *vcpu = get_vcpu(cpu_id);
496 if (!vcpu)
497 return 0;
498
499 return set_param (param_name, &(vcpu->config));
500}
501char *get_param ( int cpu_id, char *param_name )
502{
503 Vcpu *vcpu = get_vcpu(cpu_id);
504 if (!vcpu)
505 return 0;
506
507 return get_param (param_name, &(vcpu->config));
508}
509
510// set a breakpoint from a remote debugger
511int cpu_set_breakpoint ( int cpu_id, VCPU_BpType type, uint64_t addr )
512{
513 int bp_id;
514 extern int bp_action ( int bp_id, int vcpu_id );
515 Vcpu * vcpu = get_vcpu(cpu_id);
516 if(!vcpu)
517 return 0;
518 return vcpu->set_breakpoint( &bp_id,type, addr, bp_action );
519}
520
521// remove a breakpoint
522int cpu_remove_breakpoint ( int cpu_id, VCPU_BpType type, uint64_t addr )
523{
524 Vcpu * vcpu = get_vcpu(cpu_id);
525 if(!vcpu)
526 return 0;
527 return vcpu->delete_breakpoint();
528}
529
530/////////////////////////////////////////////////////////
531//
532// Disassemble instruction
533//
534int disassemble (uint32_t iw, uint64_t pc, char *buf, int size )
535{
536
537 if (
538 ! spix_sparc_dis( buf, size,
539 spix_sparc_iop(SPIX_SPARC_V9, &iw),
540 &iw, pc )
541 )
542 {
543 sprintf ( buf, "unknown" );
544 return 0;
545 }
546 return 1;
547}
548
549
550///////////////////////////////////////////////////////
551//
552// Read vcpu regs from the ui
553//
554
555int print_reg_cmd_usage()
556{
557 ui->output("usage: r [-cpu <id>] [-w [<wp>]|-g [<gwp>]|-f|df|-pr|-asr|-hpr|-tr <tr_level>|-asi <asi> <va>]\n");
558 return 0;
559}
560int regs_ui_cmd (void *, int argc, char **argv)
561{
562 if (!IN_STOP_STATE (blaze_run_state))
563 {
564 ui->error("not in stop state, use stop command first\n");
565 return 0;
566 }
567
568 int cpuid = 0;
569 int greg = 0;
570 int wreg = 0;
571 int gl = -1;
572 int wp = -1;
573 int freg = 0;
574 int dfreg = 0;
575 int pr = 0;
576 int asr = 0;
577 int hpr = 0;
578 int tr = 0;
579 int tl = 1;
580
581 int asi = 0;
582 uint8_t asi_i = 0;
583 uint64_t asi_va = 0;
584
585 Vcpu *cpu = 0;
586
587 for(int i=1; i<argc; i++)
588 {
589 // check reg type
590 if (strcmp(argv[i], "-w")==0)
591 {
592 wreg = 1;
593 if (((i+1)<argc) && isdigit(argv[i+1][0]))
594 wp = int(strtol(argv[++i], NULL, 0));
595 continue;
596 }
597 else if (strcmp(argv[i], "-g")==0)
598 {
599 greg = 1;
600 if ( ((i+1)<argc) && isdigit(argv[i+1][0]) )
601 gl = int(strtol(argv[++i], NULL, 0));
602 continue;
603 }
604 else if (strcmp(argv[i], "-f")==0) freg = 1;
605 else if (strcmp(argv[i], "-df")==0) dfreg = 1;
606 else if (strcmp(argv[i], "-pr")==0) pr = 1;
607 else if (strcmp(argv[i], "-asr")==0) asr = 1;
608 else if (strcmp(argv[i], "-hpr")==0) hpr = 1;
609 else if ((strcmp(argv[i], "-asi")==0) && ((i+2)<argc))
610 {
611 asi_i = uint8_t(strtol(argv[++i], NULL, 0));
612 asi_va = strtoll(argv[++i], NULL, 0);
613 asi = 1;
614 continue;
615 }
616 else if ((strcmp(argv[i], "-tr")==0) && ((i+1)<argc))
617 {
618 tr = 1;
619 tl = int(strtol(argv[++i], NULL, 0));
620 if (tl < 1) tl = 1;
621 continue;
622 }
623 else if ((strcmp(argv[i], "-cpu")==0) && ((i+1)<argc))
624 {
625 cpuid = int(strtol(argv[++i], NULL, 0));
626 if(cpuid<0) cpuid = 0;
627 cpu = get_vcpu(cpuid);
628 if(!cpu)
629 ui->error("cpu[%d] is not available\n",cpuid);
630 continue;
631 }
632 else if (strcmp(argv[i], "?")==0)
633 {
634 print_reg_cmd_usage();
635 return 0;
636 }
637 }
638
639 if (!( greg||wreg||freg||dfreg||pr||asr||hpr||tr|asi) )
640 return print_reg_cmd_usage();
641
642
643 if(!cpu) // no cpu id was selected
644 {
645 cpu = get_vcpu(pselect_cpu_id);
646 if(!cpu)
647 {
648 ui->error("cpu[%d] is not available\n",cpuid);
649 return 0;
650 }
651 cpuid = pselect_cpu_id;
652 }
653
654 ui->output ( "cpu[%i]:",cpuid);
655
656 if (asi)
657 {
658 uint64_t value = 0;
659 ui->output ("asi 0x%x, va=0x%llx, ", asi_i, asi_va);
660 if (cpu->get_asi(asi_i, asi_va, value) == 0)
661 ui->output ("value = 0x%llx \n", value);
662 else
663 ui->error ("unknown \n");
664 }
665
666 if (wreg)
667 {
668 uint64_t max_wp;
669 uint64_t cur_wp;
670
671 cpu->get_reg(VCPU_SIM_MAX_WP,&max_wp);
672 cpu->get_reg(VCPU_PR_CWP,&cur_wp);
673
674 ui->output ( "\nwindowed R registers,");
675
676 if (wp < 0) {
677 wp = cur_wp;
678 ui->output (" wp=%d (current)\n",wp);
679 } else {
680 if (wp > max_wp)
681 wp = max_wp;
682 ui->output (" wp=%d\n", wp);
683 }
684
685 cpu->set_reg(VCPU_PR_CWP,wp);
686
687 for (int i=0; i<8; i++)
688 {
689 uint64_t value = 0;
690 cpu->get_reg(VCPU_IRF_0 + i + 8, &value); // o regs
691 ui->output ("%s=0x%016llx ", cpu->get_reg_name(VCPU_IRF_0 + i + 8), value);
692 cpu->get_reg(VCPU_IRF_0 + i + 16, &value); // l regs
693 ui->output ("%s=0x%016llx ", cpu->get_reg_name(VCPU_IRF_0 + i + 16), value);
694 cpu->get_reg(VCPU_IRF_0 + i + 24, &value); // i regs
695 ui->output ("%s=0x%016llx\n", cpu->get_reg_name(VCPU_IRF_0 + i + 24), value);
696 }
697
698 cpu->set_reg(VCPU_PR_CWP,cur_wp);
699 }
700
701 if (greg)
702 {
703 uint64_t max_gl;
704 uint64_t cur_gl;
705
706 cpu->get_reg(VCPU_SIM_MAX_GL,&max_gl);
707 cpu->get_reg(VCPU_PR_GL,&cur_gl);
708
709 ui->output ( "\nglobal R registers,");
710
711 if (gl < 0) {
712 gl = cur_gl;
713 ui->output (" gl=%d (current)\n",gl);
714 } else {
715 if (gl > max_gl)
716 gl = max_gl;
717 ui->output (" gl=%d\n", gl);
718 }
719
720 cpu->set_reg(VCPU_PR_GL,gl);
721
722 for (int i=0; i<8; i++)
723 {
724 uint64_t value = 0;
725 cpu->get_reg(VCPU_IRF_0 + i, &value);
726 ui->output ("%s=0x%016llx\n", cpu->get_reg_name(VCPU_IRF_0 + i), value);
727 }
728
729 cpu->set_reg(VCPU_PR_GL,cur_gl);
730 }
731
732
733 if (freg)
734 {
735 ui->output ( "\nfloating point registers\n");
736
737 for (int i=0; i<32; i++)
738 {
739 uint64_t value = 0;
740 cpu->get_reg(VCPU_FRF_0 + i, &value);
741 uint32_t val32 = uint32(value);
742 ui->output ( "f%-2i = %e\n", i, val32);
743 }
744 }
745
746 if (dfreg)
747 {
748 ui->output ( "\ndouble floating point registers\n");
749
750 for (int i=0; i<63; i+=2)
751 {
752 uint64_t value = 0;
753 if (cpu->get_reg(VCPU_DRF_0 + i/2, &value) == 0)
754 ui->output ( "d%-2i = %e\n", i, value);
755 }
756
757 }
758
759 if (pr)
760 {
761 ui->output ( "\nPR registers\n");
762
763 for (int i=0; i<32; i++)
764 {
765 uint64_t value = 0;
766 if (cpu->get_reg(VCPU_PR_0 + i, &value) == Vcpu::REG_OK)
767 {
768 ui->output ( "pr%-2d %16s = 0x%llx\n", i, cpu->get_reg_name(VCPU_PR_0 + i), value);
769 }
770 }
771 }
772
773 if (asr)
774 {
775 ui->output ( "\nASR registers\n");
776
777 for (int i=0; i<32; i++)
778 {
779 uint64_t value = 0;
780 if (cpu->get_reg(VCPU_ASR_0 + i, &value) == Vcpu::REG_OK)
781 {
782 ui->output ( "asr%-2d %16s = 0x%llx\n", i, cpu->get_reg_name(VCPU_ASR_0 + i), value);
783 }
784 }
785 }
786
787 if (hpr)
788 {
789 ui->output ( "\nHPR registers\n");
790
791 for (int i=0; i<32; i++)
792 {
793 uint64_t value = 0;
794 if (cpu->get_reg(VCPU_HPR_0 + i, &value) == Vcpu::REG_OK)
795 ui->output ( "hpr%-2d %16s = 0x%llx\n", i, cpu->get_reg_name(VCPU_HPR_0 + i), value);
796 }
797
798 }
799
800 if (tr)
801 {
802 uint64_t max_tl;
803 uint64_t cur_tl;
804
805 cpu->get_reg(VCPU_SIM_MAX_TL,&max_tl);
806 cpu->get_reg(VCPU_PR_TL,&cur_tl);
807
808 ui->output ( "\ntrap registers, tl=%i\n", tl);
809
810 if (tl < 0) {
811 tl = cur_tl;
812 ui->output (" tl=%d (current)\n",tl);
813 } else {
814 if (tl > max_tl)
815 tl = max_tl;
816 ui->output (" tl=%d\n", tl);
817 }
818
819 cpu->set_reg(VCPU_PR_TL,tl);
820
821 uint64_t value = 0;
822 cpu->get_reg(VCPU_PR_TPC,&value);
823 ui->output ( "tpc = 0x%llx\n", value);
824 cpu->get_reg(VCPU_PR_TNPC,&value);
825 ui->output ( "tnpc = 0x%llx\n", value);
826 cpu->get_reg(VCPU_PR_TSTATE,&value);
827 ui->output ( "tstate = 0x%llx\n", value);
828 cpu->get_reg(VCPU_PR_TT,&value);
829 ui->output ( "tt = 0x%llx\n", value);
830 if (cpu->get_reg(VCPU_HPR_HTSTATE,&value) == Vcpu::REG_OK)
831 ui->output ( "htstate = 0x%llx\n", value);
832
833 cpu->set_reg(VCPU_PR_TL,cur_tl);
834 }
835
836 ui->output("\n");
837 return 0;
838}
839
840
841
842///////////////////////////////////////////////////////
843//
844// single step one vcpu only
845//
846int sstep_cmd (int cpu_id)
847{
848 if (!IN_STOP_STATE (blaze_run_state))
849 {
850 ui->error("not in stop state, use stop command first\n");
851 return 0;
852 }
853
854 Vcpu *vcpu = get_vcpu(cpu_id);
855 if (!vcpu)
856 return 0;
857
858 vcpu->stepi(1);
859
860 return 1;
861}
862
863
864
865/////////////////////////////////////////////////////////////////////
866//
867int pc_ui_cmd (void *, int argc, char **argv)
868{
869 for (int i=0; i<=g_vcpu_id_max; i++)
870 {
871 Vcpu *vcpu = get_vcpu(i);
872 if (!vcpu)
873 continue;
874
875 uint64_t pc = 0xdead;
876 vcpu->get_reg(VCPU_ASR_PC, &pc);
877 ui->output ("cpu[%i]: pc=0x%llx \n", i, pc);
878 }
879 return 1;
880}
881
882
883
884////////////////////////////////////////////////////////////////////////
885//
886// SAM FE command
887//
888
889// read register by name
890int cpu_read_register_name ( char *cmd )
891{
892 if (!IN_STOP_STATE(blaze_run_state))
893 {
894 ui->error("not in stop state, use stop command first\n");
895 return 0;
896 }
897
898 Vcpu* vcpu = g_vcpu[pselect_cpu_id];
899 if (vcpu == 0)
900 {
901 ui->error("cpu[%d] is not available\n", pselect_cpu_id);
902 return 0;
903 }
904 else
905 {
906 int index;
907 uint64_t value;
908 const int max_reg_name = 128;
909 char reg_name[max_reg_name];
910 strlcpy(reg_name, cmd, max_reg_name);
911
912 char *name = strtok ( reg_name, " \n\0" );
913 char *parm = strtok ( NULL, " \n\0" );
914
915 if (!name || parm)
916 {
917 ui->error("\nusage: %%reg_name , to list register names use 'cpuregs' command\n");
918 return 0;
919 }
920 if ( (vcpu->get_reg_index( reg_name, &index )==Vcpu::REG_OK) &&
921 (vcpu->get_reg( index, &value )==Vcpu::REG_OK))
922 {
923 ui->output("0x%llx\n", value);
924 }
925 else
926 {
927 ui->error("cpu[%d] register %s is not available\n", pselect_cpu_id, reg_name);
928 return 0;
929 }
930 }
931 return 1;
932}
933
934////////////////////////////////////////////////////////////
935//
936// pregs command
937//
938int pregs_cmd_usage()
939{
940 ui->output("\nusage : pregs [-cpu cpu_set]]\n");
941 return 0;
942}
943int pregs_ui_cmd(void *, int argc, char **argv)
944{
945 if (!IN_STOP_STATE (blaze_run_state))
946 {
947 ui->error("not in stop state, use stop command first\n");
948 return 0;
949 }
950
951 char *cmd = "pregs";
952 CommandOptions option;
953 CpuOption cpu_option(pselect_cpu_id,CpuOption::MULTITUDE);
954 option.add(cpu_option);
955 std::vector<std::string> args;
956 if (!option.parse(argc-1,(const char**)&argv[1],args))
957 {
958 ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str());
959 return 0;
960 }
961 if (args.size() != 0)
962 return pregs_cmd_usage();
963
964
965 CpuSet& cpu_set = cpu_option.get_value();
966
967 for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i)
968 {
969 uint32_t cpu_id = *i;
970 ui->output("cpu[%d]: \n",cpu_id);
971 Vcpu* vcpu = g_vcpu[cpu_id];
972 if (vcpu == 0)
973 {
974 ui->error("cpu[%d] is not available\n", cpu_id);
975 continue;
976 }
977
978 // pr
979 for (int i=0; i<32; i++)
980 {
981 uint64_t value = 0;
982 if (vcpu->get_reg(VCPU_PR_0 + i, &value) == Vcpu::REG_OK)
983 {
984 ui->output ( "pr%3d %16s = 0x%llx\n", i, vcpu->get_reg_name(VCPU_PR_0 + i), value);
985 }
986 }
987
988 // asr
989 for (int i=0; i<32; i++)
990 {
991 uint64_t value = 0;
992 if (vcpu->get_reg(VCPU_ASR_0 + i, &value) == Vcpu::REG_OK)
993 {
994 ui->output ( "asr%2d %16s = 0x%llx\n", i, vcpu->get_reg_name(VCPU_ASR_0 + i), value);
995 }
996 }
997
998 // hpr
999 for (int i=0; i<32; i++)
1000 {
1001 uint64_t value = 0;
1002 if (vcpu->get_reg(VCPU_HPR_0 + i, &value) == Vcpu::REG_OK)
1003 ui->output ( "hpr%2d %16s = 0x%llx\n", i, vcpu->get_reg_name(VCPU_HPR_0 + i), value);
1004 }
1005
1006 }
1007
1008 return 1;
1009}
1010
1011/////////////////////////////////////////////////////////////
1012//
1013// fpregs command
1014//
1015int fpregs_cmd_usage()
1016{
1017 ui->error("\nusage : fpregs [-cpu cpu_set]]\n");
1018 return 0;
1019}
1020int fpregs_ui_cmd(void *, int argc, char **argv)
1021{
1022 if (!IN_STOP_STATE (blaze_run_state))
1023 {
1024 ui->error("not in stop state, use stop command first\n");
1025 return 0;
1026 }
1027
1028 char *cmd = "fpregs";
1029 CommandOptions option;
1030 CpuOption cpu_option(pselect_cpu_id,CpuOption::MULTITUDE);
1031 option.add(cpu_option);
1032 std::vector<std::string> args;
1033 if (!option.parse(argc-1,(const char**)&argv[1],args))
1034 {
1035 ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str());
1036 return 0;
1037 }
1038 if (args.size() != 0)
1039 return fpregs_cmd_usage();
1040
1041
1042 CpuSet& cpu_set = cpu_option.get_value();
1043
1044 for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i)
1045 {
1046 uint32_t cpu_id = *i;
1047 Vcpu* vcpu = g_vcpu[cpu_id];
1048 if (vcpu == 0)
1049 {
1050 ui->error("cpu[%d] is not available\n", cpu_id);
1051 continue;
1052 }
1053 ui->output("cpu[%d]: ",cpu_id);
1054
1055 int index;
1056 uint64_t value = 0;
1057 const char *fsr = "fsr";
1058 if ( (vcpu->get_reg_index( fsr, &index )==Vcpu::REG_OK) &&
1059 (vcpu->get_reg( index, &value )==Vcpu::REG_OK))
1060 ui->output("%s=0x%llx\n",fsr, value);
1061
1062 for (int i=0; i<63; i+=2)
1063 {
1064 uint64_t value = 0;
1065 if (vcpu->get_reg(VCPU_DRF_0 + i/2, &value) == 0)
1066 ui->output ( "d%-2i=0x%016llx ", i, value);
1067
1068 if (i < 32)
1069 ui->output ( "f%-2i=0x%08llx f%-2i=0x%08llx\n", i, uint32(value), i+1, uint32(value>>32));
1070 else
1071 ui->output("\n");
1072 }
1073 }
1074
1075 return 1;
1076}
1077
1078/////////////////////////////////////////////////////////////
1079//
1080// cmpregs command
1081//
1082int cmpregs_cmd_usage()
1083{
1084 ui->error("\nusage : cmpregs [-cpu cpu_set]]\n");
1085 return 0;
1086}
1087
1088int cmpregs_ui_cmd(void *, int argc, char **argv)
1089{
1090 if (!IN_STOP_STATE(blaze_run_state))
1091 {
1092 ui->error("not in stop state, use stop command first\n");
1093 return 0;
1094 }
1095
1096 char *cmd = "cmpregs";
1097 CommandOptions option;
1098 CpuOption cpu_option(pselect_cpu_id,CpuOption::MULTITUDE);
1099 option.add(cpu_option);
1100 std::vector<std::string> args;
1101 if (!option.parse(argc-1,(const char**)&argv[1],args))
1102 {
1103 ui->error("%s command: %s\n",cmd,option.get_error_msg().c_str());
1104 return 0;
1105 }
1106 if (args.size() != 0)
1107 return cmpregs_cmd_usage();
1108
1109
1110 CpuSet& cpu_set = cpu_option.get_value();
1111
1112 for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i)
1113 {
1114 uint32_t cpu_id = *i;
1115 ui->output("cpu[%d]: \n",cpu_id);
1116 Vcpu* vcpu = g_vcpu[cpu_id];
1117 if (vcpu == 0)
1118 {
1119 ui->error("cpu %d is not available\n", cpu_id);
1120 continue;
1121 }
1122
1123 uint64_t value = 0;
1124 if (vcpu->get_asi(0x41, 0x0 , value) == 0) ui->output ("STRAND_AVAILABLE 0x%016llx \n", value);
1125 if (vcpu->get_asi(0x41, 0x10, value) == 0) ui->output ("STRAND_ENABLE_STATUS 0x%016llx \n", value);
1126 if (vcpu->get_asi(0x41, 0x20, value) == 0) ui->output ("STRAND_ENABLE 0x%016llx \n", value);
1127 if (vcpu->get_asi(0x41, 0x30, value) == 0) ui->output ("XIR_STEERING 0x%016llx \n", value);
1128 if (vcpu->get_asi(0x41, 0x38, value) == 0) ui->output ("CMT_TICK_ENABLE 0x%016llx \n", value);
1129 if (vcpu->get_asi(0x41, 0x50, value) == 0) ui->output ("STRAND_RUNNING 0x%016llx \n", value);
1130 if (vcpu->get_asi(0x41, 0x58, value) == 0) ui->output ("STRAND_RUNNING_STATUS 0x%016llx \n", value);
1131 ui->output ("\n");
1132 }
1133
1134 return 1;
1135}
1136
1137
1138//////////////////////////////////////////////////
1139//
1140// cpuregs command
1141//
1142int cpuregs_cmd_usage()
1143{
1144 ui->error("\nusage : cpuregs \n");
1145 return 0;
1146}
1147int cpuregs_ui_cmd(void *, int argc, char **argv)
1148{
1149 if (!IN_STOP_STATE (blaze_run_state))
1150 {
1151 ui->error("not in stop state, use stop command first\n");
1152 return 0;
1153 }
1154
1155 Vcpu* vcpu = g_vcpu[pselect_cpu_id];
1156 if (!vcpu)
1157 {
1158 ui->error("cpu %d is not available\n", pselect_cpu_id);
1159 return 0;
1160 }
1161
1162 for (int i=0; i<=VCPU_MAX_INDEX;i++)
1163 {
1164 const char *reg_name = vcpu->get_reg_name(i);
1165 if (reg_name)
1166 {
1167 ui->output("%3d) %s\n", i, reg_name);
1168 }
1169 }
1170
1171 return 1;
1172}
1173
1174
1175
1176
1177//////////////////////////////////////////////////
1178//
1179// read-reg command
1180//
1181int read_reg_cmd_usage()
1182{
1183 ui->error("\nusage : read-reg [-cpu cpu_set] reg-name\n");
1184 return 0;
1185}
1186int read_reg_ui_cmd(void *, int argc, char **argv)
1187{
1188 if (!IN_STOP_STATE (blaze_run_state))
1189 {
1190 ui->error("not in stop state, use stop command first\n");
1191 return 0;
1192 }
1193
1194 char *cmd = "read-reg";
1195
1196 CommandOptions option;
1197 CpuOption cpu_option(pselect_cpu_id,CpuOption::MULTITUDE);
1198 option.add(cpu_option);
1199 std::vector<std::string> args;
1200 if (!option.parse(argc-1,(const char**)&argv[1],args))
1201 {
1202 ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str());
1203 return 0;
1204 }
1205 if (args.size() != 1)
1206 {
1207 ui->error("%s requires 1 positional argument - register name.\n",cmd);
1208 return 0;
1209 }
1210
1211 CpuSet& cpu_set = cpu_option.get_value();
1212
1213 for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i)
1214 {
1215 uint32_t cpu_id = *i;
1216 Vcpu* vcpu = g_vcpu[cpu_id];
1217 if (vcpu == 0)
1218 {
1219 ui->error("cpu[%d] is not available\n", cpu_id);
1220 continue;
1221 }
1222 int index;
1223 uint64_t value;
1224 const char *reg_name = args[0].c_str();
1225 if ( (vcpu->get_reg_index( reg_name, &index )==Vcpu::REG_OK) &&
1226 (vcpu->get_reg( index, &value )==Vcpu::REG_OK))
1227 {
1228 ui->output("cpu[%d]: %s=0x%llx\n",cpu_id, reg_name, value);
1229 }
1230 else
1231 {
1232 ui->error("cpu[%d] - register %s is not available\n", cpu_id, reg_name);
1233 return 0;
1234 }
1235 }
1236
1237
1238 return 1;
1239}
1240
1241
1242//////////////////////////////////////////////////
1243//
1244// set-pc command
1245//
1246int set_pc_cmd_usage()
1247{
1248 ui->error("\nusage : set-pc address\n");
1249 return 0;
1250}
1251int set_pc_ui_cmd(void *, int argc, char **argv)
1252{
1253 if (!IN_STOP_STATE (blaze_run_state))
1254 {
1255 ui->error("not in stop state, use stop command first\n");
1256 return 0;
1257 }
1258
1259 char *cmd = "set_pc";
1260
1261 CommandOptions option;
1262 CpuOption cpu_option(pselect_cpu_id);
1263 option.add(cpu_option);
1264 std::vector<std::string> args;
1265 if (!option.parse(argc-1,(const char**)&argv[1],args))
1266 {
1267 ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str());
1268 return 0;
1269 }
1270 if (args.size() != 1)
1271 {
1272 ui->error("%s requires 1 positional argument - pc value.\n",cmd);
1273 return 0;
1274 }
1275
1276 uint32_t cpu_id = *(cpu_option.get_value().begin());
1277
1278 Vcpu* vcpu = g_vcpu[cpu_id];
1279 if (vcpu == 0)
1280 {
1281 ui->error("cpu[%d] is not available\n", cpu_id);
1282 return 0;
1283 }
1284
1285 uint64_t value = strtoull(args[0].c_str(), NULL, 0);
1286
1287 if ( vcpu->set_reg( VCPU_ASR_PC, value )!=Vcpu::REG_OK)
1288 {
1289 ui->error(" cannot set pc value 0x%llx for cpu[%d]\n",value,cpu_id);
1290 return 0;
1291 }
1292
1293 return 1;
1294}
1295
1296
1297//////////////////////////////////////////////////
1298//
1299// write-reg command
1300//
1301
1302int write_reg_cmd_usage()
1303{
1304 ui->output("\nusage : write-reg [-cpu cpu_set] reg-name value\n");
1305 return 0;
1306}
1307int write_reg_ui_cmd(void *, int argc, char **argv)
1308{
1309 if (!IN_STOP_STATE (blaze_run_state))
1310 {
1311 ui->error("not in stop state, use stop command first\n");
1312 return 0;
1313 }
1314
1315 char *cmd = "write-reg";
1316
1317 CommandOptions option;
1318 CpuOption cpu_option(pselect_cpu_id);
1319 option.add(cpu_option);
1320 std::vector<std::string> args;
1321 if (!option.parse(argc-1,(const char**)&argv[1],args))
1322 {
1323 ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str());
1324 return 0;
1325 }
1326 if (args.size() != 2)
1327 {
1328 ui->error("%s requires 2 positional argument - reg name and value.\n",cmd);
1329 return 0;
1330 }
1331
1332 uint32_t cpu_id = *(cpu_option.get_value().begin());
1333
1334 Vcpu* vcpu = g_vcpu[cpu_id];
1335 if (vcpu == 0)
1336 {
1337 ui->error("cpu[%d] is not available\n", cpu_id);
1338 return 0;
1339 }
1340
1341 int index;
1342 uint64_t value = strtoull(args[1].c_str(), NULL, 0);
1343
1344 const char *reg_name = args[0].c_str();
1345 if ( (vcpu->get_reg_index( reg_name, &index )!=Vcpu::REG_OK) ||
1346 (vcpu->set_reg( index, value ) !=Vcpu::REG_OK) )
1347 {
1348 ui->error("cannot set reg %s=0x%llx for cpu[%d]\n",reg_name,value,cpu_id);
1349 return 0;
1350 }
1351
1352 return 1;
1353}
1354