// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: pl_top.cpp
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
/// This is the main transmit block.
/// It gets the packet from the TLM FIFO
/// forms the PL frame and then sends out according to the LINK_WIDTH
/// It first scrambles, then encodes and then finally forms frames
/// It is also responsible for forming intermediate SKP Ordered sets and IDLE sets
void pl_top::process_packet()
unsigned short scramble_lfsr
;
map
<int,int>::iterator iter
;
RefPciePacket receive_packet
;
RefPciePacket idle_packet
;
RefPciePacket skp_packet
;
bool waitingforFirstData
= true;
bool packet_ready_dll
,packet_ready_tl
,round_robin_dll_tl
= false;
bool skp_ordered_set
= false;
bool put_end_symbol
= false;
sc_lv
<5> control
; /// control signal from the DLL
packet_ready_tl
= dll_pl_tlp_in
.is_packet_ready();
packet_ready_dll
= dll_pl_dllp_in
.is_packet_ready();
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
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
if(packet_ready_dll
&& !round_robin_dll_tl
)
dll_pl_dllp_in
.get_packet(receive_packet
);
//cout<< sc_time_stamp() <<"\t\t\t\t\t| PL: Recvd DLLP " << receive_packet->getPacketId() << " from DLL." <<endl;
if(dll_pkt_cnt
>= 5) /// Make sure FC_INIT packets go before any TLP
round_robin_dll_tl
= true;
else if(packet_ready_tl
&& round_robin_dll_tl
)
dll_pl_tlp_in
.get_packet(receive_packet
);
//cout<< sc_time_stamp() <<"\t\t\t\t\t| PL: Recvd TLP " << receive_packet->getPacketId() << " from DLL." <<endl;
round_robin_dll_tl
= false;
else if(packet_ready_dll
&& !packet_ready_tl
&& round_robin_dll_tl
) /// Still keep next priority for TL. But dequeue DLL Q for now
dll_pl_dllp_in
.get_packet(receive_packet
);
//cout<< sc_time_stamp() <<"\t\t\t\t\t| PL: Recvd DLLP " << receive_packet->getPacketId() << " from DLL." <<endl;
else if( packet_ready_tl
&& !packet_ready_dll
&& !round_robin_dll_tl
) /// Still Keep next priority for DLL. But dequeue TL for now
dll_pl_tlp_in
.get_packet(receive_packet
);
//cout<< sc_time_stamp() <<"\t\t\t\t\t| PL: Recvd TLP " << receive_packet->getPacketId() << " from DLL." <<endl;
pkt_id
= receive_packet
->getPacketId();
global_packet
= receive_packet
;
waitingforFirstData
= false;
size
= global_packet
->get_size();
control
= global_packet
->get_control();
else if((skp_counter
< 1450) || skp_counter
== 0)/// Produce IDLE packets
idle_packet
= new pciePacket(LINK_WIDTH
);
for(i
=0;i
<LINK_WIDTH
;i
++)
idle_packet
->modify_byte(i
,0x00);
global_packet
= idle_packet
;
if(packet_ready_dll
|| packet_ready_tl
)
q_not_empty
.write(true); /// data is available, but the last IDLE frame has not been transmitted
else if(!packet_ready_dll
&& !packet_ready_tl
&& waitingforFirstData
)
q_not_empty
.write(false);
size
= global_packet
->get_size();
interleave_idle
= false; /// Interleave every DLLP/TLP with an IDLE frame
control
= 0x000; /// No Control Chars in the IDLE frame
else if((skp_counter
>= 1450))
skp_packet
= new pciePacket(4*LINK_WIDTH
); /// SKP is sent across 4 frames
for(i
=0;i
<LINK_WIDTH
;i
++)
skp_packet
->modify_byte(i
,COM
);
for(i
=LINK_WIDTH
;i
<2*LINK_WIDTH
;i
++)
skp_packet
->modify_byte(i
,SKP
);
for(i
=2*LINK_WIDTH
;i
<3*LINK_WIDTH
;i
++)
skp_packet
->modify_byte(i
,SKP
);
for(i
=3*LINK_WIDTH
;i
<4*LINK_WIDTH
;i
++)
skp_packet
->modify_byte(i
,SKP
);
global_packet
= skp_packet
;
size
= global_packet
->get_size();
control
= pkt
->get_control();
if(control
[1] == 0x1) /// Only for STP, ignore the 0th byte
/// Check if LINK_WIDTH > size + 2
if(size
<= LINK_WIDTH
) /// For FC_Init and IDLE frames
control
= pkt
->get_control(); /// Control signal from the DLLP
if((control
[1] != 0x1) && (control
[2] != 0x1)) /// IDLE packet
for(i
= 0; i
< size
; i
++) /// The actual data without STP/SDP
xtracted_data
[i
] = pkt
->get_byte(i
);
xtracted_data_c
[i
] = false;
for(i
= size
; i
< LINK_WIDTH
; i
++) /// PAD or END character
xtracted_data_c
[0] = true;
else if(control
[2] == 0x1)
xtracted_data_c
[0] = true;
for(i
= 1,j
=0; i
<= size
,j
< size
; i
++,j
++) /// The actual data with CRC
xtracted_data
[i
] = pkt
->get_byte(j
);
xtracted_data_c
[i
] = false;
for(i
= size
+1 ; i
< LINK_WIDTH
; i
++) /// PAD or END character
if(((i
+1) % 4) == 0 && (control
[3] == 0x1) && !put_end_symbol
) /// END
xtracted_data_c
[i
] = true;
else if(((i
+1) %4) == 0 && (control
[4] == 0x1) && !put_end_symbol
) /// EDB
xtracted_data_c
[i
] = true;
xtracted_data_c
[i
] = true;
else/// Transaction Layer packets or SKP Ordered Set or DLLP with size > LINK_WIDTH
control
= pkt
->get_control();
if(control
[0] == 0) /// TLP
xtracted_data_c
[0] = true;
else if(control
[2] == 0x1)
xtracted_data_c
[0] = true;
for(i
=1,j
=0; i
<= size
,j
<size
; i
++,j
++) /// The actual data with CRC for TLP
if(xtracted_data
[0] == SDP
) /// get data from byte 0
xtracted_data
[i
] = pkt
->get_byte(j
);
xtracted_data
[i
] = pkt
->get_byte(i
);
xtracted_data_c
[i
] = false;
for(i
= size
+1 ; i
< LINK_WIDTH
*ceil(double((size
+2)/LINK_WIDTH
)); i
++)
if(((i
+1) % 4) == 0 && (control
[3] == 0x1) && !put_end_symbol
) /// END
xtracted_data_c
[i
] = true;
else if(((i
+1) % 4) == 0 && (control
[4] == 0x1) && !put_end_symbol
) /// EDB
xtracted_data_c
[i
] = true;
xtracted_data_c
[i
] = true;
size
= LINK_WIDTH
*ceil(double((size
+2)/LINK_WIDTH
));
xtracted_data
[i
] = pkt
->get_byte(i
);
xtracted_data_c
[i
] = true;
/// Now scramble the data
if(init_done
.read() && reset_l
.read() && reset_por_l
.read())
initialization_done
= true;
for(int lane_scram
=0; lane_scram
<LINK_WIDTH
; lane_scram
++)
scrambler_i
->start_scramble_reg
[lane_scram
] = true;
scramble_lfsr
= scrambler_i
->get_lfsr(0);
for(i
= 0 ; i
< size
; i
++) /// Whether to scramble or descramble the data. The Start, end and PAD symbols will not be scrambled anyway
if(((i
% LINK_WIDTH
) == 0 && (i
> 0)) || (LINK_WIDTH
== 1 && xtracted_data
[i
] == SKP
))
if(xtracted_data_c
[i
]) /// Should go into this block when LINK_1 and control character
if(xtracted_data
[i
] == SKP
)
scrambler_i
->scramble_descramble_all(SKP
,0,1);
scrambler_i
->scramble_descramble_all(0x00,1,0); /// Forward the LFSR for the next scramble
scramble_lfsr
= scrambler_i
->get_lfsr(0);
if(control
[0] == 0x1) /// This is a control packet. Dont scramble it at all
xtracted_data_c
[i
] = true;
if(xtracted_data_c
[i
]) /// Dont scramble K characters
/// First check if its a COM...Reset lfsr
word_val
= xtracted_data
[i
].get_word(0);
if(xtracted_data
[i
] == COM
)
scrambler_i
->scramble_descramble_all(word_val
,1,1);
word_val
= xtracted_data
[i
].get_word(0);
xtracted_data
[i
] = scrambler_i
->scramble_descramble_all(word_val
,1,0);
if(scrambler_i
->get_lfsr(0) != 0xffff) {
for(int lane_scram
=0; lane_scram
<LINK_WIDTH
; lane_scram
++)
scrambler_i
->set_lfsr(scramble_lfsr
,lane_scram
);
scrambler_i
->scramble_descramble_all(0x00,1,0); /// Size of packet is only 8 bytes
for(int lane_scram
=0; lane_scram
<LINK_WIDTH
; lane_scram
++)
scrambler_i
->start_scramble_reg
[lane_scram
] = false;
for(i
= 0; i
< size
; i
++)
if(curr_running_disp
->get_CRD(lane
) == 0)
word_val
= xtracted_data
[i
].get_word(0);
iter
= map_table
->neg_spec_symbol_map
.find(word_val
);
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
iter
= map_table
->neg_data_encode_map
.find(word_val
);
xtracted_data
[i
] = iter
->second
;
else if(curr_running_disp
->get_CRD(lane
) == 1)
word_val
= xtracted_data
[i
].get_word(0);
iter
= map_table
->spec_symbol_map
.find(word_val
);
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
iter
= map_table
->data_encode_map
.find(word_val
);
xtracted_data
[i
] = iter
->second
;
if(curr_running_disp
->calculate_disparity(xtracted_data
[i
].get_word(0),0) == 0)
curr_running_disp
->set_CRD(lane
,sc_logic(0));
else if(curr_running_disp
->calculate_disparity(xtracted_data
[i
].get_word(0),0) == 1)
curr_running_disp
->set_CRD(lane
,sc_logic(1));
/// data has now been encoded...needs to be serialized
/// Have the packet, now packetize it properly
/// If we now have to just send the data onto the bus this data, xtracted_data can be forwarded
else if(!init_done
.read())
initialization_done
= false;
finished_sending_pkt
= false;
finished_sending_pkt
= false;
for(i
=pkt_cnt
;i
< (pkt_cnt
+LINK_WIDTH
) ;i
++)
lane_data
[j
] = (xtracted_data
[i
].range(9-j
,9-j
));
lane_data
[j
] = (xtracted_data
[i
].range(9-j
,9-j
),lane_data
[j
].range(LINK_WIDTH
-1,1));
wait(frame_boundary_ltssm_tx
.posedge_event()); /// init_done will not be detected first time
/// So send IDLE frames first time only in this section
/// Else send the correct frames
/// At the end of this cycle, the data format is as we would like it to be (packetized properly)
encoded_data
= lane_data
[i
]; /// This should be just fine
wait(link_clk
.negedge_event());
case 0 : encoded_data0
= encoded_data
;
case 1 : encoded_data1
= encoded_data
;
case 2 : encoded_data2
= encoded_data
;
case 3 : encoded_data3
= encoded_data
;
case 4 : encoded_data4
= encoded_data
;
case 5 : encoded_data5
= encoded_data
;
case 6 : encoded_data6
= encoded_data
;
case 7 : encoded_data7
= encoded_data
;
case 8 : encoded_data8
= encoded_data
;
case 9 : encoded_data9
= encoded_data
;
/// The data into the serializer input is ready and available
/// The serializer gives out data at every posedge link_clk.
/// Look at the data at the negedge to take care of race conditions
/// Thus, get the serialized at every negedge link_clk for the entire packet
/// Data is in serialized_data_out. This is a logic value
finished_sending_pkt
= true;
//// Signal for retraining
void pl_top::check_reinit()
wait(frame_boundary_ltssm_tx
.posedge_event());
if(!init_done
.read() && finished_sending_pkt
)
start_reinit
.write(true);
else if(!init_done
.read() && !initialization_done
)
start_reinit
.write(true);
start_reinit
.write(false);
/// Singal for staging the retraining
void pl_top::check_stage_reinit()
wait(frame_boundary_ltssm_tx
.negedge_event());
stage_reinit
.write(true);
stage_reinit
.write(false);
/// This block is responsible for processing the incoming
/// data on the ingress port/receiver side.
/// It does the reverse of the transmit side.
/// First decodes, then descrambles and then reframes
/// Forms the appropriate packet and then puts into into the TLM FIFO
/// for the DLL to consume the packet
void pl_top::ingress_process_packet() /// Receiver/Ingress port
int idl_count
= 0,num_pad
= 0;
int lane_with_start
= 0,lane_with_end
= 0;
int reset_lfsr_counter
= 0;
unsigned short descramble_lfsr
[LINK_WIDTH
];
RefPciePacket ingress_packet
,send_packet
;
bool end_detected
= false;
bool stp_sdp_ended
= true;
bool start_ingr_packet
[LINK_WIDTH
],end_ingr_packet
[LINK_WIDTH
],start_ingr_pkt
= false;
bool first_time_after_L0
= true;
bool com_detected
= false;
bool skp_ordered_set
= false;
bool last_frame_idle
= false;
bool back2back_pkt
= false;
bool this_frame_start_detected
= false,this_frame_end_detected
= false;
map
<int,int>::iterator iter1
,iter2
,iter3
,iter4
;
enum {RE_NONE
, RE_PRD
, RE_NRD
, RE_FRA
, RE_8b10b
};
while(!end_detected
) /// Read in the entire packet
/// Now its the turn of the deserializer to play its part
/// Make sure the deserializer can see the internal PL layer frame_boundary/ref_clk properly
wait(frm_boundary_deser
.posedge_event());
wait(link_clk
.posedge_event());
ingr_xtracted_data
[ingr_cnt
++] = deser_data0
; /// First chunk and so on
ingr_xtracted_data
[ingr_cnt
++] = deser_data1
;
ingr_xtracted_data
[ingr_cnt
++] = deser_data2
;
ingr_xtracted_data
[ingr_cnt
++] = deser_data3
;
ingr_xtracted_data
[ingr_cnt
++] = deser_data4
;
ingr_xtracted_data
[ingr_cnt
++] = deser_data5
;
ingr_xtracted_data
[ingr_cnt
++] = deser_data6
;
ingr_xtracted_data
[ingr_cnt
++] = deser_data7
;
ingr_xtracted_data
[ingr_cnt
++] = deser_data8
;
ingr_xtracted_data
[ingr_cnt
++] = deser_data9
;
/// Received LINK_WIDTH number of characters
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
for(j
=0;j
<LINK_WIDTH
;j
++)
ingr_lane_data
[j
] = (ingr_xtracted_data
[ingr_cnt
+i
-10].range(j
,j
),ingr_lane_data
[j
].range(9,1));
start_ingr_packet
[j
] = false;
end_ingr_packet
[j
] = false;
descrambler_i
->start_scramble_reg
[j
] = true;
descramble_lfsr
[j
] = descrambler_i
->get_lfsr(j
); /// Descramble all the packets with this lfsr
for(i
=0;i
<LINK_WIDTH
;i
++) /// Form the packets
ingr_decoded_data
[pkt_cnt
] = ingr_lane_data
[i
].range(0,9);
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
start_ingr_packet
[i
] = true;
this_frame_start_detected
= true;
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
end_ingr_packet
[i
] = true;
this_frame_end_detected
= true;
/// Decode the characters in this frame
/// ingr_decoded_data[pkt_cnt-1].concat_get_data(val,0);
word_val
= ingr_decoded_data
[pkt_cnt
-1].get_word(0);
iter3
= map_table
->spec_symbol_decode_map
.find(word_val
);
iter1
= map_table
->data_decode_map
.find(word_val
);
iter4
= map_table
->neg_spec_symbol_decode_map
.find(word_val
);
iter2
= map_table
->neg_data_decode_map
.find(word_val
);
if(iter3
!= map_table
->spec_symbol_decode_map
.end())
ingr_xtracted_byte
[pkt_cnt
-1] = iter3
->second
;
if(!curr_running_disp
->get_rx_CRD(i
).to_bool() && init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Positive running Disparity Error in lane " << i
;
else if(init_done_rx
.read())
if(curr_running_disp
->calculate_disparity(ingr_decoded_data
[pkt_cnt
-1],0) == 1)
curr_running_disp
->set_rx_CRD(i
,sc_logic(1));
else if(curr_running_disp
->calculate_disparity(ingr_decoded_data
[pkt_cnt
-1],0) == 0)
curr_running_disp
->set_rx_CRD(i
,sc_logic(0));
/// Check for STP/SDP framing error
if(iter3
->second
== STP
|| iter3
->second
== SDP
)
if((i
% 4 != 0) && init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). STP/SDP should come on modulo 4 lanes";
if(last_frame_idle
&& i
!= 0 && init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). STP/SDP must be in lane 0 after Logical Idle";
if(!stp_sdp_ended
&& init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR : Framing Error (Lane= " << i
<< "). STP/SDP without previous END/EDB";
else if(iter3
->second
== SKP
)
LOG_DEBUG
<< "DEBUG : _PL_INGR_ : SKP Character received (Lane= " << i
<< ")";
/// Check for END/EDB framing error
else if(iter3
->second
== END
|| iter3
->second
== EDB
)
if(((i
+1) % 4) != 0 && init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). END/EDB should come in modulo 4 - 1 lanes";
if(i
!= LINK_WIDTH
- 1) /// Make sure the next packet is a PAD/STP/SDP
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())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). END/EDB must be followed by PAD/STP/SDP";
if(stp_sdp_ended
&& init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). END/EDB without previous STP/SDP";
else if(iter3
->second
== COM
&& !stp_sdp_ended
&& init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). Unexpected COM Character. Unterminated STP/SDP";
ingr_xtracted_byte_c
[pkt_cnt
-1] = true;
else if(iter4
!= map_table
->neg_spec_symbol_decode_map
.end())
ingr_xtracted_byte
[pkt_cnt
-1] = iter4
->second
;
if(curr_running_disp
->get_rx_CRD(i
).to_bool() && init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Negative running Disparity Error in lane " << i
;
else if(init_done_rx
.read())
if(curr_running_disp
->calculate_disparity(ingr_decoded_data
[pkt_cnt
-1],0) == 1)
curr_running_disp
->set_rx_CRD(i
,sc_logic(1));
else if(curr_running_disp
->calculate_disparity(ingr_decoded_data
[pkt_cnt
-1],0) == 0)
curr_running_disp
->set_rx_CRD(i
,sc_logic(0));
if(iter4
->second
== STP
|| iter4
->second
== SDP
)
if(i
% 4 != 0 && init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). STP/SDP should come on modulo 4 lanes";
if(last_frame_idle
&& i
!= 0 && init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). STP/SDP must be in lane 0 after Logical Idle";
if(!stp_sdp_ended
&& init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR : Framing Error (Lane= " << i
<< "). STP/SDP without previous END/EDB";
else if(iter4
->second
== SKP
)
LOG_DEBUG
<< "DEBUG : _PL_INGR_ : SKP Character received (Lane= " << i
<< ")";
/// Check for END/EDB framing error
else if(iter4
->second
== END
|| iter4
->second
== EDB
)
if(((i
+1) % 4) != 0 && init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). END/EDB should come in modulo 4 - 1 lanes";
if(i
!= LINK_WIDTH
- 1) /// Make sure the next packet is a PAD/STP/SDP
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())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). END/EDB must be followed by PAD/STP/SDP";
if(stp_sdp_ended
&& init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). END/EDB without previous STP/SDP";
else if(iter4
->second
== COM
&& !stp_sdp_ended
&& init_done_rx
.read())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Framing Error (Lane= " << i
<< "). Unexpected COM. Unterminated STP/SDP";
ingr_xtracted_byte_c
[pkt_cnt
-1] = true;
else if(iter1
!= map_table
->data_decode_map
.end())
ingr_xtracted_byte
[pkt_cnt
-1] = iter1
->second
;
ingr_xtracted_byte_c
[pkt_cnt
-1] = false;
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())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Positive running Disparity Error in lane " << i
;
else if(init_done_rx
.read())
if(curr_running_disp
->calculate_disparity(ingr_decoded_data
[pkt_cnt
-1],0) == 1)
curr_running_disp
->set_rx_CRD(i
,sc_logic(1));
else if(curr_running_disp
->calculate_disparity(ingr_decoded_data
[pkt_cnt
-1],0) == 0)
curr_running_disp
->set_rx_CRD(i
,sc_logic(0));
else if(iter2
!= map_table
->neg_data_decode_map
.end())
ingr_xtracted_byte
[pkt_cnt
-1] = iter2
->second
;
ingr_xtracted_byte_c
[pkt_cnt
-1] = false;
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())
LOG_WARNING
<< "WARNING : _PL_INGR_ : Negative running Disparity Error in lane " << i
;
else if(init_done_rx
.read())
if(curr_running_disp
->calculate_disparity(ingr_decoded_data
[pkt_cnt
-1],0) == 1)
curr_running_disp
->set_rx_CRD(i
,sc_logic(1));
else if(curr_running_disp
->calculate_disparity(ingr_decoded_data
[pkt_cnt
-1],0) == 0)
curr_running_disp
->set_rx_CRD(i
,sc_logic(0));
else if(!first_time_after_L0
&& init_done_rx
.read())
ingr_xtracted_byte
[pkt_cnt
-1] = "xxxxxxxx";
ingr_xtracted_byte_c
[pkt_cnt
-1] = false;
LOG_WARNING
<< "WARNING : _PL_INGR_ : 8b/10b Decode Error (Lane= " << i
<< ")";
if(ingr_xtracted_byte_c
[pkt_cnt
- 1] && ingr_xtracted_byte
[pkt_cnt
- 1] == K28_5
) /// COM Reset
if(ingr_xtracted_byte_c
[pkt_cnt
-1] && (ingr_xtracted_byte
[pkt_cnt
- 1] == SKP
) && com_detected
) /// This is a SKP ordered set
LOG_DEBUG
<< "DEBUG : _PL_INGR_ : SKP Ordered Set Received (Lane= " << i
<< ")";
/// Dont forward the LFSR
/// Also the LFSR should not be forwarded for the entire SKP ordered set
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
if(!ingr_xtracted_byte_c
[pkt_cnt
-1])
word_val
= ingr_xtracted_byte
[pkt_cnt
-1].get_word(0);
ingr_xtracted_byte
[pkt_cnt
-1] = descrambler_i
->scramble_descramble(word_val
,0,0,i
);
if(ingr_xtracted_byte
[pkt_cnt
-1] == 0x00)
descrambler_i
->set_lfsr(descramble_lfsr
[i
],i
);
if(reset_lfsr_counter
== LINK_WIDTH
)
if(idl_count
== 8) /// An IDLE Frame
descrambler_i
->scramble_descramble_all(K28_5
,0,1);
com_detected
= true; /// Could be the start of an ordered set
descrambler_i
->scramble_descramble_all(SKP
,0,1);
else if(!first_time_after_L0
) /// Dont forward the LFSR immediatly after coming out of the LTSSM control
for(int lane_num
= 0; lane_num
< LINK_WIDTH
; lane_num
++){
word_val
= ingr_xtracted_byte
[(pkt_cnt
-1)-(LINK_WIDTH
-1-lane_num
)].get_word(0);
if(ingr_xtracted_byte_c
[(pkt_cnt
-1)-(LINK_WIDTH
-1-lane_num
)])
descrambler_i
->scramble_descramble(word_val
,0,1,lane_num
);
descrambler_i
->scramble_descramble(word_val
,0,0,lane_num
);
if(first_time_after_L0
) first_time_after_L0
= false;
for(int lane_scram
= 0; lane_scram
< LINK_WIDTH
; lane_scram
++)
descrambler_i
->start_scramble_reg
[lane_scram
] = false;
/// pkt_cnt is always a multiple of LINK_WIDTH
/// the END might be encountered at a boundary of LINK_WIDTH or somewhere in between
first_time_after_L0
= true;
/// Checks for LINK_WIDTH byte DLLP or IDL interleaved TLP or back to back TLP
for(i
=0;i
<LINK_WIDTH
;i
++)
/// This lane has STP/SDP
if(this_frame_start_detected
&& this_frame_end_detected
) /// Test for Back to Back packets without interleaving
if(lane_with_start
> lane_with_end
)
if(!start_ingr_pkt
&& rcv_error
==RE_NONE
)
this_frame_start_detected
= false;
this_frame_end_detected
= false;
/// If it comes out of this loop, it means it received an END/EDB symbol
/// Its fair to assume that a start must have come
/// Now just form the packets
ingress_packet
= new pciePacket(this_pkt_size
);
for(i
=0;i
<this_pkt_size
;i
++)
ingress_packet
->modify_byte(i
,ingr_xtracted_byte
[i
]);
global_ingress_packet
= ingress_packet
;
/// Notify the producer that the packet has been produced
/// Before I reset everything to 0 I need to check for back2back
for(i
=this_pkt_size
,j
=0;i
<pkt_cnt
;i
++,j
++)
ingr_xtracted_byte
[j
] = ingr_xtracted_byte
[i
]; /// Prepare for the next packet
ingr_xtracted_byte_c
[j
] = ingr_xtracted_byte_c
[i
];
/// The Producer code now begins
send_packet
= global_ingress_packet
;
if(send_packet
->get_size() != 0)
send_packet
->set_control(DLLP_ACK
);
send_packet
->set_control(DLLP_NAK_FRAMING
);
send_packet
->set_control(DLLP_NAK
);
pl_dll_out
.send_packet(send_packet
);
LOG_DEBUG
<< "PL_TOP: Resetting rcv_error to RE_NONE";