Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: cpxPktClass.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 <std_display_defines.vri> | |
37 | #include <ccxDevicesDefines.vri> | |
38 | #include <cmp.vri> | |
39 | // #include <defines.vri> | |
40 | ||
41 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
42 | // To use this class, you must have in your bench a files called globals.vri | |
43 | // that has all global extern declerations in it. | |
44 | #include <globals.vri> | |
45 | ||
46 | #include <std_display_class.vrh> | |
47 | #include <basePktClass.vrh> | |
48 | #include <pcxPktClass.vrh> | |
49 | #include <ccxDevBaseBFM.vrh> | |
50 | #include <ccxDevMemBFM.vrh> | |
51 | #include <ccxDevSpcBFM.vrh> | |
52 | #include <baseParamsClass.vrh> | |
53 | #include <sparcParams.vrh> | |
54 | ||
55 | #define MON_CCXPKT 24 | |
56 | ||
57 | ||
58 | //---------------------------------------------------------- | |
59 | // CPX Packet | |
60 | ||
61 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
62 | // CpxPacket Format | |
63 | // 145 | 144:141 | 140 | 139:138 | 137 | 136:134 | 133 | 132:131 | 130 | 129 | 127:0 | |
64 | // --------------------------------------------------------------------------------------------- | |
65 | // valid | rtntyp | l2miss | err | nc | tid | wv | wayMMUid | wayf4b | atmIf2 | data | |
66 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
67 | ||
68 | class CpxPkt extends BasePkt{ | |
69 | ||
70 | // cpx vector | |
71 | public reg valid = 1; | |
72 | // in base public reg [3:0] rtntyp = 0; | |
73 | public reg l2miss = 0; // will be randomized by code | |
74 | public reg [1:0] err = 0; | |
75 | public reg nc = 0; | |
76 | // in base public reg [2:0] tid = 0; | |
77 | public reg wv = 0; | |
78 | public reg [1:0] wayMMUid = 0; | |
79 | public reg wayf4b = 0; | |
80 | public reg atmIf2 = 0; | |
81 | public reg pf = 0; | |
82 | public reg [127:0] data = 0; | |
83 | // end cpx vector | |
84 | ||
85 | public reg io = 0; | |
86 | ||
87 | local reg [145:0] pktVec = 0; | |
88 | local integer printCount = 0; | |
89 | local CpxPkt receivedPkt = null; | |
90 | ||
91 | // for multicast checking (one pkt becomes many). create first destination pkt. | |
92 | // in it, store all handles to twin destination packets. On checking, if | |
93 | // twin list not null, make sure all twins are identical. | |
94 | public CpxPkt twinList [8]; | |
95 | ||
96 | // bench knobs | |
97 | // hitRateParm; | |
98 | // hitDelayMinParm; | |
99 | // hitDelayMaxParm; | |
100 | // missDelayMinParm; | |
101 | // missDelayMaxParm; | |
102 | // pkt2DelayMinParm; | |
103 | // pkt2DelayMaxParm; | |
104 | ||
105 | // randoms for L2 BFM use | |
106 | public rand bit hit; // "hit" latencies are used | |
107 | public rand integer responseDelay; // value of latency for response to this pkt | |
108 | public rand integer pkt2Delay; // value of latency for second pkt of pair | |
109 | ||
110 | constraint hit_c | |
111 | { | |
112 | hit dist {0 := 100 - gParam.hitRate, 1 := gParam.hitRate}; | |
113 | } | |
114 | ||
115 | constraint responseDelay_c | |
116 | { | |
117 | if (hit == 1) | |
118 | { responseDelay >= gParam.hitDelayMin; | |
119 | responseDelay <= gParam.hitDelayMax; } | |
120 | else | |
121 | { responseDelay >= gParam.missDelayMin; | |
122 | responseDelay <= gParam.missDelayMax; } | |
123 | } | |
124 | ||
125 | constraint pkt2Delay_c | |
126 | { | |
127 | pkt2Delay >= gParam.pkt2DelayMin; | |
128 | pkt2Delay <= gParam.pkt2DelayMax; | |
129 | } | |
130 | ||
131 | ||
132 | task new(PcxPkt reqPkt = null); | |
133 | task loadPkt(reg [145:0] data, integer atPort=99); | |
134 | function reg [145:0] getVector(); | |
135 | task print(integer atPort); | |
136 | task send(integer fastResp=0); | |
137 | function reg [145:0] makeSignature(); | |
138 | task recv(); | |
139 | task createIntr (reg [5:0] thread, // 64 virtual cores | |
140 | reg [1:0] type, | |
141 | reg [5:0] vect); | |
142 | ||
143 | local task printHeader(); | |
144 | task post_randomize(); | |
145 | } | |
146 | ||
147 | ||
148 | task CpxPkt::new (PcxPkt reqPkt = null) { | |
149 | ||
150 | // in base | |
151 | name = "CpxPkt"; | |
152 | super.reqId = 0; | |
153 | super.reqTime = 0; | |
154 | super.pktArrived = 0; | |
155 | ||
156 | if (reqPkt !== null) { | |
157 | // Default init Values for responding to request | |
158 | targetPorts = 1 << reqPkt.cpuId; | |
159 | valid = reqPkt.valid; | |
160 | nc = reqPkt.nc; | |
161 | tid = reqPkt.tid; | |
162 | ccxSourced = reqPkt.ccxSourced; | |
163 | ccxSourced2 = reqPkt.ccxSourced2; | |
164 | addr = reqPkt.addr; //for ldst sync | |
165 | ||
166 | // #ifdef PKT_DEBUG | |
167 | // reqTime = reqPkt.reqTime; // time of request | |
168 | // #endif | |
169 | // #ifdef CCXDEVMEMBFM_DEBUG | |
170 | // reqTime = reqPkt.reqTime; // time of request | |
171 | // #endif | |
172 | } | |
173 | } | |
174 | ||
175 | ||
176 | // load this pkt from a vector | |
177 | task CpxPkt::loadPkt (reg [145:0] dataIn, integer atPort=99) { | |
178 | pktVec = dataIn; | |
179 | '{valid,rtntyp,l2miss,err,nc,tid,wv,wayMMUid,wayf4b,atmIf2,pf,data} = pktVec; | |
180 | arrivalPort = atPort; | |
181 | if (atPort == DEV_NCU) io = 1; | |
182 | } | |
183 | ||
184 | function reg [145:0] CpxPkt::getVector() { | |
185 | getVector = {valid,rtntyp,l2miss,err,nc,tid,wv,wayMMUid,wayf4b,atmIf2,pf,data}; | |
186 | } | |
187 | ||
188 | ||
189 | task CpxPkt::print(integer atPort) | |
190 | { | |
191 | reg vack = 0; | |
192 | reg [8:0] req; | |
193 | integer vcore = 0; | |
194 | integer line = 999; | |
195 | ||
196 | if (atPort < 8) vcore = tid + (8*atPort); | |
197 | else | |
198 | { | |
199 | // will not work well for multicast pkts, look at req | |
200 | if (this.req_wire === 9'bxxxxxxxxx) vcore = 99; | |
201 | else { | |
202 | req = this.req_wire; | |
203 | while (req[0] !== 1 && req !== 0) { | |
204 | vcore++; | |
205 | req = req >> 1; | |
206 | } | |
207 | vcore = tid + (8*vcore); | |
208 | } | |
209 | } | |
210 | ||
211 | ||
212 | printHeader () ; | |
213 | ||
214 | printf ("%9d:", get_time(LO)) ; | |
215 | printf ("|%2d", vcore) ; | |
216 | printf ("|CPX") ; | |
217 | printf ("|%2d", atPort) ; | |
218 | if (req_wire === 9'bxxxxxxxxx) printf ("|---"); | |
219 | else printf ("|%3h", req_wire) ; | |
220 | // printf ("|%3h", req_wire) ; | |
221 | // printf ("|%3h", atm_wire) ; | |
222 | printf ("|%1b", valid) ; | |
223 | ||
224 | case (rtntyp) | |
225 | { | |
226 | CPX_LD,CPX_PREF,CPX_DIAG_LD,CPX_CAS_RTN,CPX_SWAP_RTN: { // 0000 | |
227 | if (pf) printf ("|PREFETCH RTN"); | |
228 | else if (nc & atmIf2) printf ("|SWAP/CAS RTN"); | |
229 | else printf ("|LOAD/DIA RTN"); | |
230 | line = addr[10:4]; tag = addr[39:11]; | |
231 | } | |
232 | CPX_NCU_LD: printf ("|LOAD RTN NCU") ; // 1000 | |
233 | CPX_NCU_IFILL: printf ("|IFILL RTN NC"); // 1001 | |
234 | CPX_IFILL: | |
235 | if (atmIf2) printf ("|IFILL RTN 2 "); | |
236 | else printf ("|IFILL RTN 1 "); | |
237 | CPX_STR_LD: // 0010 | |
238 | { | |
239 | printf ("|STRM LD RTN ") ; | |
240 | vack = 1; | |
241 | } | |
242 | CPX_EVICT : { // 0011 | |
243 | printf ("|EVICT INVAL ") ; | |
244 | line = addr[10:4]; tag = addr[39:11]; | |
245 | } | |
246 | CPX_ST,CPX_DIAG_ST,CPX_CAS_ACK,CPX_SWAP_ACK,CPX_D_INVAL,CPX_I_INVAL: // 0100 | |
247 | { | |
248 | if (atmIf2) printf ("|SWAP/CAS ACK"); | |
249 | else if (data[124:123] == 2'b11) printf ("|ERROR IVAK!!"); | |
250 | else if (data[124] == 1) printf ("|I$ INV ACK "); | |
251 | else if (data[123] == 1) printf ("|D$ INV ACK "); | |
252 | else printf ("|STORE/DI ACK"); | |
253 | vack = 1; | |
254 | line = addr[10:4]; tag = addr[39:11]; | |
255 | } | |
256 | CPX_MMU_RTN : printf ("|MMU LD RTN "); // 0101 | |
257 | CPX_STR_ST : { | |
258 | printf ("|STRM ST ACK "); // 0110 | |
259 | vack = 1; | |
260 | } | |
261 | CPX_INTR : printf ("|INTERRUPT "); // 0111 | |
262 | CPX_ERROR_L2 : printf ("|ERR L2 "); // 1100 | |
263 | CPX_ERROR_SOC : printf ("|ERR SOC "); // 1101 | |
264 | default : printf ("|????????????") ; | |
265 | } | |
266 | ||
267 | printf ("|%3b", l2miss) ; | |
268 | printf ("|%2b", err); | |
269 | printf ("|%2b", nc); | |
270 | printf ("|%1d", tid); | |
271 | printf ("|%2b", wv) ; | |
272 | printf ("|%5b", wayMMUid) ; | |
273 | printf ("|%5b", wayf4b) ; | |
274 | printf ("|%5b", atmIf2) ; | |
275 | printf ("|%2b", pf) ; | |
276 | printf ("|%h_%h", data[127:64],data[63:0]) ; | |
277 | #ifdef CCXDEVMEMBFM_DEBUG | |
278 | printf ("|%3d", reqId); | |
279 | printf ("|%10h", addr); | |
280 | printf ("|%2h/%8h/%1h", line,tag,lineWay); | |
281 | // printf ("|%8d", reqTime); | |
282 | #endif | |
283 | printf ("\n") ; | |
284 | ||
285 | if (vack) printf ("%9d:|--|CPX|Vack -> CPU=%0d, addr[11:0]=%h, invVec=%h, mask=%h, invI/D=%h, BIS/MAid=%0b\n", | |
286 | get_time(LO),data[120:118],{data[117:112],data[122:121],data[104],3'b000}, | |
287 | data[95:64],data[103:96],data[124:123],data[125]); | |
288 | else printf("\n"); | |
289 | ||
290 | printCount++ ; | |
291 | } | |
292 | ||
293 | task CpxPkt::printHeader() | |
294 | { | |
295 | printf ("\n%9d:", get_time(LO)) ; | |
296 | printf ("|VC") ; | |
297 | printf ("|CPX"); | |
298 | printf ("|At") ; | |
299 | printf ("|Req"); | |
300 | // printf ("|Atm"); | |
301 | printf ("|V") ; | |
302 | printf ("|Type ") ; | |
303 | printf ("|Mis"); | |
304 | printf ("|Er"); | |
305 | printf ("|NC") ; | |
306 | printf ("|T") ; | |
307 | printf ("|WV") ; | |
308 | printf ("|WayMM") ; | |
309 | printf ("|Way4b") ; | |
310 | printf ("|AtmI2") ; | |
311 | printf ("|Pf") ; | |
312 | printf ("|Data ") ; | |
313 | #ifdef CCXDEVMEMBFM_DEBUG | |
314 | printf ("|RID"); | |
315 | printf ("|Req Addr "); | |
316 | printf ("|DL/Tag/Way"); | |
317 | // printf ("|Req Time"); | |
318 | #endif | |
319 | printf ("\n") ; | |
320 | } | |
321 | ||
322 | ||
323 | task CpxPkt::send(integer fastResp=0) { | |
324 | integer i; | |
325 | pktVec = {valid,rtntyp,l2miss,err,nc,tid,wv,wayMMUid,wayf4b,atmIf2,pf,data}; | |
326 | if (rtntyp == CPX_IFILL) { | |
327 | if (atmIf2 == 0) atomic = 1; | |
328 | else atomic = 2; | |
329 | } | |
330 | ||
331 | for (i=8;i<=16;i++) { | |
332 | if (sendPorts[i]) { | |
333 | if (gCcxDevice[i] == null) | |
334 | error("Can't send packet from a nonExistant BFM! \n"); | |
335 | gCcxDevice[i].send(this,fastResp); | |
336 | } | |
337 | } | |
338 | } | |
339 | ||
340 | ||
341 | // makeSignature returns certain concatinated fields of the packet. | |
342 | // called by BFM that needs it. | |
343 | function reg [145:0] CpxPkt::makeSignature() { | |
344 | makeSignature = {10'b0,valid,rtntyp,tid,data[127:0]}; | |
345 | } | |
346 | ||
347 | ||
348 | // BFM knows everything that it needs from this packet, | |
349 | // especially the signature for packet matching. | |
350 | // This packet has the signature and recvPorts. | |
351 | // Note that recvPkt call inside the receiving BFM may be blocking review | |
352 | task CpxPkt::recv() { | |
353 | ||
354 | if (manyHot(this.targetPorts) !== 1) | |
355 | error("Need to set a single target port in targetPorts var! \n"); | |
356 | ||
357 | // hand off | |
358 | gCcxDevice[whichHot(this.targetPorts)].recv(this); | |
359 | } | |
360 | ||
361 | ||
362 | ||
363 | //This task will call the cancelRecv in the BFMS | |
364 | // task cancelRecv(integer revcPortIn) | |
365 | // { | |
366 | // gCcxDevice[recvPortIn].cancelRecv(this); | |
367 | // } | |
368 | ||
369 | ||
370 | ||
371 | // Create Interrupt Pkt | |
372 | task CpxPkt::createIntr (reg [5:0] thread, // 64 virtual cores | |
373 | reg [1:0] type, | |
374 | reg [5:0] vect) { | |
375 | ||
376 | targetPorts = 1 << thread[5:3]; | |
377 | valid = 1'b1; | |
378 | rtntyp = CPX_INTR; | |
379 | l2miss = 0; | |
380 | err = 0; | |
381 | nc = 0; | |
382 | tid = thread[2:0]; | |
383 | wv = 0; | |
384 | wayMMUid = 0; | |
385 | wayf4b = 0; | |
386 | atmIf2 = 0; | |
387 | pf = 0; | |
388 | data[63:0] = {48'b0,type,thread[5:0],2'b0,vect}; | |
389 | //printf("%0d CpxPkt createIntr done, data = %0h\n", get_cycle(), data); | |
390 | ||
391 | } | |
392 | ||
393 | // // can't refer to array indexes when weighting constraints | |
394 | // // so have to play this game first. lame! | |
395 | // task CpxPkt::pre_randomize() { | |
396 | // this.hitRateParm = gParam.hitRate[sendPort-8]; | |
397 | // this.hitDelayMinParm = gParam.hitDelayMin[sendPort-8]; | |
398 | // this.hitDelayMaxParm = gParam.hitDelayMax[sendPort-8]; | |
399 | // this.missDelayMinParm = gParam.missDelayMin[sendPort-8]; | |
400 | // this.missDelayMaxParm = gParam.missDelayMax[sendPort-8]; | |
401 | // this.pkt2DelayMinParm = gParam.pkt2DelayMin[sendPort-8]; | |
402 | // this.pkt2DelayMaxParm = gParam.pkt2DelayMax[sendPort-8]; | |
403 | // } | |
404 | ||
405 | task CpxPkt::post_randomize() { | |
406 | // always set this if we "miss" | |
407 | // May clear it later for certain return types | |
408 | l2miss = ~hit; | |
409 | } | |
410 | ||
411 |