Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / pli / src / SS_TlbSync.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: SS_TlbSync.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21
22#include "SS_TlbSync.h"
23
24SS_TlbSync::SS_TlbSync( SS_Strand* _strand, SS_TimedTlb* _inst_tlb, SS_TimedTlb* _data_tlb )/*{{{*/
25 :
26 strand(_strand),
27 inst_tlb(_inst_tlb),
28 data_tlb(_data_tlb),
29 debug_level(0),
30 socket(NULL)
31{
32 strand->tlb_sync = this;
33 strand->inst_tlb_read = inst_tlb_read;
34 strand->inst_tlb_write = inst_tlb_write;
35 strand->inst_tlb_lookup = inst_tlb_lookup;
36 strand->data_tlb_read = data_tlb_read;
37 strand->data_tlb_write = data_tlb_write;
38 strand->data_tlb_lookup = data_tlb_lookup;
39}
40/*}}}*/
41
42void SS_TlbSync::pli_inst_tlb_read( uint32_t time )/*{{{*/
43{
44 inst_tlb_read_time.push_back(time);
45}
46/* }}}*/
47void SS_TlbSync::pli_inst_tlb_write( uint32_t time, int8_t entry )/*{{{*/
48{
49 inst_tlb_write_time.push_back(time);
50 inst_tlb_write_entry.push_back(entry);
51}
52/*}}}*/
53void SS_TlbSync::pli_inst_hwtw( uint32_t time, SS_Vaddr va, int8_t entry )/*{{{*/
54{
55 if (inst_tlb_read_time.size())
56 {
57 uint32_t read_time = inst_tlb_read_time.front();
58 inst_tlb_read_time.pop_front();
59 strand->inst_tlb = inst_tlb->lookup(read_time);
60
61 if (debug_level)
62 {
63 fprintf(stdout,"TLB: IHWTW-ITLBREAD tid=%d rtime=%d ::",strand->strand_id(),read_time);
64 std::list<uint32_t>::const_iterator i;
65 for (i = inst_tlb_read_time.begin(); i != inst_tlb_read_time.end(); i++)
66 fprintf(stdout," %d",(*i));
67 fprintf(stdout,"\n");
68 }
69
70 inst_tlb_write_time.push_front(time);
71 inst_tlb_write_entry.push_front(entry);
72
73 SS_Trap::Type tt = (strand->inst_hwtw)(strand,va,entry);
74
75 if (tt)
76 {
77 report_error("ERROR: PLI_IHWTW: failed to insert an entry through HWTW: tt=%d",tt);
78 }
79 }
80 else if (debug_level)
81 {
82 fprintf(stdout,"WARNING: TLB: IHWTW-ITLBREAD tid=%d queue empty\n",strand->strand_id());
83 }
84}
85/*}}}*/
86
87void SS_TlbSync::pli_data_tlb_read( uint32_t time )/*{{{*/
88{
89 data_tlb_read_time.push_back(time);
90}
91/*}}}*/
92void SS_TlbSync::pli_data_tlb_read_pop( uint32_t time )/*{{{*/
93{
94 if (data_tlb_read_time.size())
95 {
96 data_tlb_read_time.pop_back();
97 }
98 else
99 {
100 report_error("ERROR: dtlb_pop: miss DTLB pop, tid=%d",strand->strand_id());
101 }
102}
103/*}}}*/
104void SS_TlbSync::pli_data_tlb_write( uint32_t time, int8_t entry )/*{{{*/
105{
106 data_tlb_write_time.push_back(time);
107 data_tlb_write_entry.push_back(entry);
108}
109/*}}}*/
110void SS_TlbSync::pli_data_hwtw( uint32_t time, SS_Vaddr va, uint8_t asi, int8_t entry )/*{{{*/
111{
112 // data_tlb_read_time queue can be empty at this point, so check the
113 // inst_tlb_read_time queue independently.
114 if (inst_tlb_read_time.size())
115 {
116 uint32_t read_time = inst_tlb_read_time.front();
117 inst_tlb_read_time.pop_front();
118
119 if (debug_level)
120 {
121 fprintf(stdout,"TLB: DHWTW-ITLBREAD tid=%d rtime=%d ::",strand->strand_id(),read_time);
122 std::list<uint32_t>::const_iterator i;
123 for (i = inst_tlb_read_time.begin(); i != inst_tlb_read_time.end(); i++)
124 fprintf(stdout," %d",(*i));
125 fprintf(stdout,"\n");
126 }
127 }
128 else if (debug_level)
129 {
130 fprintf(stdout,"WARNING: TLB: DHWTW-ITLBREAD tid=%d queue empty\n",strand->strand_id());
131 }
132
133 if (data_tlb_read_time.size())
134 {
135 uint32_t read_time = data_tlb_read_time.front();
136 data_tlb_read_time.pop_front();
137 strand->data_tlb = data_tlb->lookup(read_time);
138
139 if (debug_level)
140 {
141 fprintf(stdout,"TLB: DHWTW-DTLBREAD tid=%d rtime=%d ::",strand->strand_id(),read_time);
142 std::list<uint32_t>::const_iterator i;
143 for (i = data_tlb_read_time.begin(); i != data_tlb_read_time.end(); i++)
144 fprintf(stdout," %d",(*i));
145 fprintf(stdout,"\n");
146 }
147
148 data_tlb_write_time.push_front(time);
149 data_tlb_write_entry.push_front(time);
150
151 SS_Trap::Type tt = (strand->data_hwtw)(strand,va,asi,entry);
152
153 if (tt)
154 {
155 report_error("ERROR: PLI: DHWTW: failed to insert an entry through HWTW: tt=%d",tt);
156 }
157 }
158 else if (debug_level)
159 {
160 fprintf(stdout,"WARNING: TLB: DHWTW-DTLBREAD tid=%d queue empty\n",strand->strand_id());
161 }
162}
163/*}}}*/
164
165void SS_TlbSync::pli_tlb_lookup( uint32_t time, uint8_t asi )/*{{{*/
166{
167 tlb_lookup_time.push_back(time);
168 tlb_lookup_asi.push_back(asi);
169}
170/*}}}*/
171
172void SS_TlbSync::pli_flush()/*{{{*/
173{
174 // Clear the sync messages that are buffered up. This is done
175 // for example when the processor gets into and error state,
176 // say, DATA_ACCESS_ERROR or PROCESSOR_INTERNAL_ERROR
177
178 inst_tlb_read_time.clear();
179 inst_tlb_write_time.clear();
180 inst_tlb_write_entry.clear();
181 data_tlb_read_time.clear();
182 data_tlb_write_time.clear();
183 data_tlb_write_entry.clear();
184 tlb_lookup_time.clear();
185 tlb_lookup_asi.clear();
186}
187/*}}}*/
188
189void SS_TlbSync::data_tlb_read( void* tlb_sync )/*{{{*/
190{
191 SS_TlbSync* self = (SS_TlbSync*)tlb_sync;
192
193 if (self->data_tlb_read_time.size())
194 {
195 uint32_t read_time = self->data_tlb_read_time.front();
196 self->data_tlb_read_time.pop_front();
197
198 if (self->debug_level)
199 {
200 fprintf(stdout,"TLB: DTLBREAD tid=%d rtime=%d ::",self->strand->strand_id(),read_time);
201 std::list<uint32_t>::const_iterator i;
202 for (i = self->data_tlb_read_time.begin(); i != self->data_tlb_read_time.end(); i++)
203 fprintf(stdout," %d",(*i));
204 fprintf(stdout,"\n");
205 }
206
207 self->strand->data_tlb = self->data_tlb->lookup(read_time);
208 }
209 else if (self->debug_level)
210 {
211 fprintf(stdout,"WARNING: TLB: DTLBREAD tid=%d queue empty\n",self->strand->strand_id());
212 }
213}
214/*}}}*/
215int SS_TlbSync::data_tlb_write( void* tlb_sync )/*{{{*/
216{
217 SS_TlbSync* self = (SS_TlbSync*)tlb_sync;
218
219 if (self->data_tlb_write_time.size())
220 {
221 uint32_t write_time = self->data_tlb_write_time.front();
222 int8_t write_entry = self->data_tlb_write_entry.front();
223 self->data_tlb_write_time.pop_front();
224 self->data_tlb_write_entry.pop_front();
225 self->strand->data_tlb = self->data_tlb->modify(write_time);
226 return write_entry;
227 }
228 return -1;
229}
230/*}}}*/
231void SS_TlbSync::data_tlb_lookup( void* tlb_sync )/*{{{*/
232{
233 SS_TlbSync* self = (SS_TlbSync*)tlb_sync;
234
235 if (self->tlb_lookup_time.size())
236 {
237 uint32_t read_time = self->tlb_lookup_time.front();
238 uint8_t read_asi = self->tlb_lookup_asi.front();
239 self->tlb_lookup_time.pop_front();
240 self->tlb_lookup_asi.pop_front();
241
242 if (self->debug_level)
243 {
244 fprintf(stdout,"TLB: DTLBLOOKUP tid=%d rtime=%d ::",self->strand->strand_id(),read_time);
245 std::list<uint32_t>::const_iterator i;
246 for (i = self->tlb_lookup_time.begin(); i != self->tlb_lookup_time.end(); i++)
247 fprintf(stdout," %d",(*i));
248 fprintf(stdout,"\n");
249 }
250
251 self->strand->data_tlb = self->data_tlb->lookup(read_time);
252 }
253 else if (self->debug_level)
254 {
255 fprintf(stdout,"WARNING: TLB: DTLBLOOKUP tid=%d queue empty\n",self->strand->strand_id());
256 }
257}
258/*}}}*/
259
260void SS_TlbSync::inst_tlb_read( void* tlb_sync )/*{{{*/
261{
262 SS_TlbSync* self = (SS_TlbSync*)tlb_sync;
263
264 if (self->inst_tlb_read_time.size())
265 {
266 uint32_t read_time = self->inst_tlb_read_time.front();
267 self->inst_tlb_read_time.pop_front();
268
269 if (self->debug_level)
270 {
271 fprintf(stdout,"TLB: ITLBREAD tid=%d rtime=%d ::",self->strand->strand_id(),read_time);
272 for (std::list<uint32_t>::const_iterator i = self->inst_tlb_read_time.begin(); i != self->inst_tlb_read_time.end(); i++)
273 fprintf(stdout," %d",(*i));
274 fprintf(stdout,"\n");
275 }
276
277 SS_Tlb* tlb = self->inst_tlb->lookup(read_time);
278 self->strand->inst_tlb_set(tlb);
279 assert(self->strand->inst_tlb);
280 }
281 else if (self->debug_level)
282 {
283 fprintf(stdout,"WARNING: TLB: ITLBREAD tid=%d queue empty\n",self->strand->strand_id());
284 }
285}
286/*}}}*/
287int SS_TlbSync::inst_tlb_write( void* tlb_sync )/*{{{*/
288{
289 SS_TlbSync* self = (SS_TlbSync*)tlb_sync;
290
291 if (self->inst_tlb_write_time.size())
292 {
293 uint32_t write_time = self->inst_tlb_write_time.front();
294 int8_t write_entry = self->inst_tlb_write_entry.front();
295 self->inst_tlb_write_time.pop_front();
296 self->inst_tlb_write_entry.pop_front();
297 self->strand->inst_tlb = self->inst_tlb->modify(write_time);
298 return write_entry;
299 }
300 return -1;
301}
302/*}}}*/
303void SS_TlbSync::inst_tlb_lookup( void* tlb_sync )/*{{{*/
304{
305 SS_TlbSync* self = (SS_TlbSync*)tlb_sync;
306
307 if (self->tlb_lookup_time.size())
308 {
309 uint32_t read_time = self->tlb_lookup_time.front();
310 uint8_t read_asi = self->tlb_lookup_asi.front();
311 self->tlb_lookup_time.pop_front();
312 self->tlb_lookup_asi.pop_front();
313
314 if (self->debug_level)
315 {
316 fprintf(stdout,"TLB: ITLBLOOKUP tid=%d rtime=%d ::",self->strand->strand_id(),read_time);
317 std::list<uint32_t>::const_iterator i;
318 for (i = self->tlb_lookup_time.begin(); i != self->tlb_lookup_time.end(); i++)
319 fprintf(stdout," %d",(*i));
320 fprintf(stdout,"\n");
321 }
322
323 self->strand->inst_tlb = self->inst_tlb->lookup(read_time);
324 }
325 else if (self->debug_level)
326 {
327 fprintf(stdout,"WARNING: TLB: ITLBLOOKUP tid=%d queue empty\n",self->strand->strand_id());
328 }
329}
330/*}}}*/
331
332void SS_TlbSync::report_error(const char *fmt, ...)/*{{{*/
333{
334 char format[256];
335 va_list args;
336 va_start(args, fmt);
337
338 sprintf(format, "%s\n", fmt);
339 vfprintf(stdout, format, args);
340
341 // write the error message to RTL testbench, so that it can show in
342 // the right place in sims.log and vcs.log
343 if (socket)
344 {
345 socket->write_err(format, args);
346 // if pli-socket condition is bad, we should not process pli commands any further
347 socket->pli_stop();
348 }
349 va_end(args);
350}
351
352