Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / rxc_sat / vera / rxdma / niu_rx_descp_cr.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: niu_rx_descp_cr.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
41#include "pg_top_pp.vrh"
42#include "pc_top_pp.vrh"
43#include "pcg_token.vrh"
44#include "niu_rxtoken.vrh"
45#include "niu_mem.vrh"
46#include "cMesg.vrh"
47#include "niu_cbclass.vrh"
48#include "hostRdCbMgr.vrh"
49#include "niu_rx_crentry.vrh"
50#include "mac_pio_class.vrh"
51
52extern CSparseMem SparseMem;
53extern mac_pio_cl mac_pio_class;
54
55extern Mesg be_msg;
56
57#define NO_OF_ENTRIES_UPDATED 8
58#define CR_WRITE_THRESHOLD 8
59#define MAX_CR_CACHE_SIZE 32
60
61extern CHostRdCbMgr hostRdCbMgr;
62
63class CCompletionRing {
64
65 VeraList_Ccr_entry completion_ring;
66 VeraList_Ccr_entry local_cr_cache;
67 integer no_of_entries;
68 bit [63:0] ring_start_address;
69 bit[63:0] last_read_address;
70 integer last_ring_index;
71 bit [18:0] ring_length; // check exact bits needed
72 integer ring_index;
73 integer rewind_last_ring_index;
74 integer page_id;
75 integer dma_num;
76 integer set_cr_cb;
77 integer cr_ack_pending;
78 integer startSemId;
79 // Added head/tail pointers . start address etc etc
80
81 task new () {
82 completion_ring = new();
83 local_cr_cache = new();
84 no_of_entries = 0;
85 cr_ack_pending = 0;
86 set_cr_cb = 0;
87 startSemId = alloc(SEMAPHORE,0,1,0);
88 fork {
89 spCacheWriteAckCb();
90 } join none
91 }
92
93 task UpdateCompletionRing(CRxToken RxToken);
94 task UpdateCRLastAddress(integer n) ;
95 local task UpdateAddress() ;
96 local function Ccr_entry format_entry(CRxToken RxToken, integer chain, integer index);
97 local task add_entry(Ccr_entry entry);
98
99 task config_ring( bit[63:0] start_address, bit [15:0] length, (integer ring_page_id = 0) ) {
100 // ring_start_address = start_address;
101 page_id = ring_page_id;
102 printf("config_ring page_id - %d dma_no - %d \n",page_id,dma_num);
103 ring_start_address = SparseMem.xlate_addr( start_address[39:0], ring_page_id );
104 ring_length = length <<3;
105 ring_index = 0;
106 last_read_address = ring_start_address;
107 last_ring_index = ring_index;
108 rewind_last_ring_index = ring_index;
109 }
110 local function bit[1:0] cr_encode_pkttype(integer pkt_class) ;
111 local task SetCRhostCb(Ccr_entry entry);
112 local task spCacheWriteAckCb();
113 local task setHostCb(bit[63:0] address);
114 local function integer free_local_cache(integer no_of_entries);
115
116 function integer ReadCrEntry( integer no_of_entries, var Ccr_entry cr[*]) ;
117
118 task CheckSysMem(integer no_of_entries);
119 function integer CheckPendingAckStatus();
120}
121
122function bit[1:0] CCompletionRing::cr_encode_pkttype(integer pkt_class){
123
124 printf(" DEBUG- pktclass - %d \n",pkt_class);
125 if((pkt_class== CL_TCP) | ( pkt_class== CL_TCP_OPT) | ( pkt_class== CL_TCP_IP_V6)) {
126 cr_encode_pkttype = 2'b01;
127 } else if( (pkt_class== CL_UDP) | ( pkt_class== CL_UDP_OPT) | (pkt_class== CL_UDP_IP_V6) ) {
128 cr_encode_pkttype = 2'b10;
129 } else if( (pkt_class== CL_SCTP) | ( pkt_class== CL_SCTP_OPT) | (pkt_class== CL_SCTP_IP_V6) ) {
130 cr_encode_pkttype = 2'b11;
131 } else {
132 cr_encode_pkttype = 2'b00;
133 }
134}
135
136function Ccr_entry CCompletionRing::format_entry(CRxToken RxToken, integer chain, integer index) {
137// various fields in the entry
138bit multi;
139bit [1:0] pkt_type;
140bit zcp;
141bit frag;
142bit promis;
143bit dcf_error;
144bit [2:0] errors;
145bit[13:0] length;
146bit [1:0] pktbufsz;
147bit[63:0] address;
148Ccr_entry cr;
149
150cr = new();
151
152multi = chain;
153//pkt_type= (index==0) ? cr_encode_pkttype(RxToken.getPktClass()):0 ;
154pkt_type= cr_encode_pkttype(RxToken.getPktClass()); // this field will be the same for all block buffers of this jumbo
155zcp = 0;// review;
156frag = (RxToken.pgToken.pack_db.flow.frame.frame_class == CL_TCP_FRAG) |
157 (RxToken.pgToken.pack_db.flow.frame.frame_class == CL_UDP_FRAG) |
158 (RxToken.pgToken.pack_db.flow.frame.frame_class == CL_SCTP_FRAG) ;
159errors = cr.setCRErrorCode(RxToken.getErrorCode());
160length = RxToken.pkt_length ;
161address = RxToken.packet_virtaddress[index];
162pktbufsz = RxToken.bufsz;
163dcf_error = 0;
164
165promis = 1'b0; // REMOVE THIS AND UNCOMMENT THE NEXT LINE
166// promis = mac_pio_class.isMACPromisBitSet(RxToken.port_num);
167
168cr.entry = {multi,pkt_type,zcp,frag,promis,errors,dcf_error,length,pktbufsz,address[43:6]};
169printf(" Ccr_entry CCompletionRing::format_entry index - %d multi - %d entry - %x\n",index,multi,cr.entry);
170format_entry = new cr;
171
172}
173
174task CCompletionRing::UpdateAddress() {
175 printf("CCompletionRing::UpdateAddress Before Update ast_ring_index - %d ring_length - %d \n",last_ring_index,ring_length);
176 last_ring_index++;
177 if( (8*last_ring_index) >= ring_length) {
178 last_ring_index = 0; // wrap around case
179 }
180 last_read_address = ring_start_address + 8*last_ring_index;
181 printf("CCompletionRing::UpdateAddress After Update ast_ring_index - %d Address - %x \n",last_ring_index,last_read_address);
182}
183
184task CCompletionRing::UpdateCRLastAddress(integer n) {
185
186 if( (8*rewind_last_ring_index) > ring_length)
187 rewind_last_ring_index = 0; // wrap around case
188 else {
189 rewind_last_ring_index = (rewind_last_ring_index + n )% (ring_length/8);
190 }
191 printf("CCompletionRing::UpdateCRLastAddress n - %d, rewind_last_index - %d ring_length - %d \n",n,rewind_last_ring_index,ring_length);
192 last_read_address = ring_start_address + 8*rewind_last_ring_index;
193 last_ring_index = rewind_last_ring_index;
194 printf("CCompletionRing::UpdateCRLastAddress n - %d, last_index - %d ring_length - %d \n",n,last_ring_index,ring_length);
195}
196
197task CCompletionRing::add_entry(Ccr_entry entry) {
198
199 bit [63:0] address;
200 address = ring_start_address + 8*ring_index;
201 // pointer manipulations ignored for now
202 entry.address = address;
203 entry.print();
204 completion_ring.push_back(entry);
205 if(set_cr_cb) {
206 SetCRhostCb(entry);
207 }
208 if( (8*ring_index) > ring_length)
209 ring_index = 0; // wrap around case
210 else ring_index++;
211}
212
213task CCompletionRing::SetCRhostCb(Ccr_entry entry) {
214 if(local_cr_cache.size() <= MAX_CR_CACHE_SIZE) {
215 local_cr_cache.push_back(entry);
216 } else {
217 printf(" ERROR local_cr_cache is FULL - Size - %d\n",local_cr_cache.size());
218 }
219}
220
221function integer CCompletionRing::CheckPendingAckStatus() {
222 integer size;
223 size = local_cr_cache.size();
224 if(size==MAX_CR_CACHE_SIZE) {
225 CheckPendingAckStatus = 0;
226 } else {
227 CheckPendingAckStatus = 1;
228 }
229 // Disable this for now
230 CheckPendingAckStatus = 1;
231 printf("CCompletionRing::CheckPendingAckStatus Status - %d Size = %d \n",CheckPendingAckStatus,size);
232}
233
234task CCompletionRing::spCacheWriteAckCb() {
235
236 bit [63:0] address;
237 Ccr_entry cr;
238 while(1) {
239 while(local_cr_cache.size() < CR_WRITE_THRESHOLD) {
240 // just wait for cache to be filled up
241 repeat(10) @(posedge CLOCK);
242 }
243 // if there is a pending callback wait for that to be done before setting the next one
244 while(cr_ack_pending) {
245 repeat(10) @(posedge CLOCK);
246 }
247 // else - not set the call back on the address
248 cr = local_cr_cache.front();
249 address = cr.address;
250 setHostCb(address);
251 }
252}
253
254task CCompletionRing::setHostCb( bit[63:0] address) {
255
256 CcbMem cb;
257 shadow bit[63:0] cr_address;
258 integer status;
259 integer semId;
260
261 cr_ack_pending = 1;
262
263 semId = startSemId;
264 cr_address = address;
265 cb = new(semId);
266 cb.set(address,CR_WAIT_FOR_ACK);
267 hostRdCbMgr.setCallBack(cb);
268
269 fork {
270 while(semaphore_get(WAIT,semId,1) == 0 ) {
271 repeat(10) @(posedge CLOCK);
272 }
273 printf(" CCompletionRing::setHostCb:: ACK RECEIVED FOR ADDRESS - %x \n",cr_address);
274 status = free_local_cache(NO_OF_ENTRIES_UPDATED);
275 cr_ack_pending = 0;
276 } join none
277 printf(" Done with CCompletionRing::setHostCb!! \n");
278}
279
280function integer CCompletionRing::free_local_cache(integer no_of_entries) {
281 integer i;
282 Ccr_entry cr;
283 if(no_of_entries > local_cr_cache.size()) {
284 printf(" TESTBENCH ERROR CCompletionRing::free_local_cache:: \n");
285 free_local_cache = -1;
286 } else {
287 for( i=0;i< no_of_entries; i++) {
288 cr = local_cr_cache.front();
289 printf(" FREEING UP Entry at address - %x \n",cr.address);
290 local_cr_cache.pop_front();
291 }
292 free_local_cache = 1;
293 }
294}
295
296task CCompletionRing::UpdateCompletionRing(CRxToken RxToken) {
297
298 // Format the content of the entry
299 Ccr_entry entry;
300 integer chain, index;
301
302 printf(" CCompletionRing::UpdateCompletionRing :: %d \n",RxToken.NoOfScatter);
303 for(index = 0 ; index < RxToken.NoOfScatter; index++ ) {
304
305 if( index == (RxToken.NoOfScatter -1) ) {
306 chain = 0;
307 } else chain =1;
308 printf(" CCompletionRing::UpdateCompletionRing ::index - %d chain - %d \n",index,chain);
309 entry = format_entry(RxToken, chain, index);
310 // if the ring is full.. do appropriate things here
311 // else add it -- for now
312 add_entry(entry);
313 if(index == (RxToken.NoOfScatter -1)) {
314 RxToken.cr_address = SparseMem.xlate_addr( entry.address[39:0], page_id );
315 }
316 }
317
318}
319
320function integer CCompletionRing::ReadCrEntry( integer no_of_entries, var Ccr_entry cr[*]) {
321
322 integer size;
323 integer i;
324 bit [63:0] rd_data;
325 bit [63:0] address;
326 Ccr_entry cr_mem;
327
328 cr = new[no_of_entries];
329
330 for(i=0;i< (no_of_entries) ;i ++ ) {
331 printf("CCompletionRing::ReadCrEntry DEBUG last_Address - %x last index - %d page_id - %d \n",last_read_address,last_ring_index,page_id);
332 address = SparseMem.xlate_addr( last_read_address[39:0], page_id );
333 SparseMem.ReadMem(address,rd_data,8'hff);
334 printf("CCompletionRing::ReadCrEntry Address - %x data - %x \n",last_read_address,rd_data);
335 cr[i] = new();
336 cr[i].set_fields(rd_data);
337 cr[i].address = address;
338 UpdateAddress();
339 }
340 ReadCrEntry = 1;
341}
342
343task CCompletionRing::CheckSysMem(integer no_of_entries) {
344
345integer size;
346integer i;
347bit [63:0] rd_data;
348bit [63:0] address;
349Ccr_entry cr;
350integer jumbo_pkt_num=0;
351
352// get the current size of the ring and make sure the no_of_entries
353// to check is not more than the size
354if(completion_ring.size() < (no_of_entries) ) {
355 printf(" ERROR -- USER ERROR, Current ring shadow size - %d , check requested for size - %d \n",completion_ring.size(), no_of_entries);
356} else {
357
358 for(i=0;i< (no_of_entries) ;i ++ ) {
359 cr = completion_ring.front();
360 completion_ring.pop_front();
361
362 address = cr.address;
363 SparseMem.ReadMem(address,rd_data,8'hff);
364 // TMP DISABLE CHECK OF PROMS BIT
365 rd_data[58] = 1'b0; // REMOVE THIS
366 if(rd_data!=cr.entry) {
367 be_msg.print(e_mesg_error,"CCompletionRing::CheckSysMem","", "CR: Mismatch. Model %x RTL %x @ Addr %x dma_num %0d, pkt_id %0d\n",cr.entry,rd_data,address,dma_num,jumbo_pkt_num);
368 printf(" EXPECTED DATA - multi - %b, pkt_type = %b error - %b length - %d pktbufsz - %b address - %x \n",cr.entry[63],cr.entry[62:61], cr.entry[57:55], cr.entry[53:40], cr.entry[39:38], cr.entry[37:0]);
369 printf(" DATA IN MEMORY - multi - %b, pkt_type = %b error - %b length - %d pktbufsz - %b address - %x \n",rd_data[63],rd_data[62:61], rd_data[57:55], rd_data[53:40], rd_data[39:38], rd_data[37:0]);
370 }
371 else {
372 be_msg.print(e_mesg_info,"CCompletionRing::CheckSysMem","", "CR: Data Matched! Model %x RTL %x @ Addr %x dma_num %0d, pkt_id %0d\n",cr.entry,rd_data,address,dma_num,jumbo_pkt_num);
373 }
374 if (!cr.entry[63]) jumbo_pkt_num++;
375 }
376}
377
378}
379
380
381