Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: siu_ncu_mondo_checker.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 <globals.vri> | |
39 | ||
40 | #define STD_DISP gDbg | |
41 | ||
42 | #include "top_defines.vrh" | |
43 | #include "siu_ncu_mondo.if.vrh" | |
44 | #include "siu_ncu_mondo_ports_binds.vrh" | |
45 | #include <std_display_defines.vri> | |
46 | #include <std_display_class.vrh> | |
47 | ///////////////////////////////////////////////////////////////////////////////// | |
48 | class mondoPacket | |
49 | { | |
50 | bit req; | |
51 | bit [31:0] header; | |
52 | bit [127:0] data; | |
53 | bit [5:0] thread; | |
54 | ||
55 | bit [5:0] mondo_id; | |
56 | bit ack; | |
57 | bit nack; | |
58 | ||
59 | task new( | |
60 | (bit req = 1'bx), | |
61 | (bit [31:0] header = 128'hx), | |
62 | (bit [127:0] data = 32'hx), | |
63 | (bit [5:0] thread = 6'bx), | |
64 | (bit [5:0] mondo_id = 6'hx), | |
65 | (bit ack = 1'bx), | |
66 | (bit nack = 1'bx) | |
67 | ); | |
68 | ||
69 | function bit checkMondo(mondoPacket mondoAckNack); | |
70 | task print_pkt(mondoPacket Pkt); | |
71 | } | |
72 | ||
73 | //////////////////////////////////////////////////////////////////////////// | |
74 | ||
75 | task mondoPacket::new( | |
76 | (bit req = 1'bx), | |
77 | (bit [31:0] header = 128'hx), | |
78 | (bit [127:0] data = 32'hx), | |
79 | (bit [5:0] thread = 6'bx), | |
80 | (bit [5:0] mondo_id = 6'hx), | |
81 | (bit ack = 1'bx), | |
82 | (bit nack = 1'bx)) | |
83 | ||
84 | { | |
85 | this.req = 1'bx; | |
86 | this.header = 32'hx; | |
87 | this.data = 127'hx; | |
88 | this.thread = 6'bx; | |
89 | this.mondo_id = 6'hx; | |
90 | this.ack = 1'bx; | |
91 | this.nack = 1'bx; | |
92 | } | |
93 | ||
94 | //////////////////////////////////////////////////////////////////////////// | |
95 | // compare mondo req and ack | |
96 | function bit mondoPacket::checkMondo(mondoPacket mondoAckNack) | |
97 | { | |
98 | if((mondoAckNack.ack) || (mondoAckNack.nack)) | |
99 | { | |
100 | if(this.mondo_id == mondoAckNack.mondo_id) | |
101 | { | |
102 | checkMondo = 1; | |
103 | } | |
104 | else | |
105 | { | |
106 | checkMondo = 0; | |
107 | } | |
108 | } | |
109 | } | |
110 | ||
111 | /////////////////////////////////////////////////////////////////// | |
112 | extern StandardDisplay gDbg; | |
113 | MakeVeraList(mondoPacket) | |
114 | ||
115 | class siu_ncu_mondo_checker | |
116 | { | |
117 | integer mondo_queue_sem; | |
118 | mondo_ncu_port mondo_port; | |
119 | VeraList_mondoPacket mondo_pkt_queue; | |
120 | ||
121 | task new(mondo_ncu_port portvar); | |
122 | task collectMondoReq(); | |
123 | task collectMondoAck(); | |
124 | task collectMondoNack(); | |
125 | task dumpExpects(); | |
126 | task checkMondoAckNack(mondoPacket Pkt); | |
127 | } | |
128 | ||
129 | task siu_ncu_mondo_checker::new(mondo_ncu_port portvar) | |
130 | { | |
131 | integer i; | |
132 | ||
133 | mondo_port = portvar; | |
134 | mondo_pkt_queue = new(); | |
135 | mondo_queue_sem = alloc(SEMAPHORE, 0, 1, 1); | |
136 | fork | |
137 | { | |
138 | collectMondoReq(); | |
139 | } | |
140 | { | |
141 | collectMondoAck(); | |
142 | } | |
143 | { | |
144 | collectMondoNack(); | |
145 | } | |
146 | join none | |
147 | } | |
148 | ||
149 | task siu_ncu_mondo_checker::collectMondoReq() | |
150 | { | |
151 | mondoPacket reqPkt; | |
152 | mondoPacket pendReqPkt; | |
153 | bit [31:0] header; | |
154 | bit [128:0] data; | |
155 | integer size,i; | |
156 | ||
157 | while (1) | |
158 | { | |
159 | @(posedge mondo_port.$req); | |
160 | @(posedge mondo_port.$grant); | |
161 | @(posedge mondo_port.$clk); | |
162 | header[31:0] = mondo_port.$data; | |
163 | reqPkt = new(); | |
164 | reqPkt.req = header[15:15]; | |
165 | reqPkt.header = header; | |
166 | reqPkt.mondo_id = {header[14:11], header[2:1]}; | |
167 | @(posedge mondo_port.$clk); | |
168 | data[127:96] = mondo_port.$data; | |
169 | @(posedge mondo_port.$clk); | |
170 | data[95:64] = mondo_port.$data; | |
171 | fork | |
172 | { | |
173 | @(posedge mondo_port.$clk); | |
174 | data[63:32] = mondo_port.$data; | |
175 | @(posedge mondo_port.$clk); | |
176 | data[31:0] = mondo_port.$data; | |
177 | reqPkt.data = data; | |
178 | reqPkt.thread = data[11:6]; | |
179 | semaphore_get(WAIT, mondo_queue_sem, 1); | |
180 | ||
181 | PR_NORMAL ("siu_ncu_mondo_checker", MON_NORMAL, psprintf("Received Mondo Interrupt : Header %8h : Data %32h : mondo_id %2h",reqPkt.header, reqPkt.data, reqPkt.mondo_id)); | |
182 | ||
183 | size = mondo_pkt_queue.size(); | |
184 | if(size > 4) | |
185 | { | |
186 | PR_ERROR ("siu_ncu_mondo_checker", MON_ERROR, psprintf("Already 4 Mondo Interrupts are pending : Unexpecvted Mondo Interrupt with mondo id : %2h",pendReqPkt.mondo_id)); | |
187 | } | |
188 | ||
189 | for(i = 0; i < size; i++) | |
190 | { | |
191 | pendReqPkt = mondo_pkt_queue.front(); | |
192 | mondo_pkt_queue.pop_front(); | |
193 | if(pendReqPkt.mondo_id == reqPkt.mondo_id) | |
194 | { | |
195 | PR_ERROR ("siu_ncu_mondo_checker", MON_ERROR, psprintf("Mondo Interrupt with mondo id : %2h already pending",pendReqPkt.mondo_id)); | |
196 | } | |
197 | mondo_pkt_queue.push_back(pendReqPkt); | |
198 | } | |
199 | mondo_pkt_queue.push_back(reqPkt); | |
200 | semaphore_put(mondo_queue_sem, 1); | |
201 | } | |
202 | join none | |
203 | } | |
204 | } | |
205 | ||
206 | ||
207 | task siu_ncu_mondo_checker::collectMondoAck() | |
208 | { | |
209 | mondoPacket ackPkt; | |
210 | ||
211 | while (1) | |
212 | { | |
213 | @(posedge mondo_port.$clk); | |
214 | if(mondo_port.$ack == 1'b1) | |
215 | { | |
216 | ackPkt = new(); | |
217 | ackPkt.ack = 1'b1; | |
218 | ackPkt.mondo_id = mondo_port.$mondo_id; | |
219 | checkMondoAckNack(ackPkt); | |
220 | } | |
221 | } | |
222 | } | |
223 | ||
224 | task siu_ncu_mondo_checker::collectMondoNack() | |
225 | { | |
226 | mondoPacket nackPkt; | |
227 | ||
228 | while (1) | |
229 | { | |
230 | @(posedge mondo_port.$clk); | |
231 | if(mondo_port.$nack == 1'b1) | |
232 | { | |
233 | nackPkt = new(); | |
234 | nackPkt.nack = 1'b1; | |
235 | nackPkt.mondo_id = mondo_port.$mondo_id; | |
236 | checkMondoAckNack(nackPkt); | |
237 | } | |
238 | } | |
239 | } | |
240 | ||
241 | /////////////////////////////////////////////////////////////////////// | |
242 | task siu_ncu_mondo_checker::checkMondoAckNack(mondoPacket Pkt) | |
243 | { | |
244 | mondoPacket reqPkt; | |
245 | integer size,i; | |
246 | bit found = 0; | |
247 | ||
248 | size = mondo_pkt_queue.size(); | |
249 | ||
250 | ||
251 | reqPkt = mondo_pkt_queue.front(); | |
252 | if(reqPkt.checkMondo(Pkt)) | |
253 | { | |
254 | mondo_pkt_queue.pop_front(); | |
255 | found = 1; | |
256 | if(Pkt.ack) | |
257 | { | |
258 | PR_NORMAL("siu_ncu_mondo_checker", MON_NORMAL, psprintf ("Received Ack for mondo Id : %2h \n", Pkt.mondo_id)); | |
259 | } | |
260 | else if(Pkt.nack) | |
261 | { | |
262 | PR_NORMAL("siu_ncu_mondo_checker", MON_NORMAL, psprintf ("Received Nack for mondo Id : %2h \n", Pkt.mondo_id)); | |
263 | } | |
264 | } | |
265 | else | |
266 | { | |
267 | dumpExpects(); | |
268 | if(Pkt.ack) | |
269 | { | |
270 | PR_ERROR ("siu_ncu_mondo_checker", MON_ERROR, psprintf ("Received unexpected mondo Ack with mondo Id : %2h \n", Pkt.mondo_id)); | |
271 | } | |
272 | else if(Pkt.nack) | |
273 | { | |
274 | PR_ERROR ("siu_ncu_mondo_checker", MON_ERROR, psprintf ("Received unexpected mondo Nack with mondo Id : %2h \n", Pkt.mondo_id)); | |
275 | } | |
276 | } | |
277 | semaphore_put(mondo_queue_sem, 1); | |
278 | } | |
279 | ||
280 | ||
281 | /////////////////////////////////////////////////////////////////////// | |
282 | task siu_ncu_mondo_checker::dumpExpects() | |
283 | { | |
284 | mondoPacket reqPkt; | |
285 | integer size,i; | |
286 | ||
287 | printf ("------ Dumping Expects for Mondo requests from SIU to NCU ------ \n"); | |
288 | ||
289 | for(i = 0; i < size; i++) | |
290 | { | |
291 | reqPkt = mondo_pkt_queue.front(); | |
292 | mondo_pkt_queue.pop_front(); | |
293 | printf (" %d : Mondo Id %2h : Header %8h : Data %32h \n", i, reqPkt.mondo_id, reqPkt.header, reqPkt.data); | |
294 | } | |
295 | ||
296 | printf("------------------------------------------------------------------ \n"); | |
297 | } | |
298 |