Commit | Line | Data |
---|---|---|
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" | |
38 | extern mbox_class mbox_id; | |
39 | #include "cMesg.vrh" | |
40 | extern 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" | |
48 | extern CHostRdCbMgr hostRdCbMgr; | |
49 | #define TIME {get_time(HI), get_time(LO)} | |
50 | ||
51 | ||
52 | #define HOSTMTU 64 // TMP ONLY | |
53 | class 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 | } | |
72 | task 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 | ||
88 | task 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); | |
122 | fork { | |
123 | WaitForRelease(semId, InitialNoOfReqs); | |
124 | } join none | |
125 | ||
126 | ||
127 | } | |
128 | task 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 | ||
142 | class 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 | ||
172 | task 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 | ||
211 | task 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 | ||
238 | task 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 | } | |
261 | function 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 | ||
278 | task 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 | ||
313 | task 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 | } | |
335 | function integer CTxPortCbMgr::isQueEmpty() { | |
336 | if(PortTxTokenList.size()) { | |
337 | isQueEmpty = 0; | |
338 | } else { | |
339 | isQueEmpty = 1; | |
340 | } | |
341 | } | |
342 | function 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 | ||
354 | task 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 | } | |
371 | task 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 | ||
405 | task CTxPortCbMgr::free_transid(integer trans_id) { | |
406 | integer status; | |
407 | status = assoc_index(DELETE,TxSemId,trans_id); | |
408 | cbTxIdMgr.releaseId(trans_id); | |
409 | } | |
410 | task CTxPortCbMgr::free_req_transid(integer trans_id) { | |
411 | integer status; | |
412 | status = assoc_index(DELETE,TxTokenReqs,trans_id); | |
413 | cbTxReqIdMgr.releaseId(trans_id); | |
414 | } | |
415 | task CTxPortCbMgr::forward_token() { | |
416 | CTxToken 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 | } |