# ========== Copyright Header Begin ==========================================
# OpenSPARC T2 Processor File: SS_InstrLsu.py
# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
# The above named program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License version 2 as published by the Free Software Foundation.
# The above named program is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
# You should have received a copy of the GNU General Public
# License along with this work; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
# ========== Copyright Header End ============================================
from SS_Instr
import _if_
setup
= setups
[sys
.argv
[1]]
#============================================================================
#============================================================================
class SS_lsu_exe(SS_InstrAsm
):
SS_InstrAsm
.__init
__(self
,opc
)
self
.asi
= ['dft', 'reg', 'imm']
self
.out
= ['rd' ,'g0', 'ia']
return self
.opc
== 'ldf' or self
.opc
== 'lddf' or self
.opc
== 'stf' or self
.opc
== 'stdf' or \
self
.opc
[2:7] == 'short' or self
.opc
[2:7] == 'block' or self
.opc
[2:7] == 'parti' or \
Is load or store a simple single precision FP operation
return self
.opc
== 'ldf' or self
.opc
== 'stf'
Is load or store a simple double precision FP operation
return self
.opc
== 'lddf' or self
.opc
== 'stdf'
return self
.opc
[:6] == 'ldstub' or self
.opc
[:4] == 'swap' or self
.opc
[:3] == 'cas'
def run_exe_c(self
,file):
if self
.is_float() or self
.opc
== 'prefetch' or self
.opc
== 'flush':
# ldfsr, stfsr, ldxfsr, stxfsr, and ldxefsr don't have alternative space versions
if self
.opc
[-3:] == 'fsr' and asi
!= 'dft':
file.write('#if defined(ARCH_X64)\n')
self
.c_code_beg_name(file,'run_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
)
if out
== 'rd' or out
== 'g0' or out
== 'fp' or out
== 'fn':
alignment
=self
.va_lower_bits()
mmu_access
= not (self
.opc
== 'flush')
file.write(' if (s->sim_state.fp_disabled())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::FP_DISABLED);\n')
file.write(' if (i->asi != s->asi())\n')
file.write(' return (s->inst_dec)(pc,npc,s,i);\n')
if (self
.opc
[:3] == 'cas'):
file.write(' uint64_t ea = s->get_irf(i->rs1);\n')
elif (self
.opc
== 'stpartial8'):
file.write(' uint64_t ea = s->get_irf(i->rs1);\n')
file.write(' uint64_t rs2 = s->get_irf(i->rs2);\n')
file.write(' s->mem_mask = rs2 & 0xff;\n')
elif (self
.opc
== 'stpartial16'):
file.write(' uint64_t ea = s->get_irf(i->rs1);\n')
file.write(' uint64_t rs2 = s->get_irf(i->rs2);\n')
file.write(' s->mem_mask = s->stpartial16[rs2 & 0xf];\n')
elif (self
.opc
== 'stpartial32'):
file.write(' uint64_t ea = s->get_irf(i->rs1);\n')
file.write(' uint64_t rs2 = s->get_irf(i->rs2);\n')
file.write(' s->mem_mask = s->stpartial32[rs2 & 0x3];\n')
file.write(' uint64_t rs1 = s->get_irf(i->rs1);\n')
file.write(' uint64_t rs2 = s->get_irf(i->rs2);\n')
file.write(' int64_t rs2 = i->rs2;\n')
file.write(' uint64_t ea = rs1 + rs2;\n')
file.write(' if (ea & '+alignment
+') {\n')
if (self
.opc
[:4] == 'lddf'):
file.write(' if ((ea & 7) == 4)\n')
file.write(' return (s->data_trap)(pc,npc,s,i,ea,SS_Trap::LDDF_MEM_ADDRESS_NOT_ALIGNED);\n')
elif (self
.opc
[:4] == 'stdf'):
file.write(' if ((ea & 7) == 4)\n')
file.write(' return (s->data_trap)(pc,npc,s,i,ea,SS_Trap::STDF_MEM_ADDRESS_NOT_ALIGNED);\n')
file.write(' return (s->data_trap)(pc,npc,s,i,ea,SS_Trap::MEM_ADDRESS_NOT_ALIGNED);\n')
file.write(' uint_t mem = idx_mem_'+self
.opc
+'_'+out
+';\n')
file.write(' SS_Tte *_tte = i->get_tte();\n')
file.write(' if (!_tte->match(ea))\n')
file.write(' return (s->data_mmu)(pc,npc,s,i,ea,mem);\n')
file.write(' SS_Memop exe = s->mem_table[mem][((uint64_t)i->tte & 3)];\n')
file.write(' return (exe)(pc,npc,s,i,ea,i->tte);\n')
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
file.write(' if (s->sim_state.fp_disabled())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::FP_DISABLED);\n')
file.write(' if (i->asi != s->asi())\n')
file.write(' return (s->inst_dec)(pc,npc,s,i);\n')
file.write(' uint64_t rs1 = s->get_irf(i->rs1);\n')
if (self
.opc
[:3] == 'cas' or self
.opc
[:9] == 'stpartial'):
file.write(' SS_Vaddr ea = rs1;\n');
file.write(' uint64_t rs2 = s->get_irf(i->rs2);\n')
file.write(' int64_t rs2 = i->rs2;\n');
file.write(' SS_Vaddr ea = rs1 + rs2;\n');
file.write(' return (s->invalid_asi)(pc,npc,s,i,ea);\n')
file.write('extern "C" SS_Vaddr run_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
+'( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i );\n')
def run_exe_s(self
,file):
if self
.is_float() or self
.opc
== 'prefetch' or self
.opc
== 'flush':
# ldfsr, stfsr, ldxfsr, stxfsr, and ldxefsr don't have alternative space versions
if self
.opc
[-3:] == 'fsr' and asi
!= 'dft':
#----------------------------------------------------------------------------
#----------------------------------------------------------------------------
if out
== 'rd' or out
== 'g0' or out
== 'fp' or out
== 'fn':
self
.asm_function(file,'run_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
)
alignment
=self
.va_lower_bits()
mmu_access
= not (self
.opc
== 'flush')
byte_mask
=self
.wp_byte_mask()
' ldx [S_PTR + S_SIM_STATE],%g5',
' andcc %g5,F_FP_DISABLED,%g0',
' bne %xcc,fpop_disabled_trap'
' lduh [I_PTR + I_ASI],%g1\n' # check for %asi change
' ldub [S_PTR + S_ASI],%g2', # change uh when asi changes ToDo
' ldptr [I_PTR + I_TTE],%o5', # o0 o1 o2 o3 -- o5 -- -- -- -- --
' lduh [I_PTR + I_RS1],%o4', # .. .. .. .. o4 .. -- -- -- -- --
' lduh [I_PTR + I_RS2],%g5' # .. .. .. .. .. .. -- -- -- -- g5
' ldsh [I_PTR + I_RS2],%g5'
' and %o5,-4,%g2', # .. .. .. .. .. .. -- g2 -- -- ..
' bne %xcc,2f', # Oops, -> redecode instruction
' ldptr [S_PTR + S_MEM_TABLE],%g3', # .. .. .. .. .. .. -- .. g3 -- ..
' ldx [S_PTR + %o4],%o4',
' ldx [S_PTR + %g5],%g5', ''
' and %o5,3,%g4', # mem b, mem l, io b, io l?
' ldx [%g2 + X_VIRT_MASK],%g1', # .. .. .. .. .. .. g1 .. .. -- ..
' sll %g4,PTR_SIZE_BITS,%g4',
' ldx [%g2 + X_VIRT_PAGE],%g2', # .. .. .. .. .. .. .. .. .. -- ..
_if_(self_opc
[:3] == 'cas',
_if_(self_opc
== 'stpartial8',
' stx %g5,[S_PTR + S_MEM_MASK]',
_if_(self_opc
== 'stpartial16',
' add %g5,S_STPARTIAL16,%g5\n'
' ldub [S_PTR + %g5],%g5\n'
' stx %g5,[S_PTR + S_MEM_MASK]',
_if_(self_opc
== 'stpartial32',
' add %g5,S_STPARTIAL32,%g5\n'
' ldub [S_PTR + %g5],%g5\n'
' stx %g5,[S_PTR + S_MEM_MASK]',
)))), # .. .. .. .. .. .. .. .. -- -- --
' and %o4,%g1,%g1', # .. .. .. .. .. .. .. .. -- -- --
' andcc %o4,'+alignment
+',%g0',
' ldptr [%g3 + IDX_MEM_'+self
.opc
.upper()+'_'+out
.upper()+'*4*PTR_SIZE],%g5',
_if_(self
.opc
[:4] == 'lddf',
' bne %xcc,ss_data_trap_lddf_mem_address_not_aligned',
_if_(self
.opc
[:4] == 'stdf' or self
.opc
[:9] == 'stpartial',
' bne %xcc,ss_data_trap_stdf_mem_address_not_aligned',
' bne %xcc,ss_data_trap_mem_address_not_aligned',
' ldptr [S_PTR + DATA_MMU],%g1',
' mov IDX_MEM_'+self
.opc
.upper()+'_'+out
.upper()+',%o5',
' lduh [I_PTR + I_ASI],%g1\n' # check for %asi change
' ldub [S_PTR + S_ASI],%g2', # change uh when asi changes ToDo
' lduh [I_PTR + I_RS1],%o4', # .. .. .. .. o4 .. -- -- -- -- --
' lduh [I_PTR + I_RS2],%g5' # .. .. .. .. .. .. -- -- -- -- g5
' ldsh [I_PTR + I_RS2],%g5'
' bne %xcc,2f', # Oops, -> redecode instruction
' ldptr [S_PTR + S_MEM_TABLE],%g3', # .. .. .. .. .. .. -- .. g3 -- ..
' ldx [S_PTR + %o4],%o4',
' ldx [S_PTR + %g5],%g5', ''
' ldptr [%g3 + IDX_MEM_'+self
.opc
.upper()+'_'+out
.upper()+'*4*PTR_SIZE],%g1',
# %asi changed compared to last time we executed the instruction.
# The instruction needs to be redecoded to correct for that change
# through recursion ... keep it simple (but avoid infinite loops!)
file.write(' ldptr [S_PTR + INST_DEC],%g1\n')
file.write(' jmpl %g1,%g0\n')
#----------------------------------------------------------------------------
# invalid asi, check all the things in a C routine ... could do effective
# address calculation there too .... ToDo
#----------------------------------------------------------------------------
self
.asm_function(file,'run_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
)
alignment
=self
.va_lower_bits()
' ldx [S_PTR + S_SIM_STATE],%g5',
' andcc %g5,F_FP_DISABLED,%g0',
' bne %xcc,fpop_disabled_trap']:
file.write(' lduh [I_PTR + I_ASI],%g1\n')
file.write(' ldub [S_PTR + S_ASI],%g2\n')
file.write(' subcc %g1,%g2,%g0\n')
file.write(' bne %xcc,2f\n')
if self
.opc
[:3] == 'cas' or self_opc
[:9] == 'stpartial':
' ldptr [S_PTR + INVALID_ASI],%g1',
' lduh [I_PTR + I_RS1],%o4',
' ldx [S_PTR + %o4],%o4']:
' lduh [I_PTR + I_RS1],%o4',
' lduh [I_PTR + I_RS2],%g5',
' ldptr [S_PTR + INVALID_ASI],%g1',
' ldx [S_PTR + %o4],%o4',
' ldx [S_PTR + %g5],%g5',
' lduh [I_PTR + I_RS1],%o4',
' ldsh [I_PTR + I_RS2],%g5',
' ldptr [S_PTR + INVALID_ASI],%g1',
' ldx [S_PTR + %o4],%o4',
file.write(' ldptr [S_PTR + INST_DEC],%g1\n')
file.write(' jmpl %g1,%g0\n')
def gen_exe_tbl(self
,file,mode
):
if self
.is_float() or self
.opc
== 'prefetch' or self
.opc
== 'flush':
if self
.opc
[-3:] == 'fsr' and asi
!= 'dft':
# handle loads -- first std FP, then odd FP, then IRF
self
.gen_exe_frI(file,mode
,imm
,out
)
self
.gen_exe_drI(file,mode
,imm
,out
)
elif self
.opc
[-3:] == 'fsr':
self
.gen_exe_0rI(file,mode
,imm
,out
)
elif self
.opc
[2:7] == 'block':
self
.gen_exe_brI(file,mode
,imm
,out
)
elif self
.opc
[2:7] == 'short' or self
.opc
[2:7] == 'parti':
self
.gen_exe_drI(file,mode
,imm
,out
)
file.write(' '+mode
+'_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
+',\n')
elif self
.opc
[:3] == 'ldd' or self
.opc
[:4] == 'ldtd':
self
.gen_exe_prI(file,mode
,imm
,out
)
self
.gen_exe_rrI(file,mode
,imm
,out
)
# handle stores -- first std FP, then odd FP, then IRF
elif self
.opc
[:2] == 'st':
self
.gen_exe_FrI(file,mode
,imm
,out
)
self
.gen_exe_DrI(file,mode
,imm
,out
)
elif self
.opc
[-3:] == 'fsr':
self
.gen_exe_0rI(file,mode
,imm
,out
)
elif self
.opc
[2:7] == 'block':
self
.gen_exe_BrI(file,mode
,imm
,out
)
elif self
.opc
[2:7] == 'short' or self
.opc
[2:7] == 'parti':
self
.gen_exe_DrI(file,mode
,imm
,out
)
file.write(' '+mode
+'_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
+',\n')
elif self
.opc
[:3] == 'std' or self
.opc
[:4] == 'sttd':
self
.gen_exe_PrI(file,mode
,imm
,out
)
self
.gen_exe_rrI(file,mode
,imm
,out
)
# handle cas, swap, and ldstub
file.write(' trc_exe_cas_'+imm
+',\n')
file.write(' '+mode
+'_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
+',\n')
elif self
.opc
[:8] == 'prefetch':
self
.gen_exe_0rI(file,mode
,imm
,out
)
elif self
.opc
== 'flush':
self
.gen_exe_0rI(file,mode
,imm
,out
)
# everything is just trc_exe_<opc>_...
file.write(' '+mode
+'_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
+',\n')
file.write(' run_exe_v8plus_to_v9, /* run_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
+' */\n')
file.write(' '+mode
+'_exe_'+self
.opc
+'_'+asi
+'_'+imm
+'_'+out
+',\n')
def exe_idx_s(self
,file):
if self
.is_float() or self
.opc
== 'prefetch' or self
.opc
== 'flush':
if self
.opc
[-3:] == 'fsr' and asi
!= 'dft':
self
.exe_idx_s_name(file,self
.opc
+'_'+asi
+'_'+imm
+'_'+out
)
if opc
== 'ldsb' or opc
== 'ldub' or opc
== 'stb' or opc
== 'ldstub' or opc
== 'ldshortf8' or \
opc
== 'stshortf8' or opc
=='prefetch' or opc
== 'flush':
elif opc
== 'ldsh' or opc
== 'lduh' or opc
== 'sth' or opc
== 'ldshortf16' or opc
== 'stshortf16':
elif opc
== 'ldsw' or opc
== 'lduw' or opc
== 'stw' or opc
== 'swap' or opc
== 'cas' or \
opc
== 'ldf' or opc
== 'stf' or opc
== 'ldfsr' or opc
== 'stfsr':
elif opc
== 'ldx' or opc
== 'ldd' or opc
== 'stx' or opc
== 'std' or opc
== 'casx' or \
opc
== 'lddf' or opc
== 'stdf' or opc
[:9] == 'stpartial' or opc
== 'ldxfsr' or opc
== 'stxfsr' or \
elif opc
== 'ldblockf' or opc
== 'stblockf':
return 'va_lower_bits unknown'
if opc
== 'ldsb' or opc
== 'ldub' or opc
== 'stb' or opc
== 'ldstub' or opc
== 'ldshortf8' or \
opc
== 'stshortf8' or opc
== 'prefetch':
elif opc
== 'ldsh' or opc
== 'lduh' or opc
== 'sth' or opc
== 'ldshortf16' or opc
== 'stshortf16':
elif opc
== 'ldsw' or opc
== 'lduw' or opc
== 'stw' or opc
== 'swap' or opc
== 'cas' or \
opc
== 'ldf' or opc
== 'stf' or opc
== 'ldfsr' or opc
== 'stfsr':
elif opc
== 'ldx' or opc
== 'ldd' or opc
== 'stx' or opc
== 'std' or opc
== 'casx' or \
opc
== 'lddf' or opc
== 'stdf' or opc
[:9] == 'stpartial' or opc
== 'ldxfsr' or opc
== 'stxfsr' or \
elif opc
== 'ldblockf' or opc
== 'stblockf':
#============================================================================
#----------------------------------------------------------------------------
# N2 verification revealed a corner case that is not being dealt with properly
# An ASI can be translating or non-translating. When it is translating it can
# be an invalid ASI for the instruction and the MEM_ADDRESS_RANGE (MEM_REAL_RANGE)
# trap has higher priority so that needs to be checked first. The code below
# combines unimplemented ASIs (will cause INVALID_ASI trap when used) and invalid
# (translating) ASI for an instruction in one routine ... ToDo, this should
# be reengineered - at the moment we path the trap type in xx_data_trap().
#============================================================================
class SS_lsu_dec(SS_InstrCpp
):
SS_InstrCpp
.__init
__(self
,opc
)
def cond_index(self
,test
,true_index
,false_index
):
return '(('+test
+') ? ' + true_index
+' : '+false_index
+')'
def run_dec_c(self
,file):
# prefetcha?_tmp is only a placeholder to prefetch_dec ... only onde decoder needed
if opc
[:8] == 'prefetch':
self
.c_code_dec_beg_name(file,'run_dec_'+opc
)
#----------------------------------------------------------------------
#----------------------------------------------------------------------
file.write(' i->asi = s->data_dft_asi();\n')
file.write(' i->tte = s->fail_tte;\n')
file.write(' i->flg = SS_Instr::DFT_ASI|SS_Instr::READ|SS_Instr::WRITE;\n')
file.write(' i->flg = SS_Instr::DFT_ASI|SS_Instr::WRITE;\n')
file.write(' i->flg = SS_Instr::DFT_ASI|SS_Instr::FETCH;\n')
file.write(' i->flg = SS_Instr::DFT_ASI|SS_Instr::FLUSH;\n')
file.write(' i->flg = SS_Instr::DFT_ASI|SS_Instr::READ;\n')
file.write(' i->len = '+self
.mem_len()+';\n')
if opc
== 'ldd' or opc
== 'std':
file.write(' if (o.get_rd_irf() & 8)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' if (o.get_i())\n')
asi_test
= 's->sim_state.priv() < s->asi_info[i->asi].get_protection()'
asi_index
= 'idx_exe_'+opc
+'_dft_i1_ia'
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i1_fp')
self
.dec_0r13(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i1_fp')
self
.dec_dr13(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i1_fp')
self
.dec_fr13(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i1_fn')
self
.dec_nr13(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i1_fn')
self
.dec_nr13(file,' ',cidx
)
file.write(' if (o.get_rd_irf())\n')
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i1_rd')
self
.dec_rr13(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i1_g0')
self
.dec_0r13(file,' ',cidx
)
file.write(' else if (o.is_zero_12_5())\n')
asi_test
= 's->sim_state.priv() < s->asi_info[i->asi].get_protection()'
asi_index
= 'idx_exe_'+opc
+'_dft_i0_ia'
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i0_fp')
self
.dec_0rr(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i0_fp')
self
.dec_drr(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i0_fp')
self
.dec_frr(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i0_fn')
self
.dec_nrr(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i0_fn')
self
.dec_nrr(file,' ',cidx
)
file.write(' if (o.get_rd_irf())\n')
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i0_rd')
self
.dec_rrr(file,' ',cidx
)
cidx
= self
.cond_index(asi_test
,asi_index
,'idx_exe_'+opc
+'_dft_i0_g0')
self
.dec_0rr(file,' ',cidx
)
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
#----------------------------------------------------------------------
# REG_ASI , note casa and casxa are still rrr iso rri
#----------------------------------------------------------------------
file.write(' i->tte = s->fail_tte;\n')
if opc
== 'ldda' or opc
== 'stda':
file.write(' if (o.get_rd_irf() & 8)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' if (o.get_i())\n')
file.write(' i->asi = s->asi();\n')
file.write(' i->flg = SS_Instr::REG_ASI|SS_Instr::READ|SS_Instr::WRITE;\n')
file.write(' i->flg = SS_Instr::REG_ASI|SS_Instr::WRITE;\n')
file.write(' i->flg = SS_Instr::REG_ASI|SS_Instr::FETCH;\n')
file.write(' i->flg = SS_Instr::REG_ASI|SS_Instr::FLUSH;\n')
file.write(' i->flg = SS_Instr::REG_ASI|SS_Instr::READ;\n')
file.write(' i->len = '+self
.mem_len()+';\n')
file.write(' SS_AsiInfo asi_info = s->asi_info[i->asi];\n')
file.write(' if (!o.is_zero_12_5())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_rr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i0_ia')
file.write(' if (!asi_info.is_valid_atomic_asi())\n')
self
.dec_rr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_rr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_atomic_asi())\n')
self
.dec_rr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_nr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_prefetch_asi())\n')
self
.dec_nr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_flush_asi())\n')
self
.dec_nr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (asi_info.is_quad_load_asi())\n')
if setup
.product
== 'N2':
file.write(' i->len = 16;\n')
file.write(' if (o.get_rd_irf() & 0x8)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (o.get_rd_irf())\n')
self
.dec_rr13(file,' ','idx_exe_ldtd_reg_i1_rd')
self
.dec_0r13(file,' ','idx_exe_ldtd_reg_i1_g0')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_ld_asi())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_ldx_asi())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_translating())\n')
file.write(' if (o.get_rd_irf())\n')
self
.dec_rr13(file,' ','idx_exe_rdasi_i1_rd')
self
.dec_0r13(file,' ','idx_exe_rdasi_i1_g0')
file.write(' if (asi_info.is_shortf8_asi())\n')
file.write(' i->len = 1;\n')
self
.dec_dr13(file,' ','idx_exe_ldshortf8_reg_i1_fp')
file.write(' else if (asi_info.is_shortf16_asi())\n')
file.write(' i->len = 2;\n')
self
.dec_dr13(file,' ','idx_exe_ldshortf16_reg_i1_fp')
file.write(' else if (asi_info.is_block_init_asi())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' else if (asi_info.is_block_load_asi())\n')
file.write(' i->len = 64;\n')
file.write(' if (o.get_rd_drf() & 0x38)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
self
.dec_dr13(file,' ','idx_exe_ldblockf_reg_i1_fp')
file.write(' else if (asi_info.is_block_store_asi())\n') # block commit are write only
file.write(' i->len = 64;\n')
file.write(' if (o.get_rd_drf() & 0x38)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_ld_asi())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_ld_asi())\n')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_rr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_stx_asi())\n')
self
.dec_rr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_translating())\n')
file.write(' if (o.get_rd_irf())\n')
self
.dec_rr13(file,' ','idx_exe_wrasi_i1_rd')
self
.dec_0r13(file,' ','idx_exe_wrasi_i1_g0')
file.write(' if (asi_info.is_shortf8_asi())\n')
file.write(' i->len = 1;\n')
self
.dec_dr13(file,' ','idx_exe_stshortf8_reg_i1_fp')
file.write(' else if (asi_info.is_shortf16_asi())\n')
file.write(' i->len = 2;\n')
self
.dec_dr13(file,' ','idx_exe_stshortf16_reg_i1_fp')
file.write(' else if (asi_info.is_partial8_asi())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' else if (asi_info.is_partial16_asi())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' else if (asi_info.is_partial32_asi())\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' else if (asi_info.is_block_store_asi())\n')
file.write(' i->len = 64;\n')
file.write(' if (o.get_rd_drf() & 0x38)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_dr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
self
.dec_dr13(file,' ','idx_exe_stblockf_reg_i1_fp')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_dr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_stf_asi())\n')
self
.dec_dr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_rr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_st_asi())\n')
self
.dec_rr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_fr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_stf_asi())\n')
self
.dec_fr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_dr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
file.write(' if (!asi_info.is_valid_st_asi())\n')
self
.dec_dr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_ia')
self
.dec_dr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_fp')
self
.dec_fr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_fp')
file.write(' else if (asi_info.is_translating())\n')
self
.dec_nr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_fn')
self
.dec_000(file,' ','idx_exe_nop')
self
.dec_nr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_fn')
file.write(' if (o.get_rd_irf())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_reg_i0_rd')
self
.dec_rr13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_rd')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_reg_i0_g0')
self
.dec_0r13(file,' ','idx_exe_'+opc
[:-1]+'_reg_i1_g0')
#----------------------------------------------------------------------
#----------------------------------------------------------------------
file.write(' i->asi = o.get_imm_asi();\n')
file.write(' i->flg = SS_Instr::IMM_ASI|SS_Instr::READ|SS_Instr::WRITE;\n')
file.write(' i->flg = SS_Instr::IMM_ASI|SS_Instr::WRITE;\n')
file.write(' i->flg = SS_Instr::IMM_ASI|SS_Instr::FETCH;\n')
file.write(' i->flg = SS_Instr::IMM_ASI|SS_Instr::FLUSH;\n')
file.write(' i->flg = SS_Instr::IMM_ASI|SS_Instr::READ;\n')
file.write(' i->len = '+self
.mem_len()+';\n')
file.write(' SS_AsiInfo asi_info = s->asi_info[i->asi];\n')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_atomic_asi())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_prefetch_asi())\n')
self
.dec_nrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_flush_asi())\n')
self
.dec_nrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (asi_info.is_quad_load_asi())\n')
file.write(' i->len = 16;\n')
file.write(' if (o.get_rd_irf() & 0x8)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (o.get_rd_irf())\n')
self
.dec_rrr(file,' ','idx_exe_ldtd_imm_i0_rd')
self
.dec_0rr(file,' ','idx_exe_ldtd_imm_i0_g0')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_ld_asi())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_ldx_asi())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_translating())\n')
file.write(' if (o.get_rd_irf())\n')
self
.dec_rrr(file,' ','idx_exe_rdasi_i0_rd')
self
.dec_0rr(file,' ','idx_exe_rdasi_i0_g0')
file.write(' if (asi_info.is_shortf8_asi())\n')
file.write(' i->len = 1;\n')
self
.dec_drr(file,' ','idx_exe_ldshortf8_imm_i0_fp')
file.write(' else if (asi_info.is_shortf16_asi())\n')
file.write(' i->len = 2;\n')
self
.dec_drr(file,' ','idx_exe_ldshortf16_imm_i0_fp')
file.write(' else if (asi_info.is_block_init_asi())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' else if (asi_info.is_block_load_asi())\n')
file.write(' i->len = 64;\n')
file.write(' if (o.get_rd_drf() & 0x38)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_drr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
self
.dec_drr(file,' ','idx_exe_ldblockf_imm_i0_fp')
file.write(' else if (asi_info.is_block_store_asi())\n') # block commit are write only
file.write(' i->len = 64;\n')
file.write(' if (o.get_rd_drf() & 0x38)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_ld_asi())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_ld_asi())\n')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_stx_asi())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_translating())\n')
file.write(' if (o.get_rd_irf())\n')
self
.dec_rrr(file,' ','idx_exe_wrasi_i0_rd')
self
.dec_rrr(file,' ','idx_exe_wrasi_i0_g0')
file.write(' if (asi_info.is_shortf8_asi())\n')
file.write(' i->len = 1;\n')
self
.dec_drr(file,' ','idx_exe_stshortf8_imm_i0_fp')
file.write(' else if (asi_info.is_shortf16_asi())\n')
file.write(' i->len = 2;\n')
self
.dec_drr(file,' ','idx_exe_stshortf16_imm_i0_fp')
file.write(' else if (asi_info.is_partial8_asi())\n')
self
.dec_drr(file,' ','idx_exe_stpartial8_imm_i0_fp')
file.write(' else if (asi_info.is_partial16_asi())\n')
self
.dec_drr(file,' ','idx_exe_stpartial16_imm_i0_fp')
file.write(' else if (asi_info.is_partial32_asi())\n')
self
.dec_drr(file,' ','idx_exe_stpartial32_imm_i0_fp')
file.write(' else if (asi_info.is_block_store_asi())\n')
file.write(' i->len = 64;\n')
file.write(' if (o.get_rd_drf() & 0x38)\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::ILLEGAL_INSTRUCTION);\n')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_drr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
self
.dec_drr(file,' ','idx_exe_stblockf_imm_i0_fp')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_drr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_stf_asi())\n')
self
.dec_drr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_st_asi())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_frr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_stf_asi())\n')
self
.dec_frr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (s->sim_state.priv() < asi_info.get_protection())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
file.write(' if (!asi_info.is_valid_st_asi())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_ia')
self
.dec_drr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_fp')
self
.dec_frr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_fp')
file.write(' else if (asi_info.is_translating())\n')
self
.dec_nrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_fn')
self
.dec_000(file,' ','idx_exe_nop')
self
.dec_nrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_fn')
file.write(' if (o.get_rd_irf())\n')
self
.dec_rrr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_rd')
self
.dec_0rr(file,' ','idx_exe_'+opc
[:-1]+'_imm_i0_g0')
return self
.opc
[0:2] == 'ld'
return self
.opc
[0:2] == 'st'
return self
.opc
[:6] == 'ldstub' or self
.opc
[:4] == 'swap' or self
.opc
[:3] == 'cas'
return self
.opc
[:4] == 'lddf' or self
.opc
[:4] == 'stdf'
return self
.opc
[:3] == 'ldf' or self
.opc
[:3] == 'stf'
def exe_idx_s_name(self
,file,n
):
def gen_exe_tbl(self
,file,mode
):
def idx_mem_s(self
,file):
if self
.opc
[:8] == 'prefetch':
return 'run_dec_%s' % self
.opc
[:-4]
return 'run_dec_%s' % self
.opc
if opc
== 'ldsb' or opc
== 'ldub' or opc
== 'stb' or opc
== 'ldstub':
elif opc
== 'ldsh' or opc
== 'lduh' or opc
== 'sth':
elif opc
== 'ldsw' or opc
== 'lduw' or opc
== 'stw' or opc
== 'swap' or opc
== 'cas' or \
opc
== 'ldf' or opc
== 'stf' or opc
== 'ldfsr' or opc
== 'stfsr':
elif opc
== 'ldx' or opc
== 'ldd' or opc
== 'stx' or opc
== 'std' or opc
== 'casx' or \
opc
== 'lddf' or opc
== 'stdf' or opc
== 'ldxfsr' or opc
== 'stxfsr' or opc
== 'ldxefsr' or \
opc
[:8] == 'prefetch' or opc
== 'flush':
return 'mem_len() missed opc '+self
.opc
#============================================================================
#============================================================================
class SS_ld_mem(SS_InstrCpp
):
def __init__(self
,opc
,out
):
SS_InstrCpp
.__init
__(self
,opc
+'_'+out
)
self
.out
= out
# 'rd' ,'g0', 'fp', 'fn'
for mode
in ['run','trc','ras']:
for src
in ['memory','io']:
args
= '( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i, SS_Vaddr va, SS_Tte* tte )\n'
name
= endian
+'_'+self
.opc
+'_'+self
.out
file.write('\nextern "C" SS_Vaddr mem_'+mode
+'_'+name
+args
)
file.write('\nextern "C" SS_Vaddr io_'+mode
+'_'+name
+args
)
file.write(' SS_Tte* _tte = (SS_Tte*)(long(tte) &~ 3);\n')
file.write(' SS_Paddr pa = _tte->trans(va);\n')
file.write('#if defined(MEMORY_MSYNC)\n')
file.write(' ((SS_MsyncMemory*)(s->'+src
+'))->msync_info(s->strand_id(),va);\n')
file.write('#elif defined(MEMORY_EXTERNAL)\n')
file.write(' ((SS_ExternalMemory*)(s->'+src
+'))->set_strand_id(s->strand_id());\n')
if self
.opc
== 'prefetch':
# ToDo: prefetch is not part of the memory interface standard yet
#file.write(' s->'+src+'->prefetch('+sid+'pa,1);\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::PREFETCH,va,_tte,0,0);\n')
if setup
.product
== 'N2':
file.write(' if (s->sim_state.ras_enabled())\n')
cpu_strand
= setup
.product
.lower()+'_strand'
file.write(' '+setup
.product
+'_Strand* '+cpu_strand
+' = ('+setup
.product
+'_Strand*)s;\n')
cpu_mem_err_detector
= setup
.product
.lower()+'_mem_err_detector'
file.write(' '+setup
.product
+'_MemErrDetector& '+cpu_mem_err_detector
+' = ('+setup
.product
+'_MemErrDetector&)'+cpu_strand
+'->mem_err_detector;\n')
file.write(' if ('+cpu_mem_err_detector
+'.is_prefetchICE(i->opc))\n')
file.write(' '+cpu_mem_err_detector
+'.prefetchICE(pa);\n')
file.write(' uint64_t val;\n')
if mode
== 'run' and src
== 'memory':
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::ld8s('+sid
+'pa);\n')
elif self
.opc
== 'ldub' or self
.opc
== 'ldshortf8':
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::ld8u('+sid
+'pa);\n')
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::ld16s('+sid
+'pa);\n')
elif self
.opc
== 'lduh' or self
.opc
== 'ldshortf16':
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::ld16u('+sid
+'pa);\n')
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::ld32s('+sid
+'pa);\n')
elif self
.opc
== 'lduw' or self
.opc
== 'ldf' or self
.opc
== 'ldfsr':
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::ld32u('+sid
+'pa);\n')
elif self
.opc
== 'ldx' or self
.opc
== 'ldd' or self
.opc
== 'lddf' or self
.opc
== 'ldxfsr' or self
.opc
== 'ldxefsr':
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::ld64('+sid
+'pa);\n')
file.write(' ((SS_Memory*)(s->'+src
+'))->SS_Memory::ld128atomic('+sid
+'pa,s->mem_data);\n')
elif self
.opc
== 'ldblockf':
file.write(' ((SS_Memory*)(s->'+src
+'))->SS_Memory::ld512('+sid
+'pa,s->mem_data);\n')
file.write(' val = ???;\n')
file.write(' val = s->'+src
+'->ld8s('+sid
+'pa);\n')
elif self
.opc
== 'ldub' or self
.opc
== 'ldshortf8':
file.write(' val = s->'+src
+'->ld8u('+sid
+'pa);\n')
file.write(' val = s->'+src
+'->ld16s('+sid
+'pa);\n')
elif self
.opc
== 'lduh' or self
.opc
== 'ldshortf16':
file.write(' val = s->'+src
+'->ld16u('+sid
+'pa);\n')
file.write(' val = s->'+src
+'->ld32s('+sid
+'pa);\n')
elif self
.opc
== 'lduw' or self
.opc
== 'ldf' or self
.opc
== 'ldfsr':
file.write(' val = s->'+src
+'->ld32u('+sid
+'pa);\n')
elif self
.opc
== 'ldx' or self
.opc
== 'ldd' or self
.opc
== 'lddf' or self
.opc
== 'ldxfsr' or self
.opc
== 'ldxefsr':
file.write(' val = s->'+src
+'->ld64('+sid
+'pa);\n')
file.write(' s->'+src
+'->ld128atomic('+sid
+'pa,s->mem_data);\n')
elif self
.opc
== 'ldblockf':
file.write(' s->'+src
+'->ld512('+sid
+'pa,s->mem_data);\n')
file.write(' val = ???;\n')
if mode
== 'ras' and src
== 'memory':
file.write(' if (s->sim_state.ras_enabled())\n')
file.write(' SS_MemErrDetector& med = s->mem_err_detector;\n')
file.write(' SS_Trap::Type tt = med.detect_load_err(SS_MemErrDetector::L1_CACHE_AND_STB, pc, npc, s, i, pa);\n')
file.write(' if (tt != SS_Trap::NO_TRAP)\n')
file.write(' return (s->trap)(pc,npc,s,i,tt);\n')
if self
.opc
== 'ldsb' or self
.opc
== 'ldub' or self
.opc
== 'ldshortf8':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_DATA,va,_tte,1,&val);\n')
elif self
.opc
== 'ldsh' or self
.opc
== 'lduh' or self
.opc
== 'ldshortf16':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_DATA,va,_tte,2,&val);\n')
elif self
.opc
== 'ldsw' or self
.opc
== 'lduw' or self
.opc
== 'ldf' or self
.opc
== 'ldfsr':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_DATA,va,_tte,4,&val);\n')
elif self
.opc
== 'ldx' or self
.opc
== 'ldd' or self
.opc
== 'lddf' or self
.opc
== 'ldxfsr' or self
.opc
== 'ldxefsr':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_DATA,va,_tte,8,&val);\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_DATA,va,_tte,16,s->mem_data);\n')
elif self
.opc
== 'ldblockf':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_DATA,va,_tte,64,s->mem_data);\n')
file.write(' s->get_irf(i->rd + 8) = s->mem_data[1];\n')
file.write(' s->get_irf(i->rd + 8) = uint32_t(val);\n')
file.write(' s->mmu_scratch = val;\n')
file.write(' s->get_irf(i->rd) = s->mem_data[0];\n')
file.write(' s->get_irf(i->rd + 8) = s->mem_data[1];\n')
file.write(' s->get_irf(i->rd ) = val >> 32;\n')
file.write(' s->get_irf(i->rd + 8) = uint32_t(val);\n')
elif self
.opc
== 'lddf' or self
.opc
[:8] == 'ldshortf':
file.write(' s->get_drf(i->rd) = val;\n')
file.write(' s->set_fprs(i->rd);\n')
file.write(' s->get_frf(i->rd) = val;\n')
file.write(' s->set_fprs(i->rd);\n')
elif self
.opc
== 'ldblockf':
file.write(' s->get_drf(i->rd ) = s->mem_data[0];\n')
file.write(' s->get_drf(i->rd + 8) = s->mem_data[1];\n')
file.write(' s->get_drf(i->rd + 16) = s->mem_data[2];\n')
file.write(' s->get_drf(i->rd + 24) = s->mem_data[3];\n')
file.write(' s->get_drf(i->rd + 32) = s->mem_data[4];\n')
file.write(' s->get_drf(i->rd + 40) = s->mem_data[5];\n')
file.write(' s->get_drf(i->rd + 48) = s->mem_data[6];\n')
file.write(' s->get_drf(i->rd + 56) = s->mem_data[7];\n')
file.write(' s->set_fprs(i->rd);\n')
elif self
.opc
== 'ldfsr':
# fsr.ftt is written only by ldxefsr
file.write(' val = (val & ~(0x7llu << 14)) | (s->fsr.ftt() << 14); // preserve ftt\n')
file.write(' s->fsr.set(((s->fsr() >> 32) << 32) + ((val << 32) >> 32));\n')
file.write(' s->set_fsr();\n')
elif self
.opc
== 'ldxfsr':
# fsr.ftt is written only by ldxefsr
file.write(' val = (val & ~(0x7llu << 14)) | (s->fsr.ftt() << 14); // preserve ftt\n')
file.write(' s->fsr.set(val);\n')
file.write(' s->set_fsr();\n')
elif self
.opc
== 'ldxefsr':
file.write(' s->fsr.set(val);\n')
if setup
.product
in ['xx']:
file.write(' s->fsr.ns(0);\n')
file.write(' s->set_fsr();\n')
file.write(' s->get_irf(i->rd) = val;\n')
file.write(' s->get_irf(i->rd + 8) = endianess_convert_64(s->mem_data[1]);\n')
file.write(' s->get_irf(i->rd + 8) = endianess_convert_32u(val);\n')
file.write(' s->mmu_scratch = val;\n')
elif self
.opc
== 'ldub' or self
.opc
== 'ldsb':
file.write(' s->get_irf(i->rd) = val;\n')
file.write(' s->get_irf(i->rd) = endianess_convert_16u(val);\n')
file.write(' s->get_irf(i->rd) = endianess_convert_16s(val);\n')
file.write(' s->get_irf(i->rd) = endianess_convert_32u(val);\n')
file.write(' s->get_irf(i->rd) = endianess_convert_32s(val);\n')
elif self
.opc
== 'ldshortf8':
file.write(' s->get_drf(i->rd) = val;\n')
file.write(' s->set_fprs(i->rd);\n')
elif self
.opc
== 'ldshortf16':
file.write(' s->get_drf(i->rd) = endianess_convert_16u(val);\n')
file.write(' s->set_fprs(i->rd);\n')
file.write(' s->get_frf(i->rd) = endianess_convert_32s(val);\n')
file.write(' s->set_fprs(i->rd);\n')
file.write(' s->get_drf(i->rd) = endianess_convert_64(val);\n')
file.write(' s->set_fprs(i->rd);\n')
file.write(' s->get_irf(i->rd) = endianess_convert_64(val);\n')
file.write(' s->get_irf(i->rd ) = endianess_convert_32u(val >> 32);\n')
file.write(' s->get_irf(i->rd + 8) = endianess_convert_32u(val);\n')
file.write(' s->get_irf(i->rd ) = endianess_convert_64(s->mem_data[0]);\n')
file.write(' s->get_irf(i->rd + 8) = endianess_convert_64(s->mem_data[1]);\n')
elif self
.opc
== 'ldblockf':
file.write(' s->get_drf(i->rd ) = endianess_convert_64(s->mem_data[0]);\n')
file.write(' s->get_drf(i->rd + 8) = endianess_convert_64(s->mem_data[1]);\n')
file.write(' s->get_drf(i->rd + 16) = endianess_convert_64(s->mem_data[2]);\n')
file.write(' s->get_drf(i->rd + 24) = endianess_convert_64(s->mem_data[3]);\n')
file.write(' s->get_drf(i->rd + 32) = endianess_convert_64(s->mem_data[4]);\n')
file.write(' s->get_drf(i->rd + 40) = endianess_convert_64(s->mem_data[5]);\n')
file.write(' s->get_drf(i->rd + 48) = endianess_convert_64(s->mem_data[6]);\n')
file.write(' s->get_drf(i->rd + 56) = endianess_convert_64(s->mem_data[7]);\n')
file.write(' s->set_fprs(i->rd);\n')
elif self
.opc
== 'ldfsr':
file.write(' val = endianess_convert_32u(val);\n')
# fsr.ftt is written only by ldxefsr
file.write(' val = (val & ~(0x7llu << 14)) | (s->fsr.ftt() << 14); // preserve ftt\n')
file.write(' s->fsr.set(((s->fsr() >> 32) << 32) + ((val << 32) >> 32));\n')
file.write(' s->set_fsr();\n')
elif self
.opc
== 'ldxfsr':
file.write(' val = endianess_convert_64(val);\n')
# fsr.ftt is written only by ldxefsr
file.write(' val = (val & ~(0x7llu << 14)) | (s->fsr.ftt() << 14); // preserve ftt\n')
file.write(' s->fsr.set(val);\n')
file.write(' s->set_fsr();\n')
elif self
.opc
== 'ldxefsr':
file.write(' val = endianess_convert_64(val);\n')
file.write(' s->fsr.set(val);\n')
if setup
.product
in ['xx']:
file.write(' s->fsr.ns(0);\n')
file.write(' s->set_fsr();\n')
file.write(' s->npc = npc+4; return npc;\n')
def run_dec_c(self
,file):
#============================================================================
#============================================================================
class SS_st_mem(SS_InstrAsm
):
def __init__(self
,opc
,out
):
SS_InstrAsm
.__init
__(self
,opc
+'_'+out
)
for mode
in ['run','trc','ras']:
for src
in ['memory','io']:
args
= '( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i, SS_Vaddr va, SS_Tte* tte )\n'
name
= endian
+'_'+self
.opc
+'_'+self
.out
file.write('\nextern "C" SS_Vaddr mem_'+mode
+'_'+name
+args
)
file.write('\nextern "C" SS_Vaddr io_'+mode
+'_'+name
+args
)
file.write(' uint64_t val;\n')
if self
.opc
[:9] == 'stpartial':
file.write(' uint64_t msk;\n')
file.write(' SS_Tte* _tte = (SS_Tte*)(long(tte) &~ 3);\n')
file.write(' SS_Paddr pa = _tte->trans(va);\n')
file.write('#if defined(MEMORY_MSYNC)\n')
file.write(' ((SS_MsyncMemory*)(s->'+src
+'))->msync_info(s->strand_id(),va);\n')
file.write('#elif defined(MEMORY_EXTERNAL)\n')
file.write(' ((SS_ExternalMemory*)(s->'+src
+'))->set_strand_id(s->strand_id());\n')
file.write(' val = uint32_t(s->get_irf(i->rd + 8));\n')
file.write(' val = s->get_irf(i->rd + 8) << 32;\n')
file.write(' val = 0;\n')
file.write(' val = (s->get_irf(i->rd) << 32) | uint32_t(s->get_irf(i->rd + 8));\n')
file.write(' val = (s->get_irf(i->rd + 8) << 32) | uint32_t(s->get_irf(i->rd));\n')
file.write(' val = s->get_frf(i->rd);\n')
elif self
.opc
== 'stdf' or self
.opc
[:8] == 'stshortf':
file.write(' val = s->get_drf(i->rd);\n')
elif self
.opc
[:9] == 'stpartial':
file.write(' val = s->get_drf(i->rd);\n')
file.write(' msk = s->mem_mask;\n')
elif self
.opc
== 'stblockf':
file.write(' s->mem_data[0] = s->get_drf(i->rd );\n')
file.write(' s->mem_data[1] = s->get_drf(i->rd + 8);\n')
file.write(' s->mem_data[2] = s->get_drf(i->rd + 16);\n')
file.write(' s->mem_data[3] = s->get_drf(i->rd + 24);\n')
file.write(' s->mem_data[4] = s->get_drf(i->rd + 32);\n')
file.write(' s->mem_data[5] = s->get_drf(i->rd + 40);\n')
file.write(' s->mem_data[6] = s->get_drf(i->rd + 48);\n')
file.write(' s->mem_data[7] = s->get_drf(i->rd + 56);\n')
elif self
.opc
[-3:] == 'fsr':
file.write(' s->get_fsr();\n')
file.write(' val = s->fsr();\n')
file.write(' s->fsr.ftt(0);\n')
file.write(' s->set_fsr();\n')
file.write(' val = s->get_irf(i->rd);\n')
if self
.opc
== 'sth' or self
.opc
== 'stshortf16':
file.write(' val = endianess_convert_16u(val);\n')
elif self
.opc
== 'stw' or self
.opc
== 'stf' or self
.opc
== 'stfsr':
file.write(' val = endianess_convert_32u(val);\n')
elif self
.opc
== 'stx' or self
.opc
== 'std' or self
.opc
== 'stdf' or self
.opc
== 'stxfsr':
file.write(' val = endianess_convert_64(val);\n')
elif self
.opc
[:9] == 'stpartial':
file.write(' val = endianess_convert_64(val);\n')
file.write(' msk = endianess_partial(s->mem_mask);\n')
elif self
.opc
== 'stblockf':
file.write(' s->mem_data[0] = endianess_convert_64(s->mem_data[0]);\n')
file.write(' s->mem_data[1] = endianess_convert_64(s->mem_data[1]);\n')
file.write(' s->mem_data[2] = endianess_convert_64(s->mem_data[2]);\n')
file.write(' s->mem_data[3] = endianess_convert_64(s->mem_data[3]);\n')
file.write(' s->mem_data[4] = endianess_convert_64(s->mem_data[4]);\n')
file.write(' s->mem_data[5] = endianess_convert_64(s->mem_data[5]);\n')
file.write(' s->mem_data[6] = endianess_convert_64(s->mem_data[6]);\n')
file.write(' s->mem_data[7] = endianess_convert_64(s->mem_data[7]);\n')
if self
.opc
== 'stb' or self
.opc
== 'stshortf8':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_DATA,va,_tte,1,&val);\n')
elif self
.opc
== 'sth' or self
.opc
== 'stshortf16':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_DATA,va,_tte,2,&val);\n')
elif self
.opc
== 'stw' or self
.opc
== 'stf' or self
.opc
== 'stfsr':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_DATA,va,_tte,4,&val);\n')
elif self
.opc
== 'stx' or self
.opc
== 'std' or self
.opc
== 'stdf' or self
.opc
== 'stxfsr':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_DATA,va,_tte,8,&val);\n')
elif self
.opc
[:9] == 'stpartial':
file.write(' s->mem_data[0] = val;\n');
file.write(' s->mem_data[1] = msk;\n');
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_DATA,va,_tte,8,s->mem_data);\n')
file.write(' val = s->mem_data[0];\n');
file.write(' msk = s->mem_data[1];\n');
elif self
.opc
== 'stblockf':
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_DATA,va,_tte,64,s->mem_data);\n')
if mode
== 'run' and src
== 'memory':
if self
.opc
== 'stb' or self
.opc
== 'stshortf8':
file.write(' ((SS_Memory*)(s->'+src
+'))->SS_Memory::st8('+sid
+'pa,val);\n')
elif self
.opc
== 'sth' or self
.opc
== 'stshortf16':
file.write(' ((SS_Memory*)(s->'+src
+'))->SS_Memory::st16('+sid
+'pa,val);\n')
elif self
.opc
== 'stw' or self
.opc
== 'stf' or self
.opc
== 'stfsr':
file.write(' ((SS_Memory*)(s->'+src
+'))->SS_Memory::st32('+sid
+'pa,val);\n')
elif self
.opc
== 'stx' or self
.opc
== 'std' or self
.opc
== 'stdf' or self
.opc
== 'stxfsr':
file.write(' ((SS_Memory*)(s->'+src
+'))->SS_Memory::st64('+sid
+'pa,val);\n')
elif self
.opc
[:9] == 'stpartial':
file.write(' ((SS_Memory*)(s->'+src
+'))->SS_Memory::st64partial('+sid
+'pa,val,msk);\n')
elif self
.opc
== 'stblockf':
file.write(' ((SS_Memory*)(s->'+src
+'))->SS_Memory::st512('+sid
+'pa,s->mem_data);\n')
if self
.opc
== 'stb' or self
.opc
== 'stshortf8':
file.write(' s->'+src
+'->st8('+sid
+'pa,val);\n')
elif self
.opc
== 'sth' or self
.opc
== 'stshortf16':
file.write(' s->'+src
+'->st16('+sid
+'pa,val);\n')
elif self
.opc
== 'stw' or self
.opc
== 'stf' or self
.opc
== 'stfsr':
file.write(' s->'+src
+'->st32('+sid
+'pa,val);\n')
elif self
.opc
== 'stx' or self
.opc
== 'std' or self
.opc
== 'stdf' or self
.opc
== 'stxfsr':
file.write(' s->'+src
+'->st64('+sid
+'pa,val);\n')
elif self
.opc
[:9] == 'stpartial':
file.write(' s->'+src
+'->st64partial('+sid
+'pa,val,msk);\n')
elif self
.opc
== 'stblockf':
file.write(' s->'+src
+'->st512('+sid
+'pa,s->mem_data);\n')
if mode
== 'ras' and src
== 'memory':
file.write(' if (s->sim_state.ras_enabled())\n')
file.write(' SS_MemErrDetector& med = s->mem_err_detector;\n')
file.write(' SS_Trap::Type tt = med.inject_store_err(SS_MemErrDetector::L1_CACHE_AND_STB, pc, npc, s, i, pa, val);\n')
file.write(' /*Precise traps not generated by any current architectures*/\n')
file.write(' assert (tt == SS_Trap::NO_TRAP);\n')
file.write(' s->npc = npc+4; return npc;\n')
def run_dec_c(self
,file):
#============================================================================
#============================================================================
class SS_swap_mem(SS_InstrAsm
):
def __init__(self
,opc
,out
):
SS_InstrAsm
.__init
__(self
,opc
+'_'+out
)
for mode
in ['run','trc','ras']:
for src
in ['memory','io']:
args
= '( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i, SS_Vaddr va, SS_Tte* tte )\n'
name
= endian
+'_'+self
.opc
+'_'+self
.out
file.write('\nextern "C" SS_Vaddr mem_'+mode
+'_'+name
+args
)
file.write('\nextern "C" SS_Vaddr io_'+mode
+'_'+name
+args
)
file.write(' uint64_t val;\n')
file.write(' SS_Tte* _tte = (SS_Tte*)(long(tte) &~ 3);\n')
file.write(' SS_Paddr pa = _tte->trans(va);\n')
file.write('#if defined(MEMORY_MSYNC)\n')
file.write(' ((SS_MsyncMemory*)(s->'+src
+'))->msync_info(s->strand_id(),va);\n')
file.write('#elif defined(MEMORY_EXTERNAL)\n')
file.write(' ((SS_ExternalMemory*)(s->'+src
+'))->set_strand_id(s->strand_id());\n')
file.write(' val = s->get_irf(i->rd);\n')
file.write(' val = 0;\n')
file.write(' val = endianess_convert_32u(val);\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_SWAP,va,_tte,4,&val);\n')
if mode
== 'run' and src
== 'memory':
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::swap('+sid
+'pa,val);\n')
file.write(' val = s->'+src
+'->swap('+sid
+'pa,val);\n')
if mode
== 'ras' and src
== 'memory':
file.write(' if (s->sim_state.ras_enabled())\n')
file.write(' SS_MemErrDetector& med = s->mem_err_detector;\n')
file.write(' SS_Trap::Type tt = med.inject_store_err(SS_MemErrDetector::L1_CACHE_AND_STB, pc, npc, s, i, pa, val);\n')
file.write(' /*Precise traps not generated by any current architectures*/\n')
file.write(' assert (tt == SS_Trap::NO_TRAP);\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_SWAP,va,_tte,4,&val);\n')
if mode
== 'ras' and src
== 'memory':
file.write(' if (s->sim_state.ras_enabled())\n')
file.write(' SS_MemErrDetector& med = s->mem_err_detector;\n')
file.write(' SS_Trap::Type tt = med.detect_load_err(SS_MemErrDetector::L1_CACHE_AND_STB, pc, npc, s, i, pa);\n')
file.write(' if (tt != SS_Trap::NO_TRAP)\n')
file.write(' return (s->trap)(pc,npc,s,i,tt);\n')
file.write(' val = endianess_convert_32u(val);\n')
file.write(' s->get_irf(i->rd) = val;\n')
file.write(' s->mmu_scratch = val;\n')
file.write(' s->npc = npc+4; return npc;\n')
def run_dec_c(self
,file):
#============================================================================
#============================================================================
class SS_cas_mem(SS_InstrAsm
):
def __init__(self
,opc
,out
):
SS_InstrAsm
.__init
__(self
,opc
+'_'+out
)
for mode
in ['run','trc','ras']:
for src
in ['memory','io']:
args
= '( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i, SS_Vaddr va, SS_Tte* tte )\n'
name
= endian
+'_'+self
.opc
+'_'+self
.out
file.write('\nextern "C" SS_Vaddr mem_'+mode
+'_'+name
+args
)
file.write('\nextern "C" SS_Vaddr io_'+mode
+'_'+name
+args
)
file.write(' uint64_t val;\n')
file.write(' uint64_t rs2;\n')
file.write(' SS_Tte* _tte = (SS_Tte*)(long(tte) &~ 3);\n')
file.write(' SS_Paddr pa = _tte->trans(va);\n')
file.write('#if defined(MEMORY_MSYNC)\n')
file.write(' ((SS_MsyncMemory*)(s->'+src
+'))->msync_info(s->strand_id(),va);\n')
file.write('#elif defined(MEMORY_EXTERNAL)\n')
file.write(' ((SS_ExternalMemory*)(s->'+src
+'))->set_strand_id(s->strand_id());\n')
file.write(' val = s->get_irf(i->rd);\n')
file.write(' val = 0;\n')
file.write(' rs2 = s->get_irf(i->rs2);\n')
file.write(' val = endianess_convert_64(val);\n')
file.write(' rs2 = endianess_convert_64(rs2);\n')
file.write(' val = endianess_convert_32u(val);\n')
file.write(' rs2 = endianess_convert_32u(rs2);\n')
file.write(' s->mem_data[0] = val;\n')
file.write(' s->mem_data[1] = rs2;\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_CAS,va,_tte,8,s->mem_data);\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_CAS,va,_tte,4,s->mem_data);\n')
file.write(' val = s->mem_data[0];\n')
file.write(' rs2 = s->mem_data[1];\n')
if mode
== 'run' and src
== 'memory':
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::'+self
.opc
+'('+sid
+'pa,val,rs2);\n')
file.write(' val = s->'+src
+'->'+self
.opc
+'('+sid
+'pa,val,rs2);\n')
if mode
== 'ras' and src
== 'memory':
file.write(' if (s->sim_state.ras_enabled())\n')
file.write(' SS_MemErrDetector& med = s->mem_err_detector;\n')
file.write(' SS_Trap::Type tt = med.inject_store_err(SS_MemErrDetector::L1_CACHE_AND_STB, pc, npc, s, i, pa, val);\n')
file.write(' /*Precise traps not generated by any current architectures*/\n')
file.write(' assert (tt == SS_Trap::NO_TRAP);\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_CAS,va,_tte,8,&val);\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_CAS,va,_tte,4,&val);\n')
if mode
== 'ras' and src
== 'memory':
file.write(' if (s->sim_state.ras_enabled())\n')
file.write(' SS_MemErrDetector& med = s->mem_err_detector;\n')
file.write(' SS_Trap::Type tt = med.detect_load_err(SS_MemErrDetector::L1_CACHE_AND_STB, pc, npc, s, i, pa);\n')
file.write(' if (tt != SS_Trap::NO_TRAP)\n')
file.write(' return (s->trap)(pc,npc,s,i,tt);\n')
file.write(' val = endianess_convert_64(val);\n')
file.write(' val = endianess_convert_32u(val);\n')
file.write(' s->get_irf(i->rd) = val;\n')
file.write(' s->mmu_scratch = val;\n')
file.write(' s->npc = npc+4; return npc;\n')
def run_dec_c(self
,file):
#============================================================================
#============================================================================
class SS_ldstub_mem(SS_InstrAsm
):
def __init__(self
,opc
,out
):
SS_InstrAsm
.__init
__(self
,opc
+'_'+out
)
for mode
in ['run','trc','ras']:
for src
in ['memory','io']:
args
= '( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i, SS_Vaddr va, SS_Tte* tte )\n'
name
= endian
+'_'+self
.opc
+'_'+self
.out
file.write('\nextern "C" SS_Vaddr mem_'+mode
+'_'+name
+args
)
file.write('\nextern "C" SS_Vaddr io_'+mode
+'_'+name
+args
)
file.write(' uint64_t val;\n')
file.write(' SS_Tte* _tte = (SS_Tte*)(long(tte) &~ 3);\n')
file.write(' SS_Paddr pa = _tte->trans(va);\n')
file.write('#if defined(MEMORY_MSYNC)\n')
file.write(' ((SS_MsyncMemory*)(s->'+src
+'))->msync_info(s->strand_id(),va);\n')
file.write('#elif defined(MEMORY_EXTERNAL)\n')
file.write(' ((SS_ExternalMemory*)(s->'+src
+'))->set_strand_id(s->strand_id());\n')
file.write(' val = 0xff;\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::ST_LDST,va,_tte,1,&val);\n')
if mode
== 'run' and src
== 'memory':
file.write(' val = ((SS_Memory*)(s->'+src
+'))->SS_Memory::ldstub('+sid
+'pa);\n')
file.write(' val = s->'+src
+'->ldstub('+sid
+'pa);\n')
if mode
== 'ras' and src
== 'memory':
file.write(' if (s->sim_state.ras_enabled())\n')
file.write(' SS_MemErrDetector& med = s->mem_err_detector;\n')
file.write(' SS_Trap::Type tt = med.inject_store_err(SS_MemErrDetector::L1_CACHE_AND_STB, pc, npc, s, i, pa, val);\n')
file.write(' /*Precise traps not generated by any current architectures*/\n')
file.write(' assert (tt == SS_Trap::NO_TRAP);\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::LD_LDST,va,_tte,1,&val);\n')
if mode
== 'ras' and src
== 'memory':
file.write(' if (s->sim_state.ras_enabled())\n')
file.write(' SS_MemErrDetector& med = s->mem_err_detector;\n')
file.write(' SS_Trap::Type tt = med.detect_load_err(SS_MemErrDetector::L1_CACHE_AND_STB, pc, npc, s, i, pa);\n')
file.write(' if (tt != SS_Trap::NO_TRAP)\n')
file.write(' return (s->trap)(pc,npc,s,i,tt);\n')
file.write(' s->get_irf(i->rd) = val;\n')
file.write(' s->mmu_scratch = val;\n')
file.write(' s->npc = npc+4; return npc;\n')
def run_dec_c(self
,file):
#============================================================================
#============================================================================
class SS_flush_mem(SS_InstrAsm
):
def __init__(self
,opc
,out
):
SS_InstrAsm
.__init
__(self
,opc
+'_'+out
)
for mode
in ['run','trc','ras']:
args
= '( SS_Vaddr pc, SS_Vaddr npc, SS_Strand* s, SS_Instr* i, SS_Vaddr va, SS_Tte* tte )\n'
name
= self
.opc
+'_'+self
.out
file.write('\nextern "C" SS_Vaddr mem_'+mode
+'_'+name
+args
)
# In cosim mode the flush is just ignored
file.write(' if (s->sim_state.cosim())\n')
file.write(' s->npc = npc + 4;\n')
file.write(' return npc;\n')
if setup
.product
== 'N2':
# On N2 say the TTE is not valid so we use an identity TTE (va == pa that is)
file.write(' SS_Tte* _tte = s->phys_tte_mem;\n')
file.write(' SS_Paddr pa = va;\n')
file.write(' if (s->trc_hook)\n s->trc_hook->mem_access(SS_Tracer::FLUSH,va,_tte,0,0);\n')
# In execution driven mode we do not do flush operations, we
# just nop the flush. We don't do decode caching in this mode.
file.write(' if (s->sim_state.exec_driven())\n')
file.write(' s->npc = npc + 4;\n')
file.write(' return pc;\n')
# The flush is broadcasted to all the strands. A strand will see the flush
# request and the next instruction will be refetched.
if setup
.product
== 'N2':
# Products like USIII and N2 have coherent instruction caches,
# which means flush is just draining the storebuffer. For us it means
# nuke the decode caches, infinite size (~0).
file.write(' s->model->flush(s,pa,~0);\n')
file.write(' s->npc = npc + 4;\n')
file.write(' return npc;\n')
def run_dec_c(self
,file):
def gen_mem_tbl(self
,file,mode
):
return SS_Instr
. gen_mem_tbl(self
,file,mode
)
file.write(' mem_%s_%s,\n' % (mode
,self
.name
))
file.write(' mem_%s_%s,\n' % (mode
,self
.name
))
file.write(' mem_%s_%s,\n' % (mode
,self
.name
))
file.write(' mem_%s_%s,\n' % (mode
,self
.name
))
#============================================================================
#============================================================================
class SS_rdasi(SS_InstrAsm
):
def __init__(self
,imm
,out
):
SS_InstrAsm
.__init
__(self
,'rdasi_'+imm
+'_'+out
)
def run_exe_c(self
,file):
self
.c_code_beg(file,'run_exe_')
file.write(' SS_Vaddr va = s->get_irf(i->rs1) + s->get_irf(i->rs2);\n')
file.write(' if (i->asi != s->asi())\n')
file.write(' return (s->inst_dec)(pc,npc,s,i);\n')
file.write(' SS_Vaddr va = s->get_irf(i->rs1) + i->rs2;\n')
file.write(' va &= s->mask_pstate_am;\n')
file.write(' if (va & 7)\n')
file.write(' return (s->data_trap)(pc,npc,s,i,va,SS_Trap::MEM_ADDRESS_NOT_ALIGNED);\n')
file.write(' if (s->sim_state.priv() < s->asi_info[i->asi].get_protection())\n')
file.write(' return (s->data_trap)(pc,npc,s,i,va,SS_Trap::PRIVILEGED_ACTION);\n')
file.write(' SS_AsiSpace::Error ok = s->asi_map.ld64(s,i->asi,va,&s->mmu_scratch);\n')
file.write(' SS_AsiSpace::Error ok = s->asi_map.ld64(s,i->asi,va,&s->get_irf(i->rd));\n')
file.write(' switch (ok)\n')
file.write(' case SS_AsiSpace::OK:\n')
file.write(' s->npc = npc+4; return npc;\n')
file.write(' case SS_AsiSpace::TRAP_PA:\n')
file.write(' return (s->data_trap)(pc,npc,s,i,va,SS_Trap::PRIVILEGED_ACTION);\n')
file.write(' case SS_AsiSpace::TRAP_IA:\n')
file.write(' return (s->data_trap)(pc,npc,s,i,va,SS_Trap::DAE_INVALID_ASI);\n')
file.write(' case SS_AsiSpace::TRAP_IPE:\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::INTERNAL_PROCESSOR_ERROR);\n')
file.write(' case SS_AsiSpace::RETRY:\n')
file.write(' return pc;\n')
file.write(' default:\n')
file.write(' return (s->invalid_asi)(pc,npc,s,i,va);\n')
def run_dec_c(self
,file):
def gen_exe_tbl(self
,file,mode
):
self
.gen_exe_rrI(file,mode
,self
.imm
,self
.out
)
#============================================================================
#============================================================================
class SS_wrasi(SS_InstrAsm
):
def __init__(self
,imm
,out
):
SS_InstrAsm
.__init
__(self
,'wrasi_'+imm
+'_'+out
)
def run_exe_c(self
,file):
self
.c_code_beg(file,'run_exe_')
if setup
.product
== 'N2':
file.write(' N2_Strand* _s = (N2_Strand*)s;\n')
file.write(' SS_Vaddr va = s->get_irf(i->rs1) + s->get_irf(i->rs2);\n')
file.write(' if (i->asi != s->asi())\n')
file.write(' return (s->inst_dec)(pc,npc,s,i);\n')
file.write(' SS_Vaddr va = s->get_irf(i->rs1) + i->rs2;\n')
file.write(' va &= s->mask_pstate_am;\n')
file.write(' if (va & 7)\n')
file.write(' return (s->data_trap)(pc,npc,s,i,va,SS_Trap::MEM_ADDRESS_NOT_ALIGNED);\n')
file.write(' if (s->sim_state.priv() < s->asi_info[i->asi].get_protection())\n')
file.write(' return (s->data_trap)(pc,npc,s,i,va,SS_Trap::PRIVILEGED_ACTION);\n')
file.write(' uint64_t rd;\n')
file.write(' SS_AsiSpace::Error ok = s->asi_map.st64(s,i->asi,va,s->get_irf(i->rd));\n')
file.write(' SS_AsiSpace::Error ok = s->asi_map.st64(s,i->asi,va,0);\n')
file.write(' switch (ok)\n')
file.write(' case SS_AsiSpace::OK:\n')
if setup
.product
== 'N2':
file.write(' //fill store buffer call for non-translating asi store\n')
file.write(' if (s->sim_state.ras_enabled())\n')
file.write(' _s->fill_store_buffer_asi(va,i->asi,s->get_irf(i->rd));\n')
file.write(' s->npc = npc+4; return npc;\n')
file.write(' case SS_AsiSpace::TRAP_PA:\n')
file.write(' return (s->data_trap)(pc,npc,s,i,va,SS_Trap::PRIVILEGED_ACTION);\n')
file.write(' case SS_AsiSpace::TRAP_IA:\n')
file.write(' return (s->data_trap)(pc,npc,s,i,va,SS_Trap::DAE_INVALID_ASI);\n')
file.write(' case SS_AsiSpace::TRAP_IPE:\n')
file.write(' return (s->trap)(pc,npc,s,i,SS_Trap::INTERNAL_PROCESSOR_ERROR);\n')
file.write(' case SS_AsiSpace::RETRY:\n')
file.write(' return pc;\n')
file.write(' default:\n')
file.write(' return (s->invalid_asi)(pc,npc,s,i,va);\n')
def run_dec_c(self
,file):
def gen_exe_tbl(self
,file,mode
):
self
.gen_exe_RrI(file,mode
,self
.imm
,self
.out
)
#============================================================================
#============================================================================
ss_flush
= SS_InstrGroup('10_111011_flush',25,0x1f)
ss_ldxfsr
= SS_InstrGroup('11_100001_ldxfsr',25,0x1f)
ss_stxfsr
= SS_InstrGroup('11_100101_stxfsr',25,0x1f)
ss_prefetch
= SS_InstrGroup('11_101101_prefetch',25,0x1f)
ss_prefetcha
= SS_InstrGroup('11_111101_prefetcha',25,0x1f)
ss_flush
.append(SS_lsu_dec('flush'))
if setup
.product
== 'N2':
ss_flush
.append(SS_ill())
ss_flush
.append(SS_ill())
ss_ldxfsr
.append(SS_lsu_dec('ldfsr'))
ss_ldxfsr
.append(SS_lsu_dec('ldxfsr'))
if setup
.product
== 'N2':
ss_ldxfsr
.append(SS_ill())
ss_stxfsr
.append(SS_lsu_dec('stfsr'))
ss_stxfsr
.append(SS_lsu_dec('stxfsr'))
ss_stxfsr
.append(SS_ill())
ss_prefetch
.append(SS_lsu_dec('prefetch_dec'))
ss_prefetch
.append(SS_lsu_dec('prefetch_tmp'))
ss_prefetch
.append(SS_ill())
ss_prefetch
.append(SS_lsu_dec('prefetch_tmp'))
ss_prefetcha
.append(SS_lsu_dec('prefetcha_dec'))
ss_prefetcha
.append(SS_lsu_dec('prefetcha_tmp'))
ss_prefetcha
.append(SS_ill())
ss_prefetcha
.append(SS_lsu_dec('prefetcha_tmp'))