Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / pli / src / SS_IrqSync.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: SS_IrqSync.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 <stdio.h>
#include "SS_IrqSync.h"
SS_IrqSync::SS_IrqSync( SS_Strand* s )/*{{{*/
:
strand(s),
cur_time(0),
head(0)
{
// Plug this IrqSync into the Strand
strand->irq_sync = this;
strand->irq_store = &SS_IrqSync::store;
}
/*}}}*/
void SS_IrqSync::store( void* _irq_sync, SS_Trap::Type irq_type, bool do_time_out ) /*{{{*/
{
SS_IrqSync* irq_sync = (SS_IrqSync*)_irq_sync;
// Insert the new trap in the chain based on priority: highest priority is on the head,
// If there are traps with same priority but different type we stick the last one at
// the end: first come first serve.
if (irq_type == SS_Trap::TRAP_LEVEL_ZERO)
do_time_out = false;
uint_t priority = SS_Trap::table[irq_type].priority;
IrqInfo* here = irq_sync->head;
if (here == 0 || priority < here->priority)
{
irq_sync->head = new IrqInfo(irq_type,priority,do_time_out ? (irq_sync->cur_time + SS_IrqSync::TIME_OUT) : 0,here);
}
else
{
IrqInfo* next = here->next;
while (next && (priority >= next->priority))
{
// Allow the same interruppt to be stored more then once ...
// It makes life so much easier if we do this.
if (here->irq_type == irq_type)
return;
here = next;
next = here->next;
}
here->next = new IrqInfo(irq_type,priority,do_time_out ? (irq_sync->cur_time + SS_IrqSync::TIME_OUT) : 0,next);
}
}
/*}}}*/
void SS_IrqSync::raise( SS_Trap::Type irq_type )/*{{{*/
{
// The DUT sends us a INTP tid tt=0 right at the beginning.
// There is no point in that as when Vonk is created the
// cpu/core/strand state has already been through a reset.
if (irq_type == 0)
return;
for (IrqInfo* here = head; here; here = here->next)
{
if (here->irq_type == irq_type)
{
here->time_out = 0;
return;
}
}
// Don't complain about reset type traps.
if ((irq_type >= SS_Trap::STORE_ERROR) &&
(irq_type != SS_Trap::RESET_GEN_WMR))
fprintf(stdout,"IRQ_SYNC: Trap tt=0x%x is raised unexpectedly\n",irq_type);
store(this,irq_type,false);
}
/*}}}*/
bool SS_IrqSync::check_list()/*{{{*/
{
IrqInfo* prev = head;
IrqInfo* here = prev;
while (here)
{
if (here->time_out == 0)
{
if (strand->trap_launch_ok(here->irq_type))
{
(strand->trap)(strand->pc(),strand->npc(),strand,0,here->irq_type);
if (prev == here)
head = here->next;
else
prev->next = here->next;
delete here;
return true;
}
else
{
prev = here;
here = here->next;
}
}
else if (here->time_out < cur_time)
{
fprintf(stdout,"IRQ_SYNC: Trap tt=0x%x timed out.\n",here->irq_type);
if (prev == here)
{
head = here->next;
delete here;
prev = head;
here = prev;
}
else
{
prev->next = here->next;
delete here;
here = prev->next;
}
}
else
{
prev = here;
here = here->next;
}
}
return false;
}
/*}}}*/
void SS_IrqSync::clear_list()/*{{{*/
{
IrqInfo* here = head;
while (here)
{
IrqInfo* next = here->next;
fprintf(stdout, "IRQ_SYNC: Trap tt=0x%x removed.\n", here->irq_type);
delete here;
here = next;
}
head = 0;
}
/*}}}*/