Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / pli / src / SS_TimedTlb.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: SS_TimedTlb.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 <stdlib.h>
#include "SS_TimedTlb.h"
SS_TimedTlb::SS_TimedTlb( SS_Tlb* _tlb, uint_t _upper_size )/*{{{*/
:
latest_time(0),
latest_tlb(_tlb),
upper_size(_upper_size),
socket(NULL)
{
tlb[latest_time] = latest_tlb;
}
/*}}}*/
SS_Tlb* SS_TimedTlb::modify( uint32_t time )/*{{{*/
{
if (latest_time < time)
{
tlb[time] = latest_tlb = (latest_tlb->clone)(latest_tlb);
latest_time = time;
}
else if (latest_time > time)
{
// If we hit this assertion then we have an inconsistancy. Somehow we ended up with
// a tlb at modification times t1 and t2 and we get asked to create a tlb with a
// modification time tx such that t1 < tx < t2. Hence that would mean modification
// caused by tx should propagate to t2 and higher meaning that we used a wrong tlb
// earlier. So I think this should never occur. Hence bail out.
char buffer[256];
sprintf(buffer, "ERROR: TLB modification time violation: last tlb_write_time=%d >= new tlb_write_time=%d",latest_time,time);
fprintf(stderr,"%s\n", buffer);
if (socket)
{
socket->write_err(buffer);
// if pli-socket condition is bad, we should not process pli commands any further
socket->pli_stop();
}
}
// Keep the number of TLBs that we keep around under an upper limit
// as they can eat quite some memory over time.
while (tlb.size() >= upper_size)
{
std::map<uint32_t,SS_Tlb*,Cmp>::reverse_iterator i = tlb.rbegin();
delete (*i).second;
tlb.erase((*i).first);
}
return latest_tlb;
}
/*}}}*/
SS_Tlb* SS_TimedTlb::lookup( uint32_t time )
{
for (std::map<uint32_t,SS_Tlb*,Cmp>::iterator i = tlb.begin(); i != tlb.end(); i++)
if (time >= (*i).first)
if ((*i).second)
return (*i).second;
else
{
char buffer[256];
sprintf(buffer, "INTERNAL ERROR: SS_TimedTlb lookup time got deleted, max size=%d", upper_size);
fprintf(stderr,"%s\n",buffer);
if (socket)
{
socket->write_err(buffer);
// if pli-socket condition is bad, we should not process pli commands any further
socket->pli_stop();
}
}
// The above should always succeed as we insert the initial tlb with time stamp 0.
char buffer[256];
sprintf(buffer, "INTERNAL ERROR: SS_TimedTlb lookup time (%d) not matched, max size=%d", time, upper_size);
fprintf(stderr,"%s\n",buffer);
if (socket)
{
socket->write_err(buffer);
// if pli-socket condition is bad, we should not process pli commands any further
socket->pli_stop();
}
return 0;
}