Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / vera / dmc_utils / niu_dma_bind.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: niu_dma_bind.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 "pio_memory_map.vri"
37#include "niu_gen_pio.vrh"
38#include "niu_mem.vrh"
39#include "niu_cbclass.vrh"
40#include "mbox_class.vrh"
41#include "cMesg.vrh"
42
43extern niu_gen_pio gen_pio_drv;
44extern CSparseMem SparseMem;
45extern mbox_class mbox_id;
46extern Mesg be_msg;
47
48
49class CNiuDMABind {
50
51 // Bind Shadows
52
53 // group to DMA Shadow
54 local bit [31:0] grp_tx_dma_bind[64];
55 local bit [31:0] grp_rx_dma_bind[64];
56 local bit[63:0] prog_grps;
57 // DMA to group Shadow
58 local integer tx_dma_grp_bind[64];
59 local integer rx_dma_grp_bind[64];
60
61 // functions numbers per DMA
62 integer tx_dma_func_bind[32];
63 integer rx_dma_func_bind[32];
64
65
66 local task WriteDMABind(integer group_no, bit[63:0] data);
67 function bit[63:0] ReadDMABind(integer group_no);
68 task SetTxBind( integer dma_no, integer group_no);
69 task SetRxBind( integer dma_no, integer group_no);
70 task ResetTxBind( integer dma_no, integer group_no);
71 task ResetRxBind( integer dma_no, integer group_no);
72 task SetRxTxBind( integer tx_dma_no, integer rx_dma_no, integer group_no);
73 function integer isDMABound(integer dma_no, integer tx_or_rx, integer group_no);
74 function bit[63:0] getPIOAddress( integer dma_no, integer tx_or_rx, integer group_no, bit[63:0] address, (integer pass_through=1) );
75 function bit[63:0] getFuncNoBase( integer group_no) ;
76 function integer getUnboundPIOAddress(var bit [63:0] address) ;
77 task CheckFunctionBinds(bit [63:0] address,integer func);
78 task InitUnBoundGroups() ;
79 task spCheckFunctionBinds ();
80 task SetDefFunc(integer func,integer type,integer id) ;
81
82
83 task new() {
84 integer i;
85 integer func_chk_enable;
86 prog_grps = 64'h0;
87 for(i=0;i<64;i++) {
88 grp_tx_dma_bind[i] = 32'h0;
89 grp_rx_dma_bind[i] = 32'h0;
90 }
91 for(i=0;i<64;i++) {
92 tx_dma_grp_bind[i] = -1;
93 rx_dma_grp_bind[i] = -1;
94 }
95 for(i=0;i<32;i++) {
96 rx_dma_func_bind[i] = -1;
97 tx_dma_func_bind[i] = -1;
98 }
99 }
100}
101
102task CNiuDMABind::SetDefFunc(integer func,integer type,integer id) {
103 if(type==1/*RX*/) {
104 rx_dma_func_bind[id] = func;
105 } else {/*TX*/
106 tx_dma_func_bind[id] = func;
107 }
108}
109
110task CNiuDMABind::WriteDMABind(integer group_no, bit[63:0] data) {
111 bit[63:0] address;
112 address = DMA_BIND + 8*group_no;
113 gen_pio_drv.pio_wr(address,data);
114}
115function bit[63:0] CNiuDMABind::ReadDMABind(integer group_no) {
116 bit[63:0] address;
117 address = DMA_BIND + 8*group_no;
118 gen_pio_drv.pio_rd(address,ReadDMABind);
119}
120
121task CNiuDMABind::SetTxBind( integer dma_no, integer group_no) {
122 // Check if this group is already bound. If so do a RMW
123 bit [63:0] rdata;
124 bit [4:0] d;
125 d = dma_no; // vera issue
126 //if((rx_dma_grp_bind[group_no]!= -1)|(tx_dma_grp_bind[group_no]!= -1)) { // }
127 if((grp_tx_dma_bind[group_no]!= 0) | (grp_rx_dma_bind[group_no]!= 0)) {
128 // group already bound
129 rdata = ReadDMABind(group_no);
130 } else {
131 rdata = 64'h0;
132 }
133 rdata[12:8] = d;
134 rdata[13] = 1;
135 WriteDMABind(group_no,rdata);
136 // update the Shadows
137 tx_dma_grp_bind[dma_no] = group_no;
138 tx_dma_func_bind[dma_no] = group_no/16;
139 grp_tx_dma_bind[group_no] = grp_tx_dma_bind[group_no] | 1<<dma_no;
140 prog_grps[group_no] = 1'b1;
141 printf("CNiuDMABind::SetTxBind: TxDMA - %d Bound to Group - %d \n",dma_no,group_no);
142}
143task CNiuDMABind::SetRxBind( integer dma_no, integer group_no) {
144 bit [63:0] rdata;
145 bit [4:0] d;
146 d = dma_no; // vera issue
147 //if((rx_dma_grp_bind[group_no]!= -1)|(tx_dma_grp_bind[group_no]!= -1)) { // }
148 if((grp_tx_dma_bind[group_no]!= 0) | (grp_rx_dma_bind[group_no]!= 0)) {
149 // group already bound
150 rdata = ReadDMABind(group_no);
151 } else {
152 rdata = 64'h0;
153 }
154 rdata[4:0] = d;
155 rdata[5] = 1;
156 WriteDMABind(group_no,rdata);
157 rx_dma_grp_bind[dma_no] = group_no;
158 rx_dma_func_bind[dma_no] = group_no/16;
159 grp_rx_dma_bind[group_no] = grp_rx_dma_bind[group_no] | 1<<dma_no;
160 prog_grps[group_no] = 1'b1;
161 printf("CNiuDMABind::SetRxBind: RxDMA - %d Bound to Group - %d \n",dma_no,group_no);
162
163}
164task CNiuDMABind::ResetTxBind( integer dma_no, integer group_no) {
165 // Check if this group is already bound. If so do a RMW
166 bit [63:0] rdata;
167 bit [4:0] d;
168 d = dma_no; // vera issue
169 rdata = ReadDMABind(group_no);
170 rdata[12:8] = d;
171 rdata[13] = 0;
172 WriteDMABind(group_no,rdata);
173 // update the Shadows
174 tx_dma_grp_bind[dma_no] = -1;
175 tx_dma_func_bind[dma_no] = group_no/16;
176 grp_tx_dma_bind[group_no] = grp_tx_dma_bind[group_no] | 0<<dma_no;
177 prog_grps[group_no] = 1'b0;
178 printf("CNiuDMABind::ResetTxBind: TxDMA - %d Reset Bound to Group - %d \n",dma_no,group_no);
179}
180task CNiuDMABind::ResetRxBind( integer dma_no, integer group_no) {
181 bit [63:0] rdata;
182 bit [4:0] d;
183 d = dma_no; // vera issue
184 rdata = ReadDMABind(group_no);
185 rdata[4:0] = d;
186 rdata[5] = 0;
187 WriteDMABind(group_no,rdata);
188 rx_dma_grp_bind[dma_no] = -1;
189 rx_dma_func_bind[dma_no] = group_no/16;
190 grp_rx_dma_bind[group_no] = grp_rx_dma_bind[group_no] | 0<<dma_no;
191 prog_grps[group_no] = 1'b0;
192 printf("CNiuDMABind::ResetRxBind: RxDMA - %d Reset Bound to Group - %d \n",dma_no,group_no);
193
194}
195task CNiuDMABind::SetRxTxBind( integer tx_dma_no, integer rx_dma_no, integer group_no) {
196
197 bit[63:0] rdata;
198 bit [4:0] t_d, r_d;
199 rdata = 64'h0;
200
201 t_d = tx_dma_no;
202 r_d = rx_dma_no;
203
204 rdata[12:8] = t_d;
205 rdata[13] = 1;
206 rdata[4:0] = r_d;
207 rdata[5] = 1;
208
209 WriteDMABind(group_no,rdata);
210 rx_dma_grp_bind[rx_dma_no] = group_no;
211 rx_dma_func_bind[rx_dma_no] = group_no/16;
212 grp_rx_dma_bind[group_no] = grp_rx_dma_bind[group_no] | 1<<rx_dma_no;
213
214 tx_dma_grp_bind[tx_dma_no] = group_no;
215 tx_dma_func_bind[tx_dma_no] = group_no/16;
216 grp_tx_dma_bind[group_no] = grp_tx_dma_bind[group_no] | 1<<tx_dma_no;
217 prog_grps[group_no] = 1'b1;
218
219
220}
221
222function bit[63:0] CNiuDMABind::getFuncNoBase( integer group_no) {
223 if(group_no<=15) {
224 getFuncNoBase = FUNC0_VIR;
225 } else if(group_no<=31) {
226 getFuncNoBase = FUNC1_VIR;
227 } else if(group_no<=47) {
228 getFuncNoBase = FUNC2_VIR;
229 } else if(group_no<=63) {
230 getFuncNoBase = FUNC3_VIR;
231 } else {
232 getFuncNoBase = 64'hx;
233 }
234}
235
236function bit[63:0] CNiuDMABind::getPIOAddress( integer dma_no, integer tx_or_rx, integer group_no, bit[63:0] address, (integer pass_through=1) ) {
237 integer func;
238 bit[5:0] g;
239 bit[63:0] orig_address;
240 orig_address = address;
241 g = group_no;
242 getPIOAddress = orig_address;
243 if((pass_through==1) | ( address[19]==1)) {
244 getPIOAddress = orig_address;
245 } else if(pass_through==-1) {
246 // place holder for generating error address
247 getPIOAddress = 0;
248 } else if(isDMABound(dma_no,tx_or_rx,group_no)) {
249
250 getPIOAddress = getFuncNoBase(group_no);
251 getPIOAddress[8:0] = orig_address[8:0];
252 getPIOAddress[9] = (tx_or_rx==0)? 0: 1; // Check polarity
253 getPIOAddress[14] = g[3];
254 getPIOAddress[12:10] = g[2:0];
255
256
257 } else {
258 // Need to generate error address here
259 getPIOAddress = 64'hx;
260 printf("CNiuDMABind::getPIOAddress dma_no - %d Not Bound to GroupNo - %d \n",dma_no,group_no);
261 }
262 printf("CNiuDMABind::getPIOAddress dma_no - %d orig_address - %x New Address - %x \n",dma_no,address,getPIOAddress);
263}
264
265function integer CNiuDMABind::isDMABound(integer dma_no, integer tx_or_rx, integer group_no) {
266 if(group_no==-1) {
267/* NEED TO GENERATE A VALID GROUP!!!*/
268 isDMABound =0;
269 } else if(tx_or_rx==0/*TX*/) {
270 if(tx_dma_grp_bind[dma_no]==group_no) isDMABound = 1;
271 else isDMABound = 0;
272 } else {/*RX*/
273 if(rx_dma_grp_bind[dma_no]==group_no) isDMABound = 1;
274 else isDMABound = 0;
275 }
276 printf("CNiuDMABind::isDMABound dma_no - %d group - %d isDMABound - %d \n",dma_no,group_no,isDMABound);
277}
278task CNiuDMABind::InitUnBoundGroups() {
279// Fill up the group table with random values, but disable the valid bit
280 integer i;
281 bit[63:0] wdata;
282
283 for(i=0;i<64;i++) {
284 if(prog_grps[i]==1'b0) {
285 wdata = {random(),random()};
286 wdata[13] = 1'b0;
287 wdata[5] = 1'b0;
288 WriteDMABind(i,wdata);
289 }
290 }
291}
292
293task CNiuDMABind::spCheckFunctionBinds () {
294 CfuncCheck funcChk;
295 bit [63:0] address;integer func;
296 integer no;
297 while(1) {
298 no = mailbox_get(WAIT,mbox_id.funcChk, funcChk);
299 address = funcChk.address;
300 func = funcChk.func;
301 CheckFunctionBinds(address,func);
302
303 }
304}
305task CNiuDMABind::CheckFunctionBinds(bit [63:0] address,integer func) {
306/*Task to be called only in Neptune and with a plusargs*/
307integer page_id;
308integer dma;
309integer rx_or_tx;
310integer group;
311integer funct_for_dma;
312
313 page_id= SparseMem.check_page_id(address);
314 if(page_id==-1) {
315 printf("CNiuDMABind::CheckFunctionBinds: WARNING Address - %x Doesnt Match any of the defined Page!! \n",address);
316 be_msg.print(e_mesg_error,"CNiuDMABind::CheckFunctionBinds:",""," Address - %x Doesnt Match any of the defined Page!! \n",address);
317
318 return;
319 } else {
320 if(page_id <64) {
321 rx_or_tx=0;
322 dma = page_id/2;
323 } else {
324 rx_or_tx=1;
325 dma = (page_id-64)/2;
326 }
327 }
328 printf("CNiuDMABind::CheckFunctionBinds: PAGE - %d rx_or_tx -%d - DMA - %d Address - %x!!\n",page_id,rx_or_tx,dma,address);
329 if(rx_or_tx) {
330 funct_for_dma = rx_dma_func_bind[dma];
331 } else {
332 funct_for_dma = tx_dma_func_bind[dma];
333 }
334
335 if(funct_for_dma==-1) {
336 printf("CNiuDMABind::CheckFunctionBinds: ERROR funct_for_dma for DMA - %d is unbound !!\n",dma);
337 be_msg.print(e_mesg_error,"CNiuDMABind::CheckFunctionBinds:",""," funct_for_dma for DMA - %d is unbound \n",dma);
338 } else {
339 if(func!==funct_for_dma) {
340 printf(" CNiuDMABind::CheckFunctionBinds: Incorrect FunctionNumber received for address - %x DMA - %d\n",address,dma);
341 be_msg.print(e_mesg_error,"CNiuDMABind::CheckFunctionBinds:",""," Incorrect FunctionNumber received Expected Function No - %d Actual - %d \n",funct_for_dma,func);
342 printf(" CNiuDMABind::CheckFunctionBinds: ERROR Incorrect FunctionNumber received Expected Function No - %d Actual - %d\n",funct_for_dma,func);
343 }
344 }
345}
346function integer CNiuDMABind::getUnboundPIOAddress(var bit [63:0] address) {
347
348 bit[5:0] g;
349 // pick up a random unbound group
350 //
351 if(prog_grps==64'hffffffffffffffff) {
352 getUnboundPIOAddress = 0;
353 } else {
354 g=random()%64;
355 while(prog_grps[g]==1'b1) {
356 g=random()%64;
357 }
358
359 address = getFuncNoBase(g);
360 address[9:0] = random();
361 address[14] = g[3];
362 address[12:10] = g[2:0];
363
364 getUnboundPIOAddress = 1;
365
366 }
367
368}