Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: niu_rx_descp.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 "niu_mem.vrh" | |
38 | #include "pcg_defines.vri" | |
39 | #include "pcg_types.vri" | |
40 | #include "pg_top_pp.vrh" | |
41 | #include "pc_top_pp.vrh" | |
42 | #include "pcg_token.vrh" | |
43 | #include "niu_rxtoken.vrh" | |
44 | #include "niu_dma.vrh" | |
45 | #include "niu_rx_descp_sch.vrh" | |
46 | #include "niu_rx_descp_cr.vrh" | |
47 | #include "niu_rx_crentry.vrh" | |
48 | #include "dmc_memory_map.vri" | |
49 | #include "zcp_memory_map.vri" | |
50 | ||
51 | #define RBR_MAX_RING_LEN 65535 | |
52 | #define RCR_MAX_RING_LEN 65535 | |
53 | #define RBR_PAGE_ALIGNMENT 65536 | |
54 | #define RCR_PAGE_ALIGNMENT 65536 | |
55 | ||
56 | #ifdef N2_FC | |
57 | #include "fc_niu_ev2a.vrh" | |
58 | #endif | |
59 | ||
60 | extern CSparseMem SparseMem; | |
61 | extern niu_gen_pio gen_pio_drv; | |
62 | extern mbox_class mbox_id; | |
63 | extern pg pack_gen[16]; | |
64 | extern integer RX_TEST_REACHED_END; | |
65 | extern CNiuDMABind NiuDMABind; | |
66 | ||
67 | class CRxBufferPool { | |
68 | bit [63:0] address; | |
69 | integer page_id; | |
70 | integer bufsz; | |
71 | integer status; | |
72 | integer no_of_expected_packets; | |
73 | integer no_of_packets_received; | |
74 | task new() { } | |
75 | function integer self_destroy() { | |
76 | if(no_of_packets_received>=no_of_expected_packets) { | |
77 | printf("debug: Pkt address to be deleted - %x \n",address); | |
78 | status = SparseMem.free_addr(address,1,page_id); | |
79 | printf("debug: xlate address to be deleted - %x %d \n",address,status); | |
80 | self_destroy = 1; | |
81 | } else self_destroy = 0; | |
82 | } | |
83 | } | |
84 | ||
85 | class rxdma_ctl_stat_reg { | |
86 | ||
87 | bit MEX_bit; | |
88 | ||
89 | bit status_DC_FIFO_ERR; | |
90 | bit status_RCRTHRES; | |
91 | bit status_RCRTO; | |
92 | bit status_PORT_DROP_PKT; | |
93 | bit status_WRED_DROP; | |
94 | bit status_RBR_PRE_EMPTY; | |
95 | bit status_RCR_SHADOW_FULL; | |
96 | bit status_RBR_EMPTY; | |
97 | ||
98 | bit [15:0] update_PTRREAD; | |
99 | bit [15:0] update_PKTREAD; | |
100 | ||
101 | task new() { | |
102 | status_DC_FIFO_ERR = 0; | |
103 | MEX_bit = 0; | |
104 | status_RCRTHRES = 0; | |
105 | status_RCRTO = 0; | |
106 | status_PORT_DROP_PKT = 0; | |
107 | status_WRED_DROP = 0; | |
108 | status_RBR_PRE_EMPTY = 0; | |
109 | status_RCR_SHADOW_FULL = 0; | |
110 | status_RBR_EMPTY = 0; | |
111 | update_PTRREAD = 0; | |
112 | update_PKTREAD = 0; | |
113 | } | |
114 | ||
115 | } | |
116 | ||
117 | class RxDMAChannel extends CDMA { | |
118 | ||
119 | integer id; // dmaid | |
120 | string type; // Tx or Rx | |
121 | integer active; | |
122 | integer total_packet_checked=0; | |
123 | integer total_packets_to_defaultdma=0; | |
124 | integer total_packets_to_nondefaultdma=0; | |
125 | ||
126 | integer desc_ring_head_ptr; | |
127 | bit [63:0] ring_start_addr; | |
128 | bit [63:0] ring_current_addr; | |
129 | integer ring_size; | |
130 | integer page0_id; | |
131 | integer page1_id; | |
132 | integer xlate_on; | |
133 | bit RBR_page; | |
134 | bit RCR_page; | |
135 | bit MailBox_page; | |
136 | bit PktBuffers_page; | |
137 | bit page0_valid; | |
138 | bit page1_valid; | |
139 | integer RBR_page_id; | |
140 | integer RCR_page_id; | |
141 | integer MailBox_page_id; | |
142 | integer PktBuffers_page_id; | |
143 | bit random_page_alloc; | |
144 | bit pkts_in_alternate_pages; | |
145 | integer ctrl_hdr_len; | |
146 | integer buffer_offset; | |
147 | bit [31:0] page_mask0, page_value0, page_reloc0; | |
148 | bit [31:0] page_mask1, page_value1, page_reloc1; | |
149 | bit [15:0] dma_block_size; | |
150 | bit [15:0] rcr_ring_len, rbr_ring_len; | |
151 | integer dis_pio_virt=0; | |
152 | ||
153 | bit[63:0] CR_rcr_start_addr, CR_rcr_tail_l, CR_rcr_tail_h; | |
154 | bit[63:0] CR_last_rcr_tail_l, CR_last_rcr_tail_h; | |
155 | integer CR_ring_length; | |
156 | integer poll_cr_active=0; | |
157 | integer poll_cr_done=0; | |
158 | ||
159 | bit dring_addr_error=0; | |
160 | bit cring_addr_error=0; | |
161 | integer descr_addr_error_pkt_num=0; | |
162 | integer curr_rbr_desc_kicked_cnt = 0; | |
163 | bit fun_no_has_been_set = 0; | |
164 | bit [1:0] function_no; | |
165 | ||
166 | integer rxdma_ctl_stat_update_done = -1; | |
167 | ||
168 | CRxdescpScheduler descpScheduler; | |
169 | CCompletionRing completionring; | |
170 | CRxBufferPool buf_pool[]; | |
171 | ||
172 | ||
173 | // descriptor_ring -- - | |
174 | CRxDescrRing desc_ring; | |
175 | ||
176 | task new(integer i,string t,(integer dev_id = 0) ){ | |
177 | ||
178 | super.new(i,1,dev_id); | |
179 | id = i; | |
180 | xlate_on =0; | |
181 | page_mask0=0; page_value0=0; page_reloc0=0; | |
182 | page_mask1=0; page_value1=0; page_reloc1=0; | |
183 | // if(xlate_on) { | |
184 | page0_id = 2*i + 64; | |
185 | page1_id = page0_id + 1; | |
186 | // } else { | |
187 | // page0_id = 0; | |
188 | // page1_id = 0; | |
189 | // } | |
190 | ||
191 | total_packet_checked=0; | |
192 | total_packets_to_defaultdma=0; | |
193 | total_packets_to_nondefaultdma=0; | |
194 | ||
195 | address_incr = 4; | |
196 | type = t; | |
197 | active = 0; | |
198 | desc_ring = new(); | |
199 | dis_pio_virt=1; | |
200 | descpScheduler = new(i); | |
201 | completionring = new(); | |
202 | completionring.dma_num = id; | |
203 | printf(" DMA Channel %d -newed\n",i); | |
204 | RBR_page = 0; | |
205 | RCR_page = 0; | |
206 | MailBox_page = 0; | |
207 | PktBuffers_page = 0; | |
208 | page0_valid = 1; | |
209 | page1_valid = 1; | |
210 | RBR_page_id = page0_id; | |
211 | RCR_page_id = page0_id; | |
212 | MailBox_page_id = page0_id; | |
213 | PktBuffers_page_id = page0_id; | |
214 | random_page_alloc = 0; | |
215 | pkts_in_alternate_pages = 0; | |
216 | ctrl_hdr_len = 2; | |
217 | buffer_offset = 0; | |
218 | dma_block_size = 4096; | |
219 | rcr_ring_len = 0; | |
220 | rbr_ring_len = 0; | |
221 | ||
222 | auto_periodic_kick(); | |
223 | rxdma_ctl_stat_update_done = alloc(SEMAPHORE, 0, 1, 1); | |
224 | if(get_plus_arg( CHECK, "RXTX_PIO_STRESS_BINDING=")) { | |
225 | function_no = get_plus_arg( NUM, "RXTX_PIO_STRESS_BINDING="); | |
226 | function_no = function_no % 4; | |
227 | } else function_no = id/4; | |
228 | ||
229 | } | |
230 | ||
231 | ||
232 | // local task add_descriptor(CRxdescriptor desc); | |
233 | local function integer incr_ptr( integer ptr){ | |
234 | incr_ptr = (ptr++)%ring_size; | |
235 | } | |
236 | ||
237 | local task create_descriptor(var CRxdescriptor desc, bit [31:0] blk_addr, (integer pkt_page_id = 0) ); | |
238 | local task set_descriptor(integer no_of_desc); | |
239 | ||
240 | function integer CheckDMAStatus( CRxToken RxToken) ; | |
241 | function integer getPacketAddress( CRxToken RxToken) ; | |
242 | function integer getPageId(bit [43:0] virt_address); | |
243 | ||
244 | function CRxdescriptor getNextDesc() { | |
245 | getNextDesc = desc_ring.front(); | |
246 | desc_ring.pop_front(); | |
247 | } | |
248 | function integer get_curr_ring_size() { | |
249 | get_curr_ring_size=descpScheduler.desc_ring.desc_ring.size(); | |
250 | } | |
251 | ||
252 | local task UpdateCompletionRing(CRxToken RxToken); | |
253 | // functions to update RxDMA Rx Kick Registers | |
254 | ||
255 | task SetCurrentPtrs() ; | |
256 | task CheckCR_Entries(); | |
257 | ||
258 | task pollCRPtr( (integer poll_interval=1000) ); | |
259 | task reclaim_buffers( (integer reclaim=1) ); | |
260 | task setRxDmaCfig_1(bit [63:0] data,(bit read_back = 1'b0),(bit read_only = 1'b0)); | |
261 | task setRxLogPgVld(bit [63:0] data,(bit read_back = 1'b0)); | |
262 | task setRbrConfig_A(bit [63:0] data,(bit read_back = 1'b0),(integer ring_page_id =0)); | |
263 | task setRbrConfig_B(bit [63:0] data,(bit read_back = 1'b0)); | |
264 | task setRxRingKick(bit [63:0] data); | |
265 | task readRxRingHead(var bit [63:0] data); | |
266 | task setZcpRdc(bit [63:0] data,(bit read_back = 1'b0)); | |
267 | task setRcrConfig_A(bit [63:0] data,(bit read_back = 1'b0),(integer ring_page_id =0)); | |
268 | local task updateHeaderLength(CRxToken RxToken); | |
269 | task SetPage0Registers(bit [31:0] mask,bit [31:0] value, bit [31:0] reloc); | |
270 | task SetPage1Registers(bit [31:0] mask,bit [31:0] value, bit [31:0] reloc); | |
271 | task InitDMAChan(integer dma_chnl, integer desc_ring_length, integer compl_ring_len, bit [63:0] rbr_config_B_data, bit [15:0] initial_kick, integer xlation); | |
272 | task CheckMailboxData(bit [63:0] ctl_data_mask); | |
273 | task UpdateRCRStat(); | |
274 | ||
275 | // functions to check data | |
276 | task CheckCRData (integer no_of_entries , (integer update_ptrs = 0) ); | |
277 | task free_memory(CRxToken RxToken); | |
278 | task flush_rcr((integer wait_for_done=0) ); | |
279 | task reset_bind_to_group( (integer dummy_g=0)); | |
280 | task bind_to_group( integer g); | |
281 | task enableWRED(bit [15:0] red_ran_init, | |
282 | bit [11:0] TCP_SYN_THR, | |
283 | bit [3:0] TCP_SYN_WIN, | |
284 | bit [11:0] THR, | |
285 | bit [3:0] WIN); | |
286 | ||
287 | task resetRxDma(); | |
288 | ||
289 | task incDefPktCnt () { | |
290 | total_packet_checked++; | |
291 | total_packets_to_defaultdma++; | |
292 | } | |
293 | ||
294 | task incPktCnt () { | |
295 | total_packet_checked++; | |
296 | total_packets_to_nondefaultdma++; | |
297 | } | |
298 | //task RXDMA_CFIG1_pio_wr(bit [63:0] address, bit [63:0] data); | |
299 | //task RXDMA_CFIG1_pio_rd(bit [63:0] address, var bit [63:0] data); | |
300 | //task RXDMA_CFIG2_pio_wr(bit [63:0] address, bit [63:0] data); | |
301 | //task RXDMA_CFIG2_pio_rd(bit [63:0] address, var bit [63:0] data); | |
302 | ||
303 | task init_descr_cache(); | |
304 | task init_compl_cache(); | |
305 | ||
306 | task periodic_kick((integer interval = 3000), (integer num_desc = 256), (integer threshold = 256)); | |
307 | task auto_periodic_kick(); | |
308 | ||
309 | task pio_wr_RXDMA_CFIG1(bit [63:0] rd_data); | |
310 | task pio_rd_RXDMA_CFIG1(var bit [63:0] rd_data); | |
311 | task pio_wr_RXDMA_CFIG2(bit [63:0] rd_data); | |
312 | task pio_rd_RXDMA_CFIG2(var bit [63:0] rd_data); | |
313 | task pio_rd_RCR_CFIG_A(var bit [63:0] rd_data); | |
314 | task pio_rd_RX_MISC_DROP(var bit [63:0] rd_data); | |
315 | task pio_rd_RED_DISC(var bit [63:0] rd_data); | |
316 | task pio_wr_RDC_RED_PARA(bit [63:0] rd_data); | |
317 | task pio_rd_RDC_RED_PARA(var bit [63:0] rd_data); | |
318 | ||
319 | task pio_wr_RX_DMA_CTL_STAT_START(bit [63:0] rd_data); | |
320 | task pio_rd_RX_DMA_CTL_STAT_START(var bit [63:0] rd_data); | |
321 | task pio_wr_RX_DMA_ENT_MSK_START(bit [63:0] rd_data); | |
322 | task pio_rd_RX_DMA_ENT_MSK_START(var bit [63:0] rd_data); | |
323 | task pio_wr_RCR_CFIG_B_START(bit [63:0] rd_data); | |
324 | task pio_rd_RCR_CFIG_B_START(var bit [63:0] rd_data); | |
325 | task pio_wr_RX_DMA_INTR_DEBUG_START(bit [63:0] rd_data); | |
326 | task pio_rd_RX_DMA_INTR_DEBUG_START(var bit [63:0] rd_data); | |
327 | task rxdma_ctl_stat_update(integer field, rxdma_ctl_stat_reg ctl_stat_reg); | |
328 | } | |
329 | ||
330 | task RxDMAChannel :: rxdma_ctl_stat_update(integer field, rxdma_ctl_stat_reg ctl_stat_reg) { | |
331 | bit [63:0] rd_data; | |
332 | ||
333 | // first wait for the SEMAPHORE for mutual exclusiveness of multiple calls to this function | |
334 | printf ("RxDMAChannel::rxdma_ctl_stat_update dma=%0d field %0d\n", id, field); | |
335 | semaphore_get(WAIT, rxdma_ctl_stat_update_done, 1); | |
336 | case(field) { | |
337 | 0: { // updating the MEX bit with given value. Write Status_bits=0, RCR_Update=0. | |
338 | pio_rd_RX_DMA_CTL_STAT_START(rd_data); | |
339 | rd_data[RX_DMA_CTL_STAT_MEX] = ctl_stat_reg.MEX_bit; // bit 47 | |
340 | rd_data[RX_DMA_CTL_STAT_RBR_TMOUT:RX_DMA_CTL_STAT_DC_FIFO_ERR] = 0; // bits 53:48 | |
341 | rd_data[RX_DMA_CTL_STAT_RCRTHRES:RX_DMA_CTL_STAT_CFIGLOGPAGE] = 0; // bits 46:32 | |
342 | rd_data[RX_DMA_CTL_STAT_PTRREAD] = 0; // bits 31:16 | |
343 | rd_data[RX_DMA_CTL_STAT_PKTREAD] = 0; // bits 15:0 | |
344 | printf ("RxDMAChannel::rxdma_ctl_stat_update field=0 dma=%0d, updating MEX<=%0d\n", id, ctl_stat_reg.MEX_bit); | |
345 | pio_wr_RX_DMA_CTL_STAT_START(rd_data); | |
346 | } | |
347 | 1: { // clearing the non-fatal status bits, Write MEX=MEX-read, RCR_Update=0. | |
348 | pio_rd_RX_DMA_CTL_STAT_START(rd_data); | |
349 | rd_data[RX_DMA_CTL_STAT_DC_FIFO_ERR] = | |
350 | ctl_stat_reg.status_DC_FIFO_ERR; // bit 48 | |
351 | rd_data[RX_DMA_CTL_STAT_RCRTHRES] = | |
352 | ctl_stat_reg.status_RCRTHRES; // bit 46 | |
353 | rd_data[RX_DMA_CTL_STAT_RCRTO] = | |
354 | ctl_stat_reg.status_RCRTO; // bit 45 | |
355 | rd_data[RX_DMA_CTL_STAT_PORT_DROP_PKT] = | |
356 | ctl_stat_reg.status_PORT_DROP_PKT; // bit 42 | |
357 | rd_data[RX_DMA_CTL_STAT_WRED_DROP] = | |
358 | ctl_stat_reg.status_WRED_DROP; // bit 41 | |
359 | rd_data[RX_DMA_CTL_STAT_RBR_PRE_EMTY] = | |
360 | ctl_stat_reg.status_RBR_PRE_EMPTY; // bit 40 | |
361 | rd_data[RX_DMA_CTL_STAT_RCR_SHADOW_FULL] = | |
362 | ctl_stat_reg.status_RCR_SHADOW_FULL; // bit 39 | |
363 | rd_data[RX_DMA_CTL_STAT_RBR_EMPTY] = | |
364 | ctl_stat_reg.status_RBR_EMPTY; // bit 35 | |
365 | rd_data[RX_DMA_CTL_STAT_PTRREAD] = 0; | |
366 | rd_data[RX_DMA_CTL_STAT_PKTREAD] = 0; | |
367 | printf ("RxDMAChannel::rxdma_ctl_stat_update field=1 dma=%0d, clear Status bits wr_data = 0x%h\n", rd_data); | |
368 | pio_wr_RX_DMA_CTL_STAT_START(rd_data); | |
369 | } | |
370 | 2: { // updating the RCR status from software, Write MEX=MEX-read, Status_bits=0. | |
371 | pio_rd_RX_DMA_CTL_STAT_START(rd_data); | |
372 | rd_data[RX_DMA_CTL_STAT_RBR_TMOUT:RX_DMA_CTL_STAT_DC_FIFO_ERR] = 0; // bits 53:48 | |
373 | rd_data[RX_DMA_CTL_STAT_RCRTHRES:RX_DMA_CTL_STAT_CFIGLOGPAGE] = 0; // bits 46:32 | |
374 | rd_data[RX_DMA_CTL_STAT_PTRREAD] = ctl_stat_reg.update_PTRREAD; // bits 31:16 | |
375 | rd_data[RX_DMA_CTL_STAT_PKTREAD] = ctl_stat_reg.update_PKTREAD; // bits 15:0 | |
376 | printf ("RxDMAChannel::rxdma_ctl_stat_update field=2 dma=%0d, RCR Update. wr_data = 0x%h\n",id, rd_data); | |
377 | pio_wr_RX_DMA_CTL_STAT_START(rd_data); | |
378 | } | |
379 | default: { | |
380 | } | |
381 | } | |
382 | ||
383 | // Now, to allow any other pending call to this function, put key back into the SEMAPHORE bucket | |
384 | semaphore_put(rxdma_ctl_stat_update_done, 1); | |
385 | ||
386 | } | |
387 | ||
388 | task RxDMAChannel :: init_descr_cache() { | |
389 | bit [63:0] rd_data; | |
390 | integer ii; | |
391 | ||
392 | printf("RxDMAChannel::init_descr_cache() Initializing the descriptor prefetch cache to 0 for DMA - %0d\n",id); | |
393 | ||
394 | // Enable the RAM debug read/write mode | |
395 | gen_pio_drv.pio_rd(getPIOAddress(RX_ADDR_MD, dis_pio_virt),rd_data); | |
396 | rd_data[RX_ADDR_MD_RAM_ACC]=1; | |
397 | gen_pio_drv.pio_wr(getPIOAddress(RX_ADDR_MD, dis_pio_virt),rd_data); | |
398 | ||
399 | //WRITE all entries to 0 (for Neptune, this is a must. Otherwise, PCIE link layer will hang due to pio_rd_data=X) | |
400 | for(ii=0; ii<8; ii++) { //dma0:0-7 dma1:8-15 (descr) | |
401 | gen_pio_drv.pio_rd(getPIOAddress(RDMC_MEM_ADDR, dis_pio_virt), rd_data); | |
402 | rd_data[RDMC_MEM_ADDR_PRE_SHAD]=0; //0=prefetch(descr) 1=shadow(cring) | |
403 | rd_data[RDMC_MEM_ADDR_PRE_ADDR]=(id*8)+ii; | |
404 | gen_pio_drv.pio_wr(getPIOAddress(RDMC_MEM_ADDR, dis_pio_virt), rd_data); | |
405 | ||
406 | gen_pio_drv.pio_wr(RDMC_MEM_DAT3, 0); | |
407 | gen_pio_drv.pio_wr(RDMC_MEM_DAT2, 0); | |
408 | gen_pio_drv.pio_wr(RDMC_MEM_DAT1, 0); | |
409 | gen_pio_drv.pio_wr(RDMC_MEM_DAT0, 0); | |
410 | gen_pio_drv.pio_wr(RDMC_MEM_DAT4, 0); | |
411 | } | |
412 | ||
413 | // Turn back off the RAM debug read/write mode | |
414 | gen_pio_drv.pio_rd(getPIOAddress(RX_ADDR_MD, dis_pio_virt),rd_data); | |
415 | rd_data[RX_ADDR_MD_RAM_ACC]=0; | |
416 | gen_pio_drv.pio_wr(getPIOAddress(RX_ADDR_MD, dis_pio_virt),rd_data); | |
417 | ||
418 | } | |
419 | ||
420 | task RxDMAChannel :: init_compl_cache() { | |
421 | bit [63:0] rd_data; | |
422 | integer ii; | |
423 | ||
424 | printf("RxDMAChannel::init_compl_cache() Initializing the compl shadow cache to 0 for DMA - %0d\n",id); | |
425 | ||
426 | // Enable the RAM debug read/write mode | |
427 | gen_pio_drv.pio_rd(getPIOAddress(RX_ADDR_MD, dis_pio_virt),rd_data); | |
428 | rd_data[RX_ADDR_MD_RAM_ACC]=1; | |
429 | gen_pio_drv.pio_wr(getPIOAddress(RX_ADDR_MD, dis_pio_virt),rd_data); | |
430 | ||
431 | //WRITE all entries to 0 (for Neptune, this is a must. Otherwise, PCIE link layer will hang due to pio_rd_data=X) | |
432 | for(ii=0; ii<8; ii++) { //dma0:0-7 dma1:8-15 (descr) | |
433 | gen_pio_drv.pio_rd(getPIOAddress(RDMC_MEM_ADDR, dis_pio_virt), rd_data); | |
434 | rd_data[RDMC_MEM_ADDR_PRE_SHAD]=1; //0=prefetch(descr) 1=shadow(cring) | |
435 | rd_data[RDMC_MEM_ADDR_PRE_ADDR]=(id*8)+ii; | |
436 | gen_pio_drv.pio_wr(getPIOAddress(RDMC_MEM_ADDR, dis_pio_virt), rd_data); | |
437 | ||
438 | gen_pio_drv.pio_wr(RDMC_MEM_DAT3, 0); | |
439 | gen_pio_drv.pio_wr(RDMC_MEM_DAT2, 0); | |
440 | gen_pio_drv.pio_wr(RDMC_MEM_DAT1, 0); | |
441 | gen_pio_drv.pio_wr(RDMC_MEM_DAT0, 0); | |
442 | gen_pio_drv.pio_wr(RDMC_MEM_DAT4, 0); | |
443 | } | |
444 | ||
445 | // Turn back off the RAM debug read/write mode | |
446 | gen_pio_drv.pio_rd(getPIOAddress(RX_ADDR_MD, dis_pio_virt),rd_data); | |
447 | rd_data[RX_ADDR_MD_RAM_ACC]=0; | |
448 | gen_pio_drv.pio_wr(getPIOAddress(RX_ADDR_MD, dis_pio_virt),rd_data); | |
449 | ||
450 | } | |
451 | ||
452 | task RxDMAChannel :: enableWRED(bit [15:0] red_ran_init, | |
453 | bit [11:0] TCP_SYN_THR, | |
454 | bit [3:0] TCP_SYN_WIN, | |
455 | bit [11:0] THR, | |
456 | bit [3:0] WIN) { | |
457 | ||
458 | // Enable WRED and set the parameters red_ran_init,TCP_SYN_THR,TCP_SYN_WIN,THR, and WIN | |
459 | gen_pio_drv.pio_wr(getPIOAddress(RED_RAN_INIT, dis_pio_virt), {45'h0, 1, red_ran_init}); | |
460 | gen_pio_drv.pio_wr(getPIOAddress(RDC_RED_PARA_START + id*RDC_RED_PARA_STEP, dis_pio_virt), {32'h0,TCP_SYN_THR,TCP_SYN_WIN,THR,WIN}); | |
461 | printf ("RxDMAChannel.enableWRED red_ran_init 0x%h TCP_SYN_THR 0x%h TCP_SYN_WIN 0x%h THR 0x%h WIN 0x%h\n", | |
462 | red_ran_init,TCP_SYN_THR,TCP_SYN_WIN,THR,WIN); | |
463 | } | |
464 | ||
465 | task RxDMAChannel :: CheckCR_Entries( ) { | |
466 | ||
467 | integer no_of_entries; | |
468 | Ccr_update cr_update; | |
469 | bit [63:0] rd_data; | |
470 | ||
471 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_C_START + RXDMA_STEP*id, dis_pio_virt), CR_rcr_tail_l); | |
472 | printf("RxDMAChannel :: CheckCR_Entries rcr_tail_l - %x last_rcr_tail_l - %x \n",CR_rcr_tail_l,CR_last_rcr_tail_l); | |
473 | if(CR_last_rcr_tail_l>CR_rcr_tail_l) { //wrap around case | |
474 | no_of_entries=((CR_rcr_tail_l-CR_rcr_start_addr[31:0])+((CR_rcr_start_addr[31:0]+CR_ring_length)-CR_last_rcr_tail_l))/8; | |
475 | printf("pollCR dma=%0d l>c last_rcr_tail_l=%x rcr_tail_l=%x no_of_entries=%0d\n", id, CR_last_rcr_tail_l, CR_rcr_tail_l, no_of_entries); | |
476 | CR_last_rcr_tail_l = CR_rcr_tail_l; | |
477 | } else if(CR_last_rcr_tail_l<CR_rcr_tail_l) { | |
478 | no_of_entries=(CR_rcr_tail_l - CR_last_rcr_tail_l)/8; | |
479 | printf("pollCR dma=%0d l<c last_rcr_tail_l=%x rcr_tail_l=%x no_of_entries=%0d\n", id, CR_last_rcr_tail_l, CR_rcr_tail_l, no_of_entries); | |
480 | CR_last_rcr_tail_l = CR_rcr_tail_l; | |
481 | } else { | |
482 | no_of_entries=0; | |
483 | } | |
484 | ||
485 | if(no_of_entries>0) { | |
486 | cr_update = new(); | |
487 | cr_update.dma_no = this.id; | |
488 | cr_update.no_of_entries = no_of_entries; | |
489 | if(get_plus_arg (CHECK, "RX_DROP_PKT_CHECK")) | |
490 | mailbox_put(mbox_id.niu_rxpath_cr, cr_update); | |
491 | ||
492 | // ######## updating PTRREAD/PKTREAD fields to RX_DMA_CTL_STAT has to be done in 1 place: checker ####### | |
493 | //gen_pio_drv.pio_rd(getPIOAddress(RX_DMA_CTL_STAT_START + RXDMA_STEP*id, dis_pio_virt), rd_data, 1'b0); | |
494 | //rd_data[31:16] = no_of_entries; | |
495 | //gen_pio_drv.pio_wr(getPIOAddress(RX_DMA_CTL_STAT_START + RXDMA_STEP*id, dis_pio_virt), rd_data); | |
496 | } | |
497 | ||
498 | } | |
499 | ||
500 | task RxDMAChannel :: SetCurrentPtrs( ) { | |
501 | ||
502 | CR_ring_length = completionring.ring_length; | |
503 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_B_START + RXDMA_STEP*id, dis_pio_virt), CR_last_rcr_tail_h); | |
504 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_C_START + RXDMA_STEP*id, dis_pio_virt), CR_last_rcr_tail_l); | |
505 | gen_pio_drv.pio_rd(getPIOAddress(RCR_CFIG_A_START + RXDMA_STEP*id, dis_pio_virt), CR_rcr_start_addr); | |
506 | printf("SetCurrentPtrs:dma=%0d cring_len=0x%0h start_addr=0x%0h starting at time=%d ptr - %x \n", id, CR_ring_length, CR_rcr_start_addr, {get_time(HI), get_time(LO)},CR_last_rcr_tail_l); | |
507 | } | |
508 | ||
509 | task RxDMAChannel :: reset_bind_to_group( (integer dummy_g=0)) { | |
510 | if(NiuDMABind.rx_dma_func_bind[id] != -1) { | |
511 | ResetDMAGroupBind(NiuDMABind.rx_dma_func_bind[id]); | |
512 | } | |
513 | } | |
514 | ||
515 | task RxDMAChannel :: bind_to_group( integer g) { | |
516 | bit [63:0] address; | |
517 | bit [63:0] rdata; | |
518 | dis_pio_virt = 0; | |
519 | address = RX_LOG_PAGE_VLD + id*40'h40; | |
520 | gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),rdata); | |
521 | rdata[3:2] = g/16; | |
522 | fun_no_has_been_set = 1; | |
523 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),rdata); | |
524 | printf("<%0d> RxDMAChannel :: bind_to_group : RX_LOG_PAGE_VLD : addr:%h data:%h, g:%0d, id:%0d\n", | |
525 | get_time(LO), address, rdata, g, id); | |
526 | SetDMAGroupBind(g); | |
527 | } | |
528 | ||
529 | task RxDMAChannel::flush_rcr((integer wait_for_done=0) ) { | |
530 | bit[63:0] rdata; | |
531 | integer count; | |
532 | count = 0; | |
533 | gen_pio_drv.pio_wr(getPIOAddress(RCR_FLUSH_START + 12'h200*id, dis_pio_virt), 64'h1); | |
534 | if(wait_for_done) { | |
535 | rdata= 1; | |
536 | while(rdata!=0) { | |
537 | gen_pio_drv.pio_rd(getPIOAddress(RCR_FLUSH_START + 12'h200*id, dis_pio_virt), rdata); | |
538 | repeat(50)@(posedge CLOCK); | |
539 | count++; | |
540 | if(count>1000){ | |
541 | printf("RxDMAChannel::flush_rcr DMA- %d ERROR, RCR FLUSH NOT DONE after %d Clocks\n",id,50*count); | |
542 | return; | |
543 | } | |
544 | } | |
545 | printf("RxDMAChannel::flush_rcr DMA - %d Done with flush\n",id); | |
546 | } | |
547 | } | |
548 | ||
549 | task RxDMAChannel::free_memory(CRxToken RxToken) { | |
550 | integer bufsz; | |
551 | bit[63:0] packet_address[3]; | |
552 | bit[63:0] norm_address[3]; | |
553 | integer blk_size; | |
554 | integer status; | |
555 | integer no_of_expected_packets; | |
556 | integer i,bit_to_ignore; | |
557 | ||
558 | CRxBufferPool buf_poollocal; | |
559 | ||
560 | bufsz = RxToken.bufsz; | |
561 | blk_size = descpScheduler.blk_size; | |
562 | if(bufsz==3) { | |
563 | no_of_expected_packets = 1; | |
564 | } else if(bufsz==2) { | |
565 | no_of_expected_packets = blk_size/descpScheduler.bufsz2; | |
566 | } else if(bufsz==1) { | |
567 | no_of_expected_packets = blk_size/descpScheduler.bufsz1; | |
568 | } else if(bufsz==0) { | |
569 | no_of_expected_packets = blk_size/descpScheduler.bufsz0; | |
570 | } | |
571 | bit_to_ignore = 0; | |
572 | while(blk_size !=0) { | |
573 | bit_to_ignore++; | |
574 | blk_size = blk_size>>1; | |
575 | } | |
576 | bit_to_ignore--; | |
577 | printf("blk_size - %d bit_to_ignore - %d no_of_expected_packets - %d \n",blk_size,bit_to_ignore,no_of_expected_packets); | |
578 | ||
579 | for(i=0;i<RxToken.NoOfScatter;i++) { | |
580 | packet_address[i] = RxToken.packet_start_address[i]; | |
581 | // ignore lower bits | |
582 | norm_address[i] = packet_address[i] >> bit_to_ignore; | |
583 | } | |
584 | ||
585 | for(i=0;i<RxToken.NoOfScatter;i++) { | |
586 | if(assoc_index(CHECK,buf_pool, norm_address[i])) { | |
587 | // if this exists | |
588 | buf_pool[norm_address[i]].no_of_packets_received++; | |
589 | printf(" destroyed address - %x no_of_packet_sofar - %d \n",norm_address[i], buf_pool[norm_address[i]].no_of_packets_received); | |
590 | buf_pool[norm_address[i]].page_id = getPageId(RxToken.packet_virtaddress[i]); | |
591 | if(buf_pool[norm_address[i]].self_destroy() ) { | |
592 | status = assoc_index(DELETE,buf_pool,norm_address[i]); | |
593 | } | |
594 | } else { | |
595 | buf_poollocal = new(); | |
596 | buf_poollocal.address = packet_address[i]; | |
597 | buf_poollocal.no_of_expected_packets = no_of_expected_packets; | |
598 | buf_poollocal.no_of_packets_received = 1; | |
599 | buf_poollocal.page_id = getPageId(RxToken.packet_virtaddress[i]); | |
600 | buf_pool[norm_address[i]] = new buf_poollocal; | |
601 | if(buf_pool[norm_address[i]].self_destroy() ) { | |
602 | status = assoc_index(DELETE,buf_pool,norm_address[i]); | |
603 | printf("destroyed address - %x \n",norm_address[i]); | |
604 | } | |
605 | } | |
606 | } | |
607 | } | |
608 | ||
609 | task RxDMAChannel::reclaim_buffers(( integer reclaim =1) ) { | |
610 | integer n; | |
611 | integer max_number_to_claim = 65535; // Make this under test control | |
612 | // gen_pio_drv.pio_rd(getPIOAddress(RBR_HDH_START + RXDMA_STEP*id, dis_pio_virt), get_rbr_head_ptr); | |
613 | if(reclaim) { | |
614 | n = 1;//CHOOSE A VALUE calculate the delta from previous reclaim | |
615 | n = descpScheduler.get_reclaim_index() - descpScheduler.last_reclaim_index; | |
616 | printf(" DMA - %d n - %d last- %d index - %d \n",id,n, descpScheduler.last_reclaim_index, descpScheduler.reclaim_index); | |
617 | if(n>max_number_to_claim) { | |
618 | n= max_number_to_claim; | |
619 | } | |
620 | descpScheduler.last_reclaim_index = descpScheduler.last_reclaim_index + n; | |
621 | desc_ring.reclaim_buffers(n); | |
622 | } | |
623 | ||
624 | ||
625 | } | |
626 | ||
627 | task RxDMAChannel::updateHeaderLength(CRxToken RxToken) { | |
628 | ||
629 | // Add code here to update the header length and buffer_offset | |
630 | RxToken.header_length = ctrl_hdr_len + buffer_offset; | |
631 | ||
632 | } | |
633 | ||
634 | task RxDMAChannel::CheckCRData( integer no_of_entries , (integer update_ptrs = 0) ) { | |
635 | // if update_ptrs == 1 | |
636 | // set RX_DMA_CTL_STAT accordingly | |
637 | bit [63:0] rcr_start_addr, rcr_tail_l, rcr_tail_h; | |
638 | integer time_cntr = 0; | |
639 | ||
640 | ||
641 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_B_START + RXDMA_STEP*id, dis_pio_virt), rcr_tail_h); | |
642 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_C_START + RXDMA_STEP*id, dis_pio_virt), rcr_tail_l); | |
643 | gen_pio_drv.pio_rd(getPIOAddress(RCR_CFIG_A_START + RXDMA_STEP*id, dis_pio_virt), rcr_start_addr); | |
644 | ||
645 | printf ("RCR_Tail = %h, RCR_Start_Addr = %h, Expected_Tail_Update = %h\n", | |
646 | {rcr_tail_h[11:0],rcr_tail_l[31:3],3'b000}, | |
647 | {rcr_start_addr[43:19], rcr_start_addr[18:6], 6'b0}, 8*no_of_entries); | |
648 | ||
649 | while (({rcr_tail_h[11:0],rcr_tail_l[31:3],3'b000}-{rcr_start_addr[43:6],6'b0}) < (8*no_of_entries)) { | |
650 | repeat (100) @(posedge CLOCK); | |
651 | printf ("RCR_Tail = %h, RCR_Start_Addr = %h, Expected_Tail_Update = %h\n", | |
652 | {rcr_tail_h[11:0],rcr_tail_l[31:3],3'b000}, | |
653 | {rcr_start_addr[43:19], rcr_start_addr[18:6], 6'b0}, 8*no_of_entries); | |
654 | if (time_cntr++ > 2000) { | |
655 | printf ("ERROR: completion entries not written, timing out\n"); | |
656 | exit(0); | |
657 | } | |
658 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_B_START + RXDMA_STEP*id, dis_pio_virt), rcr_tail_h); | |
659 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_C_START + RXDMA_STEP*id, dis_pio_virt), rcr_tail_l); | |
660 | gen_pio_drv.pio_rd(getPIOAddress(RCR_CFIG_A_START + RXDMA_STEP*id, dis_pio_virt), rcr_start_addr); | |
661 | } | |
662 | ||
663 | repeat (50) @(posedge CLOCK); | |
664 | ||
665 | completionring.CheckSysMem(no_of_entries); | |
666 | ||
667 | } | |
668 | ||
669 | function integer RxDMAChannel::getPageId(bit [43:0] virt_address) { | |
670 | if( (( virt_address[43:12]&page_mask0) == page_value0) & page0_valid) | |
671 | getPageId = page0_id; | |
672 | else if( ((virt_address[43:12]&page_mask1) == page_value1) & page1_valid) | |
673 | getPageId = page1_id; | |
674 | else | |
675 | getPageId = -1; | |
676 | printf(" virt_address - %x page_mask0 = %x page_value0 - %x valid - %d getPageId - %d \n",virt_address,page_mask0,page_value0,page0_valid,getPageId); | |
677 | } | |
678 | /////////////////////////////////////////////////////////// | |
679 | ||
680 | task RxDMAChannel::pollCRPtr( (integer poll_interval=1000) ) { | |
681 | bit[63:0] rcr_start_addr, rcr_tail_l, rcr_tail_h; | |
682 | bit[63:0] last_rcr_tail_l, last_rcr_tail_h; | |
683 | integer end_reached=0; | |
684 | integer no_of_entries, ring_length; | |
685 | Ccr_update cr_update; | |
686 | bit[63:0] rd_data; | |
687 | integer not_done=1; | |
688 | integer NO_OF_ITER = 2; | |
689 | ||
690 | ring_length = completionring.ring_length; | |
691 | //gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_B_START + RXDMA_STEP*id, dis_pio_virt), last_rcr_tail_h); | |
692 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_C_START + RXDMA_STEP*id, dis_pio_virt), last_rcr_tail_l); | |
693 | gen_pio_drv.pio_rd(getPIOAddress(RCR_CFIG_A_START + RXDMA_STEP*id, dis_pio_virt), rcr_start_addr); | |
694 | printf("RxDMAChannel::pollCRPtr dma=%0d cring_len=0x%0h start_addr=0x%0h starting at time=%d\n", id, ring_length, rcr_start_addr, {get_time(HI), get_time(LO)}); | |
695 | ||
696 | poll_cr_active = 1; | |
697 | while(not_done) { | |
698 | if(RX_TEST_REACHED_END){ | |
699 | end_reached++ ; | |
700 | printf("%d RxDMAChannel::pollCRPtr dma_id=%d REACHED END count - %d \n", {get_time(HI), get_time(LO)}, id,end_reached); | |
701 | } | |
702 | //gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_B_START + RXDMA_STEP*id, dis_pio_virt), rcr_tail_h); | |
703 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_C_START + RXDMA_STEP*id, dis_pio_virt), rcr_tail_l); | |
704 | ||
705 | if(last_rcr_tail_l>rcr_tail_l) { //wrap around case | |
706 | no_of_entries=((rcr_tail_l-rcr_start_addr[31:0])+((rcr_start_addr[31:0]+ring_length)-last_rcr_tail_l))/8; | |
707 | //printf("pollCR dma=%0d l>c rcr-start=0x%0h rcr+ring_len-last=0x%0h\n", id, (rcr_tail_l-rcr_start_addr[31:0]), ((rcr_start_addr[31:0 ]+ring_length)-last_rcr_tail_l)); | |
708 | printf("pollCR dma=%0d l>c last_rcr_tail_l=%x rcr_tail_l=%x no_of_entries=%0d\n", id, last_rcr_tail_l, rcr_tail_l, no_of_entries); | |
709 | //last_rcr_tail_h = rcr_tail_h; | |
710 | last_rcr_tail_l = rcr_tail_l; | |
711 | } | |
712 | else if(last_rcr_tail_l<rcr_tail_l) { | |
713 | no_of_entries=(rcr_tail_l-last_rcr_tail_l)/8; | |
714 | printf("pollCR dma=%0d l<c last_rcr_tail_l=%x rcr_tail_l=%x no_of_entries=%0d\n", id, last_rcr_tail_l, rcr_tail_l, no_of_entries); | |
715 | //last_rcr_tail_h = rcr_tail_h; | |
716 | last_rcr_tail_l = rcr_tail_l; | |
717 | } | |
718 | else { | |
719 | no_of_entries=0; | |
720 | //printf("pollCR dma=%0d l=c last_rcr_tail_l=%x rcr_tail_l=%x\n", id, last_rcr_tail_l, rcr_tail_l); | |
721 | } | |
722 | ||
723 | if(no_of_entries>0) { | |
724 | printf(" Sending mbox to checker DMA - %d no_of_entries - %d \n",id,no_of_entries); | |
725 | cr_update = new(); | |
726 | cr_update.dma_no = id; | |
727 | cr_update.no_of_entries = no_of_entries; | |
728 | if(get_plus_arg (CHECK, "RX_DROP_PKT_CHECK")) | |
729 | mailbox_put(mbox_id.niu_rxpath_cr, cr_update); | |
730 | ||
731 | printf(" Done Sending mbox to checker DMA - %d no_of_entries - %d \n",id,no_of_entries); | |
732 | ||
733 | // ######## updating PTRREAD/PKTREAD fields to RX_DMA_CTL_STAT has to be done in 1 place: checker ####### | |
734 | //gen_pio_drv.pio_rd(getPIOAddress(RX_DMA_CTL_STAT_START + RXDMA_STEP*id, dis_pio_virt), rd_data, 1'b0); | |
735 | //rd_data[31:16] = no_of_entries; | |
736 | //gen_pio_drv.pio_wr(getPIOAddress(RX_DMA_CTL_STAT_START + RXDMA_STEP*id, dis_pio_virt), rd_data); | |
737 | } | |
738 | if(end_reached>=NO_OF_ITER) { | |
739 | not_done =0; | |
740 | } | |
741 | ||
742 | repeat(poll_interval) @(posedge CLOCK); | |
743 | } | |
744 | ||
745 | poll_cr_done= 1; | |
746 | } | |
747 | task RxDMAChannel::UpdateRCRStat() { | |
748 | ||
749 | bit[63:0] rd_data; | |
750 | rxdma_ctl_stat_reg ctlstat_reg; | |
751 | Crcr_update rcr_update; | |
752 | integer no_of_entries; | |
753 | integer total_pkts, total_rcr_entries; | |
754 | integer i; | |
755 | ||
756 | while(1) { | |
757 | no_of_entries = mailbox_get(WAIT,mbox_id.niu_rxpath_rcr_update[id], rcr_update); | |
758 | ctlstat_reg = new(); | |
759 | ||
760 | total_pkts = rcr_update.pkts_checked; | |
761 | total_rcr_entries = 0; | |
762 | for(i=0;i<rcr_update.pkts_checked;i++) { | |
763 | total_rcr_entries += rcr_update.scatters[i]; | |
764 | } | |
765 | ||
766 | ctlstat_reg.update_PKTREAD = total_pkts; | |
767 | ctlstat_reg.update_PTRREAD = total_rcr_entries; | |
768 | rxdma_ctl_stat_update(2, ctlstat_reg); | |
769 | ||
770 | printf("UpdateRCRStat rxdma=%0d updated RX_DMA_CTL_STAT with PTRREAD=0x%x PKTREAD=0x%x at %0d\n", | |
771 | id, total_rcr_entries, total_pkts, get_time(LO)); | |
772 | ||
773 | /* | |
774 | for(i=0;i<rcr_update.pkts_checked;i++) { | |
775 | ctlstat_reg.update_PKTREAD = 1; | |
776 | ctlstat_reg.update_PTRREAD = rcr_update.scatters[i]; | |
777 | rxdma_ctl_stat_update(2, ctlstat_reg); | |
778 | } | |
779 | ||
780 | //update CR read pointer with num of entries read | |
781 | gen_pio_drv.pio_rd(getPIOAddress(RX_DMA_CTL_STAT_START + RXDMA_STEP*id, dis_pio_virt), rd_data, 1'b0); | |
782 | rd_data[RX_DMA_CTL_STAT_PKTREAD] = 1; // Choose these appropriately this cannot be more than rcr_update.pkts_checked | |
783 | rd_data[RX_DMA_CTL_STAT_PTRREAD] = rcr_update.scatters[i]; | |
784 | gen_pio_drv.pio_wr(getPIOAddress(RX_DMA_CTL_STAT_START + RXDMA_STEP*id, dis_pio_virt), rd_data); | |
785 | printf("UpdateRCRStat dma=%0d updated rx_dma_ctl_stat[31:0] with rcr_update 0x%h at %0d\n", | |
786 | id, {rd_data[RX_DMA_CTL_STAT_PTRREAD],rd_data[RX_DMA_CTL_STAT_PKTREAD]}, get_time(LO)); | |
787 | */ | |
788 | ||
789 | } | |
790 | } | |
791 | /////////////////////////////////////////////////////////// | |
792 | task RxDMAChannel::UpdateCompletionRing(CRxToken RxToken) { | |
793 | // Parse through the info in the Token and format the completion ring content | |
794 | completionring.UpdateCompletionRing(RxToken); | |
795 | } | |
796 | ||
797 | function integer RxDMAChannel::getPacketAddress(CRxToken RxToken) { | |
798 | // This is where the scheduler kicks in -- | |
799 | // Need to get the exact address from the scheduler | |
800 | integer status; | |
801 | integer i; | |
802 | ||
803 | printf ("[%0d] curr_ring_size = %0d, max_size = %0d\n", get_time(LO), | |
804 | descpScheduler.desc_ring.desc_ring.size(), desc_ring.ring_size); | |
805 | // TO BE CHANGED - should be baed upon reading head pointer before adding more descriptors- | |
806 | if (descpScheduler.desc_ring.desc_ring.size() > desc_ring.ring_size) { | |
807 | RxToken.pkt_type = RNGFULL_DROP_RxPKT; | |
808 | status = -1; | |
809 | } else { | |
810 | // Update Header length- | |
811 | updateHeaderLength(RxToken); | |
812 | status = descpScheduler.getAddress(RxToken); | |
813 | printf(" RDMC DEBUG - SCHEDULER RETURN ADDRESS - %x PktType Set to %d \n",RxToken.packet_start_address[0],RxToken.pkt_type); | |
814 | ||
815 | // update completion ring here | |
816 | if(RxToken.pkt_type == GOOD_RxPKT) | |
817 | UpdateCompletionRing( RxToken ); | |
818 | ||
819 | // The following are the various status- | |
820 | ||
821 | // No More - descriptor available - ie errors | |
822 | // successful and address get set in the Token | |
823 | } | |
824 | getPacketAddress = status; | |
825 | } | |
826 | ||
827 | function integer RxDMAChannel::CheckDMAStatus(CRxToken RxToken) { | |
828 | ||
829 | // A generic function which is supposed to check the DMA's status and return | |
830 | // the status of DMA. The status being - | |
831 | ||
832 | // If the DMA is inactive - | |
833 | // Is the Ring Full/Empty? | |
834 | // Is Completion Ring Full | |
835 | // Any Errors? | |
836 | ||
837 | // For now lets return valid if the DMA is active and has been kicked | |
838 | ||
839 | // Check if Completion ring ack is still pending in the host, if so | |
840 | // check for CR shadow getting full, based upon that drop the packet | |
841 | integer cr_status; | |
842 | ||
843 | if(active) { | |
844 | // cr_status = completionring.CheckPendingAckStatus(); | |
845 | // if(cr_status) | |
846 | // else { | |
847 | // CheckDMAStatus = 0; | |
848 | // RxToken.pkt_type = CRCACHE_FULL_DROP_RxPKT; | |
849 | // } | |
850 | CheckDMAStatus = 1; | |
851 | } else { | |
852 | CheckDMAStatus = 0; | |
853 | RxToken.pkt_type = RNGFULL_DROP_RxPKT; | |
854 | } | |
855 | } | |
856 | ||
857 | task RxDMAChannel::resetRxDma() { | |
858 | bit [39:0] address; | |
859 | bit [63:0] data; | |
860 | ||
861 | address = RXDMA_CFIG1 + id*40'h200; | |
862 | data = 64'h0; | |
863 | data[30] = 1; // reset bit | |
864 | //gen_pio_drv.pio_wr(address,data); | |
865 | //RXDMA_CFIG1_pio_wr(address,data); | |
866 | pio_wr_RXDMA_CFIG1(data); | |
867 | printf ("RxDMAChannel::resetRxDma() Time %0d, DMA - %0d was just reset\n", {get_time(HI),get_time(LO)}, id); | |
868 | } | |
869 | ||
870 | task RxDMAChannel::setRxDmaCfig_1(bit [63:0] data, (bit read_back = 1'b0), (bit read_only = 1'b0)){ | |
871 | bit [39:0] address; | |
872 | bit [63:0] rd_data; | |
873 | bit [63:0] data_tmp0; | |
874 | bit [63:0] Rdata0; | |
875 | bit rst_done = 1; | |
876 | bit [63:0] memArray_addr; | |
877 | bit [7:0] be = 8'hff; | |
878 | ||
879 | if(~read_only) { | |
880 | active = data[31]; | |
881 | address = RXDMA_CFIG1 + id*40'h200; | |
882 | //gen_pio_drv.pio_wr(address,data); | |
883 | //RXDMA_CFIG1_pio_wr(address, data); | |
884 | pio_wr_RXDMA_CFIG1(data); | |
885 | ||
886 | if(read_back) { | |
887 | repeat(10) @(posedge CLOCK); | |
888 | //gen_pio_drv.pio_rd(address,rd_data); | |
889 | //RXDMA_CFIG1_pio_rd(address,rd_data); | |
890 | pio_wr_RXDMA_CFIG1(data); | |
891 | } | |
892 | } else { | |
893 | while(rst_done) { | |
894 | repeat(100) @(posedge CLOCK); | |
895 | address = RXDMA_CFIG1 + id*40'h200; | |
896 | //gen_pio_drv.pio_rd(address,rd_data); | |
897 | //RXDMA_CFIG1_pio_rd(address,rd_data); | |
898 | pio_wr_RXDMA_CFIG1(rd_data); | |
899 | rst_done = rd_data[30]; | |
900 | } | |
901 | } | |
902 | ||
903 | #ifdef N2_FC | |
904 | Fc_Niu_Ev2a_setRxDmaCfig_1(data); | |
905 | #endif | |
906 | } | |
907 | ||
908 | task RxDMAChannel::SetPage0Registers(bit [31:0] mask,bit [31:0] value, bit [31:0] reloc) { | |
909 | bit [39:0] address; | |
910 | bit [63:0] memArray_addr; | |
911 | bit [63:0] Rdata0; | |
912 | bit [63:0] Rdata1; | |
913 | bit [63:0] Rdata2; | |
914 | bit [63:0] data_tmp0; | |
915 | bit [63:0] data_tmp1; | |
916 | bit [63:0] data_tmp2; | |
917 | bit [7:0] be = 8'hff; | |
918 | ||
919 | page_mask0=mask; page_value0=value; page_reloc0=reloc; | |
920 | address = RX_LOG_MASK1_START + id*8'h40; | |
921 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),{32'h0,mask}); | |
922 | ||
923 | address = RX_LOG_VAL1_START + id*8'h40; | |
924 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),{32'h0,value}); | |
925 | ||
926 | address = RX_LOG_RELO1_START + id*8'h40; | |
927 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),{32'h0,reloc}); | |
928 | ||
929 | #ifdef N2_FC | |
930 | Fc_Niu_Ev2a_SetPage0Registers (mask, value, reloc); | |
931 | #endif | |
932 | ||
933 | } | |
934 | ||
935 | task RxDMAChannel::SetPage1Registers(bit [31:0] mask,bit [31:0] value, bit [31:0] reloc) { | |
936 | bit [39:0] address; | |
937 | bit [63:0] memArray_addr; | |
938 | bit [7:0] be = 8'hff; | |
939 | bit [63:0] Rdata0; | |
940 | bit [63:0] Rdata1; | |
941 | bit [63:0] Rdata2; | |
942 | bit [63:0] data_tmp0; | |
943 | bit [63:0] data_tmp1; | |
944 | bit [63:0] data_tmp2; | |
945 | ||
946 | page_mask1=mask; page_value1=value; page_reloc1=reloc; | |
947 | address = RX_LOG_MASK2_START + id*8'h40; | |
948 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),{32'h0,mask}); | |
949 | ||
950 | address = RX_LOG_VAL2_START + id*8'h40; | |
951 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),{32'h0,value}); | |
952 | ||
953 | address = RX_LOG_RELO2_START + id*8'h40; | |
954 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),{32'h0,reloc}); | |
955 | ||
956 | #ifdef N2_FC | |
957 | Fc_Niu_Ev2a_SetPage1Registers (mask, value, reloc); | |
958 | #endif | |
959 | ||
960 | } | |
961 | ||
962 | ||
963 | // Should be used from common class between Tx and Rx | |
964 | task RxDMAChannel::setRxLogPgVld(bit [63:0] data,(bit read_back = 1'b0)) { | |
965 | ||
966 | ||
967 | bit [39:0] address; | |
968 | bit [63:0] rd_data; | |
969 | bit [63:0] Rdata0; | |
970 | bit [63:0] data_tmp0; | |
971 | bit [63:0] memArray_addr; | |
972 | bit [7:0] be = 8'hff; | |
973 | ||
974 | address = RX_LOG_PAGE_VLD + id*40'h40; | |
975 | printf("Log Page Address is %x \n", address); | |
976 | ||
977 | if(fun_no_has_been_set) { | |
978 | gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),rd_data); | |
979 | data[3:2] = rd_data[3:2]; // retain the original function number. | |
980 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),data); | |
981 | } else { | |
982 | SetDefFunc(data[3:2]); | |
983 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),data); | |
984 | } | |
985 | ||
986 | #ifdef N2_FC | |
987 | Fc_Niu_Ev2a_setRxLogPgVld (data); | |
988 | #endif | |
989 | ||
990 | ||
991 | ||
992 | if(read_back) { | |
993 | repeat(10) @(posedge CLOCK); | |
994 | gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),rd_data); | |
995 | } | |
996 | } | |
997 | ||
998 | ||
999 | task RxDMAChannel::setRbrConfig_A(bit [63:0] data, (bit read_back = 1'b0),(integer ring_page_id = 0) ){ | |
1000 | ||
1001 | bit [39:0] address; | |
1002 | integer status; | |
1003 | bit [63:0] config_rbr_data1; | |
1004 | bit [63:0] rd_data; | |
1005 | bit [63:0] Rdata0; | |
1006 | bit [63:0] data_tmp0; | |
1007 | bit [5:0] rand_num; | |
1008 | bit [63:0] memArray_addr; | |
1009 | bit [7:0] be = 8'hff; | |
1010 | ||
1011 | ||
1012 | // RBR_CFIG_A address is a function of dma channel | |
1013 | ||
1014 | rand_num = random()%64; | |
1015 | ring_size = data[63:48]; | |
1016 | address = RBR_CFIG_A + id*40'h200; | |
1017 | //config_rbr_data1 = {data[63:48],4'hf,ring_start_addr[43:6],rand_num}; | |
1018 | config_rbr_data1 = data[63:0]; | |
1019 | ring_start_addr = data[43:0]; | |
1020 | printf("RNG_STADDR %0h\n",ring_start_addr); | |
1021 | desc_ring.initRing(ring_start_addr,ring_size,xlate_on, ring_page_id); | |
1022 | desc_ring.xlate_on = xlate_on; | |
1023 | // ncu_driver.write_data(address,data); | |
1024 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),config_rbr_data1); | |
1025 | ||
1026 | #ifdef N2_FC | |
1027 | Fc_Niu_Ev2a_setRbrConfig_A (config_rbr_data1); | |
1028 | #endif | |
1029 | ||
1030 | if(read_back) { | |
1031 | repeat(10) @(posedge CLOCK); | |
1032 | gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),rd_data); | |
1033 | } | |
1034 | ||
1035 | } | |
1036 | ||
1037 | task RxDMAChannel::setZcpRdc(bit [63:0] data, (bit read_back = 1'b0)){ | |
1038 | ||
1039 | ||
1040 | bit [39:0] address; | |
1041 | bit [63:0] rd_data; | |
1042 | bit [4:0] dma_chnl; | |
1043 | dma_chnl = data[4:0]; | |
1044 | ||
1045 | address = ZCP_RDC_TBL; | |
1046 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),data); | |
1047 | ||
1048 | if(read_back) { | |
1049 | repeat(10) @(posedge CLOCK); | |
1050 | gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),rd_data); | |
1051 | } | |
1052 | ||
1053 | ||
1054 | } | |
1055 | task RxDMAChannel::setRbrConfig_B(bit [63:0] data, (bit read_back = 1'b0)){ | |
1056 | ||
1057 | ||
1058 | bit [39:0] address; | |
1059 | bit[1:0] blk_size; //00=4k,01=8K,10=16K,11=32K | |
1060 | bit[1:0] buf_siz0; | |
1061 | bit[1:0] buf_siz1; | |
1062 | bit[1:0] buf_siz2; | |
1063 | bit [63:0] config_rbr_data2; | |
1064 | bit [63:0] rd_data; | |
1065 | bit [63:0] Rdata0; | |
1066 | bit [63:0] data_tmp0; | |
1067 | bit valid0,valid1,valid2; | |
1068 | bit [63:0] memArray_addr; | |
1069 | bit [7:0] be = 8'hff; | |
1070 | ||
1071 | //config_data2 = {38'h00_0000_0000,blk_size,valid2,5'b0_0000,buf_siz2,valid1,5'b0_0000,buf_size1,valid0,5'b0_0000,buf_size0}; | |
1072 | ||
1073 | valid0 = data[7]; | |
1074 | valid1 = data[15]; | |
1075 | valid2 = data[23]; | |
1076 | ||
1077 | descpScheduler.set_blk_size(data[25:24]); | |
1078 | case(data[25:24]) { | |
1079 | 0: dma_block_size = 4096; | |
1080 | 1: dma_block_size = 8192; | |
1081 | 2: dma_block_size = 16384; | |
1082 | 3: dma_block_size = 32768; | |
1083 | default: { printf("WARNING: Not a valid block size for the RxDMA\n"); } | |
1084 | } | |
1085 | descpScheduler.set_bufsz0(data[1:0],valid0); | |
1086 | descpScheduler.set_bufsz1(data[9:8],valid1); | |
1087 | descpScheduler.set_bufsz2(data[17:16],valid2); | |
1088 | ||
1089 | descpScheduler.print(); | |
1090 | ||
1091 | address = RBR_CFIG_B + id*40'h200; | |
1092 | // Add this to descriptor carving class | |
1093 | ||
1094 | ||
1095 | ||
1096 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),data); | |
1097 | ||
1098 | if(read_back) { | |
1099 | repeat(10) @(posedge CLOCK); | |
1100 | gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),rd_data); | |
1101 | } | |
1102 | ||
1103 | #ifdef N2_FC | |
1104 | Fc_Niu_Ev2a_setRbrConfig_B (data); | |
1105 | #endif | |
1106 | ||
1107 | } | |
1108 | task RxDMAChannel::readRxRingHead(var bit [63:0] data){ | |
1109 | bit [39:0] address; | |
1110 | integer status; | |
1111 | ||
1112 | // This should be called once at the config time and then hardware updates it. | |
1113 | address = RBR_HDH + id*40'h200; | |
1114 | gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),data); | |
1115 | } | |
1116 | ||
1117 | task RxDMAChannel::setRxRingKick(bit[63:0] data){ | |
1118 | bit[39:0] address; | |
1119 | bit[15:0] no_of_desc; | |
1120 | bit [63:0] memArray_addr; | |
1121 | bit [63:0] Rdata0; | |
1122 | bit [63:0] data_tmp0; | |
1123 | bit [7:0] be = 8'hff; | |
1124 | ||
1125 | no_of_desc = data[15:0]; | |
1126 | printf("No of descriptors kicked is %0h\n", data); | |
1127 | address = RBR_KICK + id*40'h200; | |
1128 | set_descriptor(no_of_desc); | |
1129 | curr_rbr_desc_kicked_cnt += data; | |
1130 | curr_rbr_desc_kicked_cnt = curr_rbr_desc_kicked_cnt % (desc_ring.ring_size + 1); | |
1131 | ||
1132 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),data); | |
1133 | ||
1134 | #ifdef N2_FC | |
1135 | Fc_Niu_Ev2a_setRxRingKick (data); | |
1136 | #endif | |
1137 | } | |
1138 | ||
1139 | ||
1140 | task RxDMAChannel::setRcrConfig_A(bit[63:0] data, (bit read_back = 1'b0), (integer ring_page_id = 0)) { | |
1141 | bit[39:0] address; | |
1142 | bit[63:0] rd_data; | |
1143 | bit[63:0] Rdata0; | |
1144 | bit[63:0] data_tmp0; | |
1145 | bit [63:0] memArray_addr; | |
1146 | bit [7:0] be = 8'hff; | |
1147 | ||
1148 | // Add this to RCR class | |
1149 | ||
1150 | address = RCR_CFIG_A + id*40'h200; | |
1151 | completionring.config_ring(data[43:0],data[63:48],ring_page_id); | |
1152 | ||
1153 | gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),data); | |
1154 | ||
1155 | if(read_back) { | |
1156 | repeat(10) @(posedge CLOCK); | |
1157 | gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),rd_data); | |
1158 | } | |
1159 | #ifdef N2_FC | |
1160 | Fc_Niu_Ev2a_setRcrConfig_A (data); | |
1161 | #endif | |
1162 | } | |
1163 | ||
1164 | ||
1165 | // add transmit channel control and status reg | |
1166 | task RxDMAChannel::create_descriptor(var CRxdescriptor desc, bit[31:0] address, (integer pkt_page_id = 0) ){ | |
1167 | desc = new(0,pkt_page_id); | |
1168 | desc.blk_addr = address; | |
1169 | desc.valid = 1; | |
1170 | desc.pkt_page_id = pkt_page_id; | |
1171 | } | |
1172 | ||
1173 | ||
1174 | task RxDMAChannel::set_descriptor(integer no_of_desc) { | |
1175 | integer i; | |
1176 | bit[43:0] address; | |
1177 | CRxdescriptor desc; | |
1178 | ||
1179 | for(i=0; i<no_of_desc; i++) { | |
1180 | if(pkts_in_alternate_pages) | |
1181 | PktBuffers_page_id = (i%2) ? page0_id : page1_id; | |
1182 | else | |
1183 | PktBuffers_page_id = PktBuffers_page ? page1_id : page0_id; | |
1184 | address = SparseMem.get_address( (dma_block_size/SparseMem.get_block_size()),PktBuffers_page_id,dma_block_size); | |
1185 | ||
1186 | if(descr_addr_error_pkt_num!=0) { | |
1187 | if(i==descr_addr_error_pkt_num-1) { //only corrupt descr specified | |
1188 | printf("InitRXDMA descr_addr_error_pkt_num=%0d\n", descr_addr_error_pkt_num); | |
1189 | address = SparseMem.get_address( (dma_block_size/SparseMem.get_block_size()), PktBuffers_page_id+3, dma_block_size); | |
1190 | } | |
1191 | } | |
1192 | ||
1193 | create_descriptor(desc,address[43:12],PktBuffers_page_id); | |
1194 | desc_ring.add_descriptor(desc); | |
1195 | descpScheduler.pushDescForSch(address[43:12],PktBuffers_page_id); | |
1196 | } | |
1197 | } | |
1198 | ||
1199 | ||
1200 | task RxDMAChannel::InitDMAChan(integer dma_chnl, integer desc_ring_length, integer compl_ring_len, bit [63:0] rbr_config_B_data, bit [15:0] initial_kick, integer xlation) { | |
1201 | ||
1202 | bit [19:0] handle; | |
1203 | bit [15:0] RBR_LEN; | |
1204 | bit [15:0] compl_ring_length; | |
1205 | bit [39:0] ring_start_address, rcr_start_addr, mailbox_address; | |
1206 | integer status0; | |
1207 | integer status1; | |
1208 | bit [31:0] mask0, value0, reloc0; | |
1209 | bit [31:0] mask1, value1, reloc1; | |
1210 | bit full_hdr; | |
1211 | integer page_id, ret ; | |
1212 | integer byte_alignment; | |
1213 | integer blk_size, buf_siz0, buf_siz1, buf_siz2, vld0, vld1, vld2; | |
1214 | integer desired_blocks; | |
1215 | integer mailbox_size; | |
1216 | integer no_of_pages; | |
1217 | integer pkt_configurator; | |
1218 | integer sp_bsize; | |
1219 | bit rbr_addr_overflow; | |
1220 | bit [63:0] cfig2_wr_data=0; | |
1221 | bit [63:0] memArray_addr; | |
1222 | bit [7:0] be = 8'hff; | |
1223 | bit [63:0] Rdata0; | |
1224 | bit [63:0] Rdata1; | |
1225 | bit [63:0] data_tmp0; | |
1226 | bit [63:0] data_tmp1; | |
1227 | bit [1:0] func_num; | |
1228 | ||
1229 | sp_bsize = SparseMem.get_block_size(); | |
1230 | ||
1231 | if (get_plus_arg (CHECK,"PKT_CONFIGURATOR")) | |
1232 | pkt_configurator = 1; | |
1233 | else | |
1234 | pkt_configurator = 0; | |
1235 | ||
1236 | if (!pkt_configurator) { | |
1237 | // Set the dma number in the ZCP RDC Table | |
1238 | setZcpRdc({32'h0000_0000,dma_chnl}); | |
1239 | } | |
1240 | ||
1241 | // program the control header length in the hardware/shadow, bit[0] in RXDMA_CFIG2 reg | |
1242 | printf ("buffer_offset=%0d, ctrl_hdr_len=%0d\n", buffer_offset,ctrl_hdr_len); | |
1243 | if (ctrl_hdr_len==18) | |
1244 | cfig2_wr_data[0] = 1; | |
1245 | if (buffer_offset==64) | |
1246 | cfig2_wr_data[1] = 1; | |
1247 | if (buffer_offset==128) | |
1248 | cfig2_wr_data[2] = 1; | |
1249 | if (cfig2_wr_data[2:0] && (cfig2_wr_data[2:1] != 2'b11)) { | |
1250 | //gen_pio_drv.pio_wr(RXDMA_CFIG2_START + RXDMA_STEP*dma_chnl, cfig2_wr_data); | |
1251 | gen_pio_drv.pio_wr(getPIOAddress(RXDMA_CFIG2_START + RXDMA_STEP*dma_chnl, dis_pio_virt), cfig2_wr_data); | |
1252 | printf ("InitRXDMA buffer offset encoding = 2'b%b, full_hdr_len = %b for dma - %0d\n", \ | |
1253 | cfig2_wr_data[2:1], cfig2_wr_data[0], dma_chnl); | |
1254 | } | |
1255 | ||
1256 | //printf("InitRXDMA calling setRbrConfig_B rbr_config_B_data=0x%0h dma=%0d\n", rbr_config_B_data, dma_chnl); | |
1257 | setRbrConfig_B(rbr_config_B_data,1'b0); | |
1258 | ||
1259 | #ifdef N2_FC | |
1260 | #else | |
1261 | xlate_on = xlation; | |
1262 | #endif | |
1263 | ||
1264 | // RBR Setup. Using SparseMem model for unique start_addresses allocation across RDMA channels | |
1265 | handle = SparseMem.get_page_handle(); | |
1266 | printf("Value of the Page handle is %h\n", handle); | |
1267 | ||
1268 | // get mask,value and reloc for page0 | |
1269 | compl_ring_length = compl_ring_len; | |
1270 | RBR_LEN = desc_ring_length; | |
1271 | mailbox_size = 64; | |
1272 | no_of_pages = (4*RBR_LEN + 8*compl_ring_length + RBR_LEN*dma_block_size + mailbox_size)/sp_bsize; | |
1273 | //no_of_pages = (4*RBR_LEN + 8*compl_ring_length + RBR_LEN*sp_bsize + mailbox_size)/sp_bsize; | |
1274 | if (no_of_pages < 1) no_of_pages = 1; else no_of_pages = no_of_pages + 1; | |
1275 | ||
1276 | // to account for prefetch which is 4 wide 8 deep, we need to allocate 32 more than desired | |
1277 | no_of_pages += 32; | |
1278 | ||
1279 | #ifdef N2_FC | |
1280 | xlate_on = xlation; | |
1281 | if(xlate_on){ | |
1282 | status0 = SparseMem.get_page_mask(no_of_pages,0,page0_id,mask0,value0,reloc0); | |
1283 | } else { | |
1284 | mask0 = 0; | |
1285 | value0 = 0; | |
1286 | reloc0 = 0; | |
1287 | status0 = 1; | |
1288 | } | |
1289 | #else | |
1290 | status0 = SparseMem.get_page_mask(no_of_pages,0,page0_id,mask0,value0,reloc0); | |
1291 | if (!xlate_on) { | |
1292 | ret = SparseMem.force_page_contexts(page0_id, 32'h0, 32'h0, 32'h0); | |
1293 | mask0 = 0; | |
1294 | value0 = 0; | |
1295 | reloc0 = 0; | |
1296 | status0 = 1; | |
1297 | } | |
1298 | #endif | |
1299 | ||
1300 | if(status0 == -1) { | |
1301 | return; | |
1302 | printf("TB_ERROR: SparseMem.get_page_mask() function call was not Successful\n"); | |
1303 | } else { | |
1304 | // add the task set page0 registers | |
1305 | if(xlate_on) { | |
1306 | printf("InitRXDMA: RxAddressTranslation Mask0 %h Page_id %4d for DMA-%0d\n",mask0,page0_id,dma_chnl); | |
1307 | printf("InitRXDMA: RxAddressTranslation Value0 %h Page_id %4d for DMA-%0d\n",value0,page0_id,dma_chnl); | |
1308 | printf("InitRXDMA: RxAddressTranslation Reloc0 %h Page_id %4d for DMA-%0d\n",reloc0,page0_id,dma_chnl); | |
1309 | } | |
1310 | // call task setpage0 registers | |
1311 | if (xlate_on) | |
1312 | SetPage0Registers( mask0,value0,reloc0); | |
1313 | } | |
1314 | ||
1315 | // get mask,value and reloc for page1 | |
1316 | compl_ring_length = compl_ring_len; | |
1317 | RBR_LEN = desc_ring_length; | |
1318 | mailbox_size = 64; | |
1319 | no_of_pages = (4*RBR_LEN + 8*compl_ring_length + RBR_LEN*dma_block_size + mailbox_size)/sp_bsize; | |
1320 | //no_of_pages = (4*RBR_LEN + 8*compl_ring_length + RBR_LEN*sp_bsize + mailbox_size)/sp_bsize; | |
1321 | if (no_of_pages < 1) no_of_pages = 1; else no_of_pages = no_of_pages + 1; | |
1322 | ||
1323 | // to account for prefetch which is 4 wide 8 deep, we need to allocate 32 more than desired | |
1324 | no_of_pages += 32; | |
1325 | ||
1326 | #ifdef N2_FC | |
1327 | if(xlate_on){ | |
1328 | status1 = SparseMem.get_page_mask(no_of_pages,0,page1_id,mask1,value1,reloc1); | |
1329 | } else { | |
1330 | mask1 = 0; | |
1331 | value1 = 0; | |
1332 | reloc1 = 0; | |
1333 | status1 = 1; | |
1334 | } | |
1335 | #else | |
1336 | status1 = SparseMem.get_page_mask(no_of_pages,0,page1_id,mask1,value1,reloc1); | |
1337 | if (!xlate_on) { | |
1338 | ret = SparseMem.force_page_contexts(page1_id, 32'h0, 32'h0, 32'h0); | |
1339 | mask1 = 0; | |
1340 | value1 = 0; | |
1341 | reloc1 = 0; | |
1342 | status1 = 1; | |
1343 | } | |
1344 | #endif | |
1345 | ||
1346 | if(status1 == -1) { | |
1347 | return; | |
1348 | printf("TB_ERROR: SparseMem.get_page_mask() function call was not Successful\n"); | |
1349 | } else { | |
1350 | // add the task set page1 registers | |
1351 | if(xlate_on) { | |
1352 | printf("InitRXDMA: RxAddressTranslation Mask1 %h Page_id %4d for DMA-%0d\n",mask1,page1_id,dma_chnl); | |
1353 | printf("InitRXDMA: RxAddressTranslation Value1 %h Page_id %4d for DMA-%0d\n",value1,page1_id,dma_chnl); | |
1354 | printf("InitRXDMA: RxAddressTranslation Reloc1 %h Page_id %4d for DMA-%0d\n",reloc1,page1_id,dma_chnl); | |
1355 | } | |
1356 | // call task setpage1 registers | |
1357 | if (xlate_on) | |
1358 | SetPage1Registers( mask1,value1,reloc1); | |
1359 | } | |
1360 | ||
1361 | // set the id | |
1362 | id = dma_chnl; | |
1363 | ||
1364 | ||
1365 | ||
1366 | // Enable the logical pages | |
1367 | func_num = function_no; | |
1368 | setRxLogPgVld({60'h0, func_num, page1_valid, page0_valid},1'b0); | |
1369 | printf("function number assigned to rxdma%0d is %0d\n", id, func_num); | |
1370 | ||
1371 | // page_id = (random()%2) ? page0_id : page1_id; | |
1372 | ||
1373 | ||
1374 | if (random_page_alloc) { | |
1375 | RBR_page_id = (random()%2) ? page0_id : page1_id; | |
1376 | RCR_page_id = (random()%2) ? page0_id : page1_id; | |
1377 | MailBox_page_id = (random()%2) ? page0_id : page1_id; | |
1378 | PktBuffers_page_id = (random()%2) ? page0_id : page1_id; | |
1379 | } | |
1380 | else { | |
1381 | RBR_page_id = RBR_page ? page1_id : page0_id; | |
1382 | RCR_page_id = RCR_page ? page1_id : page0_id; | |
1383 | MailBox_page_id = MailBox_page ? page1_id : page0_id; | |
1384 | PktBuffers_page_id = PktBuffers_page ? page1_id : page0_id; | |
1385 | } | |
1386 | printf ("InitRXDMA(): random_page_alloc=%b, RBR_page=%0d, RCR_page=%0d, MailBox_page=%0d, PktBuffers_page=%0d\n", | |
1387 | random_page_alloc,RBR_page,RCR_page,MailBox_page,PktBuffers_page); | |
1388 | page_id = page0_id; | |
1389 | byte_alignment = 64; | |
1390 | ||
1391 | RBR_LEN = desc_ring_length; | |
1392 | printf ("SparseMem.get_block_size() = %0d\n", SparseMem.get_block_size()); | |
1393 | if ((4*RBR_LEN/SparseMem.get_block_size()) < 1) | |
1394 | desired_blocks = 1; | |
1395 | else | |
1396 | desired_blocks = 4*RBR_LEN/SparseMem.get_block_size() + 1; | |
1397 | ||
1398 | //printf ("desired_blocks asking SparseMem.get_page_mask() for ring_start_address = %0d\n", desired_blocks); | |
1399 | //To avoid rbr_addr_overflow, | |
1400 | ring_start_address = SparseMem.get_address(desired_blocks,RBR_page_id,RBR_PAGE_ALIGNMENT); | |
1401 | ||
1402 | if(dring_addr_error==1) { | |
1403 | printf("InitRXDMA dring_addr_error=1 'before corrupt' Dring_start_addr=0x%0h\n", ring_start_address); | |
1404 | ring_start_address=SparseMem.get_address(desired_blocks, RBR_page_id+3, RBR_PAGE_ALIGNMENT); | |
1405 | } | |
1406 | printf("InitRXDMA Dring_start_addr=0x%0h\n", ring_start_address); | |
1407 | ||
1408 | ||
1409 | rbr_addr_overflow = (ring_start_address[17:2]+RBR_LEN) > RBR_MAX_RING_LEN; | |
1410 | ||
1411 | while (rbr_addr_overflow) { | |
1412 | printf ("SparseMem allocated a non-64KB-aligned addr. start_addr+RBR_LEN=%0d, MAX_RBR_PAGE_LEN=65536\n"); | |
1413 | ring_start_address = SparseMem.get_address(desired_blocks,RBR_page_id,64); | |
1414 | rbr_addr_overflow = (ring_start_address[17:2]+RBR_LEN) > RBR_MAX_RING_LEN; | |
1415 | } | |
1416 | ||
1417 | ||
1418 | if(ring_start_address === 40'hzz_zzzz_zzzz) { | |
1419 | printf("TESTBENCH ERROR. SparseMem.get_address() returned an unknown value.\n"); | |
1420 | return; | |
1421 | } | |
1422 | else { | |
1423 | printf("Start Address of the RBR for dma[%0d] is %h\n", id, ring_start_address); | |
1424 | } | |
1425 | ||
1426 | // Now that we have start_addr, program the RBR_CONFIG_A register with LEN and STADDR | |
1427 | RBR_LEN = desc_ring_length; | |
1428 | rbr_ring_len = desc_ring_length; // global variable for other functions' use | |
1429 | setRbrConfig_A({RBR_LEN, 8'h00, ring_start_address}, 1'b0,RBR_page_id); | |
1430 | //moved above to get dma_block_size setRbrConfig_B(rbr_config_B_data,1'b0); | |
1431 | ||
1432 | if ((8*compl_ring_length/SparseMem.get_block_size()) < 1) | |
1433 | desired_blocks = 1; | |
1434 | else | |
1435 | desired_blocks = 8*compl_ring_length/SparseMem.get_block_size() + 1; | |
1436 | ||
1437 | rcr_start_addr = SparseMem.get_address(desired_blocks,RCR_page_id,RCR_PAGE_ALIGNMENT); | |
1438 | ||
1439 | if(cring_addr_error==1) { | |
1440 | printf("InitRXDMA cring_addr_error=1 'before corrupt' Cring_start_addr=0x%0h\n", rcr_start_addr); | |
1441 | rcr_start_addr=SparseMem.get_address(desired_blocks, RCR_page_id+3, RCR_PAGE_ALIGNMENT); | |
1442 | } | |
1443 | printf("InitRXDMA Cring_start_addr=0x%0h\n", rcr_start_addr); | |
1444 | ||
1445 | ||
1446 | if(rcr_start_addr === 40'hzz_zzzz_zzzz) { | |
1447 | printf("TESTBENCH ERROR. SparseMem.get_address() returned an unknown value.\n"); | |
1448 | return; | |
1449 | } | |
1450 | else { | |
1451 | printf("Start Address of the RCR for dma[%0d] is %h\n", id, rcr_start_addr); | |
1452 | } | |
1453 | ||
1454 | rcr_ring_len = rcr_start_addr; | |
1455 | setRcrConfig_A({compl_ring_length, 8'h0, rcr_start_addr}, 1'b0,RCR_page_id); | |
1456 | ||
1457 | // Get the mailbox address too | |
1458 | mailbox_address = SparseMem.get_address(8,MailBox_page_id,64); | |
1459 | printf ("MAILBOX address allocated by SparseMem for dma[%0d] is %h\n", id, mailbox_address); | |
1460 | ||
1461 | // program the mailbox address | |
1462 | setRxDmaCfig_1({32'h0000_0000, 24'h000000, mailbox_address[39:32]}, 1'b0); | |
1463 | full_hdr = (ctrl_hdr_len==18); | |
1464 | //gen_pio_drv.pio_wr(RXDMA_CFIG2_START+12'h200*id, {32'h0000_0000, mailbox_address[31:6], 3'b000, cfig2_wr_data[2:1], full_hdr}); | |
1465 | gen_pio_drv.pio_wr(getPIOAddress(RXDMA_CFIG2_START+12'h200*id,dis_pio_virt), {32'h0000_0000, mailbox_address[31:6], 3'b000, cfig2_wr_data[2:1], full_hdr}); | |
1466 | ||
1467 | #ifdef N2_FC | |
1468 | Fc_Niu_Ev2a_setRxDmaCfig_2 ({32'h0000_0000, mailbox_address[31:6], 6'h00}); | |
1469 | #endif | |
1470 | // Enable this particular DMA channel (#dma_chnl) | |
1471 | setRxDmaCfig_1({32'h0000_0000, 24'h800000, mailbox_address[39:32]}, 1'b0); | |
1472 | #ifdef N2_FC | |
1473 | Fc_Niu_Ev2a_setRxDmaCfig_1_1 ({32'h0000_0000, 24'h800000, mailbox_address[39:32]}); | |
1474 | #endif | |
1475 | ||
1476 | // Enable WRED by default (extremely desirable) | |
1477 | enableWRED(16'h6512, rcr_ring_len-16'h0020, 4'h0, rcr_ring_len-16'h0020, 4'h0); | |
1478 | ||
1479 | // Kick the initial number of blocks specified as the argument | |
1480 | setRxRingKick({48'h0, initial_kick}); | |
1481 | repeat (50) @(posedge CLOCK); | |
1482 | ||
1483 | ||
1484 | } | |
1485 | ||
1486 | ||
1487 | task RxDMAChannel::CheckMailboxData(bit [63:0] ctl_data_mask) { | |
1488 | bit [63:0] mbox_addr_h, mbox_addr_l,rx_dma_ctl_stat,rbr_stat,rbr_hdl,rbr_hdh,rcr_stat_a,rcr_stat_b,rcr_stat_c; | |
1489 | bit [63:0] mailbox_address,mem_read_data; | |
1490 | ||
1491 | // read the mailbox address | |
1492 | //gen_pio_drv.pio_rd(RXDMA_CFIG1_START+12'h200*id,mbox_addr_h); | |
1493 | gen_pio_drv.pio_rd(getPIOAddress(RXDMA_CFIG1_START+12'h200*id, dis_pio_virt),mbox_addr_h); | |
1494 | //gen_pio_drv.pio_rd(RXDMA_CFIG2_START+12'h200*id,mbox_addr_l); | |
1495 | gen_pio_drv.pio_rd(getPIOAddress(RXDMA_CFIG2_START+12'h200*id, dis_pio_virt),mbox_addr_l); | |
1496 | ||
1497 | printf ("RxDMAChannel::CheckMailboxData: xlate_on = %d \n", xlate_on); | |
1498 | if (!xlate_on) | |
1499 | mailbox_address = {20'h0,mbox_addr_h[11:0],mbox_addr_l[31:6],6'b0}; | |
1500 | else | |
1501 | mailbox_address = { 24'h0, SparseMem.xlate_addr({20'h0,mbox_addr_h[11:0],mbox_addr_l[31:6],6'b0}, page0_id) }; | |
1502 | ||
1503 | printf ("RxDMAChannel::CheckMailboxData: actual mailbox address %h\n", mailbox_address); | |
1504 | ||
1505 | // read all the status registers which go into the mailbox update | |
1506 | gen_pio_drv.pio_rd(getPIOAddress(RX_DMA_CTL_STAT_START+12'h200*id, dis_pio_virt),rx_dma_ctl_stat); | |
1507 | gen_pio_drv.pio_rd(getPIOAddress(RBR_STAT_START+12'h200*id, dis_pio_virt),rbr_stat); | |
1508 | gen_pio_drv.pio_rd(getPIOAddress(RBR_HDL_START+12'h200*id, dis_pio_virt),rbr_hdl); | |
1509 | gen_pio_drv.pio_rd(getPIOAddress(RBR_HDH_START+12'h200*id, dis_pio_virt),rbr_hdh); | |
1510 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_C_START+12'h200*id, dis_pio_virt),rcr_stat_c); | |
1511 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_B_START+12'h200*id, dis_pio_virt),rcr_stat_b); | |
1512 | gen_pio_drv.pio_rd(getPIOAddress(RCR_STAT_A_START+12'h200*id, dis_pio_virt),rcr_stat_a); | |
1513 | ||
1514 | ||
1515 | SparseMem.ReadMem(mailbox_address,mem_read_data,8'hff); | |
1516 | if ((mem_read_data&ctl_data_mask) != ((rx_dma_ctl_stat|64'h0000_8000_0000_0000)&ctl_data_mask)) | |
1517 | printf( "ERROR: MailBox update WRONG in bytes 0-7. Expected %h Got %h @ Addr %h\n", rx_dma_ctl_stat, mem_read_data, mailbox_address); | |
1518 | else | |
1519 | printf ("MailBox update is CORRECT in bytes 0-7. Expected %h Got %h @ Addr %h\n", rx_dma_ctl_stat, mem_read_data, mailbox_address); | |
1520 | ||
1521 | SparseMem.ReadMem(mailbox_address+8,mem_read_data,8'hff); | |
1522 | if (mem_read_data != rbr_stat) | |
1523 | printf( "ERROR: MailBox update WRONG in bytes 8-15. Expected %h Got %h @ Addr %h\n", rbr_stat, mem_read_data, mailbox_address+8); | |
1524 | else | |
1525 | printf ("MailBox update is CORRECT in bytes 8-15. Expected %h Got %h @ Addr %h\n", rbr_stat, mem_read_data, mailbox_address+8); | |
1526 | ||
1527 | SparseMem.ReadMem(mailbox_address+16,mem_read_data,8'hff); | |
1528 | if (mem_read_data[31:0] != rbr_hdl[31:0]) | |
1529 | printf( "ERROR: MailBox update WRONG in bytes 16-19. Expected %h Got %h @ Addr %h\n", rbr_hdl[31:0], mem_read_data, mailbox_address+16); | |
1530 | else | |
1531 | printf ("MailBox update is CORRECT in bytes 16-19. Expected %h Got %h @ Addr %h\n", rbr_hdl[31:0], mem_read_data, mailbox_address+16); | |
1532 | ||
1533 | SparseMem.ReadMem(mailbox_address+20,mem_read_data,8'hff); | |
1534 | if (mem_read_data[31:0] != rbr_hdh[31:0]) | |
1535 | printf( "ERROR: MailBox update WRONG in bytes 20-23. Expected %h Got %h @ Addr %h\n", rbr_hdh[31:0], mem_read_data, mailbox_address+20); | |
1536 | else | |
1537 | printf ("MailBox update is CORRECT in bytes 20-23. Expected %h Got %h @ Addr %h\n", rbr_hdh[31:0], mem_read_data, mailbox_address+20); | |
1538 | ||
1539 | SparseMem.ReadMem(mailbox_address+32,mem_read_data,8'hff); | |
1540 | if (mem_read_data[31:0] != rcr_stat_c[31:0]) | |
1541 | printf( "ERROR: MailBox update WRONG in bytes 32-35. Expected %h Got %h @ Addr %h\n", rcr_stat_c[31:0], mem_read_data, mailbox_address+32); | |
1542 | else | |
1543 | printf ("MailBox update is CORRECT in bytes 32-35. Expected %h Got %h @ Addr %h\n", rcr_stat_c[31:0], mem_read_data, mailbox_address+32); | |
1544 | ||
1545 | SparseMem.ReadMem(mailbox_address+36,mem_read_data,8'hff); | |
1546 | if (mem_read_data[31:0] != rcr_stat_b[31:0]) | |
1547 | printf( "ERROR: MailBox update WRONG in bytes 36-39. Expected %h Got %h @ Addr %h\n", rcr_stat_b[31:0], mem_read_data, mailbox_address+36); | |
1548 | else | |
1549 | printf ("MailBox update is CORRECT in bytes 36-39. Expected %h Got %h @ Addr %h\n", rcr_stat_b[31:0], mem_read_data, mailbox_address+36); | |
1550 | ||
1551 | SparseMem.ReadMem(mailbox_address+40,mem_read_data,8'hff); | |
1552 | if (mem_read_data != rcr_stat_a) | |
1553 | printf( "ERROR: MailBox update WRONG in bytes 40-47. Expected %h Got %h @ Addr %h\n", rcr_stat_a, mem_read_data, mailbox_address+40); | |
1554 | else | |
1555 | printf ("MailBox update is CORRECT in bytes 40-47. Expected %h Got %h @ Addr %h\n", rcr_stat_a, mem_read_data, mailbox_address+40); | |
1556 | ||
1557 | } | |
1558 | ||
1559 | // obseleted, see other funs | |
1560 | //task RxDMAChannel::RXDMA_CFIG1_pio_wr(bit [63:0] address, bit [63:0] data) { | |
1561 | // gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),data); | |
1562 | //} | |
1563 | // | |
1564 | //task RxDMAChannel::RXDMA_CFIG1_pio_rd(bit [63:0] address, var bit [63:0] data) { | |
1565 | // gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),data); | |
1566 | //} | |
1567 | // | |
1568 | //task RxDMAChannel::RXDMA_CFIG2_pio_wr(bit [63:0] address, bit [63:0] data) { | |
1569 | // gen_pio_drv.pio_wr(getPIOAddress(address, dis_pio_virt),data); | |
1570 | //} | |
1571 | // | |
1572 | //task RxDMAChannel::RXDMA_CFIG2_pio_rd(bit [63:0] address, var bit [63:0] data) { | |
1573 | // gen_pio_drv.pio_rd(getPIOAddress(address, dis_pio_virt),data); | |
1574 | //} | |
1575 | ||
1576 | task RxDMAChannel::periodic_kick((integer interval = 3000), | |
1577 | (integer num_desc = -1), // -1 indicate random #desc kick | |
1578 | (integer threshold = 256)) { | |
1579 | ||
1580 | bit [31:0] num_desc_local; | |
1581 | integer max_desc_can_be_kicked; | |
1582 | ||
1583 | // over write input parameters using plus args | |
1584 | if(get_plus_arg( CHECK, "RX_PERIODIC_KICK_NUM_DESC=")) | |
1585 | num_desc = get_plus_arg( NUM, "RX_PERIODIC_KICK_NUM_DESC="); | |
1586 | ||
1587 | if(get_plus_arg( CHECK, "RX_PERIODIC_KICK_THRESHOLD=")) | |
1588 | threshold = get_plus_arg( NUM, "RX_PERIODIC_KICK_THRESHOLD="); | |
1589 | ||
1590 | if(get_plus_arg( CHECK, "RX_PERIODIC_KICK_INTERVAL=")) | |
1591 | interval = get_plus_arg( NUM, "RX_PERIODIC_KICK_INTERVAL="); | |
1592 | ||
1593 | printf("<%0d> RxDMAChannel::periodic_kick: interval:%0d num_desc:%0d threshold:%0d id:%0d\n", | |
1594 | get_time(LO), interval, num_desc, threshold, id); | |
1595 | ||
1596 | // wait for init done | |
1597 | while(!active) { repeat (100) @(posedge CLOCK); } | |
1598 | ||
1599 | while(1) { | |
1600 | ||
1601 | // interval | |
1602 | if (interval <= 100) | |
1603 | interval = 3000; | |
1604 | ||
1605 | repeat (interval) @(posedge CLOCK); | |
1606 | ||
1607 | // avoid infinite loop | |
1608 | @(posedge CLOCK); | |
1609 | ||
1610 | ||
1611 | // check input parameters | |
1612 | max_desc_can_be_kicked = desc_ring.ring_size - descpScheduler.desc_ring.desc_ring.size(); | |
1613 | ||
1614 | // avoid ERROR: Modulo by zero! | |
1615 | if(max_desc_can_be_kicked == 0) | |
1616 | max_desc_can_be_kicked =1; | |
1617 | ||
1618 | // threshold | |
1619 | if(threshold > desc_ring.ring_size) { | |
1620 | threshold = desc_ring.ring_size; | |
1621 | } else if(threshold < 2) { | |
1622 | threshold = 2; // to account for large/medium/min | |
1623 | } | |
1624 | ||
1625 | // num_desc | |
1626 | if(num_desc > max_desc_can_be_kicked) { | |
1627 | num_desc_local = max_desc_can_be_kicked; | |
1628 | } else if (num_desc == -1) { | |
1629 | num_desc_local = urandom(); | |
1630 | num_desc_local = num_desc_local % (max_desc_can_be_kicked+1); | |
1631 | } else { | |
1632 | num_desc_local = num_desc; | |
1633 | } | |
1634 | ||
1635 | // Kick multiples of 16 to accomadate issue with rdmc reorder mechanism. | |
1636 | num_desc_local = num_desc_local - (num_desc_local % 16); | |
1637 | ||
1638 | // kick 16 more descriptors if it is reaching max count to avoid rtl to issue | |
1639 | // non aligned 64 byte address which will land up in out of order responses from | |
1640 | // siu bus. | |
1641 | if ((desc_ring.ring_size - curr_rbr_desc_kicked_cnt) < 16) { | |
1642 | num_desc_local += desc_ring.ring_size - curr_rbr_desc_kicked_cnt; | |
1643 | } | |
1644 | ||
1645 | ||
1646 | num_desc_local = num_desc_local % (max_desc_can_be_kicked+1); | |
1647 | ||
1648 | // avoid -ve number | |
1649 | num_desc_local[31] = 0; | |
1650 | ||
1651 | ||
1652 | if(RX_TEST_REACHED_END) { | |
1653 | printf("<%0d> RxDMAChannel::periodic_kick: exiting the task since RX_TEST_REACHED_END=1\n", get_time(LO)); | |
1654 | return; | |
1655 | } | |
1656 | ||
1657 | // if current ring size reduced to threshold, kick specified num_desc | |
1658 | if(descpScheduler.desc_ring.desc_ring.size() <= threshold) { | |
1659 | printf("<%0d> RxDMAChannel::periodic_kick: interval:%0d num_desc:%0d threshold:%0d curr_desc_size:%0d, max_desc_size:%0d, dma_id:%0d\n", | |
1660 | get_time(LO), interval, num_desc_local, threshold, descpScheduler.desc_ring.desc_ring.size(), desc_ring.ring_size, id); | |
1661 | setRxRingKick(num_desc_local); | |
1662 | } | |
1663 | } | |
1664 | } | |
1665 | ||
1666 | task RxDMAChannel::auto_periodic_kick() { | |
1667 | bit [31:0] dma_num; | |
1668 | ||
1669 | if(get_plus_arg( CHECK, "RX_PERIODIC_KICK_AUTO=")) { | |
1670 | dma_num = get_plus_arg( HNUM, "RX_PERIODIC_KICK_AUTO="); | |
1671 | if(dma_num[id] == 1'b1 && (id < 16)) { | |
1672 | fork | |
1673 | periodic_kick(); | |
1674 | join none | |
1675 | } | |
1676 | } | |
1677 | } | |
1678 | task RxDMAChannel::pio_wr_RXDMA_CFIG1(bit [63:0] rd_data) { | |
1679 | gen_pio_drv.pio_wr(getPIOAddress(RXDMA_CFIG1 + RXDMA_STEP*id, dis_pio_virt), rd_data); | |
1680 | } | |
1681 | task RxDMAChannel::pio_rd_RXDMA_CFIG1(var bit [63:0] rd_data) { | |
1682 | gen_pio_drv.pio_rd(getPIOAddress(RXDMA_CFIG1+RXDMA_STEP*id, dis_pio_virt),rd_data); | |
1683 | } | |
1684 | task RxDMAChannel::pio_wr_RXDMA_CFIG2(bit [63:0] rd_data) { | |
1685 | gen_pio_drv.pio_wr(getPIOAddress(RXDMA_CFIG2 + RXDMA_STEP*id, dis_pio_virt), rd_data); | |
1686 | } | |
1687 | task RxDMAChannel::pio_rd_RXDMA_CFIG2(var bit [63:0] rd_data) { | |
1688 | gen_pio_drv.pio_rd(getPIOAddress(RXDMA_CFIG2+RXDMA_STEP*id, dis_pio_virt),rd_data); | |
1689 | } | |
1690 | ||
1691 | task RxDMAChannel::pio_wr_RX_DMA_CTL_STAT_START(bit [63:0] rd_data) { | |
1692 | gen_pio_drv.pio_wr(getPIOAddress(RX_DMA_CTL_STAT_START + RXDMA_STEP*id, dis_pio_virt), rd_data); | |
1693 | } | |
1694 | task RxDMAChannel::pio_rd_RX_DMA_CTL_STAT_START(var bit [63:0] rd_data) { | |
1695 | gen_pio_drv.pio_rd(getPIOAddress(RX_DMA_CTL_STAT_START+RXDMA_STEP*id, dis_pio_virt),rd_data); | |
1696 | } | |
1697 | ||
1698 | task RxDMAChannel::pio_wr_RX_DMA_ENT_MSK_START(bit [63:0] rd_data) { | |
1699 | gen_pio_drv.pio_wr(getPIOAddress(RX_DMA_ENT_MSK_START + RXDMA_STEP*id, dis_pio_virt), rd_data); | |
1700 | } | |
1701 | task RxDMAChannel::pio_rd_RX_DMA_ENT_MSK_START(var bit [63:0] rd_data) { | |
1702 | gen_pio_drv.pio_rd(getPIOAddress(RX_DMA_ENT_MSK_START+RXDMA_STEP*id, dis_pio_virt),rd_data); | |
1703 | } | |
1704 | ||
1705 | task RxDMAChannel::pio_wr_RCR_CFIG_B_START(bit [63:0] rd_data) { | |
1706 | gen_pio_drv.pio_wr(getPIOAddress(RCR_CFIG_B_START + RXDMA_STEP*id, dis_pio_virt), rd_data); | |
1707 | } | |
1708 | task RxDMAChannel::pio_rd_RCR_CFIG_B_START(var bit [63:0] rd_data) { | |
1709 | gen_pio_drv.pio_rd(getPIOAddress(RCR_CFIG_B_START+RXDMA_STEP*id, dis_pio_virt),rd_data); | |
1710 | } | |
1711 | ||
1712 | task RxDMAChannel::pio_wr_RX_DMA_INTR_DEBUG_START(bit [63:0] rd_data) { | |
1713 | gen_pio_drv.pio_wr(getPIOAddress(RX_DMA_INTR_DEBUG_START + RXDMA_STEP*id, dis_pio_virt), rd_data); | |
1714 | } | |
1715 | task RxDMAChannel::pio_rd_RX_DMA_INTR_DEBUG_START(var bit [63:0] rd_data) { | |
1716 | gen_pio_drv.pio_rd(getPIOAddress(RX_DMA_INTR_DEBUG_START+RXDMA_STEP*id, dis_pio_virt),rd_data); | |
1717 | } | |
1718 | ||
1719 | task RxDMAChannel::pio_rd_RCR_CFIG_A(var bit [63:0] rd_data){ | |
1720 | gen_pio_drv.pio_rd(getPIOAddress(RCR_CFIG_A+RXDMA_STEP*id, dis_pio_virt), rd_data); | |
1721 | } | |
1722 | task RxDMAChannel::pio_rd_RX_MISC_DROP(var bit [63:0] rd_data){ | |
1723 | gen_pio_drv.pio_rd(getPIOAddress(RX_MISC_START+RXDMA_STEP*id, dis_pio_virt), rd_data); | |
1724 | } | |
1725 | task RxDMAChannel::pio_rd_RED_DISC(var bit [63:0] rd_data){ | |
1726 | gen_pio_drv.pio_rd(getPIOAddress(RED_DIS_CNT_START+RED_DIS_CNT_STEP*id, dis_pio_virt), rd_data); | |
1727 | } | |
1728 | task RxDMAChannel::pio_wr_RDC_RED_PARA(bit [63:0] rd_data) { | |
1729 | gen_pio_drv.pio_wr(getPIOAddress(RDC_RED_PARA + 'h40*id, dis_pio_virt), rd_data); | |
1730 | } | |
1731 | task RxDMAChannel::pio_rd_RDC_RED_PARA(var bit [63:0] rd_data) { | |
1732 | gen_pio_drv.pio_rd(getPIOAddress(RDC_RED_PARA+'h40*id, dis_pio_virt),rd_data); | |
1733 | } | |
1734 | ||
1735 | ||
1736 | ||
1737 |