Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / model / pcie / peu / ilu_intf.cpp
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: ilu_intf.cpp
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 "ilu_intf.hpp"
36#include "pcie_common/logger.hpp"
37
38namespace pcie {
39
40 /**
41 * Binary to gray code helper function
42 */
43 sc_uint<32> bin2gc (sc_uint<32> binval) {
44 sc_uint<32> gcval = 0;
45 sc_uint<1> bit_zero = 0;
46
47 gcval = binval ^ (bit_zero, binval(32-1, 1));
48 return gcval;
49 }
50
51 /**
52 * Gray code to binary helper function
53 */
54 sc_uint<32> gc2bin (sc_uint<32> gcval) {
55 sc_uint<32> binval = 0;
56 int i;
57
58 binval[32-1] = gcval[32-1];
59 for (i = (32 - 2); i >= 0; --i)
60 binval[i] = binval[i+1] ^ gcval[i];
61 return binval;
62 }
63
64 /**
65 * Parity calculator
66 */
67 int parity (sc_uint<32> data) {
68 sc_uint<1> par =0;
69
70 par = 1;
71 for (int i = 0; i < 32; i++) {
72 par ^= (data & 1);
73 data >>= 1;
74 }
75 return par;
76 }
77
78 /**
79 * This thread collects outgoing Hdr from the ILU and loads it into the EHB.
80 */
81 void ilu_intf::ehb_write(void) {
82 bool ehb_we = false;
83 sc_uint<D2P_EHB_ADDR_WDTH> ehb_addr;
84
85 while (1) {
86 wait(clk.negedge_event());
87 ehb_we = d2p_ehb_we.read();
88 ehb_addr = d2p_ehb_addr.read().to_uint();
89
90 if (ehb_we) {
91 ehb_buffer[ehb_addr](127,0) = d2p_ehb_data.read();
92 ehb_buffer[ehb_addr](131,128) = d2p_ehb_dpar.read();
93
94 LOG_DEBUG << "EHB Write @ " << ehb_addr
95 << " DATA: " << (string) d2p_ehb_data.read().to_string();
96 }
97 }
98 }
99
100 /**
101 * This thread collects outgoing data from the ILU and loads it into the EDB.
102 */
103 void ilu_intf::edb_write(void) {
104 bool edb_we;
105 sc_uint<D2P_EDB_ADDR_WDTH> edb_addr;
106
107 while (1) {
108 wait(clk.negedge_event());
109 edb_we = d2p_edb_we.read();
110 edb_addr = d2p_edb_addr.read().to_uint();
111
112 if (edb_we) {
113 edb_buffer[edb_addr](127,0) = d2p_edb_data.read();
114 edb_buffer[edb_addr](131,128) = d2p_edb_dpar.read();
115 LOG_DEBUG << "EDB Write @ " << edb_addr;
116
117 if (edb_addr < 0x80)
118 ecd_waddr += 1;
119 else
120 erd_waddr += 1;
121 }
122 }
123 }
124
125 /**
126 * This thread provides IHB content to the ILU.
127 */
128 void ilu_intf::ihb_read(void) {
129 bool ihb_rd;
130 sc_uint<D2P_IHB_ADDR_WDTH> ihb_addr;
131
132 while (1) {
133 wait (clk.negedge_event());
134 ihb_addr = d2p_ihb_addr.read().to_uint();
135 ihb_rd = d2p_ihb_rd.read();
136
137 if (ihb_rd) {
138 wait (clk.posedge_event());
139 if ( (bin2gc(ihb_addr) != ihb_wptr) && (!ihb_empty) ) {
140 p2d_ihb_dpar.write ( ihb_buffer[ihb_addr]
141 (P2D_IHB_DATA_WDTH+P2D_IHB_DPAR_WDTH-1,
142 P2D_IHB_DATA_WDTH)
143 );
144 p2d_ihb_data.write(ihb_buffer[ihb_addr](P2D_IHB_DATA_WDTH-1, 0));
145 LOG_DEBUG << "IHB Read @ " << ihb_addr;
146 } else {
147 ihb_empty = true;
148 LOG_DEBUG << "Reading empty IHB @ " << ihb_addr;
149 }
150 }
151 }// while(1)
152 }//end ihb_read()
153
154 /**
155 * This thread provides IDB content to the ILU.
156 */
157 void ilu_intf::idb_read(void) {
158 bool idb_rd;
159 sc_uint<D2P_IDB_ADDR_WDTH> idb_addr;
160
161 while (1) {
162 wait (clk.negedge_event());
163 idb_addr = d2p_idb_addr.read().to_uint();
164 idb_rd = d2p_idb_rd.read();
165
166 if (idb_rd) {
167 wait (clk.posedge_event());
168 p2d_idb_dpar.write ( idb_buffer[idb_addr]
169 (P2D_IDB_DATA_WDTH+P2D_IDB_DPAR_WDTH-1,
170 P2D_IDB_DATA_WDTH) );
171 p2d_idb_data.write(idb_buffer[idb_addr](P2D_IDB_DATA_WDTH-1, 0));
172 //LOG_DEBUG << "IDB Read @ " << idb_addr;
173 }
174 }// while(1)
175 }
176
177 /**
178 * This thread receives ingress TLPs from the lower layers (i.e. ITL), and loads
179 * it into the IHB and IDB.
180 */
181 void ilu_intf::ingress_packet_handler() {
182 LOG_INFO<<"ILU_INTF: ingress_packet_handler begins...";
183 RefPciePacket next_pkt;
184 //sc_uint<D2P_IHB_ADDR_WDTH> ihb_wr_addr;
185 //sc_uint<D2P_IHB_ADDR_WDTH+1> nxt_ihb_wr_addr;
186 sc_uint<10> pld_len;
187 sc_uint<10> idb_wr_len;
188 //sc_uint<D2P_IDB_ADDR_WDTH> idb_wr_addr;
189 //sc_uint<D2P_IDB_ADDR_WDTH> nxt_idb_wr_addr;
190
191 //ihb_wr_addr = 0;
192 //nxt_ihb_wr_addr = 0;
193 try{
194 while (true) {
195 in_pkt_port.get_packet(next_pkt);
196 LOG_DEBUG << "Received Ingress Packet " << next_pkt->to_string();
197 //cout<< sc_time_stamp() << " ILU_INTF: Received TLP " << next_pkt->getPacketId() << " from itl." << endl;
198 if(next_pkt->get_control() == DROP_TLP_ILUINTF_RECOVER_CREDITS){//indicates that the packet is to be dropped in here and credits are to be recovered
199 LOG_DEBUG<<"Recvd pkt to be dropped";
200 if(next_pkt->isCmpl()){
201 LOG_DEBUG<<"Recovering CHC/CDC...";
202 recovered_credits.range(CHC) = recovered_credits.range(CHC) + 1;
203 if(next_pkt->hasData()){
204 sc_uint<12> cred = (GET_TLP_LEN(next_pkt))/4;
205 if((GET_TLP_LEN(next_pkt))%4 != 0) cred++;
206 recovered_credits.range(CDC) = recovered_credits.range(CDC) + cred;
207 }
208 }
209 else if(next_pkt->isPosted()){
210 LOG_DEBUG<<"Recovering PHC/PDC...";
211 recovered_credits.range(PHC) = recovered_credits.range(PHC) + 1;
212 if(next_pkt->hasData()){
213 sc_uint<12> cred = (GET_TLP_LEN(next_pkt))/4;
214 if((GET_TLP_LEN(next_pkt))%4 != 0) cred++;
215 recovered_credits.range(PDC) = recovered_credits.range(PDC) + cred;
216 }
217 }
218 else{
219 LOG_DEBUG<<"Recovering NHC/NDC...";
220 recovered_credits.range(NHC) = recovered_credits.range(NHC) + 1;
221 if(next_pkt->hasData()){
222 sc_uint<12> cred = (GET_TLP_LEN(next_pkt))/4;
223 if((GET_TLP_LEN(next_pkt))%4 != 0) cred++;
224 recovered_credits.range(NDC) = recovered_credits.range(NDC) + cred;
225 }
226 }
227 }
228 else {
229 ihb_empty = false;
230 ihb_wr_addr = nxt_ihb_wr_addr;
231 nxt_ihb_wr_addr += 1;
232 if(!drain_state && !POR_RESET ){
233 int hdr_size;
234 if (GET_TLP_FMT(next_pkt) & 0x01) {
235 hdr_size = 16;
236 } else {
237 hdr_size = 12;
238 }
239
240 /// Load the Header into Header buffer
241 for (int byte = 15, pkt_byte=0; pkt_byte < hdr_size; byte--, pkt_byte++) {
242 ihb_buffer[ihb_wr_addr](byte*8+7, byte*8) =
243 next_pkt->get_byte(TLP_HDR_START + pkt_byte);
244 }
245
246 /// Calculate Header Parity
247 ihb_buffer[ihb_wr_addr][128] = parity(ihb_buffer[ihb_wr_addr](31,0).to_uint());
248 ihb_buffer[ihb_wr_addr][129] = parity(ihb_buffer[ihb_wr_addr](63,32).to_uint());
249 ihb_buffer[ihb_wr_addr][130] = parity(ihb_buffer[ihb_wr_addr](95,64).to_uint());
250 ihb_buffer[ihb_wr_addr][131] = parity(ihb_buffer[ihb_wr_addr](127,96).to_uint());
251
252 /// Polulate Data buffers, if data associated with the packet
253 if ((GET_TLP_FMT(next_pkt) >> 1) &&
254 ((next_pkt->get_byte(TLP_HDR_START) != tlp_IORd) &&
255 (next_pkt->get_byte(TLP_HDR_START) != tlp_IOWr) &&
256 (next_pkt->get_byte(TLP_HDR_START) != tlp_MRdLk_32) &&
257 (next_pkt->get_byte(TLP_HDR_START) != tlp_MRdLk_64) &&
258 (next_pkt->get_byte(TLP_HDR_START) != tlp_CfgRd0) &&
259 (next_pkt->get_byte(TLP_HDR_START) != tlp_CfgRd1) &&
260 (next_pkt->get_byte(TLP_HDR_START) != tlp_CfgWr0) &&
261 (next_pkt->get_byte(TLP_HDR_START) != tlp_CfgWr1) )
262 ) { // Packet with data
263 pld_len = GET_TLP_LEN(next_pkt);
264 idb_wr_len = pld_len(9,2);
265 LOG_DEBUG << "Payload Length: " << pld_len << " IDB Write Len: " << idb_wr_len;
266
267 int pkt_byte_ctr = TLP_HDR_START+hdr_size;
268 for (int idb_ctr = 0; idb_ctr < idb_wr_len; idb_ctr++) {
269 idb_wr_addr = nxt_idb_wr_addr;
270 nxt_idb_wr_addr += 1;
271 for (int byte = 15; byte >= 0; byte--) {
272 idb_buffer[idb_wr_addr](byte*8+7, byte*8) =
273 next_pkt->get_byte(pkt_byte_ctr++);
274 idb_buffer[idb_wr_addr][128] =
275 parity(idb_buffer[idb_wr_addr](31,0).to_uint());
276 idb_buffer[idb_wr_addr][129] =
277 parity(idb_buffer[idb_wr_addr](63,32).to_uint());
278 idb_buffer[idb_wr_addr][130] =
279 parity(idb_buffer[idb_wr_addr](95,64).to_uint());
280 idb_buffer[idb_wr_addr][131] =
281 parity(idb_buffer[idb_wr_addr](127,96).to_uint());
282 }
283 }
284 if (pld_len(1,0).or_reduce()) {
285 idb_wr_addr = nxt_idb_wr_addr;
286 nxt_idb_wr_addr += 1;
287 sc_uint<32> idb_byte_cnt = pld_len(1,0) * 4;
288
289 for (int byte = 15; byte > 15-(pld_len(1,0)*4); byte--) {
290 idb_buffer[idb_wr_addr](byte*8+7, byte*8) =
291 next_pkt->get_byte(pkt_byte_ctr++);
292
293 idb_buffer[idb_wr_addr][128] =
294 parity(idb_buffer[idb_wr_addr](31,0).to_uint());
295 idb_buffer[idb_wr_addr][129] =
296 parity(idb_buffer[idb_wr_addr](63,32).to_uint());
297 idb_buffer[idb_wr_addr][130] =
298 parity(idb_buffer[idb_wr_addr](95,64).to_uint());
299 idb_buffer[idb_wr_addr][131] =
300 parity(idb_buffer[idb_wr_addr](127,96).to_uint());
301 }
302 }
303 } // If Payload
304 WAIT(clk.posedge_event());
305 p2d_ihb_wptr.write(bin2gc(nxt_ihb_wr_addr));
306 ihb_wptr = bin2gc(nxt_ihb_wr_addr);
307 }//end if(!drain_state)
308 else WAIT(clk.posedge_event());
309 }
310 } //end while(1)
311 }//end try
312 catch(sc_exception &e){
313 LOG_WARNING<<"ILU_INTF: Out of ingress_packet_handler";
314 }
315 } // ingress_packet_handler()
316
317
318 /**
319 * This thread build TLPs out of requests in the EHB and fwds them to the DLL.
320 * Parity errors are also checked for. If detected, Drain State is entered.
321 */
322 void ilu_intf::egress_packet_handler() {
323 /** EHB Interface Signals
324 d2p_ehb_clk
325 d2p_ehb_we
326 d2p_ehb_addr
327 d2p_ehb_data & dpar
328
329 d2p_ech_wptr
330 d2p_erh_wptr
331
332 p2d_ech_rptr
333 p2d_erh_rptr
334
335 p2d_ecd_rptr
336 p2d_erd_rptr
337 */
338 LOG_INFO<<"ILU_INTF: egress_packet_handler begins...";
339 sc_uint<P2D_EHB_ADDR_WDTH> erh_addr;
340 sc_uint<P2D_ERH_RPTR_WDTH> erh_rptr;
341 sc_uint<P2D_ERH_RPTR_WDTH> nxt_erh_rptr;
342 sc_uint<P2D_EHB_ADDR_WDTH> ech_addr;
343 sc_uint<P2D_ECH_RPTR_WDTH> ech_rptr;
344 sc_uint<P2D_ERH_RPTR_WDTH> nxt_ech_rptr;
345 sc_uint<P2D_EHB_ADDR_WDTH> ehb_addr;
346
347 sc_uint<D2P_EDB_ADDR_WDTH-1> erd_rd_addr;
348 sc_uint<D2P_EDB_ADDR_WDTH-1> ecd_rd_addr;
349 sc_uint<D2P_EDB_ADDR_WDTH> edb_rd_addr;
350
351 sc_biguint<D2P_EHB_DATA_WDTH> ehb_data;
352 sc_uint<D2P_EHB_DPAR_WDTH> ehb_dpar;
353 sc_biguint<D2P_EDB_DATA_WDTH> edb_data;
354 sc_uint<D2P_EDB_DPAR_WDTH> edb_dpar;
355
356 bool req_arb = true;
357 RefPciePacket nxt_pkt;
358 bool par_error = false;
359 sc_uint<PCIE_PLD_LEN_WDTH> pld_len;
360 sc_uint<PCIE_PLD_LEN_WDTH-1> edb_rd_len;
361
362 erh_addr = 0x00;
363 ech_addr = 0x00;
364 erd_rd_addr = 0x00;
365 ecd_rd_addr = 0x00;
366 ihb_wptr = 0x00;
367
368 pld_len = 0;
369 edb_rd_len = 0;
370
371 erh_rptr = bin2gc(erh_addr);
372 nxt_erh_rptr = bin2gc(erh_addr);
373 ech_rptr = bin2gc(ech_addr);
374
375 try{
376 while (true) {
377 WAIT(clk.negedge_event());
378 if(!drain_state && !POR_RESET){
379 if (req_arb) {
380 req_arb = false;
381 nxt_erh_rptr = d2p_erh_wptr.read();
382 /// Check if the req empty
383 if (erh_rptr != nxt_erh_rptr) {
384 ehb_addr = erh_addr | 0x20;
385 p2d_erh_rptr.write(erh_rptr);
386 LOG_DEBUG << " Processing Egress Request Header \n"
387 << " ERH_ADDR : " << erh_addr
388 << " ERH_RPTR : " << erh_rptr
389 << " EHB_ADDR : " << ehb_addr << "\n"
390 << "Next: ERH Addr: " << erh_addr+1
391 << " ERH Rptr: " << bin2gc(erh_addr+1);
392 /// Read erh
393 (ehb_dpar, ehb_data) = ehb_buffer[ehb_addr];
394
395 /// Verify parity
396 for (int dword = 0; dword < 4; dword++) {
397 sc_uint<32> dw_data = (sc_uint<32>) ehb_data(31+(dword * 32), dword * 32);
398 LOG_DEBUG << "dw_data: " << dw_data << " datapar: " << ehb_dpar[dword] << " calcpar: " <<parity(dw_data);
399 if (ehb_dpar[dword] != parity(dw_data)) {
400 LOG_ERROR << "Parity Error detected on DMU Request Header\n"
401 << "Data: " << (string) dw_data.to_string()
402 << " Parity: " << (int) parity(dw_data);
403 par_error = true;
404 }
405 }
406 if(par_error){
407 write_error_csr(OE,12,44,"ehp");
408 drain_req_ev.notify();
409 }
410 if(!par_error){
411 /// Build TLP
412 int hdr_size = (ehb_data[125] & 0x1) ? 16 : 12;
413 nxt_pkt = NEW_TLP(hdr_size);
414 nxt_pkt->modify_byte(0, STP);
415 LOG_DEBUG << " TLP Hdr Size " << hdr_size;
416 for (int byte = 15, pkt_byte = 0;
417 pkt_byte < hdr_size;
418 byte--, pkt_byte++) {
419 sc_uint<8> data_byte;
420 data_byte = ehb_data((byte*8)+7, (byte*8));
421 nxt_pkt->modify_byte( TLP_HDR_START+pkt_byte,
422 data_byte);
423 }
424
425 /// Check for the Data:
426 if ((GET_TLP_FMT(nxt_pkt) >> 1)) {
427 pld_len = GET_TLP_LEN(nxt_pkt);
428 edb_rd_len = pld_len(9,2);
429 int pkt_byte_ctr = TLP_HDR_START+hdr_size;
430 LOG_DEBUG << "Egress Request : Payload Length: " << pld_len
431 << " EDB Read Len: " << edb_rd_len;
432
433 nxt_pkt->alloc_bytes(edb_rd_len * 16 + (pld_len(1,0)*4));
434 /// Read Req Data
435 for (int edb_ctr = 0; edb_ctr < edb_rd_len; edb_ctr++) {
436 while (erd_rd_addr == erd_waddr) {
437 WAIT(clk.negedge_event());
438 }
439
440 edb_rd_addr = (1,erd_rd_addr);
441 erd_rd_addr += 1;
442 p2d_erd_rptr.write(bin2gc(edb_rd_addr));
443 LOG_DEBUG << "TL: EDB Read Addr: " << edb_rd_addr
444 << " ERD Rd Ptr: " << bin2gc(edb_rd_addr);
445 (edb_dpar, edb_data) = edb_buffer[edb_rd_addr];
446
447 /// Verify Data Parity
448 for (int dword = 0; dword < 4; dword++) {
449 sc_uint<32> dw_data = (sc_uint<32>) edb_data(31+(dword * 32), dword * 32);
450 LOG_DEBUG << "EBD: dw_data: " << dw_data << " datapar: " << edb_dpar[dword] << " calcpar: " <<parity(dw_data);
451 if (edb_dpar[dword] != parity(dw_data) && GET_TLP_EP(nxt_pkt)!=1) {
452 LOG_ERROR << "Parity Error detected on DMU Request Data\n";
453 par_error = true;
454 }
455 }
456 if(par_error){
457 write_error_csr(OE,13,45,"edp");
458 }
459 /// Load ERD Data to Packet
460 for (int byte = 15; byte >= 0; byte--) {
461 sc_uint<8> data_byte;
462 data_byte = (sc_uint<8>) edb_data((byte*8)+7, (byte*8));
463 nxt_pkt->modify_byte( pkt_byte_ctr++, data_byte);
464 }
465 } // Read ERD Data
466 if (pld_len(1,0).or_reduce()) {
467 while (erd_rd_addr == erd_waddr) {
468 WAIT(clk.negedge_event());
469 }
470 edb_rd_addr = (1,erd_rd_addr);
471 erd_rd_addr += 1;
472 p2d_erd_rptr.write(bin2gc(edb_rd_addr));
473 LOG_DEBUG << "TL: EDB Read Addr: " << edb_rd_addr
474 << " ERD Rd Ptr: " << bin2gc(edb_rd_addr);
475 (edb_dpar, edb_data) = edb_buffer[edb_rd_addr];
476
477 /// Verify Data Parity
478 for (int dword = 0; dword < 4; dword++) {
479 sc_uint<32> dw_data = (sc_uint<32>) edb_data(31+(dword * 32), dword * 32);
480 LOG_DEBUG << "EBD: dw_data: " << dw_data << " datapar: " << edb_dpar[dword] << " calcpar: " <<parity(dw_data);
481 if (edb_dpar[dword] != parity(dw_data) && GET_TLP_EP(nxt_pkt)!=1) {
482 LOG_ERROR << "Parity Error detected on DMU Request Data\n";
483 par_error = true;
484 }
485 }
486 if(par_error){
487 write_error_csr(OE,13,45,"edp");
488 }
489
490 for (int byte = 15; byte >= 15-(pld_len(1,0)*4); byte--) {
491 sc_uint<8> data_byte;
492 data_byte = (sc_uint<8>) edb_data((byte*8)+7, (byte*8));
493 nxt_pkt->modify_byte( pkt_byte_ctr++, data_byte);
494 }
495 }
496 } // If Packet contains Data
497 if(!par_error){
498 par_error=false;
499 nxt_pkt->set_control(0x2);
500 LOG_DEBUG << "Sending Request Packet to DLL" << nxt_pkt->to_string();
501 //cout << sc_time_stamp() << "\t\t\t\t\t| ILU_INTF: Sending Req TLP " << nxt_pkt->getPacketId() << " to ETL." << endl;
502 req_pkt_port.send_packet(nxt_pkt);
503 }
504 else{
505 nxt_pkt->set_control(0x12);
506 LOG_DEBUG << "Sending Request Packet to DLL" << nxt_pkt->to_string();
507 //cout << sc_time_stamp() << "\t\t\t\t\t| ILU_INTF: Sending Req TLP " << nxt_pkt->getPacketId() << " to ETL." << endl;
508 req_pkt_port.send_packet(nxt_pkt);
509 drain_req_ev.notify();
510 }
511
512 }//end if(!par_error)
513 erh_addr += 1;
514 erh_rptr = bin2gc(erh_addr);
515 } // If Req Hdr not empty
516 } else { // Completion arb
517 req_arb = true;
518 nxt_ech_rptr = d2p_ech_wptr.read();
519 /// Check if the req empty
520 if (ech_rptr != nxt_ech_rptr) {
521 ehb_addr = ech_addr & 0x1F;
522 p2d_ech_rptr.write(ech_rptr);
523
524 LOG_DEBUG << " Processing Completion Header "
525 << " ECH_ADDR : " << ech_addr
526 << " ECH_RPTR : " << ech_rptr
527 << " EHB_ADDR : " << ehb_addr << "\n"
528 << "Next: ERH Addr: " << ech_addr+1
529 << " ERH Rptr: " << bin2gc(ech_addr+1);
530 /// Read erh
531 (ehb_dpar, ehb_data) = ehb_buffer[ehb_addr];
532 /// Verify parity
533 for (int dword = 0; dword < 4; dword++) {
534 sc_uint<32> dw_data = (sc_uint<32>) ehb_data(31+(dword * 32), dword * 32);
535 if (ehb_dpar[dword] != parity(dw_data)) {
536 LOG_ERROR << "Parity Error detected on DMU Completion Header\n"
537 << "Data: " << (string) dw_data.to_string()
538 << " Parity: " << (int) parity(dw_data);
539 par_error = true;
540 }
541 }
542 if(par_error){
543 write_error_csr(OE,12,44,"ehp");
544 drain_req_ev.notify();
545 }
546 if(!par_error){
547 /// Build TLP
548 int hdr_size = (ehb_data[125] & 0x1) ? 16 : 12;
549 nxt_pkt = NEW_TLP(hdr_size);
550 nxt_pkt->modify_byte(0, STP);
551 LOG_DEBUG << " TLP Hdr Size " << hdr_size;
552 for (int byte = 15, pkt_byte = 0;
553 pkt_byte < hdr_size;
554 byte--, pkt_byte++) {
555 sc_uint<8> data_byte;
556 data_byte = ehb_data((byte*8)+7, (byte*8));
557 nxt_pkt->modify_byte( TLP_HDR_START+pkt_byte, data_byte);
558 }
559
560 /// Check for the Data:
561 if ((GET_TLP_FMT(nxt_pkt) >> 1)) {
562 pld_len = GET_TLP_LEN(nxt_pkt);
563 edb_rd_len = pld_len(9,2);
564 int pkt_byte_ctr = TLP_HDR_START+hdr_size;
565 LOG_DEBUG << "Egress Completion Packet : Payload Length: " << pld_len
566 << "EDB Read Len: " << edb_rd_len;
567
568 nxt_pkt->alloc_bytes(edb_rd_len * 16 + (pld_len(1,0)*4));
569 /// Read Req Data
570 for (int edb_ctr = 0; edb_ctr < edb_rd_len; edb_ctr++) {
571 while (ecd_rd_addr == ecd_waddr) {
572 WAIT(clk.negedge_event());
573 }
574
575 edb_rd_addr = (0,ecd_rd_addr);
576 ecd_rd_addr += 1;
577 p2d_ecd_rptr.write(bin2gc(edb_rd_addr));
578 LOG_DEBUG << "TL: EDB Read Addr: " << edb_rd_addr
579 << " ECD Rd Ptr: " << bin2gc(edb_rd_addr);
580
581 (edb_dpar, edb_data) = edb_buffer[edb_rd_addr];
582
583 /// Verify Data Parity
584 for (int dword = 0; dword < 4; dword++) {
585 sc_uint<32> dw_data = (sc_uint<32>) edb_data(31+(dword * 32), dword * 32);
586 if (edb_dpar[dword] != parity(dw_data) && GET_TLP_EP(nxt_pkt)!=1) {
587 LOG_ERROR << "Parity Error detected on DMU Request Data\n";
588 par_error = true;
589 }
590 }
591 if(par_error){
592 write_error_csr(OE,13,45,"edp");
593 }
594 /// Load ECD Data to Packet
595 for (int byte = 15; byte >= 0; byte--) {
596 sc_uint<8> data_byte;
597 data_byte = (sc_uint<8>) edb_data((byte*8)+7, (byte*8));
598 nxt_pkt->modify_byte( pkt_byte_ctr++, data_byte);
599
600 } // Load ECD Data
601 } // Read ECD Data
602 if (pld_len(1,0).or_reduce()) {
603 while (ecd_rd_addr == ecd_waddr) {
604 WAIT(clk.negedge_event());
605 }
606
607 edb_rd_addr = (0,ecd_rd_addr);
608 ecd_rd_addr += 1;
609 p2d_ecd_rptr.write(bin2gc(edb_rd_addr));
610
611 LOG_DEBUG << "TL: EDB Read Addr: " << edb_rd_addr
612 << " ECD Rd Ptr: " << bin2gc(edb_rd_addr);
613 (edb_dpar, edb_data) = edb_buffer[edb_rd_addr];
614
615 /// Verify Data Parity
616 for (int dword = 0; dword < 4; dword++) {
617 sc_uint<32> dw_data = (sc_uint<32>) edb_data(31+(dword * 32), dword * 32);
618 if (edb_dpar[dword] != parity(dw_data) && GET_TLP_EP(nxt_pkt)!=1) {
619 LOG_ERROR << "Parity Error detected on DMU Request Data\n";
620 par_error = true;
621 }
622 }
623 if(par_error){
624 write_error_csr(OE,13,45,"edp");
625 }
626
627 for (int byte = 15; byte >= 15-(pld_len(1,0)*4); byte--) {
628 sc_uint<8> data_byte;
629 data_byte = (sc_uint<8>) edb_data((byte*8)+7, (byte*8));
630 nxt_pkt->modify_byte( pkt_byte_ctr++, data_byte);
631 }
632 }
633 } // If Packet contains Data
634 if(!par_error){
635 par_error=false;
636 nxt_pkt->set_control(0x2);
637 LOG_DEBUG << "Sending Completion Packet to DLL" << nxt_pkt->to_string();
638 //cout<< sc_time_stamp() << "\t\t\t\t\t| ILU_INTF: Sending Cpl TLP " << nxt_pkt->getPacketId() << " to ETL." << endl;
639 cmpl_pkt_port.send_packet(nxt_pkt);
640 }
641 else{
642 nxt_pkt->set_control(0x12);
643 LOG_DEBUG << "Sending Completion Packet to DLL" << nxt_pkt->to_string();
644 //cout<< sc_time_stamp() << "\t\t\t\t\t| ILU_INTF: Sending Cpl TLP " << nxt_pkt->getPacketId() << " to ETL." << endl;
645 cmpl_pkt_port.send_packet(nxt_pkt);
646 drain_req_ev.notify();
647 }
648 }//end if(!parr_error)
649 ech_addr += 1;
650 ech_rptr = bin2gc(ech_addr);
651 } // If Req Hdr not empty
652 }
653 par_error=false;
654 }
655 } // while (true)
656 }
657 catch(sc_exception &e){
658 LOG_WARNING<<"ILU_INTF: Out of egress_packet_handler";
659 }
660 }
661
662 /** Interrupt Generators
663 * When interrupt enabled error bits are set in the OE, CE or UE CSRs, a corresponding interrupt
664 * is generated.
665 */
666
667 void ilu_intf::proc_ce_int() {
668 csr_port.set_notify_event(PEU_CSR_A_CE_ERR_RW1C_ALIAS_HW_ADDR, &ce_ev);
669
670 while (1) {
671 wait (ce_ev);
672 ce_err = csr_port.read_csr(PEU_CSR_A_CE_ERR_RW1C_ALIAS_HW_ADDR);
673
674 if ( (ce_err & ce_int_en) != 0) {
675 wait (clk.posedge_event());
676 p2d_ce_int.write(1);
677 } else {
678 wait (clk.posedge_event());
679 p2d_ce_int.write(0);
680 }
681 }
682 }
683
684 void ilu_intf::proc_ce_int_en() {
685 csr_port.set_notify_event(PEU_CSR_A_CE_INT_EN_HW_ADDR, &ce_en_ev);
686 while (1) {
687 wait (ce_en_ev);
688 ce_int_en = csr_port.read_csr(PEU_CSR_A_CE_INT_EN_HW_ADDR);
689 }
690 }
691
692 void ilu_intf::proc_ue_int() {
693 csr_port.set_notify_event(PEU_CSR_A_UE_ERR_RW1C_ALIAS_HW_ADDR, &ue_ev);
694
695 while (1) {
696 wait (ue_ev);
697 ue_err = csr_port.read_csr(PEU_CSR_A_UE_ERR_RW1C_ALIAS_HW_ADDR);
698
699 if ( (ue_err & ue_int_en) != 0) {
700 wait (clk.posedge_event());
701 p2d_ue_int.write(1);
702 } else {
703 wait (clk.posedge_event());
704 p2d_ue_int.write(0);
705 }
706 }
707 }
708
709 void ilu_intf::proc_ue_int_en() {
710 csr_port.set_notify_event(PEU_CSR_A_UE_INT_EN_HW_ADDR, &ue_en_ev);
711 while (1) {
712 wait (ue_en_ev);
713 ue_int_en = csr_port.read_csr(PEU_CSR_A_UE_INT_EN_HW_ADDR);
714 }
715 }
716
717 void ilu_intf::proc_oe_int() {
718 csr_port.set_notify_event(PEU_CSR_A_OE_ERR_RW1C_ALIAS_HW_ADDR, &oe_ev);
719
720 while (1) {
721 wait (oe_ev);
722 oe_err = csr_port.read_csr(PEU_CSR_A_OE_ERR_RW1C_ALIAS_HW_ADDR);
723
724 if ( (oe_err & oe_int_en) != 0) {
725 wait (clk.posedge_event());
726 p2d_oe_int.write(1);
727 } else {
728 wait (clk.posedge_event());
729 p2d_oe_int.write(0);
730 }
731 }
732 }
733
734 void ilu_intf::proc_oe_int_en() {
735 csr_port.set_notify_event(PEU_CSR_A_OE_INT_EN_HW_ADDR, &oe_en_ev);
736 while (1) {
737 wait (oe_en_ev);
738 oe_int_en = csr_port.read_csr(PEU_CSR_A_OE_INT_EN_HW_ADDR);
739 }
740 }
741
742 /**
743 * This thread collects credits from the ILU and updates the Ingress Credits Allocated CSR.
744 */
745 void ilu_intf::ilu_credit_update_handler(){
746 sc_uint<D2P_IBC_NHC_WDTH> prev_nhc_cred=0;
747 sc_uint<D2P_IBC_PHC_WDTH> prev_phc_cred=0;
748 sc_uint<D2P_IBC_PDC_WDTH> prev_pdc_cred=0;
749 while(1) {
750 wait(d2p_ibc_req.posedge_event()|p2d_drain.negedge_event());
751 sc_uint<D2P_IBC_NHC_WDTH> nhc_cred = d2p_ibc_nhc.read();
752 sc_uint<D2P_IBC_PHC_WDTH> phc_cred = d2p_ibc_phc.read();
753 sc_uint<D2P_IBC_PDC_WDTH> pdc_cred = d2p_ibc_pdc.read();
754 //LOG_DEBUG << "ILU_INTF: ilu_credit_update_handler: drain_state: " << drain_state << " nhc:" << nhc_cred << " phc:" << phc_cred << " pdc:" << pdc_cred;
755 //LOG_DEBUG << "ILU_INTF: p_nhc:" << prev_nhc_cred << " p_phc:" << prev_phc_cred << " p_pdc:" << prev_pdc_cred;
756 if(!drain_state && (nhc_cred!=prev_nhc_cred || phc_cred!=prev_phc_cred || pdc_cred!=prev_pdc_cred))
757 {
758 LOG_DEBUG << "ILU_INTF : IIL has sent IBC credit updates. ";
759 LOG_DEBUG << "NHC: " << nhc_cred << " PHC: " << phc_cred << " PDC: " << pdc_cred;
760 sc_uint<64> ica_reg = csr_port.read_csr(PEU_CSR_A_TLU_ICA_HW_ADDR);
761 sc_uint<64> ici_reg = csr_port.read_csr(PEU_CSR_A_TLU_ICI_HW_ADDR);
762 ica_reg.range(NHC) = (sc_uint<8>)(ici_reg(NHC) + nhc_cred + recovered_credits(NHC));
763 ica_reg.range(PHC) = (sc_uint<8>)(ici_reg(PHC) + phc_cred + recovered_credits(PHC));
764 ica_reg.range(PDC) = (sc_uint<12>)(ici_reg(PDC) + pdc_cred + recovered_credits(PDC));
765 csr_port.write_csr(PEU_CSR_A_TLU_ICA_HW_ADDR,ica_reg);
766 prev_nhc_cred = nhc_cred;
767 prev_phc_cred = phc_cred;
768 prev_pdc_cred = pdc_cred;
769 }
770 p2d_ibc_ack.write(true);
771 try{
772 WAIT(clk.posedge_event());
773 WAIT(clk.posedge_event());
774 WAIT(clk.posedge_event());
775 WAIT(clk.posedge_event());
776 WAIT(clk.posedge_event());
777 WAIT(clk.posedge_event());
778 }
779 catch(sc_exception &e){
780 LOG_WARNING<<"ILU_INTF: ilu_credit_update_handler...ending clock wait";
781 if(RETRAIN_NO_RESET) wait(clk.posedge_event());
782 }
783 p2d_ibc_ack.write(false);
784 }
785 }
786
787 /**
788 * This thread forwards CMPL Timeout requests from the RSB to the ILU.
789 */
790 void ilu_intf::cto_req_handler(){
791 sc_uint<5> cto_req_tag;
792 while(1){
793 cto_req_port->get(cto_req_tag);
794 LOG_WARNING << "ILU_INTF: cto_req_handler recvd: " << cto_req_tag ;
795 p2d_cto_req.write(1);
796 p2d_cto_tag.write(cto_req_tag);
797 try{
798 WAIT(d2p_cto_ack.posedge_event());
799 p2d_cto_req.write(0);
800 WAIT(d2p_cto_ack.negedge_event());
801 LOG_INFO << "ILU_INTF: CTO Req handling complete" ;
802 }
803 catch(sc_exception &e){
804 LOG_WARNING<<"ILUT_INTF: cto req handler resetting...";
805 p2d_cto_req.write(0);
806 p2d_cto_tag.write(0);
807 }
808 }
809 }
810
811 /**
812 * This function updates the requested UE, CE and OE error bits.
813 */
814 void ilu_intf::write_error_csr(uint8 err_type, uint8 primary, uint8 secondary, char field_name[3]){
815 sc_uint<64> orig_csr_val;
816 sc_uint<64> new_csr_val=0;
817 sc_uint<64> log_enable;
818
819 LOG_DEBUG << "Setting err bit: " << field_name;
820
821 switch(err_type){
822 case OE: orig_csr_val = csr_port.read_csr(PEU_CSR_A_OE_ERR_RW1C_ALIAS_HW_ADDR);
823 LOG_DEBUG << "Updating OE CSR (orig val: " << orig_csr_val << ")";
824 break;
825 case UE: orig_csr_val = csr_port.read_csr(PEU_CSR_A_UE_ERR_RW1C_ALIAS_HW_ADDR);
826 LOG_DEBUG << "Updating UE CSR (orig val: " << orig_csr_val << ")";
827 break;
828 case CE: orig_csr_val = csr_port.read_csr(PEU_CSR_A_CE_ERR_RW1C_ALIAS_HW_ADDR);
829 LOG_DEBUG << "Updating CE CSR (orig val: " << orig_csr_val << ")";
830 break;
831 default: LOG_ERROR << "Warning: undefined error type!";
832 return;
833 }
834
835 switch(err_type){
836 case OE: log_enable = csr_port.read_csr(PEU_CSR_A_OE_LOG_HW_ADDR);
837 LOG_DEBUG << "OE Log enable : " << log_enable << ")";
838 break;
839 case UE: log_enable = csr_port.read_csr(PEU_CSR_A_UE_LOG_HW_ADDR);
840 LOG_DEBUG << "UE Log Enable : " << log_enable << ")";
841 break;
842 case CE: log_enable = csr_port.read_csr(PEU_CSR_A_CE_LOG_HW_ADDR);
843 LOG_DEBUG << "CE Log Enable : " << log_enable << ")";
844 break;
845 }
846
847 if(log_enable.range(primary,primary)==1)
848 {
849 if(orig_csr_val.range(primary,primary)!=1)
850 new_csr_val.range(primary,primary)=1;
851 else if(orig_csr_val.range(secondary,secondary)!=1)
852 new_csr_val.range(secondary,secondary)=1;
853 else
854 LOG_DEBUG << "Warning: Both PRIMARY and SECONDARY of " << field_name << "are set.";
855 }
856
857 switch(err_type){
858 case OE: csr_port.write_csr(PEU_CSR_A_OE_ERR_RW1S_ALIAS_HW_ADDR,new_csr_val);
859 LOG_DEBUG << "Updating OE CSR (new val : " << new_csr_val << ")";
860 break;
861 case UE: csr_port.write_csr(PEU_CSR_A_UE_ERR_RW1S_ALIAS_HW_ADDR,new_csr_val);
862 LOG_DEBUG << "Updating UE CSR (new val : " << new_csr_val << ")";
863 break;
864 case CE: csr_port.write_csr(PEU_CSR_A_CE_ERR_RW1S_ALIAS_HW_ADDR,new_csr_val);
865 LOG_DEBUG << "Updating CE CSR (new val : " << new_csr_val << ")";
866 break;
867 }
868 return;
869 }//end write_csr_error
870
871 /**
872 * Updates to the Max Payload Size ILU port are reflected into the corresponding CSR.
873 */
874 void ilu_intf::mps_handler() {
875 sc_uint<64> dev_ctl;
876 sc_uint<3> dev_mps;
877
878 csr_port.set_notify_event(PEU_CSR_A_DEV_CTL_HW_ADDR, &dev_ctl_ev);
879 while (1) {
880 wait (dev_ctl_ev);
881 dev_ctl = csr_port.read_csr(PEU_CSR_A_DEV_CTL_HW_ADDR);
882 dev_mps = dev_ctl(7,5);
883 LOG_DEBUG << "P2D MPS: " << dev_mps << " Device Ctrl Reg: " << dev_ctl;
884 p2d_mps.write(dev_mps);
885 LOG_DEBUG << "P2D MPS: " << dev_mps << " Device Ctrl Reg: " << dev_ctl << " written";
886 }
887 }
888
889 /**
890 * This thread handles entry and exit of the model from 'drain state'.
891 */
892 void ilu_intf::drain_handler(){
893 sc_event csr_core_status_ev,csr_tlu_status_ev,csr_lnk_ctl_ev;
894 csr_port.set_notify_event(PEU_CSR_A_CORE_STATUS_HW_ADDR,&csr_core_status_ev);
895 csr_port.set_notify_event(PEU_CSR_A_TLU_STS_HW_ADDR,&csr_tlu_status_ev);
896 csr_port.set_notify_event(PEU_CSR_A_LINK_CTL_HW_ADDR,&csr_lnk_ctl_ev);
897 while(1){
898 wait(drain_req_ev);
899 if(!drain_state){
900 LOG_DEBUG<<"++++++++++ ILU_INTF: Signaling DRAIN STATE to ILU ++++++++++";
901 drain_state=true;
902 if(csr_port.read_csr(ILU_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_HW_ADDR).range(4,4)!=1){
903 //Setting drain bit in PEU Status CSR
904 csr_port.write_csr_mask(PEU_CSR_A_TLU_STS_HW_ADDR,(0x1 << 8),PEU_CSR_TLU_STS_SET_MASK);
905 p2d_drain.write(1);
906 }
907 *parent_global_event_type = SW_RESET_ENTER; //This state is needed to ensure timers are stopped and to keep updatefcs sent...
908 notify(*parent_global_event);
909 wait(SC_ZERO_TIME);
910
911 if(csr_port.read_csr(PEU_CSR_A_OE_ERR_RW1C_ALIAS_HW_ADDR).range(9,9)!=1){
912 //Wait for RESET ASSERT
913 while((csr_port.read_csr(PEU_CSR_A_LINK_CTL_HW_ADDR)).range(0,0)!=0x1) wait(csr_lnk_ctl_ev);
914 LOG_INFO<<"ILU_INTF: Reset-assert bit is set...";
915 //Setting retrain bit in Link Ctrl CSR
916 sc_uint<64> lnk_ctrl_reg = csr_port.read_csr(PEU_CSR_A_LNK_CTL_HW_ADDR);
917 lnk_ctrl_reg(5,5)=1;
918 csr_port.write_csr(PEU_CSR_A_LNK_CTL_HW_ADDR,lnk_ctrl_reg);
919
920 while((csr_port.read_csr(PEU_CSR_A_CORE_STATUS_HW_ADDR)).range(48,44)!=0x0D) wait(csr_core_status_ev);
921 LOG_WARNING<<"ILU_INTF: PEU now in Recovery...";
922 }
923 while(1){
924 wait(rst_l.negedge_event()|csr_tlu_status_ev);
925 if(rst_l.read()==0){
926 LOG_WARNING<<"ILU_INTF: PEU now receives RESET_L...";
927 break;
928 }
929 if(csr_port.read_csr(PEU_CSR_A_TLU_STS_HW_ADDR).range(8,8)==0){
930 //cout << "=== ILU_INTF: SW has cleared drain-state bit ===" << endl;
931 sc_uint<D2P_IHB_ADDR_WDTH> prev_ihb_wr_addr = ihb_wr_addr;
932 sc_uint<D2P_IHB_ADDR_WDTH+1> prev_nxt_ihb_wr_addr = nxt_ihb_wr_addr;
933 sc_uint<D2P_IDB_ADDR_WDTH> prev_idb_wr_addr = idb_wr_addr;
934 sc_uint<D2P_IDB_ADDR_WDTH+1> prev_nxt_idb_wr_addr = nxt_idb_wr_addr;
935
936 RETRAIN_NO_RESET = true;
937
938 *parent_global_event_type = SW_RESET_EXIT;
939 notify(*parent_global_event);
940 wait(SC_ZERO_TIME);
941
942 p2d_drain.write(0);
943
944 *parent_global_event_type = WMR_RESET_ENTER;
945 notify(*parent_global_event);
946 wait(SC_ZERO_TIME);
947
948 *parent_global_event_type = SW_RESET_CHNL_EXIT;
949 notify(*parent_global_event);
950 wait(SC_ZERO_TIME);
951
952 *parent_global_event_type = WMR_RESET_EXIT;
953 notify(*parent_global_event);
954 wait(SC_ZERO_TIME);
955
956
957 ihb_wr_addr = prev_ihb_wr_addr;
958 nxt_ihb_wr_addr = prev_nxt_ihb_wr_addr;
959 p2d_ihb_wptr.write(bin2gc(nxt_ihb_wr_addr));
960 idb_wr_addr = prev_idb_wr_addr;
961 nxt_idb_wr_addr = prev_nxt_idb_wr_addr;
962
963 break;
964 }
965 }
966 if(rst_l.read()==0){
967 *parent_global_event_type = SW_RESET_EXIT;
968 notify(*parent_global_event);
969 wait(SC_ZERO_TIME);
970 p2d_drain.write(0);
971
972 *parent_global_event_type = WMR_RESET_ENTER;
973 notify(*parent_global_event);
974 wait(SC_ZERO_TIME);
975 sc_uint<D2P_IHB_ADDR_WDTH> ihb_wr_addr=0;
976 p2d_ihb_wptr.write(bin2gc(ihb_wr_addr));
977
978 *parent_global_event_type = SW_RESET_CHNL_EXIT;
979 notify(*parent_global_event);
980 wait(rst_l.posedge_event());
981
982 *parent_global_event_type = WMR_RESET_EXIT;
983 notify(*parent_global_event);
984 wait(SC_ZERO_TIME);
985 drain_state=false;
986 }
987 }
988
989 }//end while(1)
990 }//end drain_handler()
991
992 /**
993 * This thread monitors the 'link down' event. This event puts the model into 'drain state'
994 */
995 void ilu_intf::pl_drain_catcher(){
996 sc_event csr_status_ev;
997 csr_port.set_notify_event(PEU_CSR_A_OE_ERR_RW1C_ALIAS_HW_ADDR,&csr_status_ev);
998 while(1){
999 wait(csr_status_ev);
1000 if(!drain_state && csr_port.read_csr(PEU_CSR_A_OE_ERR_RW1C_ALIAS_HW_ADDR).range(9,9)==1) {
1001 LOG_WARNING<<"ILU_INTF: LINK DOWN...Entering DRAIN state";
1002 drain_req_ev.notify();
1003 }
1004 }
1005 }
1006
1007 /**
1008 * This method initializes module registers and flags.
1009 * It also spawns threads that handle module operation.
1010 */
1011 void ilu_intf::init(){
1012 ihb_empty = true;
1013 ecd_waddr = 0x00;
1014 erd_waddr = 0x00;
1015 ihb_wr_addr = 0;
1016 nxt_ihb_wr_addr = 0;
1017 idb_wr_addr = 0;
1018 nxt_idb_wr_addr = 0;
1019 recovered_credits=0x0;
1020 drain_state=false;
1021 SW_RESET=false;
1022 POR_RESET=false;
1023 RETRAIN_NO_RESET=false;
1024 sc_uint<P2D_EHB_ADDR_WDTH> erh_addr;
1025 p2d_erh_rptr.write(bin2gc(erh_addr));
1026 sc_uint<P2D_EHB_ADDR_WDTH> ech_addr;
1027 p2d_ech_rptr.write(bin2gc(ech_addr));
1028 p2d_ihb_wptr.write(bin2gc(ihb_wr_addr));
1029 ihb_wptr = bin2gc(ihb_wr_addr);
1030 ingress_packet_handler_ph = sc_spawn(sc_bind(&ilu_intf::ingress_packet_handler,this));
1031 egress_packet_handler_ph = sc_spawn(sc_bind(&ilu_intf::egress_packet_handler,this));
1032 p2d_ce_int.write(0);
1033 p2d_oe_int.write(0);
1034 p2d_ue_int.write(0);
1035 LOG_INFO<<"ILU_INTF: threads spawned...";
1036 }//end init()
1037
1038 /**
1039 * This thread handles reset behavior of the module. On the arrival of a reset global event,
1040 * it issues termination requests to threads in this module. Following the reset exit global event
1041 * it invokes init() to re-spawn terminated threads.
1042 */
1043 void ilu_intf::reset_handler(){
1044 while(1){
1045 wait(*parent_global_event);
1046 switch(*parent_global_event_type){
1047 case WMR_RESET_ENTER:
1048 case POR_RESET_ENTER:
1049 POR_RESET=true;
1050 reset_ev.notify();
1051 //Wait for all thread to terminate
1052 while(1){
1053 if(ingress_packet_handler_ph.terminated() && egress_packet_handler_ph.terminated()) break;
1054 wait(ingress_packet_handler_ph.terminated_event()|egress_packet_handler_ph.terminated_event());
1055 }
1056 LOG_WARNING << "ILU_INTF: WMR/POR Reset threads terminated" ;
1057 LOG_WARNING << "ILU_INTF: WMR/POR Reset dbs cleared" ;
1058 break;
1059
1060 case WMR_RESET_EXIT:
1061 case POR_RESET_EXIT:
1062 LOG_INFO<<"ILU_INTF: WMR/POR Reset exit";
1063 init();
1064 break;
1065 }
1066 }//end while(1)
1067 }//end reset_handler()
1068
1069 /**
1070 * This thread monitors the 'ihb parity error' event. This event puts the model into 'drain state'
1071 */
1072 void ilu_intf::ilu_drain_catcher(){
1073 sc_event ilu_err_rw1s_ev;
1074 csr_port.set_notify_event(ILU_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_HW_ADDR,&ilu_err_rw1s_ev);
1075 while(1){
1076 wait(ilu_err_rw1s_ev);
1077 if(!drain_state && csr_port.read_csr(ILU_CSR_A_ILU_LOG_ERR_RW1S_ALIAS_HW_ADDR).range(4,4)==1) {
1078 LOG_WARNING<<"ILU_INTF: ILU has detected a parity error...Entering DRAIN state";
1079 drain_req_ev.notify();
1080 }
1081 }
1082 }
1083
1084
1085}; // namespace pcie