Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: ios_err_interrupt.vr | |
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 <vera_defines.vrh> | |
36 | #include <VeraListProgram.vrh> | |
37 | #include <ListMacros.vrh> | |
38 | #include "ios_err_packet.vrh" | |
39 | #include "ios_rasmon.if.vrh" | |
40 | #include "ios_rasmon_ports_binds.vrh" | |
41 | #include "std_display_class.vrh" | |
42 | #include "siu_common.vrh" | |
43 | ||
44 | // added this to exclude code for NIU | |
45 | #ifndef FC_NO_NIU_T2 | |
46 | #include "niu_gen_pio.vrh" | |
47 | #endif | |
48 | #include "ios_ras_defines.vrh" | |
49 | #include "ios_injerr.vrh" | |
50 | ||
51 | extern StandardDisplay dbg; | |
52 | // for interrupt handler, not for FC | |
53 | ||
54 | #ifndef FC_NO_NIU_T2 | |
55 | extern niu_gen_pio gen_pio_drv; | |
56 | #endif | |
57 | ||
58 | class ios_err_interrupt_mon { | |
59 | local string myname; | |
60 | integer timeout; | |
61 | integer wait_for_report; | |
62 | integer ios_ras_interrupt_mon_on; | |
63 | integer interrupt_mon_running; | |
64 | ios_ras_inj ras_injector; | |
65 | ||
66 | task new(integer timeout = 100) { | |
67 | this.myname = "IOS-RAS INTMON"; | |
68 | this.timeout = timeout; | |
69 | this.wait_for_report = 100; | |
70 | ios_ras_interrupt_mon_on = 1; | |
71 | interrupt_mon_running = 0; | |
72 | } | |
73 | ||
74 | task monitor_err_interrupt(ios_ras_inj ras_injector, integer tout); | |
75 | task handle_err_interrupt(var integer result); | |
76 | ||
77 | } | |
78 | ||
79 | task ios_err_interrupt_mon::monitor_err_interrupt(ios_ras_inj ras_injector, integer tout) | |
80 | { | |
81 | bit [145:0] data; | |
82 | bit not_match = 1; | |
83 | integer counter = 0; | |
84 | integer wait_time, pass_check; | |
85 | ||
86 | this.ras_injector = ras_injector; | |
87 | wait_time = (tout != 0) ? tout : this.timeout; | |
88 | ||
89 | if (get_plus_arg(CHECK, "ios_ras_interrupt_chk_off")) | |
90 | ios_ras_interrupt_mon_on = 0; | |
91 | else | |
92 | ios_ras_interrupt_mon_on = 1; | |
93 | ||
94 | if (interrupt_mon_running) | |
95 | dbg.dispmon(myname, MON_NORMAL, psprintf("user cannot activate more than one interrupt monitor!")); | |
96 | else | |
97 | fork { | |
98 | dbg.dispmon(myname, MON_NORMAL, psprintf("wait for error interrupt timeout %0d", wait_time)); | |
99 | interrupt_mon_running = 1; | |
100 | while (ios_ras_interrupt_mon_on) | |
101 | { | |
102 | if (!ras_injector.injected_err_list.empty()) | |
103 | { | |
104 | counter = 0; | |
105 | pass_check = 0; | |
106 | not_match = 1; | |
107 | while (not_match) { | |
108 | @ (posedge ncu_cpx_err_mon.clk); | |
109 | counter ++ ; | |
110 | if (ncu_cpx_err_mon.req !== 8'h0) { | |
111 | @ (posedge ncu_cpx_err_mon.clk); | |
112 | data = ncu_cpx_err_mon.data[145:0]; | |
113 | //dbg.dispmon(myname, MON_NORMAL, psprintf("sample ncu cpx request %0h", data)); | |
114 | if (data[144:141] == 4'b1101) { | |
115 | dbg.dispmon(myname, MON_NORMAL, psprintf("Got an error interrupt with data %0h", data[127:0])); | |
116 | // call ras interrupt handler FC shall be different | |
117 | this.handle_err_interrupt(pass_check); | |
118 | if (!pass_check) | |
119 | dbg.dispmon(myname, MON_ERR, psprintf("ras checking failed!")); | |
120 | // end of interrupt checker | |
121 | not_match = 0; | |
122 | } | |
123 | } | |
124 | if (counter > wait_time && not_match) | |
125 | { | |
126 | dbg.dispmon(myname, MON_ERR, psprintf("interrupt timeout")); | |
127 | not_match = 0; | |
128 | } | |
129 | } // search for the | |
130 | } // injected_err_list not empty | |
131 | else | |
132 | @ (posedge ncu_cpx_err_mon.clk); | |
133 | } // while(1) | |
134 | } join none | |
135 | } // task | |
136 | ||
137 | task ios_err_interrupt_mon::handle_err_interrupt(var integer result) { | |
138 | bit [63:0] tdata1 = 64'b0; | |
139 | bit [63:0] syn_data = 64'b0; | |
140 | bit [63:0] per_data = 64'b0; | |
141 | bit [63:0] esr_data = 64'b0; | |
142 | bit [63:0] expect_data = 64'b0; | |
143 | bit [63:0] ncuele_value, ncueie_value; | |
144 | bit [63:0] sii_syndrome = 64'b0; | |
145 | bit [2:0] sii_etag = 3'b011; | |
146 | bit check_sii_syndrome = 0; | |
147 | bit [63:0] ncu_syndrome = 64'b0; | |
148 | bit [4:0] ncu_etag = 5'b0; | |
149 | bit check_ncu_syndrome = 0; | |
150 | ios_err_packet ptr_pkt; | |
151 | VeraListIterator_ios_err_packet list_ptr; | |
152 | ||
153 | ras_injector.injector_on = 0; | |
154 | ||
155 | // read whole injection list | |
156 | list_ptr = ras_injector.injected_err_list.start(); | |
157 | ptr_pkt = list_ptr.data(); | |
158 | dbg.dispmon(myname, MON_NORMAL, psprintf("reading injection list size %0d", ras_injector.injected_err_list.size())); | |
159 | while (ptr_pkt != null) | |
160 | { | |
161 | dbg.dispmon(myname, MON_NORMAL, psprintf("injection pkt tag=%x pa=%x type=%0d", ptr_pkt.ctag, ptr_pkt.pa, ptr_pkt.type)); | |
162 | case (ptr_pkt.type) | |
163 | { | |
164 | #ifndef FC_NO_NIU_T2 | |
165 | NIUSII_CUE: { expect_data[siiNiuCtagUe] = 1'b1; sii_etag = 0; } | |
166 | NIUSII_CCE: { expect_data[siiNiuCtagCe] = 1'b1; } | |
167 | NIUSII_AP: { expect_data[siiNiuAPe] = 1'b1; sii_etag = 4; } | |
168 | NIUSII_DP: { expect_data[siiNiuDPe] = 1'b1; sii_etag = 6; } | |
169 | SIONIU_DP: { expect_data[niuDPe] = 1'b1; } | |
170 | SIONIU_CUE: { expect_data[niuCtagUe] = 1'b1; } | |
171 | SIONIU_CCE: { expect_data[niuCtagCe] = 1'b1; } | |
172 | #endif | |
173 | DMUSII_CUE: { expect_data[siiDmuCtagUe] = 1'b1; sii_etag = 1; } | |
174 | DMUSII_CCE: { expect_data[siiDmuCtagCe] = 1'b1; } | |
175 | DMUSII_AP: { expect_data[siiDmuAPe] = 1'b1; sii_etag = 7; } | |
176 | DMUSII_DP: { expect_data[siiDmuDPe] = 1'b1; sii_etag = 5; } | |
177 | SIODMU_DP: { expect_data[dmuDPe] = 1'b1; } | |
178 | SIODMU_CUE: { expect_data[dmuCtagUe] = 1'b1; } | |
179 | SIODMU_CCE: { expect_data[dmuCtagCe] = 1'b1; } | |
180 | L2SIO_DP: { expect_data[sioDPe] = 1'b1; } | |
181 | L2SIO_EBIT:{} | |
182 | L2SIO_CUE: { expect_data[sioCtagUe] = 1'b1; } | |
183 | L2SIO_CCE: { expect_data[sioCtagCe] = 1'b1; } | |
184 | SIINCU_DP: { expect_data[ncuDataParity] = 1'b1;} | |
185 | SIINCU_CCE: { expect_data[ncuCtagCe] = 1'b1; } | |
186 | SIINCU_CUE: { expect_data[ncuCtagUe] = 1'b1; } | |
187 | #ifndef FC_NO_NIU_T2 | |
188 | NIUSII_IOAE: {} | |
189 | NIUSII_IOUE: {} | |
190 | NIUSII_CMDP: {} | |
191 | #endif | |
192 | DMUSII_TOUT: {} | |
193 | DMUSII_IOAE: {} | |
194 | DMUSII_IOUE: {} | |
195 | DMUSII_CMDP: {} | |
196 | DMUSII_BEP: {} | |
197 | DMUNCU_WRACK_P: { expect_data[ncuDmuCr] = 1'b1; } | |
198 | NCUDMU_MONDO_IDP: { expect_data[dmuNcuCrPe] = 1'b1; } | |
199 | SIIDMU_WRACK_P: { expect_data[dmuSiiCrPe] = 1'b1; } | |
200 | } | |
201 | // only take first one on the list | |
202 | if (!check_sii_syndrome) | |
203 | { | |
204 | if (sii_etag !== 3'b011) | |
205 | { | |
206 | check_sii_syndrome = 1; | |
207 | sii_syndrome = {1'b1, 4'b0, sii_etag, ptr_pkt.ctag, ptr_pkt.pa}; | |
208 | } | |
209 | } | |
210 | ||
211 | list_ptr = ras_injector.injected_err_list.erase(list_ptr); | |
212 | ptr_pkt = list_ptr.data(); | |
213 | } | |
214 | ||
215 | #ifdef N2_FC | |
216 | // direct read from the ncu ras csr | |
217 | per_data = 64'b0; | |
218 | per_data[42:0] = ncu_ras_csr.per; | |
219 | if (expect_data[42:0] !== per_data[42:0]) | |
220 | { | |
221 | repeat (wait_for_report) @ (posedge ncu_cpx_err_mon.clk); | |
222 | esr_data[42:0] = ncu_ras_csr.esr[42:0]; | |
223 | per_data = esr_data | per_data; | |
224 | result = (expect_data[42:0] === per_data[42:0]) ? 1 : 0; | |
225 | } | |
226 | else | |
227 | result = 1; | |
228 | ||
229 | if (result) | |
230 | dbg.dispmon(myname, MON_NORMAL, psprintf("direct read: error status register match get=%x exp=%x", per_data[42:0], expect_data[42:0])); | |
231 | else | |
232 | dbg.dispmon(myname, MON_ERR, psprintf("direct read: error status register mismatch get=%x exp=%x", per_data[42:0], expect_data[42:0])); | |
233 | ||
234 | if (check_sii_syndrome) | |
235 | { | |
236 | repeat (30) @ (posedge ncu_cpx_err_mon.clk); | |
237 | syn_data = 64'b0; | |
238 | syn_data[58:0] = ncu_ras_csr.siisyn; | |
239 | if (sii_syndrome[58:56] === 3'b0 || sii_syndrome[58:56] === 3'b001) sii_syndrome[55:40] = syn_data[55:40]; | |
240 | if (sii_syndrome[58:0] === syn_data[58:0]) | |
241 | { | |
242 | dbg.dispmon(myname, MON_NORMAL, psprintf("direct read: sii error syndrome register match get=%x exp=%x", syn_data[58:0], sii_syndrome[58:0])); | |
243 | result = 1; | |
244 | } | |
245 | else | |
246 | { | |
247 | dbg.dispmon(myname, MON_ERR, psprintf("direct read: sii error syndrome register mismatch get=%x exp=%x", syn_data[58:0], sii_syndrome[58:0])); | |
248 | result = 0; | |
249 | } | |
250 | } | |
251 | // end of direct read checking | |
252 | #else | |
253 | ||
254 | // disable interrupt | |
255 | gen_pio_drv.pio_rd(40'h80_0000_3010, ncueie_value); | |
256 | gen_pio_drv.pio_wr(40'h80_0000_3010, 64'h0000_0000_0000_0000); | |
257 | // read per, | |
258 | gen_pio_drv.pio_rd(40'h80_0000_3028, tdata1); | |
259 | per_data = {tdata1[7:0],tdata1[15:8],tdata1[23:16],tdata1[31:24],tdata1[39:32],tdata1[47:40],tdata1[55:48],tdata1[63:56]}; | |
260 | // if not matched, wait 100 cycles | |
261 | if (expect_data[62:0] !== per_data[62:0]) | |
262 | { | |
263 | repeat (wait_for_report) @ (posedge ncu_cpx_err_mon.clk); | |
264 | gen_pio_drv.pio_rd(40'h80_0000_3000, tdata1); | |
265 | esr_data = {tdata1[7:0],tdata1[15:8],tdata1[23:16],tdata1[31:24],tdata1[39:32],tdata1[47:40],tdata1[55:48],tdata1[63:56]}; | |
266 | per_data = esr_data | per_data; | |
267 | result = (expect_data[62:0] === per_data[62:0]) ? 1 : 0; | |
268 | } | |
269 | else | |
270 | result = 1; | |
271 | if (result) | |
272 | dbg.dispmon(myname, MON_NORMAL, psprintf("error status register match get=%x exp=%x", per_data, expect_data)); | |
273 | else | |
274 | dbg.dispmon(myname, MON_ERR, psprintf("error status register mismatch get=%x exp=%x", per_data, expect_data)); | |
275 | ||
276 | ||
277 | // disable logging | |
278 | gen_pio_drv.pio_rd(40'h80_0000_3008, ncuele_value); | |
279 | gen_pio_drv.pio_wr(40'h80_0000_3008, 64'h0000_0000_0000_0000); | |
280 | ||
281 | ||
282 | // check syndrome | |
283 | if (check_sii_syndrome) | |
284 | { | |
285 | gen_pio_drv.pio_rd(40'h80_0000_3030, tdata1); | |
286 | syn_data = {tdata1[7:0],tdata1[15:8],tdata1[23:16],tdata1[31:24],tdata1[39:32],tdata1[47:40],tdata1[55:48],tdata1[63:56]}; | |
287 | if (sii_syndrome[58:56] === 3'b0 || sii_syndrome[58:56] === 3'b001) sii_syndrome[55:40] = syn_data[55:40]; | |
288 | if (sii_syndrome === syn_data) | |
289 | { | |
290 | dbg.dispmon(myname, MON_NORMAL, psprintf("sii error syndrome register match get=%x exp=%x", syn_data, sii_syndrome)); | |
291 | result = 1; | |
292 | } | |
293 | else | |
294 | { | |
295 | dbg.dispmon(myname, MON_ERR, psprintf("sii error syndrome register mismatch get=%x exp=%x", syn_data, sii_syndrome)); | |
296 | result = 0; | |
297 | } | |
298 | } | |
299 | ||
300 | gen_pio_drv.pio_wr(40'h80_0000_3028, 64'h0000_0000_0000_0000); | |
301 | gen_pio_drv.pio_wr(40'h80_0000_3000, 64'h0000_0000_0000_0000); | |
302 | gen_pio_drv.pio_wr(40'h80_0000_3030, 64'h0000_0000_0000_0000); | |
303 | gen_pio_drv.pio_wr(40'h80_0000_3008, ncuele_value); | |
304 | gen_pio_drv.pio_wr(40'h80_0000_3010, ncueie_value); | |
305 | #endif | |
306 | ||
307 | ras_injector.injector_on = 1; | |
308 | } |