Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / fc / vera / classes / ssi.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: ssi.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 "plusArgMacros.vri"
38#include "globals.vri"
39
40#include "std_display_class.vrh"
41#include "memArray.vrh"
42#include "ssi.if.vrh"
43#include "ssi.vrh"
44
45#define CLASSNAME SSI
46#define CLASSNAMEQ "SSI"
47
48class CLASSNAME {
49
50 local string className = "SSI";
51 local StandardDisplay dbg;
52 local reg ssi_mon;
53 local string dispmonScope = "SSI";
54 ssi_iport ncu;
55 ssi_oport ssi;
56 integer send, send_int, send_parity_error;//Synchronization variables
57 integer ssi_timeout, ssi_parity_error, ssi_side_effect;
58 reg [27:0] ncu_addr;
59 reg [63:0] ncu_data;
60 reg [2:0] ncu_cmd;
61 reg [63:0] ssi_int_soft, ssi_int_parity, ssi_int_mask, ssi_response_latency;//These are shadow registers
62 task new(StandardDisplay dbgHndl, ssi_iport ncu, ssi_oport ssi);
63 task Rcv();
64 task Send();
65 task Int();
66 task SsiMon();
67 task SsiDem();
68 task pulse_ssi_int_l(integer pulsedelay, integer pulsewidth);
69 task generate_pulse(integer pulsedelay, integer pulsewidth);
70// task GPIO();
71}
72
73
74task CLASSNAME::new(StandardDisplay dbgHndl, ssi_iport ncu, ssi_oport ssi) {
75 this.ncu = ncu;
76 this.ssi = ssi;
77 this.send = 0;
78 this.send_int = 0;
79 this.send_parity_error = 0;
80 this.ssi_timeout = 0;
81 this.ssi_parity_error = 0;
82 this.ssi_side_effect = 0;
83 this.dbg = dbgHndl;
84 this.ssi_mon = 0;
85 if (mChkPlusarg(ssi_mon) || mChkPlusarg(SSI_MON)) ssi_mon = 1;
86 fork
87 ssi.$data = 1'b0;
88 ssi.$int_l = 1'b1;
89 SsiDem();
90 join none
91}
92
93/*
94 * Tasks for SSI user event generation
95 */
96task CLASSNAME::pulse_ssi_int_l(integer pulsedelay, integer pulsewidth) {
97 fork
98 generate_pulse(pulsedelay, pulsewidth);
99 join none
100}
101
102task CLASSNAME::generate_pulse(integer pulsedelay, integer pulsewidth) {
103 integer i;
104 //breakpoint;
105 for(i=0; i<=pulsedelay; i++) {
106 ssi.$int_l = 1;
107 @(posedge ncu.$clk);
108 }
109
110 for(i=0; i<=pulsewidth; i++) {
111 ssi.$int_l = 0;
112 @(posedge ncu.$clk);
113 }
114
115 ssi.$int_l = 1;
116 @(posedge ncu.$clk);
117}
118
119/*
120 * SSI monitors
121 */
122task CLASSNAME::SsiMon() {
123 while(1) {
124 @(posedge ncu.$clk);
125 printf("SSI_PINS: SSI_INT %x\n", ssi.$int_l);
126 }
127}
128
129
130/*
131 *Main process control
132 */
133task CLASSNAME::SsiDem() {
134 while(1) {
135 // wait_var(reset);
136 // wait_var(reset);
137 // wait_var(reset);
138 // wait_var(reset);
139 @(posedge ncu.$clk);
140 // wait for reset low
141 // while(ncu.$reset) {
142 // @(posedge ncu.$clk);
143 // }
144 if (ncu.$reset !== 0) @(negedge ncu.$reset);
145 fork
146 Rcv();
147 Send();
148 Int();
149 join none
150 @(posedge ncu.$clk);
151 // wait for reset high
152 // while(ncu.$reset != 1) {
153 // @(posedge ncu.$clk);
154 // }
155 if (ncu.$reset !== 1) @(posedge ncu.$reset);
156 terminate;
157 } // while 1
158}
159
160/*
161 * Main Rcv fuction
162 */
163
164task CLASSNAME::Rcv() {
165 integer i, rcv_data_width;
166 reg parity;
167 reg [63:0] tmp_data;
168
169 while (1) {
170 while (ncu.$data != 1) @(posedge ncu.$clk);
171 //printf ("SSI: %d: NCU requesting data %h\n", get_time(LO), ncu.$data);
172 //breakpoint;
173 ncu_addr = 28'b0;
174 ncu_data = 64'b0;
175 ncu_cmd = 3'b0;
176 for (i=2; i>=0; i--) {
177 @(posedge ncu.$clk);
178 ncu_cmd[i] = ncu.$data;
179 //printf("SSI: MOSI = %h i=%d\n", ncu.$data, i);
180 }
181
182 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Rcv: NCU cmd = 0x%h (read = %0d, size = %0d bytes)", ncu_cmd, ncu_cmd[2], 1 << ncu_cmd[1:0]));
183
184 for (i=27; i>=0; i--) {
185 @(posedge ncu.$clk);
186 ncu_addr[i] = ncu.$data;
187 //printf("SSI: MOSI = %h i=%d\n", ncu.$data, i);
188 }
189
190 //if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Rcv: ADDR decoded = 0x%x", ncu_addr));
191
192 //The length of recieved data depends on the byte size
193 case (ncu_cmd[1:0]) {
194 2'b00: rcv_data_width = 7;
195 2'b01: rcv_data_width = 15;
196 2'b10: rcv_data_width = 31;
197 2'b11: rcv_data_width = 63;
198 }
199
200 if(~ncu_cmd[2]) {
201 for (i=rcv_data_width; i>=0; i--) {
202 @(posedge ncu.$clk);
203 ncu_data[i] = ncu.$data;
204 //printf("SSI: MOSI = %h i=%d\n", ncu.$data, i);
205 }
206 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Rcv: WR cmd rcvd addr=0x%h dataWidth=%0d data=0x%x", ncu_addr, rcv_data_width+1, ncu_data));
207
208 //printf("SSI: %d WR cmd rcvd size=%d data=0x%x\n", get_time(LO), rcv_data_width, ncu_data, get_time(LO));
209 } else {
210 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Rcv: RD cmd rcvd addr=0x%h dataWidth=%0d data=0x%x", ncu_addr, rcv_data_width+1, ncu_data));
211 //printf("SSI: RD cmd rcvd size=%d data=0x%x\n", rcv_data_width, ncu_data);
212 }
213
214 @(posedge ncu.$clk);
215 parity = ncu.$data;
216 //printf("SSI: MOSI = %h i=%d\n", ncu.$data, i);
217
218 ////printf ("The parity calculated is %h\n", ^{1'b1, ncu_cmd, ncu_addr});
219 if (parity != (^{1'b1, ncu_cmd, ncu_addr})) {
220 }
221
222 //Decode address to update shadow registers
223 //ssi_int_soft = ff_fff0_0000
224 //ssi_int_parity = ff_fff0_0010
225 //ssi_int_mask = ff_fff0_0020
226 //ssi_response_latency = ff_fff0_0030
227 //ssi_timeout = ff_fff1_0000
228 //ssi_parity_error = ff_fff2_0000
229 //ssi_side_effect = ff_fff3_0000
230 case (ncu_addr[27:16]) {
231 12'hff0: {
232 //SSI interrupt device
233 //breakpoint;
234 case (ncu_addr[7:0]) {
235 8'h00: ssi_int_soft = ncu_data;
236 8'h10: ssi_int_parity = ncu_data;
237 8'h20: ssi_int_mask = ncu_data;
238 8'h30: ssi_response_latency = ncu_data;
239 }
240 }
241 12'hff1: {
242 //SSI timeout
243 ssi_timeout = 1'b1;
244 }
245 12'hff2: {
246 //SSI parity
247 ssi_parity_error = 1'b1;
248 }
249 12'hff3: {
250 ssi_side_effect = 1'b1;
251 }
252// 12'hff4: {
253// //GPIO registers
254// case([
255// }
256 }
257 if (~ssi_timeout) {
258 send = 1;
259 }
260 //printf ("SSI: %d cmd received is %h, addr received is %h, data received is %h, SEND is set\n", get_time(LO),ncu_cmd, ncu_addr, ncu_data);
261 @(posedge ncu.$clk);
262 }
263}
264
265/*
266task CLASSNAME::GPIO() {
267 reg [7:0] gpio_0_latency;
268 reg [7:0] gpio_0_duration;
269 reg gpio_0_set = 0;
270
271 reg [7:0] gpio_1_latency;
272 reg [7:0] gpio_1_duration;
273 reg gpio_1_set = 0;
274
275 reg gpio_2_set = 0;
276 reg gpio_3_set = 0;
277
278
279fork
280 {
281 while(1) {
282 while(~gpio_0_set) {
283 @(posedge ncu.$clk);
284 gpio_0_set = GPIO_0[16];
285 }
286
287 gpio_0_latency = GPIO_0[7:0];
288 gpio_0_duration = GPIO_0[15:8];
289
290 while( gpio_0_latency ) {
291 gpio_0_latency = gpio_0_latency - 1;
292 @(posedge ncu.$clk);
293 }
294
295 gpio_0_out = 1;
296
297
298 while( gpio_0_duration ) {
299 gpio_0_duration = gpio_0_duration - 1;
300 @(posedge ncu.$clk);
301 }
302
303 gpio_0_out = 0;
304 }
305 }
306
307
308 {
309 while(1) {
310 while(~gpio_1_set) {
311 @(posedge ncu.$clk);
312 gpio_1_set = GPIO_1[16];
313 }
314
315 gpio_1_latency = GPIO_1[7:0];
316 gpio_1_duration = GPIO_1[15:8];
317
318 while( gpio_1_latency ) {
319 gpio_1_latency = gpio_1_latency - 1;
320 @(posedge ncu.$clk);
321 }
322
323 gpio_1_out = 1;
324
325
326 while( gpio_0_duration ) {
327 gpio_1_duration = gpio_1_duration - 1;
328 @(posedge ncu.$clk);
329 }
330
331 gpio_1_out = 0;
332 }
333 }
334
335 {
336 while(1) {
337 gpio_2_out = gpio_2_reg;
338 gpio_3_out = gpio_3_reg;
339 @(posedge ncu.$clk);
340 }
341
342 }
343
344join
345
346}
347*/
348
349task CLASSNAME::Int() {
350 reg [7:0] int_latency;
351 reg post_int, cyc, post_cyc, randcyc;
352 reg parity_int, parity_detect_enable;
353 reg soft_enable, parity_enable;
354 integer i = 0;
355 post_int = 0; cyc=0; post_cyc=1'b1; randcyc=0; int_latency=8'b0;
356 ssi_int_soft = 64'b0;
357
358 while (ncu.$reset) {
359 while( ~(post_int | cyc) ) {
360 @(posedge ncu.$clk);
361 post_int = ssi_int_soft[8];
362 cyc = ssi_int_soft[9];
363 //printf("SSI: ssi_int_soft = 0x%x\n", ssi_int_soft);
364 }
365
366 while (post_int | cyc) {
367 //printf("Entered post Int\n");
368 int_latency = ssi_int_soft[7:0];
369 post_int = ssi_int_soft[8];
370 cyc = ssi_int_soft[9];
371 post_cyc = ssi_int_soft[10];
372 randcyc = ssi_int_soft[11];
373 //if their is a latency set then interrupt
374 //after that
375 //breakpoint;
376 if (post_int) {
377 while(int_latency != 8'h00) {
378 int_latency = int_latency - 1;
379 @(posedge ncu.$clk);
380 }
381 }
382 ssi.$int_l = 0;
383 while (cyc) {
384 //interrupt after int_latency cycles
385 //printf("SSI: CYC interrupt set\n");
386 //breakpoint;
387 while(int_latency != 8'h00) {
388 int_latency = int_latency - 1;
389 @(posedge ncu.$clk);
390 }
391 cyc = ssi_int_soft[9];
392 int_latency = ssi_int_soft[7:0];
393 //pulse the iterrupt for 8 SSI
394 for (i=7; i>=0; i--) {
395 ssi.$int_l = 0;
396 @(posedge ncu.$clk);
397 }
398 ssi.$int_l = 1;
399 @(posedge ncu.$clk);
400 }
401 }
402 @(posedge ncu.$clk);
403 ssi.$int_l = 1;
404 //printf("SSI: Deassert post_int\n");
405
406 } // while not in reset
407
408}
409
410// read and/or write gMem
411task CLASSNAME::Send() {
412 reg [39:0] tmpAddr;
413 integer i, trans_data_width;
414 reg [63:0] read_data, transmit_data, tmp_data;
415 reg [63:0] send_data;
416 reg send_parity;
417
418 while (1) {
419 @(posedge ssi.$clk); // wait for Rcv() to set send true
420 if (send == 1) {
421 //printf ("SSI: %d send set to 1\n", get_time(LO));
422 tmpAddr = {12'hfff, ncu_addr};
423 read_data = gMem.read_mem({tmpAddr[39:3], 3'b0});
424 //printf ("SSI: READ from GLOBAL tmpAddr=0x%h data=0x%h\n", tmpAddr, read_data);
425 /*
426 *Switch byte order
427 */
428 // tmp_data = {ncu_data[7:0], ncu_data[15:8], ncu_data[23:16], ncu_data[31:24], ncu_data[39:32], ncu_data[47:40], ncu_data[55:48], ncu_data[63:56]};
429 // ncu_data = tmp_data;
430 //printf ("SSI: %d Read made from global memory ncu_cmd=0x%x\n", get_time(LO), ncu_cmd);
431 //rd request
432 //breakpoint;
433 if (ncu_cmd[2] == 1'b1) {
434 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: RD request addr = 0x%h", ncu_addr));
435 //printf("SSI: RD request made\n");
436 case (ncu_cmd[1:0]) {
437 2'b00: {
438 case (ncu_addr[2:0]) {
439 3'b000: transmit_data = {read_data[7:0]};
440 3'b001: transmit_data = {read_data[15:8]};
441 3'b010: transmit_data = {read_data[23:16]};
442 3'b011: transmit_data = {read_data[31:24]};
443 3'b100: transmit_data = {read_data[39:32]};
444 3'b101: transmit_data = {read_data[47:40]};
445 3'b110: transmit_data = {read_data[55:48]};
446 3'b111: transmit_data = {read_data[63:56]};
447 }
448 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: BYTE RD req addr=0x%x data=0x%x", ncu_addr, transmit_data));
449 trans_data_width = 7;
450 }
451 2'b01: {
452 case (ncu_addr[2:1]) {
453 2'b00: transmit_data = {read_data[15:0]};
454 2'b01: transmit_data = {read_data[31:16]};
455 2'b10: transmit_data = {read_data[47:32]};
456 2'b11: transmit_data = {read_data[63:48]};
457 }
458 trans_data_width = 15;
459 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: HALF WORD RD req addr=0x%x data=0x%x", ncu_addr, transmit_data));
460 }
461 2'b10: {
462 transmit_data = tmpAddr[2] == 1'b1 ? read_data[31:0] : read_data[63:32];
463 trans_data_width = 31;
464 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: WORD RD req addr=0x%x data=0x%x", ncu_addr, transmit_data));
465 }
466 2'b11: {
467 transmit_data = read_data[63:0];
468 trans_data_width = 63;
469 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: DOUBLE WORD RD req addr=0x%x data=0x%x", ncu_addr, transmit_data));
470 }
471 }
472 ////printf ("data read is %h, data to send is %h\n", read_data, send_data);
473 } else {
474 //write requested
475 //printf("SSI: WRITE command recieved\n");
476 //if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: WR request addr = 0x%h", ncu_addr));
477 case (ncu_cmd[1:0]) {
478 2'b00: {
479 case (ncu_addr[2:0]) {
480 3'b000: transmit_data = {read_data[63:8], ncu_data[7:0]};
481 3'b001: transmit_data = {read_data[63:16], ncu_data[7:0], read_data[7:0]};
482 3'b010: transmit_data = {read_data[63:24], ncu_data[7:0], read_data[15:0]};
483 3'b011: transmit_data = {read_data[63:32], ncu_data[7:0], read_data[23:0]};
484 3'b100: transmit_data = {read_data[63:40], ncu_data[7:0], read_data[31:0]};
485 3'b101: transmit_data = {read_data[63:48], ncu_data[7:0], read_data[39:0]};
486 3'b110: transmit_data = {read_data[63:56], ncu_data[7:0], read_data[47:0]};
487 3'b111: transmit_data = { ncu_data[7:0], read_data[55:0]};
488 }
489 trans_data_width = 7;
490 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: WR Byte req done addr=0x%x data=0x%h mergedData=0x%h", ncu_addr, ncu_data[7:0], transmit_data));
491 }
492 2'b01: {
493 case (ncu_addr[2:1]) {
494 2'b00: transmit_data = {read_data[63:16], ncu_data[15:0]};
495 2'b01: transmit_data = {read_data[63:32], ncu_data[15:0], read_data[15:0]};
496 2'b10: transmit_data = {read_data[63:48], ncu_data[15:0], read_data[31:0]};
497 2'b11: transmit_data = { ncu_data[15:0], read_data[47:0]};
498 }
499 trans_data_width = 15;
500 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: WR HALF req done addr=0x%x data=0x%h mergedData=0x%h", ncu_addr, ncu_data[15:0], transmit_data));
501 }
502 2'b10: {
503 transmit_data = tmpAddr[2] == 1'b1 ? {read_data[63:32], ncu_data[31:0]} : {ncu_data[31:0], read_data[31:0]};
504 trans_data_width = 31;
505 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: WR WORD req done addr=0x%x data=0x%h mergedData=0x%h", ncu_addr, ncu_data[31:0], transmit_data));
506 }
507 2'b11: {
508 transmit_data = ncu_data[63:0];
509 trans_data_width = 63;
510 if (ssi_mon) PR_NORMAL(dispmonScope, MON_NORMAL, psprintf("SSI Send: WR DOUBLE req done addr=0x%x data=0x%h mergedData=0x%h", ncu_addr, ncu_data, transmit_data));
511 }
512
513 }
514
515 gMem.write_mem({tmpAddr[39:3], 3'b0}, transmit_data);
516 //printf("SSI: Did a write to the global memmory\n");
517 } // write
518
519 /*
520 * Added one cycle latency
521 */
522
523 ssi.$data = 1'b0;
524 @(posedge ssi.$clk);
525
526 /*
527 * Starting response to master
528 */
529
530 ssi.$data = 1'b1;
531 @(posedge ssi.$clk);
532 send_parity = 1'b0;
533
534 // if a read
535 if( ncu_cmd[2] ) {
536 for (i=trans_data_width; i>=0; i--) {
537 ssi.$data = transmit_data[i];
538 send_parity = send_parity ^ transmit_data[i];
539 @(posedge ssi.$clk);
540 }
541 if (ssi_parity_error) {
542 send_parity = send_parity^1;
543 }
544 ssi.$data = ^{1'b1, send_parity};
545 @(posedge ssi.$clk);
546 ssi.$data = 1'b0;
547 } else { // else write
548 ssi.$data = 1'b1;
549 if(ssi_parity_error) {
550 ssi.$data = 1'b0;
551 }
552 @(posedge ssi.$clk);
553 ssi.$data = 1'b0;
554 }
555 // done
556 send = 0;
557 } // if send
558 } // while 1
559}