Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / txc_sat / vera / niu_txport_cb.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: niu_txport_cb.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"
38extern mbox_class mbox_id;
39#include "cMesg.vrh"
40extern Mesg be_msg;
41
42// To Support MAC Loop back mode
43#include "niu_rxtoken.vrh"
44
45#include "niu_cbclass.vrh"
46#include "niu_txcbmgr.vrh"
47#include "hostRdCbMgr.vrh"
48extern CHostRdCbMgr hostRdCbMgr;
49#define TIME {get_time(HI), get_time(LO)}
50
51
52#define HOSTMTU 64 // TMP ONLY
53class CTxSemId {
54 integer id;
55 integer port_id;
56 integer noOfReqs;
57 integer noOfResp;
58 integer trans_id;
59 bit[63:0] address[15]; // 15 gathers
60 integer length[15]; // 15 gathers
61 integer NoofGathers;
62
63 task SetCb() ;
64 task spawm_mini_cbs(bit[63:0] address, integer no_of_chunks, integer semId);
65 task WaitForRelease(integer semId, integer InitialNoOfReqs);
66
67 task new(integer i) {
68 noOfReqs = -1;
69 port_id = i;
70 }
71}
72task CTxSemId::spawm_mini_cbs(bit[63:0] address, integer no_of_chunks, integer semId){
73
74 CcbMem cb;
75 integer i;
76 bit[63:0] address_incr;
77
78 for(i=0;i<no_of_chunks;i++) {
79 cb = new(semId);
80 address_incr = address + HOSTMTU *i;
81 printf("spawm_mini_cbs - Address - %x i - %d SemId 0 %d \n",address_incr,i,semId);
82 cb.set(address_incr,GOOD_PACKET) ;
83 hostRdCbMgr.setCallBack(cb);
84 }
85
86}
87
88task CTxSemId::SetCb() {
89// for each address/length - split them into MTU chunks and
90// set the callback
91
92 integer i;
93 integer semId;
94 integer no_of_chunks;
95 bit[63:0] adjusted_address[15];
96 bit[63:0] adjusted_length[15];
97 integer InitialNoOfReqs;
98
99// This code applicable for N2 only -
100 for(i=0;i<NoofGathers;i++) {
101 adjusted_address[i] = (address[i] >>6 )<<6; // 64 bytes aligned
102 adjusted_length[i] = length[i] + ( address[i] & 6'h3f ); // extra offset due to alignment
103 }
104
105 noOfReqs = 0;
106 for(i=0;i<NoofGathers;i++) {
107 no_of_chunks = adjusted_length[i]/ HOSTMTU + ( (adjusted_length[i]%HOSTMTU) ? 1:0);
108 noOfReqs+=no_of_chunks;
109 }
110 semId = alloc(SEMAPHORE,0,1,0);
111 printf("After alloc - %d id - %d\n",noOfReqs,semId);
112 noOfReqs = 0;
113
114 for(i=0;i<NoofGathers;i++) {
115 no_of_chunks = adjusted_length[i]/ HOSTMTU + ( (adjusted_length[i]%HOSTMTU) ? 1:0);
116 spawm_mini_cbs(adjusted_address[i],no_of_chunks,semId);
117 noOfReqs+=no_of_chunks;
118 printf(" SetCb no_of_chunks - %d \n",no_of_chunks);
119 }
120 InitialNoOfReqs = noOfReqs;
121 printf("InitialNoOfReqs - %d\n",InitialNoOfReqs);
122fork {
123 WaitForRelease(semId, InitialNoOfReqs);
124 } join none
125
126
127}
128task CTxSemId::WaitForRelease(integer semId, integer InitialNoOfReqs) {
129
130 printf("WaitForRelease noOfReqs - %d SemId - %d \n",InitialNoOfReqs,semId);
131
132 @(posedge CLOCK);
133 while(semaphore_get(WAIT,semId,InitialNoOfReqs) != 1 ) {
134 repeat(100) @(posedge CLOCK);
135 }
136 printf("before mailbox WaitForRelease noOfReqs - %d SemId - %d \n",noOfReqs,semId);
137 // free this id and send the appropriate message further
138 mailbox_put(mbox_id.niu_tx_cb[port_id], this.trans_id);
139
140}
141
142class CTxPortCbMgr {
143 integer port_id;
144 integer cb_enable;
145
146 VeraList_CTxToken PortTxTokenList;
147 event lock_for_mark;
148 event freeze_token_list;
149
150 CTxSemId TxSemId[];
151 CTxToken TxTokenReqs[];
152 CcbTxIdMgr cbTxIdMgr;
153 CcbTxIdMgr cbTxReqIdMgr;
154 event lock_port_queue;
155 task new(integer i=0);
156 task pushToPortTokenList(CTxToken TxToken);
157 function integer PullPortTokenList(var CTxToken TxToken) ;
158 local function integer isQueEmpty() ;
159 local function integer isQueHeadValid();
160 local task forward_token() ;
161 local task checkForSemRelease();
162 local task MarkTokens(integer trans_id);
163 local task free_transid(integer trans_id);
164 local task free_req_transid(integer trans_id) ;
165 local task SetCb(CTxToken TxToken) ;
166 task CheckReqCbs(CTxToken TxToken) ;
167 task FreezeCurrentTokenList();
168
169
170}
171
172task CTxPortCbMgr::CheckReqCbs(CTxToken TxToken) {
173
174 integer trans_id;
175 bit[39:0] address;
176 integer semId;
177 CcbMem cb;
178 CTxToken txtoken;
179
180 if(cb_enable) {
181 fork {
182
183 while(!cbTxReqIdMgr.isAvailable() ) {
184 repeat(10) @(posedge CLOCK);
185 }
186
187 trans_id = cbTxReqIdMgr.getTransId(); // tmp for now
188 address=TxToken.xlate_gather_address[0];
189 TxTokenReqs[trans_id] = TxToken;
190
191 semId = alloc(SEMAPHORE,0,1,0);
192 cb = new(semId);
193 address = (address >>6 )<<6; // 64 bytes aligned
194 cb.set(address,READ_REQUEST) ;
195 hostRdCbMgr.setCallBack(cb);
196
197 while(semaphore_get(WAIT,semId,1) != 1 ) {
198 repeat(100) @(posedge CLOCK);
199 }
200
201 txtoken = TxTokenReqs[trans_id];
202 txtoken.pgToken.tx_request_seen = 1;
203 printf("CheckReqCbs:: TX REQUEST SEEN FOR ADDRESS - %x ID - %d\n", address,txtoken.pgToken.gId);
204 free_req_transid(trans_id);
205
206 } join none
207 }
208
209}
210
211task CTxPortCbMgr::FreezeCurrentTokenList() {
212
213 VeraListIterator_CTxToken item, next_item;
214 CTxToken Entry;
215 integer i;
216 sync(ALL,lock_for_mark);
217 trigger(OFF,freeze_token_list);
218
219 if(PortTxTokenList.size() ==1) {
220 Entry = PortTxTokenList.back();
221 Entry.CannotTouch = 1;
222 PortTxTokenList.pop_back();
223 PortTxTokenList.push_back(Entry);
224 } else if(PortTxTokenList.size() >1) {
225 item = PortTxTokenList.start();
226 while( item.neq(PortTxTokenList.finish())) {
227 Entry = item.data();
228 printf("CTxPortCbMgr::FreezeCurrentTokenList Freezing Entry: Token id - %d Size - %d Address - %x \n",Entry.id,PortTxTokenList.size(),Entry.xlate_gather_address[0]);
229 next_item = PortTxTokenList.erase(item);
230 Entry.CannotTouch = 1;
231 PortTxTokenList.insert(next_item,Entry);
232 item = next_item;
233 }
234 }
235 trigger(ON,freeze_token_list);
236}
237
238task CTxPortCbMgr::pushToPortTokenList(CTxToken TxToken) {
239 // Look at the addresses, length set the call back table etc here
240 CTxToken tmp;
241
242 // TxToken.port_data_valid = 0;
243 if(TxToken.CallBackPending) {
244 printf("DEBUG Added : cb pending pushToPortTokenList id - %d Size - %d Time - %d \n",TxToken.id,PortTxTokenList.size(),TIME);
245 } else {
246 printf("DEBUG Added : cb to be set pushToPortTokenList id - %d Size - %d Time - %d \n",TxToken.id,PortTxTokenList.size(),TIME);
247 }
248 if(TxToken.CallBackPending==0) {
249 fork {
250 SetCb(TxToken);
251 } join none
252 TxToken.CallBackPending = 1;
253 }
254 sync(ALL,lock_for_mark);
255 PortTxTokenList.push_back(TxToken);
256 tmp = PortTxTokenList.back();
257 printf("DEBUG trans_id Added Address - %x Size - %d Time - %d \n",tmp.xlate_gather_address[0],PortTxTokenList.size(),TIME);
258
259
260}
261function integer CTxPortCbMgr::PullPortTokenList(var CTxToken TxToken) {
262 sync(ALL,lock_for_mark);
263 sync(ALL,freeze_token_list);
264 if(PortTxTokenList.size()==0) {
265 PullPortTokenList = 0;
266 } else {
267 TxToken = PortTxTokenList.back();
268 if(TxToken.CannotTouch) {
269 PullPortTokenList = 0;
270 } else {
271 printf("PullPortTokenList: DEBUG trans_id - Size -%d Address - %x Time - %d id - %d \n",PortTxTokenList.size(),TxToken.xlate_gather_address[0],TIME,TxToken.id);
272 PortTxTokenList.pop_back();
273 PullPortTokenList = 1;
274 }
275 }
276}
277
278task CTxPortCbMgr::SetCb(CTxToken TxToken) {
279
280 CTxSemId TxSemIdlocal;
281 integer i;
282 integer trans_id;
283
284 while(!cbTxIdMgr.isAvailable() ) {
285 repeat(10) @(posedge CLOCK);
286 }
287 TxToken.call_back_set = 1;
288
289 TxSemIdlocal= new(port_id);
290 // TxSemIdlocal.semId = cbTxIdMgr.getSemId();
291 // trans_id = cbTxIdMgr.getTransId();
292 trans_id = cbTxIdMgr.getTransId(); // tmp for now
293 TxSemIdlocal.trans_id = trans_id;
294
295 // TxSemId.NoofGathers = TxToken.getNoofGathers();
296 TxSemIdlocal.NoofGathers = TxToken.NoofGathers;
297
298 for(i=0;i<TxSemIdlocal.NoofGathers;i++) {
299 TxSemIdlocal.address[i] = TxToken.xlate_gather_address[i];
300 TxSemIdlocal.length[i] = TxToken.gather_pkt_length[i] ;
301
302 }
303
304 TxSemId[trans_id] = new TxSemIdlocal;
305 for(i=0;i<TxSemId[trans_id].NoofGathers;i++) {
306 printf("SetCb: DEBUG trans_id - %d Address - %x i = %d \n",trans_id,TxSemId[trans_id].address[i],i);
307 printf("Token: DEBUG trans_id - %d Address - %x i = %d \n",trans_id,TxToken.xlate_gather_address[i],i);
308 }
309
310 TxSemId[trans_id].SetCb();
311}
312
313task CTxPortCbMgr::new(integer i=0) {
314 port_id = i;
315 PortTxTokenList = new();
316 trigger(ON,lock_port_queue);
317 trigger(ON,lock_for_mark);
318 trigger(ON,freeze_token_list);
319
320 if (get_plus_arg(CHECK, "SIU_CB_ENABLE")) {
321 cb_enable = 1;
322 } else {
323 cb_enable = 0;
324 }
325
326 cbTxIdMgr = new(1000);
327 cbTxReqIdMgr = new(5000);
328 fork{
329 forward_token();
330 } join none
331 fork {
332 checkForSemRelease();
333 } join none
334}
335function integer CTxPortCbMgr::isQueEmpty() {
336 if(PortTxTokenList.size()) {
337 isQueEmpty = 0;
338 } else {
339 isQueEmpty = 1;
340 }
341}
342function integer CTxPortCbMgr::isQueHeadValid() {
343 CTxToken TxToken;
344 printf("CTxPortCbMgr::isQueHeadValid Size - %d \n",PortTxTokenList.size());
345 if(PortTxTokenList.size()==0) isQueHeadValid=0;
346 else {
347 TxToken = PortTxTokenList.front();
348 isQueHeadValid = TxToken.port_data_valid;
349 printf("CTxPortCbMgr::isQueHeadValid Valid - %d Address - %x \n",isQueHeadValid,TxToken.xlate_gather_address[0]);
350
351 }
352}
353
354task CTxPortCbMgr::checkForSemRelease() {
355 integer trans_id;
356 integer no_of_entries;
357 while(1) {
358 @(posedge CLOCK);
359 no_of_entries = mailbox_get(WAIT,mbox_id.niu_tx_cb[port_id], trans_id);
360 printf("Before Sync ALL Time - %d \n",TIME);
361 sync(ALL,lock_port_queue);
362 printf("After Sync ALL Time - %d \n",TIME);
363
364 printf("checkForSemRelease releasing %d \n",trans_id);
365 sync(ALL,freeze_token_list);
366 trigger(OFF,lock_for_mark);
367 MarkTokens(trans_id);
368 trigger(ON,lock_for_mark);
369 }
370}
371task CTxPortCbMgr::MarkTokens(integer trans_id) {
372 bit[63:0] packet_address;
373 VeraListIterator_CTxToken item, next_item;
374 CTxToken Entry;
375 bit match;
376 integer status;
377 integer i;
378
379 packet_address = TxSemId[trans_id].address[0];
380 for(i=0;i<TxSemId[trans_id].NoofGathers;i++) {
381 printf("MarkTokens DEBUG trans_id - %d Address - %x i = %d Size - %d Time - %d \n",trans_id,TxSemId[trans_id].address[i],i,PortTxTokenList.size(),TIME);
382 }
383 // scan through the token list for this address and mark it good
384 match = 0;
385 item = PortTxTokenList.start();
386 while(!match & item.neq(PortTxTokenList.finish())) {
387 Entry = item.data();
388 printf("DEBUG packet_address - %x Entry.xlate_gather_address[0] - %x \n",packet_address,Entry.xlate_gather_address[0]);
389 if(Entry.xlate_gather_address[0] == packet_address) {
390 next_item = PortTxTokenList.erase(item);
391 Entry.port_data_valid = 1;
392 printf(" CTxPortCbMgr::MarkTokens Validating Entry: Token id - %d Size - %d Address - %x \n",Entry.id,PortTxTokenList.size(),packet_address);
393 PortTxTokenList.insert(next_item,Entry);
394 match = 1;
395 } else {
396 item.next();
397 }
398 }
399 if(match==0) printf(" SOMETHING WRONG!! CTxPortCbMgr::MarkTokens ERROR Time - %d \n",TIME);
400 free_transid(trans_id);
401
402
403}
404
405task CTxPortCbMgr::free_transid(integer trans_id) {
406 integer status;
407 status = assoc_index(DELETE,TxSemId,trans_id);
408 cbTxIdMgr.releaseId(trans_id);
409}
410task CTxPortCbMgr::free_req_transid(integer trans_id) {
411 integer status;
412 status = assoc_index(DELETE,TxTokenReqs,trans_id);
413 cbTxReqIdMgr.releaseId(trans_id);
414}
415task CTxPortCbMgr::forward_token() {
416CTxToken TxToken;
417
418 while(1) {
419 while(isQueEmpty()) @(posedge CLOCK);
420 while(isQueHeadValid()==0) @(posedge CLOCK);
421 sync(ALL,lock_for_mark);
422 sync(ALL,freeze_token_list);
423 TxToken = PortTxTokenList.front();
424 printf("DEBUG trans_id Forwarding Token: Address - %x Time - %d id - %d \n",TxToken.xlate_gather_address[0],TIME,TxToken.id);
425 mailbox_put(mbox_id.mac_opp[this.port_id],TxToken.pgToken);
426 PortTxTokenList.pop_front();
427 }
428}