Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | #include "rsb.hpp" |
2 | #include "pcie_common/logger.hpp" | |
3 | ||
4 | namespace pcie{ | |
5 | ||
6 | /** | |
7 | * This method initializes module registers and flags. | |
8 | * It also spawns threads that handle module operation. | |
9 | */ | |
10 | void rsb::init(){ | |
11 | for(unsigned int i=0; i<NUM_RSB_ENTRIES ; i++){ | |
12 | rsb_db[i].vld=0; | |
13 | } | |
14 | POR_RESET=false; | |
15 | STOP_TIMER=false; | |
16 | eg_handler_ph = sc_spawn(sc_bind(&rsb::eg_handler,this)); | |
17 | update_timer_ph = sc_spawn(sc_bind(&rsb::update_timer,this)); | |
18 | LOG_INFO << "RSB: SW Reset : threads spawned"; | |
19 | } | |
20 | ||
21 | /** | |
22 | * This thread processes ingress TLP CMPL headers. Detected errors are flagged and reported. | |
23 | */ | |
24 | void rsb::ing_handler(){ | |
25 | RefPciePacket in_pkt; | |
26 | while(1){ | |
27 | try{ | |
28 | ing_port->get(in_pkt); | |
29 | LOG_DEBUG << "ITL->RSB: Get Packet: " << in_pkt->getPacketId() << "\n"; | |
30 | sc_uint<RSB_TAG_SIZE> rsb_tag = GET_TLP_CMPL_TAG(in_pkt).range(RSB_TAG_SIZE-1,0); | |
31 | ||
32 | rs2it_err = 0; //Reset error bits | |
33 | ||
34 | if(in_pkt->isCmpl()){ | |
35 | sc_uint<64> peu_diag_reg = csr_port.read_csr(PEU_CSR_A_TLU_DIAG_HW_ADDR); | |
36 | LOG_DEBUG << "PEU_DIAG_CSR: " << peu_diag_reg; | |
37 | ||
38 | if( (!rsb_db[rsb_tag].vld) || | |
39 | (GET_TLP_CMPL_REQ_ID(in_pkt)!=rsb_db[rsb_tag].req_id) || | |
40 | (in_pkt->get_byte(TLP_HDR_START) == tlp_CplLk) || | |
41 | (in_pkt->get_byte(TLP_HDR_START) == tlp_CplDLk) || | |
42 | (rsb_db[rsb_tag].vld && (rsb_db[rsb_tag].tlp_tag != GET_TLP_CMPL_TAG(in_pkt))) | |
43 | ){ | |
44 | //Check for Unsolicited CMPLs | |
45 | ||
46 | LOG_WARNING << "Warning: Unsolicited CMPLs " ; | |
47 | rs2it_err.range(3,3) = 1; | |
48 | ||
49 | } else if(in_pkt->hasData() && GET_TLP_CMPL_STATUS(in_pkt)!=0 && GET_TLP_CMPL_STATUS(in_pkt)!=0x2){ | |
50 | //Check for Malformed Completion///////////////////////////////// | |
51 | //1. CplD with unsuccessful status | |
52 | ||
53 | LOG_WARNING << "Warning: CplD with unsuccessful status." ; | |
54 | rs2it_err.range(2,2) = 1; | |
55 | ||
56 | } else if((peu_diag_reg.range(40,40)!=1) && //Error check is not disabled | |
57 | (GET_TLP_CMPL_STATUS(in_pkt)==0x2 && | |
58 | (rsb_db[rsb_tag].raw_payload[0] != tlp_CfgRd0 && | |
59 | rsb_db[rsb_tag].raw_payload[0] != tlp_CfgRd1 && | |
60 | rsb_db[rsb_tag].raw_payload[0] != tlp_CfgWr0 && | |
61 | rsb_db[rsb_tag].raw_payload[0] != tlp_CfgWr1 )) | |
62 | ) { | |
63 | //2. completion status is "configuration retry" for a non-configuration PIO request. | |
64 | ||
65 | LOG_WARNING << "Warning: completion status is configuration retry for a non-configuration PIO request." ; | |
66 | rs2it_err.range(2,2) = 1; | |
67 | ||
68 | } else if((in_pkt->get_byte(TLP_HDR_START) == tlp_CplD) && | |
69 | ((rsb_db[rsb_tag].raw_payload[0] == tlp_MWr_32) || | |
70 | (rsb_db[rsb_tag].raw_payload[0] == tlp_MWr_64) || | |
71 | (rsb_db[rsb_tag].raw_payload[0] == tlp_IOWr) || | |
72 | (rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr0) || | |
73 | (rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr1) ) | |
74 | ) { | |
75 | //3. CplD associates with a PIO write request. | |
76 | ||
77 | LOG_WARNING << "Warning: CplD associates with a PIO write request. " ; | |
78 | rs2it_err.range(2,2) = 1; | |
79 | ||
80 | } else if((in_pkt->get_byte(TLP_HDR_START) == tlp_Cpl) && | |
81 | ( GET_TLP_CMPL_STATUS(in_pkt) == 0) && | |
82 | ((rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_32) || | |
83 | (rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_64) || | |
84 | (rsb_db[rsb_tag].raw_payload[0] == tlp_IORd) || | |
85 | (rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd0) || | |
86 | (rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd1) ) | |
87 | ) { | |
88 | //4. Successful Cpl associates with a PIO read request. | |
89 | ||
90 | LOG_WARNING << "Warning: Successful Cpl associates with a PIO read request." ; | |
91 | rs2it_err.range(2,2) = 1; | |
92 | ||
93 | } else if((GET_TLP_ATTR(in_pkt)!=0 && peu_diag_reg.range(42,42)!=1) || (GET_TLP_TC(in_pkt)!=0 && peu_diag_reg.range(41,41)!=1)) { | |
94 | //5. Hdr field mis-match: (i) TC!=0. (ii) Attr!=0 | |
95 | LOG_WARNING << "Warning: Incorrect (non-zero) Attr/TC fields. Attr: " << GET_TLP_ATTR(in_pkt) << " TC: " << GET_TLP_TC(in_pkt) ; | |
96 | rs2it_err.range(2,2) = 1; | |
97 | ||
98 | } else if( in_pkt->get_byte(TLP_HDR_START) == tlp_CplD && | |
99 | (GET_TLP_LEN(in_pkt) != (rsb_db[rsb_tag].raw_payload[2].range(1,0),rsb_db[rsb_tag].raw_payload[3])) | |
100 | ){ | |
101 | // (iii) length for CplD | |
102 | ||
103 | LOG_WARNING << "Warning: length for CplD" ; | |
104 | rs2it_err.range(2,2) = 1; | |
105 | ||
106 | } else if( (peu_diag_reg.range(43,43)!=1) && //Error check is not disabled | |
107 | (((rsb_db[rsb_tag].raw_payload[0] == tlp_IORd || rsb_db[rsb_tag].raw_payload[0] == tlp_IOWr || | |
108 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd0 || //if IO/Cfg Rd/Wr, byteCount==4 | |
109 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr0 || rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd1 || | |
110 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr1 ) && (GET_TLP_BYTEC(in_pkt)!=0x4) ) || | |
111 | ||
112 | ((rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_32 || rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_64) && | |
113 | (GET_TLP_BYTEC(in_pkt) != rsb_db[rsb_tag].expect_bc) ) | |
114 | ) | |
115 | ) { | |
116 | // (iv) Byte Count (it should be 12?h4 in Cpl/CplD resulted from PIO io/cfg rd/wr requests) | |
117 | ||
118 | LOG_WARNING << "Warning: Byte Count (it should be 12?h4 in Cpl/CplD resulted from PIO io/cfg rd/wr requests). ByteCnt= " << GET_TLP_BYTEC(in_pkt) ; | |
119 | rs2it_err.range(2,2) = 1; | |
120 | ||
121 | } else if( (peu_diag_reg.range(44,44)!=1) && //Error check is not disabled | |
122 | (((rsb_db[rsb_tag].raw_payload[0] == tlp_IORd || rsb_db[rsb_tag].raw_payload[0] == tlp_IOWr || | |
123 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd0 || //if IO/Cfg Rd/Wr, lowAddr==0 | |
124 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr0 || rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd1 || | |
125 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr1 ) && (GET_TLP_CMPL_LADDR(in_pkt)!=0) ) || | |
126 | ||
127 | ((rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_32 || rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_64) && | |
128 | (GET_TLP_CMPL_LADDR(in_pkt) != rsb_db[rsb_tag].expect_la) ) | |
129 | ) | |
130 | ) { | |
131 | // (v) Lower Address (it should be 7?b0 in Cpl/CplD resulted from PIO io/cfg rd/wr requests) | |
132 | ||
133 | LOG_WARNING << "Warning: Lower Address (it should be 7?b0 in Cpl/CplD resulted from PIO io/cfg rd/wr requests). LowAddr= " << GET_TLP_CMPL_LADDR(in_pkt) ; | |
134 | rs2it_err.range(2,2) = 1; | |
135 | ||
136 | ////////////////////////////////////////////////////////////////// | |
137 | } else if( GET_TLP_CMPL_STATUS(in_pkt)==0x2 && | |
138 | (rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd0 || | |
139 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd1 || | |
140 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr0 || | |
141 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr1 ) | |
142 | ){ | |
143 | LOG_WARNING << "Configuration retry error - completion status in Cpl header is configuration retry for a configuration PIO request." ; | |
144 | rs2it_err.range(1,1) = 1; | |
145 | } else if( (peu_diag_reg.range(40,40)==1) && | |
146 | GET_TLP_CMPL_STATUS(in_pkt)!=0x0 && | |
147 | (rsb_db[rsb_tag].raw_payload[0] == tlp_IORd || | |
148 | rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_32 || | |
149 | rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_64 || | |
150 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd0 || | |
151 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd1 ) | |
152 | ){ | |
153 | LOG_WARNING << "Unsuccessful read error - completion resulted from PIO read request, whose status in Cpl header is not successful completion" ; | |
154 | rs2it_err.range(4,4) = 1; | |
155 | rsb_db[rsb_tag].vld=false; | |
156 | } else if( (peu_diag_reg.range(40,40)==1) && | |
157 | GET_TLP_CMPL_STATUS(in_pkt)!=0x0 && | |
158 | (rsb_db[rsb_tag].raw_payload[0] == tlp_IOWr || | |
159 | rsb_db[rsb_tag].raw_payload[0] == tlp_MWr_32 || | |
160 | rsb_db[rsb_tag].raw_payload[0] == tlp_MWr_64 || | |
161 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr0 || | |
162 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr1 ) | |
163 | ){ | |
164 | LOG_WARNING << "Unsuccessful write error - completion resulted from PIO write request, whose status in Cpl header is not successful completion" ; | |
165 | rs2it_err.range(5,5) = 1; | |
166 | rsb_db[rsb_tag].vld=false; | |
167 | } else if( GET_TLP_CMPL_STATUS(in_pkt)==0x4 && | |
168 | (rsb_db[rsb_tag].raw_payload[0] == tlp_IORd || | |
169 | rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_32 || | |
170 | rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_64 || | |
171 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd0 || | |
172 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd1 ) | |
173 | ){ | |
174 | LOG_WARNING << "Rd CMPL with Completer Abort Status set" ; | |
175 | rs2it_err.range(4,4) = 1; | |
176 | } else if( GET_TLP_CMPL_STATUS(in_pkt)==0x4 && | |
177 | (rsb_db[rsb_tag].raw_payload[0] == tlp_IOWr || | |
178 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr0 || | |
179 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr1 ) | |
180 | ){ | |
181 | LOG_WARNING << "Wr CMPL with Completer Abort Status set" ; | |
182 | rs2it_err.range(5,5) = 1; | |
183 | ||
184 | } else if(((GET_TLP_CMPL_STATUS(in_pkt)==0x1) || //CMPL Status is UR | |
185 | (GET_TLP_CMPL_STATUS(in_pkt)!=0x0 && GET_TLP_CMPL_STATUS(in_pkt)!=0x1 && //or CMPL Status is a reserved value | |
186 | GET_TLP_CMPL_STATUS(in_pkt)!=0x2 && GET_TLP_CMPL_STATUS(in_pkt)!=0x4)) && | |
187 | (rsb_db[rsb_tag].raw_payload[0] == tlp_IOWr || | |
188 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr0 || | |
189 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgWr1 ) | |
190 | ){ | |
191 | LOG_WARNING << "IO/CfgWr with UR status" ; | |
192 | rs2it_err.range(5,5) = 1; | |
193 | } else if( ((GET_TLP_CMPL_STATUS(in_pkt)==0x1) || //CMPL Status is UR | |
194 | (GET_TLP_CMPL_STATUS(in_pkt)!=0x0 && GET_TLP_CMPL_STATUS(in_pkt)!=0x1 && //or CMPL Status is a reserved value | |
195 | GET_TLP_CMPL_STATUS(in_pkt)!=0x2 && GET_TLP_CMPL_STATUS(in_pkt)!=0x4)) && | |
196 | (rsb_db[rsb_tag].raw_payload[0] == tlp_IORd || | |
197 | rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_32 || | |
198 | rsb_db[rsb_tag].raw_payload[0] == tlp_MRd_64 || | |
199 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd0 || | |
200 | rsb_db[rsb_tag].raw_payload[0] == tlp_CfgRd1 ) | |
201 | ){ | |
202 | LOG_WARNING << "Rd CMPL with UR Status set" ; | |
203 | rs2it_err.range(4,4) = 1; | |
204 | ||
205 | } else { | |
206 | rsb_db[rsb_tag].vld=false; | |
207 | } | |
208 | ///////////////////////////////////////////////////////////////// | |
209 | if(rs2it_err==0) | |
210 | ing_port->put(false); | |
211 | else { | |
212 | if(rs2it_err.range(4,4)==1 || rs2it_err.range(5,5)==1) | |
213 | ing_port->put(false); | |
214 | else | |
215 | ing_port->put(true); | |
216 | ||
217 | //CSR Error Bit and Header Log updates | |
218 | //Error Bits | |
219 | sc_uint<64> peu_oes_clr_reg; //PEU Other Event Error Clr Status Reg | |
220 | sc_uint<64> peu_ues_clr_reg; //PEU Uncorrectable Error Clr Status Reg | |
221 | if(rs2it_err.range(2,2)==1){ | |
222 | write_error_csr(OE,22,54,"mfc"); | |
223 | } | |
224 | if(rs2it_err.range(1,1)==1){ | |
225 | write_error_csr(OE,15,47,"crs"); | |
226 | } | |
227 | if(rs2it_err.range(4,4)==1){ | |
228 | write_error_csr(OE,16,48,"ruc"); | |
229 | } | |
230 | if(rs2it_err.range(5,5)==1){ | |
231 | write_error_csr(OE,17,49,"wuc"); | |
232 | } | |
233 | ||
234 | if(rs2it_err.range(3,3)==1 ){ | |
235 | write_error_csr(UE,16,48,"uc"); | |
236 | ||
237 | sc_uint<64> peu_rcv_ueh1_log_reg; //PEU Recv Other Event Header1 Log Register | |
238 | sc_uint<64> peu_rcv_ueh2_log_reg; //PEU Recv Other Event Header2 Log Register | |
239 | peu_rcv_ueh1_log_reg(63,56) = in_pkt->get_byte(TLP_HDR_START+ 0); | |
240 | peu_rcv_ueh1_log_reg(55,48) = in_pkt->get_byte(TLP_HDR_START+ 1); | |
241 | peu_rcv_ueh1_log_reg(47,40) = in_pkt->get_byte(TLP_HDR_START+ 2); | |
242 | peu_rcv_ueh1_log_reg(39,32) = in_pkt->get_byte(TLP_HDR_START+ 3); | |
243 | peu_rcv_ueh1_log_reg(31,24) = in_pkt->get_byte(TLP_HDR_START+ 4); | |
244 | peu_rcv_ueh1_log_reg(23,16) = in_pkt->get_byte(TLP_HDR_START+ 5); | |
245 | peu_rcv_ueh1_log_reg(15, 8) = in_pkt->get_byte(TLP_HDR_START+ 6); | |
246 | peu_rcv_ueh1_log_reg( 7, 0) = in_pkt->get_byte(TLP_HDR_START+ 7); | |
247 | ||
248 | peu_rcv_ueh2_log_reg(63,56) = in_pkt->get_byte(TLP_HDR_START+ 8); | |
249 | peu_rcv_ueh2_log_reg(55,48) = in_pkt->get_byte(TLP_HDR_START+ 9); | |
250 | peu_rcv_ueh2_log_reg(47,40) = in_pkt->get_byte(TLP_HDR_START+10); | |
251 | peu_rcv_ueh2_log_reg(39,32) = in_pkt->get_byte(TLP_HDR_START+11); | |
252 | if(GET_TLP_FMT(in_pkt) == 1 || GET_TLP_FMT(in_pkt) == 3) | |
253 | { | |
254 | peu_rcv_ueh2_log_reg(31,24) = in_pkt->get_byte(TLP_HDR_START+12); | |
255 | peu_rcv_ueh2_log_reg(23,16) = in_pkt->get_byte(TLP_HDR_START+13); | |
256 | peu_rcv_ueh2_log_reg(15, 8) = in_pkt->get_byte(TLP_HDR_START+14); | |
257 | peu_rcv_ueh2_log_reg( 7, 0) = in_pkt->get_byte(TLP_HDR_START+15); | |
258 | } | |
259 | LOG_INFO << "RUEH1: " << peu_rcv_ueh1_log_reg ; | |
260 | LOG_INFO << "RUEH2: " << peu_rcv_ueh2_log_reg ; | |
261 | csr_port.write_csr(PEU_CSR_A_RUE_HDR1_HW_ADDR,peu_rcv_ueh1_log_reg); | |
262 | csr_port.write_csr(PEU_CSR_A_RUE_HDR2_HW_ADDR,peu_rcv_ueh2_log_reg); | |
263 | } | |
264 | ||
265 | //Log Header | |
266 | if(rs2it_err.range(2,2)==1 || rs2it_err.range(1,1)==1 || rs2it_err.range(4,4)==1 || rs2it_err.range(5,5)==1){ | |
267 | sc_uint<64> peu_rcv_oeh1_log_reg; //PEU Recv Other Event Header1 Log Register | |
268 | sc_uint<64> peu_rcv_oeh2_log_reg; //PEU Recv Other Event Header2 Log Register | |
269 | peu_rcv_oeh1_log_reg(63,56) = in_pkt->get_byte(TLP_HDR_START+ 0); | |
270 | peu_rcv_oeh1_log_reg(55,48) = in_pkt->get_byte(TLP_HDR_START+ 1); | |
271 | peu_rcv_oeh1_log_reg(47,40) = in_pkt->get_byte(TLP_HDR_START+ 2); | |
272 | peu_rcv_oeh1_log_reg(39,32) = in_pkt->get_byte(TLP_HDR_START+ 3); | |
273 | peu_rcv_oeh1_log_reg(31,24) = in_pkt->get_byte(TLP_HDR_START+ 4); | |
274 | peu_rcv_oeh1_log_reg(23,16) = in_pkt->get_byte(TLP_HDR_START+ 5); | |
275 | peu_rcv_oeh1_log_reg(15, 8) = in_pkt->get_byte(TLP_HDR_START+ 6); | |
276 | peu_rcv_oeh1_log_reg( 7, 0) = in_pkt->get_byte(TLP_HDR_START+ 7); | |
277 | ||
278 | peu_rcv_oeh2_log_reg(63,56) = in_pkt->get_byte(TLP_HDR_START+ 8); | |
279 | peu_rcv_oeh2_log_reg(55,48) = in_pkt->get_byte(TLP_HDR_START+ 9); | |
280 | peu_rcv_oeh2_log_reg(47,40) = in_pkt->get_byte(TLP_HDR_START+10); | |
281 | peu_rcv_oeh2_log_reg(39,32) = in_pkt->get_byte(TLP_HDR_START+11); | |
282 | if(GET_TLP_FMT(in_pkt) == 1 || GET_TLP_FMT(in_pkt) == 3) | |
283 | { | |
284 | peu_rcv_oeh2_log_reg(31,24) = in_pkt->get_byte(TLP_HDR_START+12); | |
285 | peu_rcv_oeh2_log_reg(23,16) = in_pkt->get_byte(TLP_HDR_START+13); | |
286 | peu_rcv_oeh2_log_reg(15, 8) = in_pkt->get_byte(TLP_HDR_START+14); | |
287 | peu_rcv_oeh2_log_reg( 7, 0) = in_pkt->get_byte(TLP_HDR_START+15); | |
288 | } | |
289 | LOG_INFO << "ROEH1: " << peu_rcv_oeh1_log_reg ; | |
290 | LOG_INFO << "ROEH2: " << peu_rcv_oeh2_log_reg ; | |
291 | csr_port.write_csr(PEU_CSR_A_ROE_HDR1_HW_ADDR,peu_rcv_oeh1_log_reg); | |
292 | csr_port.write_csr(PEU_CSR_A_ROE_HDR2_HW_ADDR,peu_rcv_oeh2_log_reg); | |
293 | ||
294 | ||
295 | sc_uint<RSB_TAG_SIZE> tlp_tag = GET_TLP_CMPL_TAG(in_pkt).range(RSB_TAG_SIZE-1,0); | |
296 | sc_uint<64> peu_xmt_oeh1_log_reg; //PEU Xmit Other Event Header1 Log Register | |
297 | sc_uint<64> peu_xmt_oeh2_log_reg; //PEU Xmit Other Event Header2 Log Register | |
298 | peu_xmt_oeh1_log_reg(63,56) = rsb_db[tlp_tag].raw_payload[0]; | |
299 | peu_xmt_oeh1_log_reg(55,48) = rsb_db[tlp_tag].raw_payload[1]; | |
300 | peu_xmt_oeh1_log_reg(47,40) = rsb_db[tlp_tag].raw_payload[2]; | |
301 | peu_xmt_oeh1_log_reg(39,32) = rsb_db[tlp_tag].raw_payload[3]; | |
302 | peu_xmt_oeh1_log_reg(31,24) = rsb_db[tlp_tag].raw_payload[4]; | |
303 | peu_xmt_oeh1_log_reg(23,16) = rsb_db[tlp_tag].raw_payload[5]; | |
304 | peu_xmt_oeh1_log_reg(15, 8) = rsb_db[tlp_tag].raw_payload[6]; | |
305 | peu_xmt_oeh1_log_reg( 7, 0) = rsb_db[tlp_tag].raw_payload[7]; | |
306 | ||
307 | peu_xmt_oeh2_log_reg(63,56) = rsb_db[tlp_tag].raw_payload[8]; | |
308 | peu_xmt_oeh2_log_reg(55,48) = rsb_db[tlp_tag].raw_payload[9]; | |
309 | peu_xmt_oeh2_log_reg(47,40) = rsb_db[tlp_tag].raw_payload[10]; | |
310 | peu_xmt_oeh2_log_reg(39,32) = rsb_db[tlp_tag].raw_payload[11]; | |
311 | peu_xmt_oeh2_log_reg(31,24) = rsb_db[tlp_tag].raw_payload[12]; | |
312 | peu_xmt_oeh2_log_reg(23,16) = rsb_db[tlp_tag].raw_payload[13]; | |
313 | peu_xmt_oeh2_log_reg(15, 8) = rsb_db[tlp_tag].raw_payload[14]; | |
314 | peu_xmt_oeh2_log_reg( 7, 0) = rsb_db[tlp_tag].raw_payload[15]; | |
315 | LOG_INFO << "TOEH1: " << peu_xmt_oeh1_log_reg ; | |
316 | LOG_INFO << "TOEH2: " << peu_xmt_oeh2_log_reg ; | |
317 | csr_port.write_csr(PEU_CSR_A_TOE_HDR1_HW_ADDR,peu_xmt_oeh1_log_reg); | |
318 | csr_port.write_csr(PEU_CSR_A_TOE_HDR2_HW_ADDR,peu_xmt_oeh2_log_reg); | |
319 | } | |
320 | if(rs2it_err.range(2,2)==1 || rs2it_err.range(1,1)==1) | |
321 | cto_req_port->put(GET_TLP_CMPL_TAG(in_pkt).range(CTO_TAG_SIZE-1,0)); | |
322 | } | |
323 | } | |
324 | else | |
325 | LOG_WARNING << "Warning: RSB has received a non-CMPL for processing." ; | |
326 | } | |
327 | catch(sc_exception &e){ | |
328 | LOG_WARNING<<"RSB: ing_handler exception...remaining in the thread"; | |
329 | } | |
330 | }//end while(1) | |
331 | } //ing_handler() | |
332 | ||
333 | /** | |
334 | * This thread receives out-going TLP requests and populates the RSB for check on the ingress side. | |
335 | */ | |
336 | void rsb::eg_handler(){ | |
337 | LOG_INFO << "RSB: eg_handler begins..."; | |
338 | RefPciePacket in_pkt; | |
339 | try{ | |
340 | while(1){ | |
341 | eg_port.get_packet(in_pkt); | |
342 | LOG_DEBUG << "ETL->RSB: In_pkt: " << in_pkt->to_string(); | |
343 | ||
344 | sc_uint<RSB_TAG_SIZE> rsb_tag = GET_TLP_REQ_TAG(in_pkt).range(RSB_TAG_SIZE-1,0); | |
345 | ||
346 | if(rsb_db[rsb_tag].vld) | |
347 | LOG_WARNING << "\tWarning: RSB already has a valid entry at location: " << rsb_tag ; | |
348 | ||
349 | rsb_db[rsb_tag].vld = 1; | |
350 | rsb_db[rsb_tag].raw_payload.resize((in_pkt->get_pkt_size())-TLP_HDR_START); | |
351 | for(unsigned int i=0; i<(rsb_db[rsb_tag].raw_payload.size()) ; i++){ | |
352 | rsb_db[rsb_tag].raw_payload[i]=in_pkt->get_byte(TLP_HDR_START+i); | |
353 | } | |
354 | rsb_db[rsb_tag].tlp_tag = GET_TLP_REQ_TAG(in_pkt).range(CTO_TAG_SIZE-1,0); | |
355 | rsb_db[rsb_tag].timeout = get_Cpl_TO(); | |
356 | if(rsb_db[rsb_tag].timeout == SC_ZERO_TIME) rsb_db[rsb_tag].infTO = true; | |
357 | else rsb_db[rsb_tag].infTO = false; | |
358 | ||
359 | rsb_db[rsb_tag].req_id = GET_TLP_REQ_ID(in_pkt); | |
360 | ||
361 | sc_uint<4> becount = 0; | |
362 | sc_uint<8> benable = 0; | |
363 | benable=GET_TLP_BE(in_pkt); | |
364 | if(benable!=0){ | |
365 | if(benable.range(7,4)==0){ | |
366 | if(benable.range(3,0) == 1 || benable.range(3,0) == 2 || benable.range(3,0) == 4 || benable.range(3,0) == 8){ | |
367 | rsb_db[rsb_tag].expect_bc = 1; | |
368 | } else if(benable.range(3,0) == 3 || benable.range(3,0) == 6 || benable.range(3,0) == 12){ | |
369 | rsb_db[rsb_tag].expect_bc = 2; | |
370 | } else if(benable.range(0,0) == 1 && benable.range(3,3)==1 ){ | |
371 | rsb_db[rsb_tag].expect_bc = 4; | |
372 | } else { | |
373 | rsb_db[rsb_tag].expect_bc = 3; | |
374 | } | |
375 | unsigned int index = 0; | |
376 | while(benable.range(index,index)!=1 && index<4) {becount++; index++;} | |
377 | rsb_db[rsb_tag].expect_la.range(1,0) = becount; | |
378 | } else { | |
379 | unsigned int index = 0; | |
380 | while(benable.range(index,index)!=1 && index<4) {becount++; index++;} | |
381 | rsb_db[rsb_tag].expect_la.range(1,0) = becount; | |
382 | if(GET_TLP_LEN(in_pkt)!=1){ | |
383 | index=7; | |
384 | while(benable.range(index,index)!=1 && index>3) {becount++; index--;} | |
385 | } | |
386 | rsb_db[rsb_tag].expect_bc = GET_TLP_LEN(in_pkt)*4 - becount; | |
387 | } | |
388 | } else { | |
389 | rsb_db[rsb_tag].expect_bc = 1; | |
390 | rsb_db[rsb_tag].expect_la.range(1,0) = 0; | |
391 | } | |
392 | if(GET_TLP_FMT(in_pkt)==1 || GET_TLP_FMT(in_pkt)==3){ | |
393 | rsb_db[rsb_tag].expect_la.range(6,2) = in_pkt->get_byte(TLP_HDR_START+15)(6,2); | |
394 | } else | |
395 | rsb_db[rsb_tag].expect_la.range(6,2) = in_pkt->get_byte(TLP_HDR_START+11)(6,2); | |
396 | } //end while() | |
397 | } | |
398 | catch(sc_exception &e){ | |
399 | LOG_WARNING<<"RSB: Out of eg_handler"; | |
400 | } | |
401 | } //eg_handler() | |
402 | ||
403 | /** | |
404 | * This thread updates the RSB timer and checks for CMPL timeout. | |
405 | * A detected timeout is reported to the ILU interface. | |
406 | */ | |
407 | void rsb::update_timer(){ | |
408 | LOG_INFO << "RSB: update_timer begins..." ; | |
409 | sc_uint<RSB_TAG_SIZE> rsb_ctr = 0; | |
410 | try{ | |
411 | while(1){ | |
412 | WAIT(rsb_clk.posedge_event()); | |
413 | WAIT(rsb_clk.posedge_event()); | |
414 | WAIT(rsb_clk.posedge_event()); | |
415 | WAIT(rsb_clk.posedge_event()); | |
416 | if(!STOP_TIMER && rsb_db[rsb_ctr].vld){ | |
417 | if(!rsb_db[rsb_ctr].infTO) | |
418 | ||
419 | if((sc_time_stamp()) >= rsb_db[rsb_ctr].timeout){ | |
420 | sc_uint<64> peu_csr_ue_log_enable = csr_port.read_csr(PEU_CSR_A_UE_LOG_HW_ADDR); | |
421 | sc_uint<64> peu_csr_oe_log_enable = csr_port.read_csr(PEU_CSR_A_OE_LOG_HW_ADDR); | |
422 | ||
423 | LOG_WARNING << "RSB: Warning: CMPL Timeout for tag " << rsb_db[rsb_ctr].tlp_tag ; | |
424 | LOG_WARNING << "RSB: CTO ENABLED..." ; | |
425 | cto_req_port->put((rsb_db[rsb_ctr].tlp_tag)); | |
426 | rsb_db[rsb_ctr].vld = false; | |
427 | ||
428 | if(peu_csr_ue_log_enable.range(14,14)==1 && peu_csr_oe_log_enable.range(21,21)==1){ | |
429 | ||
430 | write_error_csr(UE,14,46,"cto"); | |
431 | ||
432 | sc_uint<64> peu_ueh1_log_reg; //PEU Uncorrectable Error Header1 Log Register | |
433 | sc_uint<64> peu_ueh2_log_reg; //PEU Uncorrectable Error Header2 Log Register | |
434 | peu_ueh1_log_reg(63,56) = rsb_db[rsb_ctr].raw_payload[0]; | |
435 | peu_ueh1_log_reg(55,48) = rsb_db[rsb_ctr].raw_payload[1]; | |
436 | peu_ueh1_log_reg(47,40) = rsb_db[rsb_ctr].raw_payload[2]; | |
437 | peu_ueh1_log_reg(39,32) = rsb_db[rsb_ctr].raw_payload[3]; | |
438 | peu_ueh1_log_reg(31,24) = rsb_db[rsb_ctr].raw_payload[4]; | |
439 | peu_ueh1_log_reg(23,16) = rsb_db[rsb_ctr].raw_payload[5]; | |
440 | peu_ueh1_log_reg(15, 8) = rsb_db[rsb_ctr].raw_payload[6]; | |
441 | peu_ueh1_log_reg( 7, 0) = rsb_db[rsb_ctr].raw_payload[7]; | |
442 | ||
443 | peu_ueh2_log_reg(63,56) = rsb_db[rsb_ctr].raw_payload[8]; | |
444 | peu_ueh2_log_reg(55,48) = rsb_db[rsb_ctr].raw_payload[9]; | |
445 | peu_ueh2_log_reg(47,40) = rsb_db[rsb_ctr].raw_payload[10]; | |
446 | peu_ueh2_log_reg(39,32) = rsb_db[rsb_ctr].raw_payload[11]; | |
447 | peu_ueh2_log_reg(31,24) = rsb_db[rsb_ctr].raw_payload[12]; | |
448 | peu_ueh2_log_reg(23,16) = rsb_db[rsb_ctr].raw_payload[13]; | |
449 | peu_ueh2_log_reg(15, 8) = rsb_db[rsb_ctr].raw_payload[14]; | |
450 | peu_ueh2_log_reg( 7, 0) = rsb_db[rsb_ctr].raw_payload[15]; | |
451 | LOG_INFO << "TUEH1: " << peu_ueh1_log_reg ; | |
452 | LOG_INFO << "TUEH2: " << peu_ueh2_log_reg ; | |
453 | csr_port.write_csr(PEU_CSR_A_TUE_HDR1_HW_ADDR,peu_ueh1_log_reg); | |
454 | csr_port.write_csr(PEU_CSR_A_TUE_HDR2_HW_ADDR,peu_ueh2_log_reg); | |
455 | ||
456 | write_error_csr(OE,21,53,"cto"); | |
457 | ||
458 | sc_uint<64> peu_xmt_oeh1_log_reg; //PEU Xmit Other Event Header1 Log Register | |
459 | sc_uint<64> peu_xmt_oeh2_log_reg; //PEU Xmit Other Event Header2 Log Register | |
460 | peu_xmt_oeh1_log_reg(63,56) = rsb_db[rsb_ctr].raw_payload[0]; | |
461 | peu_xmt_oeh1_log_reg(55,48) = rsb_db[rsb_ctr].raw_payload[1]; | |
462 | peu_xmt_oeh1_log_reg(47,40) = rsb_db[rsb_ctr].raw_payload[2]; | |
463 | peu_xmt_oeh1_log_reg(39,32) = rsb_db[rsb_ctr].raw_payload[3]; | |
464 | peu_xmt_oeh1_log_reg(31,24) = rsb_db[rsb_ctr].raw_payload[4]; | |
465 | peu_xmt_oeh1_log_reg(23,16) = rsb_db[rsb_ctr].raw_payload[5]; | |
466 | peu_xmt_oeh1_log_reg(15, 8) = rsb_db[rsb_ctr].raw_payload[6]; | |
467 | peu_xmt_oeh1_log_reg( 7, 0) = rsb_db[rsb_ctr].raw_payload[7]; | |
468 | ||
469 | peu_xmt_oeh2_log_reg(63,56) = rsb_db[rsb_ctr].raw_payload[8]; | |
470 | peu_xmt_oeh2_log_reg(55,48) = rsb_db[rsb_ctr].raw_payload[9]; | |
471 | peu_xmt_oeh2_log_reg(47,40) = rsb_db[rsb_ctr].raw_payload[10]; | |
472 | peu_xmt_oeh2_log_reg(39,32) = rsb_db[rsb_ctr].raw_payload[11]; | |
473 | peu_xmt_oeh2_log_reg(31,24) = rsb_db[rsb_ctr].raw_payload[12]; | |
474 | peu_xmt_oeh2_log_reg(23,16) = rsb_db[rsb_ctr].raw_payload[13]; | |
475 | peu_xmt_oeh2_log_reg(15, 8) = rsb_db[rsb_ctr].raw_payload[14]; | |
476 | peu_xmt_oeh2_log_reg( 7, 0) = rsb_db[rsb_ctr].raw_payload[15]; | |
477 | LOG_INFO << "TOEH1: " << peu_xmt_oeh1_log_reg ; | |
478 | LOG_INFO << "TOEH2: " << peu_xmt_oeh2_log_reg ; | |
479 | csr_port.write_csr(PEU_CSR_A_TOE_HDR1_HW_ADDR,peu_xmt_oeh1_log_reg); | |
480 | csr_port.write_csr(PEU_CSR_A_TOE_HDR2_HW_ADDR,peu_xmt_oeh2_log_reg); | |
481 | } | |
482 | else | |
483 | LOG_INFO << "RSB: Error log disabled..." ; | |
484 | } | |
485 | } | |
486 | rsb_ctr++; | |
487 | }//end while(1) | |
488 | }//end try | |
489 | catch(sc_exception &e){ | |
490 | LOG_WARNING<<"RSB: Out of update_timer"; | |
491 | } | |
492 | }//update_timer() | |
493 | ||
494 | /** | |
495 | * This method determines the CMPL timeout value specified in the control CSR. | |
496 | */ | |
497 | sc_time rsb::get_Cpl_TO(){ | |
498 | sc_time to4US(4,SC_US); | |
499 | sc_time to8_4MS(8.4,SC_MS); | |
500 | sc_time to16_8MS(16.8,SC_MS); | |
501 | sc_time to33_6MS(33.6,SC_MS); | |
502 | sc_time to67_1MS(67.1,SC_MS); | |
503 | sc_time to134MS(134,SC_MS); | |
504 | sc_time to268MS(2684,SC_MS); | |
505 | ||
506 | sc_uint<64> peu_ctrl_csr_reg = csr_port.read_csr(PEU_CSR_A_TLU_CTL_HW_ADDR); | |
507 | ||
508 | switch(peu_ctrl_csr_reg.range(18,16)){ | |
509 | case 0: return SC_ZERO_TIME;//RSB_TIMER_MAX_TIME; //Infinite CPL Timeout | |
510 | case 1: return (to268MS +sc_time_stamp()); | |
511 | case 2: return (to134MS +sc_time_stamp()); | |
512 | case 3: return (to67_1MS+sc_time_stamp()); | |
513 | case 4: return (to33_6MS+sc_time_stamp()); | |
514 | case 5: return (to16_8MS+sc_time_stamp()); | |
515 | case 6: return (to8_4MS +sc_time_stamp()); | |
516 | case 7: return (to4US +sc_time_stamp()); | |
517 | }//end switch | |
518 | }//end get_Cpl_TO() | |
519 | ||
520 | /** | |
521 | * This function updates the requested UE, CE and OE error bits. | |
522 | */ | |
523 | void rsb::write_error_csr(uint8 err_type, uint8 primary, uint8 secondary, char field_name[3]){ | |
524 | sc_uint<64> orig_csr_val; | |
525 | sc_uint<64> new_csr_val=0; | |
526 | sc_uint<64> log_enable; | |
527 | ||
528 | LOG_WARNING << "Setting err bit: " << field_name; | |
529 | ||
530 | switch(err_type){ | |
531 | case OE: orig_csr_val = csr_port.read_csr(PEU_CSR_A_OE_ERR_RW1C_ALIAS_HW_ADDR); | |
532 | LOG_INFO << "Updating OE CSR (orig val: " << orig_csr_val << ")"; | |
533 | log_enable = csr_port.read_csr(PEU_CSR_A_OE_LOG_HW_ADDR); | |
534 | LOG_INFO << "OE Log enable : " << log_enable << ")"; | |
535 | break; | |
536 | case UE: orig_csr_val = csr_port.read_csr(PEU_CSR_A_UE_ERR_RW1C_ALIAS_HW_ADDR); | |
537 | LOG_INFO << "Updating UE CSR (orig val: " << orig_csr_val << ")"; | |
538 | log_enable = csr_port.read_csr(PEU_CSR_A_UE_LOG_HW_ADDR); | |
539 | LOG_INFO << "UE Log Enable : " << log_enable << ")"; | |
540 | break; | |
541 | case CE: orig_csr_val = csr_port.read_csr(PEU_CSR_A_CE_ERR_RW1C_ALIAS_HW_ADDR); | |
542 | LOG_INFO << "Updating CE CSR (orig val: " << orig_csr_val << ")"; | |
543 | log_enable = csr_port.read_csr(PEU_CSR_A_CE_LOG_HW_ADDR); | |
544 | LOG_INFO << "CE Log Enable : " << log_enable << ")"; | |
545 | break; | |
546 | default: LOG_ERROR << "Warning: undefined error type!"; | |
547 | return; | |
548 | } | |
549 | ||
550 | if(log_enable.range(primary,primary)==1) | |
551 | { | |
552 | if(orig_csr_val.range(primary,primary)!=1) | |
553 | new_csr_val.range(primary,primary)=1; | |
554 | else if(orig_csr_val.range(secondary,secondary)!=1) | |
555 | new_csr_val.range(secondary,secondary)=1; | |
556 | else | |
557 | LOG_DEBUG << "Warning: Both PRIMARY and SECONDARY of " << field_name << "are set."; | |
558 | } | |
559 | ||
560 | switch(err_type){ | |
561 | case OE: csr_port.write_csr(PEU_CSR_A_OE_ERR_RW1S_ALIAS_HW_ADDR,new_csr_val); | |
562 | LOG_DEBUG << "Updating OE CSR (new val : " << new_csr_val << ")"; | |
563 | break; | |
564 | case UE: csr_port.write_csr(PEU_CSR_A_UE_ERR_RW1S_ALIAS_HW_ADDR,new_csr_val); | |
565 | LOG_DEBUG << "Updating UE CSR (new val : " << new_csr_val << ")"; | |
566 | break; | |
567 | case CE: csr_port.write_csr(PEU_CSR_A_CE_ERR_RW1S_ALIAS_HW_ADDR,new_csr_val); | |
568 | LOG_DEBUG << "Updating CE CSR (new val : " << new_csr_val << ")"; | |
569 | break; | |
570 | } | |
571 | return; | |
572 | }//end write_csr_error | |
573 | ||
574 | /** | |
575 | * This thread handles reset behavior of the module. On the arrival of a reset global event, | |
576 | * it issue termination requests to threads in this module. Following the reset exit global event | |
577 | * it invokes init() to re-spawn terminated threads. | |
578 | */ | |
579 | void rsb::reset_handler(){ | |
580 | while(1){ | |
581 | wait(*parent_global_ev); | |
582 | switch(*global_event_type){ | |
583 | case POR_RESET_ENTER: | |
584 | case WMR_RESET_ENTER: | |
585 | LOG_WARNING << "\tRSB: WMR/POR_RESET enter signal..." ; | |
586 | POR_RESET=true; | |
587 | //Notify wait()'s in ITL thread | |
588 | reset_ev.notify(); | |
589 | //Wait for all thread to terminate | |
590 | while(1){ | |
591 | if(eg_handler_ph.terminated() && update_timer_ph.terminated()) break; | |
592 | wait(eg_handler_ph.terminated_event()|update_timer_ph.terminated_event()); | |
593 | } | |
594 | LOG_WARNING << "RSB: WMR/POR Reset threads terminated" ; | |
595 | LOG_WARNING << "RSB: WMR/POR Reset dbs cleared" ; | |
596 | break; | |
597 | ||
598 | case POR_RESET_EXIT: | |
599 | case WMR_RESET_EXIT: | |
600 | LOG_INFO << "\tRSB: WMR/POR_RESET exit signal..." ; | |
601 | init(); | |
602 | break; | |
603 | ||
604 | case SW_RESET_ENTER: | |
605 | LOG_WARNING<<"RSB: SW_RESET_ENTER"; | |
606 | STOP_TIMER=true; | |
607 | break; | |
608 | ||
609 | case SW_RESET_EXIT: | |
610 | LOG_INFO<<"RSB: SW_RESET_EXIT"; | |
611 | STOP_TIMER=false; | |
612 | break; | |
613 | } | |
614 | }//end while(1) | |
615 | }//end reset_handler() | |
616 | } |