// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: SS_TlbSync.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 ============================================
SS_TlbSync::SS_TlbSync( SS_Strand
* _strand
, SS_TimedTlb
* _inst_tlb
, SS_TimedTlb
* _data_tlb
)/*{{{*/
strand
->inst_tlb_read
= inst_tlb_read
;
strand
->inst_tlb_write
= inst_tlb_write
;
strand
->inst_tlb_lookup
= inst_tlb_lookup
;
strand
->data_tlb_read
= data_tlb_read
;
strand
->data_tlb_write
= data_tlb_write
;
strand
->data_tlb_lookup
= data_tlb_lookup
;
void SS_TlbSync::pli_inst_tlb_read( uint32_t time
)/*{{{*/
inst_tlb_read_time
.push_back(time
);
void SS_TlbSync::pli_inst_tlb_write( uint32_t time
, int8_t entry
)/*{{{*/
inst_tlb_write_time
.push_back(time
);
inst_tlb_write_entry
.push_back(entry
);
void SS_TlbSync::pli_inst_hwtw( uint32_t time
, SS_Vaddr va
, int8_t entry
)/*{{{*/
if (inst_tlb_read_time
.size())
uint32_t read_time
= inst_tlb_read_time
.front();
inst_tlb_read_time
.pop_front();
strand
->inst_tlb
= inst_tlb
->lookup(read_time
);
fprintf(stdout
,"TLB: IHWTW-ITLBREAD tid=%d rtime=%d ::",strand
->strand_id(),read_time
);
std::list
<uint32_t>::const_iterator i
;
for (i
= inst_tlb_read_time
.begin(); i
!= inst_tlb_read_time
.end(); i
++)
fprintf(stdout
," %d",(*i
));
inst_tlb_write_time
.push_front(time
);
inst_tlb_write_entry
.push_front(entry
);
SS_Trap::Type tt
= (strand
->inst_hwtw
)(strand
,va
,entry
);
report_error("ERROR: PLI_IHWTW: failed to insert an entry through HWTW: tt=%d",tt
);
fprintf(stdout
,"WARNING: TLB: IHWTW-ITLBREAD tid=%d queue empty\n",strand
->strand_id());
void SS_TlbSync::pli_data_tlb_read( uint32_t time
)/*{{{*/
data_tlb_read_time
.push_back(time
);
void SS_TlbSync::pli_data_tlb_read_pop( uint32_t time
)/*{{{*/
if (data_tlb_read_time
.size())
data_tlb_read_time
.pop_back();
report_error("ERROR: dtlb_pop: miss DTLB pop, tid=%d",strand
->strand_id());
void SS_TlbSync::pli_data_tlb_write( uint32_t time
, int8_t entry
)/*{{{*/
data_tlb_write_time
.push_back(time
);
data_tlb_write_entry
.push_back(entry
);
void SS_TlbSync::pli_data_hwtw( uint32_t time
, SS_Vaddr va
, uint8_t asi
, int8_t entry
)/*{{{*/
// data_tlb_read_time queue can be empty at this point, so check the
// inst_tlb_read_time queue independently.
if (inst_tlb_read_time
.size())
uint32_t read_time
= inst_tlb_read_time
.front();
inst_tlb_read_time
.pop_front();
fprintf(stdout
,"TLB: DHWTW-ITLBREAD tid=%d rtime=%d ::",strand
->strand_id(),read_time
);
std::list
<uint32_t>::const_iterator i
;
for (i
= inst_tlb_read_time
.begin(); i
!= inst_tlb_read_time
.end(); i
++)
fprintf(stdout
," %d",(*i
));
fprintf(stdout
,"WARNING: TLB: DHWTW-ITLBREAD tid=%d queue empty\n",strand
->strand_id());
if (data_tlb_read_time
.size())
uint32_t read_time
= data_tlb_read_time
.front();
data_tlb_read_time
.pop_front();
strand
->data_tlb
= data_tlb
->lookup(read_time
);
fprintf(stdout
,"TLB: DHWTW-DTLBREAD tid=%d rtime=%d ::",strand
->strand_id(),read_time
);
std::list
<uint32_t>::const_iterator i
;
for (i
= data_tlb_read_time
.begin(); i
!= data_tlb_read_time
.end(); i
++)
fprintf(stdout
," %d",(*i
));
data_tlb_write_time
.push_front(time
);
data_tlb_write_entry
.push_front(time
);
SS_Trap::Type tt
= (strand
->data_hwtw
)(strand
,va
,asi
,entry
);
report_error("ERROR: PLI: DHWTW: failed to insert an entry through HWTW: tt=%d",tt
);
fprintf(stdout
,"WARNING: TLB: DHWTW-DTLBREAD tid=%d queue empty\n",strand
->strand_id());
void SS_TlbSync::pli_tlb_lookup( uint32_t time
, uint8_t asi
)/*{{{*/
tlb_lookup_time
.push_back(time
);
tlb_lookup_asi
.push_back(asi
);
void SS_TlbSync::pli_flush()/*{{{*/
// Clear the sync messages that are buffered up. This is done
// for example when the processor gets into and error state,
// say, DATA_ACCESS_ERROR or PROCESSOR_INTERNAL_ERROR
inst_tlb_read_time
.clear();
inst_tlb_write_time
.clear();
inst_tlb_write_entry
.clear();
data_tlb_read_time
.clear();
data_tlb_write_time
.clear();
data_tlb_write_entry
.clear();
void SS_TlbSync::data_tlb_read( void* tlb_sync
)/*{{{*/
SS_TlbSync
* self
= (SS_TlbSync
*)tlb_sync
;
if (self
->data_tlb_read_time
.size())
uint32_t read_time
= self
->data_tlb_read_time
.front();
self
->data_tlb_read_time
.pop_front();
fprintf(stdout
,"TLB: DTLBREAD tid=%d rtime=%d ::",self
->strand
->strand_id(),read_time
);
std::list
<uint32_t>::const_iterator i
;
for (i
= self
->data_tlb_read_time
.begin(); i
!= self
->data_tlb_read_time
.end(); i
++)
fprintf(stdout
," %d",(*i
));
self
->strand
->data_tlb
= self
->data_tlb
->lookup(read_time
);
else if (self
->debug_level
)
fprintf(stdout
,"WARNING: TLB: DTLBREAD tid=%d queue empty\n",self
->strand
->strand_id());
int SS_TlbSync::data_tlb_write( void* tlb_sync
)/*{{{*/
SS_TlbSync
* self
= (SS_TlbSync
*)tlb_sync
;
if (self
->data_tlb_write_time
.size())
uint32_t write_time
= self
->data_tlb_write_time
.front();
int8_t write_entry
= self
->data_tlb_write_entry
.front();
self
->data_tlb_write_time
.pop_front();
self
->data_tlb_write_entry
.pop_front();
self
->strand
->data_tlb
= self
->data_tlb
->modify(write_time
);
void SS_TlbSync::data_tlb_lookup( void* tlb_sync
)/*{{{*/
SS_TlbSync
* self
= (SS_TlbSync
*)tlb_sync
;
if (self
->tlb_lookup_time
.size())
uint32_t read_time
= self
->tlb_lookup_time
.front();
uint8_t read_asi
= self
->tlb_lookup_asi
.front();
self
->tlb_lookup_time
.pop_front();
self
->tlb_lookup_asi
.pop_front();
fprintf(stdout
,"TLB: DTLBLOOKUP tid=%d rtime=%d ::",self
->strand
->strand_id(),read_time
);
std::list
<uint32_t>::const_iterator i
;
for (i
= self
->tlb_lookup_time
.begin(); i
!= self
->tlb_lookup_time
.end(); i
++)
fprintf(stdout
," %d",(*i
));
self
->strand
->data_tlb
= self
->data_tlb
->lookup(read_time
);
else if (self
->debug_level
)
fprintf(stdout
,"WARNING: TLB: DTLBLOOKUP tid=%d queue empty\n",self
->strand
->strand_id());
void SS_TlbSync::inst_tlb_read( void* tlb_sync
)/*{{{*/
SS_TlbSync
* self
= (SS_TlbSync
*)tlb_sync
;
if (self
->inst_tlb_read_time
.size())
uint32_t read_time
= self
->inst_tlb_read_time
.front();
self
->inst_tlb_read_time
.pop_front();
fprintf(stdout
,"TLB: ITLBREAD tid=%d rtime=%d ::",self
->strand
->strand_id(),read_time
);
for (std::list
<uint32_t>::const_iterator i
= self
->inst_tlb_read_time
.begin(); i
!= self
->inst_tlb_read_time
.end(); i
++)
fprintf(stdout
," %d",(*i
));
SS_Tlb
* tlb
= self
->inst_tlb
->lookup(read_time
);
self
->strand
->inst_tlb_set(tlb
);
assert(self
->strand
->inst_tlb
);
else if (self
->debug_level
)
fprintf(stdout
,"WARNING: TLB: ITLBREAD tid=%d queue empty\n",self
->strand
->strand_id());
int SS_TlbSync::inst_tlb_write( void* tlb_sync
)/*{{{*/
SS_TlbSync
* self
= (SS_TlbSync
*)tlb_sync
;
if (self
->inst_tlb_write_time
.size())
uint32_t write_time
= self
->inst_tlb_write_time
.front();
int8_t write_entry
= self
->inst_tlb_write_entry
.front();
self
->inst_tlb_write_time
.pop_front();
self
->inst_tlb_write_entry
.pop_front();
self
->strand
->inst_tlb
= self
->inst_tlb
->modify(write_time
);
void SS_TlbSync::inst_tlb_lookup( void* tlb_sync
)/*{{{*/
SS_TlbSync
* self
= (SS_TlbSync
*)tlb_sync
;
if (self
->tlb_lookup_time
.size())
uint32_t read_time
= self
->tlb_lookup_time
.front();
uint8_t read_asi
= self
->tlb_lookup_asi
.front();
self
->tlb_lookup_time
.pop_front();
self
->tlb_lookup_asi
.pop_front();
fprintf(stdout
,"TLB: ITLBLOOKUP tid=%d rtime=%d ::",self
->strand
->strand_id(),read_time
);
std::list
<uint32_t>::const_iterator i
;
for (i
= self
->tlb_lookup_time
.begin(); i
!= self
->tlb_lookup_time
.end(); i
++)
fprintf(stdout
," %d",(*i
));
self
->strand
->inst_tlb
= self
->inst_tlb
->lookup(read_time
);
else if (self
->debug_level
)
fprintf(stdout
,"WARNING: TLB: ITLBLOOKUP tid=%d queue empty\n",self
->strand
->strand_id());
void SS_TlbSync::report_error(const char *fmt
, ...)/*{{{*/
sprintf(format
, "%s\n", fmt
);
vfprintf(stdout
, format
, args
);
// write the error message to RTL testbench, so that it can show in
// the right place in sims.log and vcs.log
socket
->write_err(format
, args
);
// if pli-socket condition is bad, we should not process pli commands any further