Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / model / pcie / pl / pl_top.cpp
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: pl_top.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 <systemc.h>
36#include <math.h>
37#include "pl/pl_top.h"
38#include <map>
39
40USING_NAMESPACE(pcie)
41USING_NAMESPACE(Logger)
42
43/// This is the main transmit block.
44/// It gets the packet from the TLM FIFO
45/// forms the PL frame and then sends out according to the LINK_WIDTH
46/// It first scrambles, then encodes and then finally forms frames
47/// It is also responsible for forming intermediate SKP Ordered sets and IDLE sets
48void pl_top::process_packet()
49{
50 int i,j;
51 int lane;
52 int pkt_cnt = 0;
53 int pkt_id = 0;
54 int skp_counter = 0;
55 int dll_pkt_cnt = 0;
56 double size;
57 unsigned short scramble_lfsr;
58 unsigned long word_val;
59 map<int,int>::iterator iter;
60 RefPciePacket pkt;
61 RefPciePacket receive_packet;
62 RefPciePacket idle_packet;
63 RefPciePacket skp_packet;
64 bool waitingforFirstData = true;
65 bool packet_ready_dll,packet_ready_tl,round_robin_dll_tl = false;
66 bool skp_ordered_set = false;
67 bool put_end_symbol = false;
68 sc_lv<5> control; /// control signal from the DLL
69
70 while(1){
71 if ( dll_pkt_cnt >= 5)
72 packet_ready_tl = dll_pl_tlp_in.is_packet_ready();
73
74 packet_ready_dll = dll_pl_dllp_in.is_packet_ready();
75
76
77#ifdef SEND_SKP
78 if((packet_ready_tl || packet_ready_dll) && init_done.read() && !last_idle_frame.read() && !interleave_idle && ((skp_counter < 1450) || skp_counter == 0)) /// Link Init complete and DLLP has put a packet into the FIFO
79#else
80 if((packet_ready_tl || packet_ready_dll) && init_done.read() && !last_idle_frame.read() && !interleave_idle) /// Link Init complete and DLLP has put a packet into the FIFO
81#endif
82 {
83 if(packet_ready_dll && !round_robin_dll_tl)
84 {
85 dll_pl_dllp_in.get_packet(receive_packet);
86 //cout<< sc_time_stamp() <<"\t\t\t\t\t| PL: Recvd DLLP " << receive_packet->getPacketId() << " from DLL." <<endl;
87 dll_pkt_cnt++;
88 if(dll_pkt_cnt >= 5) /// Make sure FC_INIT packets go before any TLP
89 round_robin_dll_tl = true;
90 }
91 else if(packet_ready_tl && round_robin_dll_tl)
92 {
93 dll_pl_tlp_in.get_packet(receive_packet);
94 //cout<< sc_time_stamp() <<"\t\t\t\t\t| PL: Recvd TLP " << receive_packet->getPacketId() << " from DLL." <<endl;
95 round_robin_dll_tl = false;
96 }
97 else if(packet_ready_dll && !packet_ready_tl && round_robin_dll_tl) /// Still keep next priority for TL. But dequeue DLL Q for now
98 {
99 dll_pl_dllp_in.get_packet(receive_packet);
100 //cout<< sc_time_stamp() <<"\t\t\t\t\t| PL: Recvd DLLP " << receive_packet->getPacketId() << " from DLL." <<endl;
101 dll_pkt_cnt++;
102 }
103 else if( packet_ready_tl && !packet_ready_dll && !round_robin_dll_tl) /// Still Keep next priority for DLL. But dequeue TL for now
104 {
105 dll_pl_tlp_in.get_packet(receive_packet);
106 //cout<< sc_time_stamp() <<"\t\t\t\t\t| PL: Recvd TLP " << receive_packet->getPacketId() << " from DLL." <<endl;
107 }
108
109 pkt_id = receive_packet->getPacketId();
110
111 global_packet = receive_packet;
112 q_not_empty.write(true);
113 waitingforFirstData = false;
114 size = global_packet->get_size();
115 interleave_idle = true;
116 control = global_packet->get_control();
117 }
118#ifdef SEND_SKP
119 else if((skp_counter < 1450) || skp_counter == 0)/// Produce IDLE packets
120#else
121 else
122#endif
123 {
124 idle_packet = new pciePacket(LINK_WIDTH);
125 for(i=0;i<LINK_WIDTH;i++)
126 idle_packet->modify_byte(i,0x00);
127 global_packet = idle_packet;
128 if(packet_ready_dll || packet_ready_tl)
129 {
130 q_not_empty.write(true); /// data is available, but the last IDLE frame has not been transmitted
131 }
132 else if(!packet_ready_dll && !packet_ready_tl && waitingforFirstData)
133 q_not_empty.write(false);
134
135 size = global_packet->get_size();
136 interleave_idle = false; /// Interleave every DLLP/TLP with an IDLE frame
137 control = 0x000; /// No Control Chars in the IDLE frame
138 }
139#ifdef SEND_SKP
140 else if((skp_counter >= 1450))
141 {
142 skp_packet = new pciePacket(4*LINK_WIDTH); /// SKP is sent across 4 frames
143 for(i=0;i<LINK_WIDTH;i++)
144 skp_packet->modify_byte(i,COM);
145 for(i=LINK_WIDTH;i<2*LINK_WIDTH;i++)
146 skp_packet->modify_byte(i,SKP);
147 for(i=2*LINK_WIDTH;i<3*LINK_WIDTH;i++)
148 skp_packet->modify_byte(i,SKP);
149 for(i=3*LINK_WIDTH;i<4*LINK_WIDTH;i++)
150 skp_packet->modify_byte(i,SKP);
151
152 global_packet = skp_packet;
153 size = global_packet->get_size();
154 control = 0x001;
155 skp_counter = 0;
156 }
157#endif
158 pkt = global_packet;
159
160 put_end_symbol = false;
161 control = pkt->get_control();
162 if(control[1] == 0x1) /// Only for STP, ignore the 0th byte
163 size--;
164 /// Check if LINK_WIDTH > size + 2
165 if(size <= LINK_WIDTH) /// For FC_Init and IDLE frames
166 {
167 control = pkt->get_control(); /// Control signal from the DLLP
168 /// [0] = D/K#
169 /// [1] = STP
170 /// [2] = SDP
171 /// [3] = END
172 /// [4] = EDB
173 if((control[1] != 0x1) && (control[2] != 0x1)) /// IDLE packet
174 {
175 for(i = 0; i < size; i++) /// The actual data without STP/SDP
176 {
177 xtracted_data[i] = pkt->get_byte(i);
178 xtracted_data_c[i] = false;
179 }
180 for(i = size ; i < LINK_WIDTH ; i++) /// PAD or END character
181 {
182 xtracted_data[i] = PAD;
183 }
184 size = LINK_WIDTH;
185 }
186 else /// FC_Init
187 {
188 if(control[1] == 0x1)
189 {
190 xtracted_data[0] = STP;
191 xtracted_data_c[0] = true;
192 }
193 else if(control[2] == 0x1)
194 {
195 xtracted_data[0] = SDP;
196 xtracted_data_c[0] = true;
197 }
198 for(i = 1,j=0; i <= size,j< size; i++,j++) /// The actual data with CRC
199 {
200 xtracted_data[i] = pkt->get_byte(j);
201 xtracted_data_c[i] = false;
202 }
203 for(i = size+1 ; i < LINK_WIDTH ; i++) /// PAD or END character
204 {
205 if(((i+1) % 4) == 0 && (control[3] == 0x1) && !put_end_symbol) /// END
206 {
207 xtracted_data[i] = END;
208 xtracted_data_c[i] = true;
209 put_end_symbol = true;
210 }
211 else if(((i+1) %4) == 0 && (control[4] == 0x1) && !put_end_symbol) /// EDB
212 {
213 xtracted_data[i] = EDB;
214 xtracted_data_c[i] = true;
215 put_end_symbol = true;
216 }
217 else
218 {
219 xtracted_data[i] = PAD;
220 xtracted_data_c[i] = true;
221 }
222 }
223 size = LINK_WIDTH;
224 }
225 }
226 else/// Transaction Layer packets or SKP Ordered Set or DLLP with size > LINK_WIDTH
227 {
228 control = pkt->get_control();
229 if(control[0] == 0) /// TLP
230 {
231 if(control[1] == 0x1)
232 {
233 xtracted_data[0] = STP;
234 xtracted_data_c[0] = true;
235 }
236 else if(control[2] == 0x1)
237 {
238 xtracted_data[0] = SDP;
239 xtracted_data_c[0] = true;
240 }
241 for(i=1,j=0; i<= size,j<size ; i++,j++) /// The actual data with CRC for TLP
242 {
243 if(xtracted_data[0] == SDP) /// get data from byte 0
244 xtracted_data[i] = pkt->get_byte(j);
245 else
246 xtracted_data[i] = pkt->get_byte(i);
247 xtracted_data_c[i] = false;
248 }
249 for(i = size+1 ; i < LINK_WIDTH*ceil(double((size+2)/LINK_WIDTH)); i++)
250 {
251 if(((i+1) % 4) == 0 && (control[3] == 0x1) && !put_end_symbol) /// END
252 {
253 xtracted_data[i] = END;
254 xtracted_data_c[i] = true;
255 put_end_symbol = true;
256 }
257 else if(((i+1) % 4) == 0 && (control[4] == 0x1) && !put_end_symbol) /// EDB
258 {
259 xtracted_data[i] = EDB;
260 xtracted_data_c[i] = true;
261 put_end_symbol = true;
262 }
263 else
264 {
265 xtracted_data[i] = PAD;
266 xtracted_data_c[i] = true;
267 }
268 }
269 size = LINK_WIDTH*ceil(double((size+2)/LINK_WIDTH));
270 }
271 else
272 {
273 /// SKP Ordered Set
274 for(i=0; i< size; i++)
275 {
276 xtracted_data[i] = pkt->get_byte(i);
277 xtracted_data_c[i] = true;
278 }
279 size = 4*LINK_WIDTH;
280 }
281 }
282
283 /// Now scramble the data
284 if(init_done.read() && reset_l.read() && reset_por_l.read())
285 {
286 initialization_done = true;
287 for(int lane_scram=0; lane_scram<LINK_WIDTH; lane_scram++)
288 scrambler_i->start_scramble_reg[lane_scram] = true;
289 scramble_lfsr = scrambler_i->get_lfsr(0);
290 for(i = 0 ; i< size ; i++) /// Whether to scramble or descramble the data. The Start, end and PAD symbols will not be scrambled anyway
291 {
292 if(((i % LINK_WIDTH) == 0 && (i > 0)) || (LINK_WIDTH == 1 && xtracted_data[i] == SKP))
293 {
294 if(xtracted_data_c[i]) /// Should go into this block when LINK_1 and control character
295 {
296 if(xtracted_data[i] == SKP)
297 {
298 skp_ordered_set = true;
299 scrambler_i->scramble_descramble_all(SKP,0,1);
300 }
301 }
302 else
303 {
304 scrambler_i->scramble_descramble_all(0x00,1,0); /// Forward the LFSR for the next scramble
305 scramble_lfsr = scrambler_i->get_lfsr(0);
306 }
307 }
308
309 if(control[0] == 0x1) /// This is a control packet. Dont scramble it at all
310 {
311 xtracted_data_c[i] = true;
312 continue;
313 }
314
315 if(xtracted_data_c[i]) /// Dont scramble K characters
316 {
317 /// First check if its a COM...Reset lfsr
318 word_val = xtracted_data[i].get_word(0);
319 if(xtracted_data[i] == COM)
320 scrambler_i->scramble_descramble_all(word_val,1,1);
321 continue;
322 }
323
324 word_val = xtracted_data[i].get_word(0);
325 xtracted_data[i] = scrambler_i->scramble_descramble_all(word_val,1,0);
326 if(scrambler_i->get_lfsr(0) != 0xffff) {
327 for(int lane_scram=0; lane_scram<LINK_WIDTH; lane_scram++)
328 scrambler_i->set_lfsr(scramble_lfsr,lane_scram);
329 }
330 wait(SC_ZERO_TIME);
331
332 }
333 if(!skp_ordered_set)
334 {
335 scrambler_i->scramble_descramble_all(0x00,1,0); /// Size of packet is only 8 bytes
336 for(int lane_scram=0; lane_scram<LINK_WIDTH; lane_scram++)
337 scrambler_i->start_scramble_reg[lane_scram] = false;
338 }
339 else
340 {
341 skp_ordered_set = false;
342 }
343
344 skp_ordered_set = false;
345 /// Now encode the data
346 for(i = 0; i< size ; i++)
347 {
348 wait(SC_ZERO_TIME);
349 lane = i%LINK_WIDTH;
350 if(curr_running_disp->get_CRD(lane) == 0)
351 {
352 word_val = xtracted_data[i].get_word(0);
353 iter = map_table->neg_spec_symbol_map.find(word_val);
354 if((iter == map_table->neg_spec_symbol_map.end()) || !xtracted_data_c[i]) /// This is not a control packet and not STP/SDP/END/EDB when not scrambled
355 iter = map_table->neg_data_encode_map.find(word_val);
356 xtracted_data[i] = iter->second;
357 }
358 else if(curr_running_disp->get_CRD(lane) == 1)
359 {
360 word_val = xtracted_data[i].get_word(0);
361 iter = map_table->spec_symbol_map.find(word_val);
362 if((iter == map_table->spec_symbol_map.end()) || !xtracted_data_c[i]) /// This is not a control packet and not STP/SDP/END/EDB when not scrambled
363 iter = map_table->data_encode_map.find(word_val);
364 xtracted_data[i] = iter->second;
365 }
366 if(curr_running_disp->calculate_disparity(xtracted_data[i].get_word(0),0) == 0)
367 {
368 curr_running_disp->set_CRD(lane,sc_logic(0));
369 }
370 else if(curr_running_disp->calculate_disparity(xtracted_data[i].get_word(0),0) == 1)
371 {
372 curr_running_disp->set_CRD(lane,sc_logic(1));
373 }
374 wait(SC_ZERO_TIME);
375 }
376 /// data has now been encoded...needs to be serialized
377 /// Have the packet, now packetize it properly
378 /// If we now have to just send the data onto the bus this data, xtracted_data can be forwarded
379 }
380 else if(!init_done.read())
381 {
382 initialization_done = false;
383 interleave_idle = true;
384 skp_counter = 0;
385 }
386
387 finished_sending_pkt = false;
388 while(pkt_cnt < size)
389 {
390 finished_sending_pkt = false;
391 for(j=0;j<10;j++)
392 {
393 for(i=pkt_cnt;i< (pkt_cnt+LINK_WIDTH) ;i++)
394 {
395 if(LINK_WIDTH == 1)
396 lane_data[j] = (xtracted_data[i].range(9-j,9-j));
397 else
398 lane_data[j] = (xtracted_data[i].range(9-j,9-j),lane_data[j].range(LINK_WIDTH-1,1));
399 }
400 }
401 pkt_cnt += LINK_WIDTH;
402 sym_boundary = 1;
403 wait(frame_boundary_ltssm_tx.posedge_event()); /// init_done will not be detected first time
404 /// So send IDLE frames first time only in this section
405 /// Else send the correct frames
406 /// At the end of this cycle, the data format is as we would like it to be (packetized properly)
407 for(i=0;i<10;i++)
408 {
409 encoded_data = 0;
410 encoded_data = lane_data[i]; /// This should be just fine
411 wait(link_clk.negedge_event());
412 skp_counter++;
413 switch(i)
414 {
415 case 0 : encoded_data0 = encoded_data;
416 case 1 : encoded_data1 = encoded_data;
417 case 2 : encoded_data2 = encoded_data;
418 case 3 : encoded_data3 = encoded_data;
419 case 4 : encoded_data4 = encoded_data;
420 case 5 : encoded_data5 = encoded_data;
421 case 6 : encoded_data6 = encoded_data;
422 case 7 : encoded_data7 = encoded_data;
423 case 8 : encoded_data8 = encoded_data;
424 case 9 : encoded_data9 = encoded_data;
425 }
426 }
427 sym_boundary = 0;
428 /// The data into the serializer input is ready and available
429 /// The serializer gives out data at every posedge link_clk.
430 /// Look at the data at the negedge to take care of race conditions
431 /// Thus, get the serialized at every negedge link_clk for the entire packet
432 /// Data is in serialized_data_out. This is a logic value
433 }
434 finished_sending_pkt = true;
435 pkt_cnt = 0;
436 }
437}
438
439//// Signal for retraining
440void pl_top::check_reinit()
441{
442 while(true)
443 {
444 wait(frame_boundary_ltssm_tx.posedge_event());
445 if(!init_done.read() && finished_sending_pkt)
446 start_reinit.write(true);
447 else if(!init_done.read() && !initialization_done)
448 start_reinit.write(true);
449 else
450 start_reinit.write(false);
451 }
452}
453
454/// Singal for staging the retraining
455void pl_top::check_stage_reinit()
456{
457 while(true)
458 {
459 wait(frame_boundary_ltssm_tx.negedge_event());
460 if(start_reinit.read())
461 stage_reinit.write(true);
462 else
463 stage_reinit.write(false);
464 }
465}
466
467/// This block is responsible for processing the incoming
468/// data on the ingress port/receiver side.
469/// It does the reverse of the transmit side.
470/// First decodes, then descrambles and then reframes
471/// Forms the appropriate packet and then puts into into the TLM FIFO
472/// for the DLL to consume the packet
473void pl_top::ingress_process_packet() /// Receiver/Ingress port
474{
475 int i,j;
476 int ingr_cnt = 0;
477 int pkt_cnt = 0;
478 int idl_count = 0,num_pad = 0;
479 int lane_with_start = 0,lane_with_end = 0;
480 int reset_lfsr_counter = 0;
481 unsigned short descramble_lfsr[LINK_WIDTH];
482 unsigned long word_val;
483 RefPciePacket ingress_packet,send_packet;
484 bool end_detected = false;
485 bool stp_sdp_ended = true;
486 bool start_ingr_packet[LINK_WIDTH],end_ingr_packet[LINK_WIDTH],start_ingr_pkt = false;
487 bool first_time_after_L0 = true;
488 bool reset_lfsr;
489 bool com_detected = false;
490 bool skp_ordered_set = false;
491 bool last_frame_idle = false;
492 bool back2back_pkt = false;
493 bool this_frame_start_detected = false,this_frame_end_detected = false;
494 map<int,int>::iterator iter1,iter2,iter3,iter4;
495
496 //Receive Error types
497 enum {RE_NONE, RE_PRD, RE_NRD, RE_FRA, RE_8b10b};
498 int rcv_error = RE_NONE;
499
500 while(true)
501 {
502 while(!end_detected) /// Read in the entire packet
503 {
504 /// Now its the turn of the deserializer to play its part
505 /// Make sure the deserializer can see the internal PL layer frame_boundary/ref_clk properly
506 wait(frm_boundary_deser.posedge_event());
507 wait(link_clk.posedge_event());
508
509 ingr_xtracted_data[ingr_cnt++] = deser_data0; /// First chunk and so on
510 ingr_xtracted_data[ingr_cnt++] = deser_data1;
511 ingr_xtracted_data[ingr_cnt++] = deser_data2;
512 ingr_xtracted_data[ingr_cnt++] = deser_data3;
513 ingr_xtracted_data[ingr_cnt++] = deser_data4;
514 ingr_xtracted_data[ingr_cnt++] = deser_data5;
515 ingr_xtracted_data[ingr_cnt++] = deser_data6;
516 ingr_xtracted_data[ingr_cnt++] = deser_data7;
517 ingr_xtracted_data[ingr_cnt++] = deser_data8;
518 ingr_xtracted_data[ingr_cnt++] = deser_data9;
519 /// Received LINK_WIDTH number of characters
520 if((init_done_rx.read() && reset_l.read() && reset_por_l.read())) /// Wait until a packet is sent before handling over control to the LTSSM
521 {
522 for(j=0;j<LINK_WIDTH;j++)
523 {
524 for(i=0;i<10;i++)
525 {
526 ingr_lane_data[j] = (ingr_xtracted_data[ingr_cnt+i-10].range(j,j),ingr_lane_data[j].range(9,1));
527 }
528 start_ingr_packet[j] = false;
529 end_ingr_packet[j] = false;
530 descrambler_i->start_scramble_reg[j] = true;
531 descramble_lfsr[j] = descrambler_i->get_lfsr(j); /// Descramble all the packets with this lfsr
532 }
533 for(i=0;i<LINK_WIDTH;i++) /// Form the packets
534 {
535 ingr_decoded_data[pkt_cnt] = ingr_lane_data[i].range(0,9);
536 pkt_cnt++;
537 if(i % 4 == 0)
538 {
539 if(ingr_decoded_data[pkt_cnt-1] == 0x097 || ingr_decoded_data[pkt_cnt-1] == 0x368 || ingr_decoded_data[pkt_cnt-1] == 0x30a || ingr_decoded_data[pkt_cnt-1] == 0x0f5) /// STP/SDP
540 {
541 start_ingr_packet[i] = true;
542 start_ingr_pkt = true;
543 this_frame_start_detected = true;
544 }
545 }
546 if((i+1) % 4 == 0)
547 {
548 if(ingr_decoded_data[pkt_cnt-1] == 0x117 || ingr_decoded_data[pkt_cnt-1] == 0x2e8 || ingr_decoded_data[pkt_cnt-1] == 0x217 || ingr_decoded_data[pkt_cnt-1] == 0x1e8) /// END/EDB
549 {
550 end_ingr_packet[i] = true;
551 this_pkt_size = pkt_cnt;
552 end_detected = true;
553 this_frame_end_detected = true;
554 }
555 }
556 /// Decode the characters in this frame
557 /// ingr_decoded_data[pkt_cnt-1].concat_get_data(val,0);
558 word_val = ingr_decoded_data[pkt_cnt-1].get_word(0);
559 iter3 = map_table->spec_symbol_decode_map.find(word_val);
560 iter1 = map_table->data_decode_map.find(word_val);
561 iter4 = map_table->neg_spec_symbol_decode_map.find(word_val);
562 iter2 = map_table->neg_data_decode_map.find(word_val);
563 if(iter3 != map_table->spec_symbol_decode_map.end())
564 {
565 ingr_xtracted_byte[pkt_cnt-1] = iter3->second;
566 if(!curr_running_disp->get_rx_CRD(i).to_bool() && init_done_rx.read())
567 {
568 LOG_WARNING << "WARNING : _PL_INGR_ : Positive running Disparity Error in lane " << i;
569 rcv_error = RE_PRD;
570 }
571 else if(init_done_rx.read())
572 {
573 if(curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) == 1)
574 curr_running_disp->set_rx_CRD(i,sc_logic(1));
575 else if(curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) == 0)
576 curr_running_disp->set_rx_CRD(i,sc_logic(0));
577 }
578 /// Check for STP/SDP framing error
579 if(iter3->second == STP || iter3->second == SDP)
580 {
581 if((i % 4 != 0) && init_done_rx.read())
582 {
583 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). STP/SDP should come on modulo 4 lanes";
584 rcv_error = RE_FRA;
585 }
586 if(last_frame_idle && i != 0 && init_done_rx.read())
587 {
588 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). STP/SDP must be in lane 0 after Logical Idle";
589 rcv_error = RE_FRA;
590 }
591 if(!stp_sdp_ended && init_done_rx.read())
592 {
593 LOG_WARNING << "WARNING : _PL_INGR : Framing Error (Lane= " << i << "). STP/SDP without previous END/EDB";
594 rcv_error = RE_FRA;
595 }
596 stp_sdp_ended = false;
597 }
598 else if(iter3->second == SKP)
599 {
600 LOG_DEBUG << "DEBUG : _PL_INGR_ : SKP Character received (Lane= " << i << ")";
601 }
602
603 /// Check for END/EDB framing error
604 else if(iter3->second == END || iter3->second == EDB)
605 {
606 if(((i+1) % 4) != 0 && init_done_rx.read())
607 {
608 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). END/EDB should come in modulo 4 - 1 lanes";
609 rcv_error = RE_FRA;
610 }
611
612 if(i != LINK_WIDTH - 1) /// Make sure the next packet is a PAD/STP/SDP
613 {
614 if(ingr_lane_data[i+1].range(0,9) != 0x97 && ingr_lane_data[i+1].range(0,9) != 0x368 && ingr_lane_data[i+1].range(0,9) != 0x30a && ingr_lane_data[i+1].range(0,9) != 0xf5 && ingr_lane_data[i+1].range(0,9) != 0x3a8 && ingr_lane_data[i+1].range(0,9) != 0x57 && init_done_rx.read())
615 {
616 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). END/EDB must be followed by PAD/STP/SDP";
617 rcv_error = RE_FRA;
618 }
619 }
620 if(stp_sdp_ended && init_done_rx.read())
621 {
622 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). END/EDB without previous STP/SDP";
623 rcv_error = RE_FRA;
624 }
625 stp_sdp_ended = true;
626 }
627 else if(iter3->second == COM && !stp_sdp_ended && init_done_rx.read())
628 {
629 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). Unexpected COM Character. Unterminated STP/SDP";
630 rcv_error = RE_FRA;
631 }
632
633 ingr_xtracted_byte_c[pkt_cnt-1] = true;
634 }
635 else if(iter4 != map_table->neg_spec_symbol_decode_map.end())
636 {
637 ingr_xtracted_byte[pkt_cnt-1] = iter4->second;
638 if(curr_running_disp->get_rx_CRD(i).to_bool() && init_done_rx.read())
639 {
640 LOG_WARNING << "WARNING : _PL_INGR_ : Negative running Disparity Error in lane " << i;
641 rcv_error = RE_NRD;
642 }
643 else if(init_done_rx.read())
644 {
645 if(curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) == 1)
646 curr_running_disp->set_rx_CRD(i,sc_logic(1));
647 else if(curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) == 0)
648 curr_running_disp->set_rx_CRD(i,sc_logic(0));
649 }
650 if(iter4->second == STP || iter4->second == SDP)
651 {
652 if(i % 4 != 0 && init_done_rx.read())
653 {
654 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). STP/SDP should come on modulo 4 lanes";
655 rcv_error = RE_FRA;
656 }
657 if(last_frame_idle && i != 0 && init_done_rx.read())
658 {
659 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). STP/SDP must be in lane 0 after Logical Idle";
660 rcv_error = RE_FRA;
661 }
662 if(!stp_sdp_ended && init_done_rx.read())
663 {
664 LOG_WARNING << "WARNING : _PL_INGR : Framing Error (Lane= " << i << "). STP/SDP without previous END/EDB";
665 rcv_error = RE_FRA;
666 }
667 stp_sdp_ended = false;
668 }
669 else if(iter4->second == SKP)
670 {
671 LOG_DEBUG << "DEBUG : _PL_INGR_ : SKP Character received (Lane= " << i << ")";
672 }
673 /// Check for END/EDB framing error
674 else if(iter4->second == END || iter4->second == EDB)
675 {
676 if(((i+1) % 4) != 0 && init_done_rx.read())
677 {
678 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). END/EDB should come in modulo 4 - 1 lanes";
679 rcv_error = RE_FRA;
680 }
681
682 if(i != LINK_WIDTH - 1) /// Make sure the next packet is a PAD/STP/SDP
683 {
684 if(ingr_lane_data[i+1].range(0,9) != 0x97 && ingr_lane_data[i+1].range(0,9) != 0x368 && ingr_lane_data[i+1].range(0,9) != 0x30a && ingr_lane_data[i+1].range(0,9) != 0xf5 && ingr_lane_data[i+1].range(0,9) != 0x3a8 && ingr_lane_data[i+1].range(0,9) != 0x57 && init_done_rx.read())
685 {
686 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). END/EDB must be followed by PAD/STP/SDP";
687 rcv_error = RE_FRA;
688 }
689 }
690 if(stp_sdp_ended && init_done_rx.read())
691 {
692 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). END/EDB without previous STP/SDP";
693 rcv_error = RE_FRA;
694 }
695 stp_sdp_ended = true;
696 }
697 else if(iter4->second == COM && !stp_sdp_ended && init_done_rx.read())
698 {
699 LOG_WARNING << "WARNING : _PL_INGR_ : Framing Error (Lane= " << i << "). Unexpected COM. Unterminated STP/SDP";
700 rcv_error = RE_FRA;
701 }
702 ingr_xtracted_byte_c[pkt_cnt-1] = true;
703 }
704 else if(iter1 != map_table->data_decode_map.end())
705 {
706 ingr_xtracted_byte[pkt_cnt-1] = iter1->second;
707 ingr_xtracted_byte_c[pkt_cnt-1] = false;
708 if(!curr_running_disp->get_rx_CRD(i).to_bool() && curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) != 2 && init_done_rx.read())
709 {
710 LOG_WARNING << "WARNING : _PL_INGR_ : Positive running Disparity Error in lane " << i;
711 rcv_error = RE_PRD;
712 }
713 else if(init_done_rx.read())
714 {
715 if(curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) == 1)
716 curr_running_disp->set_rx_CRD(i,sc_logic(1));
717 else if(curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) == 0)
718 curr_running_disp->set_rx_CRD(i,sc_logic(0));
719 }
720 }
721 else if(iter2 != map_table->neg_data_decode_map.end())
722 {
723 ingr_xtracted_byte[pkt_cnt-1] = iter2->second;
724 ingr_xtracted_byte_c[pkt_cnt-1] = false;
725 if(curr_running_disp->get_rx_CRD(i).to_bool() && curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) != 2 && init_done_rx.read())
726 {
727 LOG_WARNING << "WARNING : _PL_INGR_ : Negative running Disparity Error in lane " << i;
728 rcv_error = RE_NRD;
729 }
730 else if(init_done_rx.read())
731 {
732 if(curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) == 1)
733 curr_running_disp->set_rx_CRD(i,sc_logic(1));
734 else if(curr_running_disp->calculate_disparity(ingr_decoded_data[pkt_cnt-1],0) == 0)
735 curr_running_disp->set_rx_CRD(i,sc_logic(0));
736 }
737 }
738 else if(!first_time_after_L0 && init_done_rx.read())
739 {
740 ingr_xtracted_byte[pkt_cnt-1] = "xxxxxxxx";
741 ingr_xtracted_byte_c[pkt_cnt-1] = false;
742 LOG_WARNING << "WARNING : _PL_INGR_ : 8b/10b Decode Error (Lane= " << i << ")";
743 rcv_error = RE_8b10b;
744 }
745
746 if(ingr_xtracted_byte_c[pkt_cnt - 1] && ingr_xtracted_byte[pkt_cnt - 1] == K28_5) /// COM Reset
747 {
748 reset_lfsr_counter++;
749 }
750 if(ingr_xtracted_byte_c[pkt_cnt-1] && (ingr_xtracted_byte[pkt_cnt - 1] == SKP) && com_detected) /// This is a SKP ordered set
751 {
752 skp_ordered_set = true;
753 LOG_DEBUG << "DEBUG : _PL_INGR_ : SKP Ordered Set Received (Lane= " << i << ")";
754 }
755 else
756 {
757 skp_ordered_set = false;
758 }
759 /// Dont forward the LFSR
760 /// Also the LFSR should not be forwarded for the entire SKP ordered set
761 if(ingr_xtracted_byte_c[pkt_cnt-1] && (ingr_xtracted_byte[pkt_cnt-1] == PAD) && (end_detected == 1)) /// Dont send PAD after END/EDB to DLL
762 {
763 num_pad++;
764 }
765 if(!ingr_xtracted_byte_c[pkt_cnt-1])
766 {
767 word_val = ingr_xtracted_byte[pkt_cnt-1].get_word(0);
768 ingr_xtracted_byte[pkt_cnt-1] = descrambler_i->scramble_descramble(word_val,0,0,i);
769 if(ingr_xtracted_byte[pkt_cnt-1] == 0x00)
770 idl_count++;
771 descrambler_i->set_lfsr(descramble_lfsr[i],i);
772 }
773 }
774 if(reset_lfsr_counter == LINK_WIDTH)
775 reset_lfsr = true;
776 else
777 reset_lfsr = false;
778 reset_lfsr_counter = 0;
779
780 if(idl_count == 8) /// An IDLE Frame
781 {
782 last_frame_idle = 1;
783 idl_count = 0;
784 }
785 else
786 {
787 last_frame_idle = 0;
788 }
789 if(reset_lfsr)
790 {
791 descrambler_i->scramble_descramble_all(K28_5,0,1);
792 reset_lfsr = false;
793 com_detected = true; /// Could be the start of an ordered set
794 }
795 else if(skp_ordered_set)
796 descrambler_i->scramble_descramble_all(SKP,0,1);
797 else if(!first_time_after_L0) /// Dont forward the LFSR immediatly after coming out of the LTSSM control
798 {
799 com_detected = false;
800 for(int lane_num = 0; lane_num < LINK_WIDTH; lane_num++){
801 word_val = ingr_xtracted_byte[(pkt_cnt-1)-(LINK_WIDTH-1-lane_num)].get_word(0);
802 if(ingr_xtracted_byte_c[(pkt_cnt-1)-(LINK_WIDTH-1-lane_num)])
803 descrambler_i->scramble_descramble(word_val,0,1,lane_num);
804 else
805 descrambler_i->scramble_descramble(word_val,0,0,lane_num);
806 }
807 }
808
809 if(first_time_after_L0) first_time_after_L0 = false;
810
811 for(int lane_scram = 0; lane_scram < LINK_WIDTH; lane_scram++)
812 descrambler_i->start_scramble_reg[lane_scram] = false;
813 /// pkt_cnt is always a multiple of LINK_WIDTH
814 /// the END might be encountered at a boundary of LINK_WIDTH or somewhere in between
815 /// Lets check for that
816 }
817 else
818 {
819 ingr_cnt = 0;
820 pkt_cnt = 0;
821 num_pad = 0;
822 first_time_after_L0 = true;
823 rcv_error = RE_NONE;
824 stp_sdp_ended = true;
825 }
826 /// Checks for LINK_WIDTH byte DLLP or IDL interleaved TLP or back to back TLP
827 for(i=0;i<LINK_WIDTH;i++)
828 {
829 if(start_ingr_packet[i])
830 {
831 /// This lane has STP/SDP
832 lane_with_start = i;
833 }
834 if(end_ingr_packet[i])
835 {
836 lane_with_end = i;
837 }
838 }
839 if(this_frame_start_detected && this_frame_end_detected) /// Test for Back to Back packets without interleaving
840 {
841 if(lane_with_start > lane_with_end)
842 back2back_pkt = true;
843 else
844 back2back_pkt = false;
845
846 lane_with_start = 0;
847 lane_with_end = 0;
848 }
849 if(!start_ingr_pkt && rcv_error==RE_NONE)
850 {
851 pkt_cnt = 0;
852 this_pkt_size = 0;
853 ingr_cnt = 0;
854 num_pad = 0;
855 }
856
857 this_frame_start_detected = false;
858 this_frame_end_detected = false;
859 }
860 /// If it comes out of this loop, it means it received an END/EDB symbol
861 /// Its fair to assume that a start must have come
862
863 /// Now just form the packets
864 ingress_packet = new pciePacket(this_pkt_size);
865
866 for(i=0;i<this_pkt_size;i++)
867 {
868 ingress_packet->modify_byte(i,ingr_xtracted_byte[i]);
869 }
870 global_ingress_packet = ingress_packet;
871 /// Notify the producer that the packet has been produced
872 /// Before I reset everything to 0 I need to check for back2back
873 if(back2back_pkt)
874 {
875 for(i=this_pkt_size,j=0;i<pkt_cnt;i++,j++)
876 {
877 ingr_xtracted_byte[j] = ingr_xtracted_byte[i]; /// Prepare for the next packet
878 ingr_xtracted_byte_c[j] = ingr_xtracted_byte_c[i];
879 }
880 start_ingr_pkt = true;
881 pkt_cnt = j;
882 end_detected = 0;
883 num_pad = 0;
884 ingr_cnt = 0;
885 }
886 else
887 {
888 pkt_cnt = 0;
889 end_detected = 0;
890 start_ingr_pkt = false;
891 num_pad = 0;
892 ingr_cnt = 0;
893 }
894 back2back_pkt = false;
895
896 /// The Producer code now begins
897 send_packet = global_ingress_packet;
898
899 if(send_packet->get_size() != 0)
900 {
901 switch(rcv_error){
902 case RE_NONE:
903 send_packet->set_control(DLLP_ACK);
904 break;
905 case RE_FRA:
906 send_packet->set_control(DLLP_NAK_FRAMING);
907 break;
908 case RE_8b10b:
909 case RE_PRD:
910 case RE_NRD:
911 send_packet->set_control(DLLP_NAK);
912 break;
913
914 }
915 pl_dll_out.send_packet(send_packet);
916 }
917 LOG_DEBUG << "PL_TOP: Resetting rcv_error to RE_NONE";
918 rcv_error=RE_NONE;
919 }
920}