Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / vera / niu_pio / pio_driver.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: pio_driver.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 "pio.port.vri"
37#include "cMesg.vrh"
38// #include "ncu_stub.vrh"
39#include "niu_gen_pio.vrh"
40
41extern Mesg be_msg;
42// extern Cncu_stub ncu_driver;
43extern niu_gen_pio gen_pio_drv;
44
45class pio_drv {
46
47 bit [39:0] address; // msb = 0 real access
48 // msb = 1 force register
49 bit [31:0] wr_data; // data for pio_wr/pio_cfg_wr
50 bit [31:0] rd_data; // data returned for pio_rd/pio_cfg_rd
51 bit rd_wr; // 1 = read; 0 = write
52 bit cfg_access; // 1 = cfg_access; 0 = register access
53 bit ht_pio = 1'b0; // 1 = ht_bus_access to register; 0 = pio_driver access
54 integer pio_access; // flag to prevent multiple use of database
55 event pio_start; // signal to start the primary task
56 event pio_complete; // return signal to initiator
57 event pio_checker_start; // signal to have the pio checker
58 // anticipate pending activity
59 bit expect_pio_err = 1'b0; // = 1'b1, when where is a pio_error expected.
60
61 task new((pio_port port_bind = null)) ;
62
63 task init_outputs(pio_port port_bind) ;
64
65 task float_outputs(pio_port port_bind) ;
66
67 task ht_reset( pio_port port_bind,
68 (integer no_of_clocks = 110)
69 ) ;
70
71 task pio_wr( bit [39:0] addr, bit [31:0] write_data,
72 (bit exp_pio_err = 1'b0) ) ;
73
74 task pio_rd( bit [39:0] addr, var bit [31:0] read_data,
75 (bit [31:0] exp_data = 32'b0),
76 (bit [31:0] data_mask = 32'hFFFF_FFFF),
77 bit exp_data_valid,
78 (bit exp_pio_err = 1'b0) );
79
80 task pio(pio_port port_bind) ;
81
82 task pio_handshake (pio_port port_bind) ;
83
84 task ht_pio_enable () ;
85
86}
87
88/* **********************************************************
89 init_outputs
90 Initialize the output signals
91 ********************************************************** */
92task pio_drv::new((pio_port port_bind = null)) {
93
94
95 pio_port my_port = port_bind ;
96 // create a sempahore for this class
97 pio_access = alloc(SEMAPHORE, 0, 1, 1);
98 if(!ht_pio) {
99 // execute primary tasks
100 fork
101// init_outputs(my_port);
102 pio(my_port);
103 join none
104
105 }
106 // ht_reset(my_port);
107}
108
109
110/* **********************************************************
111 init_outputs
112 Initialize the output signals
113 ********************************************************** */
114
115task pio_drv::init_outputs(pio_port port_bind) {
116
117 port_bind.$reg_offset = 0;
118 port_bind.$write_data = 32'h0000_0000;
119 port_bind.$rd_wr = 0;
120 port_bind.$mod_select = 0;
121 port_bind.$reset = 1'b0;
122
123}
124
125task pio_drv::float_outputs(pio_port port_bind) {
126
127 port_bind.$reg_offset = 24'hz;
128 port_bind.$write_data = 32'hz;
129 port_bind.$rd_wr = 1'bz;
130 port_bind.$mod_select = 1'bz;
131
132 repeat(5) @(posedge CLOCK);
133
134}
135
136/* **********************************************************
137 ht_reset
138 All the blocks within Vega (FFL, ILC, IRX, ITX, MAC, NRX, NTX,
139 PHY, PSEUDO_DDR_IO) are reset by "reset" signal from HT.
140 The "ht_reset" task mimics that functionality.
141 ********************************************************** */
142
143task pio_drv::ht_reset( pio_port port_bind,
144 (integer no_of_clocks = 110)
145 )
146{
147 printf(" Entering ht_reset \n");
148 if (!ht_pio) {
149 // MAC requirement that the reset is applied two times and
150 // for a minimum duration of 440ns (110 clock cycles) each time.
151
152 if (no_of_clocks < 110) no_of_clocks = 110;
153 port_bind.$reset = 1'b0;
154 repeat (10) @(posedge port_bind.$clock);
155
156 repeat (no_of_clocks) {
157 port_bind.$reset = 1'b1;
158 @(posedge port_bind.$clock);
159 }
160
161 repeat (no_of_clocks) {
162 port_bind.$reset = 1'b0;
163 @(posedge port_bind.$clock);
164 }
165
166 repeat (no_of_clocks) {
167 port_bind.$reset = 1'b1;
168 @(posedge port_bind.$clock);
169 }
170
171 port_bind.$reset = 1'b0;
172 repeat (5) @(posedge port_bind.$clock);
173 } // end of if (!ht_pio)
174
175}
176
177
178/* ***********************************************************
179 pio_wr
180 This task performs a PIO write of a VEGA register. In asic
181 simulation the write is performed across the HT interface;
182 In module simulation, the driver module will simulate the
183 GPIO interface.
184
185 The "addr" field is a 33 bit field. If the msb is set to
186 zero, then the lower 32 bits are used to access the memory
187 mapped VEGA register. If the msb is set to one, then a
188 case statement will determine the functionality -- in most
189 situations the "phony" addresses will (1) access items not
190 in the memory map, (2) directly force registers to save
191 simulation time, or (3) access multiple registers in one
192 command.
193
194 The "wr_data" field is a 32 bit field which contains the
195 data to be written.
196
197 All writes using this task updates the shadow space.
198 ********************************************************** */
199
200task pio_drv::pio_wr(bit [39:0] addr, bit [31:0] write_data,
201 (bit exp_pio_err = 1'b0) ) {
202
203 semaphore_get(WAIT, pio_access, 1);
204
205 address = addr;
206 wr_data = write_data;
207 rd_wr = 1'b0;
208 cfg_access = 1'b0;
209 expect_pio_err = exp_pio_err;
210
211 if (ht_pio) {
212 // Do nothing!
213 }
214 else {
215 // if msb is one, then access does not go to core
216 //if (addr[32] != 1) {
217 trigger(ONE_SHOT, pio_start);
218 sync(ALL, pio_complete);
219 //}
220 }
221
222 semaphore_put(pio_access, 1);
223
224}
225
226/* **********************************************************
227 pio_rd
228 This task performs a PIO read of a VEGA register. In asic
229 simulation the read is performed across the HT interface;
230 in module simulation, the pio driver will simulate the GIO++
231 interface.
232
233 The "addr" field is a 33 bit field. If the msb is set to
234 zero, then the lower 32 bits are used to access the memory
235 mapped VEGA register. If the msb is set to one, then a
236 case statement will determine the functionality -- in most
237 situations the "phony" addresses will (1) access items not
238 in the memory map, (2) directly read registers to save
239 simulation time, or (3) access multiple registers in one
240 command.
241
242 The "rd_data" field is a 32 bit field which will be loaded
243 with the data read from the register.
244
245 If a corresponding address exists in the shadow space, then
246 a comparison will be made with the shadow copy.
247 ********************************************************** */
248
249task pio_drv::pio_rd(bit [39:0] addr, var bit [31:0] read_data,
250 (bit [31:0] exp_data = 32'b0),
251 (bit [31:0] data_mask = 32'hFFFF_FFFF),
252 bit exp_data_valid,
253 (bit exp_pio_err = 1'b0) ) {
254
255 bit [31:0] reg_data;
256 semaphore_get(WAIT, pio_access, 1);
257 address = addr;
258 rd_wr = 1'b1;
259 cfg_access = 1'b0;
260 expect_pio_err = exp_pio_err;
261
262 if (ht_pio) {
263 // Do nothing!!
264 }
265 else {
266 // if msb is one, then access does not go to core
267 // if (addr[32] != 1) {
268 trigger(ONE_SHOT, pio_start);
269 sync(ALL, pio_complete);
270 // }
271 read_data = rd_data;
272 if ( exp_data_valid) {
273 if ((rd_data & data_mask) !== (exp_data & data_mask)) {
274 printf("PIO: pio_rd failure: Data miscompare\n");
275 be_msg.print(e_mesg_error, "pio_rd", "pio_driver",
276 "Data miscompare: Addr: 0x%h, expected: %h, observed: %h, mask: %h \n ",
277 address, exp_data, rd_data, data_mask);
278 }
279 }
280
281 }
282
283 semaphore_put(pio_access, 1);
284
285}
286
287/* **********************************************************
288 pio
289 Primary task for the pio driver.
290 Flow: (1) Enter continuous while loop
291 (2) Make sure that system is out of reset
292 This is ensured through pio_tasks.vr
293 (3) Wait for pio command
294 (4) Send pio_token to checker
295 (5) Decode address and perform pio with appropriate
296 port
297 (6) signal the originating task that the operation
298 is complete
299 (7) add a one clock delay
300 ********************************************************** */
301
302task pio_drv::pio(pio_port port_bind) {
303
304 pio_port my_port = port_bind;
305
306 // eventually replace (1) with a system variable that can turn task on/off
307 while (1) {
308
309 // Wait for the testbench to issue a pio command
310 sync(ALL, pio_start);
311
312 // Once the token is received, it should be passed on to the checker.
313
314 trigger(ONE_SHOT, pio_checker_start);
315
316 cfg_access = 0;
317
318 if (cfg_access == 0) {
319
320 pio_handshake (my_port) ;
321
322 } // end of if (cfg_access == 0)
323
324 // Tell the originating task that the pio operation has been completed.
325
326 trigger(ONE_SHOT, pio_complete);
327
328 } // end of while (1)
329
330} // end of pio task
331
332
333/* **********************************************************
334 pio_handshake
335
336 Perform the 250 Mhz handshake across the pio interface.
337 This task has to drive the proper signals at the proper
338 time. The checker will verify incoming signals such
339 as rd_data.
340
341 NOTE: The delay between select asserted and select deasserted
342 should be programmable between 3 and 4.
343 ********************************************************** */
344/**************************
345task pio_drv::pio_handshake (pio_port port_bind) {
346 integer MAX_DELAY = 1000;
347 bit ht_pio_error ;
348
349 @1 port_bind.$reg_offset = address;
350 port_bind.$write_data = wr_data;
351 port_bind.$rd_wr = rd_wr;
352 port_bind.$mod_select = 1; // select must be active for at least
353
354 // $pio_err should be driven by all modules and is active high signal.
355 // $pio_err should be asserted high only when there is a PIO error condition.
356 @1,MAX_DELAY port_bind.$pio_ack == 1'b1;
357 ht_pio_error = port_bind.$pio_err;
358
359 rd_data = port_bind.$read_data;
360 @(posedge port_bind.$clock);
361 port_bind.$pio_ack == 1'b0;
362 if (expect_pio_err != 1'b1) {
363 port_bind.$pio_err == 1'b0;
364 }
365 port_bind.$mod_select = 0; // three clock cycles.
366 repeat (3) { // make sure process is complete
367 @(port_bind.$clock);
368 }
369
370 // Error if the $pio_err signal is asserted with expect_pio_err bit is not set!
371 if ( (expect_pio_err != 1'b1) & (ht_pio_error == 1'b1) ) {
372 be_msg.print(e_mesg_error, "pio_handshake", "pio_driver",
373 "PIO ERROR Asserted for Address = %0h \n ", address);
374 }
375
376 // Error if the $pio_err signal is NOT asserted with expect_pio_err bit is set!
377 if ( (expect_pio_err == 1'b1) & (ht_pio_error != 1'b1) ) {
378 be_msg.print(e_mesg_error, "pio_handshake", "pio_driver",
379 "PIO ERROR Expected for Address = %0h \n ", address);
380 }
381}
382*******************************************/
383
384task pio_drv::pio_handshake (pio_port port_bind) {
385 integer MAX_DELAY = 1000;
386 bit ht_pio_error ;
387 integer status;
388 bit [63:0] local_read_data;
389 bit [63:0] local_write_data;
390 local_read_data = {32'h0000_0000,rd_data};
391 local_write_data = {32'h0000_0000,wr_data};
392
393 if(rd_wr == 1) // Read
394 {
395 // ncu_driver.read_data(address,local_read_data,status);
396 gen_pio_drv.pio_rd(address,local_read_data);
397 /* if((expect_pio_err == 0) && (status != 1))
398 printf("ERROR: pio_rd error seen when not expected\n");
399 if((expect_pio_err == 1) && (status == 1))
400 printf("ERROR: pio_rd error not seen when expected\n"); */
401 rd_data = local_read_data[31:0];
402 }
403 else
404 {
405 // ncu_driver.write_data(address,local_write_data);
406 gen_pio_drv.pio_wr(address,local_write_data);
407 wr_data = local_write_data[31:0];
408 }
409}
410
411/* **********************************************************
412 ht_pio_enable
413 Enable the ht_pio bit to indicate that the register
414 acceses will be done from HT interface and not the PIO
415 slave interface driver.
416 ********************************************************** */
417task pio_drv::ht_pio_enable() {
418
419 // set the ht_pio bit to enable HT interface access
420 ht_pio = 1'b1;
421
422}
423
424