Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / common / vera / niu_intr / niu_int_ldg.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: niu_int_ldg.vr
4// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
5// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
6//
7// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8//
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; version 2 of the License.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21//
22// For the avoidance of doubt, and except that if any non-GPL license
23// choice is available it will apply instead, Sun elects to use only
24// the General Public License version 2 (GPLv2) at this time for any
25// software where a choice of GPL license versions is made
26// available with the language indicating that GPLv2 or any later version
27// may be used, or where a choice of which version of the GPL is applied is
28// otherwise unspecified.
29//
30// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31// CA 95054 USA or visit www.sun.com if you need additional information or
32// have any questions.
33//
34// ========== Copyright Header End ============================================
35#include <vera_defines.vrh>
36#include <ListMacros.vrh>
37#include "pio_memory_map.vri"
38#include "niu_int_dev.vrh"
39#include "pio_driver.vrh"
40#include "niu_int_qmgr.vrh"
41
42extern niu_gen_pio gen_pio_drv;
43extern Mesg be_msg;
44
45class CNiuLdg {
46 bit[6:0] sid;
47 integer test_controlled_isr = 0;
48 integer function_no=0;
49 integer dis_pio_virt=1; // This needs to be set correctly
50 integer device68_already_bound=0;
51 integer multi_device_68bound = 0;
52 integer gid;
53 integer rearm = 0;
54 integer pending_flag = 0;
55 integer no_of_isrs_spawned;
56 integer REARM_TIMEOUT = 1000;
57 local bit ArmStatus;
58 local bit [5:0] timerStatus;
59 local bit [8:0] error_mask;
60 bit[68:0] active_devices;
61 bit[15:0] error_devices_bound;
62 CNiuIntrDev IntrDev[69];
63 CNiuIntrDev IntrErrDev[16]; // 16 extra devices for error
64 bit[63:0] lastreadLDSV0,lastreadLDSV1,lastreadLDSV2;
65 task new(integer i);
66 task ldgbind( CNiuIntrDev dev, (integer active = 1)) ;
67 task setSid(bit[6:0] s) ;
68 task SetIntrMgm(bit arm, bit[5:0] timer ) ;
69 task ReArmIntrMgm( (integer rearm_wait=100) , (integer rearm_timeout=1000) ) ;
70 virtual task ldgIsr((integer blanket_int=0),(CniuGenIntrMsg IntrMsg=null) );
71 task CheckIntrDev((integer blanket_int=0),(CniuGenIntrMsg IntrMsg=null) );
72 function bit[63:0] PioReadLDSV0() ;
73 function bit[63:0] PioReadLDSV1() ;
74 function bit[63:0] PioReadLDSV2() ;
75 local function bit [63:0] getPIOAddress(bit[63:0] orig_address,(integer pass_through=1));
76 function integer LaunchDev68Isr(bit [15:0] error_state,bit[1:0] ldf_flags);
77 task clrArm((integer check= 0)) ;
78 task incIsrCnt() { no_of_isrs_spawned++;
79 printf("CNiuLdg:incIsrCnt cnt - %d \n",no_of_isrs_spawned);
80 }
81 function integer getIsrCnt() { getIsrCnt = no_of_isrs_spawned; }
82 task SetPendingFlag() {pending_flag=1;}
83 task ClrPendingFlag() {pending_flag=0;}
84 function integer isPending();
85
86 function integer getDevIsrCnt(integer id ) ;
87 task setDevIsrCnt(integer id);
88 function integer isISRDone(integer id) ;
89 task resetISRDone(integer id) ;
90 task SetErrMask ( bit [8:0] mask ) ;
91 function bit[31:0] PioReadErrState () ;
92 function bit[31:0] getErrState() ;
93 task mask_all_devices();
94 task unmask_all_devices();
95 task ldgunbind( integer dev_id) ;
96
97
98}
99
100
101task CNiuLdg::SetErrMask ( bit [8:0] mask ) {
102// Applicable for device #68 only
103 bit [63:0] address, wdata;
104 if(active_devices[68]) {
105 address = SYS_ERR_MASK;
106 wdata = {55'h0,mask};
107 gen_pio_drv.pio_wr(address,wdata);
108 error_mask = mask;
109 }
110}
111
112function bit[31:0] CNiuLdg::PioReadErrState () {
113 bit [63:0] address, rdata;
114 address = SYS_ERR_STAT;
115 gen_pio_drv.pio_rd(address,rdata);
116 PioReadErrState = rdata[31:0];
117}
118
119task CNiuLdg::new(integer i) {
120 gid = i;
121 active_devices = 0;
122 lastreadLDSV0 = 0;
123 lastreadLDSV1 = 0;
124 lastreadLDSV2 = 0;
125 error_mask = 9'h1ff;
126 no_of_isrs_spawned = 0;
127}
128task CNiuLdg::ldgunbind( integer dev_id) {
129
130 if(dev_id==68) {
131 // Not supported yet
132 printf("CNiuLdg::ldgunbind ERROR Not Supported for device #68!!! \n");
133 } else {
134 if(active_devices[dev_id]) {
135 IntrDev[dev_id].setGid(0); // remove the old group association
136 IntrDev[dev_id] = null;
137 active_devices[dev_id]= 0;
138 } else {
139 printf("CNiuLdg::ldgunbind ERROR Device %d Not bound!!! \n",dev_id);
140 }
141
142 }
143}
144
145task CNiuLdg::ldgbind( CNiuIntrDev dev, (integer active = 1)) {
146integer ii;
147
148/* Need to do differnetly for device 68
149There can be multiple of these therefore we cannot overwrite the previous one*/
150
151/*
152if(device68_already_bound & (dev.dev_id==68) ) {
153 if(dev.getErrId()==-1) {
154 printf("ERROR Test seems to be binding multiple device 68 without setting proper id. Cannot bind!! FIX IT\n");
155 } else {
156 IntrErrDev[dev.getErrId()] = dev;
157 error_devices_bound[dev.getErrId()] = 1;
158 // remove the old one..
159 // This is done only to mainitain compatibility with some of the old testcases
160 if(IntrDev[68].getErrId()==-1) {
161 printf("ERROR Test seems to be binding multiple device 68 without setting proper id. Cannot bind!! FIX IT\n");
162 } else {
163 IntrErrDev[IntrDev[68].getErrId()] = IntrDev[68];
164 error_devices_bound[IntrDev[68].getErrId()] = 1;
165 }
166 multi_device_68bound = 1;
167 }
168} else {
169 IntrDev[dev.getid()] = dev;
170 if(dev.dev_id==68) device68_already_bound=1;
171
172}
173*/
174if (dev.dev_id==68) {
175 if(dev.getErrId()==-1) {
176 // old testcases
177 if (get_plus_arg (CHECK,"NIU_INTR_COPY"))
178 IntrDev[dev.getid()] = dev.object_copy();
179 else
180 IntrDev[dev.getid()] = dev;
181 } else {
182 IntrErrDev[dev.getErrId()] = dev;
183 error_devices_bound[dev.getErrId()] = 1;
184 multi_device_68bound = 1;
185 printf("CNiuLdg::ldgbind DEBUG: Binding device error id - %d to group - %d \n",dev.getErrId(),gid);
186 }
187} else {
188 IntrDev[dev.getid()] = dev;
189}
190if(active) {
191 active_devices[dev.getid()] = 1;
192 }
193 dev.setGid(gid);
194
195
196 // Check for correctness of function no
197}
198task CNiuLdg::setSid(bit[6:0] s) {
199 sid = s;
200 function_no = sid[6:5];
201 printf(" CNiuLdg::setSid LDG - %d Bound to function - %d \n",gid,function_no);
202}
203task CNiuLdg::ReArmIntrMgm( (integer rearm_wait=100) , (integer rearm_timeout=1000) ) {
204
205 bit[63:0] address, wdata,rdata;
206 integer rearm_timeout_reached;
207 integer poll_cnt;
208 integer not_done;
209 bit[5:0] timer;
210
211 not_done = 0;
212 rearm_timeout_reached = 0;
213 timer = timerStatus; fork {
214 while(not_done==0) {
215 rdata = 0;
216 rdata[31] = 1'b1;
217 while( rdata[31] & (rearm_timeout_reached==0) ) {
218 gen_pio_drv.pio_rd(address,rdata);
219 repeat(rearm_wait) @(posedge CLOCK);
220 poll_cnt++;
221 if(poll_cnt > rearm_timeout) {
222 printf("ERROR CNiuLdg::SetIntrMgm: ReArm Counter Timeout!! Exiting loop cnt - %d\n",poll_cnt);
223 rearm_timeout_reached = 1;
224 not_done = 1;
225 return;
226 }
227 }
228 if(rearm_timeout==0) {
229 address = LDGIMGN + 8192*gid;
230 wdata = {32'h0,1'b1,25'h0,timer};
231 gen_pio_drv.pio_wr(address,wdata);
232 }
233 repeat(50) @(posedge CLOCK);
234 }
235
236 }join none // end fork
237}
238task CNiuLdg::SetIntrMgm(bit arm, bit[5:0] timer ) {
239 bit[63:0] address, wdata,rdata;
240 integer rearm_timeout;
241 integer poll_cnt;
242 integer not_done;
243 ArmStatus = arm;
244 timerStatus = timer;
245 address = LDGIMGN + 8192*gid;
246 wdata = {32'h0,arm,25'h0,timer};
247 gen_pio_drv.pio_wr(address,wdata);
248
249/* TBD */
250/* Function to expect an interrupt based upon the arm bit , timer*/
251
252}
253function bit [63:0] CNiuLdg::getPIOAddress(bit[63:0] orig_address, (integer pass_through=1)) {
254 integer func;
255 if(pass_through){
256 getPIOAddress = orig_address;
257 } else {
258 getPIOAddress = 64'h0;
259 getPIOAddress[4:0] = orig_address[4:0];
260 getPIOAddress[11:5] = gid & 7;
261 getPIOAddress[15:12] = ((gid/8)%2)? 4'h6:4'h2;
262 func = gid/16; // This needs to match with what has been programmed;
263 if(func!==function_no) {
264 printf("CNiuLdg::getPIOAddress TEST ERROR - Incorrect programming!!!\n");
265 getPIOAddress = 64'hx;
266 } else {
267 if(func==0) {
268 getPIOAddress = FUNC0_VIR + getPIOAddress;
269 } else if(func==1){
270 getPIOAddress = FUNC1_VIR + getPIOAddress;
271 } else if(func==2){
272 getPIOAddress = FUNC2_VIR + getPIOAddress;
273 } else if(func==3) {
274 getPIOAddress = FUNC3_VIR + getPIOAddress;
275 } else {
276 getPIOAddress = 64'hx;
277 }
278 }
279
280 }
281
282}
283
284function bit[63:0] CNiuLdg::PioReadLDSV0() {
285 bit[63:0] address, rdata;
286 address = getPIOAddress(LDSV0 + 8192*gid,dis_pio_virt);
287 gen_pio_drv.pio_rd(address,rdata);
288 /* Add functions here to check the correctness of rdata based upon various settings*/
289 /* Only devices bound to this group should be setting their bits */
290 printf(" DEBUG CNiuLdg::PioReadLDSV0 Address - %x data - %x id - %d\n",address,rdata,gid);
291 PioReadLDSV0 = rdata;
292 lastreadLDSV0 = rdata;
293}
294function bit[63:0] CNiuLdg::PioReadLDSV1() {
295 bit[63:0] address, rdata;
296 address = getPIOAddress(LDSV1 + 8192*gid,dis_pio_virt);
297 gen_pio_drv.pio_rd(address,rdata);
298 /* Add functions here to check the correctness of rdata based upon various settings*/
299 printf(" DEBUG CNiuLdg::PioReadLDSV1 Address - %x data - %x id - %d\n",address,rdata,gid);
300 PioReadLDSV1 = rdata;
301 lastreadLDSV1 = rdata;
302}
303function bit[63:0] CNiuLdg::PioReadLDSV2() {
304 bit[63:0] address, rdata;
305 address = getPIOAddress(LDSV2 + 8192*gid,dis_pio_virt);
306 gen_pio_drv.pio_rd(address,rdata);
307 /* Add functions here to check the correctness of rdata based upon various settings*/
308 printf(" DEBUG CNiuLdg::PioReadLDSV2 Address - %x data - %x id - %d\n",address,rdata,gid);
309 PioReadLDSV2 = rdata;
310 lastreadLDSV2 = rdata;
311}
312task CNiuLdg::clrArm((integer check= 0)) {
313 bit [63:0] address,rdata;
314 ArmStatus = 0;
315 // Function to be called only after interrupt has been received
316 if(check) {
317 address = LDGIMGN + 8192*gid;
318 gen_pio_drv.pio_rd(address,rdata);
319 if(rdata[31]!==0) {
320 printf("ERROR - Arm bit expected tobe cleared !!! \n");
321 }
322 }
323
324}
325
326
327/* Function for Spawing off various ISRs */
328
329task CNiuLdg::ldgIsr((integer blanket_int=0),(CniuGenIntrMsg IntrMsg=null) ) {
330
331 CheckIntrDev(blanket_int);
332}
333
334task CNiuLdg::CheckIntrDev((integer blanket_int=0),(CniuGenIntrMsg IntrMsg=null) ) {
335 bit[63:0] ldsv0,ldsv1,ldsv2;
336 bit [68:0] intr_dev_id_ldf0;
337 bit [68:0] intr_dev_id_ldf1;
338 bit [68:0] intr_dev_id;
339 bit [8:0] error_state;
340 shadow integer i;
341 shadow integer status;
342 integer isrs_active;
343
344// get a list of all the interrupting devices
345/* May need some modification here based upon s/w feedback*/
346//
347
348 printf(" CNiuLdg::CheckIntrDev id - %d active_devices - %x \n",gid,active_devices);
349 // read state vector
350 SetPendingFlag();
351
352
353 ldsv0 = PioReadLDSV0();
354 ldsv1 = PioReadLDSV1();
355 ldsv2 = PioReadLDSV2();
356
357 // compare this against the set of active devices
358 // and spawns off the isrs
359
360 intr_dev_id_ldf0[63:0] = ldsv0 & active_devices[63:0];
361 intr_dev_id_ldf1[63:0] = ldsv1 & active_devices[63:0];
362 intr_dev_id_ldf0[68:64] = ldsv2[4:0] & active_devices[68:64];
363 intr_dev_id_ldf1[68:64] = ldsv2[9:5] & active_devices[68:64];
364
365 intr_dev_id = intr_dev_id_ldf0 | intr_dev_id_ldf1;
366
367 printf(" CNiuLdg::CheckIntrDev gid - %d ldsv0 - %x \n",gid,ldsv0);
368 printf(" CNiuLdg::CheckIntrDev gid - %d ldsv1 - %x \n",gid,ldsv1);
369 printf(" CNiuLdg::CheckIntrDev gid - %d ldsv2 - %x \n",gid,ldsv2);
370 printf(" CNiuLdg::CheckIntrDev gid - %d intr_dev_id - %x \n",gid,intr_dev_id);
371
372 if(active_devices[68] & intr_dev_id[68]) {
373 // For interrupts from device 68
374 // read the state and check with the mask
375 error_state = PioReadErrState();
376 if((error_state === 32'h0)) {
377 be_msg.print(e_mesg_error,"CNiuLdg","CheckIntrDev","ERROR Device #68 ERR_STAT Incorrect ! ERR_STAT - %x MASK - %x \n",error_state, error_mask);
378 }
379 }
380 isrs_active = 0;
381 for(i =0;i< 68;i++) { // handle only upto device 67
382 if(active_devices[i]) {
383 if(intr_dev_id[i]) {
384 printf(" Interrupt Received from DeviceId - %d Flags: ldf1-%b ldf0-%b \n",i,intr_dev_id_ldf1[i],intr_dev_id_ldf0[i]);
385
386 isrs_active++;
387 IntrDev[i].incIsrCnt();
388 this.incIsrCnt();
389 fork {
390 status = IntrDev[i].isr({intr_dev_id_ldf1[i],intr_dev_id_ldf0[i]});
391 }join none
392 }
393 }
394 }
395 // handle 68 seperately here
396
397 if(intr_dev_id[68]) {
398 // first check if 68 is bound to this group
399 if(active_devices[68]) {
400 isrs_active = isrs_active + LaunchDev68Isr(error_state,{intr_dev_id_ldf1[i],intr_dev_id_ldf0[i]});
401 } else {
402 be_msg.print(e_mesg_error,"CNiuLdg","CheckIntrDev","ERROR Device #68 Interorted in wrong LDG - %d! \n",gid);
403 } // endif active_devices
404 } // endif intr_dev_id
405
406
407
408 if(blanket_int) {
409
410 } else {
411 if(isrs_active==0){
412 // printf("ERROR - Incorrect Message Received from Hardware !\n");
413 be_msg.print(e_mesg_error,"CNiuLdg","CheckIntrDev","ERROR - Incorrect Message Received from Hardware !\n");
414 }
415 }
416
417 if(rearm & (isrs_active!=0)) {
418 wait_child();
419 SetIntrMgm(ArmStatus , timerStatus);
420 }
421
422 ClrPendingFlag();
423
424}
425function integer CNiuLdg::LaunchDev68Isr(bit [15:0] error_state,bit[1:0] ldf_flags) {
426 shadow integer i;
427 integer status;
428
429 LaunchDev68Isr =0;
430 if(multi_device_68bound) {
431 for(i=0;i<16;i++) {
432 if(error_state[i]) {
433 if(error_devices_bound[i]==0) {
434 printf("CNiuLdg::LaunchDev68Isr:: ERROR ERR_STAT- Set for devices not bound!! ERR_STAT - %x group = %d \n",error_state,gid);
435 LaunchDev68Isr = -1;
436 return;
437 }
438 }
439 }
440 for(i=0;i<16;i++) {
441 if(error_state[i]) {
442 IntrErrDev[i].incIsrCnt();
443 this.incIsrCnt();
444
445 fork {
446 printf("CNiuLdg::LaunchDev68Isr::DEBUG Launching ISR for error id - %d \n",i);
447 status = IntrErrDev[i].isr(ldf_flags);
448 }join none
449 LaunchDev68Isr++;
450 } // end if error_state
451 } // end for
452 } else {
453 IntrDev[68].incIsrCnt();
454 this.incIsrCnt();
455 fork {
456 status = IntrDev[68].isr(ldf_flags);
457 }join none
458 LaunchDev68Isr = 1;
459 }
460
461}
462
463function integer CNiuLdg::getDevIsrCnt(integer id ) {
464 if(active_devices[id])
465 getDevIsrCnt = IntrDev[id].getIsrCnt();
466 else getDevIsrCnt = -1;
467}
468task CNiuLdg::setDevIsrCnt(integer id) {
469 if(active_devices[id])
470 IntrDev[id].setIsrCnt();
471}
472function integer CNiuLdg::isISRDone(integer id) {
473 if(active_devices[id]){
474 isISRDone= IntrDev[id].isr_done;
475 } else {
476 isISRDone = 0;
477 }
478}
479task CNiuLdg::resetISRDone(integer id) {
480 if(active_devices[id]){
481 IntrDev[id].isr_done = 0;
482 //active_devices[id] = 0;
483 }
484}
485function bit[31:0] CNiuLdg::getErrState() {
486 if(active_devices[68])
487 getErrState = IntrDev[68].getErrState();
488 else getErrState = 0;
489}
490function integer CNiuLdg::isPending() {
491 bit [68:0] flags;
492 bit [15:0] error_dev_flags;
493 bit done;
494 integer i;
495 integer count;
496 bit flags_set;
497 // check pending flags all the devices bound to this group
498 // Also check the local pending flag
499
500 flags = 0;
501 error_dev_flags = 0;
502 for(i=0;i<69;i++) {
503 if(active_devices[i]) flags[i] = 1;
504 else flags[i] = 0;
505 }
506 if(multi_device_68bound ) {
507 for(i=0;i<16;i++) {
508 if(error_devices_bound[i]) error_dev_flags[i] = 1;
509 else error_dev_flags[i] = 0;
510 }
511
512 }
513 count =0;
514 isPending = 1;
515 done = 0;
516 while(done==0) {
517
518 for(i=0;i<68;i++) {
519 if(active_devices[i] & (flags[i]==1) )
520 flags[i] = IntrDev[i].isPending() ;
521 }
522 if(multi_device_68bound & active_devices[68]) {
523 for(i=0;i<16;i++) {
524 if(error_devices_bound[i] & error_dev_flags[i] )
525 error_dev_flags[i] = IntrErrDev[i].isPending();
526 }
527 flags[68] = 0;
528 } else {
529 // for backward compatibility
530 if(active_devices[68] & (flags[68]==1) )
531 flags[68] = IntrDev[68].isPending() ;
532 }
533
534 if((flags==0)&&(error_dev_flags==0)) done = 1;
535
536 isPending = 0;
537 count++;
538 if(count>100) {
539 printf("CNiuLdg::isPending!! ERROR Pending flag not cleared for group - %d!! Count - %d \n",gid,count);
540 done = 1;
541 isPending = -1;
542 }
543 repeat(100) @(posedge CLOCK);
544 }
545}
546task CNiuLdg::mask_all_devices() {
547 integer i;
548 for(i=0;i<69;i++) {
549 if(active_devices[i])
550 IntrDev[i].pioSetMasks(3'h3); // may need to be enhanced!
551 }
552}
553task CNiuLdg::unmask_all_devices(){
554 integer i;
555 for(i=0;i<69;i++) {
556 if(active_devices[i])
557 IntrDev[i].pioSetMasks(3'h0);
558 }
559}