Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / cpu / src / SS_Strand.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: SS_Strand.h
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23#ifndef __SS_Strand_h__
24#define __SS_Strand_h__
25
26/*{{{includes*/
27#include "BL_BoundedArray.h"
28#include "BL_BaseEcc.h"
29#include "BL_Memory.h"
30#include "SS_Memory.h"
31#include "SS_Node.h"
32#include "SS_Model.h"
33#include "SS_Trap.h"
34#include "SS_Interrupt.h"
35#include "SS_Decode.h"
36#include "SS_InstrCache.h"
37#include "SS_Io.h"
38#include "SS_Tte.h"
39#include "SS_State.h"
40#include "SS_Signal.h"
41#include "SS_Message.h"
42#include "SS_AsiInfoTable.h"
43#include "SS_AsiMap.h"
44#include "SS_Registers.h"
45#include "SS_SnapShot.h"
46#include "SS_Tracer.h"
47#include "SS_PidContext.h"
48
49namespace Sam {
50#include "vcpu.h"
51}
52/*}}}*/
53
54class SS_Tlb;
55
56extern "C"
57{
58 typedef SS_Vaddr (*SS_InstMmu)( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr*, SS_InstrCache::Tag* );
59 typedef SS_Vaddr (*SS_TrapFun)( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr*, SS_Trap::Type );
60 typedef SS_Vaddr (*SS_MmuTrap)( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr*, SS_Vaddr, SS_Trap::Type );
61 typedef SS_Vaddr (*SS_DataMmu)( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr*, SS_Vaddr, uint_t mem );
62 typedef SS_Vaddr (*SS_InvalidAsi)( SS_Vaddr, SS_Vaddr, SS_Strand*, SS_Instr*, SS_Vaddr );
63
64 SS_Vaddr ss_break_inst_va_dec( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i );
65
66 SS_Vaddr mem_run_fetch512( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* line, SS_Vaddr va, SS_Tte* tte );
67 SS_Vaddr io_run_fetch512( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* line, SS_Vaddr va, SS_Tte* tte );
68 SS_Vaddr mem_trc_fetch512( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* line, SS_Vaddr va, SS_Tte* tte );
69 SS_Vaddr io_trc_fetch512( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* line, SS_Vaddr va, SS_Tte* tte );
70}
71
72// ==================================================================================
73// The SS_Strand class has no virtual methods and classes derived from SS_Strand
74// can not have virtual methods either. Function pointers are used instead of virtual.
75// The reason for non-virtual is avoidance of hidden speed penalties and avoiding
76// an add on computing IRF register offsets: g0 is at offset 0 so we can check for
77// g0 by comparing index against 0 (this saves setting a constant to compare against).
78//
79// Additionally the class has a very open public interface. This does not mean that
80// all members can be accessed at will. Contrary, all intertfaces (SAM virtual cpu),
81// verification PLI, PFE are expected to only use methods defined between the Public
82// Interface Start and End markers below.
83// ==================================================================================
84
85class SS_Strand
86{
87 public:
88 SS_Strand( SS_Node& _parent, const char* _name,
89 SS_Execute run_exe_table[],
90 SS_Memop mem_run_table_init[][4],
91 SS_Memop mem_trc_table_init[][4],
92 SS_MemErrDetector& mem_err_detector);
93 ~SS_Strand();
94
95 void hard_reset();
96 void warm_reset(bool intp=true);
97 void xtrn_reset();
98
99 // run_step() and trc_step() execute count instruction in run (fast)
100 // and trc (slow) mode respectively. Both routines do not check tick
101 // and stick against tick_cmpr, stick_cmpr and the hstick_cmpr. This
102 // is handled separately by run_tick(). The correct order of calling
103 // is run_step() or trc_step() followed by run_tick().
104
105 uint64_t run_step( uint64_t count );
106 uint64_t trc_step( uint64_t count );
107
108 void run_tick( uint64_t incr );
109
110 void add_tracer( SS_Tracer* t );
111 void del_tracer( SS_Tracer* t );
112
113 void snapshot( SS_SnapShot& ss );
114
115 const char* get_node_name() { return name; }
116
117 void get_name( char* dst );
118
119 SS_BreakPoint::Ident break_on_inst_va( SS_Vaddr va );
120 SS_BreakPoint::Ident break_on_trap( uint_t tt );
121 SS_BreakPoint::Ident break_on_red_mode();
122
123 SS_BreakPoint::Error break_enable( SS_BreakPoint::Ident id );
124 SS_BreakPoint::Error break_disable( SS_BreakPoint::Ident id );
125 SS_BreakPoint::Error break_delete( SS_BreakPoint::Ident id );
126
127 void irq_launch( SS_Trap::Type, bool do_time_out=true );
128
129 enum Cnv2Pa
130 {
131 VA2PA,
132 VA2PA_CTX,
133 VA2PA_CTX_PID,
134 RA2PA,
135 RA2PA_PID,
136 PA2PA
137 };
138
139 SS_Paddr va2pa( SS_Vaddr va ) { SS_Paddr pa; return ((cnv2pa)(this,Sam::Vcpu::TRANSLATE_VA_TO_PA,va,0,0,&pa)) ? 0 : pa; }
140 SS_Paddr va2pa( SS_Vaddr va, uint_t ctx ) { SS_Paddr pa; return ((cnv2pa)(this,Sam::Vcpu::TRANSLATE_VA_TO_PA_CTX,va,ctx,0,&pa)) ? 0 : pa; }
141 SS_Paddr va2pa( SS_Vaddr va, uint_t ctx, uint_t pid ) { SS_Paddr pa; return ((cnv2pa)(this,Sam::Vcpu::TRANSLATE_VA_TO_PA_CTX_PID,va,ctx,pid,&pa)) ? 0 : pa; }
142
143 SS_Paddr ra2pa( SS_Vaddr ra ) { SS_Paddr pa; return ((cnv2pa)(this,Sam::Vcpu::TRANSLATE_RA_TO_PA,ra,0,0,&pa)) ? 0 : pa; }
144 SS_Paddr ra2pa( SS_Vaddr ra, uint_t pid ) { SS_Paddr pa; return ((cnv2pa)(this,Sam::Vcpu::TRANSLATE_RA_TO_PA_PID,ra,0,pid,&pa)) ? 0 : pa; }
145
146 enum Limits // These are SunSparc limits, not implementation limits
147 {
148 MAX_WP = 7, // Actual limit is 31, but that has never been used.
149 MAX_TL = 7,
150 MAX_GL = 7,
151 MAX_PTL = 2,
152 MAX_PGL = 2
153 };
154
155 enum Mode
156 {
157 SS_USER,
158 SS_PRIV,
159 SS_HPRV
160 };
161
162 //======================================================================
163 // Do not add data members above here and do not change the layout
164 // of the members below here as we need to most critical state
165 // reachable with a single ld/st with immediate offset (4 Kb space).
166 // For that reason the SS_ ctr registers are sorted in 64, 32, 16 & 8
167 // bit sizes so that there are no unused gaps between the members
168 //======================================================================
169
170 // These accessors take a byte offset into the register file, not an index
171 uint64_t& get_irf( int64_t ofs ) { return *(uint64_t*)((char*)this + ofs); }
172 uint32_t& get_frf( int64_t ofs ) { return *(uint32_t*)((char*)this + ofs); }
173 uint64_t& get_drf( int64_t ofs ) { return *(uint64_t*)((char*)this + ofs); }
174
175 static uint64_t reg_off2idx( int64_t ofs ) { return (ofs-offsetof(SS_Strand,irf))/sizeof(uint64_t); }
176 static uint64_t reg_idx2off( int64_t idx ) { return idx*sizeof(uint64_t)+offsetof(SS_Strand,irf); }
177
178 static uint64_t freg_off2idx( int64_t ofs )
179 {
180 uint64_t idx = (ofs-offsetof(SS_Strand,drf))/sizeof(uint32_t);
181#if defined(ARCH_X64)
182 return (idx ^ 1);
183#else
184 return idx;
185#endif
186 }
187 static uint64_t freg_idx2off( int64_t idx )
188 {
189#if defined(ARCH_X64)
190 idx ^= 1;
191#endif
192 return idx*sizeof(uint32_t)+offsetof(SS_Strand,drf);
193 }
194
195 // set_fprs() sets the dl and du bits based on the ofs (rd). The ofs is
196 // from the this pointer to the frf member + rd index (scaled by 4(%f) or 8(%d)).
197
198 void set_fprs( int64_t ofs ) { fprs = fprs() | ((ofs - (32 * 4)) >> 7); }
199
200 uint64_t irf[32]; // %g, %o, %l, %i
201
202 // Floating point register file. Note that single precision registers
203 // are not listed here since they are aliased with double precision.
204 // The little endian platform such as AMD64 makes this aliasing a little
205 // more tricky.
206 uint64_t drf[32]; // %d
207
208 // Some processors generate helper sequences of Sparc lookalike
209 // opcodes that use temporary registers. The %g, %i, %l, %o regs
210 // need to be present at the same time as the %t (temps)
211
212 uint64_t trf[8]; // Temporary registers
213
214 SS_Pc pc;
215 SS_Npc npc;
216 SS_Gsr gsr;
217 SS_Tick tick;
218 SS_Stick stick;
219 SS_TickCmpr tick_cmpr;
220 SS_StickCmpr stick_cmpr;
221 SS_HstickCmpr hstick_cmpr;
222 SS_Softint softint;
223 SS_Tpc tpc;
224 SS_Tnpc tnpc;
225 SS_Tstate tstate;
226 SS_Tba tba;
227 SS_Htba htba;
228 SS_RstvAddr rstv_addr; // Strand's PowerOnReset vector address
229 SS_Hver hver;
230 SS_Y y;
231 SS_Pstate pstate;
232 SS_Tt tt;
233 SS_Hpstate hpstate;
234 SS_Htstate htstate;
235 SS_SimState sim_state;
236 SS_Ccr ccr;
237 SS_AsiReg asi;
238 SS_Fprs fprs;
239 SS_Tl tl;
240 SS_Gl gl;
241 SS_Cwp cwp;
242 SS_Cansave cansave;
243 SS_Canrestore canrestore;
244 SS_Cleanwin cleanwin;
245 SS_Otherwin otherwin;
246 SS_Wstate wstate;
247 SS_Pil pil;
248 SS_Hintp hintp;
249 SS_StrandId strand_id; // The one and only strand id
250 SS_MaxWp max_wp; // Strand's NWINDOWS - 1
251 SS_MaxGl max_gl; // Strand's MAX_GL
252 SS_MaxTl max_tl; // Strand's MAX_TL
253 SS_MaxPgl max_pgl; // Strand's MAX_PGL
254 SS_MaxPtl max_ptl; // Strand's MAX_PTL
255 SS_VaBits va_bits; // Size of the SS_Vaddr in bits
256 SS_PaBits pa_bits; // Size of the SS_Paddr in bits
257 SS_LsuCtr lsu_ctr; // ToDo remove this as not all product have this ..
258 SS_InstCount inst_count; // Number of instructions executed so far
259
260 SS_Fsr fsr; // The real FSR of the simulated host.
261 SS_Fsr fsr_run; // The FSR of the simulated host, excluding tem=0, aexc=0, cexc=0
262 SS_Fsr fsr_tem; // The FSR.tem bits of the simulated host
263 SS_Fsr fsr_exc; // The FSR.cexc and FSR.aexc of the simulated host
264 uint64_t fsr_cpu; // The FSR of the host (save place for keeping fsr during fpop execution)
265 uint64_t fsr_tmp; // The FSR after an fpop has executed (scratch)
266
267 bool running; // True when the strand is running
268 bool halted; // True when the strand is halted
269
270 // unhalt() is called to pull the strand out of halted mode.
271 // The new running mode is _running
272 void unhalt( bool _running=true )
273 {
274 sim_state.running(_running);
275 if (change_running)
276 (change_running)(this);
277 running = _running;
278 halted = false;
279 }
280
281
282 SS_DecodeTable* dec_table; // Pointer to the decode tree
283 SS_Execute* exe_table; // Pointers to tables of execute functions
284 SS_Execute* run_exe_table_ref; // Ref to trace run table
285 SS_Memop (*mem_table)[4]; // Pointers to tables of current memory access functions
286 SS_Memop (*mem_run_table_ref)[4]; // Pointers to tables of fast memory access functions
287 SS_Memop (*mem_trc_table_ref)[4]; // Pointers to tables of tracing memory access functions
288 BL_Memory* memory; // Pointer to RAM
289 SS_Io* io; // Pointer to I/O
290 uint64_t mmu_scratch; // The MMU uses this as scratch space for enidan conversion
291 uint64_t mem_data[8]; // For holding values loaded/stored to memory (avoid %sp adjustment code!)
292 uint8_t stpartial16[16]; // Partial store 16 to partial store 8 byte mask conversion table
293 uint8_t stpartial32[4]; // Partial store 32 to partial store 8 byte mask conversion table
294 uint64_t mem_mask; // Mask used for partial stores ... iso %o6
295
296 BL_BoundedArray<BL_EccBits,32> irf_ecc; // Ecc values for IRF RAS
297 SS_MemErrDetector& mem_err_detector; // RAS memory hierarchy error detector
298
299 // Returns all the I$ information for a paddr associated w/ this core
300 char* icache_info(SS_Paddr pa)
301 {
302 return mem_err_detector.icache_info(pa, this);
303 }
304
305 // Returns all the I$ information for a set associated w/ this core
306 char* icache_set(uint_t set)
307 {
308 return mem_err_detector.icache_set(set, this);
309 }
310
311 // Returns all the D$ information for a set associated w/ this core
312 char* dcache_set(uint_t set)
313 {
314 return mem_err_detector.dcache_set(set, this);
315 }
316
317 // Returns all the L2$ information for a set associated w/ this core
318 char* l2cache_set(uint_t set)
319 {
320 return mem_err_detector.l2cache_set(set, this);
321 }
322
323 // Returns all the L2$ information for a set associated w/ this core
324 char* l2cache_set(uint_t bank, uint_t set)
325 {
326 return mem_err_detector.l2cache_set(bank, set, this);
327 }
328
329 protected:
330 union InstBreakpoint
331 {
332 uint32_t md[2]; // Instruction breakpoint opcode match mask and match data
333 uint64_t mask_data; // A union so that a core can update a strand atomically without locks
334 };
335
336 BL_BoundedArray<InstBreakpoint,2> inst_iw;
337 SS_Vaddr inst_wp_va_mask; // The bits that should be match for a watchpoint hit.
338 SS_Vaddr inst_wp_va_addr; // Bit0 of addr is used to disable (1) or enable(0) watchpoint.
339
340 public:
341 // inst_breakpoint_set() sets the mask and data value for instruction
342 // word breakpoints atomically.
343
344 void inst_breakpoint_set( uint_t index, uint32_t mask, uint32_t data )
345 {
346 assert((data &~ mask) == 0); // Expect data bits not used in match to be zero'd
347 InstBreakpoint ib;
348 ib.md[0] = mask;
349 ib.md[1] = data;
350 inst_iw[index].mask_data = ib.mask_data;
351 }
352
353 // inst_breakpoint_hit() returns true when one of the instruction
354 // breakpoints matches.
355
356 bool inst_breakpoint_hit( uint32_t opc )
357 {
358 return sim_state.ib_enabled()
359 && (inst_iw[0].md[0] && ((opc & inst_iw[0].md[0]) == inst_iw[0].md[1]))
360 || (inst_iw[1].md[0] && ((opc & inst_iw[1].md[0]) == inst_iw[1].md[1]));
361 }
362
363 // inst_watchpoint_va_set() sets the instr_watchpoint of virtual
364 // addesses atomically. Note that bit 0 of the inst_wp_va_addr
365 // is used as enabled(bit0=0) and disable (bit0=1)
366
367 void inst_watchpoint_va_set( SS_Vaddr mask, SS_Vaddr addr )
368 {
369 inst_wp_va_addr = 1; // Force mismatch always
370 inst_wp_va_mask = mask;
371 inst_wp_va_addr = addr;
372 }
373 SS_Vaddr inst_watchpoint_va_get()
374 {
375 return inst_wp_va_addr;
376 }
377
378 // inst_watchpoint_va_hit() returns true when the va matches the
379 // set va watchpoints.
380
381 bool inst_watchpoint_va_hit( SS_Vaddr va )
382 {
383 return (va & inst_wp_va_mask) == inst_wp_va_addr;
384 }
385 // inst_watchpoint_va_near_hit() returns true when the va matches the
386 // set va watchpoints when the mask is applied first. This is used in
387 // decode cache situations to avoid caching cases that should go through
388 // the mmu to check for va watchpoint hits.
389
390 bool inst_watchpoint_va_near_hit( SS_Vaddr mask, SS_Vaddr va )
391 {
392 return (va & inst_wp_va_mask & mask) == (inst_wp_va_addr & (mask + 1));
393 }
394
395 // The inst_mmu can set the inst_dec to a decoder that is used just for a
396 // single cache line. The fetch 512 routines resets the inst_dec back to
397 // the save_dec. ss_trap() also resets the inst_dec back to save_dec.
398 // inst_dec and save_dec can cange when breakpoints on instruction opcode
399 // are activated, either for front end use or for hardware purposes.
400
401 SS_Execute inst_dec; // Pointer to the instruction decode function
402 SS_Execute save_dec; // Always points at the true instruction decoder
403
404 SS_Tte* fail_tte; // Default tte that always mismatches
405 SS_Tte* inst_tte; // Current tte used by IMMU
406 SS_Tte* trc_inst_tte; // Same as inst_tte for tracing purpose
407 SS_Tte* phys_tte_mem; // The TTE used for MMU bypass, e.g. pa == pa, mode for RAM
408 SS_Tte* phys_tte_io; // The TTE used for MMU bypass, e.g. pa == pa, mode for I/O
409 SS_Tte* phys_tte_mem_am; // The TTE used for MMU bypass, e.g. pa == pa, mode for RAM in V8!?!
410 uint64_t mask_pstate_am; // V8 addressing mode mask
411
412 SS_AsiReg inst_dft_asi; // Default instruction ASI with priv mode
413 SS_AsiReg data_dft_asi; // Default data ASI with priv mode
414
415 SS_Tlb* inst_tlb;
416 SS_Tlb* data_tlb;
417
418 SS_PidContext inst_ctx; // Keep track of partition id and context switching
419 SS_PidContext inst_ctx_pa; // For pa2pa pid and ctx don't care
420 SS_PidContext inst_ctx_ra; // For ra2pa ctx don't care
421 SS_PidContext inst_ctx_va; // For va2pa we do care about pid and ctx
422 SS_PidContext data_ctx; // Keep track of partition id and context switching
423
424 SS_Chain* inst_tte_link; // Inst TLB tte usage places
425 uint_t inst_tte_link_size; // Inst TLB tte usage places size
426 SS_Chain phys_tte_link; // Phys tte usage places (inst only)
427 SS_Chain* data_tte_link; // Data TLB tte usage places
428 uint_t data_tte_link_size; // Data TLB tte usage places size
429
430 void (*sim_update)( SS_Strand* );
431
432 SS_TrapFun trap;
433 SS_InstMmu inst_mmu;
434 SS_InstMmu inst_mmu_va;
435 SS_InstMmu inst_mmu_ra;
436 SS_InstMmu inst_mmu_pa;
437 SS_DataMmu data_mmu;
438 SS_MmuTrap inst_trap;
439 SS_MmuTrap data_trap;
440 SS_InvalidAsi invalid_asi;
441
442 const char* (*get_state_name)( SS_Strand*, SS_Registers::Index index );
443 SS_Registers::Error (*get_state)( SS_Strand*, SS_Registers::Index index, uint64_t* value );
444 SS_Registers::Error (*set_state)( SS_Strand*, SS_Registers::Index index, uint64_t value );
445
446
447 // The change_running_from_snapshot can be set to signal to
448 // the change_running() routine that it was called after a
449 // restore from a duymp (snapshot). change_running() should
450 // clear the flag when iut sees it set.
451
452 bool change_running_from_snapshot;
453 void (*change_running)( SS_Strand* );
454
455 bool trap_launch_ok( SS_Trap::Type tt );
456
457 // In v8plus mode we have assembly routines that call trap. Trap is
458 // implemented in C. So in v8plus mode we have v9 assembly calling a
459 // v8plus piece of code. So we need to make a mode conversion between
460 // the assembly and the c code - note we don't want to recode the assembly.
461 // The same happens for a few other routines.
462
463 SS_Execute* v8_exe_table; // Pointers to tables of execute functions
464 SS_TrapFun v8_trap; // v9 to v8plus convertor
465 SS_MmuTrap v8_inst_trap; // ,,
466 SS_MmuTrap v8_data_trap; // ,,
467 SS_DataMmu v8_data_mmu; // ,,
468 SS_InvalidAsi v8_invalid_asi; // ,,
469 SS_Execute v8_inst_dec; // Pointer to the instruction decode function in v8 mode
470
471 // The internal_interrupt and external_interrupt routines deal with
472 // interrupts that come from crosscall or from devices. The external
473 // routine gets a 64 byte payload describing a sun4v interrupt say,
474 // from which it derives and to call the internal routine. The external
475 // routine creates an EXTERNAL_INTERRUPT signal taht is posted with
476 // post_signal; this to make it MP safe.
477
478 void (*internal_interrupt)( SS_Strand*, uint_t, bool );
479 void (*external_interrupt)( SS_Strand*, uint64_t*, bool );
480
481 // TrapState is one entry on the trap stack.
482 struct TrapState
483 {
484 uint64_t pc;
485 uint64_t npc;
486 uint64_t tstate;
487 uint16_t htstate;
488 uint16_t tt;
489 };
490
491 BL_BoundedArray<TrapState,MAX_TL + 1> trap_state;
492
493 BL_BoundedArray<SS_BreakTrap*,SS_Trap::MAX_TT> break_trap;
494 // Breakpoints on a specific trap
495 SS_BreakRedMode*break_red_mode; // Breakpoints on switch to red mode
496 SS_BreakInstVa* break_inst_va; // Breakpoints on instruction va
497 SS_BreakPoint* break_points; // The current set of breakpoints
498 SS_BreakPoint* break_hit;
499
500 // skip_break_inst_va is for the case when the pc matches in the inst_mmu
501 // routine rather then in the ss_break_inst_va_dec. In that case we get
502 // double hits ... this boolean is for ignoring the second hit.
503
504 bool skip_break_inst_va;
505
506 // test_break_inst_va() returns true when at least one breakpoint
507 // matches the given va. When natching it will insert a break signal
508 // in the strands signal queue that will cause exit of the loop.
509
510 bool test_break_inst_va( SS_Vaddr va )
511 {
512 for (SS_BreakInstVa* bp = break_inst_va; bp; bp = (SS_BreakInstVa*)(bp->link))
513 if (bp->break_inst_va(this,va))
514 return true;
515 return false;
516 }
517
518 // near_break_inst_va() returns true when va matches when msk is applied
519 // first ... when the pc walks into a decode cacheline that has a breakpoint
520 // enabled in it.
521
522 bool near_break_inst_va( SS_Vaddr mask, SS_Vaddr va )
523 {
524 for (SS_BreakInstVa* bp = break_inst_va; bp; bp = (SS_BreakInstVa*)(bp->link))
525 if (bp->check_inst_va(mask,va))
526 return true;
527 return false;
528 }
529
530 SS_AsiInfoTable asi_info;
531 SS_AsiMap asi_map;
532 SS_InstrCache* inst_cache;
533 SS_Tracer* trc_hook; // Hook for putting different tracers, for trc_step.
534 SS_Strand* run_next; // Pointer to next strand that is in running mode
535
536 // wrf and grf (and Ecc) point to malloc'ed arrays and never move afterwards
537
538 uint64_t* wrf; // The window registers
539 BL_EccBits* wrf_ecc; // ECC values for window regs
540 uint64_t* grf; // The global registers
541 BL_EccBits* grf_ecc; // ECC values for global regs
542
543 BL_BoundedArray<uint64_t,8> scratchpad; // The privileged scratchpad registers
544 BL_BoundedArray<uint64_t,8> hscratchpad; // The hyper privileged scratchpad registers
545
546 SS_InstrCache* inst_cache_va_nuc_user; // Nucleus context inst cache for user
547 SS_InstrCache* inst_cache_va_pri_user; // Primary context inst cache for user
548 SS_InstrCache* inst_cache_va_nuc_nuc_nuc_priv; // Inst cache for va->pa priv code
549 SS_InstrCache* inst_cache_va_nuc_nuc_sec_priv; // Inst cache for va->pa priv code
550 SS_InstrCache* inst_cache_va_nuc_pri_sec_priv; // Inst cache for va->pa priv code
551 SS_InstrCache* inst_cache_va_pri_priv; // Inst cache for va->pa priv code
552 SS_InstrCache* inst_cache_ra_nuc_user; // Inst cache for user ra->pa code
553 SS_InstrCache* inst_cache_ra_pri_user; // Inst cache for user ra->pa code
554 SS_InstrCache* inst_cache_ra_nuc_priv; // Inst cache for priv ra->pa code
555 SS_InstrCache* inst_cache_ra_pri_priv; // Inst cache for priv ra->pa code
556 SS_InstrCache* inst_cache_pa; // Inst cache for hprv and red mode pa->pa
557
558 SS_Model* model;
559 SS_Node* parent;
560 const char* name;
561
562 static void ss_sim_update( SS_Strand* );
563 static SS_Vaddr ss_trap( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i, SS_Trap::Type tt );
564 static SS_AsiSpace::Error scratchpad_ld64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t* );
565 static SS_AsiSpace::Error scratchpad_st64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t );
566 static SS_AsiSpace::Error lsu_ctr_st64 ( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t );
567
568 void merge_asi_map();
569
570 void cwp_save();
571 void do_save_inst();
572 void cwp_load();
573 void do_restore_inst();
574 void gl_save();
575 void gl_load();
576 void tl_save();
577 void tl_load();
578 void get_fsr();
579 void set_fsr();
580 void do_retry();
581 void trc_state();
582
583 // irq is the structure that holds all the disrupting traps until they are take.
584 SS_Interrupt irq;
585
586 // flush_va() is for va watchpoint and va breakpoint detection
587 void flush_va( SS_Vaddr );
588
589 // flush() is mainly useful for frontends to flush a particular pa
590 // when code has been written to memory throu the FPE
591
592 static const uint64_t RAS_TTE_POISON = 1;
593 void flush( SS_Paddr, bool for_ras=false );
594
595 void setup_tte_link_tables();
596 void flush_tte( SS_Tlb* tlb, SS_Tte* );
597 void flush_tte_all();
598
599 SS_Message msg;
600
601 void post_signal( SS_Signal* sgn ) { msg.post_signal(sgn); }
602 bool peek_signal();
603
604 // The swig interface is a bit anoying for the get/set_state methods.
605 // So we provide SWIG (Python) two members to hold errors returned.
606 // This is a workaround, need to look into this to fix (see SWIG pointer.i file)
607
608 SS_Registers::Error reg_error;
609 SS_AsiSpace::Error asi_error;
610
611 // cnv2pa is for frontend purposes and translates a given va/ra with optional
612 // given context and optional given partition id to a physical address.
613 // The default context is primary_context[0] .
614
615 Sam::Vcpu::TranslateError (*cnv2pa)( SS_Strand*, Sam::Vcpu::TranslateMode, SS_Vaddr, uint64_t ctx, uint64_t pid, SS_Paddr* pa );
616
617 // Hooks for IRF/FRF ras support
618 SS_RasIrfSrc ras_rs1; // IRF
619 SS_RasIrfSrc ras_rs2;
620 SS_RasIrfSrc ras_rs3;
621 SS_RasIrfDst ras_rd;
622
623 SS_RasFrfSrc ras_frs1; // Single precison FP
624 SS_RasFrfSrc ras_frs2;
625 SS_RasFrfSrc ras_frs3;
626 SS_RasFrfDst ras_frd;
627
628 SS_RasDrfSrc ras_drs1; // Double precison FP
629 SS_RasDrfSrc ras_drs2;
630 SS_RasDrfSrc ras_drs3;
631 SS_RasDrfDst ras_drd;
632
633 // The ras_enable routine is used to turn on RAS features
634
635 void (*ras_enable)( SS_Strand*, char* cmd);
636
637 static void default_ras_enable( SS_Strand*, char* cmd );
638
639 void (*run_perf) ( SS_Strand* s, Sam::Vcpu::perfcntr which, int64_t incr );
640
641 //============================================================================
642 // For cosim mode we need a few hooks for irq, tlb and other syncing that goes
643 // on between the reference and device under test. All those hooks go here
644 //============================================================================
645
646 std::map<SS_Registers::Index,uint64_t> *ctr_sync;
647
648 void* irq_sync;
649 void (*irq_store)( void* irq_sync, SS_Trap::Type irq_type, bool do_time_out );
650
651 void* tlb_sync;
652 void (*inst_tlb_read)( void* tlb_sync );
653 void inst_tlb_set( SS_Tlb* );
654 int (*inst_tlb_write)( void* tlb_sync );
655 void (*inst_tlb_lookup)( void* tlb_sync );
656 void (*data_tlb_read)( void* tlb_sync );
657 bool data_tlb_read_skip;
658 int (*data_tlb_write)( void* tlb_sync );
659 void (*data_tlb_lookup)( void* tlb_sync );
660
661 SS_Trap::Type (*inst_hwtw)( SS_Strand* strand, SS_Vaddr va, int_t entry );
662 SS_Trap::Type (*data_hwtw)( SS_Strand* strand, SS_Vaddr va, uint8_t asi, int_t entry );
663
664 bool inst_mmu_error; // Used in cosim to sync trap 0x71
665 bool data_mmu_error; // Used in cosim to sync trap 0x72
666
667 void *asi_ext_obj; // The object that have the external call back function
668
669 SS_AsiSpace::Error (*asi_ext_ld64_fp)( SS_Node*, void*, SS_Strand* s, SS_Vaddr va, uint64_t* data );
670 SS_AsiSpace::Error (*asi_ext_st64_fp)( SS_Node*, void*, SS_Strand* s, SS_Vaddr va, uint64_t data );
671
672 static SS_AsiSpace::Error asi_ext_ld64( SS_Node* a, void* b, SS_Strand* s, SS_Vaddr va, uint64_t* data );
673 static SS_AsiSpace::Error asi_ext_st64( SS_Node* a, void* b, SS_Strand* s, SS_Vaddr va, uint64_t data );
674
675 static void SS_Strand::ss_run_perf( SS_Strand* s, Sam::Vcpu::perfcntr which, int64_t incr );
676
677 static const char* ss_get_state_name( SS_Strand*, SS_Registers::Index index );
678 static SS_Registers::Error ss_get_state( SS_Strand*, SS_Registers::Index index, uint64_t* value );
679 static SS_Registers::Error ss_set_state( SS_Strand*, SS_Registers::Index index, uint64_t value );
680};
681
682inline void SS_Strand::cwp_save()/*{{{*/
683{
684 int i;
685 uint64_t* q = &wrf[cwp()*16];
686
687 if (!sim_state.ras_enabled())
688 {
689 for (i=0; i < 16; i++)
690 q[i] = irf[i + 16];
691
692 if (cwp() == max_wp())
693 q = &wrf[0];
694 else
695 q = q + 16;
696
697 for (i=8; i < 16; i++)
698 q[i] = irf[i];
699 }
700 else
701 {
702 BL_EccBits* q_ecc = &wrf_ecc[cwp()*16];
703
704 for (i=0; i < 16; i++)
705 {
706 q[i] = irf[i + 16];
707 q_ecc[i] = irf_ecc[i + 16];
708 }
709
710 if (cwp() == max_wp())
711 {
712 q = &wrf[0];
713 q_ecc = &wrf_ecc[0];
714 }
715 else
716 {
717 q = q + 16;
718 q_ecc += 16;
719 }
720
721 for (i=8; i < 16; i++)
722 {
723 q[i] = irf[i];
724 q_ecc[i] = irf_ecc[i];
725 }
726 }
727}
728/*}}}*/
729inline void SS_Strand::cwp_load()/*{{{*/
730{
731 int i;
732 uint64_t* q = &wrf[cwp()*16];
733 BL_EccBits* q_ecc = &wrf_ecc[cwp()*16];
734
735 if (!sim_state.ras_enabled())
736 {
737 for (i=0; i < 16; i++)
738 irf[i + 16] = q[i];
739
740 if (cwp() == max_wp())
741 q = &wrf[0];
742 else
743 q = q + 16;
744
745 for (i=0; i < 8; i++)
746 irf[i + 8] = q[i + 8];
747 }
748 else
749 {
750 for (i=0; i < 16; i++)
751 {
752 irf[i + 16] = q[i];
753 irf_ecc[i + 16] = q_ecc[i];
754 }
755
756 if (cwp() == max_wp())
757 {
758 q = &wrf[0];
759 q_ecc = &wrf_ecc[0];
760 }
761 else
762 {
763 q = q + 16;
764 q_ecc += 16;
765 }
766
767 for (i=0; i < 8; i++)
768 {
769 irf[i + 8] = q[i + 8];
770 irf_ecc[i + 8] = q_ecc[i + 8];
771 }
772 }
773}
774/*}}}*/
775inline void SS_Strand::do_save_inst()/*{{{*/
776{
777 int i;
778 uint64_t* q = &wrf[cwp()*16];
779
780 if (!sim_state.ras_enabled())
781 {
782 for (i=0; i < 16; i++)
783 q[i] = irf[i + 16];
784
785 for (i=0; i < 8; i++)
786 irf[i + 24] = irf[i + 8];
787
788 cwp = (cwp() < max_wp()) ? (cwp() + 1) : 0;
789 cansave = cansave() ? (cansave() - 1) : max_wp();
790 canrestore = (canrestore() < max_wp()) ? (canrestore() + 1) : 0;
791 q = &wrf[cwp()*16];
792
793 for (i=0; i < 8; i++)
794 irf[i + 16] = q[i];
795
796 if (cwp() == max_wp())
797 q = &wrf[0];
798 else
799 q = q + 16;
800
801 for (i=0; i < 8; i++)
802 irf[i + 8] = q[i + 8];
803 }
804 else
805 {
806 BL_EccBits* q_ecc = &wrf_ecc[cwp()*16];
807
808 for (i=0; i < 16; i++)
809 {
810 q[i] = irf[i + 16];
811 q_ecc[i] = irf_ecc[i + 16];
812 }
813
814 for (i=0; i < 8; i++)
815 {
816 irf[i + 24] = irf[i + 8];
817 irf_ecc[i + 24] = irf_ecc[i + 8];
818 }
819
820 cwp = (cwp() < max_wp()) ? (cwp() + 1) : 0;
821 cansave = cansave() ? (cansave() - 1) : max_wp();
822 canrestore = (canrestore() < max_wp()) ? (canrestore() + 1) : 0;
823 q = &wrf[cwp()*16];
824 q_ecc = &wrf_ecc[cwp()*16];
825
826 for (i=0; i < 8; i++)
827 {
828 irf[i + 16] = q[i];
829 irf_ecc[i + 16] = q_ecc[i];
830 }
831
832 if (cwp() == max_wp())
833 {
834 q = &wrf[0];
835 q_ecc = &wrf_ecc[0];
836 }
837 else
838 {
839 q = q + 16;
840 q_ecc += 16;
841 }
842
843 for (i=0; i < 8; i++)
844 {
845 irf[i + 8] = q[i + 8];
846 irf_ecc[i + 8] = q_ecc[i + 8];
847 }
848 }
849}
850/*}}}*/
851inline void SS_Strand::do_restore_inst()/*{{{*/
852{
853 int i;
854 uint64_t* q = &wrf[cwp()*16];
855 BL_EccBits* q_ecc = &wrf_ecc[cwp()*16];
856
857 if (!sim_state.ras_enabled())
858 {
859 for (i=0; i < 16; i++)
860 q[i] = irf[16 + i];
861
862 if (cwp() == max_wp())
863 q = &wrf[0];
864 else
865 q = q + 16;
866
867 for (i=8; i < 16; i++)
868 q[i] = irf[i];
869
870 cwp = cwp() ? (cwp() - 1) : max_wp();
871 cansave = (cansave() < max_wp()) ? (cansave() + 1) : 0;
872 canrestore = canrestore() ? (canrestore() - 1) : max_wp();
873
874 q = &wrf[cwp()*16];
875
876 for (i=0; i < 8; i++)
877 {
878 irf[i + 8] = irf[i + 24];
879 irf[i + 24] = q[i + 8];
880 irf[i + 16] = q[i];
881 }
882 }
883 else
884 {
885 for (i=0; i < 16; i++)
886 {
887 q[i] = irf[16 + i];
888 q_ecc[i] = irf_ecc[16 + i];
889 }
890
891 if (cwp() == max_wp())
892 {
893 q = &wrf[0];
894 q_ecc = &wrf_ecc[0];
895 }
896 else
897 {
898 q = q + 16;
899 q_ecc = q_ecc + 16;
900 }
901
902 for (i=8; i < 16; i++)
903 {
904 q[i] = irf[i];
905 q_ecc[i] = irf_ecc[i];
906 }
907
908 cwp = cwp() ? (cwp() - 1) : max_wp();
909 cansave = (cansave() < max_wp()) ? (cansave() + 1) : 0;
910 canrestore = canrestore() ? (canrestore() - 1) : max_wp();
911
912 q = &wrf[cwp()*16];
913 q_ecc = &wrf_ecc[cwp()*16];
914
915 for (i=0; i < 8; i++)
916 {
917 irf[i + 8] = irf[i + 24];
918 irf[i + 24] = q[i + 8];
919 irf[i + 16] = q[i];
920
921 irf_ecc[i + 8] = irf_ecc[i + 24];
922 irf_ecc[i + 24] = q_ecc[i + 8];
923 irf_ecc[i + 16] = q_ecc[i];
924 }
925 }
926}
927/*}}}*/
928inline void SS_Strand::gl_save()/*{{{*/
929{
930 int i;
931 uint64_t* q = &grf[gl() * 8];
932
933 for (i=0; i < 8; i++)
934 q[i] = irf[i];
935
936 if (sim_state.ras_enabled())
937 {
938 BL_EccBits* q_ecc = &grf_ecc[gl() * 8];
939
940 for (i=0; i < 8; i++)
941 q_ecc[i] = irf_ecc[i];
942 }
943}
944/*}}}*/
945inline void SS_Strand::gl_load()/*{{{*/
946{
947 int i;
948 uint64_t* q = &grf[gl() * 8];
949
950 for (i=0; i < 8; i++)
951 irf[i] = q[i];
952
953 if (sim_state.ras_enabled())
954 {
955 BL_EccBits* q_ecc = &grf_ecc[gl() * 8];
956
957 for (i=0; i < 8; i++)
958 irf_ecc[i] = q_ecc[i];
959 }
960}
961/*}}}*/
962
963#endif