Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: iob_main.c | |
5 | * Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
6 | * 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
7 | * | |
8 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; version 2 of the License. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | * | |
23 | * For the avoidance of doubt, and except that if any non-GPL license | |
24 | * choice is available it will apply instead, Sun elects to use only | |
25 | * the General Public License version 2 (GPLv2) at this time for any | |
26 | * software where a choice of GPL license versions is made | |
27 | * available with the language indicating that GPLv2 or any later version | |
28 | * may be used, or where a choice of which version of the GPL is applied is | |
29 | * otherwise unspecified. | |
30 | * | |
31 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
32 | * CA 95054 USA or visit www.sun.com if you need additional information or | |
33 | * have any questions. | |
34 | * | |
35 | * | |
36 | * ========== Copyright Header End ============================================ | |
37 | */ | |
38 | #include <malloc.h> | |
39 | #include "global.h" | |
40 | ||
41 | #include "b_ary.h" | |
42 | #include "bw_lib.h" | |
43 | #include "list.h" | |
44 | #include "l2warm.h" | |
45 | #include "l1warm.h" | |
46 | #include "utility.h" | |
47 | ||
48 | typedef struct iop_main_struct{ | |
49 | b_tree_node_ptr sysMem;//b_try for memory | |
50 | list_head_ptr l1_list; | |
51 | ||
52 | }*iop_main_structPtr; | |
53 | static struct iop_main_struct iop_TempVariable; | |
54 | //--------------------------------------------------------------- | |
55 | // | |
56 | char* searchPattern(char *buf, char* pattern) | |
57 | { | |
58 | return strpbrk(buf, pattern); | |
59 | } | |
60 | //--------------------------------------------------------------- | |
61 | // | |
62 | void copyStr(char *nextPtr, char* tbuf, char* pattern) | |
63 | { | |
64 | ||
65 | int size; | |
66 | if(strlen(nextPtr) == 0){ | |
67 | tbuf[0] = '\0'; | |
68 | } | |
69 | else{ | |
70 | size = strcspn(nextPtr, pattern); | |
71 | memcpy(tbuf, nextPtr, size); | |
72 | tbuf[size] = '\0'; | |
73 | } | |
74 | } | |
75 | //--------------------------------------------------------------- | |
76 | // | |
77 | int extract_intValue(char *nextPtr, char* pattern) | |
78 | { | |
79 | char tbuf[BUFFER]; | |
80 | copyStr(nextPtr, tbuf, pattern); | |
81 | return atoi(tbuf); | |
82 | } | |
83 | //--------------------------------------------------------------- | |
84 | // | |
85 | unsigned long long extract_longValue(char *nextPtr, char* pattern) | |
86 | { | |
87 | char tbuf[BUFFER]; | |
88 | copyStr(nextPtr, tbuf, pattern); | |
89 | return n2_ck_getEight(tbuf, 0); | |
90 | } | |
91 | /*------------------------------------------------------------------------------- | |
92 | convert ascii to hex array. | |
93 | --------------------------------------------------------------------------------*/ | |
94 | void packingData(char* buf, char* cbuf) | |
95 | { | |
96 | char ch; | |
97 | int idx, cidx; | |
98 | idx = 0; | |
99 | cidx= 0; | |
100 | while(buf[idx] != '\0'){ | |
101 | ch = buf[idx] > '9' ? ((buf[idx] & 0xf) + 9) : buf[idx] & 0xf; | |
102 | ch <<= 4; | |
103 | idx++; | |
104 | if(buf[idx] == '\0')break; | |
105 | ch |= buf[idx] > '9' ? ((buf[idx] & 0xf) + 9) : buf[idx] & 0xf; | |
106 | cbuf[cidx] = ch; | |
107 | idx++; | |
108 | cidx++; | |
109 | } | |
110 | } | |
111 | ||
112 | /*------------------------------------------ | |
113 | load and go | |
114 | ||
115 | -------------------------------------------*/ | |
116 | void l2_warm_forloadAndgo_call() | |
117 | { | |
118 | ||
119 | char *pargs; | |
120 | ||
121 | io_printf("Info(PLI):loadandgo warm start....\n"); | |
122 | l2warm_set(); | |
123 | FILE *fp; | |
124 | char buf [BUFFER]; | |
125 | char tbuf[BUFFER]; | |
126 | KeyType addr; | |
127 | ||
128 | int subbank; | |
129 | char *nextPtr; | |
130 | char hexa[17] = "0123456789abcdef"; | |
131 | char space[3] = " \n"; | |
132 | char data[65]; //hold data | |
133 | int expected; | |
134 | int set, bank, way; | |
135 | ||
136 | //get options will bes used in this file. | |
137 | pargs = mc_scan_plusargs ("loadngo_log="); | |
138 | if(pargs != (char *) 0)fp = fopen(pargs, "r"); | |
139 | else fp = fopen("loadngo_l2array_dumped.log", "r"); | |
140 | ||
141 | if(fp == null){ | |
142 | io_printf("Error: can not open file %s for reading\n", pargs != (char *) 0 ? pargs : | |
143 | "loadngo_l2array_dumped.log"); | |
144 | tf_dofinish(); | |
145 | } | |
146 | io_printf("Info: reading %s file \n", pargs != (char *) 0 ? pargs : "loadngo_l2array_dumped.log"); | |
147 | expected = 0; | |
148 | while(fgets(buf, BUFFER, fp)){ | |
149 | ||
150 | if(expected){//slam here | |
151 | nextPtr = searchPattern(buf, hexa); | |
152 | if(nextPtr == null)continue; | |
153 | copyStr(nextPtr, tbuf, space); | |
154 | packingData(tbuf, data); | |
155 | ||
156 | subbank = (int)((addr >> 4) & 0x3); | |
157 | l2warm_get_Mode(&addr); | |
158 | l2warm_vars.way = way; | |
159 | l2warm_vars.bank = bank; | |
160 | l2warm_vars.l2_index = set; | |
161 | ||
162 | l2warm_slam_tag(); //process tag | |
163 | l2warm_slam_vuad();//process vuad | |
164 | // for(int idx = 0;idx<64;idx++)io_printf("%02x",data[idx] &0xff);io_printf("\n"); | |
165 | l2warm_slam_real_data(data, subbank);//process data | |
166 | expected = 0; | |
167 | continue; | |
168 | } | |
169 | if((nextPtr = strstr(buf, "Set")) == null)continue; | |
170 | nextPtr = searchPattern(nextPtr+3, hexa); | |
171 | set = extract_intValue(nextPtr, space); | |
172 | if((nextPtr = strstr(buf, "Bank")) == null)continue; | |
173 | nextPtr = searchPattern(nextPtr+4, hexa); | |
174 | bank = extract_intValue(nextPtr, space); | |
175 | if((nextPtr = strstr(buf, "Way")) == null)continue; | |
176 | nextPtr = searchPattern(nextPtr+4, hexa); | |
177 | way = extract_intValue(nextPtr, space); | |
178 | if((nextPtr = strstr(buf, "Addr")) == null)continue; | |
179 | nextPtr = searchPattern(nextPtr+4, hexa); | |
180 | addr = extract_longValue(nextPtr, space); | |
181 | expected = 1; | |
182 | } | |
183 | fclose(fp); | |
184 | } | |
185 | ||
186 | /*------------------------------------------ | |
187 | do l2 warming here. | |
188 | -------------------------------------------*/ | |
189 | void l2_warm_call() | |
190 | { | |
191 | int idx ; | |
192 | char *pargs, cbuf[17]; | |
193 | //b_tree_node_ptr sysMem;//b_try for memory | |
194 | char zero_data[64]; | |
195 | int slam_flag; | |
196 | b_tree_atom_ptr data;//b-tree node. | |
197 | list_node_ptr addr_ptr; | |
198 | list_head_ptr addr_list; | |
199 | KeyType mask_addr, b_addr; | |
200 | //get options will bes used in this file. | |
201 | pargs = mc_scan_plusargs ("loandgo="); | |
202 | if(pargs != (char *) 0)l2warm_vars.loadandgo = atoi(pargs); | |
203 | if(l2warm_vars.loadandgo != 0){ | |
204 | l2_warm_forloadAndgo_call(); | |
205 | return; | |
206 | } | |
207 | l2warm_set(); | |
208 | //get options will bes used in this file. | |
209 | l2warm_vars.l2_warm = 0; | |
210 | pargs = mc_scan_plusargs ("l2warm="); | |
211 | if(pargs != (char *) 0)l2warm_vars.l2_warm = atoi(pargs); | |
212 | l2warm_vars.l1_warm = 0; | |
213 | pargs = mc_scan_plusargs ("l1warm="); | |
214 | if(pargs != (char *) 0)l2warm_vars.l1_warm = atoi(pargs); | |
215 | if(l2warm_vars.l2_warm == 0)return; | |
216 | addr_list = (list_head_ptr)malloc(sizeof(struct list_head_node)); | |
217 | addr_list->head_ptr = 0; | |
218 | addr_list->tail_ptr = 0; | |
219 | addr_list->num = 0; | |
220 | ||
221 | //set argment | |
222 | iop_TempVariable.sysMem = b_create();//create | |
223 | n2_ck_read_mem("mem.image", &iop_TempVariable.sysMem, addr_list);//read memory | |
224 | ||
225 | io_printf("Info:l2 warm start....\n"); | |
226 | l2warm_vars.check_range = 0; | |
227 | pargs = mc_scan_plusargs ("l2range="); | |
228 | ||
229 | if(pargs != (char *) 0){ | |
230 | l2warm_vars.check_range = 1; | |
231 | idx = l2warm_copy(pargs, cbuf, 0); | |
232 | l2warm_vars.up_bound = l2warm_getEight(cbuf); | |
233 | l2warm_copy(pargs, cbuf, idx); | |
234 | l2warm_vars.low_bound = l2warm_getEight(cbuf); | |
235 | io_printf("Info:L2warm range %llx:%llx\n", l2warm_vars.up_bound, l2warm_vars.low_bound); | |
236 | } | |
237 | for(idx = 0; idx < MAX_BANK;idx++)l2warm_l2_clear_vuad(idx); | |
238 | if(l2warm_vars.l1_warm ){ | |
239 | iop_TempVariable.l1_list = (list_head_ptr)malloc(sizeof(struct list_head_node)); | |
240 | iop_TempVariable.l1_list->head_ptr = 0; | |
241 | iop_TempVariable.l1_list->tail_ptr = 0; | |
242 | iop_TempVariable.l1_list->num = 0; | |
243 | io_printf("Info:L1warm is on\n"); | |
244 | } | |
245 | if(l2warm_vars.check_range){ | |
246 | for(b_addr = l2warm_vars.low_bound & 0xffffffffc0 ; b_addr < l2warm_vars.up_bound;b_addr += 64){ | |
247 | mask_addr = (b_addr >> 6) & 0x3ffffffff; | |
248 | data = b_Find(&iop_TempVariable.sysMem, &mask_addr); | |
249 | if(data == 0)for(idx = 0; idx < 64;idx++)zero_data[idx] = random() & 0xff; | |
250 | slam_flag = data ? l2warm_slam(b_addr, data->data) : l2warm_slam(b_addr, zero_data); | |
251 | if(l2warm_vars.l1_warm && (slam_flag & 1) ){//slam this address | |
252 | addr_ptr = (list_node_ptr)malloc(sizeof(struct list_node)); | |
253 | addr_ptr->addr = b_addr; | |
254 | addr_ptr->way = (slam_flag >> 1) & 0xf; | |
255 | n2_ck_push(iop_TempVariable.l1_list, &addr_ptr); | |
256 | } | |
257 | } | |
258 | } | |
259 | else{ | |
260 | //warm start | |
261 | while((addr_ptr = n2_ck_pop(addr_list)) != 0 ){//get address | |
262 | mask_addr = (addr_ptr->addr >> 6) & 0x3ffffffff; | |
263 | data = b_Find(&iop_TempVariable.sysMem, &mask_addr);//get data to be slammed. | |
264 | slam_flag = data ? l2warm_slam(addr_ptr->addr, data->data) : l2warm_slam(addr_ptr->addr, zero_data); | |
265 | if(l2warm_vars.l1_warm && (slam_flag & 1)){ | |
266 | addr_ptr->way = (slam_flag >> 1) & 0xf; | |
267 | n2_ck_push(iop_TempVariable.l1_list, &addr_ptr); | |
268 | } | |
269 | else free(addr_ptr); | |
270 | } | |
271 | } | |
272 | if(l2warm_vars.l1_warm == 0)b_destory(&iop_TempVariable.sysMem); | |
273 | } | |
274 | /*------------------------------------------ | |
275 | do l1 warming here. | |
276 | -------------------------------------------*/ | |
277 | void l1_warm_call() | |
278 | { | |
279 | int dev; | |
280 | char* pargs; | |
281 | b_tree_atom_ptr data;//b-tree node. | |
282 | list_node_ptr addr_ptr; | |
283 | KeyType mask_addr; | |
284 | ||
285 | //no l2slam, it means that we dont need l1slam. | |
286 | //because l2 is an inclusive cache. | |
287 | pargs = mc_scan_plusargs ("l2warm="); | |
288 | if(pargs != (char *) 0)dev = atoi(pargs); | |
289 | else return; | |
290 | if(dev == 0)return; | |
291 | pargs = mc_scan_plusargs ("l1warm="); | |
292 | if(pargs != (char *) 0)dev = atoi(pargs); | |
293 | else return; | |
294 | if(dev == 0)return; | |
295 | ||
296 | l1warm_set_cpu();//get the infomation how many core is on. | |
297 | ||
298 | l1warm_set(); | |
299 | l1warm_clean_dir(); | |
300 | io_printf("Info:L1 warm start\n"); | |
301 | //warm start | |
302 | while((addr_ptr = n2_ck_pop(iop_TempVariable.l1_list)) != 0){ | |
303 | //here we can slam l1 randomly. | |
304 | mask_addr = (addr_ptr->addr >> 6) & 0x3ffffffff; | |
305 | data = b_Find(&iop_TempVariable.sysMem, &mask_addr); | |
306 | if(data)l1warm_slam(addr_ptr->addr, data->data, addr_ptr->way); | |
307 | //io_printf("Info address %llx %x\n", addr_ptr->addr, addr_ptr->way); | |
308 | free(addr_ptr); | |
309 | } | |
310 | l1warm_store_parityValidAddr(); | |
311 | b_destory(&iop_TempVariable.sysMem); | |
312 | } | |
313 | ||
314 | /*------------------------------------------ | |
315 | get l2event. | |
316 | !$EV trig_pc_d(1, 64'h0000000001834140) -> l2warm() | |
317 | ||
318 | --------------------------------------------*/ | |
319 | void l2warm_get_event(char *str) | |
320 | { | |
321 | FILE *fp;//file pointer | |
322 | char buf [BUFFER], cbuf[BUFFER];//temp variavle for intermiate data | |
323 | int idx; | |
324 | long long key; | |
325 | ||
326 | l2warm_vars.avl_ptr = 0; | |
327 | if((fp = fopen(str, "r")) == 0){ | |
328 | io_printf("Info(Warnning): can not open the event file %s for reading\n", str); | |
329 | return; | |
330 | } | |
331 | while(fgets(buf, BUFFER, fp)){ | |
332 | idx = n2_ck_rmSpace(buf, 0, BUFFER); | |
333 | l2warm_replace(buf); | |
334 | if(strncmp(buf, "trig_pc_d ", 10))continue; | |
335 | idx = n2_ck_rmSpace(buf, 10, BUFFER); | |
336 | idx = l2warm_copy(buf, cbuf, idx); | |
337 | ||
338 | idx = n2_ck_rmSpace(buf, idx, BUFFER); | |
339 | idx = l2warm_copy(buf, cbuf, idx);//pc value | |
340 | ||
341 | l2warm_rmhexa(cbuf); | |
342 | key = l2warm_getEight(cbuf); | |
343 | idx = n2_ck_rmSpace(buf, idx, BUFFER); | |
344 | idx = l2warm_copy(buf, cbuf, idx); | |
345 | ||
346 | if(strncmp(cbuf, "l2warm", 6))continue;//here only handle interrupt | |
347 | l2warm_insert_avl_node(&l2warm_vars.avl_ptr, &key); | |
348 | ||
349 | } | |
350 | fclose(fp); | |
351 | } | |
352 | /*------------------------------------------ | |
353 | do the pc event check here. | |
354 | -------------------------------------------*/ | |
355 | void n2_check_event_call() | |
356 | { | |
357 | int active, l2warm, loc, low, high, idx; | |
358 | long long pc, tlow, thigh; | |
359 | char *str; | |
360 | if(tf_getp(1) == 2){ | |
361 | l2warm = tf_getp(3); | |
362 | if(l2warm)return;//have event to be executed. | |
363 | active = tf_getp(2); | |
364 | loc = 4; | |
365 | for(idx = 0;idx < (tf_nump() - 4);idx += 2){ | |
366 | if(tf_getp(loc)){ | |
367 | low = tf_getlongp(&high, loc+1); | |
368 | tlow = low; | |
369 | thigh = high; | |
370 | thigh <<= 32; | |
371 | thigh &= 0xffffffff00000000; | |
372 | tlow &= 0x00000000ffffffff; | |
373 | pc = thigh | tlow; | |
374 | if(l2warm_vars.avl_ptr && l2warm_search_node(&l2warm_vars.avl_ptr, &pc)){ | |
375 | io_printf("Info(%d): l2warm event HIT pc = %llx\n", tf_gettime(), pc); | |
376 | tf_putp(3, 1); | |
377 | break; | |
378 | } | |
379 | } | |
380 | loc += 2; | |
381 | } | |
382 | } | |
383 | else if(tf_getp(1) == 1){ | |
384 | l2warm_vars.avl_ptr = 0; | |
385 | str = tf_getcstringp(3); // a get file name | |
386 | l2warm_get_event(str); | |
387 | l2warm_setRdancy(tf_getp(4)); | |
388 | } | |
389 | } |