Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: siu_niu_mon.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 "siumon.if.vrh" | |
36 | #include "siumon_ports_binds.vrh" | |
37 | #include "std_display_class.vrh" | |
38 | #include "siu_niu_packet.vrh" | |
39 | #include "siu_monitor.vrh" | |
40 | ||
41 | class siu_niu_monitor { | |
42 | niumon_port monitor; | |
43 | ||
44 | local integer niu_credit; | |
45 | ||
46 | siu_niu_packet snd_packet; | |
47 | siu_niu_packet rec_packet; | |
48 | integer snd_mbox, rec_mbox; | |
49 | ||
50 | StandardDisplay dbg; | |
51 | string myname; | |
52 | ||
53 | task new (niumon_port monitor, integer snd_mbox, integer rec_mbox, StandardDisplay dbg); | |
54 | ||
55 | task monitor_send (); | |
56 | task monitor_recv (); | |
57 | task monitor_niudq (); | |
58 | ||
59 | function integer get_send_pkt(Cycle_Mode mode, integer cycle); | |
60 | function integer check_send(Cycle_Mode mode); | |
61 | function integer get_recv_pkt(Cycle_Mode mode, integer cycle); | |
62 | function integer check_recv(Cycle_Mode mode); | |
63 | } | |
64 | ||
65 | task siu_niu_monitor::new(niumon_port monitor, integer snd_mbox, integer rec_mbox, StandardDisplay dbg) | |
66 | { | |
67 | this.monitor = monitor; | |
68 | ||
69 | snd_packet = new(RDD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
70 | rec_packet = new(RDD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
71 | ||
72 | this.dbg = dbg; | |
73 | myname = "siu-niu"; | |
74 | niu_credit = NIU_SIO_CREDIT; | |
75 | this.snd_mbox = snd_mbox; | |
76 | this.rec_mbox = rec_mbox; | |
77 | ||
78 | dbg.dispmon(myname, MON_NORMAL, psprintf ("monitor ready !")); | |
79 | ||
80 | fork { monitor_send(); } join none | |
81 | fork { monitor_recv(); } join none | |
82 | fork { monitor_niudq(); } join none | |
83 | } | |
84 | ||
85 | task siu_niu_monitor::monitor_niudq() | |
86 | { | |
87 | while (1) | |
88 | { | |
89 | @(posedge monitor.$clk); | |
90 | if (monitor.$niu_dq === 1'b1 && monitor.$rreq !== 1'b1) | |
91 | { | |
92 | niu_credit++; | |
93 | dbg.dispmon (myname, MON_INFO, psprintf ("niu_sio_dq credit = %1d", niu_credit)); | |
94 | } | |
95 | } | |
96 | } | |
97 | ||
98 | task siu_niu_monitor::monitor_send() | |
99 | { | |
100 | siu_niu_packet packet; | |
101 | integer i, data_cycles; | |
102 | integer fail, result, temp; | |
103 | string t, p, q; | |
104 | ||
105 | while (1) | |
106 | { | |
107 | @(posedge monitor.$clk); | |
108 | if (monitor.$sreq === 1'b1) | |
109 | { | |
110 | data_cycles = 0; | |
111 | fail = 0; | |
112 | temp = 0; | |
113 | ||
114 | // header | |
115 | result = get_send_pkt(HEADER_C, 1); | |
116 | fail = check_send(HEADER_C); | |
117 | ||
118 | if (snd_packet.type == RDD) | |
119 | { t="R"; p="N"; } | |
120 | else | |
121 | { | |
122 | t="W"; | |
123 | p=(snd_packet.posted) ? "P" : "N"; | |
124 | } | |
125 | q = (snd_packet.bypass) ? "bypass" : "order"; | |
126 | dbg.dispmon (myname, MON_NORMAL, psprintf ("snd [%s%s,%4x,%10x] %s", t, p, snd_packet.id, snd_packet.pa, q)); | |
127 | ||
128 | // data | |
129 | if (monitor.$sdatareq === 1'b1) | |
130 | data_cycles = 4; | |
131 | for (i=0; i<data_cycles; i++) | |
132 | { | |
133 | @(posedge monitor.$clk); | |
134 | result = get_send_pkt(DATA_C, i); | |
135 | temp = check_send(DATA_C); | |
136 | fail += temp; | |
137 | } | |
138 | ||
139 | if (fail != 0) | |
140 | dbg.dispmon(myname, MON_ERR, psprintf ("niu -> siu pkt=%x protocol fail!", snd_packet.id)); | |
141 | else | |
142 | mailbox_put(snd_mbox, snd_packet); | |
143 | } | |
144 | } | |
145 | } | |
146 | ||
147 | task siu_niu_monitor::monitor_recv() | |
148 | { | |
149 | integer i, result, fail, temp, data_cycles; | |
150 | ||
151 | while (1) | |
152 | { | |
153 | @(posedge monitor.$clk); | |
154 | if (monitor.$rreq === 1'b1) | |
155 | { | |
156 | if (monitor.$niu_dq !== 1'b1) | |
157 | niu_credit--; | |
158 | ||
159 | data_cycles = 0; | |
160 | fail = 0; | |
161 | temp = 0; | |
162 | ||
163 | result = get_recv_pkt(HEADER_C, 1); | |
164 | fail = check_recv(HEADER_C); | |
165 | ||
166 | if (niu_credit < 0) | |
167 | dbg.dispmon(myname, MON_ERR, psprintf ("rec [%4x] credit underflow = %1d!", rec_packet.id, niu_credit)); | |
168 | else | |
169 | dbg.dispmon (myname, MON_NORMAL, psprintf ("rec [%4x] credit = %1d", rec_packet.id, niu_credit)); | |
170 | ||
171 | ||
172 | // data | |
173 | if (monitor.$rdatareq === 1'b1) data_cycles = 4; | |
174 | for (i=0; i<data_cycles; i++) | |
175 | { | |
176 | @(posedge monitor.$clk); | |
177 | result = get_recv_pkt(DATA_C, i); | |
178 | temp = check_recv(DATA_C); | |
179 | fail += temp; | |
180 | } | |
181 | ||
182 | if (fail != 0) | |
183 | dbg.dispmon(myname, MON_ERR, psprintf ("siu -> niu pkt=%x protocol fail!", rec_packet.id)); | |
184 | else | |
185 | mailbox_put(rec_mbox, rec_packet); | |
186 | } | |
187 | } | |
188 | } | |
189 | ||
190 | function integer siu_niu_monitor::get_send_pkt(Cycle_Mode mode, integer cycle) | |
191 | { | |
192 | if (mode == HEADER_C) | |
193 | { | |
194 | // bypass | |
195 | snd_packet.bypass = monitor.$bypass; | |
196 | // take header | |
197 | snd_packet.posted = monitor.$sdata[126]; | |
198 | snd_packet.id = monitor.$sdata[79:64]; | |
199 | snd_packet.pa = monitor.$sdata[39:0]; | |
200 | snd_packet.tout = monitor.$sdata[82]; | |
201 | snd_packet.ue = monitor.$sdata[81]; | |
202 | snd_packet.uce = monitor.$sdata[80]; | |
203 | // type | |
204 | if (monitor.$sdatareq === 1'b0) | |
205 | snd_packet.type = RDD; | |
206 | else | |
207 | if (monitor.$sdatareq === 1'b1) | |
208 | snd_packet.type = WRI; | |
209 | } | |
210 | if (mode == DATA_C) | |
211 | { | |
212 | snd_packet.data[cycle*2] = monitor.$sdata[63:0]; | |
213 | snd_packet.data[cycle*2+1] = monitor.$sdata[127:64]; | |
214 | } | |
215 | } | |
216 | ||
217 | function integer siu_niu_monitor::check_send(Cycle_Mode mode) | |
218 | { | |
219 | integer fail = 0; | |
220 | reg posted = monitor.$sdata[126]; | |
221 | ||
222 | if (mode == HEADER_C) | |
223 | { | |
224 | if (monitor.$sdatareq === 1'b0) | |
225 | { | |
226 | if (monitor.$sdata[127:122] !== 6'b001010) | |
227 | { | |
228 | fail++; | |
229 | dbg.dispmon(myname, MON_NORMAL, psprintf ("send: invalid RDD header")); | |
230 | } | |
231 | } | |
232 | if (monitor.$sdatareq === 1'b1) | |
233 | { | |
234 | if (monitor.$sdata[127:122] !== {1'b0, posted, 4'b0010} ) | |
235 | { | |
236 | fail++; | |
237 | dbg.dispmon(myname, MON_NORMAL, psprintf ("send: invalid RDD header")); | |
238 | } | |
239 | } | |
240 | ||
241 | /* Comment out for RAS, will add back when stable | |
242 | if (monitor.$sdata[121:83] !== 39'b0 || monitor.$sdata[63:40] !== 24'b0) | |
243 | { | |
244 | fail++; | |
245 | dbg.dispmon(myname, MON_NORMAL, psprintf ("send: header error, reserved bits not zero")); | |
246 | } | |
247 | */ | |
248 | } | |
249 | if (mode == DATA_C) | |
250 | { | |
251 | if (monitor.$sreq === 1'b1 || monitor.$sdatareq === 1'b1) | |
252 | { | |
253 | fail++; | |
254 | dbg.dispmon(myname, MON_NORMAL, psprintf ("send: req error, active in data cycles")); | |
255 | } | |
256 | } | |
257 | ||
258 | check_send = fail; | |
259 | } | |
260 | ||
261 | function integer siu_niu_monitor::get_recv_pkt(Cycle_Mode mode, integer cycle) | |
262 | { | |
263 | if (mode == HEADER_C) | |
264 | { | |
265 | // take header | |
266 | rec_packet.posted = monitor.$rdata[126]; | |
267 | rec_packet.id = monitor.$rdata[79:64]; | |
268 | rec_packet.pa = monitor.$rdata[39:0]; | |
269 | rec_packet.tout = monitor.$rdata[82]; | |
270 | rec_packet.ue = monitor.$rdata[81]; | |
271 | rec_packet.uce = monitor.$rdata[80]; | |
272 | // type | |
273 | if (monitor.$rdatareq === 1'b0) | |
274 | rec_packet.type = WRI; | |
275 | else | |
276 | if (monitor.$rdatareq === 1'b1) | |
277 | rec_packet.type = RDD; | |
278 | } | |
279 | if (mode == DATA_C) | |
280 | { | |
281 | rec_packet.data[cycle*2] = monitor.$rdata[63:0]; | |
282 | rec_packet.data[cycle*2+1] = monitor.$rdata[127:64]; | |
283 | } | |
284 | } | |
285 | ||
286 | function integer siu_niu_monitor::check_recv(Cycle_Mode mode) | |
287 | { | |
288 | integer fail = 0; | |
289 | reg posted = monitor.$rdata[126]; | |
290 | ||
291 | if (mode == HEADER_C) | |
292 | { | |
293 | if (monitor.$rdatareq === 1'b0) | |
294 | { | |
295 | if (monitor.$rdata[127:122] !== 6'b100010) | |
296 | { | |
297 | fail++; | |
298 | dbg.dispmon(myname, MON_NORMAL, psprintf ("recv: invalid WRI ack header %b", monitor.$rdata[127:122])); | |
299 | } | |
300 | } | |
301 | if (monitor.$rdatareq === 1'b1) | |
302 | { | |
303 | if (monitor.$rdata[127:122] !== 6'b101010) | |
304 | { | |
305 | fail++; | |
306 | dbg.dispmon(myname, MON_NORMAL, psprintf ("recv: invalid RDD rtn header %b", monitor.$rdata[127:122])); | |
307 | } | |
308 | } | |
309 | ||
310 | if (monitor.$rdata[121:83] !== 39'b0 || monitor.$rdata[63:62] !== 2'b0 || monitor.$rdata[55:40] !== 16'b0) | |
311 | { | |
312 | fail++; | |
313 | dbg.dispmon(myname, MON_NORMAL, psprintf ("recv: header error, reserved bits not zero")); | |
314 | } | |
315 | } | |
316 | if (mode == DATA_C) | |
317 | { | |
318 | if (monitor.$rreq === 1'b1) | |
319 | { | |
320 | fail++; | |
321 | dbg.dispmon(myname, MON_NORMAL, psprintf ("recv: req error, active in data cycles")); | |
322 | } | |
323 | } | |
324 | ||
325 | check_recv = fail; | |
326 | } |