Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / cpu / src / SS_Interrupt.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: SS_Interrupt.h
* 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 ============================================
*/
#ifndef __SS_Interrupt_h__
#define __SS_Interrupt_h__
#include "SS_Types.h"
#include "SS_Trap.h"
#include "SS_SnapShot.h"
class SS_Strand;
class SS_Interrupt
{
public:
SS_Interrupt();
// The Bit enum is ordered on priority (highest priority has lowest index)
// The priority is taken from the Sun Sparc architecture (trap section)
// and repeated in the comment after the enum variable
enum Bit
{
BIT_STORE_ERROR, // 2.1
BIT_TRAP_LEVEL_ZERO, // 2.2
BIT_NO_RETIRE, // 15.8
BIT_SIU_INBOUND_EXCEPTION, // 15.9
BIT_PERFORMANCE_EVENT, // 16.0
BIT_HSTICK_MATCH, // 16.1
BIT_INTERRUPT_VECTOR, // 16.3
BIT_MODULAR_ARITH_INT, // 16.4
BIT_CTRL_WORD_QUEUE_INT, // 16.5
BIT_HYPERPRIV_QUEUE_0, // 16.07
BIT_CPU_MONDO_TRAP, // 16.08
BIT_HYPERPRIV_QUEUE_1, // 16.10
BIT_DEV_MONDO_TRAP, // 16.11
BIT_INTERRUPT_LEVEL_15, // 17.0
BIT_INTERRUPT_LEVEL_14, // 18.0
BIT_INTERRUPT_LEVEL_13, // 19.0
BIT_INTERRUPT_LEVEL_12, // 20.0
BIT_INTERRUPT_LEVEL_11, // 21.0
BIT_INTERRUPT_LEVEL_10, // 22.0
BIT_INTERRUPT_LEVEL_9, // 23.0
BIT_INTERRUPT_LEVEL_8, // 24.0
BIT_INTERRUPT_LEVEL_7, // 25.0
BIT_INTERRUPT_LEVEL_6, // 26.0
BIT_INTERRUPT_LEVEL_5, // 27.0
BIT_INTERRUPT_LEVEL_4, // 28.0
BIT_INTERRUPT_LEVEL_3, // 29.0
BIT_INTERRUPT_LEVEL_2, // 30.0
BIT_INTERRUPT_LEVEL_1, // 31.0
BIT_SW_RECOVERABLE_ERROR, // 33.1
BIT_DATA_ACCESS_SIU_ERROR, // 32.0
BIT_HW_CORRECTED_ERROR, // 33.2
BIT_RESUMABLE_ERROR, // 33.3
BIT_NONRESUMABLE_ERROR, // 33.3
BIT_ASSERT_INDEX // To check our logic
};
// enable() and disabled() are for hard enabling interrupts.
// In some simulation situations we have to be carefull. These
// enable disable allow us to block interrupts the hard way.
void enable() { disabled = false; }
void disable() { disabled = true; }
// raise() is used to mark an interrupt pending, and check
// if the strand is in the correct state to deal with the
// interrupt on the next instruction.
void raise( SS_Strand* strand, Bit b )
{
if (!is_pending(b))
{
mark_pending(b);
_check(strand);
}
}
// retract() is used to remove a pending interrupt. Note that
// this means that the irq should be registered as manual_retract();
void retract( Bit b )
{
pending &= ~(1ull << b);
delivered &= ~(1ull << b);
}
// is_pending() can be used to test if a particular interrupt is
// pending. True is returned when it is pending.
bool is_pending( Bit b )
{
return pending & (1ull << b);
}
// any_pending() can be used to see if any interrupt is pending.
bool any_pending()
{
return pending;
}
// update_softint() is called whenever the SPARC softint register
// changes. This is a kind of meta raise()
void update_softint( SS_Strand* strand );
void check( SS_Strand* strand )
{
if (pending)
_check(strand);
}
void snapshot( SS_SnapShot& ss, const char* prefix );
// manual_retract() is used at simulator startup time to notify
// the _check() routine that the simulater will call retract()
// when the interrupt is no longer pending. The default is
// to auto retract as soon as irq is delivered.
void manual_retract( Bit b )
{
auto_retract_mask &= ~(1ull << b);
}
// edge_triggered() is used at simulator startup time to notify
// the _check() routine that the irq should be edge triggered
// iso level triggered. This can only be used in conjunction with
// manual_retract(). The default detection is level triggered.
void edge_triggered( Bit b )
{
assert((auto_retract_mask & (1ull << b)) == 0); // must be manual
edge_triggered_mask |= 1ull << b;
}
protected:
uint64_t pending; // Set bit means irq is pending.
uint64_t auto_retract_mask; // The mask controls clearing the pending bit when the irq is delivered.
uint64_t delivered; // Set bit means the irq has been delivered.
uint64_t edge_triggered_mask; // Set bit means the irq is edge iso level triggered.
bool disabled; // Really checking interrupts?
void _check( SS_Strand* );
static SS_Trap::Type irq_trap_type[];
// mark_pending() is used to mark an interrupt pending. No action will
// be taken on the interrupt. For action after mark_pending() call
// check() or use raise().
void mark_pending( Bit b )
{
pending |= 1ull << b;
}
};
#endif