Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / test_utils / vera / niu_intr_setup.vr
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: niu_intr_setup.vr
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
//
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This 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 program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
//
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
// ========== Copyright Header End ============================================
#include <vera_defines.vrh>
#include "niu_int_dev.vrh"
#include "niu_int_mgr.vrh"
#include "niu_ldgintr_utils.vrh"
extern CNiuIntrMgr NiuIntrMgr;
class CNiuIntrTest {
// variables
integer timer = 10; // Test can change this
integer random_intr_timer = 0;
integer sys_err_mask_prog=0;
integer dev68grp=0;
integer dev68grpbound=0;
bit[68:0] virt_on = 69'h0;
bit[4:0] sidTab[];
local bit[4:0] sids[32];
integer fixed_function_no = 0;
local bit[5:0] virt_rx_dma_binds[32];
local bit[5:0] virt_tx_dma_binds[32];
local integer dev_to_grp_bind[69];
local integer group_already_bound[64];
task InitDevice ( CNiuIntrDev dev, integer group_info, (integer mask = 0),(integer sid_from_test=-1) );
task RemoveDevice (integer device_id, (CNiuIntrDev dev=null) );
local function integer getFuncNo(integer g);
local task compute_random_sids();
local task compute_random_virt_grp_no();
local function bit [6:0] getSid(integer group,integer func);
local function integer getLdgNo(integer func);
task new( (integer tx_v = -1), (integer rx_v = -1) );
task use_alt_ldg(bit[63:0] groups);
}
task CNiuIntrTest::new( (integer tx_v = -1), (integer rx_v = -1) ) {
integer i;
for(i=0;i<64;i++) group_already_bound[i] = 0;
if(rx_v ==-1) {
virt_on[31:0] = random();
} else virt_on[31:0] = rx_v;
if(tx_v ==-1) {
virt_on[63:32] = random();
} else virt_on[63:32] = tx_v;
printf(" CNiuIntrTest::new Virtualization Vector - %x \n",virt_on);
compute_random_sids();
compute_random_virt_grp_no();
for(i=0;i<68;i++) dev_to_grp_bind[i] = -1;
}
task CNiuIntrTest::use_alt_ldg(bit[63:0] groups) {
integer i;
CNiuLdgEx ldgEx[64];
for(i=0;i<64;i++) {
if(groups[i]) {
ldgEx[i] = new(i);
NiuIntrMgr.ldg[i] = ldgEx[i];
}
}
}
task CNiuIntrTest::compute_random_virt_grp_no(){
bit[5:0] rand_rx_gids[];
bit[5:0] rand_tx_gids[];
integer func_binding_type = 0;
bit [3:0] rand_max_15;
integer i;
bit[5:0] r;
if(get_plus_arg( CHECK, "RXTX_PIO_STRESS_BINDING=")) {
func_binding_type = get_plus_arg( NUM, "RXTX_PIO_STRESS_BINDING=");
func_binding_type = func_binding_type % 4;
fixed_function_no = 1;
}
if(get_plus_arg( CHECK, "RANDOM_INTR_TIMER")) {
random_intr_timer = 1;
} else random_intr_timer = 0;
for(i=0;i<32;i++){
r = random();
if(assoc_index(CHECK,rand_rx_gids,r)) {
// recompute
i--;
} else {
rand_rx_gids[r] = r;
virt_rx_dma_binds[i] = r;
}
// Over write for stress testMatrix requirements
if(get_plus_arg( CHECK, "RXTX_PIO_STRESS_BINDING=")) {
// rand_max_15 = random();
virt_rx_dma_binds[i] = getLdgNo(func_binding_type);
printf(" virt_rx_dma_binds - %d i = %d\n",virt_rx_dma_binds[i],i);
}
}
for(i=0;i<32;i++){
r = random();
if(assoc_index(CHECK,rand_tx_gids,r)) {
// recompute
i--;
} else {
rand_tx_gids[r] = r;
virt_tx_dma_binds[i] = r;
}
// Over write for stress testMatrix requirements
if(get_plus_arg( CHECK, "RXTX_PIO_STRESS_BINDING=")) {
// rand_max_15 = random();
virt_tx_dma_binds[i] = getLdgNo(func_binding_type);
printf(" virt_tx_dma_binds - %d i = %d\n",virt_tx_dma_binds[i],i);
}
}
}
task CNiuIntrTest::compute_random_sids(){
bit[4:0] rand_sids[];
integer i;
bit[4:0] r;
for(i=0;i<32;i++){
r = random();
if(assoc_index(CHECK,rand_sids,r)) {
// recompute
i--;
} else {
rand_sids[r] = r;
sids[i] = r;
}
}
}
function bit[6:0] CNiuIntrTest::getSid(integer group,integer func){
bit[1:0] f;
bit[4:0] g;
f= func ;
g = group ;
getSid = {f,sids[g]};
}
function integer CNiuIntrTest::getLdgNo(integer func){
integer min, max;
min = 0 +16*func;
max = 15 +16*func;
getLdgNo = random() %16 +min;
}
function integer CNiuIntrTest::getFuncNo(integer g) {
if(g<=15) getFuncNo = 0;
else if(g<=31) getFuncNo = 1;
else if(g<=47) getFuncNo = 2;
else if(g<=63) getFuncNo = 3;
else { printf("CNiuIntrTest::getFuncNo TESTBENCH ERROR Incorrect Group Specified !!\n");}
}
task CNiuIntrTest::RemoveDevice (integer device_id, (CNiuIntrDev dev=null) ){
// if device class is specified that takes precedence
// else take the device_id
integer device_to_remove;
integer group_bound;
if(dev==null) {
device_to_remove = device_id;
} else {
device_to_remove = dev.dev_id;
}
group_bound = dev_to_grp_bind[device_to_remove];
if(group_bound ==-1) {
printf("CNiuIntrTest::RemoveDevice:ERROR Device ID - %d Not bound to any group \n",device_to_remove);
return;
}
NiuIntrMgr.ldg[group_bound].ldgunbind(device_to_remove);
group_already_bound[group_bound]--;
if(group_already_bound[group_bound]==0) {
// remove SID also from the table
NiuIntrMgr.invalidateSidTab(group_bound);
}
}
task CNiuIntrTest::InitDevice ( CNiuIntrDev dev, integer group_info, (integer mask = 0),(integer sid_from_test=-1) ){
integer func;
integer group;
bit[6:0] sid;
integer grp_num;
integer rx_or_tx;
integer id;
integer skip_virt;
// group determines the function to which this is going to be bound
// if virtualization is enabled this is determined by the dma-virtual bind
// if virtualization is not defined, this get determined by the ldg
// ....
// ....
id = dev.dev_id;
// compute dma id from device_id
if(dev.dev_id<32) {
rx_or_tx = 1; // 0 - Tx 1 - Rx
id = dev.dev_id;
skip_virt = 0;
} else if(dev.dev_id<63) {
rx_or_tx = 0; // 0 - Tx 1 - Rx
id = dev.dev_id - 32;
skip_virt = 0;
} else {
// This device is either MAC or one of the error device
// cannot do virtualization on these
skip_virt = 1;
}
if(fixed_function_no) {
if(rx_or_tx) {
grp_num = virt_rx_dma_binds[id];
} else {
grp_num = virt_tx_dma_binds[id];
}
group_info = grp_num;
printf("FIXED FUNCTION NO!! Group - %d \n",group_info);
skip_virt = 1;
}
if(virt_on[dev.dev_id] && (skip_virt==0) ) {
if(rx_or_tx) {
grp_num = virt_rx_dma_binds[id];
} else {
grp_num = virt_tx_dma_binds[id];
}
func = getFuncNo(grp_num);
dev.bind_to_group(grp_num);
group_info = getLdgNo(func);
}
if((dev.dev_id==68) && (dev68grpbound)) {
// override the group_info
group_info = dev68grp;
}
if(group_info ==-1) {
// pick up a random group for this device
group = random()%64;
func = getFuncNo(group);
} else {
group = group_info;
func = getFuncNo(group_info);
}
if(group_already_bound[group]!=0) {
printf(" Group - %d Already has members - Not programming SID for this group\n",group);
} else {
// bind this group
group_already_bound[group]++;
if(sid_from_test==-1)
sid = getSid(group,func);
else sid = sid_from_test;
printf("CNiuIntrTest::InitDevice - SID - %x Group - %d Func - %d \n",sid,group,func);
NiuIntrMgr.updateSidTab(group,sid);
// Arm the initial interrupt
if(random_intr_timer)
NiuIntrMgr.ldg[group].SetIntrMgm(1/*Arm*/,timer + random()%timer /*Timer*/); // Set up Arm bit
else
NiuIntrMgr.ldg[group].SetIntrMgm(1/*Arm*/,timer/*Timer*/); // Set up Arm bit
// Set up rearm flag - Need to be under test control
NiuIntrMgr.ldg[group].rearm = 1;
}
dev.pioSetMasks(mask);
dev_to_grp_bind [dev.dev_id] = group;
NiuIntrMgr.ldg[group].ldgbind(dev);
if(dev.dev_id==68) {
dev68grp = group;
if(sys_err_mask_prog==0) {
NiuIntrMgr.ldg[group].SetErrMask(0);// programs all 0s for now...
sys_err_mask_prog = 1;
}
}
if(virt_on[dev.dev_id] && (skip_virt==0) ) {
NiuIntrMgr.ldg[group].dis_pio_virt = 0;
}
}