Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / fc / vera / cpxorder.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: cpxorder.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<defines.vri>
39#include<ccx.vri>
40#include<defines.vri>
41#include<cpxorder_ports_binds.vrh>
42//#include<iop_rtl.h>
43// #include<ccm_top.if.vrh>
44#include<std_display_class.vrh>
45#include<std_display_defines.vri>
46#include "globals.vri"
47
48
49class ccmCpxPkt {
50
51 integer index;
52 bit [CPX_WIDTH-1:0] packet;
53}
54
55// declare list of ccmCpxPkt objects
56MakeVeraList(ccmCpxPkt)
57
58// This class is an ordered list. All packets should be removed from this list
59// in the same order as they were added to this list.
60class ccmCpxPktFIFO {
61
62 integer core, indexCounter;
63 VeraList_ccmCpxPkt List;
64 VeraListIterator_ccmCpxPkt I;
65 ccmCpxPkt p;
66
67
68 task new(integer core) {
69 this.core = core;
70 indexCounter = 0;
71 List = new();
72 }
73
74 task Add(ccmCpxPkt packet) {
75
76 // assign an identifying number to the packet
77 packet.index = indexCounter++;
78
79 // add packet to back of list.
80 List.push_back(packet);
81
82 return;
83 }
84
85 task Remove(bit [CPX_WIDTH-1:0] packet) {
86 // packets issued in PerformEndChecks() are not added to OqOrder and therefore
87 // cannot be removed
88 if(List.empty())
89 return;
90
91 // packet to be removed must be the p on the list
92 p = List.front();
93
94 if(p.packet =?= packet)
95 List.pop_front();
96 else {
97 //error("%0d: CPXORDER ERROR: Packet received (%x) is not the first (%x) on Core %0d's list\n", get_time(LO), packet, p.packet, core);
98 PR_ERROR("CPXORDER", MON_ERR, psprintf ("%0d: CPXORDER ERROR: Packet received (%x) is not the first (%x) on Core %0d's list\n", get_time(LO), packet, p.packet, core));
99 }
100 return;
101 }
102
103 function integer LastIndex() {
104
105 p = List.back();
106 LastIndex = p.index;
107
108 return;
109 }
110
111 task Replace(integer index, bit [CPX_WIDTH-1:0] packet) {
112
113 if(!List.empty()) {
114 I = List.start();
115 p = I.data();
116
117 while(p.index != index) {
118 I.next();
119 p = I.data();
120 }
121
122 p.packet = packet;
123 }
124 }
125
126 task Reset() {
127 indexCounter = 0;
128 List.clear();
129 }
130}
131
132
133/////////////////////////////////////////////////////////////////////////////////
134
135task MonitorCPX() {
136// local StandardDisplay dbg;
137 string myname;
138 shadow integer i, j, k;
139 integer reqcount[72];
140 bit [7:0] sctag_cpx_req_cq;
141 bit [7:0] sctag_cpx_ifill2_cq[9];
142
143 // a single pulse of bit j of request[i] represents 1 packet being sent from Bank i to Core j.
144 bit [7:0] request[9];
145 bit [7:0] request_d1[9];
146 bit [8:0] atom = 0, atom_d1 = 0;
147 // a single pulse of bit j of ifill2[i] represents 1 IFILL_RET2 being sent from Bank i to Core j.
148 bit [7:0] ifill2[9];
149 bit [7:0] ifill2_d1[9];
150 bit [145:0] io_cpx_data_ca;
151 shadow bit [7:0] scratch;
152
153 l2port lp[9];
154 cpxport cp[8];
155 ccmCpxPktFIFO Core[8];
156 ccmCpxPkt packet;
157
158
159 // bind ports
160 cp[0] = cpxbind_0;
161 cp[1] = cpxbind_1;
162 cp[2] = cpxbind_2;
163 cp[3] = cpxbind_3;
164 cp[4] = cpxbind_4;
165 cp[5] = cpxbind_5;
166 cp[6] = cpxbind_6;
167 cp[7] = cpxbind_7;
168 lp[0] = l2bind_0;
169 lp[1] = l2bind_1;
170 lp[2] = l2bind_2;
171 lp[3] = l2bind_3;
172 lp[4] = l2bind_4;
173 lp[5] = l2bind_5;
174 lp[6] = l2bind_6;
175 lp[7] = l2bind_7;
176 lp[8] = iobind;
177
178 //dbg = new;
179
180 // initialize variables
181 for(i=0; i<9; i++) {
182 sctag_cpx_ifill2_cq[i] = 8'b0;
183 request_d1[i] = 8'b0;
184 request[i] = 8'b0;
185 ifill2_d1[i] = 8'b0;
186 ifill2[i] = 8'b0;
187
188 for(j=0; j<8; j++)
189 reqcount[i*8 + j] = 0;
190 }
191
192 for(j=0; j<8; j++)
193 Core[j] = new(j);
194
195 myname = "CPXORDER";
196
197 PR_NORMAL(myname, MON_NORMAL, psprintf("%0d: CPX Ordering Monitor started\n", get_time(LO)));
198 //printf("%0d: CPX Ordering Monitor started\n", get_time(LO));
199
200
201 fork
202 {
203 while(1) {
204 // if reset is active, drop all requests
205 if(cpxorder.ccx_gdbginit_l == 1'b0) {
206 for(i=0; i<9; i++) {
207 sctag_cpx_ifill2_cq[i] = 8'b0;
208 request_d1[i] = 8'b0;
209 request[i] = 8'b0;
210 ifill2_d1[i] = 8'b0;
211 ifill2[i] = 8'b0;
212
213 for(j=0; j<8; j++)
214 reqcount[i*8 + j] = 0;
215 }
216
217 for(j=0; j<8; j++)
218 Core[j].Reset();
219
220 @(posedge cpxorder.ccx_gdbginit_l);
221 }
222
223 /// Determine if a packet is being passed to the CPX by each bank in this cycle
224 // 8 banks + io
225 for(i=0; i<9; i++) {
226 sctag_cpx_req_cq = lp[i].$sctag_cpx_req_cq;
227
228 // add to reqcount[dest_core] for each request if reqcount[dest_core] is less than 3
229 if(sctag_cpx_req_cq != 8'b0) {
230 for(j=0; j<8; j++) {
231 if(sctag_cpx_req_cq[j] && reqcount[i*8+j] < 3) {
232 reqcount[i*8+j]++;
233 }
234 }
235 }
236
237 // subtract from reqcount[dest_core] if grant for dest_core is given
238 if(lp[i].$cpx_sctag_grant_cx != 0) {
239 for(j=0; j<8; j++) {
240 if(lp[i].$cpx_sctag_grant_cx[j])
241 reqcount[i*8+j]--;
242 }
243 }
244
245 if(sctag_cpx_req_cq != 8'b0 || sctag_cpx_ifill2_cq[i] != 8'b0) {
246 if(reqcount[i*8] < 3 && reqcount[i*8+1] < 3 && reqcount[i*8+2] < 3 && reqcount[i*8+3] < 3 &&
247 reqcount[i*8+4] < 3 && reqcount[i*8+5] < 3 && reqcount[i*8+6] < 3 && reqcount[i*8+7] < 3) {
248 // signifies that this packet(s) is/are to be passed to the CPX
249 request[i] = sctag_cpx_req_cq;
250
251 // IFILL_RET1
252 if(lp[i].$sctag_cpx_atom_cq) {
253 // signifies that the next packet to be passed to the CPX is an IFILL_RET1
254 atom[i] = 1'b1;
255
256 // remember that next request from the same bank to the same core is an IFILL_RET2 request
257 // (since sctag_cpx_req_cq is not asserted for IFILL_RET2 packets)
258 sctag_cpx_ifill2_cq[i] = sctag_cpx_req_cq;
259
260 // increment reqcount[dest_core] for IFILL_RET2 after IFILL_RET1 is dequeued
261 for(j=0; j<8; j++) {
262 if(sctag_cpx_req_cq[j])
263 reqcount[i*8+j]++;
264 }
265 }
266 // all other packets
267 else {
268 ifill2[i] = sctag_cpx_ifill2_cq[i];
269 sctag_cpx_ifill2_cq[i] = 8'b0;
270 }
271 } // if(reqcount[i*8] < 3 && ... && reqcount[i*8+7] < 3)
272 } // if(sctag_cpx_req_cq[i] != 8'b0 || sctag_cpx_ifill2_cq[i] != 8'b0)
273 } // for(i=0; i<9; i++)
274
275
276 /// Arrange CPX packets in the order that each Core is supposed to receive them
277 if(request[0] != 8'b0 || request[1] != 8'b0 || request[2] != 8'b0 || request[3] != 8'b0 ||
278 request[4] != 8'b0 || request[5] != 8'b0 || request[6] != 8'b0 || request[7] != 8'b0 | request[8] != 8'b0) {
279 fork
280 {
281 // direction of priority is determined 1 cycle after the request is asserted
282 if(i==8)
283 io_cpx_data_ca = lp[8].$sctag_cpx_data_ca;
284 @(posedge cpxorder.ccx_rclk);
285
286 for(j=0; j<8; j++) {
287 // ascending priority (bank0 > bank2 ... bank7 > NCU)
288 if(cp[j].$dir_a) {
289 for(i=0; i<9; i++) {
290 scratch = request_d1[i];
291
292 if(scratch[j]) {
293 packet = new();
294 if(i==8)
295 //packet.packet = lp[i].$sctag_cpx_data_ca ^ 146'b1;
296 packet.packet = io_cpx_data_ca;
297 else
298 packet.packet = lp[i].$sctag_cpx_data_ca;
299
300 Core[j].Add(packet);
301 PR_INFO(myname, MON_INFO, psprintf("CPXORDER: Added %x from Bank%0d to Core%0d\n", packet.packet, i, j));
302 //printf("CPXORDER: Added %x from Bank%0d to Core%0d\n", packet.packet, i, j);
303
304 if(atom_d1[i]) {
305 packet = new();
306 Core[j].Add(packet); // add empty packet to list
307 k = Core[j].LastIndex();
308
309 fork
310 {
311 @(posedge cpxorder.ccx_rclk);
312 while(1) {
313 scratch = ifill2_d1[i];
314 if(scratch[j])
315 break;
316 @(posedge cpxorder.ccx_rclk);
317 }
318 Core[j].Replace(k, lp[i].$sctag_cpx_data_ca);
319
320 PR_INFO(myname, MON_INFO, psprintf("CPXORDER: Replaced %x from Bank%0d to Core%0d\n", lp[i].$sctag_cpx_data_ca, i, j));
321 //printf("CPXORDER: Replaced %x from Bank%0d to Core%0d\n", lp[i].$sctag_cpx_data_ca, i, j);
322 }
323 join none
324 }
325 }
326 }
327 }
328 // descending priority ( NCU > bank7 > ... bank2 > bank1 > bank0)
329 else {
330 for(i=8; i>=0; i--) {
331 scratch = request_d1[i];
332
333 if(scratch[j]) {
334 packet = new();
335 if(i==8)
336 //packet.packet = lp[i].$sctag_cpx_data_ca ^ 145'b1;
337 packet.packet = io_cpx_data_ca;
338 else
339 packet.packet = lp[i].$sctag_cpx_data_ca;
340 Core[j].Add(packet);
341 PR_INFO(myname, MON_INFO, psprintf("CPXORDER: Added %x from Bank%0d to Core%0d\n", packet.packet, i, j));
342 //printf("CPXORDER: Added %x from Bank%0d to Core%0d\n", packet.packet, i, j);
343
344 if(atom_d1[i]) {
345 packet = new();
346 Core[j].Add(packet); // add empty packet to list
347 k = Core[j].LastIndex();
348
349 fork
350 {
351 @(posedge cpxorder.ccx_rclk);
352 while(1) {
353 scratch = ifill2_d1[i];
354 if(scratch[j])
355 break;
356 @(posedge cpxorder.ccx_rclk);
357 }
358 Core[j].Replace(k, lp[i].$sctag_cpx_data_ca);
359 PR_INFO(myname, MON_INFO, psprintf("CPXORDER: Replaced %x from Bank%0d to Core%0d\n", lp[i].$sctag_cpx_data_ca, i, j));
360 //printf("CPXORDER: Replaced %x from Bank%0d to Core%0d\n", lp[i].$sctag_cpx_data_ca, i, j);
361 }
362 join none
363 }
364 }
365 }
366 }
367 } // for(j=0; j<8; j++)
368 }
369 join none
370 }
371
372
373 /// Check that CPX packets arrive at the Cores in the correct order
374 // (packets from the NCU are excluded)
375 for(j=0; j<8; j++) {
376 if(cp[j].$cpx_spc_data_cx2[CPX_VALID]) {
377 Core[j].Remove(cp[j].$cpx_spc_data_cx2);
378 PR_INFO(myname, MON_INFO, psprintf("CPXORDER: Removed %x from Core%0d\n", cp[j].$cpx_spc_data_cx2, j));
379 //printf("CPXORDER: Removed %x from Core%0d\n", cp[j].$cpx_spc_data_cx2, j);
380 }
381 }
382
383
384 /// Stage request signals to the next cycle (on negedge cpxorder.ccx_rclk to prevent possible
385 /// race between forked threads)
386 @(negedge cpxorder.ccx_rclk);
387
388 for(i=0; i<9; i++) {
389 request_d1[i] = request[i];
390 request[i] = 8'b0;
391 ifill2_d1[i] = ifill2[i];
392 ifill2[i] = 8'b0;
393 }
394 atom_d1 = atom;
395 atom = 9'b0;
396
397
398 @(posedge cpxorder.ccx_rclk);
399 } // while(1)
400 }
401 join none
402}