Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / exe / nas / bin / SS_Main.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: SS_Main.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** Copyright (C) 2006, Sun Microsystems, Inc.
24**
25** Sun considers its source code as an unpublished, proprietary
26** trade secret and it is available only under strict license provisions.
27** This copyright notice is placed here only to protect Sun in the event
28** the source is deemed a published work. Disassembly, decompilation,
29** or other means of reducing the object code to human readable form
30** is prohibited by the license agreement under which this code is
31** provided to the user or company in possession of this copy.
32**
33*************************************************************************/
34//
35// @-ARCH-@_Main.cc is automatically generated from
36// ss/exe/nas/bin/Bl_Main.cc, do not modify @-ARCH-@_Main.cc
37// make necessary changes in ss/exe/nas/bin/Bl_Main.cc instead.
38//
39#include <string>
40#include "Python.h"
41#include "spix_sparc.h"
42
43#include "MemorySync.h"
44
45#include "SS_PliCommand.h"
46#include "SS_IrqSync.h"
47#include "SS_TlbSync.h"
48#include "SS_ValSync.h"
49#include "SS_ConfigObject.h"
50#include "SS_PliSocket.h"
51#include "SS_TrcStrand.h"
52#include "SS_GoodBadTrap.h"
53
54#include "@-ARCH-@_Model.h"
55#include "@-ARCH-VF-@_Cpu.h"
56#include "@-ARCH-VF-@_Core.h"
57#include "@-ARCH-VF-@_Strand.h"
58#include "@-ARCH-@_RegCompare.h"
59#include "@-ARCH-@_Csr.h"
60#include "@-ARCH-@_CsrReadWrite.h"
61
62#define MAIN_ARCH_@-ARCH-@
63
64static char error_buffer[80];
65
66using namespace std;
67
68class @-ARCH-@_Main : public @-ARCH-@_Model/*{{{*/
69{
70 public:
71 @-ARCH-@_Main();
72
73 void init( int record, int replay );
74 uint_t step( uint_t n );
75 void dump_regs( );
76 int set_record;
77 int set_replay;
78 int set_trace;
79
80 protected:
81 SS_TrcStrand* trc_strand[@-ARCH-@_Model::NO_STRANDS];
82 @-ARCH-@_RegCompare* reg_comp[@-ARCH-@_Model::NO_STRANDS];
83 SS_PliSocket pli_socket;
84 SS_TimedTlb* inst_tlb[@-ARCH-@_Model::NO_CORES];
85 SS_TimedTlb* data_tlb[@-ARCH-@_Model::NO_CORES];
86 SS_TlbSync* tlb_sync[@-ARCH-@_Model::NO_STRANDS];
87 SS_IrqSync* irq_sync[@-ARCH-@_Model::NO_STRANDS];
88 SS_ValSync* val_sync[@-ARCH-@_Model::NO_STRANDS];
89 MemorySync* mem_sync;
90
91 @-ARCH-@_Csr* csr;
92 @-ARCH-@_CsrReadWrite* csr_sync;
93
94 std::string cfg_replay_fn;
95 std::string cfg_record_fn;
96
97 int cfg_socket;
98 int cfg_cosim;
99 int cfg_replay;
100 int cfg_record;
101 int cfg_reg_comp; // Nonzero means send state changes to the pli socket (DUT)
102 int cfg_tlb_sync; // Nonzero means perform tlb syncing
103 int cfg_mem_sync; // Nonzero means perform mem syncing
104 int cfg_pli_debug; // Debug pli socket commands
105 int cfg_mem_debug; // Debug memory sync and tso checker
106 int cfg_tso_debug; // Nonzero means perform tso checking
107 int cfg_tlb_debug;
108 int cfg_standalone; // Nonzero means there is no RTL or replay
109 int cfg_rstv_mask;
110 int cfg_dump_regs;
111 int cfg_tlb_sync_size; // max number of TimedTlb to keep
112
113 inline int check_strand( int strand_id );
114 void create_cpu_extra( int new_cpu_cnt, int no_core );
115 int count_core( string mask );
116 void cmp_init( int cpu_id, string mask, int ii=0 );
117 void cmp_write( int cpu_id, SS_PliCommand_CMP_WRITE& arg );
118 void pli_trace( uint_t tid );
119 void pli_trace_0x0( uint_t tid, uint64_t trc_pc );
120
121 SS_Registers::Index asr2index( uint8_t idx );
122
123 void set_cmpr_list(string sub, bool exclude);
124
125 uint_t step_count;
126
127 SS_GoodBadTrap gbt;
128
129 // INTP '00 00' is used to indicate a system-wide POR or warm-reset, the
130 // first time it shows up is before any 'STEP' command is issued, which
131 // indicates a POR. If it shows up again later, then it means a warm-reset,
132 // we will have to set the system to a warm-reset state in such case.
133 int intp0_count;
134 // the first INTP 'xx 01' for each strand is considered POW, after that
135 // it is WMR
136 bool first_intp1[@-ARCH-@_Model::NO_STRANDS];
137};
138/* }}}*/
139
140@-ARCH-@_Main::@-ARCH-@_Main()/*{{{*/
141 :
142 set_record(0),
143 set_replay(0),
144 cfg_replay_fn(),
145 cfg_record_fn(),
146 cfg_cosim(0),
147 cfg_replay(0),
148 cfg_record(false),
149 cfg_reg_comp(0),
150 cfg_tlb_sync(0),
151 cfg_mem_sync(0),
152 cfg_pli_debug(0),
153 cfg_mem_debug(0),
154 cfg_tso_debug(0),
155 cfg_tlb_debug(0),
156 cfg_socket(0),
157 step_count(0),
158 set_trace(0),
159 cfg_standalone(0),
160 intp0_count(0),
161 cfg_tlb_sync_size(0)
162{
163 int c, s;
164
165 csr_sync = new @-ARCH-@_CsrReadWrite();
166 csr = new @-ARCH-@_Csr();
167 csr->model = this;
168
169 mem_sync = 0; // Allocate in init() as it needs conf info in constructor
170}
171/*}}}*/
172
173inline int @-ARCH-@_Main::check_strand( int strand_id )/*{{{*/
174{
175 // when detect a un-initialized strand pointer, force a cosim miscompare
176 // on PC
177 if (!trc_strand[strand_id])
178 {
179 if (pli_socket.pli_ok())
180 {
181 fprintf(stderr, "ERROR: strand %d is not initialized, use -sas_run_args=-DTHREAD_MASK to specify valid strands.\n", strand_id);
182 sprintf(error_buffer, "%d: [swvp0,th%02d] <v:%016llx> <p:%016llx> [%08x] %s\n", 0, strand_id, 0, 0, 0, "ERROR");
183 pli_socket.write(error_buffer);
184 sprintf(error_buffer, "STEP: %d C %d %016llx\n", strand_id, 32, 0);
185 pli_socket.write(error_buffer);
186 pli_socket.flush();
187 pli_socket.pli_stop();
188 }
189 return -1;
190 }
191 return 0;
192}
193/*}}}*/
194
195// by default we only instantiate one cpu, if more are needed, then those
196// are instantiated on the fly, along with related objects.
197void @-ARCH-@_Main::create_cpu_extra( int new_cpu_cnt, int no_core )/*{{{*/
198{
199 int c, s;
200
201 int current_cpu_cnt = cpu_cnt();
202 if ((current_cpu_cnt >= new_cpu_cnt) ||
203 (@-ARCH-@_Model::NO_CPUS < new_cpu_cnt))
204 {
205 // current cpu count is no less than the new cpu count, do nothing.
206 return;
207 }
208
209 // create new cpu(s)
210 create_cpu_dynamic((new_cpu_cnt - current_cpu_cnt), no_core);
211
212 c = current_cpu_cnt * @-ARCH-@_Model::NO_CORES_PER_CPU;
213 for (; c < (new_cpu_cnt*@-ARCH-@_Model::NO_CORES_PER_CPU); c++)
214 {
215 // global cpu id
216 int pid = c / @-ARCH-@_Model::NO_CORES_PER_CPU;
217 // core id within a cpu
218 int cid = c % @-ARCH-@_Model::NO_CORES_PER_CPU;
219 @-ARCH-VF-@_Core* core = cpu_ptr(pid)->core[cid];
220 if (core)
221 {
222 inst_tlb[c] = new SS_TimedTlb(&core->inst_tlb, cfg_tlb_sync_size);
223 data_tlb[c] = new SS_TimedTlb(&core->data_tlb, cfg_tlb_sync_size);
224 }
225 }
226
227 s = current_cpu_cnt * @-ARCH-@_Model::NO_STRANDS_PER_CPU;
228 for (; s < (new_cpu_cnt*@-ARCH-@_Model::NO_STRANDS_PER_CPU); s++)
229 {
230 // global cpu id
231 int pid = s / @-ARCH-@_Model::NO_STRANDS_PER_CPU;
232 // global core id
233 int gcid = s / @-ARCH-@_Model::NO_STRANDS_PER_CORE;
234 // core id within a cpu
235 int cid = gcid % @-ARCH-@_Model::NO_CORES_PER_CPU;
236 // strand id iwthin a cpu
237 int sid = s % @-ARCH-@_Model::NO_STRANDS_PER_CPU;
238
239 @-ARCH-VF-@_Core* core = cpu_ptr(pid)->core[cid];
240 if (core && (cpu[pid]->strand[sid]))
241 {
242 core->inst_tlb.add_strand(cpu[pid]->strand[sid]);
243 core->data_tlb.add_strand(cpu[pid]->strand[sid]);
244
245 trc_strand[s] = new SS_TrcStrand(cpu[pid]->strand[sid]);
246 tlb_sync[s] = new SS_TlbSync(cpu[pid]->strand[sid],inst_tlb[gcid],data_tlb[gcid]);
247 irq_sync[s] = new SS_IrqSync(cpu[pid]->strand[sid]);
248 val_sync[s] = new SS_ValSync(cpu[pid]->strand[sid]);
249 reg_comp[s] = new @-ARCH-@_RegCompare((@-ARCH-VF-@_Strand*)cpu[pid]->strand[sid],&pli_socket);
250
251 // ToDo this should be one function call obj + fun passed as arguments.
252 cpu[pid]->strand[sid]->io->set_access_io(csr->access_io);
253 cpu[pid]->strand[sid]->io->set_access_io_obj((void*)csr);
254
255 // SPU_CWQCSR IR[4], HWE[3], BUSY[1], ENABLED[0]
256#ifdef MAIN_ARCH_N2
257 cpu[pid]->strand[sid]->asi_map.set_asi_va_follow_me_mask(0x40,0x20,0x1f);
258#else
259 cpu[pid]->strand[sid]->asi_map.set_asi_va_follow_me_mask(0x40,0x20,0x1b);
260#endif
261 // SPU_CQ_SYNC ditto
262#ifdef MAIN_ARCH_N2
263 cpu[pid]->strand[sid]->asi_map.set_asi_va_follow_me_mask(0x40,0x30,0x1f);
264#else
265 cpu[pid]->strand[sid]->asi_map.set_asi_va_follow_me_mask(0x40,0x30,0x1b);
266#endif
267 // SPU_MA_CTL IR[26], HWE[22], BUSY[16]
268 cpu[pid]->strand[sid]->asi_map.set_asi_va_follow_me_mask(0x40,0x80,0x4410000);
269 // set ASIs that allow multi-entry ASI FOLLOW-ME
270 val_sync[s]->set_multi_entry(0x53);
271 val_sync[s]->set_multi_entry(0x55);
272 val_sync[s]->set_multi_entry(0x56);
273 val_sync[s]->set_multi_entry(0x5d);
274 val_sync[s]->set_multi_entry(0x5e);
275 }
276 }
277
278 s = current_cpu_cnt * @-ARCH-@_Model::NO_STRANDS_PER_CPU;
279 for (; s < (new_cpu_cnt*@-ARCH-@_Model::NO_STRANDS_PER_CPU); s++)
280 first_intp1[s] = true;
281}
282/*}}}*/
283
284void @-ARCH-@_Main::init( int record, int replay )/*{{{*/
285{
286 int s;
287
288 // First get the val_xxx parameters from the diag.conf file
289
290 SS_ConfigReader config("diag.conf");
291
292 SS_ConfigValue* val_socket = config.value("socket0","socket");
293 SS_ConfigValue* val_pli_log = config.value("socket0","pli_log");
294 SS_ConfigValue* val_replay_log = config.value("socket0","replay_log");
295 SS_ConfigValue* val_pli_debug = config.value("socket0","debug_level");
296 SS_ConfigValue* val_reg_comp = config.value("socket0","reg_cmp");
297 SS_ConfigValue* val_tlb_sync = config.value("socket0","tlb_sync");
298 SS_ConfigValue* val_tlb_debug = config.value("socket0","tlb_debug");
299 SS_ConfigValue* val_mem_sync = config.value("socket0","mem_model");
300 SS_ConfigValue* val_mem_debug = config.value("swvmem0","debug_level");
301 SS_ConfigValue* val_tso_check = config.value("swvmem0","tso_checker");
302 SS_ConfigValue* val_ras_enable = config.value("socket0","ras_enable");
303 SS_ConfigValue* val_rstv_mask = config.value("socket0","rstv_mask");
304 SS_ConfigValue* val_dump_regs = config.value("socket0","dump_regs");
305 SS_ConfigValue* val_cmpr_list = config.value("socket0","cmpr_list");
306 SS_ConfigValue* val_tlb_sync_size = config.value("socket0","tlb_sync_size");
307
308 // we must have this value before creating cpu
309 cfg_tlb_sync_size = (val_tlb_sync_size && val_tlb_sync_size->is_num()) ? val_tlb_sync_size->num()->value : 128;
310
311 // CMP value for asi=0x41/va=0x0, asi=0x41/va=0x50, and other related CMPs.
312 // the value comes in the fomrat of [0..9,a..f,x],
313 // e.g., 00xx11 means va=0x0 : 0xff00ff, and va=0x50 : 000011. In other
314 // words, core0 and core2 are available, and strand0 and strand4 are
315 // enabled. Every 2 chars (i.e., 8 bits) from the right represents one
316 // core, if any one of the 2 chars is 'x', then the core is considered
317 // not available. Any un-specified cores are considered not available. If
318 // no strand is specified as enabled, then the lowest strand is set to be
319 // enabled.
320
321 // process CPU option, if specified
322 SS_ConfigValue* val_num_cpu = config.value("swvmem0","cpu");
323 if (val_num_cpu)
324 {
325 int num_cpu = (val_num_cpu->is_num()) ? val_num_cpu->num()->value : 1;
326 create_cpu_extra(num_cpu, @-ARCH-@_Model::NO_CORES_PER_CPU);
327 // default is having cpu0 available and cpu0.core0.strand0 enabled.
328 // If other masking is desired, then THREAD_MASK should be used instead.
329 cpu_ptr(0)->strand_available.set_unmasked(0xffffffffffffffff);
330 cpu_ptr(0)->strand_enable_status.set_unmasked(0xffffffffffffffff);
331 cpu_ptr(0)->strand_enable = 0xffffffffffffffff;
332 cpu_ptr(0)->xir_steering = 0xffffffffffffffff;
333 cpu_ptr(0)->strand_running = 0x1;
334 cpu_ptr(0)->strand_running_update(cpu_ptr(0)->strand[0]->strand_id());
335 }
336
337 if (cpu_cnt() == 0)
338 {
339 // if no CPU is specified, then process THREAD_MASKs.
340 for (int i = 0; i < @-ARCH-@_Model::NO_CPUS; i++)
341 {
342 int no_core = 0;
343 char thd_mask[32];
344 sprintf(thd_mask, "thread_mask%d", i);
345 SS_ConfigValue* val_thd_mask0 = config.value("swvmem0",thd_mask);
346 if ((val_thd_mask0) && (val_thd_mask0->is_str()))
347 {
348 no_core = count_core(val_thd_mask0->str()->value);
349 }
350 if (val_thd_mask0)
351 {
352 if (val_thd_mask0->is_str())
353 {
354 if (cpu_cnt() < i+1)
355 {
356 create_cpu_extra(i+1, no_core);
357 }
358 cmp_init(i, val_thd_mask0->str()->value);
359 }
360 else
361 {
362 fprintf(stdout, "ERROR: input THREAD_MASK%d is not a string: ", i);
363 val_thd_mask0->reflect();
364 }
365 }
366 }
367 }
368
369 cfg_socket = val_socket && val_socket->is_num() ? val_socket->num()->value : 0;
370 cfg_cosim = cfg_socket > 0;
371 cfg_replay = cfg_socket == 0;
372
373 // First get the diag.conf settings.
374
375 // If pli_log given and none zero then record
376
377 if (!val_pli_log)
378 cfg_record = false;
379 else if (val_pli_log->is_num())
380 cfg_record = val_pli_log->num()->value > 0;
381 else if (val_pli_log->is_var())
382 {
383 cfg_record = true;
384 cfg_record_fn = val_pli_log->var()->value;
385 }
386 else if (val_pli_log->is_str())
387 {
388 cfg_record = true;
389 cfg_record_fn = val_pli_log->str()->value;
390 }
391
392 // If the frontend say we should record we should record !!!
393
394 if (record)
395 cfg_record = true;
396
397 // If replay_log is given and none zero then replay
398
399 if (!val_replay_log)
400 cfg_replay = false;
401 else if (val_replay_log->is_num())
402 cfg_replay = val_replay_log->num()->value > 0;
403 else if (val_replay_log->is_var())
404 {
405 cfg_replay = true;
406 cfg_replay_fn = val_replay_log->var()->value;
407 }
408 else if (val_replay_log->is_str())
409 {
410 cfg_replay = true;
411 cfg_replay_fn = val_replay_log->str()->value;
412 }
413
414 // If the frontend says we should replay we should replay
415
416 if (replay)
417 cfg_replay = true;
418
419 // Digest all the config info in elegant variables
420
421 cfg_reg_comp = (val_reg_comp && val_reg_comp->is_num()) ? val_reg_comp->num()->value : 0;
422 cfg_tlb_sync = (val_tlb_sync && val_tlb_sync->is_num()) ? val_tlb_sync->num()->value : 0;
423 cfg_mem_sync = (val_mem_sync && val_mem_sync->is_num()) ? val_mem_sync->num()->value : 0;
424
425 cfg_pli_debug = (val_pli_debug && val_pli_debug->is_num()) ? val_pli_debug->num()->value : 0;
426 cfg_tlb_debug = (val_tlb_debug && val_tlb_debug->is_num()) ? val_tlb_debug->num()->value : 0;
427 cfg_mem_debug = (val_mem_debug && val_mem_debug->is_num()) ? val_mem_debug->num()->value : 0;
428 cfg_tso_debug = (val_tso_check && val_tso_check->is_num()) ? val_tso_check->num()->value : 0;
429 cfg_rstv_mask = (val_rstv_mask && val_rstv_mask->is_num()) ? val_rstv_mask->num()->value : 0;
430 cfg_dump_regs = (val_dump_regs && val_dump_regs->is_num()) ? val_dump_regs->num()->value : 0;
431
432 // Now apply the cfg_xxx variables to setup the simulation
433
434 if (cfg_replay)
435 {
436 pli_socket.open_replay(cfg_replay_fn);
437 if (cfg_record)
438 pli_socket.open_record(cfg_record_fn);
439 }
440 else if (cfg_cosim)
441 {
442 pli_socket.open_cosim(cfg_socket);
443 if (cfg_record)
444 pli_socket.open_record(cfg_record_fn);
445 if (cfg_pli_debug > 0)
446 for (int s=0;s<(cpu_cnt()*@-ARCH-@_Model::NO_STRANDS_PER_CPU);s++)
447 if (reg_comp[s])
448 reg_comp[s]->debug_output(stderr);
449 }
450 else
451 {
452 // there will be no RTL or replay log to provide execution commands,
453 // just step through all strands in round robin.
454 cfg_standalone = true;
455 gbt.read_good_bad_trap(cpu[0]->strand[0]->va_bits());
456 }
457
458 // set debug flag
459 pli_socket.debug(cfg_pli_debug, cfg_reg_comp);
460 for (s = 0; s < (cpu_cnt()*@-ARCH-@_Model::NO_STRANDS_PER_CPU); s++)
461 {
462 if (tlb_sync[s])
463 {
464 tlb_sync[s]->debug(cfg_tlb_debug);
465 // set up connection with RTL testbench socket to report error
466 tlb_sync[s]->socket = &pli_socket;
467 }
468 }
469
470 // set up connection with RTL testbench socket to report error
471 for (int c = 0; c < (cpu_cnt()*@-ARCH-@_Model::NO_CORES_PER_CPU); c++)
472 {
473 if (inst_tlb[c])
474 {
475 inst_tlb[c]->socket = &pli_socket;
476 data_tlb[c]->socket = &pli_socket;
477 }
478 }
479
480 mem_sync = new MemorySync((cpu_cnt()*@-ARCH-@_Model::NO_STRANDS_PER_CPU),@-ARCH-@_Model::NO_STRANDS_PER_CORE,@-ARCH-@_Model::NO_CORES_PER_CPU,cfg_mem_debug,cfg_tso_debug,cfg_mem_sync);
481 // set up connection with RTL testbench socket to report error
482 mem_sync->socket = &pli_socket;
483
484 set_trace = cfg_pli_debug;
485
486 // RAS enable for all cpus
487 if(val_ras_enable) {
488 for (int i = 0; i < cpu_cnt(); i++)
489 {
490 cpu[i]->ras_enable(NULL);
491 }
492 }
493
494 // RST_VEC_MASK
495 if (cfg_rstv_mask)
496 {
497 for (int p = 0; p < cpu_cnt(); p++)
498 {
499 SS_Strand* strand = cpu[p]->strand[0];
500 strand->asi_map.wr64(strand, 0x45, 0x18, 0x1);
501 }
502 hard_reset();
503 }
504 // register comparison list
505 if (val_cmpr_list)
506 {
507 string cfg_cmpr_list;
508 if (val_cmpr_list->is_var())
509 cfg_cmpr_list = val_cmpr_list->var()->value;
510 else if (val_cmpr_list->is_str())
511 cfg_cmpr_list = val_cmpr_list->str()->value;
512 // G/W/F/PC - only compare those
513 // -/G/W/F/PC - exclude those from comparison
514 bool exclude = false;
515 int start_pos = 0;
516 if (cfg_cmpr_list[0] == '-')
517 {
518 exclude = true;
519 start_pos = 2;
520 }
521 else
522 {
523 // turn off comparison on all registers first, then add back the ones
524 // specified in CMPR_LIST
525 for (int i = 0; i < @-ARCH-@_Model::NO_STRANDS; i++)
526 if (reg_comp[i])
527 reg_comp[i]->cmpr_off();
528 }
529 // process the cmpr_list string
530 bool done = false;
531 while (!done)
532 {
533 string sub;
534 int end_pos = cfg_cmpr_list.find('/', start_pos);
535 if (end_pos >= 0)
536 {
537 sub = cfg_cmpr_list.substr(start_pos, (end_pos - start_pos));
538 start_pos = end_pos + 1;
539 }
540 else
541 {
542 sub = cfg_cmpr_list.substr(start_pos);
543 done = true;
544 }
545 if (sub.size() > 0)
546 set_cmpr_list(sub, exclude);
547 }
548 }
549}
550/*}}}*/
551
552void @-ARCH-@_Main::set_cmpr_list(string sub, bool exclude)/*{{{*/
553{
554 int ii = reg_comp[0]->name_2_index(sub);
555 if (exclude)
556 {
557 for (int i = 0; i < @-ARCH-@_Model::NO_STRANDS; i++)
558 if (reg_comp[i])
559 reg_comp[i]->cmpr_off(ii);
560 }
561 else
562 {
563 for (int i = 0; i < @-ARCH-@_Model::NO_STRANDS; i++)
564 if (reg_comp[i])
565 reg_comp[i]->cmpr_on(ii);
566 }
567}
568/*}}}*/
569
570int @-ARCH-@_Main::count_core(string mask)/*{{{*/
571{
572 // CMP masking, e.g., 00xx0031 means core0, core1, and core3 are available,
573 // strand0, strand4, and strand5 are enabled.
574 // counting the number of cores to be allocated.
575 string var2 = mask;
576 if (var2.size() % 2)
577 return (var2.size()/2 + 1);
578 else
579 return var2.size()/2;
580}
581
582void @-ARCH-@_Main::cmp_init(int cid, string mask, int ii)/*{{{*/
583{
584 // CMP masking, e.g., 00xx0031 means core0, core1, and core3 are available,
585 // strand0, strand4, and strand5 are enabled.
586 uint64_t available = 0;
587 uint64_t enabled = 0;
588 int core = 0;
589 string var2 = mask;
590 if (var2.size() % 2)
591 var2.insert(0, "0");
592 for (int j = var2.size()-2; j >= 0; j -= 2)
593 {
594 string var3 = var2.substr(j, 2);
595 if ((var3.find("x") == string::npos) && (var3.find("X") == string::npos))
596 {
597 // hex value, the core is available
598 available |= (0xffULL) << (8*core);
599 enabled |= ((uint64_t)strtoul(var3.c_str(), NULL, 16)) << (8*core);
600 }
601 else
602 {
603 // with 'x', the core is not available
604 available |= (0x00) << (8*core);
605 enabled |= (0x00) << (8*core);
606 }
607 core++;
608 }
609 // set CMP (0x41) values according to runtime thread_mask options
610 cpu_ptr(cid)->strand_available.set_unmasked(available);
611 cpu_ptr(cid)->strand_enable_status.set_unmasked(available);
612 cpu_ptr(cid)->strand_enable = available;
613 cpu_ptr(cid)->xir_steering = available;
614 cpu_ptr(cid)->strand_running = enabled;
615 cpu_ptr(cid)->strand_running_update(cpu_ptr(cid)->strand[0]->strand_id());
616}
617/*}}}*/
618
619void @-ARCH-@_Main::dump_regs( )/*{{{*/
620{
621 if (cfg_dump_regs)
622 for (int p = 0; p < cpu_cnt(); p++)
623 for (int s = 0; s < @-ARCH-@_Model::NO_STRANDS_PER_CPU; s++)
624 if (cpu_ptr(p)->strand[s]->running)
625 reg_comp[(p*@-ARCH-@_Model::NO_STRANDS_PER_CPU)+s]->dump_regs();
626}
627/*}}}*/
628
629uint_t @-ARCH-@_Main::step( uint_t n )/*{{{*/
630{
631 // step(n) grants the pli socket to step n instructions forward
632 // When n reaches 0 step() return 0. If a PLI_QUIT command is
633 // received step() return -1. In all other cases, when something
634 // went wrong, step() returns the remaining n (n > 0).
635
636 if (cfg_standalone)
637 {
638 if (cfg_reg_comp)
639 for (int s = 0; s < (cpu_cnt()*@-ARCH-@_Model::NO_STRANDS_PER_CPU); s++)
640 if (reg_comp[s])
641 reg_comp[s]->initialise();
642
643 // in standalone mode, just step through all strands in round robin
644 while (n)
645 {
646 for (int p = 0; p < cpu_cnt(); p++)
647 {
648 int ss = p * @-ARCH-@_Model::NO_STRANDS_PER_CPU;
649 for (int s = 0; s < @-ARCH-@_Model::NO_STRANDS_PER_CPU; s++)
650 {
651 if (cpu[p] && cpu[p]->strand[s])
652 {
653 SS_Strand* strand = cpu[p]->strand[s];
654 strand->flush_va(strand->pc());
655 if (strand->trc_step(1) != 0)
656 {
657 // likely hit a breakpoint
658 return -1;
659 }
660 if (strand->running)
661 {
662 step_count++;
663 pli_trace(ss+s);
664 if (cfg_reg_comp)
665 reg_comp[ss+s]->compare(trc_strand[ss+s]->iw);
666 }
667 if (gbt.hit_good_bad_trap(strand->pc()) != 0)
668 {
669 // hit a good/bad trap
670 dump_regs();
671 return -1;
672 }
673 }
674 }
675 }
676 n--;
677 }
678 return 0;
679 }
680
681 while (n)
682 {
683 // When we set breakpoints in the interactive mode then we
684 // already have read the plic socket command and the DUT is
685 // waiting for the results. So jump to the cause ...
686
687 if (pli_socket.read(1) == 0)
688 return -2;
689
690 switch (pli_socket.get8(0))
691 {
692 case SS_PliCommand::PLI_QUIT:
693 {
694 SS_PliCommand_QUIT arg(pli_socket);
695 pli_socket.close();
696 return -1;
697 break;
698 }
699 case SS_PliCommand::PLI_SSTEP:
700 {
701 step_count++;
702 SS_PliCommand_SSTEP@-PLICMD-@ arg(pli_socket,&step_count);
703 n--;
704 if (check_strand(arg.tid) != 0) break;
705 if (!reg_comp[arg.tid]->is_initialise() && cfg_reg_comp)
706 reg_comp[arg.tid]->initialise();
707 if (cfg_tlb_sync)
708 SS_TlbSync::inst_tlb_read(tlb_sync[arg.tid]);
709 int pid = arg.tid / @-ARCH-@_Model::NO_STRANDS_PER_CPU;
710 int sid = arg.tid % @-ARCH-@_Model::NO_STRANDS_PER_CPU;
711 SS_Strand* strand = cpu[pid]->strand[sid];
712 uint64_t trc_pc = strand->pc();
713 if (!irq_sync[arg.tid]->check())
714 {
715 strand->flush_va(strand->pc());
716 strand->trc_step(1);
717 pli_trace(arg.tid);
718 }
719 else
720 {
721 // a pending interrupt is taken, we need to generate an instruciton
722 // line in cosim log
723 pli_trace_0x0(arg.tid, trc_pc);
724 }
725 if (cfg_reg_comp)
726 {
727 if (!pli_socket.pli_ok())
728 {
729 // if pli-socket has problem (e.g., msync, tlbsync, etc encounter
730 // error), we should force cosim to stop as soon as possible, one
731 // trick is to force %g7 to a weird value.
732 (strand->set_state)(strand,SS_Registers::G7, 0xffffffffffffffff);
733 }
734 reg_comp[arg.tid]->compare(trc_strand[arg.tid]->iw);
735 }
736 break;
737 }
738 case SS_PliCommand::PLI_SSTEP_N:
739 {
740 step_count++;
741 SS_PliCommand_SSTEP_N@-PLICMD-@ arg(pli_socket,&step_count);
742 if (check_strand(arg.tid) != 0) break;
743 if (!reg_comp[arg.tid]->is_initialise() && cfg_reg_comp)
744 reg_comp[arg.tid]->initialise();
745 int pid = arg.tid / @-ARCH-@_Model::NO_STRANDS_PER_CPU;
746 int sid = arg.tid % @-ARCH-@_Model::NO_STRANDS_PER_CPU;
747 SS_Strand* strand = cpu[pid]->strand[sid];
748 for (int i = 0; i < arg.count; i++)
749 {
750 n--;
751 if (cfg_tlb_sync)
752 SS_TlbSync::inst_tlb_read(tlb_sync[arg.tid]);
753 uint64_t trc_pc = strand->pc();
754 if (!irq_sync[arg.tid]->check())
755 {
756 strand->flush_va(strand->pc());
757 strand->trc_step(1);
758 pli_trace(arg.tid);
759 }
760 else
761 {
762 // a pending interrupt is taken, we need to generate an instruciton
763 // line in cosim log
764 pli_trace_0x0(arg.tid, trc_pc);
765 }
766 }
767 if (cfg_reg_comp)
768 if (!pli_socket.pli_ok())
769 {
770 // if pli-socket has problem (e.g., msync, tlbsync, etc encounter
771 // error), we should force cosim to stop as soon as possible, one
772 // trick is to force %g7 to a weird value.
773 (strand->set_state)(strand,SS_Registers::G7, 0xffffffffffffffff);
774 }
775 reg_comp[arg.tid]->compare(trc_strand[arg.tid]->iw);
776 break;
777 }
778 case SS_PliCommand::PLI_ITLBREAD:
779 {
780 SS_PliCommand_ITLBREAD@-PLICMD-@ arg(pli_socket);
781 if (check_strand(arg.tid) != 0) break;
782 if (pli_socket.pli_ok() && cfg_tlb_sync)
783 tlb_sync[arg.tid]->pli_inst_tlb_read(arg.rtime);
784 break;
785 }
786 case SS_PliCommand::PLI_ITLBWRITE:
787 {
788 SS_PliCommand_ITLBWRITE@-PLICMD-@ arg(pli_socket);
789 if (check_strand(arg.tid) != 0) break;
790 if (pli_socket.pli_ok() && cfg_tlb_sync)
791 tlb_sync[arg.tid]->pli_inst_tlb_write(arg.wtime,arg.entry);
792 break;
793 }
794 case SS_PliCommand::PLI_DTLBREAD:
795 {
796 SS_PliCommand_DTLBREAD@-PLICMD-@ arg(pli_socket);
797 if (check_strand(arg.tid) != 0) break;
798 if (pli_socket.pli_ok() && cfg_tlb_sync)
799 tlb_sync[arg.tid]->pli_data_tlb_read(arg.rtime);
800 break;
801 }
802 case SS_PliCommand::PLI_DTLBWRITE:
803 {
804 SS_PliCommand_DTLBWRITE@-PLICMD-@ arg(pli_socket);
805 if (check_strand(arg.tid) != 0) break;
806 if (pli_socket.pli_ok() && cfg_tlb_sync)
807 tlb_sync[arg.tid]->pli_data_tlb_write(arg.wtime,arg.entry);
808 break;
809 }
810 case SS_PliCommand::PLI_IHWTW:
811 {
812 SS_PliCommand_IHWTW@-PLICMD-@ arg(pli_socket);
813 if (check_strand(arg.tid) != 0) break;
814 if (pli_socket.pli_ok() && cfg_tlb_sync)
815 tlb_sync[arg.tid]->pli_inst_hwtw(arg.wtime,arg.va,arg.entry);
816 break;
817 }
818 case SS_PliCommand::PLI_DHWTW:
819 {
820 SS_PliCommand_DHWTW@-PLICMD-@ arg(pli_socket);
821 if (check_strand(arg.tid) != 0) break;
822 if (pli_socket.pli_ok() && cfg_tlb_sync)
823 tlb_sync[arg.tid]->pli_data_hwtw(arg.wtime,arg.va,arg.asi,arg.entry);
824 break;
825 }
826 case SS_PliCommand::PLI_TLBLOOKUP:
827 {
828 SS_PliCommand_TLBLOOKUP@-PLICMD-@ arg(pli_socket);
829 if (check_strand(arg.tid) != 0) break;
830 if (pli_socket.pli_ok() && cfg_tlb_sync)
831 tlb_sync[arg.tid]->pli_tlb_lookup(arg.rtime,arg.asi);
832 break;
833 }
834 case SS_PliCommand::PLI_DTLBREAD_POP:
835 {
836 SS_PliCommand_DTLBREAD_POP@-PLICMD-@ arg(pli_socket);
837 if (check_strand(arg.tid) != 0) break;
838 if (pli_socket.pli_ok() && cfg_tlb_sync)
839 tlb_sync[arg.tid]->pli_data_tlb_read_pop(arg.ptime);
840 break;
841 }
842 case SS_PliCommand::PLI_MEM_ST_ISSUE:
843 {
844 SS_PliCommand_MEM_ST_ISSUE@-PLICMD-@ arg(pli_socket);
845 if (check_strand(arg.tid) != 0) break;
846 if (pli_socket.pli_ok() && cfg_mem_sync)
847 {
848 StoreIssueCmd mem_oper((enum INSTR_TYPE)arg.itype,arg.tid,0,arg.pa,arg.data,arg.size_vec,arg.time);
849 mem_sync->handleStoreIssue(mem_oper);
850 }
851 break;
852 }
853 case SS_PliCommand::PLI_MEM_ST_L2_COMMIT:
854 {
855 SS_PliCommand_MEM_ST_L2_COMMIT@-PLICMD-@ arg(pli_socket);
856 if (check_strand(arg.tid) != 0) break;
857 bool cas_cmp = (arg.size_vec == 0) ? false : true;
858 if (pli_socket.pli_ok() && cfg_mem_sync)
859 {
860 StoreCommitCmd mem_oper(arg.tid,arg.inv_vec,0,arg.pa,arg.size_vec,arg.l2hit,cas_cmp,arg.time);
861 mem_sync->handleStoreCommit(mem_oper);
862 }
863 break;
864 }
865 case SS_PliCommand::PLI_MEM_ST_INV:
866 {
867 SS_PliCommand_MEM_ST_INV@-PLICMD-@ arg(pli_socket);
868 if (check_strand(arg.tid) != 0) break;
869 if (pli_socket.pli_ok() && cfg_mem_sync)
870 {
871 StoreInvCmd mem_oper(arg.cid,arg.tid,arg.pa,arg.time);
872 mem_sync->handleStoreInv(mem_oper);
873 }
874 break;
875 }
876 case SS_PliCommand::PLI_MEM_ST_UPDATE:
877 {
878 SS_PliCommand_MEM_ST_UPDATE@-PLICMD-@ arg(pli_socket);
879 if (check_strand(arg.tid) != 0) break;
880 if (pli_socket.pli_ok() && cfg_mem_sync)
881 {
882 StoreUpdateCmd mem_oper(arg.tid,arg.pa,arg.time);
883 mem_sync->handleStoreUpdate(mem_oper);
884 }
885 break;
886 }
887 case SS_PliCommand::PLI_MEM_ST_ACK:
888 {
889 SS_PliCommand_MEM_ST_ACK@-PLICMD-@ arg(pli_socket);
890 if (check_strand(arg.tid) != 0) break;
891 if (pli_socket.pli_ok() && cfg_mem_sync)
892 {
893 StoreAckCmd mem_oper(arg.tid,0,arg.rmo,arg.time);
894 mem_sync->handleStoreAck(mem_oper);
895 }
896 break;
897 }
898 case SS_PliCommand::PLI_MEM_LD_ISSUE:
899 {
900 SS_PliCommand_MEM_LD_ISSUE@-PLICMD-@ arg(pli_socket);
901 if (check_strand(arg.tid) != 0) break;
902 if (pli_socket.pli_ok() && cfg_mem_sync)
903 {
904 LoadIssueCmd mem_oper((enum INSTR_TYPE)arg.itype,arg.tid,0,arg.pa,(1 << arg.size),0,arg.time);
905 mem_sync->handleLoadIssue(mem_oper);
906 }
907 break;
908 }
909 case SS_PliCommand::PLI_MEM_LD_DATA:
910 {
911 SS_PliCommand_MEM_LD_DATA@-PLICMD-@ arg(pli_socket);
912 if (check_strand(arg.tid) != 0) break;
913 if (pli_socket.pli_ok() && cfg_mem_sync)
914 {
915 LoadDataCmd mem_oper(arg.tid,0,arg.pa,0,(enum DATA_SRC)arg.src,0,arg.time);
916 mem_sync->handleLoadData(mem_oper);
917 }
918 break;
919 }
920 case SS_PliCommand::PLI_MEM_LD_FILL:
921 {
922 SS_PliCommand_MEM_LD_FILL@-PLICMD-@ arg(pli_socket);
923 if (check_strand(arg.tid) != 0) break;
924 if (pli_socket.pli_ok() && cfg_mem_sync)
925 {
926 LoadFillCmd mem_oper(arg.tid,0,arg.pa,arg.time);
927 mem_sync->handleLoadFill(mem_oper);
928 }
929 break;
930 }
931 case SS_PliCommand::PLI_MEM_EVICT:
932 {
933 SS_PliCommand_MEM_EVICT@-PLICMD-@ arg(pli_socket);
934 if (pli_socket.pli_ok() && cfg_mem_sync)
935 {
936 EvictCmd mem_oper(arg.inv_vec,0,0,arg.pa,arg.time);
937 mem_sync->handleEvict(mem_oper);
938 }
939 break;
940 }
941 case SS_PliCommand::PLI_MEM_EVICT_INV:
942 {
943 SS_PliCommand_MEM_EVICT_INV@-PLICMD-@ arg(pli_socket);
944 if (pli_socket.pli_ok() && cfg_mem_sync)
945 {
946 EvictInvCmd mem_oper(arg.cid,arg.bid,0,0,arg.time);
947 mem_sync->handleEvictInv(mem_oper);
948 }
949 break;
950 }
951 case SS_PliCommand::PLI_MEM_SLAM:
952 {
953 SS_PliCommand_MEM_SLAM@-PLICMD-@ arg(pli_socket);
954 if (pli_socket.pli_ok() && cfg_mem_sync)
955 {
956 StoreIssueCmd mem_oper((enum INSTR_TYPE)0,0,0,arg.pa,arg.data,arg.size,arg.time);
957 mem_sync->handleStoreSlam(mem_oper);
958#ifdef TODO
959 //TODO do we handle reset_gen properly in store_slam?
960 try {
961 mem_sync->handleStoreSlam(mem_oper);
962 }
963 catch ( ResetGen &e ) {
964 ((@-ARCH-@_RegReader*)regReader_)->handleResetGen(@-ARCH-@_System::RESET_GEN);
965 }
966 catch (...) {
967 throw;
968 }
969#endif
970 }
971 break;
972 }
973 case SS_PliCommand::PLI_MEM_LD_POP:
974 {
975 SS_PliCommand_MEM_LD_POP@-PLICMD-@ arg(pli_socket);
976 if (check_strand(arg.tid) != 0) break;
977 if (pli_socket.pli_ok() && cfg_mem_sync)
978 mem_sync->handleLoadPop(arg.tid);
979 break;
980 }
981 case SS_PliCommand::PLI_MEM_ST_POP:
982 {
983 SS_PliCommand_MEM_ST_POP@-PLICMD-@ arg(pli_socket);
984 if (check_strand(arg.tid) != 0) break;
985 if (pli_socket.pli_ok() && cfg_mem_sync)
986 mem_sync->handleStorePop(arg.tid);
987 break;
988 }
989 case SS_PliCommand::PLI_MEM_CHECK:
990 {
991 SS_PliCommand_MEM_CHECK@-PLICMD-@ arg(pli_socket);
992 if (pli_socket.pli_ok() && cfg_mem_sync)
993 mem_sync->handleMemoryCheck(arg.pa,arg.data,8);
994 break;
995 }
996 case SS_PliCommand::PLI_MEM_DMA_STORE:
997 {
998 SS_PliCommand_MEM_DMA_STORE@-PLICMD-@ arg(pli_socket);
999 if (pli_socket.pli_ok() && cfg_mem_sync){
1000 DmaStoreCmd memCmd(0, 0, arg.pa, arg.data, arg.size_vec, arg.inv, arg.tsize, arg.time);
1001 mem_sync->handleDmaStore(memCmd);
1002#ifdef TODO
1003 //TODO do we handle reset_gen properly in dma_store?
1004 try {
1005 mem_sync->handleDmaStore(memCmd);
1006 }
1007 catch ( ResetGen &e ) {
1008 ((@-ARCH-@_RegReader*)regReader_)->handleResetGen(@-ARCH-@_System::RESET_GEN);
1009 }
1010 catch (...) {
1011 throw;
1012 }
1013#endif
1014 }
1015 break;
1016 }
1017 case SS_PliCommand::PLI_MEM_DMA_STORE_START:
1018 {
1019 SS_PliCommand_MEM_DMA_STORE_START@-PLICMD-@ arg(pli_socket);
1020 if (pli_socket.pli_ok() && cfg_mem_sync){
1021 DmaStoreCmd memCmd(0, 0, arg.pa, 0, 0, 0, arg.tsize, arg.time);
1022 mem_sync->handleDmaStoreStart(memCmd);
1023 }
1024 break;
1025 }
1026 case SS_PliCommand::PLI_INTP:
1027 {
1028 SS_PliCommand_INTP@-PLICMD-@ arg(pli_socket);
1029 if (check_strand(arg.tid) != 0) break;
1030 if (!pli_socket.pli_ok()) break;
1031 switch (arg.tt)
1032 {
1033 case SS_Trap::RESERVED: // warm reset
1034 {
1035 for (int s = 0; s < (cpu_cnt()*@-ARCH-@_Model::NO_STRANDS_PER_CPU); s++)
1036 if (tlb_sync[s])
1037 tlb_sync[s]->pli_flush();
1038 mem_sync->flushAll();
1039 intp0_count++;
1040 if (intp0_count > 1)
1041 {
1042 // we are seeing the second or more "INTP 00 00", it is
1043 // considered a wmr
1044 csr->warm_reset();
1045 // the warm_reset() is invoked by "INTP 00 00", do not throw a
1046 // WMR trap here, the following "INTP xx 01" will take care of
1047 // that.
1048 warm_reset(false);
1049 }
1050 irq_sync[arg.tid]->raise(SS_Trap::Type(arg.tt));
1051 break;
1052 }
1053 case SS_Trap::POWER_ON_RESET:
1054 {
1055 // the first encounter of "INTP xx 01" for each strand is
1056 // considered POR, the seond and up are considered WMR
1057 if (first_intp1[arg.tid])
1058 {
1059 first_intp1[arg.tid] = false;
1060 irq_sync[arg.tid]->raise(SS_Trap::Type(arg.tt));
1061 }
1062 else
1063 {
1064 // enter a WMR, clean up other pending interrupts
1065 irq_sync[arg.tid]->clear_list();
1066 irq_sync[arg.tid]->raise(SS_Trap::RESET_GEN_WMR);
1067 }
1068 irq_sync[arg.tid]->check();
1069 break;
1070 }
1071 case SS_Trap::EXTERNALLY_INITIATED_RESET:
1072 // enter a XIR, clean up other pending interrupts
1073 irq_sync[arg.tid]->clear_list();
1074 irq_sync[arg.tid]->raise(SS_Trap::Type(arg.tt));
1075 break;
1076 case SS_Trap::DATA_ACCESS_ERROR:
1077 case SS_Trap::INTERNAL_PROCESSOR_ERROR:
1078 {
1079 mem_sync->flushMsyncCallback(arg.tid);
1080 irq_sync[arg.tid]->raise(SS_Trap::Type(arg.tt));
1081 break;
1082 }
1083 case SS_Trap::INSTRUCTION_ACCESS_MMU_ERROR:
1084 {
1085 int pid = arg.tid / @-ARCH-@_Model::NO_STRANDS_PER_CPU;
1086 int sid = arg.tid % @-ARCH-@_Model::NO_STRANDS_PER_CPU;
1087 SS_Strand* strand = cpu[pid]->strand[sid];
1088 strand->inst_mmu_error = true;
1089 strand->flush_tte_all();
1090 break;
1091 }
1092 case SS_Trap::DATA_ACCESS_MMU_ERROR:
1093 {
1094 int pid = arg.tid / @-ARCH-@_Model::NO_STRANDS_PER_CPU;
1095 int sid = arg.tid % @-ARCH-@_Model::NO_STRANDS_PER_CPU;
1096 SS_Strand* strand = cpu[pid]->strand[sid];
1097 strand->data_mmu_error = true;
1098 strand->flush_tte_all();
1099 break;
1100 }
1101 default:
1102 {
1103 irq_sync[arg.tid]->raise(SS_Trap::Type(arg.tt));
1104 break;
1105 }
1106 }
1107 break;
1108 }
1109 case SS_PliCommand::PLI_ASR_READ:
1110 {
1111 SS_PliCommand_ASR_READ@-PLICMD-@ arg(pli_socket);
1112 if (check_strand(arg.tid) != 0) break;
1113 if (!pli_socket.pli_ok()) break;
1114 val_sync[arg.tid]->ctr_read(asr2index(arg.asr),arg.data);
1115 break;
1116 }
1117 case SS_PliCommand::PLI_ASR_WRITE:
1118 {
1119 SS_PliCommand_ASR_WRITE@-PLICMD-@ arg(pli_socket);
1120 if (check_strand(arg.tid) != 0) break;
1121 if (!pli_socket.pli_ok()) break;
1122 if (arg.asr == 0x46)
1123 {
1124 // HVER. Strands on a physical core share the same hver, but our
1125 // internal implementation gives each strand its own hver, so we
1126 // have to update the hver of all the strands (on the same core)
1127 // together
1128 int core_id = arg.tid / @-ARCH-@_Model::NO_STRANDS_PER_CORE;
1129 for (int i = (core_id*@-ARCH-@_Model::NO_STRANDS_PER_CORE); i < ((core_id+1)*@-ARCH-@_Model::NO_STRANDS_PER_CORE); i++)
1130 val_sync[i]->ctr_write(asr2index(arg.asr),arg.data);
1131 }
1132 else
1133 {
1134 val_sync[arg.tid]->ctr_write(asr2index(arg.asr),arg.data);
1135 }
1136 break;
1137 }
1138 case SS_PliCommand::PLI_ASI_READ:
1139 {
1140 SS_PliCommand_ASI_READ@-PLICMD-@ arg(pli_socket);
1141 if (check_strand(arg.tid) != 0) break;
1142 if (!pli_socket.pli_ok()) break;
1143 val_sync[arg.tid]->asi_read(arg.asi,arg.va,arg.data);
1144 break;
1145 }
1146 case SS_PliCommand::PLI_ASI_WRITE:
1147 {
1148 SS_PliCommand_ASI_WRITE@-PLICMD-@ arg(pli_socket);
1149 if (check_strand(arg.tid) != 0) break;
1150 if (!pli_socket.pli_ok()) break;
1151 val_sync[arg.tid]->asi_write(arg.asi,arg.va,arg.data);
1152 break;
1153 }
1154 case SS_PliCommand::PLI_CMP_WRITE:
1155 {
1156 SS_PliCommand_CMP_WRITE arg(pli_socket);
1157 if (check_strand(0) != 0) break;
1158 if (!pli_socket.pli_ok()) break;
1159 cmp_write(0, arg);
1160 break;
1161 }
1162 case SS_PliCommand::PLI_CSR_READ:
1163 {
1164 SS_PliCommand_CSR_READ@-PLICMD-@ arg(pli_socket);
1165 if (!pli_socket.pli_ok()) break;
1166 csr_sync->pliReadCsrReg(csr,arg.pa,arg.data,arg.le,-1);
1167 break;
1168 }
1169 case SS_PliCommand::PLI_CSR_WRITE:
1170 {
1171 SS_PliCommand_CSR_WRITE@-PLICMD-@ arg(pli_socket);
1172 if (!pli_socket.pli_ok()) break;
1173 csr_sync->pliWriteCsrReg(csr,arg.pa,arg.data,arg.le,-1);
1174 break;
1175 }
1176 case SS_PliCommand::PLI_CMP_WRITE_MN:
1177 {
1178 SS_PliCommand_CMP_WRITE_MN arg(pli_socket);
1179 if (check_strand(arg.nid*@-ARCH-@_Model::NO_STRANDS_PER_CPU) != 0) break;
1180 if (!pli_socket.pli_ok()) break;
1181 cmp_write(arg.nid, SS_PliCommand_CMP_WRITE(arg.va, arg.data));
1182 break;
1183 }
1184 case SS_PliCommand::PLI_CSR_READ_MN:
1185 {
1186 SS_PliCommand_CSR_READ_MN@-PLICMD-@ arg(pli_socket);
1187 if (check_strand(arg.tid) != 0) break;
1188 if (!pli_socket.pli_ok()) break;
1189 csr_sync->pliReadCsrReg(csr,arg.pa,arg.data,arg.le,arg.tid);
1190 break;
1191 }
1192 case SS_PliCommand::PLI_CSR_WRITE_MN:
1193 {
1194 SS_PliCommand_CSR_WRITE_MN@-PLICMD-@ arg(pli_socket);
1195 if (check_strand(arg.nid*@-ARCH-@_Model::NO_STRANDS_PER_CPU) != 0) break;
1196 if (!pli_socket.pli_ok()) break;
1197 csr_sync->pliWriteCsrReg(csr,arg.pa,arg.data,arg.le,(arg.nid*@-ARCH-@_Model::NO_STRANDS_PER_CPU));
1198 break;
1199 }
1200 case SS_PliCommand::PLI_SSTEP_SNIPER:
1201 {
1202 step_count++;
1203 SS_PliCommand_SSTEP_SNIPER@-PLICMD-@ arg(pli_socket, &step_count);
1204 if (check_strand(arg.tid) != 0) break;
1205 if (!pli_socket.pli_ok()) break;
1206 mem_sync->handleSniper(arg.tid, arg.pa, (INSTR_TYPE)arg.itype, arg.data);
1207 break;
1208 }
1209 default:
1210 {
1211 fprintf(stderr,"Received strange PLI command %02x, socket error ?!\n", pli_socket.get8(0));
1212 // read & display a few more bytes and then close down socket properly
1213 pli_socket.debug(99);
1214 pli_socket.read(4);
1215 pli_socket.close();
1216 assert(0);
1217 break;
1218 }
1219 }
1220
1221 fflush(stderr);
1222 fflush(stdout);
1223 }
1224 return 0;
1225}
1226/*}}}*/
1227
1228void @-ARCH-@_Main::cmp_write( int cid, SS_PliCommand_CMP_WRITE& arg )/*{{{*/
1229{
1230 // CMP_WRITE command does not carry the strand_id info we need to
1231 // prevent all strands from getting parked. So we use strand_id 0
1232 // for this purpose.
1233
1234 switch (arg.va)
1235 {
1236 case 0x10:
1237 // POR: strand_available (0x0) ---> strand_enable_status (0x10)
1238 // ---> strand_enable (0x20)
1239 // ---> xir_steering (0x30)
1240 // WMR: no change: strand_available (0x0) & strand_enable (0x20)
1241 // strand_enable (0x20) ---> strand_enable_status (0x10)
1242 // ---> xir_steering (0x30)
1243 // testbench will send over 'strand_enable_status' (0x10) during POR,
1244 // we should propogate the value to 0x0/0x20/0x30
1245 if (intp0_count <= 1)
1246 {
1247 // during POR
1248 cpu_ptr(cid)->strand_available.set_unmasked(arg.data);
1249 cpu_ptr(cid)->strand_enable_status.set_unmasked(arg.data);
1250 cpu_ptr(cid)->strand_enable = arg.data;
1251 cpu_ptr(cid)->xir_steering = arg.data;
1252 // provide msync strand_enable info for cache invalidation process
1253 if (mem_sync)
1254 mem_sync->setCoreEnable((@-ARCH-@_Model::NO_CORES_PER_CPU*cid/8), arg.data);
1255 }
1256 else
1257 {
1258 // after POR, strand_available should not change, other values must
1259 // be masked by strand_available. strand_enable (0x20) will not change
1260 // during wmr, either.
1261 uint64_t mask_data = arg.data & cpu_ptr(cid)->strand_available();
1262 cpu_ptr(cid)->strand_enable_status.set_unmasked(mask_data);
1263 cpu_ptr(cid)->xir_steering = mask_data;
1264 }
1265 break;
1266 case 0x50:
1267 cpu_ptr(cid)->strand_running = arg.data;
1268 break;
1269 case 0x58:
1270 cpu_ptr(cid)->strand_running_update(0,2,arg.data);
1271 break;
1272 default:
1273 pli_socket.pli_stop();
1274 fprintf(stderr,"PLI: ERROR: CMP_WRITE unexpected va=0x%x\n",arg.va);
1275 break;
1276 }
1277}
1278/*}}}*/
1279void @-ARCH-@_Main::pli_trace( uint_t tid )/*{{{*/
1280{
1281 if (reg_comp[tid]->is_cmpr(SS_RegCompare::CTR_INSTR))
1282 {
1283 const char* fmt = "%d: [swvp0,th%02d] <v:%016llx> <p:%016llx> [%08x] %s %s\n";
1284 char str[1024];
1285 char str_inst[512];
1286 char str_trap[512];
1287
1288 SS_TrapInfo* info = &SS_Trap::table[trc_strand[tid]->trap_type];
1289
1290 if (info->disrupting)
1291 {
1292 sprintf(str_trap,"(Interrupted %s)",info->name);
1293 }
1294 else if (trc_strand[tid]->get_trap_mode() == SS_Tracer::INST_TRAP)
1295 {
1296 switch (trc_strand[tid]->trap_type)
1297 {
1298 case SS_Trap::INSTRUCTION_ACCESS_MMU_MISS:
1299 case SS_Trap::FAST_INSTRUCTION_ACCESS_MMU_MISS:
1300 sprintf(str_trap,"(I-miss %#x)",trc_strand[tid]->trap_type);
1301 break;
1302 default:
1303 sprintf(str_trap,"(I-mmu trap %#x)",trc_strand[tid]->trap_type);
1304 break;
1305 }
1306 }
1307 else if (trc_strand[tid]->get_trap_mode() == SS_Tracer::DATA_TRAP)
1308 {
1309 switch (trc_strand[tid]->trap_type)
1310 {
1311 case SS_Trap::DATA_ACCESS_MMU_MISS:
1312 case SS_Trap::FAST_DATA_ACCESS_MMU_MISS:
1313 sprintf(str_trap,"(D-miss %#x)",trc_strand[tid]->trap_type);
1314 break;
1315 default:
1316 sprintf(str_trap,"(D-mmu trap %#x)",trc_strand[tid]->trap_type);
1317 break;
1318 }
1319 }
1320 else
1321 {
1322 sprintf(str_trap,"");
1323 }
1324
1325 uint32_t _iw = trc_strand[tid]->iw;
1326 SS_Vaddr _pc = trc_strand[tid]->pc_va;
1327 size_t n = spix_sparc_dis(str_inst,512,spix_sparc_iop(SPIX_SPARC_V9,&_iw),&_iw,_pc);
1328
1329 sprintf(str,fmt,step_count,tid,_pc,trc_strand[tid]->pc_pa,trc_strand[tid]->iw,str_inst,str_trap);
1330
1331 pli_socket.write(str);
1332 }
1333 trc_strand[tid]->clear();
1334}
1335/*}}}*/
1336void @-ARCH-@_Main::pli_trace_0x0( uint_t tid, uint64_t trc_pc )/*{{{*/
1337{
1338 // this function is used to produce a instruction line with
1339 // "[ 0x00000000 ] illtrap 0", it is mainly used in situation where a
1340 // cosim step is called, but because of a pending interrupt, the interrupt
1341 // is taken instead of the intended instruction, we need the information to
1342 // make cosim log more complete. Because the instruction is not executed,
1343 // the PC_PA is not valid, we use 0x0 in its place.
1344 if (reg_comp[tid]->is_cmpr(SS_RegCompare::CTR_INSTR))
1345 {
1346 const char* fmt = "%d: [swvp0,th%02d] <v:%016llx> <p:%016llx> [%08x] %s %s\n";
1347 char str[1024];
1348 char str_inst[512];
1349 char str_trap[512];
1350
1351 SS_TrapInfo* info = &SS_Trap::table[trc_strand[tid]->trap_type];
1352
1353 if (info->disrupting)
1354 {
1355 sprintf(str_trap,"(Interrupted %s)",info->name);
1356 }
1357 else if (trc_strand[tid]->get_trap_mode() == SS_Tracer::INST_TRAP)
1358 {
1359 switch (trc_strand[tid]->trap_type)
1360 {
1361 case SS_Trap::INSTRUCTION_ACCESS_MMU_MISS:
1362 case SS_Trap::FAST_INSTRUCTION_ACCESS_MMU_MISS:
1363 sprintf(str_trap,"(I-miss)");
1364 break;
1365 default:
1366 sprintf(str_trap,"(ERROR mmutrap %#x)",trc_strand[tid]->trap_type);
1367 break;
1368 }
1369 }
1370 else if (trc_strand[tid]->get_trap_mode() == SS_Tracer::DATA_TRAP)
1371 {
1372 switch (trc_strand[tid]->trap_type)
1373 {
1374 case SS_Trap::DATA_ACCESS_MMU_MISS:
1375 case SS_Trap::FAST_DATA_ACCESS_MMU_MISS:
1376 sprintf(str_trap,"(D-miss)");
1377 break;
1378 default:
1379 sprintf(str_trap,"(ERROR mmutrap %#x)",trc_strand[tid]->trap_type);
1380 break;
1381 }
1382 }
1383 else
1384 {
1385 sprintf(str_trap,"");
1386 }
1387
1388 uint32_t _iw = 0x0;
1389 SS_Vaddr _pc = trc_pc;
1390 size_t n = spix_sparc_dis(str_inst,512,spix_sparc_iop(SPIX_SPARC_V9,&_iw),&_iw,_pc);
1391
1392 sprintf(str,fmt,step_count,tid,_pc,0x0,_iw,str_inst,str_trap);
1393
1394 pli_socket.write(str);
1395 }
1396 trc_strand[tid]->clear();
1397}
1398/*}}}*/
1399SS_Registers::Index @-ARCH-@_Main::asr2index( uint8_t idx )/*{{{*/
1400{
1401 if (idx < 0x20)
1402 return SS_Registers::Index(SS_Registers::ASR_OFS + (idx & 0x1f));
1403 else if (idx < 0x40)
1404 return SS_Registers::Index(SS_Registers::PR_OFS + (idx & 0x1f));
1405 else if (idx < 0x60)
1406 return SS_Registers::Index(SS_Registers::HPR_OFS + (idx & 0x1f));
1407 else
1408 assert(0);
1409 // Should really never get here, but if we do lets return something that make
1410 // sence as we don't have an invalid index value (should we add that?) ...
1411 // %g0 is the best candidate as it ought to be read only.
1412 return SS_Registers::G0;
1413}
1414/*}}}*/
1415
1416@-ARCH-@_Main* @-arch-@ = 0;
1417
1418extern "C" static PyObject* @-arch-@_model( PyObject* self, PyObject* args )/*{{{*/
1419{
1420 if (!PyArg_ParseTuple(args,(char*)""))
1421 return 0;
1422 return Py_BuildValue((char*)"l",@-arch-@);
1423}
1424/*}}}*/
1425extern "C" static PyObject* @-arch-@_init( PyObject* self, PyObject* args )/*{{{*/
1426{
1427 int record, replay;
1428
1429 if (!PyArg_ParseTuple(args,(char*)"ii",&record,&replay))
1430 return 0;
1431 @-arch-@->init(record,replay);
1432 return Py_BuildValue((char*)"");
1433}
1434/*}}}*/
1435extern "C" static PyObject* @-arch-@_step( PyObject* self, PyObject* args )/*{{{*/
1436{
1437 uint_t n;
1438 if (!PyArg_ParseTuple(args,(char*)"i",&n))
1439 return 0;
1440 n = @-arch-@->step(n);
1441 return Py_BuildValue((char*)"i",n);
1442}
1443/*}}}*/
1444
1445extern "C" static PyObject* @-arch-@_trace( PyObject* self, PyObject* args )/*{{{*/
1446{
1447 if (!PyArg_ParseTuple(args,(char*)""))
1448 return 0;
1449 return Py_BuildValue((char*)"i",@-arch-@->set_trace);
1450}
1451/*}}}*/
1452
1453static PyMethodDef @-arch-@_methods[] = /*{{{*/
1454{
1455 {(char*)"model", @-arch-@_model, METH_VARARGS, (char*)"@-ARCH-@ Model created for cosim."},
1456 {(char*)"init", @-arch-@_init, METH_VARARGS, (char*)"Initialise simulation"},
1457 {(char*)"step", @-arch-@_step, METH_VARARGS, (char*)"Step @-ARCH-@ simulator N steps forward (driven by test bench)."},
1458 {(char*)"trace", @-arch-@_trace, METH_VARARGS, (char*)"0 means trace (i.e., instr & reg delta) is off, otherwise on"},
1459 {0, 0, 0, 0}
1460};
1461/*}}}*/
1462
1463int main( int argc, char* argv[] )
1464{
1465 @-arch-@ = new @-ARCH-@_Main();
1466
1467 Py_Initialize();
1468 Py_InitModule((char*)"@-arch-@",@-arch-@_methods);
1469 int ok = Py_Main(argc,argv);
1470 Py_Finalize();
1471
1472 return ok;
1473}