Commit | Line | Data |
---|---|---|
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 | ||
24 | SS_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 | ||
42 | void SS_TlbSync::pli_inst_tlb_read( uint32_t time )/*{{{*/ | |
43 | { | |
44 | inst_tlb_read_time.push_back(time); | |
45 | } | |
46 | /* }}}*/ | |
47 | void 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 | /*}}}*/ | |
53 | void 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 | ||
87 | void SS_TlbSync::pli_data_tlb_read( uint32_t time )/*{{{*/ | |
88 | { | |
89 | data_tlb_read_time.push_back(time); | |
90 | } | |
91 | /*}}}*/ | |
92 | void 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 | /*}}}*/ | |
104 | void 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 | /*}}}*/ | |
110 | void 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 | ||
165 | void 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 | ||
172 | void 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 | ||
189 | void 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 | /*}}}*/ | |
215 | int 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 | /*}}}*/ | |
231 | void 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 | ||
260 | void 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 | /*}}}*/ | |
287 | int 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 | /*}}}*/ | |
303 | void 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 | ||
332 | void 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 |