Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / vera / dmc_utils / niu_dma_bind.vr
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: niu_dma_bind.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 "pio_memory_map.vri"
#include "niu_gen_pio.vrh"
#include "niu_mem.vrh"
#include "niu_cbclass.vrh"
#include "mbox_class.vrh"
#include "cMesg.vrh"
extern niu_gen_pio gen_pio_drv;
extern CSparseMem SparseMem;
extern mbox_class mbox_id;
extern Mesg be_msg;
class CNiuDMABind {
// Bind Shadows
// group to DMA Shadow
local bit [31:0] grp_tx_dma_bind[64];
local bit [31:0] grp_rx_dma_bind[64];
local bit[63:0] prog_grps;
// DMA to group Shadow
local integer tx_dma_grp_bind[64];
local integer rx_dma_grp_bind[64];
// functions numbers per DMA
integer tx_dma_func_bind[32];
integer rx_dma_func_bind[32];
local task WriteDMABind(integer group_no, bit[63:0] data);
function bit[63:0] ReadDMABind(integer group_no);
task SetTxBind( integer dma_no, integer group_no);
task SetRxBind( integer dma_no, integer group_no);
task ResetTxBind( integer dma_no, integer group_no);
task ResetRxBind( integer dma_no, integer group_no);
task SetRxTxBind( integer tx_dma_no, integer rx_dma_no, integer group_no);
function integer isDMABound(integer dma_no, integer tx_or_rx, integer group_no);
function bit[63:0] getPIOAddress( integer dma_no, integer tx_or_rx, integer group_no, bit[63:0] address, (integer pass_through=1) );
function bit[63:0] getFuncNoBase( integer group_no) ;
function integer getUnboundPIOAddress(var bit [63:0] address) ;
task CheckFunctionBinds(bit [63:0] address,integer func);
task InitUnBoundGroups() ;
task spCheckFunctionBinds ();
task SetDefFunc(integer func,integer type,integer id) ;
task new() {
integer i;
integer func_chk_enable;
prog_grps = 64'h0;
for(i=0;i<64;i++) {
grp_tx_dma_bind[i] = 32'h0;
grp_rx_dma_bind[i] = 32'h0;
}
for(i=0;i<64;i++) {
tx_dma_grp_bind[i] = -1;
rx_dma_grp_bind[i] = -1;
}
for(i=0;i<32;i++) {
rx_dma_func_bind[i] = -1;
tx_dma_func_bind[i] = -1;
}
}
}
task CNiuDMABind::SetDefFunc(integer func,integer type,integer id) {
if(type==1/*RX*/) {
rx_dma_func_bind[id] = func;
} else {/*TX*/
tx_dma_func_bind[id] = func;
}
}
task CNiuDMABind::WriteDMABind(integer group_no, bit[63:0] data) {
bit[63:0] address;
address = DMA_BIND + 8*group_no;
gen_pio_drv.pio_wr(address,data);
}
function bit[63:0] CNiuDMABind::ReadDMABind(integer group_no) {
bit[63:0] address;
address = DMA_BIND + 8*group_no;
gen_pio_drv.pio_rd(address,ReadDMABind);
}
task CNiuDMABind::SetTxBind( integer dma_no, integer group_no) {
// Check if this group is already bound. If so do a RMW
bit [63:0] rdata;
bit [4:0] d;
d = dma_no; // vera issue
//if((rx_dma_grp_bind[group_no]!= -1)|(tx_dma_grp_bind[group_no]!= -1)) { // }
if((grp_tx_dma_bind[group_no]!= 0) | (grp_rx_dma_bind[group_no]!= 0)) {
// group already bound
rdata = ReadDMABind(group_no);
} else {
rdata = 64'h0;
}
rdata[12:8] = d;
rdata[13] = 1;
WriteDMABind(group_no,rdata);
// update the Shadows
tx_dma_grp_bind[dma_no] = group_no;
tx_dma_func_bind[dma_no] = group_no/16;
grp_tx_dma_bind[group_no] = grp_tx_dma_bind[group_no] | 1<<dma_no;
prog_grps[group_no] = 1'b1;
printf("CNiuDMABind::SetTxBind: TxDMA - %d Bound to Group - %d \n",dma_no,group_no);
}
task CNiuDMABind::SetRxBind( integer dma_no, integer group_no) {
bit [63:0] rdata;
bit [4:0] d;
d = dma_no; // vera issue
//if((rx_dma_grp_bind[group_no]!= -1)|(tx_dma_grp_bind[group_no]!= -1)) { // }
if((grp_tx_dma_bind[group_no]!= 0) | (grp_rx_dma_bind[group_no]!= 0)) {
// group already bound
rdata = ReadDMABind(group_no);
} else {
rdata = 64'h0;
}
rdata[4:0] = d;
rdata[5] = 1;
WriteDMABind(group_no,rdata);
rx_dma_grp_bind[dma_no] = group_no;
rx_dma_func_bind[dma_no] = group_no/16;
grp_rx_dma_bind[group_no] = grp_rx_dma_bind[group_no] | 1<<dma_no;
prog_grps[group_no] = 1'b1;
printf("CNiuDMABind::SetRxBind: RxDMA - %d Bound to Group - %d \n",dma_no,group_no);
}
task CNiuDMABind::ResetTxBind( integer dma_no, integer group_no) {
// Check if this group is already bound. If so do a RMW
bit [63:0] rdata;
bit [4:0] d;
d = dma_no; // vera issue
rdata = ReadDMABind(group_no);
rdata[12:8] = d;
rdata[13] = 0;
WriteDMABind(group_no,rdata);
// update the Shadows
tx_dma_grp_bind[dma_no] = -1;
tx_dma_func_bind[dma_no] = group_no/16;
grp_tx_dma_bind[group_no] = grp_tx_dma_bind[group_no] | 0<<dma_no;
prog_grps[group_no] = 1'b0;
printf("CNiuDMABind::ResetTxBind: TxDMA - %d Reset Bound to Group - %d \n",dma_no,group_no);
}
task CNiuDMABind::ResetRxBind( integer dma_no, integer group_no) {
bit [63:0] rdata;
bit [4:0] d;
d = dma_no; // vera issue
rdata = ReadDMABind(group_no);
rdata[4:0] = d;
rdata[5] = 0;
WriteDMABind(group_no,rdata);
rx_dma_grp_bind[dma_no] = -1;
rx_dma_func_bind[dma_no] = group_no/16;
grp_rx_dma_bind[group_no] = grp_rx_dma_bind[group_no] | 0<<dma_no;
prog_grps[group_no] = 1'b0;
printf("CNiuDMABind::ResetRxBind: RxDMA - %d Reset Bound to Group - %d \n",dma_no,group_no);
}
task CNiuDMABind::SetRxTxBind( integer tx_dma_no, integer rx_dma_no, integer group_no) {
bit[63:0] rdata;
bit [4:0] t_d, r_d;
rdata = 64'h0;
t_d = tx_dma_no;
r_d = rx_dma_no;
rdata[12:8] = t_d;
rdata[13] = 1;
rdata[4:0] = r_d;
rdata[5] = 1;
WriteDMABind(group_no,rdata);
rx_dma_grp_bind[rx_dma_no] = group_no;
rx_dma_func_bind[rx_dma_no] = group_no/16;
grp_rx_dma_bind[group_no] = grp_rx_dma_bind[group_no] | 1<<rx_dma_no;
tx_dma_grp_bind[tx_dma_no] = group_no;
tx_dma_func_bind[tx_dma_no] = group_no/16;
grp_tx_dma_bind[group_no] = grp_tx_dma_bind[group_no] | 1<<tx_dma_no;
prog_grps[group_no] = 1'b1;
}
function bit[63:0] CNiuDMABind::getFuncNoBase( integer group_no) {
if(group_no<=15) {
getFuncNoBase = FUNC0_VIR;
} else if(group_no<=31) {
getFuncNoBase = FUNC1_VIR;
} else if(group_no<=47) {
getFuncNoBase = FUNC2_VIR;
} else if(group_no<=63) {
getFuncNoBase = FUNC3_VIR;
} else {
getFuncNoBase = 64'hx;
}
}
function bit[63:0] CNiuDMABind::getPIOAddress( integer dma_no, integer tx_or_rx, integer group_no, bit[63:0] address, (integer pass_through=1) ) {
integer func;
bit[5:0] g;
bit[63:0] orig_address;
orig_address = address;
g = group_no;
getPIOAddress = orig_address;
if((pass_through==1) | ( address[19]==1)) {
getPIOAddress = orig_address;
} else if(pass_through==-1) {
// place holder for generating error address
getPIOAddress = 0;
} else if(isDMABound(dma_no,tx_or_rx,group_no)) {
getPIOAddress = getFuncNoBase(group_no);
getPIOAddress[8:0] = orig_address[8:0];
getPIOAddress[9] = (tx_or_rx==0)? 0: 1; // Check polarity
getPIOAddress[14] = g[3];
getPIOAddress[12:10] = g[2:0];
} else {
// Need to generate error address here
getPIOAddress = 64'hx;
printf("CNiuDMABind::getPIOAddress dma_no - %d Not Bound to GroupNo - %d \n",dma_no,group_no);
}
printf("CNiuDMABind::getPIOAddress dma_no - %d orig_address - %x New Address - %x \n",dma_no,address,getPIOAddress);
}
function integer CNiuDMABind::isDMABound(integer dma_no, integer tx_or_rx, integer group_no) {
if(group_no==-1) {
/* NEED TO GENERATE A VALID GROUP!!!*/
isDMABound =0;
} else if(tx_or_rx==0/*TX*/) {
if(tx_dma_grp_bind[dma_no]==group_no) isDMABound = 1;
else isDMABound = 0;
} else {/*RX*/
if(rx_dma_grp_bind[dma_no]==group_no) isDMABound = 1;
else isDMABound = 0;
}
printf("CNiuDMABind::isDMABound dma_no - %d group - %d isDMABound - %d \n",dma_no,group_no,isDMABound);
}
task CNiuDMABind::InitUnBoundGroups() {
// Fill up the group table with random values, but disable the valid bit
integer i;
bit[63:0] wdata;
for(i=0;i<64;i++) {
if(prog_grps[i]==1'b0) {
wdata = {random(),random()};
wdata[13] = 1'b0;
wdata[5] = 1'b0;
WriteDMABind(i,wdata);
}
}
}
task CNiuDMABind::spCheckFunctionBinds () {
CfuncCheck funcChk;
bit [63:0] address;integer func;
integer no;
while(1) {
no = mailbox_get(WAIT,mbox_id.funcChk, funcChk);
address = funcChk.address;
func = funcChk.func;
CheckFunctionBinds(address,func);
}
}
task CNiuDMABind::CheckFunctionBinds(bit [63:0] address,integer func) {
/*Task to be called only in Neptune and with a plusargs*/
integer page_id;
integer dma;
integer rx_or_tx;
integer group;
integer funct_for_dma;
page_id= SparseMem.check_page_id(address);
if(page_id==-1) {
printf("CNiuDMABind::CheckFunctionBinds: WARNING Address - %x Doesnt Match any of the defined Page!! \n",address);
be_msg.print(e_mesg_error,"CNiuDMABind::CheckFunctionBinds:",""," Address - %x Doesnt Match any of the defined Page!! \n",address);
return;
} else {
if(page_id <64) {
rx_or_tx=0;
dma = page_id/2;
} else {
rx_or_tx=1;
dma = (page_id-64)/2;
}
}
printf("CNiuDMABind::CheckFunctionBinds: PAGE - %d rx_or_tx -%d - DMA - %d Address - %x!!\n",page_id,rx_or_tx,dma,address);
if(rx_or_tx) {
funct_for_dma = rx_dma_func_bind[dma];
} else {
funct_for_dma = tx_dma_func_bind[dma];
}
if(funct_for_dma==-1) {
printf("CNiuDMABind::CheckFunctionBinds: ERROR funct_for_dma for DMA - %d is unbound !!\n",dma);
be_msg.print(e_mesg_error,"CNiuDMABind::CheckFunctionBinds:",""," funct_for_dma for DMA - %d is unbound \n",dma);
} else {
if(func!==funct_for_dma) {
printf(" CNiuDMABind::CheckFunctionBinds: Incorrect FunctionNumber received for address - %x DMA - %d\n",address,dma);
be_msg.print(e_mesg_error,"CNiuDMABind::CheckFunctionBinds:",""," Incorrect FunctionNumber received Expected Function No - %d Actual - %d \n",funct_for_dma,func);
printf(" CNiuDMABind::CheckFunctionBinds: ERROR Incorrect FunctionNumber received Expected Function No - %d Actual - %d\n",funct_for_dma,func);
}
}
}
function integer CNiuDMABind::getUnboundPIOAddress(var bit [63:0] address) {
bit[5:0] g;
// pick up a random unbound group
//
if(prog_grps==64'hffffffffffffffff) {
getUnboundPIOAddress = 0;
} else {
g=random()%64;
while(prog_grps[g]==1'b1) {
g=random()%64;
}
address = getFuncNoBase(g);
address[9:0] = random();
address[14] = g[3];
address[12:10] = g[2:0];
getUnboundPIOAddress = 1;
}
}