Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: irritator.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 | ||
39 | #include <globals.vri> | |
40 | ||
41 | #include <baseParamsClass.vrh> | |
42 | #include <sparcParams.vrh> | |
43 | #include <baseUtilsClass.vrh> | |
44 | #include <sparcBenchUtils.vrh> | |
45 | #include <std_display_class.vrh> | |
46 | #include <basePktClass.vrh> | |
47 | #include <cpxPktClass.vrh> | |
48 | #include <pcxPktClass.vrh> | |
49 | #include <ccxDevBaseBFM.vrh> | |
50 | #include <ccxDevMemBFM.vrh> | |
51 | #include <ccxDevSpcBFM.vrh> | |
52 | #include <memArray.vrh> | |
53 | #include <ccx_tag_class.vrh> | |
54 | #include <baseCCXtrans.vrh> | |
55 | ||
56 | #define CLASSNAME Irritator | |
57 | #define CLASSNAMEQ "Irritator" | |
58 | ||
59 | ||
60 | //gCcxDevice[] 0-16 !== null | |
61 | ||
62 | class CLASSNAME extends BaseCCXtrans { | |
63 | ||
64 | local string className = "Irritator"; | |
65 | ||
66 | // rands | |
67 | ||
68 | // end rands | |
69 | ||
70 | ||
71 | task new(StandardDisplay dbgHndl, reg l2BFMs); | |
72 | task decker(); | |
73 | task evictFlood(); | |
74 | task bufferFlood(); | |
75 | task randStores(); | |
76 | task randStLd(); | |
77 | task randLoads(); | |
78 | } | |
79 | ||
80 | ||
81 | task CLASSNAME::new(StandardDisplay dbgHndl, reg l2BFMs) { | |
82 | super.new(dbgHndl, l2BFMs); | |
83 | srandom(gSeed,this); | |
84 | ||
85 | // void = randomize(); | |
86 | ||
87 | anyMemPort = gCpxPort[0]; | |
88 | anySpcPort = gPcxPort[0]; | |
89 | ||
90 | fork { | |
91 | evictFlood(); | |
92 | bufferFlood(); | |
93 | randStores(); | |
94 | randStLd(); | |
95 | randLoads(); | |
96 | } join none | |
97 | ||
98 | } | |
99 | ||
100 | ||
101 | ||
102 | ////////////////////////////////////////////////////// | |
103 | // higher level tasks | |
104 | ////////////////////////////////////////////////////// | |
105 | ||
106 | // enqueue a bunch of noop evictions for directed coverage. | |
107 | // every source sends to every FloodTarget. No checking. | |
108 | // +evictFloodAmount, +evictFloodFreq, +evictFloodTargets | |
109 | task CLASSNAME::evictFlood() | |
110 | { | |
111 | ||
112 | integer amount; | |
113 | ||
114 | if (! gParam.evictFloodFreq || | |
115 | ! gParam.evictFloodAmount || | |
116 | ! gParam.evictFloodTargets) return; | |
117 | ||
118 | if (gCcxDevice[8] == null || gCcxDevice[16] == null) | |
119 | PR_ERROR(CLASSNAMEQ, MON_ERROR, | |
120 | psprintf ("evictFlood task needs L2 BFMs and NCU BFM!")); | |
121 | ||
122 | amount = gParam.evictFloodAmount; | |
123 | repeat (500) @(posedge anyMemPort.$clk); | |
124 | while (amount) { | |
125 | repeat (gParam.evictFloodFreq) @(posedge anyMemPort.$clk); | |
126 | repeat (2) bogusEvict(gParam.evictFloodTargets, 8'hff); | |
127 | repeat (2) super.sendIntr(0, 3, 0); | |
128 | amount--; | |
129 | } | |
130 | } | |
131 | ||
132 | ||
133 | // For CCX coverage activity. 2 ifill resp followed by 1 eviction. (ncu does 3 interrupts) | |
134 | // Will enqueue a bunch of ifill responses and noop evictions for directed coverage. | |
135 | // Every source sends to ONE FloodTarget, all at once. No checking. | |
136 | // | |
137 | // bufferFloodFreq = getParam(DEC, "bufferFloodFreq", 0, 100000, 0); | |
138 | // bufferFloodAmount = getParam(DEC, "bufferFloodAmount", 1, 100, 10); | |
139 | // bufferFloodTarget = getParam(HEX, "bufferFloodTarget", 1, 7, 7); | |
140 | task CLASSNAME::bufferFlood() | |
141 | { | |
142 | ||
143 | integer amount; | |
144 | ||
145 | if (! gParam.bufferFloodFreq || | |
146 | ! gParam.bufferFloodAmount || | |
147 | ! gParam.bufferFloodTarget) return; | |
148 | ||
149 | if (gCcxDevice[8] == null || gCcxDevice[16] == null) | |
150 | PR_ERROR(CLASSNAMEQ, MON_ERROR, | |
151 | psprintf ("bufferFlood task needs L2 BFMs and NCU BFM!")); | |
152 | ||
153 | amount = gParam.bufferFloodAmount; | |
154 | repeat (500) @(posedge anyMemPort.$clk); | |
155 | while (amount) { | |
156 | repeat (gParam.bufferFloodFreq) @(posedge anyMemPort.$clk); | |
157 | bogusEvict(1<<gParam.bufferFloodTarget, 8'h0C); | |
158 | @(posedge anyMemPort.$clk); | |
159 | bogusEvict(1<<gParam.bufferFloodTarget, 8'h30); | |
160 | super.sendIntr(gParam.bufferFloodTarget<<3, 3, 0); | |
161 | @(posedge anyMemPort.$clk); | |
162 | super.sendIntr(gParam.bufferFloodTarget<<3, 3, 0); | |
163 | super.sendIntr(gParam.bufferFloodTarget<<3, 3, 0); | |
164 | // pre pkt | |
165 | ifillPair(gParam.bufferFloodTarget, 8'hff, | |
166 | {urandom(),urandom()},{urandom(),urandom()}); | |
167 | bogusEvict(1<<gParam.bufferFloodTarget, 8'hff); | |
168 | bogusEvict(1<<gParam.bufferFloodTarget, 8'hff); | |
169 | amount--; | |
170 | } | |
171 | } | |
172 | ||
173 | ||
174 | ||
175 | ||
176 | // From all L2 ports, broadcast 1 eviction packet (with unique signature | |
177 | // for each source) to every core. All core targets should have the exact | |
178 | // packet stream coming out at the exact same time. Each send packet will | |
179 | // go to 8 cores, each core will receive 8 packets. Will be 64 destination | |
180 | // packets from 8 source packets. | |
181 | task CLASSNAME::decker() { | |
182 | ||
183 | CpxPkt sndPkt[8]; | |
184 | CpxPkt recvPkt[8][8]; | |
185 | CpxPkt finalOrder[8][8]; | |
186 | integer startTime; | |
187 | shadow integer sp,rp; | |
188 | reg [127:0] rand128, tmp128; | |
189 | ||
190 | ||
191 | // create array of 8 unique source packets | |
192 | for (sp=0;sp<8;sp++) { | |
193 | sndPkt[sp] = new(); | |
194 | rand128 = {urandom(),urandom(),urandom(),urandom()}; | |
195 | sndPkt[sp].tid = rand128[2:0]; | |
196 | sndPkt[sp].sendPorts = 1 << 8+sp; | |
197 | sndPkt[sp].rtntyp = CPX_EVICT; | |
198 | sndPkt[sp].rtntypU = U_CPX_EVICT; | |
199 | sndPkt[sp].addr = rand128[39:0]; | |
200 | sndPkt[sp].targetPorts = 8'hff; | |
201 | sndPkt[sp].data = rand128; | |
202 | } | |
203 | ||
204 | // register the 8 unique source packets | |
205 | // at each destination. 64 total. | |
206 | for (sp=0;sp<8;sp++) { | |
207 | for (rp=0;rp<8;rp++) { | |
208 | recvPkt[sp][rp] = new(); | |
209 | recvPkt[sp][rp].signature = sndPkt[sp].makeSignature(); | |
210 | recvPkt[sp][rp].targetPorts = 1<<rp; | |
211 | recvPkt[sp][rp].recv(); // register arrival w/ BFM | |
212 | } | |
213 | } | |
214 | ||
215 | ||
216 | // initiator, 8 unique packets | |
217 | for (sp=0;sp<8;sp++) { | |
218 | sndPkt[sp].send(1); // let fly | |
219 | PR_NORMAL(CLASSNAMEQ, MON_NORMAL, | |
220 | psprintf ("Sending random EVICTION pkt from 0b%b to 0b%b, vec=0x%h", | |
221 | sndPkt[sp].sendPorts, sndPkt[sp].targetPorts, | |
222 | sndPkt[sp].getVector())); | |
223 | } | |
224 | ||
225 | // for checker. Collect packets at destination. | |
226 | // for each send port, collect 8 destination pkts. | |
227 | for (sp=0;sp<8;sp++) { // for each send port | |
228 | for (rp=0;rp<8;rp++) { // wait on/collect 8 packets in a row | |
229 | fork { | |
230 | wait_var(recvPkt[sp][rp].pktArrived); // 64 of these | |
231 | // compare sndPkt[sp] to recvPkt[sp][rp] | |
232 | if (recvPkt[sp][rp].makeSignature() !== sndPkt[sp].makeSignature()) | |
233 | PR_ERROR(CLASSNAMEQ, MON_ERROR, | |
234 | psprintf ("mismatch error, pkt from port %0d, to port %0d", sp, rp)); | |
235 | finalOrder[sp][rp] = recvPkt[sp][rp]; | |
236 | } join none | |
237 | } | |
238 | } | |
239 | wait_child(); // wait for 64 pkts to arrive | |
240 | ||
241 | ||
242 | // now make sure that every recv port got the same packets in | |
243 | // the same order at the same time. Order is implied in the finalOrder array. | |
244 | // Time is stored in the recieved packets. Compare time along with order. | |
245 | for (rp=0;rp<8;rp++) { // for each recv port | |
246 | for (sp=0;sp<7;sp++) { // make sure all packest are same for that clock | |
247 | ||
248 | // arrivial times (as loaded into finalOrder array) must inc by one, | |
249 | // or dec by one depending on arb direction. | |
250 | if (sp == 0 && rp == 0) startTime = finalOrder[rp][sp].arrivalTime; | |
251 | ||
252 | if (finalOrder[rp][sp].getVector() !== finalOrder[rp][sp+1].getVector() || | |
253 | finalOrder[rp][sp].arrivalTime !== finalOrder[rp][sp+1].arrivalTime || | |
254 | (finalOrder[rp][sp].arrivalTime !== startTime+rp && finalOrder[rp][sp].arrivalTime !== startTime-rp)) | |
255 | PR_ERROR(CLASSNAMEQ, MON_ERROR, | |
256 | psprintf ("decker ORDER/TIME mismatch error, [%0d][%0d] not == to [%0d][%0d]", rp, sp, rp, sp+1)); | |
257 | printf("pkt sp=%0d,rp=%0d: vec=%h, time=%0d\n", rp, sp, finalOrder[rp][sp].getVector(), finalOrder[rp][sp].arrivalTime); | |
258 | } | |
259 | printf("pkt sp=%0d,rp=%0d: vec=%h, time=%0d\n", rp, sp, finalOrder[rp][sp].getVector(), finalOrder[rp][sp].arrivalTime); | |
260 | } | |
261 | ||
262 | } | |
263 | ||
264 | ||
265 | // send a bunch of store packets | |
266 | // irritStFreq | |
267 | // irritStAdr1 | |
268 | // irritStAdr2 | |
269 | task CLASSNAME::randStores() { | |
270 | ||
271 | integer i; | |
272 | ||
273 | // if (! gParam.irritStFreq) return; | |
274 | // spcCheck("randStores"); | |
275 | ||
276 | ||
277 | } | |
278 | ||
279 | ||
280 | // send a bunch of load packets. This will mess up a real | |
281 | // L2/core if the packet core is incorrect (same as real core)! | |
282 | // irritLdFreq | |
283 | // irritLdAdr1 | |
284 | // irritLdAdr2 | |
285 | task CLASSNAME::randLoads() { | |
286 | ||
287 | integer i; | |
288 | PcxPkt pkt; | |
289 | reg [31:0] rnd; | |
290 | ||
291 | ||
292 | // // if (! gParam.irritLdFreq) return; | |
293 | // spcCheck("randLoads"); | |
294 | // | |
295 | // rnd = urandom(); | |
296 | // | |
297 | // // create load pkt | |
298 | // pkt = new(); | |
299 | // | |
300 | // pickCore(pkt.cpuId, pkt.sendPorts); | |
301 | // pkt.nc = 0; | |
302 | // pkt.inv = 0; | |
303 | // pkt.pf = 0; | |
304 | // pkt.l1wayBis = rnd[2:0]; | |
305 | // pkt.l1wayMMUid = rnd[5:3]; | |
306 | // pkt.size = ; | |
307 | // pkt.tid = random(); | |
308 | // pkt.rqtyp = | |
309 | // pkt.rqtypU = | |
310 | // pkt.addr = | |
311 | // pkt.targetPorts = | |
312 | // | |
313 | // // end to end checking | |
314 | // // pktRecv.signature = pkt.makeSignature(); | |
315 | // // pktRecv.targetPorts = | |
316 | // // pktRecv.recv(); | |
317 | // | |
318 | // | |
319 | // pkt.send(1); // doit | |
320 | // | |
321 | // PR_NORMAL(CLASSNAMEQ, MON_NORMAL, | |
322 | // psprintf ("Sending bogus EVICTION pkt to targets=0b%b, a=0x%h, vec=0x%h", | |
323 | // pkt.targetPorts,0,0)); | |
324 | ||
325 | } | |
326 | ||
327 | ||
328 | // send a bunch of checked st -> ld packet pairs | |
329 | // irritLdStFreq | |
330 | // irritLdStAdr1 | |
331 | // irritLdStAdr2 | |
332 | task CLASSNAME::randStLd() { | |
333 | ||
334 | integer i; | |
335 | ||
336 | // if (! gParam.irritLdStFreq) return; | |
337 | // spcCheck("randStLd"); | |
338 | ||
339 | ||
340 | } |