Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: niu_tx_port.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 "niu_tx_descp.vrh" | |
36 | #include "dmc_memory_map.vri" | |
37 | #include "txc_memory_map.vri" | |
38 | extern niu_gen_pio gen_pio_drv; | |
39 | // tmp only | |
40 | // #include "txc_drr_chk_if.vri" | |
41 | #include "tx_port_drr_if.vri" | |
42 | extern mbox_class mbox_id; | |
43 | #include "cMesg.vrh" | |
44 | extern Mesg be_msg; | |
45 | extern event TX_rvcd_allpkts[4]; | |
46 | extern mac_pio_cl mac_pio_class; | |
47 | extern mac_util_class mac_util; | |
48 | ||
49 | // To Support MAC Loop back mode | |
50 | #include "niu_rxtoken.vrh" | |
51 | #include "niu_txport_cb.vrh" | |
52 | ||
53 | #define TIME {get_time(HI), get_time(LO)} | |
54 | ||
55 | class CMacTxPort { | |
56 | ||
57 | integer id; // port id | |
58 | DMAChannel dma[32]; // a max of 32 dma channels per port can be bound | |
59 | integer port_speed; | |
60 | integer USE_CALL_BACKS = 0; | |
61 | ||
62 | bit[31:0] DMAActiveList; | |
63 | bit[31:0] OrigDMAActiveList; | |
64 | bit [11:0] port_offset; | |
65 | bit [3:0] MAC_LOOP_BACK_MODE; | |
66 | integer EXT_LOOPBACK_DST=-1; | |
67 | ||
68 | CTxPortCbMgr TxPortCbMgr; | |
69 | ||
70 | task new(integer i=0); | |
71 | task add_channels( integer i); | |
72 | task delete_channels( integer i); | |
73 | task BindDmaIntrDev( DMAChannel TxDma, integer i ); | |
74 | task SetActive (integer list, (integer rebind = 0)); | |
75 | task DRR(/*TMPONLY*/txc_port_drr port_bind); | |
76 | task pollLatchActive(txc_port_drr port_bind); | |
77 | function integer check_active ( integer j, integer activeList); | |
78 | ||
79 | task check_exit_status(); | |
80 | task check_pkt_cnt (integer no_of_pkts, (integer timeout_count= 100),(integer chk_type = 0)); | |
81 | task check_randompkt_cnt (integer no_of_pkts[24], (integer timeout_count = 100)); | |
82 | task check_pkt_cnt_perdma (integer no_of_pkts); | |
83 | function integer get_allpkts_toport (integer no_of_pkts); | |
84 | function integer get_allpkts_toport_random (integer no_of_pkts[24]); | |
85 | ||
86 | task SetActive_NoOfDMAs (integer list) ; | |
87 | task Inj_ReEcc_Error(bit [63:0] data, (integer fifo_sel = 0)); | |
88 | task Rd_ReEcc_St(var bit [63:0] r_data); | |
89 | task Rd_ReEcc_UE(); | |
90 | task Rd_ReEcc_CE(); | |
91 | task Enb_Watermark_Reg(bit [63:0] data); | |
92 | task Wr_TXC_RO_CTL(bit [63:0] data); | |
93 | task Rd_TXC_RO_CTL(var bit [63:0] rd_data); | |
94 | task SnapShotDMAs( bit[31:0] ActiveListSnapShot); | |
95 | task LoadDMAStates( bit[31:0] ActiveListSnapShot); | |
96 | task PullTokensBack( bit[31:0] list); | |
97 | function integer wait_for_addcredit(txc_port_drr port_bind); | |
98 | ||
99 | task Wr_Txc_max_reoder(bit[63:0] wr_data); | |
100 | task Wr_Txc_Port_Ctl(bit[63:0] wr_data); | |
101 | task Wr_Txc_Pkt_stuffed(bit[63:0] wr_data); | |
102 | task Wr_Txc_Pkt_Xmitted(bit[63:0] wr_data); | |
103 | task Rd_Txc_Pkt_stuffed(var bit[63:0] rd_data); | |
104 | task Rd_Txc_Pkt_Xmitted(var bit[63:0] rd_data); | |
105 | ||
106 | // add tasks to read & write RO ECC | |
107 | ||
108 | task Wr_Txc_ROECC_ST(bit [63:0] wr_data); | |
109 | task Rd_Txc_ROECC_ST(var bit [63:0] rd_data); | |
110 | ||
111 | task Rd_Txc_RO_Data0(var bit [63:0] rd_data); | |
112 | task Rd_Txc_RO_Data1(var bit [63:0] rd_data); | |
113 | task Rd_Txc_RO_Data2(var bit [63:0] rd_data); | |
114 | task Rd_Txc_RO_Data3(var bit [63:0] rd_data); | |
115 | task Rd_Txc_RO_Data4(var bit [63:0] rd_data); | |
116 | ||
117 | // add tasks to read & write SF ECC | |
118 | ||
119 | task Wr_Txc_SFECC_ST(bit [63:0] wr_data); | |
120 | task Rd_Txc_SFECC_ST(var bit [63:0] rd_data); | |
121 | ||
122 | task Rd_Txc_SF_Data0(var bit [63:0] rd_data); | |
123 | task Rd_Txc_SF_Data1(var bit [63:0] rd_data); | |
124 | task Rd_Txc_SF_Data2(var bit [63:0] rd_data); | |
125 | task Rd_Txc_SF_Data3(var bit [63:0] rd_data); | |
126 | task Rd_Txc_SF_Data4(var bit [63:0] rd_data); | |
127 | ||
128 | // add rds & wr to txc-tid regs | |
129 | ||
130 | task Wr_Txc_RO_Tids(bit [63:0] wr_data); | |
131 | task Wr_Txc_RO_State0(bit [63:0] wr_data); | |
132 | task Wr_Txc_RO_State1(bit [63:0] wr_data); | |
133 | task Wr_Txc_RO_State2(bit [63:0] wr_data); | |
134 | task Wr_Txc_RO_State3(bit [63:0] wr_data); | |
135 | ||
136 | task Rd_Txc_RO_Tids(var bit [63:0] rd_data); | |
137 | task Rd_Txc_RO_State0(var bit [63:0] rd_data); | |
138 | task Rd_Txc_RO_State1(var bit [63:0] rd_data); | |
139 | task Rd_Txc_RO_State2(var bit [63:0] rd_data); | |
140 | task Rd_Txc_RO_State3(var bit [63:0] rd_data); | |
141 | ||
142 | task DeActivate_channel(integer i); | |
143 | ||
144 | task check_bytes_txmitted(); | |
145 | task check_pkts_stuffed(integer no_of_pkts); | |
146 | task Wr_Txc_Intr_Mask(bit[63:0] data); | |
147 | task Rd_Txc_Intr_Stat(var bit[63:0] rd_data); | |
148 | task Wr_Txc_Intr_Stat(bit [63:0] data); | |
149 | ||
150 | task check_mac_txfrmcnt(integer no_of_pkts); | |
151 | ||
152 | } | |
153 | ||
154 | function integer CMacTxPort::check_active ( integer j, integer activeList) { | |
155 | // returns 1 if jth bit in the ActiveList is set else returns 0 | |
156 | integer tmp; | |
157 | tmp = 1 <<j; | |
158 | if(activeList & tmp) check_active = (1); | |
159 | else check_active = (0); | |
160 | ||
161 | } | |
162 | ||
163 | task CMacTxPort::new (integer i = 0) { | |
164 | ||
165 | string init_loopback,temp_port; | |
166 | bit [31:0] loopback; | |
167 | integer j; | |
168 | ||
169 | printf("MacTxPort %0d newed\n", this.id); | |
170 | id = i; | |
171 | trigger(OFF,TX_rvcd_allpkts[id]); | |
172 | DMAActiveList = 0; // none of the DMAs active | |
173 | OrigDMAActiveList = DMAActiveList; | |
174 | port_offset = 256*i; | |
175 | MAC_LOOP_BACK_MODE = 0; | |
176 | if(get_plus_arg(CHECK, "rx0_txloopback_src")) | |
177 | if(get_plus_arg(NUM, "rx0_txloopback_src=") == this.id) { | |
178 | EXT_LOOPBACK_DST = 0; | |
179 | printf("MacTxPort %0d EXT_LOOPBACK_DST=%0d\n", this.id, EXT_LOOPBACK_DST); | |
180 | } | |
181 | if(get_plus_arg(CHECK, "rx1_txloopback_src")) | |
182 | if(get_plus_arg(NUM, "rx1_txloopback_src=") == this.id) { | |
183 | EXT_LOOPBACK_DST = 1; | |
184 | printf("MacTxPort %0d EXT_LOOPBACK_DST=%0d\n", this.id, EXT_LOOPBACK_DST); | |
185 | } | |
186 | if(get_plus_arg(CHECK, "rx2_txloopback_src")) | |
187 | if(get_plus_arg(NUM, "rx2_txloopback_src=") == this.id) { | |
188 | EXT_LOOPBACK_DST = 2; | |
189 | printf("MacTxPort %0d EXT_LOOPBACK_DST=%0d\n", this.id, EXT_LOOPBACK_DST); | |
190 | } | |
191 | if(get_plus_arg(CHECK, "rx3_txloopback_src")) | |
192 | if(get_plus_arg(NUM, "rx3_txloopback_src=") == this.id) { | |
193 | EXT_LOOPBACK_DST = 3; | |
194 | printf("MacTxPort %0d EXT_LOOPBACK_DST=%0d\n", this.id, EXT_LOOPBACK_DST); | |
195 | } | |
196 | ||
197 | TxPortCbMgr = new(i); | |
198 | for(j=0;j<4;j++) { | |
199 | if(mbox_id.niu_tx_cb[j] == -1) { | |
200 | // Alocate Mailbox | |
201 | mbox_id.niu_tx_cb[j] = alloc(MAILBOX,0,1); | |
202 | // Check if we were succesfull allocating the mailbox | |
203 | if(mbox_id.niu_tx_cb[j] == 0) { | |
204 | printf("ERROR Could not allocate the outgoing mailbox port %d \n",j); | |
205 | mbox_id.niu_tx_cb[j] = -1; | |
206 | return; | |
207 | } | |
208 | } | |
209 | } | |
210 | ||
211 | for(j=0;j<4;j++) { | |
212 | if(mbox_id.niu_txdrr[j] == -1) { | |
213 | // Alocate Mailbox | |
214 | mbox_id.niu_txdrr[j] = alloc(MAILBOX,0,1); | |
215 | // Check if we were succesfull allocating the mailbox | |
216 | if(mbox_id.niu_txdrr[j] == 0) { | |
217 | printf("ERROR Could not allocate the outgoing mailbox port %d \n",j); | |
218 | mbox_id.niu_txdrr[j] = -1; | |
219 | return; | |
220 | } | |
221 | } | |
222 | } | |
223 | if( get_plus_arg( CHECK, "NW_DRR_MODEL")) { | |
224 | USE_CALL_BACKS = 1; | |
225 | } | |
226 | ||
227 | if( get_plus_arg( CHECK, "MAC_LOOP_BACK=")) { | |
228 | loopback = get_plus_arg( STR, "MAC_LOOP_BACK="); | |
229 | init_loopback.bittostr(loopback); | |
230 | for (j=0; j<init_loopback.len();j++) | |
231 | { | |
232 | temp_port =init_loopback.substr(j,j); | |
233 | MAC_LOOP_BACK_MODE = MAC_LOOP_BACK_MODE | ( 1<<temp_port.atoi()); | |
234 | } | |
235 | printf(" MAC LOOP BACK ENABLED!! LoopBack Configuration - %b \n",MAC_LOOP_BACK_MODE); | |
236 | } else MAC_LOOP_BACK_MODE = 0; | |
237 | ||
238 | ||
239 | fork | |
240 | case(id) { | |
241 | 0: DRR(txc_port0_drr_bind) ; | |
242 | 1: DRR(txc_port1_drr_bind) ; | |
243 | default: printf("ERROR Incorrect port id set for CMacTxPort got id=%0d\n",id); | |
244 | } | |
245 | join none | |
246 | ||
247 | } | |
248 | ||
249 | task CMacTxPort::BindDmaIntrDev( DMAChannel TxDma, integer i ) { | |
250 | /* For binding interruptable dma devices */ | |
251 | dma[i] = TxDma; | |
252 | dma[i].bind_to_txport(id/*port_id*/); | |
253 | printf(" CMacTxPort::BindDmaIntrDevTRxDMA Channel - %d Bound as Logical DeviceId - %d \n",i,dma[i].dev_id); | |
254 | ||
255 | } | |
256 | task CMacTxPort::add_channels( integer i) { | |
257 | dma[i] = null; | |
258 | dma[i] = new(i,"TX"); | |
259 | dma[i].bind_to_txport(id/*port_id*/); | |
260 | } | |
261 | ||
262 | task CMacTxPort:: delete_channels( integer i) { | |
263 | dma[i].unbind_from_txport(id); | |
264 | dma[i] = null; | |
265 | } | |
266 | ||
267 | task CMacTxPort::SetActive( integer list, (integer rebind = 0)) { | |
268 | ||
269 | bit [39:0] address; | |
270 | bit [63:0] w_data; | |
271 | bit [63:0] rd_data; | |
272 | ||
273 | DMAActiveList = list; | |
274 | OrigDMAActiveList = DMAActiveList; | |
275 | ||
276 | if(!rebind) { | |
277 | ||
278 | address = TXC_FZC_BASE+ (TXC_PORT0_DMA_ENBALE + port_offset); | |
279 | w_data = {random(),DMAActiveList} ; // | |
280 | gen_pio_drv.pio_wr(address,w_data); | |
281 | ||
282 | } else { | |
283 | ||
284 | // do a read modify write while trying to rebind | |
285 | ||
286 | address = TXC_FZC_BASE+ (TXC_PORT0_DMA_ENBALE + port_offset); | |
287 | // first read the data | |
288 | gen_pio_drv.pio_rd(address,rd_data); | |
289 | ||
290 | w_data = rd_data | {random(),DMAActiveList} ; // | |
291 | gen_pio_drv.pio_wr(address,w_data); | |
292 | ||
293 | DMAActiveList = w_data; | |
294 | OrigDMAActiveList = w_data; | |
295 | } | |
296 | ||
297 | } | |
298 | ||
299 | task CMacTxPort :: DeActivate_channel(integer list) { | |
300 | ||
301 | integer i; | |
302 | bit [31:0] delete_list; | |
303 | bit [39:0] address; | |
304 | bit [63:0] w_data = 64'h0; | |
305 | bit [63:0] rd_data; | |
306 | ||
307 | delete_list = list; | |
308 | ||
309 | address = TXC_FZC_BASE+ (TXC_PORT0_DMA_ENBALE + port_offset); | |
310 | gen_pio_drv.pio_rd(address,rd_data); | |
311 | ||
312 | for(i=0;i<32;i++) { | |
313 | if(delete_list[i] & rd_data[i]) | |
314 | w_data[i] = 0; | |
315 | else | |
316 | w_data[i] = rd_data[i]; | |
317 | } | |
318 | ||
319 | gen_pio_drv.pio_wr(address,w_data); | |
320 | } | |
321 | ||
322 | ||
323 | //temp task for Set Active based on the number of DMAs tied to the ports | |
324 | ||
325 | task CMacTxPort :: SetActive_NoOfDMAs (integer list) { | |
326 | ||
327 | bit [39:0] address; | |
328 | bit [63:0] w_data; | |
329 | ||
330 | DMAActiveList = (1 << list) - 1; | |
331 | OrigDMAActiveList = DMAActiveList; | |
332 | ||
333 | address = TXC_FZC_BASE+ (TXC_PORT0_DMA_ENBALE + port_offset); | |
334 | w_data = {random(),DMAActiveList} ; // | |
335 | gen_pio_drv.pio_wr(address,w_data); | |
336 | ||
337 | } | |
338 | ||
339 | //-- progranmme the watermark register -----// | |
340 | ||
341 | task CMacTxPort :: Enb_Watermark_Reg(bit [63:0] data) { | |
342 | ||
343 | bit [39:0] address; | |
344 | ||
345 | address = TXC_FZC_BASE + (TXC_RO_STATE3 + port_offset); | |
346 | gen_pio_drv.pio_wr(address,data); | |
347 | } | |
348 | ||
349 | //-- write to TXC_RO_st_ctl | |
350 | ||
351 | task CMacTxPort :: Wr_TXC_RO_CTL(bit [63:0] data) | |
352 | { | |
353 | ||
354 | bit [39:0] address; | |
355 | ||
356 | address = TXC_FZC_BASE + (TXC_RO_CTL + port_offset); | |
357 | gen_pio_drv.pio_wr(address,data); | |
358 | } | |
359 | ||
360 | //-- write to TXC_RO_st_ctl | |
361 | ||
362 | task CMacTxPort :: Rd_TXC_RO_CTL(var bit [63:0] rd_data) | |
363 | { | |
364 | ||
365 | bit [39:0] address; | |
366 | ||
367 | address = TXC_FZC_BASE + (TXC_RO_CTL + port_offset); | |
368 | gen_pio_drv.pio_rd(address,rd_data); | |
369 | } | |
370 | ||
371 | ||
372 | // task to inject ECC errors | |
373 | ||
374 | task CMacTxPort :: Inj_ReEcc_Error(bit [63:0] data, (integer fifo_sel = 0)) | |
375 | { | |
376 | bit [39:0] address; | |
377 | ||
378 | if(fifo_sel == 0) { | |
379 | // ecc error RO fifo | |
380 | address = TXC_FZC_BASE + (TXC_ROECC_CTL + port_offset); | |
381 | gen_pio_drv.pio_wr(address,data); | |
382 | } else if(fifo_sel == 1) { | |
383 | // ecc error SO fifo | |
384 | address = TXC_FZC_BASE + (TXC_SFECC_CTL + port_offset); | |
385 | gen_pio_drv.pio_wr(address,data); | |
386 | } | |
387 | } | |
388 | ||
389 | // task to read ecc status register | |
390 | ||
391 | task CMacTxPort :: Rd_ReEcc_St(var bit [63:0] r_data) | |
392 | { | |
393 | bit [39:0] address; | |
394 | ||
395 | address = TXC_FZC_BASE + (TXC_ROECC_ST + port_offset); | |
396 | gen_pio_drv.pio_rd(address,r_data); | |
397 | } | |
398 | ||
399 | // Task to read correct able err | |
400 | ||
401 | task CMacTxPort :: Rd_ReEcc_CE() | |
402 | { | |
403 | bit [63:0] rd_data; | |
404 | ||
405 | Rd_ReEcc_St(rd_data); | |
406 | ||
407 | if(rd_data[17]) | |
408 | be_msg.print(e_mesg_info,"niu_tx_port","Rd_ReEcc_Ce","Detected CE at address %0h\n",rd_data[9:0]); | |
409 | else | |
410 | be_msg.print(e_mesg_error,"niu_tx_port","Rd_ReEcc_Ce","No CE detected at address %0h\n",rd_data[9:0]); | |
411 | } | |
412 | ||
413 | // Task to read correct able err | |
414 | ||
415 | task CMacTxPort :: Rd_ReEcc_UE() | |
416 | { | |
417 | bit [63:0] rd_data; | |
418 | ||
419 | Rd_ReEcc_St(rd_data); | |
420 | ||
421 | if(rd_data[16]) | |
422 | be_msg.print(e_mesg_info,"niu_tx_port","Rd_ReEcc_UE","Detected UE at address %0h\n",rd_data[9:0]); | |
423 | else | |
424 | be_msg.print(e_mesg_error,"niu_tx_port","Rd_ReEcc_UE","No UE detected at address %0h\n",rd_data[9:0]); | |
425 | } | |
426 | ||
427 | ||
428 | // task to read modify write to TXC_MAX_REORDER | |
429 | ||
430 | task CMacTxPort :: Wr_Txc_max_reoder(bit[63:0] wr_data) { | |
431 | ||
432 | bit [39:0] address; | |
433 | bit [63:0] rd_data; | |
434 | bit [63:0] ac_wrdata; | |
435 | ||
436 | address = TXC_FZC_BASE + (TXC_MAX_REORDER); | |
437 | gen_pio_drv.pio_rd(address,rd_data); | |
438 | ac_wrdata = rd_data | wr_data; | |
439 | ||
440 | address = TXC_FZC_BASE + (TXC_MAX_REORDER); | |
441 | gen_pio_drv.pio_wr(address,ac_wrdata); | |
442 | ||
443 | } | |
444 | ||
445 | ||
446 | ||
447 | // task to write to txc_port_ctl | |
448 | ||
449 | task CMacTxPort :: Wr_Txc_Port_Ctl(bit[63:0] wr_data) { | |
450 | ||
451 | bit [39:0] address; | |
452 | ||
453 | address = TXC_FZC_BASE + (TXC_PORT0_CONTROL + port_offset); | |
454 | gen_pio_drv.pio_wr(address,wr_data); | |
455 | } | |
456 | ||
457 | ||
458 | // task to rd & wr pkts stuffed & pkts_xmitted | |
459 | ||
460 | task CMacTxPort :: Wr_Txc_Pkt_stuffed(bit[63:0] wr_data) { | |
461 | ||
462 | bit [39:0] address; | |
463 | address = TXC_FZC_BASE + (TXC_PKT_STUFFED + port_offset); | |
464 | gen_pio_drv.pio_wr(address,wr_data); | |
465 | ||
466 | } | |
467 | ||
468 | task CMacTxPort :: Wr_Txc_Pkt_Xmitted(bit[63:0] wr_data) { | |
469 | ||
470 | bit [39:0] address; | |
471 | address = TXC_FZC_BASE + (TXC_PKT_XMIT + port_offset); | |
472 | gen_pio_drv.pio_wr(address,wr_data); | |
473 | } | |
474 | ||
475 | task CMacTxPort :: Rd_Txc_Pkt_stuffed(var bit[63:0] rd_data) { | |
476 | ||
477 | bit [39:0] address; | |
478 | address = TXC_FZC_BASE + (TXC_PKT_STUFFED + port_offset); | |
479 | gen_pio_drv.pio_rd(address, rd_data); | |
480 | } | |
481 | ||
482 | task CMacTxPort :: Rd_Txc_Pkt_Xmitted(var bit[63:0] rd_data) { | |
483 | ||
484 | bit [39:0] address; | |
485 | address = TXC_FZC_BASE + (TXC_PKT_XMIT + port_offset); | |
486 | gen_pio_drv.pio_rd(address, rd_data); | |
487 | } | |
488 | ||
489 | // tasks to rd & write RO based regs | |
490 | ||
491 | task CMacTxPort :: Wr_Txc_ROECC_ST(bit [63:0] wr_data) { | |
492 | bit [39:0] address; | |
493 | address = TXC_FZC_BASE + (TXC_ROECC_ST + port_offset); | |
494 | gen_pio_drv.pio_wr(address,wr_data); | |
495 | } | |
496 | ||
497 | task CMacTxPort :: Rd_Txc_ROECC_ST(var bit [63:0] rd_data) { | |
498 | bit [39:0] address; | |
499 | address = TXC_FZC_BASE + (TXC_ROECC_ST + port_offset); | |
500 | gen_pio_drv.pio_rd(address, rd_data); | |
501 | } | |
502 | ||
503 | ||
504 | task CMacTxPort :: Rd_Txc_RO_Data0(var bit [63:0] rd_data) { | |
505 | bit [39:0] address; | |
506 | address = TXC_FZC_BASE + (TXC_RO_DATA0 + port_offset); | |
507 | gen_pio_drv.pio_rd(address, rd_data); | |
508 | } | |
509 | ||
510 | task CMacTxPort :: Rd_Txc_RO_Data1(var bit [63:0] rd_data) { | |
511 | bit [39:0] address; | |
512 | address = TXC_FZC_BASE + (TXC_RO_DATA1 + port_offset); | |
513 | gen_pio_drv.pio_rd(address, rd_data); | |
514 | } | |
515 | ||
516 | task CMacTxPort :: Rd_Txc_RO_Data2(var bit [63:0] rd_data) { | |
517 | bit [39:0] address; | |
518 | address = TXC_FZC_BASE + (TXC_RO_DATA2 + port_offset); | |
519 | gen_pio_drv.pio_rd(address, rd_data); | |
520 | } | |
521 | ||
522 | task CMacTxPort :: Rd_Txc_RO_Data3(var bit [63:0] rd_data) { | |
523 | bit [39:0] address; | |
524 | address = TXC_FZC_BASE + (TXC_RO_DATA3 + port_offset); | |
525 | gen_pio_drv.pio_rd(address, rd_data); | |
526 | } | |
527 | ||
528 | task CMacTxPort :: Rd_Txc_RO_Data4(var bit [63:0] rd_data) { | |
529 | bit [39:0] address; | |
530 | address = TXC_FZC_BASE + (TXC_RO_DATA4 + port_offset); | |
531 | gen_pio_drv.pio_rd(address, rd_data); | |
532 | } | |
533 | ||
534 | ||
535 | // tasks to rd & write SF based regs | |
536 | ||
537 | task CMacTxPort :: Wr_Txc_SFECC_ST(bit [63:0] wr_data) { | |
538 | bit [39:0] address; | |
539 | address = TXC_FZC_BASE + (TXC_SFECC_ST + port_offset); | |
540 | gen_pio_drv.pio_wr(address,wr_data); | |
541 | } | |
542 | ||
543 | task CMacTxPort :: Rd_Txc_SFECC_ST(var bit [63:0] rd_data) { | |
544 | bit [39:0] address; | |
545 | address = TXC_FZC_BASE + (TXC_SFECC_ST + port_offset); | |
546 | gen_pio_drv.pio_rd(address, rd_data); | |
547 | } | |
548 | ||
549 | task CMacTxPort :: Rd_Txc_SF_Data0(var bit [63:0] rd_data) { | |
550 | bit [39:0] address; | |
551 | address = TXC_FZC_BASE + (TXC_SF_DATA0 + port_offset); | |
552 | gen_pio_drv.pio_rd(address, rd_data); | |
553 | } | |
554 | ||
555 | task CMacTxPort :: Rd_Txc_SF_Data1(var bit [63:0] rd_data) { | |
556 | bit [39:0] address; | |
557 | address = TXC_FZC_BASE + (TXC_SF_DATA1 + port_offset); | |
558 | gen_pio_drv.pio_rd(address, rd_data); | |
559 | } | |
560 | ||
561 | task CMacTxPort :: Rd_Txc_SF_Data2(var bit [63:0] rd_data) { | |
562 | bit [39:0] address; | |
563 | address = TXC_FZC_BASE + (TXC_SF_DATA2 + port_offset); | |
564 | gen_pio_drv.pio_rd(address, rd_data); | |
565 | } | |
566 | ||
567 | task CMacTxPort :: Rd_Txc_SF_Data3(var bit [63:0] rd_data) { | |
568 | bit [39:0] address; | |
569 | address = TXC_FZC_BASE + (TXC_SF_DATA3 + port_offset); | |
570 | gen_pio_drv.pio_rd(address, rd_data); | |
571 | } | |
572 | ||
573 | task CMacTxPort :: Rd_Txc_SF_Data4(var bit [63:0] rd_data) { | |
574 | bit [39:0] address; | |
575 | address = TXC_FZC_BASE + (TXC_SF_DATA4 + port_offset); | |
576 | gen_pio_drv.pio_rd(address, rd_data); | |
577 | } | |
578 | ||
579 | //### txc tid register read & write | |
580 | ||
581 | task CMacTxPort :: Wr_Txc_RO_Tids(bit [63:0] wr_data) { | |
582 | bit [39:0] address; | |
583 | address = TXC_FZC_BASE + (TXC_RO_TIDS + port_offset); | |
584 | gen_pio_drv.pio_wr(address,wr_data); | |
585 | } | |
586 | ||
587 | task CMacTxPort :: Wr_Txc_RO_State0(bit [63:0] wr_data){ | |
588 | bit [39:0] address; | |
589 | address = TXC_FZC_BASE + (TXC_RO_STATE0 + port_offset); | |
590 | gen_pio_drv.pio_wr(address,wr_data); | |
591 | } | |
592 | ||
593 | task CMacTxPort :: Wr_Txc_RO_State1(bit [63:0] wr_data){ | |
594 | bit [39:0] address; | |
595 | address = TXC_FZC_BASE + (TXC_RO_STATE1 + port_offset); | |
596 | gen_pio_drv.pio_wr(address,wr_data); | |
597 | } | |
598 | ||
599 | task CMacTxPort :: Wr_Txc_RO_State2(bit [63:0] wr_data){ | |
600 | bit [39:0] address; | |
601 | address = TXC_FZC_BASE + (TXC_RO_STATE2 + port_offset); | |
602 | gen_pio_drv.pio_wr(address,wr_data); | |
603 | } | |
604 | ||
605 | task CMacTxPort :: Wr_Txc_RO_State3(bit [63:0] wr_data){ | |
606 | bit [39:0] address; | |
607 | address = TXC_FZC_BASE + (TXC_RO_STATE3 + port_offset); | |
608 | gen_pio_drv.pio_wr(address,wr_data); | |
609 | } | |
610 | ||
611 | task CMacTxPort :: Rd_Txc_RO_Tids(var bit [63:0] rd_data) { | |
612 | bit [39:0] address; | |
613 | address = TXC_FZC_BASE + (TXC_RO_TIDS + port_offset); | |
614 | gen_pio_drv.pio_rd(address, rd_data); | |
615 | } | |
616 | ||
617 | task CMacTxPort :: Rd_Txc_RO_State0(var bit [63:0] rd_data) { | |
618 | bit [39:0] address; | |
619 | address = TXC_FZC_BASE + (TXC_RO_STATE0 + port_offset); | |
620 | gen_pio_drv.pio_rd(address, rd_data); | |
621 | } | |
622 | ||
623 | task CMacTxPort :: Rd_Txc_RO_State1(var bit [63:0] rd_data) { | |
624 | bit [39:0] address; | |
625 | address = TXC_FZC_BASE + (TXC_RO_STATE1 + port_offset); | |
626 | gen_pio_drv.pio_rd(address, rd_data); | |
627 | } | |
628 | ||
629 | task CMacTxPort :: Rd_Txc_RO_State2(var bit [63:0] rd_data) { | |
630 | bit [39:0] address; | |
631 | address = TXC_FZC_BASE + (TXC_RO_STATE2 + port_offset); | |
632 | gen_pio_drv.pio_rd(address, rd_data); | |
633 | } | |
634 | ||
635 | task CMacTxPort :: Rd_Txc_RO_State3(var bit [63:0] rd_data) { | |
636 | bit [39:0] address; | |
637 | address = TXC_FZC_BASE + (TXC_RO_STATE3 + port_offset); | |
638 | gen_pio_drv.pio_rd(address, rd_data); | |
639 | } | |
640 | ||
641 | task CMacTxPort :: Wr_Txc_Intr_Mask(bit[63:0] data) { | |
642 | bit [63:0] address; | |
643 | address = TXC_FZC_BASE + TXC_INT_MASK; | |
644 | gen_pio_drv.pio_wr(address, data); | |
645 | } | |
646 | ||
647 | task CMacTxPort :: Rd_Txc_Intr_Stat(var bit[63:0] rd_data) { | |
648 | ||
649 | bit [63:0] address; | |
650 | ||
651 | address = TXC_FZC_BASE + TXC_INT_STAT; | |
652 | gen_pio_drv.pio_rd(address, rd_data); | |
653 | } | |
654 | ||
655 | task CMacTxPort :: Wr_Txc_Intr_Stat(bit [63:0] data) { | |
656 | ||
657 | bit [63:0] address; | |
658 | ||
659 | address = TXC_FZC_BASE + TXC_INT_STAT; | |
660 | gen_pio_drv.pio_wr(address, data); | |
661 | } | |
662 | ||
663 | ||
664 | ||
665 | ||
666 | task CMacTxPort::pollLatchActive(txc_port_drr port_bind) { | |
667 | CTxDrrTr drr_trigger; | |
668 | ||
669 | #ifndef RXC_SAT | |
670 | while(1) { | |
671 | while(~port_bind.$latch_activedma){ | |
672 | @(posedge port_bind.$clk); | |
673 | } | |
674 | @(posedge port_bind.$clk); | |
675 | drr_trigger = new(); | |
676 | drr_trigger.LatchActiveSeen = 1; | |
677 | drr_trigger.activeList = port_bind.$activeListDMA; | |
678 | mailbox_put(mbox_id.niu_txdrr[id] , drr_trigger); | |
679 | @(posedge port_bind.$clk); | |
680 | ||
681 | } | |
682 | #endif | |
683 | } | |
684 | task CMacTxPort::SnapShotDMAs( bit[31:0] ActiveListSnapShot) { | |
685 | integer i; | |
686 | integer status; | |
687 | ||
688 | for(i=0;i<32;i++) { | |
689 | if(ActiveListSnapShot[i]) { | |
690 | dma[i].SnapShotDRRState(); | |
691 | ||
692 | if (get_plus_arg(CHECK,"RAND_KMCD")) { | |
693 | if(dma[i].list_empty) { | |
694 | status = dma[i].enableTokens(dma[i].lkick_data); | |
695 | dma[i].start = 0; | |
696 | } | |
697 | } | |
698 | } | |
699 | } | |
700 | } | |
701 | ||
702 | task CMacTxPort::LoadDMAStates( bit[31:0] ActiveListSnapShot) { | |
703 | integer i; | |
704 | for(i=0;i<32;i++) { | |
705 | if(ActiveListSnapShot[i]) | |
706 | dma[i].LoadDRRState(); | |
707 | } | |
708 | } | |
709 | task CMacTxPort::PullTokensBack( bit[31:0] list) { | |
710 | integer i; | |
711 | integer empty; | |
712 | CTxToken TxToken; | |
713 | integer dmas_updated[32]; | |
714 | bit[31:0] dmas_touched; | |
715 | ||
716 | ||
717 | dmas_touched = 0; | |
718 | ||
719 | printf("CMacTxPort::PullTokensBack Start - Time - %d \n",TIME); | |
720 | empty = TxPortCbMgr.PullPortTokenList(TxToken); | |
721 | while(empty==1) { | |
722 | if ( ( list[TxToken.dma_num] ==1)) { | |
723 | dmas_updated[TxToken.dma_num] = TxToken.current_deficit; | |
724 | dmas_touched[TxToken.dma_num] = 1; | |
725 | printf("DEBUG trans_id PullTokensBack DMA- %d Address - %x Deficit - %d \n",TxToken.dma_num,TxToken.xlate_gather_address[0],TxToken.current_deficit); | |
726 | } | |
727 | dma[TxToken.dma_num].push_back_token(TxToken); | |
728 | empty = TxPortCbMgr.PullPortTokenList(TxToken); | |
729 | //@(posedge CLOCK); | |
730 | } | |
731 | printf("CMacTxPort::PullTokensBack End - Time - %d \n",TIME); | |
732 | for(i=0;i<32;i++) { | |
733 | if(list[i] & dmas_touched[i]) { | |
734 | printf("Setting DMA - %d defict to %d \n",i,dmas_updated[i]); | |
735 | dma[i].current_deficit = dmas_updated[i]; | |
736 | } | |
737 | } | |
738 | ||
739 | } | |
740 | task CMacTxPort::DRR(txc_port_drr port_bind) { | |
741 | ||
742 | ||
743 | // from a list of active DMAs sort through the TxTokenList - and generate appropriate | |
744 | // tokens for the packet checker | |
745 | ||
746 | integer arb_id,old_arb_id; | |
747 | integer dmas_active; | |
748 | integer total_dmas_active; | |
749 | integer i,match_found; | |
750 | integer iter; | |
751 | integer status; | |
752 | integer maintain_active_state; | |
753 | integer dma_id,length; | |
754 | CTxToken TxToken; | |
755 | CRxToken RxToken; // FOR MAC LOOP BACK MODE | |
756 | integer debug_count; | |
757 | bit [31:0] ActiveListFromHardware; | |
758 | bit [31:0] ActiveListFromHardware_old = 32'h0; | |
759 | bit [31:0] deficit_list = 32'h0; | |
760 | integer dma_deficit_list =0; | |
761 | integer all_dmas_deficit = 1; | |
762 | bit start_sim = 0; | |
763 | ||
764 | // For Random Kicks | |
765 | bit [31:0] ActiveListSnapShot; | |
766 | integer old_arb_idSnapShot; | |
767 | CTxDrrTr drr_trigger; | |
768 | integer no_of_entries; | |
769 | integer NewKickDMA; | |
770 | integer NewKickSeen; | |
771 | integer LatchActiveSeen; | |
772 | integer LatchActiveSeenFirstTime; | |
773 | integer no_of_dmas_eoflist; | |
774 | integer got_new_kick; | |
775 | LatchActiveSeenFirstTime = 0; | |
776 | ||
777 | // allocate memory for port0 mailbox | |
778 | if(mbox_id.mac_opp[this.id] == -1) { | |
779 | // Alocate Mailbox | |
780 | mbox_id.mac_opp[this.id] = alloc(MAILBOX,0,1); | |
781 | // Check if we were succesfull allocating the mailbox | |
782 | if(mbox_id.mac_opp[this.id] == 0) { | |
783 | printf("ERROR Could not allocate the outgoing mailbox port %d \n",this.id); | |
784 | mbox_id.mac_opp[this.id] = -1; | |
785 | return; | |
786 | } | |
787 | } | |
788 | ||
789 | ||
790 | @(posedge port_bind.$clk); | |
791 | @(posedge port_bind.$clk); | |
792 | @(posedge port_bind.$clk); | |
793 | @(posedge port_bind.$clk); | |
794 | old_arb_id = 0; | |
795 | debug_count = 0; | |
796 | ||
797 | fork { | |
798 | pollLatchActive(port_bind); | |
799 | } join none | |
800 | ||
801 | while(1) { | |
802 | debug_count ++; | |
803 | ||
804 | // wait for some conditions - initial version look for latch enable | |
805 | // for all active DMAs, add credits | |
806 | ||
807 | /* | |
808 | There are two ways to evaluate this | |
809 | 1. LatchActive is Seen | |
810 | 2. New Kick is Set | |
811 | If both happens at the same time, LatchActive takes precedence for now | |
812 | 3. Any Kicks before the first LatchActive will also not trigger this | |
813 | ||
814 | */ | |
815 | ||
816 | printf(" Before mailbox_get Time - %d \n",TIME); | |
817 | no_of_entries = mailbox_get(WAIT,mbox_id.niu_txdrr[id],drr_trigger); | |
818 | printf(" After mailbox_get Time - %d \n",TIME); | |
819 | LatchActiveSeen = drr_trigger.LatchActiveSeen; | |
820 | NewKickSeen = drr_trigger.NewKickSeen; | |
821 | NewKickDMA = drr_trigger.NewKickDMA; | |
822 | ActiveListFromHardware = drr_trigger.activeList; | |
823 | ||
824 | if(NewKickSeen & LatchActiveSeenFirstTime & (LatchActiveSeen==0)) { | |
825 | printf("LOCK Time - %d \n",TIME); | |
826 | trigger(OFF,TxPortCbMgr.lock_port_queue); | |
827 | } | |
828 | if(LatchActiveSeen) { | |
829 | // Take SnapShot of the current State and Store this | |
830 | printf("DRR DEBUG ActiveList from Hardware - %x From Verif Model - %x \n",ActiveListFromHardware,OrigDMAActiveList); | |
831 | ActiveListSnapShot = ActiveListFromHardware; | |
832 | printf("DRR DEBUG ActiveListSnapShot - %x From Verif Model - %x \n",ActiveListSnapShot,OrigDMAActiveList); | |
833 | // SnapShot All the Contexts | |
834 | old_arb_idSnapShot = old_arb_id; | |
835 | SnapShotDMAs(ActiveListSnapShot); | |
836 | LatchActiveSeenFirstTime = 1; | |
837 | TxPortCbMgr.FreezeCurrentTokenList(); | |
838 | ||
839 | ActiveListFromHardware_old = ActiveListFromHardware; | |
840 | } else if(NewKickSeen & LatchActiveSeenFirstTime) { | |
841 | ActiveListFromHardware = ActiveListSnapShot; | |
842 | printf("New KICK Seen\n"); | |
843 | // StoreBack All the old Contexts | |
844 | old_arb_id= old_arb_idSnapShot; | |
845 | // LoadDMAStates(ActiveListSnapShot); | |
846 | printf("DRR DEBUG ActiveListSnapShot - %x From Verif Model - %x \n",ActiveListSnapShot,OrigDMAActiveList); | |
847 | PullTokensBack(ActiveListSnapShot); | |
848 | printf("DRR DEBUG Restart DRR - Time - %d \n",TIME); | |
849 | ||
850 | ||
851 | } | |
852 | ||
853 | if(LatchActiveSeenFirstTime==0) { | |
854 | ActiveListFromHardware = 0; | |
855 | printf("First KICK Seen\n"); | |
856 | } | |
857 | //@(posedge port_bind.$clk); | |
858 | ||
859 | ||
860 | if(ActiveListFromHardware!==OrigDMAActiveList) { | |
861 | printf(" DRR DEBUG - Warning - Changing Verif List to - %d !! \n",ActiveListFromHardware); | |
862 | } else { | |
863 | printf(" DRR DEBUG - Active Lists Match -!! \n"); | |
864 | } | |
865 | DMAActiveList = ActiveListFromHardware; | |
866 | ||
867 | dmas_active = 0; | |
868 | ||
869 | ||
870 | for(i = 0; i < 32; i ++) { | |
871 | if(DMAActiveList[i] ) { | |
872 | // added code for using cache model | |
873 | // checktoken_valid | |
874 | ||
875 | if (get_plus_arg(CHECK,"WCACHE_MODEL")) { | |
876 | if(dma[i].checkTokenHeadValid_from_Mcache()) { | |
877 | dmas_active = ( dmas_active | ( 1<< i )); | |
878 | if(NewKickSeen & LatchActiveSeenFirstTime) { | |
879 | printf("SKIP CREDITS ADDITIONS at time %d\n",{get_time(HI), get_time(LO)}); | |
880 | } else { | |
881 | if(all_dmas_deficit) { | |
882 | dma[i].add_drr_credits(); | |
883 | printf("DRR_DEBUG ADDED CREDITS at time %d\n",{get_time(HI), get_time(LO)}); | |
884 | } | |
885 | } | |
886 | } else printf(" WCACHE_MODEL TokenList Empty\n"); | |
887 | } else { | |
888 | if(dma[i].checkTokenHeadValid()) { | |
889 | dmas_active = ( dmas_active | ( 1<< i )); | |
890 | if(NewKickSeen & LatchActiveSeenFirstTime) { | |
891 | printf("SKIP CREDITS ADDITIONS at time %d\n",{get_time(HI), get_time(LO)}); | |
892 | } else { | |
893 | if(all_dmas_deficit) { | |
894 | dma[i].add_drr_credits(); | |
895 | printf("DRR_DEBUG ADDED CREDITS at time %d\n",{get_time(HI), get_time(LO)}); | |
896 | } | |
897 | } | |
898 | } else printf("TokenList Empty\n"); | |
899 | } | |
900 | } | |
901 | } | |
902 | ||
903 | ||
904 | printf("DRR DEBUG -Active list - %x Time - %d \n",dmas_active,{get_time(HI), get_time(LO)}); | |
905 | while(dmas_active) { | |
906 | ||
907 | printf("DRR DEBUG Restart DRR - Time - %d \n",TIME); | |
908 | arb_id = old_arb_id ; | |
909 | ||
910 | dma_id = -1; | |
911 | match_found =0; | |
912 | iter =0; | |
913 | ||
914 | while( (iter <32 /*MAX_NO_OF_DMAS*/) & ( !match_found)) { | |
915 | // printf(" DRR DEBUG arb_id - %x dmas_active - %x \n",arb_id,dmas_active); | |
916 | if(check_active(arb_id,dmas_active)) { | |
917 | printf(" DRR DEBUG MATCHED arb_id - %x dmas_active - %x \n",arb_id,dmas_active); | |
918 | dma_id = arb_id; | |
919 | match_found = 1; | |
920 | } | |
921 | arb_id = (arb_id + 1)%32; | |
922 | iter++; | |
923 | } // At the end of this there should be at least one dma_id selected | |
924 | ||
925 | if( (dma_id == -1) ) { | |
926 | printf("DRR DEBUG Error in the code -- FIX IT \n"); | |
927 | return; | |
928 | } | |
929 | ||
930 | ||
931 | if (get_plus_arg(CHECK,"WCACHE_MODEL")) | |
932 | status = dma[dma_id].get_current_token_from_Mcache(TxToken); | |
933 | else | |
934 | status = dma[dma_id].get_current_token(TxToken); | |
935 | ||
936 | /* TODO | |
937 | if the token is valid then only send it across, else do nothing | |
938 | ||
939 | The status above indicates the following | |
940 | - EOL reached or not | |
941 | - any error associated with this packet | |
942 | - if the dma hasnt been kicked | |
943 | ||
944 | */ | |
945 | ||
946 | maintain_active_state = 1; | |
947 | if(status == -1) { | |
948 | printf(" DRR DEBUG descriptor either not initialised or packet in the descriptor not kicked DMA = %d \n",dma_id); | |
949 | maintain_active_state = 0; | |
950 | } else { | |
951 | if(dma[dma_id].current_deficit > 0) { | |
952 | length = TxToken.pkt_length + 16; | |
953 | TxToken.current_deficit = dma[dma_id].current_deficit; | |
954 | ||
955 | maintain_active_state = dma[dma_id].update_deficit(length); // | |
956 | printf("DRR DEBUG Sending data for channel #%d length = %d New Deficit = %d \n",dma_id,length,dma[dma_id].current_deficit); | |
957 | printf("DRR DEBUG Sending Token %d for channel #%d length = %d descriptor address - %x \n",TxToken.id,dma_id,length,TxToken.descriptor_address); | |
958 | printf("DEBUG trans_id Sending Token %d for channel #%d length = %d packet_Addres - %x Deficit - %d \n",TxToken.id,dma_id,length,TxToken.xlate_gather_address[0],TxToken.current_deficit); | |
959 | ||
960 | if (get_plus_arg(CHECK,"WCACHE_MODEL")) | |
961 | dma[dma_id].M_TxTokenList.pop_front(); | |
962 | else | |
963 | dma[dma_id].TxTokenList.pop_front(); | |
964 | ||
965 | if(dma[dma_id].conf_part_err_seen) { | |
966 | printf(" Tx Token id - %d Error Set - Packet to be dropped !!!! \n",TxToken.id); | |
967 | } else if((TxToken.error_info.hosterrors.packet_errors == PKT_PART_ERROR)|(dma[dma_id].pkt_part_err_seen )){ | |
968 | dma[dma_id].pkt_part_err_seen = 1; | |
969 | ||
970 | printf(" Tx Token id - %d Error Set - Packet to be dropped !!!! \n",TxToken.id); | |
971 | } else { | |
972 | dma[dma_id].incPktCnt(); | |
973 | if(USE_CALL_BACKS) { | |
974 | TxPortCbMgr.CheckReqCbs(TxToken); | |
975 | TxPortCbMgr.pushToPortTokenList(TxToken); | |
976 | } else { | |
977 | TxPortCbMgr.CheckReqCbs(TxToken); | |
978 | mailbox_put(mbox_id.mac_opp[this.id],TxToken.pgToken); | |
979 | } | |
980 | printf("DRR_DEBUG Token_id %0d sent to end_chkr at time %d\n",TxToken.id,{get_time(HI),get_time(LO)}); | |
981 | ||
982 | if(MAC_LOOP_BACK_MODE[this.id]) { | |
983 | // Send the packet to Rx Token List | |
984 | RxToken = new(); | |
985 | RxToken.id=TxToken.pgToken.gId; | |
986 | RxToken.pkt_length = TxToken.pkt_length + 4 ; | |
987 | RxToken.pgToken = TxToken.pgToken.object_copy(); | |
988 | RxToken.pgToken.pack_db.flow.partial_chksum = 0; | |
989 | RxToken.dma_num=TxToken.loop_back_rxdma_num; | |
990 | RxToken.last_packet=TxToken.loop_back_rx_lastpacket; | |
991 | RxToken.port_num=this.id; | |
992 | mailbox_put(mbox_id.niu_rxpath_mb[RxToken.port_num],RxToken); | |
993 | printf("Tx DRR_DEBUG Token_id %0d sent to Rx DRR Loop Back Mode at time %d\n",TxToken.id,{get_time(HI),get_time(LO)}); | |
994 | } else if(EXT_LOOPBACK_DST != -1 ) { | |
995 | // Send the packet to Rx Token List | |
996 | RxToken = new(); | |
997 | RxToken.id=TxToken.pgToken.gId; | |
998 | RxToken.pkt_length = TxToken.pkt_length + 4 ; | |
999 | RxToken.pgToken = TxToken.pgToken.object_copy(); | |
1000 | RxToken.pgToken.pack_db.flow.partial_chksum = 0; | |
1001 | RxToken.dma_num= EXT_LOOPBACK_DST; | |
1002 | //RxToken.dma_num=TxToken.loop_back_rxdma_num; | |
1003 | RxToken.last_packet=TxToken.loop_back_rx_lastpacket; | |
1004 | RxToken.port_num= EXT_LOOPBACK_DST; | |
1005 | mailbox_put(mbox_id.niu_rxpath_mb[RxToken.port_num], RxToken); | |
1006 | printf("MaxTxPort%0d Token_id=%0d sent to Rx Ext loopback port=%0d dma=%0d time=%0d\n", this.id, TxToken.id, RxToken.port_num, RxToken.dma_num, TIME); | |
1007 | ||
1008 | } | |
1009 | } // end elseif error_set | |
1010 | ||
1011 | } else { | |
1012 | maintain_active_state = 0; | |
1013 | printf("DRR DEBUG DMA# %d In deficit Need more credit \n",dma_id); | |
1014 | } | |
1015 | } | |
1016 | ||
1017 | // int status = DMA[dma_id]->update_descriptor(); | |
1018 | ||
1019 | ||
1020 | if (get_plus_arg(CHECK,"WCACHE_MODEL")) | |
1021 | status = dma[dma_id].get_current_token_from_Mcache(TxToken); | |
1022 | else | |
1023 | status = dma[dma_id].get_current_token(TxToken); | |
1024 | ||
1025 | if(status == -1) { | |
1026 | // EOL Reached | |
1027 | // dma[dma_id].current_deficit_old = dma[dma_id].current_deficit; | |
1028 | // dma[dma_id].current_deficit = 0; | |
1029 | // deficit_list[dma_id] = 1'b1; | |
1030 | } | |
1031 | ||
1032 | status = 1; | |
1033 | if(status==0) { // delete the DMA from the active list | |
1034 | dmas_active = dmas_active ^ ( 1 << dma_id ); | |
1035 | maintain_active_state = 0; | |
1036 | printf("DRR DEBUG Deleting Channel #%d from Active List due to descriptor errors \n",dma_id); | |
1037 | } | |
1038 | ||
1039 | if(maintain_active_state==0) { | |
1040 | printf(" DRR DEBUG - Before deleting dmas_active = %x \n",dmas_active); | |
1041 | dmas_active = dmas_active ^ ( 1 << dma_id ); | |
1042 | printf("DRR DEBUG Deleting Channel #%d from Active List: Channel Id %d has -ve Deficit= %d \n",dma_id,dma_id,dma[dma_id].current_deficit); | |
1043 | // deficit_list[dma_id] = 1'b1; | |
1044 | printf(" DRR DEBUG - After deleting dmas_active = %x \n",dmas_active); | |
1045 | old_arb_id = (dma_id + 1) %32 ; | |
1046 | } | |
1047 | } | |
1048 | // @(posedge CLOCK); | |
1049 | // @(posedge port_bind.$clk); | |
1050 | ||
1051 | printf(" DRR DEBUG Resetting old_arb_id to 0 Time - %d \n",{get_time(HI), get_time(LO)}); | |
1052 | old_arb_id = 0; | |
1053 | printf(" DRR DEBUG done with DRR Time - %d list - %x \n", {get_time(HI), get_time(LO)},dmas_active); | |
1054 | ||
1055 | ||
1056 | dma_deficit_list=0; | |
1057 | total_dmas_active = 0; | |
1058 | deficit_list = 0; | |
1059 | for(i=0;i<32;i++) { | |
1060 | if(ActiveListFromHardware[i] && (dma[i]!=null)) { | |
1061 | total_dmas_active++; | |
1062 | if(dma[i].current_deficit <=0) { | |
1063 | dma_deficit_list++; | |
1064 | deficit_list[i] = 1'b1; | |
1065 | printf("DRR DEBUG Before Add Credit - dma - %d in defict, Total - %d \n",i,dma_deficit_list); | |
1066 | } | |
1067 | } | |
1068 | } | |
1069 | ||
1070 | ||
1071 | ||
1072 | no_of_dmas_eoflist=0; | |
1073 | ||
1074 | if(NewKickSeen & LatchActiveSeenFirstTime & (LatchActiveSeen==0)) { | |
1075 | // unlock the queue | |
1076 | printf("UNLOCK Time - %d \n",TIME); | |
1077 | trigger(ON,TxPortCbMgr.lock_port_queue); | |
1078 | } | |
1079 | ||
1080 | if(1){ | |
1081 | // All of these gets processed when clr_eoflist signal comes | |
1082 | // if a new kick is seen then this need not be executed | |
1083 | got_new_kick = wait_for_addcredit(port_bind); | |
1084 | if(got_new_kick) { | |
1085 | printf("Exiting wait_for_addcredit because of new kick Time - %d \n",TIME); | |
1086 | } else { | |
1087 | for(i=0;i<32;i++) { | |
1088 | if(OrigDMAActiveList[i]) { | |
1089 | if(( total_dmas_active==1)&& ( port_bind.$eoflist[i] )) { | |
1090 | dma[i].current_deficit = 0; | |
1091 | if(deficit_list[i]==1'b0) { | |
1092 | no_of_dmas_eoflist++; | |
1093 | } | |
1094 | dma[i].add_drr_credits(); | |
1095 | printf("Resetting the deficit for DMA_ID %d total_dmas = %d \n",i,total_dmas_active); | |
1096 | /*FIX } else if(port_bind.$eoflist[i] && (dma[i].current_deficit <0) ){*/ | |
1097 | /* Seems like RTL clears defict regardless of the current defict.. Check with Rahoul*/ | |
1098 | } else if(port_bind.$eoflist[i] ){ | |
1099 | dma[i].current_deficit = 0; | |
1100 | if(deficit_list[i]==1'b0) { | |
1101 | no_of_dmas_eoflist++; | |
1102 | } | |
1103 | dma[i].add_drr_credits(); | |
1104 | printf("Resetting the deficit for DMA_ID %d total_dmas = %d \n",i,total_dmas_active); | |
1105 | } | |
1106 | } | |
1107 | } | |
1108 | dma_deficit_list = dma_deficit_list+no_of_dmas_eoflist; | |
1109 | all_dmas_deficit = ((dma_deficit_list>=total_dmas_active)|| ( total_dmas_active==1)) ; | |
1110 | printf("DRR DEBUG : val of dma_deficit_list %0d\n",dma_deficit_list); | |
1111 | printf("DRR DEBUG : val of total_dmas_active %0d at time 0%d\n",total_dmas_active,{get_time(HI),get_time(LO)}); | |
1112 | } | |
1113 | } | |
1114 | ||
1115 | ||
1116 | } | |
1117 | ||
1118 | } | |
1119 | ||
1120 | function integer CMacTxPort :: wait_for_addcredit(txc_port_drr port_bind) | |
1121 | { | |
1122 | ||
1123 | integer no_of_entries,got_new_kick; | |
1124 | CTxDrrTr drr_trigger; | |
1125 | ||
1126 | got_new_kick =0; | |
1127 | fork { | |
1128 | no_of_entries = mailbox_get(COPY_WAIT,mbox_id.niu_txdrr[id],drr_trigger); | |
1129 | if(drr_trigger.NewKickSeen) { | |
1130 | got_new_kick = 1; | |
1131 | } else got_new_kick = 0; | |
1132 | } | |
1133 | { | |
1134 | @(posedge port_bind.$clr_eoflist); | |
1135 | printf("GOT TXC_ADD_CREDIT\n"); | |
1136 | got_new_kick = 0; | |
1137 | } | |
1138 | join any | |
1139 | wait_for_addcredit = got_new_kick; | |
1140 | } | |
1141 | ||
1142 | task CMacTxPort :: check_pkt_cnt (integer no_of_pkts, (integer timeout_count = 100),(integer chk_type = 0)) { | |
1143 | ||
1144 | integer no_ofpkts_toprt = 0; | |
1145 | integer rtl_tot_pkcnt; | |
1146 | integer all_pkts_done = 0; | |
1147 | integer timeout_cnt = 0; | |
1148 | integer prev_rtl_pkt_cnt = 0; | |
1149 | ||
1150 | bit [39:0] address; | |
1151 | bit [63:0] r_data; | |
1152 | ||
1153 | address = TXC_FZC_BASE+ (TXC_PKT_XMIT + port_offset); | |
1154 | no_ofpkts_toprt = get_allpkts_toport(no_of_pkts); | |
1155 | printf("Total_expected_pkts %d from Port %d\n",no_ofpkts_toprt,this.id); | |
1156 | ||
1157 | while(!all_pkts_done) { | |
1158 | repeat (timeout_count) @(posedge CLOCK); | |
1159 | gen_pio_drv.pio_rd(address,r_data); | |
1160 | rtl_tot_pkcnt = r_data[15:0]; | |
1161 | ||
1162 | if(chk_type == 0) { | |
1163 | if(rtl_tot_pkcnt == no_ofpkts_toprt) { | |
1164 | all_pkts_done = 1; | |
1165 | trigger(ON,TX_rvcd_allpkts[id]); | |
1166 | be_msg.print(e_mesg_info,"niu_tx_port","chk_pkt_cnt","All pkts_rvcd at Port %0d\n", id); | |
1167 | } else { | |
1168 | if((timeout_cnt > 1000) && (prev_rtl_pkt_cnt == rtl_tot_pkcnt)) { | |
1169 | all_pkts_done = 1; | |
1170 | trigger(ON,TX_rvcd_allpkts[id]); | |
1171 | be_msg.print(e_mesg_error,"niu_tx_port","chk_pkt_cnt","No change In pkt_cnt for 10000 clocks for Port %0d\n", id); | |
1172 | } else { | |
1173 | if(prev_rtl_pkt_cnt == rtl_tot_pkcnt) { | |
1174 | timeout_cnt++; | |
1175 | } else { | |
1176 | timeout_cnt = 0; | |
1177 | } | |
1178 | prev_rtl_pkt_cnt = rtl_tot_pkcnt; | |
1179 | } | |
1180 | ||
1181 | } | |
1182 | } else { | |
1183 | if(rtl_tot_pkcnt >= no_ofpkts_toprt) { | |
1184 | all_pkts_done = 1; | |
1185 | trigger(ON,TX_rvcd_allpkts[id]); | |
1186 | be_msg.print(e_mesg_info,"niu_tx_port","chk_pkt_cnt","All pkts_rvcd at Port %0d\n", id); | |
1187 | } else { | |
1188 | if((timeout_cnt > 100) && (prev_rtl_pkt_cnt == rtl_tot_pkcnt)) { | |
1189 | all_pkts_done = 1; | |
1190 | trigger(ON,TX_rvcd_allpkts[id]); | |
1191 | be_msg.print(e_mesg_error,"niu_tx_port","chk_pkt_cnt","No change In pkt_cnt for 10000 clocks for Port %0d\n", id); | |
1192 | } else { | |
1193 | if(prev_rtl_pkt_cnt == rtl_tot_pkcnt) { | |
1194 | timeout_cnt++; | |
1195 | } else { | |
1196 | timeout_cnt = 0; | |
1197 | } | |
1198 | prev_rtl_pkt_cnt = rtl_tot_pkcnt; | |
1199 | } | |
1200 | ||
1201 | } | |
1202 | } | |
1203 | } | |
1204 | ||
1205 | if(get_plus_arg (CHECK, "MAC_SPEED0=100")) | |
1206 | repeat (10000) @(posedge CLOCK); | |
1207 | else if(get_plus_arg (CHECK, "MAC_SPEED0=10")) | |
1208 | repeat (60000) @(posedge CLOCK); | |
1209 | else | |
1210 | repeat (2000) @(posedge CLOCK); | |
1211 | ||
1212 | // using a plus arg to turn this on | |
1213 | ||
1214 | if( get_plus_arg(CHECK,"ENB_TXEXIT_RT")) { | |
1215 | ||
1216 | // check for pks stuffed in RE-ORDER fifo & Packets proccessed in PKT_ASSEMBLY | |
1217 | check_pkts_stuffed(no_of_pkts); | |
1218 | ||
1219 | // check pkt count for each DMA | |
1220 | check_pkt_cnt_perdma(no_of_pkts); | |
1221 | ||
1222 | // check mac tx frame cnt | |
1223 | check_mac_txfrmcnt(no_ofpkts_toprt); | |
1224 | } | |
1225 | ||
1226 | } | |
1227 | ||
1228 | //--- task to get check number of pkts on each port | |
1229 | //--- random number of pkts per DMA channel | |
1230 | ||
1231 | task CMacTxPort :: check_randompkt_cnt (integer no_of_pkts[24], (integer timeout_count = 100)) { | |
1232 | ||
1233 | integer no_ofpkts_toprt = 0; | |
1234 | integer rtl_tot_pkcnt; | |
1235 | integer all_pkts_done = 0; | |
1236 | integer timeout_cnt = 0; | |
1237 | integer prev_rtl_pkt_cnt = 0; | |
1238 | ||
1239 | bit [39:0] address; | |
1240 | bit [63:0] r_data; | |
1241 | ||
1242 | address = TXC_FZC_BASE+ (TXC_PKT_XMIT + port_offset); | |
1243 | no_ofpkts_toprt = get_allpkts_toport_random(no_of_pkts); | |
1244 | // printf("TOT_PKT_CNT %0d\n",no_ofpkts_toprt); | |
1245 | printf("Total_expected_pkts %d from Port %d\n",no_ofpkts_toprt,this.id); | |
1246 | ||
1247 | while(!all_pkts_done) { | |
1248 | repeat (timeout_count) @(posedge CLOCK); | |
1249 | gen_pio_drv.pio_rd(address,r_data); | |
1250 | rtl_tot_pkcnt = r_data[15:0]; | |
1251 | ||
1252 | if(rtl_tot_pkcnt == no_ofpkts_toprt) { | |
1253 | all_pkts_done = 1; | |
1254 | trigger(ON,TX_rvcd_allpkts[id]); | |
1255 | be_msg.print(e_mesg_info,"niu_tx_port","chk_pkt_cnt","All pkts_rvcd at Port %0d\n", id); | |
1256 | } else { | |
1257 | if((timeout_cnt > 100) && (prev_rtl_pkt_cnt == rtl_tot_pkcnt)) { | |
1258 | all_pkts_done = 1; | |
1259 | trigger(ON,TX_rvcd_allpkts[id]); | |
1260 | be_msg.print(e_mesg_error,"niu_tx_port","chk_pkt_cnt","No change In pkt_cnt for 10000 clocks for Port %0d\n", id); | |
1261 | } else { | |
1262 | if(prev_rtl_pkt_cnt == rtl_tot_pkcnt) { | |
1263 | timeout_cnt++; | |
1264 | } else { | |
1265 | timeout_cnt = 0; | |
1266 | } | |
1267 | prev_rtl_pkt_cnt = rtl_tot_pkcnt; | |
1268 | } | |
1269 | ||
1270 | } | |
1271 | } | |
1272 | ||
1273 | repeat (2000) @(posedge CLOCK); | |
1274 | ||
1275 | } | |
1276 | ||
1277 | ||
1278 | //-- Calculte the number of pkts to port | |
1279 | //-- Number of pkts per DMA are same | |
1280 | ||
1281 | function integer CMacTxPort :: get_allpkts_toport (integer no_of_pkts) { | |
1282 | ||
1283 | integer i; | |
1284 | integer t_no_of_pkts = 0; | |
1285 | ||
1286 | for(i = 0; i < 24; i ++) { | |
1287 | if(OrigDMAActiveList[i]) { | |
1288 | t_no_of_pkts = t_no_of_pkts + no_of_pkts; | |
1289 | // printf("TOT_PKTS %0d\n",t_no_of_pkts); | |
1290 | } | |
1291 | } | |
1292 | ||
1293 | get_allpkts_toport = t_no_of_pkts; | |
1294 | } | |
1295 | ||
1296 | ||
1297 | //-- Calculte the number of pkts to port | |
1298 | //-- Number of pkts per DMA are same | |
1299 | ||
1300 | function integer CMacTxPort :: get_allpkts_toport_random (integer no_of_pkts[24]) { | |
1301 | ||
1302 | integer i; | |
1303 | integer t_no_of_pkts = 0; | |
1304 | ||
1305 | for(i = 0; i < 24; i ++) { | |
1306 | if(OrigDMAActiveList[i]) { | |
1307 | t_no_of_pkts = t_no_of_pkts + no_of_pkts[i]; | |
1308 | // printf("TOT_PKTS %0d\n",t_no_of_pkts); | |
1309 | } | |
1310 | } | |
1311 | ||
1312 | get_allpkts_toport_random = t_no_of_pkts; | |
1313 | } | |
1314 | ||
1315 | ||
1316 | task CMacTxPort::check_pkt_cnt_perdma (integer no_of_pkts) { | |
1317 | ||
1318 | integer i = 0; | |
1319 | bit [63:0] rd_data; | |
1320 | bit [63:0] hd_ptr; | |
1321 | bit [63:0] tail_ptr; | |
1322 | ||
1323 | for(i = 0; i < 24; i ++) { | |
1324 | if(OrigDMAActiveList[i]) { | |
1325 | dma[i].Read_TxCs(rd_data); | |
1326 | if(rd_data[59:48] != no_of_pkts) { | |
1327 | be_msg.print(e_mesg_error,"niu_tx_port","check_pkt_cnt_perdma","PKT_CNT MISMATCH for DMA_ID %d\n",i); | |
1328 | } | |
1329 | // read the head and tail and compare they should be equal | |
1330 | dma[i].RdTxRngHDL(hd_ptr); | |
1331 | @(posedge CLOCK); | |
1332 | dma[i].RdTxRngKick(tail_ptr); | |
1333 | if(hd_ptr[19:0] != tail_ptr[19:0]) { | |
1334 | be_msg.print(e_mesg_error,"niu_tx_port","check_pkt_cnt_perdma","HD & TAIL PTRs MISMATCH for DMA_ID %d\n",i); | |
1335 | } | |
1336 | } | |
1337 | } | |
1338 | } | |
1339 | ||
1340 | ||
1341 | task CMacTxPort::check_exit_status() { | |
1342 | ||
1343 | ||
1344 | // Tasks to look at the remaining tokens in the mailbox and determine the appropriate | |
1345 | // action to be taken | |
1346 | ||
1347 | integer no_of_tokens_remaining; | |
1348 | CpgToken pgToken; | |
1349 | integer i; | |
1350 | ||
1351 | if( get_plus_arg(CHECK,"BYPASS_TXDRR")) { | |
1352 | // do no checks of the mailbox, drr byppassed in this mode | |
1353 | } else { | |
1354 | printf(" DEBUG- Checking exit status for Tx port %d \n",id); | |
1355 | no_of_tokens_remaining = mailbox_get(NO_WAIT,mbox_id.mac_opp[id], pgToken); | |
1356 | if(no_of_tokens_remaining >0) { | |
1357 | printf("ERROR Not all tokens received by packetchecker at port %d \n",id); | |
1358 | printf("Pending Tokens not received by Packet Checker= %d \n",no_of_tokens_remaining); | |
1359 | be_msg.print(e_mesg_error, "","","ERROR Not all tokens received by packetchecker at port = %d\n",id); | |
1360 | ||
1361 | } | |
1362 | ||
1363 | for(i = 0; i < 32; i ++) { | |
1364 | if(OrigDMAActiveList[i]) { | |
1365 | if(dma[i].checkTokenHeadValid()) { | |
1366 | printf("ERROR Not all tokens sent to packetchecker at port %d for DMA # %d \n",id,i); | |
1367 | be_msg.print(e_mesg_error, "","","ERROR Not all tokens sent to packetchecker from DRR at port = %d\n",id); | |
1368 | } | |
1369 | } | |
1370 | } | |
1371 | } | |
1372 | } | |
1373 | ||
1374 | task CMacTxPort :: check_pkts_stuffed(integer no_of_pkts) { | |
1375 | ||
1376 | integer ro_pkts_num = 0; | |
1377 | integer pkt_ass_pkts_num = 0; | |
1378 | integer num_pkts_sent = 0; | |
1379 | ||
1380 | bit [39:0] address; | |
1381 | bit [63:0] r_data; | |
1382 | ||
1383 | address = TXC_FZC_BASE+ (TXC_PKT_STUFFED + port_offset); | |
1384 | gen_pio_drv.pio_rd(address,r_data); | |
1385 | ||
1386 | ro_pkts_num = r_data[31:16]; | |
1387 | pkt_ass_pkts_num = r_data[15:0]; | |
1388 | ||
1389 | num_pkts_sent = get_allpkts_toport(no_of_pkts); | |
1390 | ||
1391 | if(ro_pkts_num != num_pkts_sent) | |
1392 | be_msg.print(e_mesg_error,"CMacTxPort","check_pkts_stuffed","RO_fifo pkts stuffed check failed for port_id %d\n",this.id); | |
1393 | else | |
1394 | be_msg.print(e_mesg_info,"CMacTxPort","check_pkts_stuffed","RO_fifo pkts stuffed check passed for port_id %d\n",this.id); | |
1395 | ||
1396 | if( pkt_ass_pkts_num != num_pkts_sent) | |
1397 | be_msg.print(e_mesg_error,"CMacTxPort","check_pkts_stuffed","Pktassem_fifo pkts stuffed check failed for port_id %d\n",this.id); | |
1398 | else | |
1399 | be_msg.print(e_mesg_info,"CMacTxPort","check_pkts_stuffed","Pktassem_fifo pkts stuffed check passed for port_id %d\n",this.id); | |
1400 | ||
1401 | } | |
1402 | ||
1403 | task CMacTxPort :: check_mac_txfrmcnt(integer no_of_pkts) { | |
1404 | ||
1405 | bit [39:0] base_addr; | |
1406 | bit[31:0] rd_data, rd_status, rd_mask; | |
1407 | ||
1408 | base_addr = mac_util.get_mac_reg_base(this.id); | |
1409 | if((this.id == 0) || (this.id == 1)) | |
1410 | mac_pio_class.xmac_pio_rd(base_addr + TxMAC_FRM_CNT, rd_status, 1'b0); | |
1411 | else | |
1412 | mac_pio_class.xmac_pio_rd(base_addr + BTxMAC_FRM_CNT, rd_status, 1'b0); | |
1413 | ||
1414 | if(rd_data[20:0] != no_of_pkts) | |
1415 | be_msg.print(e_mesg_error,"CMacTxPort","check_mac_txfrmcnt","MAC Tx_frame_cnt chk failed for port_id %d\n",this.id); | |
1416 | else | |
1417 | be_msg.print(e_mesg_info,"CMacTxPort","check_mac_txfrmcnt","MAC Tx_frame_cnt chk passed for port_id %d\n",this.id); | |
1418 | ||
1419 | } |