Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / model / pcie / dll / replay_buffer.cpp
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: replay_buffer.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#ifndef DLL_replay_buffer_h
36#define DLL_replay_buffer_h
37
38#include "dll_top.hpp"
39
40
41namespace pcie {
42
43 /** This function adds packets to the replay buffer **/
44 void dll_top::buffer_add( RefPciePacket packet){
45
46 replay_buffer.push(packet);
47 if ( packet->get_size() < replay_buffer_size )
48 replay_buffer_size-=packet->get_size();
49 else
50 replay_buffer_size=0;
51
52 LOG_DEBUG << "REPLAY_BUFFER: Added packet " << packet->getPacketId() << ". Current replay buffer size:" << replay_buffer_size ;
53 }
54
55 /** This function removes elements from the replay buffer **/
56 //void dll_top::buffer_remove( RefPciePacket packet){
57 void dll_top::buffer_remove(sc_uint<12> seq_num){
58 if(in_replay_buffer(seq_num)){
59 sc_uint<12> rx_pkt_seq_num;
60 sc_uint<8> byte_seq_num;
61 USE_NAMESPACE(std)queue<RefPciePacket> tmp_replay_buffer2;
62 RefPciePacket list_packet;
63 bool acked=true;
64 while(!replay_buffer.empty()){
65 list_packet = replay_buffer.front();
66 replay_buffer.pop();
67
68 byte_seq_num= list_packet->get_byte(1);
69 rx_pkt_seq_num.range(11,8)=byte_seq_num.range(3,0);
70 byte_seq_num= list_packet->get_byte(2);
71 rx_pkt_seq_num.range(7,0)=byte_seq_num.range(7,0);
72
73 if(seq_num==rx_pkt_seq_num)
74 {
75 //replay_buffer_size+= packet->get_size();
76 LOG_DEBUG << "REPLAY_BUFFER: 1removed " << rx_pkt_seq_num;
77 acked=false;
78 }
79 else if(!acked){
80 tmp_replay_buffer2.push(list_packet);
81 }
82 else{
83 //replay_buffer_size+= packet->get_size();
84 LOG_DEBUG << "REPLAY_BUFFER: 2removed " << rx_pkt_seq_num;
85 }
86 }// while
87 replay_buffer = tmp_replay_buffer2;
88 }
89 }
90
91 /** This function replays all entries in the buffer **/
92 void dll_top::buffer_replay(sc_uint<12> seq_num){
93 dll_pl_tlp_out.purge_channel();
94 if(REPLAY_NUM==3){
95 LOG_WARNING << "DLL: REPLAY_BUFFER: REPLAY_NUM ROLLOVER. Need to Retrain Link..." ;
96 //notify an event
97 //Setting retrain bit in Link Ctrl CSR
98 sc_uint<64> lnk_ctrl_reg = csr_port.read_csr(PEU_CSR_A_LNK_CTL_HW_ADDR);
99 lnk_ctrl_reg(5,5)=1;
100 csr_port.write_csr(PEU_CSR_A_LNK_CTL_HW_ADDR,lnk_ctrl_reg);
101 dll_pl_tlp_out.purge_channel();
102 }
103 REPLAY_NUM++;
104 REPLAY_TIMER=0;
105
106 if(seq_num>ACKD_SEQ){
107 LOG_DEBUG<<"Fwd progress in seq num ack";
108 REPLAY_NUM=0;
109 }
110
111 sc_uint<12> rx_pkt_seq_num;
112 sc_uint<8> byte_seq_num;
113 RefPciePacket list_packet;
114 USE_NAMESPACE(std)queue<RefPciePacket> tmp_replay_buffer2;
115
116 if(in_replay_buffer(seq_num)){
117 bool replay = false;
118 while (!replay_buffer.empty())
119 {
120 // get packet from replay buffer
121 list_packet = replay_buffer.front();
122 replay_buffer.pop();
123 //Extract seq num
124 byte_seq_num = list_packet->get_byte(1);
125 rx_pkt_seq_num.range(11,8) = byte_seq_num.range(3,0);
126 byte_seq_num = list_packet->get_byte(2);
127 rx_pkt_seq_num.range(7,0) = byte_seq_num.range(7,0);
128 if(rx_pkt_seq_num==seq_num){
129 replay=true;
130 }
131 else if(replay){
132 LOG_DEBUG << "REPLAY_BUFFER: Replay packet " << rx_pkt_seq_num ;
133 // send packet to pl to be retried
134 dll_pl_tlp_out.send_packet(list_packet);
135 // copy packet to tmp list
136 tmp_replay_buffer2.push(list_packet);
137 }
138 }// while
139 replay_buffer = tmp_replay_buffer2;
140 }
141 else{
142 LOG_DEBUG << "REPLAY_BUFFER: TLP not found. Replaying entire replay buffer..." ;
143 //A NAK for a TLP not in the replay buffer
144 //The whole replay buffer has to be replayed...
145 while (!replay_buffer.empty())
146 {
147 // get packet from replay buffer
148 list_packet = replay_buffer.front();
149 replay_buffer.pop();
150 //Extract seq num
151 byte_seq_num = list_packet->get_byte(1);
152 rx_pkt_seq_num.range(11,8) = byte_seq_num.range(3,0);
153 byte_seq_num = list_packet->get_byte(2);
154 rx_pkt_seq_num.range(7,0) = byte_seq_num.range(7,0);
155 LOG_DEBUG << "REPLAY_BUFFER: Replay packet " << rx_pkt_seq_num ;
156 // send packet to pl to be retried
157 dll_pl_tlp_out.send_packet(list_packet);
158 // copy packet to tmp list
159 tmp_replay_buffer2.push(list_packet);
160 }// while
161 replay_buffer = tmp_replay_buffer2;
162 }
163 }
164
165 /** This function replays a single element from the replay buffer **/
166 void dll_top::buffer_replay_single( sc_uint<12> seq_id){
167 sc_uint<12> rx_pkt_seq_num;
168 sc_uint<8> byte_seq_num;
169
170 //RefPciePacket list_packet;
171 RefPciePacket list_packet;
172 USE_NAMESPACE(std)queue<RefPciePacket> tmp_replay_buffer2;
173
174 while ( !replay_buffer.empty() )
175 {
176 // get packet from replay buffer
177 list_packet = replay_buffer.front();
178 replay_buffer.pop();
179 // send packet to pl to be retried
180 byte_seq_num= list_packet->get_byte(1);
181 rx_pkt_seq_num.range(11,8)=byte_seq_num.range(3,0);
182 byte_seq_num= list_packet->get_byte(2);
183 rx_pkt_seq_num.range(7,0)=byte_seq_num.range(7,0);
184 if ( rx_pkt_seq_num == seq_id ) {
185 dll_pl_dllp_out.send_packet(list_packet);
186 LOG_DEBUG << "REPLAY_BUFFER: SINGLE Replay packet " << rx_pkt_seq_num ;
187 }
188 // copy packet to tmp list
189 tmp_replay_buffer2.push(list_packet);
190 }// while
191 replay_buffer = tmp_replay_buffer2;
192 }
193
194 bool dll_top::in_replay_buffer(sc_uint<12> seq_num)
195 {
196 bool is_in_buffer = false;
197 sc_uint<12> rx_pkt_seq_num;
198 sc_uint<8> byte_seq_num;
199
200 //RefPciePacket list_packet;
201 RefPciePacket list_packet;
202 USE_NAMESPACE(std)queue<RefPciePacket> tmp_replay_buffer2;
203 while (!replay_buffer.empty())
204 {
205 // get packet from replay buffer
206 list_packet = replay_buffer.front();
207 replay_buffer.pop();
208 //Extract seq num
209 byte_seq_num = list_packet->get_byte(1);
210 rx_pkt_seq_num.range(11,8) = byte_seq_num.range(3,0);
211 byte_seq_num = list_packet->get_byte(2);
212 rx_pkt_seq_num.range(7,0) = byte_seq_num.range(7,0);
213 if(rx_pkt_seq_num==seq_num){
214 is_in_buffer=true;
215 }
216 tmp_replay_buffer2.push(list_packet);
217 }// while
218 replay_buffer = tmp_replay_buffer2;
219
220 return is_in_buffer;
221 }
222
223}
224#endif