// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: SS_Interrupt.cc
// 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 ============================================
#include "SS_Interrupt.h"
SS_Interrupt::SS_Interrupt()/*{{{*/
auto_retract_mask(~uint64_t(0)),
manual_retract(BIT_CPU_MONDO_TRAP
);
manual_retract(BIT_DEV_MONDO_TRAP
);
manual_retract(BIT_RESUMABLE_ERROR
);
void SS_Interrupt::update_softint( SS_Strand
* strand
)/*{{{*/
uint64_t v
= strand
->softint
.level();
// Bit reverse the softint.level() bits to put the highest
// priority bit at the lowest bit iso the highest bit.
v
= ((v
>> 8) & 0x00ffull
) | ((v
<< 8) & 0xff00ull
);
v
= ((v
>> 4) & 0x0f0full
) | ((v
<< 4) & 0xf0f0ull
);
v
= ((v
>> 2) & 0x3333ull
) | ((v
<< 2) & 0xccccull
);
v
= ((v
>> 1) & 0x5555ull
) | ((v
<< 1) & 0xaaaaull
);
// Clear out old softint flags and or in new.
pending
&= (~0 << (BIT_INTERRUPT_LEVEL_1
+ 1)) | ((1 << BIT_INTERRUPT_LEVEL_15
) - 1);
pending
|= v
<< BIT_INTERRUPT_LEVEL_15
;
// tick and stick match share softint level 14.
pending
|= (strand
->softint
.sm() | strand
->softint
.tm()) << BIT_INTERRUPT_LEVEL_14
;
void SS_Interrupt::_check( SS_Strand
* strand
)/*{{{*/
// HPRV_NM_EVER are traps that are never ever maskable.
static const uint64_t HPRV_NM_EVER
= (1 << BIT_STORE_ERROR
);
// HPRV_IE_MASK is the set of traps that can be taken when in
// hyperpriv mode and when pstate.ie is set (ie).
static const uint64_t HPRV_IE_MASK
= HPRV_NM_EVER
| (1 << BIT_HSTICK_MATCH
)
| (1 << BIT_SIU_INBOUND_EXCEPTION
)
| (1 << BIT_PERFORMANCE_EVENT
)
| (1 << BIT_INTERRUPT_VECTOR
)
| (1 << BIT_MODULAR_ARITH_INT
)
| (1 << BIT_CTRL_WORD_QUEUE_INT
)
| (1 << BIT_HYPERPRIV_QUEUE_0
)
| (1 << BIT_HYPERPRIV_QUEUE_1
)
| (1 << BIT_SW_RECOVERABLE_ERROR
)
| (1 << BIT_HW_CORRECTED_ERROR
);
// PRIV_NM_MASK is the set of traps that will always be taken when
// in user or priviledge mode. These are non maskable traps (nm).
static const uint64_t PRIV_NM_MASK
= HPRV_IE_MASK
| (1 << BIT_TRAP_LEVEL_ZERO
);
uint64_t set
; // Which traps we can take
// Figure out which traps can be taken. In hyperpriv mode we look at the
// traps that are maskable: pstate.ie == 1 at that level. In priv or user
// mode all interrupts are allowed when pstate.ie == 1. If pstate.ie == 0
// then only non maskable interrupts are allowed. Interrupts maskable at
// hyperpriviledge are non maskable at user or priv level.
if (strand
->sim_state
.irq_pending())
return; // Only one interrupt per step please.
else if (strand
->hpstate
.hpriv())
set
= pending
& HPRV_IE_MASK
;
set
= pending
& HPRV_NM_EVER
;
else if (strand
->pstate
.ie())
// Take PIL into account when looking at the softint generated
// interrupt levels. PIL >= 15 blocks all softints.
uint_t mask
= ((1 << (15 - strand
->pil() + BIT_INTERRUPT_LEVEL_15
)) - 1)
| (~0 << (BIT_INTERRUPT_LEVEL_1
+ 1));
set
= pending
& PRIV_NM_MASK
;
// OK, if all traps got masked out then we're done
// or when the unit is disabled in a hard way ...
// Get the highest priority trap that can be taken,
// which is the least significant set bit in set.
// For edge triggered it should not have been delivered yet.
uint64_t bit
= get_lsb(set
);
// For some disrupting traps we handle both raise() and retract()
// For the ones where we don't have the retract() code we need to
// clear the pending bit. The ones() for which we do have the retract()
// code and that are edge triggered we mark as delivered.
pending
&= ~(bit
& auto_retract_mask
);
delivered
|= bit
& edge_triggered_mask
;
uint_t idx
= bit2idx(bit
);
assert(idx
< BIT_ASSERT_INDEX
);
SS_Trap::Type trap_type
= irq_trap_type
[idx
];
// In cosim more we have an irq store which holds interrupts until
// the DUT is telling us to take the irq.
(strand
->irq_store
)(strand
->irq_sync
,trap_type
,true);
// Mark interrupt pending so that we don't launch two interrupt per step
strand
->sim_state
.irq_pending(1);
strand
->msg
.set_handle_trap(trap_type
);
SS_Trap::Type
SS_Interrupt::irq_trap_type
[] = /*{{{*/
SS_Trap::TRAP_LEVEL_ZERO
,
SS_Trap::SIU_INBOUND_EXCEPTION
,
SS_Trap::PERFORMANCE_EVENT
,
SS_Trap::INTERRUPT_VECTOR
,
SS_Trap::MODULAR_ARITH_INT
,
SS_Trap::CTRL_WORD_QUEUE_INT
,
SS_Trap::HYPERPRIV_QUEUE_0
,
SS_Trap::HYPERPRIV_QUEUE_1
,
SS_Trap::INTERRUPT_LEVEL_15
,
SS_Trap::INTERRUPT_LEVEL_14
,
SS_Trap::INTERRUPT_LEVEL_13
,
SS_Trap::INTERRUPT_LEVEL_12
,
SS_Trap::INTERRUPT_LEVEL_11
,
SS_Trap::INTERRUPT_LEVEL_10
,
SS_Trap::INTERRUPT_LEVEL_9
,
SS_Trap::INTERRUPT_LEVEL_8
,
SS_Trap::INTERRUPT_LEVEL_7
,
SS_Trap::INTERRUPT_LEVEL_6
,
SS_Trap::INTERRUPT_LEVEL_5
,
SS_Trap::INTERRUPT_LEVEL_4
,
SS_Trap::INTERRUPT_LEVEL_3
,
SS_Trap::INTERRUPT_LEVEL_2
,
SS_Trap::INTERRUPT_LEVEL_1
,
SS_Trap::SW_RECOVERABLE_ERROR
,
SS_Trap::DATA_ACCESS_SIU_ERROR
,
SS_Trap::HW_CORRECTED_ERROR
,
SS_Trap::RESUMABLE_ERROR
,
SS_Trap::NONRESUMABLE_ERROR
void SS_Interrupt::snapshot( SS_SnapShot
& ss
, const char* prefix
)/*{{{*/
// Do save/load of the pending flags in a flexible format.
// The characters assigned to the interrupts can not change.
// The enumeration however can change. This makes the snapshot
// extensible without version control.
if (is_pending(BIT_TRAP_LEVEL_ZERO
)) *ptr
++ = 'A';
if (is_pending(BIT_NO_RETIRE
)) *ptr
++ = 'B';
if (is_pending(BIT_SIU_INBOUND_EXCEPTION
)) *ptr
++ = 'C';
if (is_pending(BIT_PERFORMANCE_EVENT
)) *ptr
++ = 'D';
if (is_pending(BIT_HSTICK_MATCH
)) *ptr
++ = 'E';
if (is_pending(BIT_INTERRUPT_VECTOR
)) *ptr
++ = 'F';
if (is_pending(BIT_MODULAR_ARITH_INT
)) *ptr
++ = 'G';
if (is_pending(BIT_CTRL_WORD_QUEUE_INT
)) *ptr
++ = 'H';
if (is_pending(BIT_HYPERPRIV_QUEUE_0
)) *ptr
++ = 'I';
if (is_pending(BIT_CPU_MONDO_TRAP
)) *ptr
++ = 'J';
if (is_pending(BIT_HYPERPRIV_QUEUE_1
)) *ptr
++ = 'K';
if (is_pending(BIT_DEV_MONDO_TRAP
)) *ptr
++ = 'L';
if (is_pending(BIT_INTERRUPT_LEVEL_15
)) *ptr
++ = 'M';
if (is_pending(BIT_INTERRUPT_LEVEL_14
)) *ptr
++ = 'N';
if (is_pending(BIT_INTERRUPT_LEVEL_13
)) *ptr
++ = 'O';
if (is_pending(BIT_INTERRUPT_LEVEL_12
)) *ptr
++ = 'P';
if (is_pending(BIT_INTERRUPT_LEVEL_11
)) *ptr
++ = 'Q';
if (is_pending(BIT_INTERRUPT_LEVEL_10
)) *ptr
++ = 'R';
if (is_pending(BIT_INTERRUPT_LEVEL_9
)) *ptr
++ = 'S';
if (is_pending(BIT_INTERRUPT_LEVEL_8
)) *ptr
++ = 'T';
if (is_pending(BIT_INTERRUPT_LEVEL_7
)) *ptr
++ = 'U';
if (is_pending(BIT_INTERRUPT_LEVEL_6
)) *ptr
++ = 'V';
if (is_pending(BIT_INTERRUPT_LEVEL_5
)) *ptr
++ = 'W';
if (is_pending(BIT_INTERRUPT_LEVEL_4
)) *ptr
++ = 'X';
if (is_pending(BIT_INTERRUPT_LEVEL_3
)) *ptr
++ = 'Y';
if (is_pending(BIT_INTERRUPT_LEVEL_2
)) *ptr
++ = 'Z';
if (is_pending(BIT_INTERRUPT_LEVEL_1
)) *ptr
++ = 'a';
if (is_pending(BIT_SW_RECOVERABLE_ERROR
)) *ptr
++ = 'b';
if (is_pending(BIT_DATA_ACCESS_SIU_ERROR
)) *ptr
++ = 'c';
if (is_pending(BIT_HW_CORRECTED_ERROR
)) *ptr
++ = 'd';
if (is_pending(BIT_RESUMABLE_ERROR
)) *ptr
++ = 'e';
if (is_pending(BIT_NONRESUMABLE_ERROR
)) *ptr
++ = 'f';
if (is_pending(BIT_STORE_ERROR
)) *ptr
++ = 'g';
if (ptr
== flg
) *ptr
++ = '-';
sprintf(ss
.tag
,"%s.irq.pending",prefix
); ss
.val(flg
);
case 'A': mark_pending(BIT_TRAP_LEVEL_ZERO
); break;
case 'B': mark_pending(BIT_NO_RETIRE
); break;
case 'C': mark_pending(BIT_SIU_INBOUND_EXCEPTION
); break;
case 'D': mark_pending(BIT_PERFORMANCE_EVENT
); break;
case 'E': mark_pending(BIT_HSTICK_MATCH
); break;
case 'F': mark_pending(BIT_INTERRUPT_VECTOR
); break;
case 'G': mark_pending(BIT_MODULAR_ARITH_INT
); break;
case 'H': mark_pending(BIT_CTRL_WORD_QUEUE_INT
); break;
case 'I': mark_pending(BIT_HYPERPRIV_QUEUE_0
); break;
case 'J': mark_pending(BIT_CPU_MONDO_TRAP
); break;
case 'K': mark_pending(BIT_HYPERPRIV_QUEUE_1
); break;
case 'L': mark_pending(BIT_DEV_MONDO_TRAP
); break;
case 'M': mark_pending(BIT_INTERRUPT_LEVEL_15
); break;
case 'N': mark_pending(BIT_INTERRUPT_LEVEL_14
); break;
case 'O': mark_pending(BIT_INTERRUPT_LEVEL_13
); break;
case 'P': mark_pending(BIT_INTERRUPT_LEVEL_12
); break;
case 'Q': mark_pending(BIT_INTERRUPT_LEVEL_11
); break;
case 'R': mark_pending(BIT_INTERRUPT_LEVEL_10
); break;
case 'S': mark_pending(BIT_INTERRUPT_LEVEL_9
); break;
case 'T': mark_pending(BIT_INTERRUPT_LEVEL_8
); break;
case 'U': mark_pending(BIT_INTERRUPT_LEVEL_7
); break;
case 'V': mark_pending(BIT_INTERRUPT_LEVEL_6
); break;
case 'W': mark_pending(BIT_INTERRUPT_LEVEL_5
); break;
case 'X': mark_pending(BIT_INTERRUPT_LEVEL_4
); break;
case 'Y': mark_pending(BIT_INTERRUPT_LEVEL_3
); break;
case 'Z': mark_pending(BIT_INTERRUPT_LEVEL_2
); break;
case 'a': mark_pending(BIT_INTERRUPT_LEVEL_1
); break;
case 'b': mark_pending(BIT_SW_RECOVERABLE_ERROR
); break;
case 'c': mark_pending(BIT_DATA_ACCESS_SIU_ERROR
); break;
case 'd': mark_pending(BIT_HW_CORRECTED_ERROR
); break;
case 'e': mark_pending(BIT_RESUMABLE_ERROR
); break;
case 'f': mark_pending(BIT_NONRESUMABLE_ERROR
); break;
case 'g': mark_pending(BIT_STORE_ERROR
); break;
fprintf(stderr
,"Warning: Unknown character in "
"irq_pending snapshot %s\n",flg
);