Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / tcu / vera / classes / ccu_clks_states.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: ccu_clks_states.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_class.vrh"
37#include "ucb_defines.vri"
38#include "ucb___packet.vrh"
39#include "ccu_defines.vri"
40#include "ucb_top.vri"
41#include "ccu_top.vri"
42#include "ucb_monitor.vrh"
43#include "ccu_clk_packet.vrh"
44
45class CCU_clks_states {
46 //---ports and classes--
47 local UCB_port ccu_ucb_port; // CCU-NCU interface
48 local CCU_clk_port ccu_clk_port; // port for all CCU clk signals
49 local CCU_mon_port ccu_mon_port;
50 local UCB_monitor ccu_ucb_monitor; // monitor UCB bus
51 local StandardDisplay dbg; // Standard display for printing
52
53 //---CCU CSRs---
54 local bit [63:0] pll_ctl;
55 local bit [63:0] rng_ctl;
56 local bit [63:0] rng_data;
57 local bit [63:0] pll_ctl_staging; // staging reg
58 //---pll inputs----
59 local integer sys_clk_per; // sys clk per sampled at CCU input
60
61 //---vars: limits/deviations---
62 local integer cmp_per_dev; // deviation in cmp clk per in % from nominal
63 local integer cmp_pw_dev; // deviation in cmp clk pulse width in % from nominal
64 local integer dr_per_dev;
65 local integer dr_pw_dev;
66 local integer iox_per_dev, iox_pw_dev; // deviation of IO and io2X clk period and duty cycle (in %)
67 local integer dtm_dr_iox_pw_dev; // dtm-mode: dr and iox pulse width deviation
68
69 //---vars: control---
70 local string name; // name of this object
71 local string dispScope; // for standard display
72 local integer error_cnt; // Error count. Init to 0. WARN: become negative if exeed max integer
73 local integer max_error_printed; // not print error msg if (errors > max_error_printed)
74 local integer running; // 0: not running; otherwise, running
75 local event stop_e; // triggered by stop_it() to terminate start()
76 local integer is_fc_bench; // 0: not FC_bench; otherwise, it's FC bench
77 local integer pllbypass_mode;// 0: not pll bypass mode; otherwise, it's pll bypass
78 local bit [5:0] pllbypass_virtual_div2; // imaginary values of div2 that produce same effect as non-bypass mode
79 local bit [6:0] pllbypass_virtual_div4; // imaginary values of div4 that produce same effect as non-bypass mode
80
81 //---public tasks---
82 task new(string name="CCU_clks_states", StandardDisplay dbg, integer start_it=0);
83 task start();
84 task stop_it();
85 function CCU_clk_packet get_exp_clk_pkt();
86 task show_clk_pkt(CCU_clk_packet pkt);
87 task put_per_pw_dev(integer cmp_per_dev, integer cmp_pw_dev,
88 integer iox_per_dev, integer iox_pw_dev,
89 integer dr_per_dev, integer dr_pw_dev);
90
91 //---public one-line subroutines---
92 function integer get_error_cnt() { get_error_cnt = (error_cnt >= 0)? error_cnt : 1; }
93 task ignore_ccu_ucb_error() { this.ccu_ucb_monitor.ignore_err = 1; }
94 task put_pllbypass_mode(integer value) { this.pllbypass_mode = (value == 0)? 0 : 1; }
95 task put_pllbypass_virtual_div(bit [5:0] div2, bit [6:0] div4) { this.pllbypass_virtual_div2 = div2; this.pllbypass_virtual_div4 = div4; }
96 function bit [63:0] get_pll_ctl() { get_pll_ctl = this.pll_ctl; }
97
98 //---local subroutines---
99 local task mon_update_ccu_csrs();
100 local function integer get_sys_clk_per(integer wait_cycs=0);
101 local function CCU_clk_packet get_expClkPkt_func_mode();
102 local function CCU_clk_packet get_expClkPkt_dtm_mode();
103}
104
105//################################################################
106//######### implementation of subroutines ###########
107//################################################################
108
109task CCU_clks_states::new(string name="CCU_clks_states", StandardDisplay dbg, integer start_it=0) {
110 //---from arg list---
111 this.dbg = dbg;
112 this.name = name;
113
114 //---ports and classes---
115 this.ccu_ucb_port = ccu_ucb_mon_bind;
116 this.ccu_clk_port = ccu_clk_bind;
117 this.ccu_mon_port = ccu_mon_bind;
118 this.ccu_ucb_monitor = new("ccu_ucb_mon", dbg, ccu_ucb_port, 4, 8'h83); // 4: ucb bus data width
119
120 //---others---
121 this.pll_ctl = CCU__PLL_CTL__INIT_VALUE;
122 this.rng_ctl = 0; // review: may need to change
123 this.rng_data = 0; // review: may need to change
124 this.pll_ctl_staging = this.pll_ctl;
125
126 //--- testing limits for clk period and duty cycle----
127 //--- WARNING: per CCU designer, these limits should be as follows:
128 this.cmp_per_dev = 7; // in % (ie. nominal +/- per_dev in percent)
129 this.cmp_pw_dev = 7; // in % (ie. 50% +/- (pw_dev% of clk per))
130 this.iox_per_dev = 7;
131 this.iox_pw_dev = 7;
132 this.dr_per_dev = 7;
133 this.dr_pw_dev = 10; // in % (ie. 50% +/- (pw_dev% of clk per))
134 this.dtm_dr_iox_pw_dev = 10; // in % (ie. 50% +/- (pw_dev% of clk per))
135
136 //----the rest -----
137 this.dispScope = this.name;
138 this.error_cnt = 0;
139 this.max_error_printed = 20;
140 this.running = 0;
141#ifdef FC_BENCH
142 this.is_fc_bench = 1;
143 dbg.dispmon(name, MON_ALWAYS, "FC testbench");
144#else
145 this.is_fc_bench = 0;
146 dbg.dispmon(name, MON_ALWAYS, "SAT-level testbench");
147#endif
148 this.pllbypass_mode = 0;
149 this.pllbypass_virtual_div2 = 6'h7;
150 this.pllbypass_virtual_div4 = 7'h8;
151
152 //---process plus_arg to override default values---
153 if (get_plus_arg(CHECK, "cmp_per_dev="))
154 this.cmp_per_dev = get_plus_arg(NUM, "cmp_per_dev=");
155 if (get_plus_arg(CHECK, "cmp_pw_dev="))
156 this.cmp_pw_dev = get_plus_arg(NUM, "cmp_pw_dev=");
157 if (get_plus_arg(CHECK, "iox_per_dev="))
158 this.iox_per_dev = get_plus_arg(NUM, "iox_per_dev=");
159 if (get_plus_arg(CHECK, "iox_pw_dev="))
160 this.iox_pw_dev = get_plus_arg(NUM, "iox_pw_dev=");
161 if (get_plus_arg(CHECK, "dr_per_dev="))
162 this.dr_per_dev = get_plus_arg(NUM, "dr_per_dev=");
163 if (get_plus_arg(CHECK, "dr_pw_dev="))
164 this.dr_pw_dev = get_plus_arg(NUM, "dr_pw_dev=");
165
166 //---start background threads ---
167 if (start_it)
168 start();
169 fork { // always do this
170 this.sys_clk_per = this.get_sys_clk_per(3);
171 } join none
172}
173
174//=============================================================
175// WHAT: start this object
176//=============================================================
177task CCU_clks_states::start() {
178 if (running)
179 return;
180 dbg.dispmon(this.dispScope, MON_INFO, "starts ...");
181 this.running = 1;
182 ccu_ucb_monitor.start(); // run in back ground
183 fork {
184 fork {
185 mon_update_ccu_csrs();
186 } join none
187 sync(ALL, this.stop_e); // stop_it() triggers this event
188 terminate;
189 dbg.dispmon(this.dispScope, MON_INFO, psprintf("%s stopped", this.name));
190 this.running = 0;
191 } join none
192}
193
194//=============================================================
195// WHAT: stop this object
196//=============================================================
197task CCU_clks_states::stop_it() {
198 if (this.running) {
199 dbg.dispmon(this.dispScope, MON_INFO, psprintf("stopping %s ...", this.name));
200 trigger(this.stop_e); // this event terminates start()
201 }
202}
203
204//=============================================================
205// WHAT: monitor CCU's UCB bus and update CSRs when NCU writes to them.
206// When RST does WMR reset, copy staging CSRs to real CSR
207//=============================================================
208task CCU_clks_states::mon_update_ccu_csrs() {
209 UCB___packet ucb_pkt;
210
211 //---Update CSRs when NCU writes to them---
212 fork {
213 while (1) {
214 sync(ALL, ccu_ucb_monitor.req_end); // wait NCU completes a req
215 ucb_pkt = ccu_ucb_monitor.get_req_pkt(); // get write req pkt
216 if (ucb_pkt.pkt_type == UCB_PKT_WRITE_REQ) {
217 case (ucb_pkt.addr) {
218 CCU__PLL_CTL : this.pll_ctl_staging = ucb_pkt.payload; // update staging CSR only
219 CCU__RNG_CTL : this.rng_ctl = ucb_pkt.payload;
220 CCU__RNG_DATA : this.rng_data = ucb_pkt.payload;
221 // ignore if other addrs
222 }
223 }
224 }
225 } join none
226
227 //---copy staging CSRs into real CSRs when PLL is reseted--
228 fork {
229 while (1) {
230 @(posedge ccu_clk_port.$rst_ccu_pll_); // PLL got reset
231 if (this.is_fc_bench) { // FC bench forces values onto these signals
232 this.pll_ctl[CCU__PLL_CTL__PLL_DIV1__MSB : CCU__PLL_CTL__PLL_DIV1__POS] = ccu_mon_port.$pll_div1_at_csrblk async;
233 this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS] = ccu_mon_port.$pll_div2_at_csrblk async;
234 this.pll_ctl[CCU__PLL_CTL__PLL_DIV3__MSB : CCU__PLL_CTL__PLL_DIV3__POS] = ccu_mon_port.$pll_div3_at_csrblk async;
235 this.pll_ctl[CCU__PLL_CTL__PLL_DIV4__MSB : CCU__PLL_CTL__PLL_DIV4__POS] = ccu_mon_port.$pll_div4_at_csrblk async;
236 this.pll_ctl[CCU__PLL_CTL__SERDES_DTM1__POS] = ccu_mon_port.$serdes_dtm1_at_csrblk async;
237 this.pll_ctl[CCU__PLL_CTL__SERDES_DTM2__POS] = ccu_mon_port.$serdes_dtm2_at_csrblk async;
238 }
239 else { // TCU SAT which programs CCU's CSR via UCB bus
240 this.pll_ctl = this.pll_ctl_staging; // copy staging CSR into real CSR
241 if (this.pllbypass_mode) {
242 this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS] = this.pllbypass_virtual_div2;
243 this.pll_ctl[CCU__PLL_CTL__PLL_DIV4__MSB : CCU__PLL_CTL__PLL_DIV4__POS] = this.pllbypass_virtual_div4;
244 }
245 }
246 }
247 } join none
248}
249
250//=============================================================
251// WHAT: get sys clk period by sampling CCU input
252// ARGs:
253// wait_cycs: number of sys clk cycles need to wait before sampling
254
255//=============================================================
256function integer CCU_clks_states::get_sys_clk_per(integer wait_cycs=0) {
257 integer old_posedge;
258 if (wait_cycs > 0)
259 repeat (wait_cycs) @(posedge ccu_clk_port.$sys_clk);
260 @(posedge ccu_clk_port.$sys_clk);
261 old_posedge = get_time(LO);
262 @(posedge ccu_clk_port.$sys_clk);
263 get_sys_clk_per = get_time(LO) - old_posedge;
264 dbg.dispmon(this.dispScope, MON_INFO, psprintf("sys clk period at CCU input is %0d ticks", get_sys_clk_per));
265}
266
267//=============================================================
268// WHAT: compute expected values for clk pkt
269//=============================================================
270function CCU_clk_packet CCU_clks_states::get_exp_clk_pkt() {
271 string mode = "func"; // default is functional/mission mode
272
273 if (this.pll_ctl[CCU__PLL_CTL__SERDES_DTM1__POS] == 1'b1
274 || this.pll_ctl[CCU__PLL_CTL__SERDES_DTM2__POS] == 1'b1)
275 mode = "dtm";
276
277 case (mode) {
278 "dtm" : get_exp_clk_pkt = get_expClkPkt_dtm_mode();
279 default : get_exp_clk_pkt = get_expClkPkt_func_mode();
280 }
281}
282
283//=============================================================
284// WHAT: compute expected values for clk pkt in functional/normal/mission mode
285//=============================================================
286function CCU_clk_packet CCU_clks_states::get_expClkPkt_func_mode() {
287 CCU_clk_packet clk_pkt = new(); // create a separate copy
288 bit [CCU__PLL_CTL__PLL_DIV1__SIZE-1:0] div1 = this.pll_ctl[CCU__PLL_CTL__PLL_DIV1__MSB : CCU__PLL_CTL__PLL_DIV1__POS]; // encoded values
289 bit [CCU__PLL_CTL__PLL_DIV2__SIZE-1:0] div2 = this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS];
290 bit [CCU__PLL_CTL__PLL_DIV3__SIZE-1:0] div3 = this.pll_ctl[CCU__PLL_CTL__PLL_DIV3__MSB : CCU__PLL_CTL__PLL_DIV3__POS];
291 bit [CCU__PLL_CTL__PLL_DIV4__SIZE-1:0] div4 = this.pll_ctl[CCU__PLL_CTL__PLL_DIV4__MSB : CCU__PLL_CTL__PLL_DIV4__POS];
292 integer d1_eff, d2_eff, d3_eff; // effective values (ie. 2 means divided by 2, etc.)
293 integer d4_int, d4_frac; // d4_int: integral part. d4_frac: fractional part (0 means 0.0 and 1 means 0.5)
294 integer nom_4_min, nom_4_max; // nominal value for calculating min and max by rounding down or up
295
296 //--- compute effective values of clk dividers---
297 d1_eff = div1 + 1; // warn: bit to integer conversion
298 d2_eff = div2 + 1;
299 d3_eff = div3 + 1;
300 d4_int = div4[CCU__PLL_CTL__PLL_DIV4__SIZE-1:1]; // integral part
301 d4_frac = div4[0]; // fractional part. 0 means 0.0 and 1 means 0.5
302
303 //---compute expected clk pkt----
304 clk_pkt.mode = CCU_FUNC_MODE;
305 clk_pkt.pll_ctl = this.pll_ctl;
306 clk_pkt.sys_clk_per = this.sys_clk_per;
307 clk_pkt.cmp2io_ratio = 4;
308 clk_pkt.cmp2io2x_ratio = 2;
309 clk_pkt.cmp_mult = d2_eff / d1_eff;
310 clk_pkt.cmp_mult_frac = (d2_eff % d1_eff)? 1'b1 : 1'b0;
311 // note: dr_mult and dr_mult_frac are computed in DR section down below
312 clk_pkt.cmp_per_dev = this.cmp_per_dev;
313 clk_pkt.cmp_pw_dev = this.cmp_pw_dev;
314 clk_pkt.dr_per_dev = this.dr_per_dev;
315 clk_pkt.dr_pw_dev = this.dr_pw_dev;
316 clk_pkt.iox_per_dev = this.iox_per_dev;
317 clk_pkt.iox_pw_dev = this.iox_pw_dev;
318
319 //---compute expected clk pkt: period/pulse_with/effective_multipler for cmp/io/io2x clk------
320 clk_pkt.cmp_clk_per_nom = (this.sys_clk_per * d1_eff) / d2_eff;
321 nom_4_min = clk_pkt.cmp_clk_per_nom - 1; // rounding down
322 nom_4_max = clk_pkt.cmp_clk_per_nom + 1; // rounding up
323 clk_pkt.cmp_clk_per_min = nom_4_min - (((nom_4_max / 100) + 1) * this.cmp_per_dev); // rounding down
324 clk_pkt.cmp_clk_per_max = nom_4_max + (((nom_4_max / 100) + 1) * this.cmp_per_dev); // rounding up
325
326 clk_pkt.io_out_per_nom = (this.sys_clk_per * d1_eff * 4) / d2_eff;
327 nom_4_min = clk_pkt.io_out_per_nom - 1; // rounding down
328 nom_4_max = clk_pkt.io_out_per_nom + 1; // rounding up
329 clk_pkt.io_out_per_min = nom_4_min - (((nom_4_max / 100) + 1) * this.iox_per_dev); // rouding down
330 clk_pkt.io_out_per_max = nom_4_max + (((nom_4_max / 100) + 1) * this.iox_per_dev); // rouding up
331
332 clk_pkt.io2x_out_per_nom = (this.sys_clk_per * d1_eff * 2) / d2_eff;
333 nom_4_min = clk_pkt.io2x_out_per_nom - 1; // rounding down
334 nom_4_max = clk_pkt.io2x_out_per_nom + 1; // rounding up
335 clk_pkt.io2x_out_per_min = nom_4_min - (((nom_4_max / 100) + 1) * this.iox_per_dev); // rouding down
336 clk_pkt.io2x_out_per_max = nom_4_max + (((nom_4_max / 100) + 1) * this.iox_per_dev); // rouding up
337
338 //---compute expected clk pkt: period/pulse_with/effective_multipler for dr clk------
339 if ((div1 == 1) && (div3 == 1) && ((div2 + CCU__PLL_CTL__PLL_DIV2__SIZE'h1) == div4)) { // ie. div4 is 1/2 of div2
340 clk_pkt.dr_mult = 2;
341 clk_pkt.dr_mult_frac = 1'b0;
342 clk_pkt.dr_clk_per_nom = this.sys_clk_per / 2; // DR clk freq is twice sys clk freq
343 nom_4_min = clk_pkt.dr_clk_per_nom - 1; // rounding down
344 nom_4_max = clk_pkt.dr_clk_per_nom + 1; // rounding up
345 clk_pkt.dr_clk_per_min = nom_4_min - (((nom_4_max / 100) + 1) * this.dr_per_dev); // rounding down
346 clk_pkt.dr_clk_per_max = nom_4_max + (((nom_4_max / 100) + 1) * this.dr_per_dev); // rounding up
347 //---compute dr sync locations at the cluster outputs ---
348 case (d2_eff) {
349 8: { clk_pkt.dr_sync_loc[0] = 1; clk_pkt.dr_sync_loc[1] = 3; clk_pkt.dr_sync_loc[2] = 5; clk_pkt.dr_sync_loc[3] = 7; }
350 9: { clk_pkt.dr_sync_loc[0] = 1; clk_pkt.dr_sync_loc[1] = 3; clk_pkt.dr_sync_loc[2] = 6; clk_pkt.dr_sync_loc[3] = 8; }
351 10: { clk_pkt.dr_sync_loc[0] = 1; clk_pkt.dr_sync_loc[1] = 4; clk_pkt.dr_sync_loc[2] = 6; clk_pkt.dr_sync_loc[3] = 9; }
352 11: { clk_pkt.dr_sync_loc[0] = 1; clk_pkt.dr_sync_loc[1] = 4; clk_pkt.dr_sync_loc[2] = 7; clk_pkt.dr_sync_loc[3] = 10; }
353 12: { clk_pkt.dr_sync_loc[0] = 1; clk_pkt.dr_sync_loc[1] = 4; clk_pkt.dr_sync_loc[2] = 7; clk_pkt.dr_sync_loc[3] = 10; }
354 13: { clk_pkt.dr_sync_loc[0] = 2; clk_pkt.dr_sync_loc[1] = 5; clk_pkt.dr_sync_loc[2] = 8; clk_pkt.dr_sync_loc[3] = 11; }
355 14: { clk_pkt.dr_sync_loc[0] = 2; clk_pkt.dr_sync_loc[1] = 5; clk_pkt.dr_sync_loc[2] = 9; clk_pkt.dr_sync_loc[3] = 12; }
356 15: { clk_pkt.dr_sync_loc[0] = 2; clk_pkt.dr_sync_loc[1] = 6; clk_pkt.dr_sync_loc[2] = 9; clk_pkt.dr_sync_loc[3] = 13; }
357 16: { clk_pkt.dr_sync_loc[0] = 2; clk_pkt.dr_sync_loc[1] = 6; clk_pkt.dr_sync_loc[2] = 10; clk_pkt.dr_sync_loc[3] = 14; }
358 17: { clk_pkt.dr_sync_loc[0] = 2; clk_pkt.dr_sync_loc[1] = 6; clk_pkt.dr_sync_loc[2] = 11; clk_pkt.dr_sync_loc[3] = 15; }
359 18: { clk_pkt.dr_sync_loc[0] = 2; clk_pkt.dr_sync_loc[1] = 7; clk_pkt.dr_sync_loc[2] = 11; clk_pkt.dr_sync_loc[3] = 16; }
360 19: { clk_pkt.dr_sync_loc[0] = 2; clk_pkt.dr_sync_loc[1] = 7; clk_pkt.dr_sync_loc[2] = 12; clk_pkt.dr_sync_loc[3] = 17; }
361 20: { clk_pkt.dr_sync_loc[0] = 2; clk_pkt.dr_sync_loc[1] = 7; clk_pkt.dr_sync_loc[2] = 12; clk_pkt.dr_sync_loc[3] = 17; }
362 21: { clk_pkt.dr_sync_loc[0] = 3; clk_pkt.dr_sync_loc[1] = 8; clk_pkt.dr_sync_loc[2] = 13; clk_pkt.dr_sync_loc[3] = 18; }
363 default:
364 dbg.dispmon(this.dispScope, MON_ERR, psprintf("div2_eff=%0d <= no spec for dr_sync locations", d2_eff));
365 }
366 }
367 else {
368 dbg.dispmon(this.dispScope, MON_ERR, psprintf("PLL_CTL: d1_eff=%0d, d2_eff=%0d, d3_eff=%0d, d4=0x%h <= illegal combinations\n",
369 d1_eff, d2_eff, d3_eff, div4));
370 }
371 get_expClkPkt_func_mode = clk_pkt; // return value
372}
373
374//=============================================================
375// WHAT: compute expected values for clk pkt in dtm mode
376// review: need to revise this task to better handling rounding effect of Vera integer division
377//=============================================================
378function CCU_clk_packet CCU_clks_states::get_expClkPkt_dtm_mode() {
379 CCU_clk_packet clk_pkt = new(); // create a separate copy
380 integer nom_4_min, nom_4_max; // nominal value for calculating min and max by rounding down or up
381
382 if (! ((this.pll_ctl[CCU__PLL_CTL__PLL_DIV1__MSB : CCU__PLL_CTL__PLL_DIV1__POS] == 6'h0)
383 && (this.pll_ctl[CCU__PLL_CTL__PLL_DIV3__MSB : CCU__PLL_CTL__PLL_DIV3__POS] == 6'h1)
384 && ((this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS] == 6'h7)
385 || (this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS] == 6'ha)
386 || (this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS] == 6'he)))) {
387 dbg.dispmon(this.dispScope, MON_ERR, psprintf("pll_ctl=0x%h <= values of div1, div2, div3 are illegal for dtm mode", this.pll_ctl));
388 get_expClkPkt_dtm_mode = clk_pkt; // just satisfy function return requirement
389 return;
390 }
391
392 //---compute clk pkt---
393 clk_pkt.mode = CCU_DTM_MODE;
394 clk_pkt.pll_ctl = this.pll_ctl;
395 clk_pkt.sys_clk_per = this.sys_clk_per;
396 clk_pkt.cmp2io_ratio = this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS] + 1;
397 clk_pkt.cmp2io2x_ratio = this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS] + 1;
398 clk_pkt.cmp_mult = this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS] + 1;
399 clk_pkt.cmp_mult_frac = 0;
400 clk_pkt.dr_mult = 1;
401 clk_pkt.dr_mult_frac = 1'b0;
402 clk_pkt.cmp_per_dev = this.cmp_per_dev;
403 clk_pkt.cmp_pw_dev = this.cmp_pw_dev;
404 clk_pkt.dr_per_dev = this.dr_per_dev;
405 clk_pkt.dr_pw_dev = this.dtm_dr_iox_pw_dev;
406 clk_pkt.iox_per_dev = this.iox_per_dev;
407 clk_pkt.iox_pw_dev = this.dtm_dr_iox_pw_dev;
408
409 clk_pkt.cmp_clk_per_nom = this.sys_clk_per / clk_pkt.cmp_mult;
410 nom_4_min = clk_pkt.cmp_clk_per_nom - 1; // rounding down
411 nom_4_max = clk_pkt.cmp_clk_per_nom + 1; // rounding up
412 clk_pkt.cmp_clk_per_min = nom_4_min - (((nom_4_max / 100) + 1) * this.cmp_per_dev); // rounding down
413 clk_pkt.cmp_clk_per_max = nom_4_max + (((nom_4_max / 100) + 1) * this.cmp_per_dev); // rounding up
414
415 clk_pkt.dr_clk_per_nom = this.sys_clk_per;
416 clk_pkt.dr_clk_per_min = clk_pkt.dr_clk_per_nom - (((clk_pkt.dr_clk_per_nom / 100) + 1) * this.dr_per_dev); // rounding down
417 clk_pkt.dr_clk_per_max = clk_pkt.dr_clk_per_nom + (((clk_pkt.dr_clk_per_nom / 100) + 1) * this.dr_per_dev); // rounding up
418
419 clk_pkt.io_out_per_nom = this.sys_clk_per;
420 clk_pkt.io_out_per_min = clk_pkt.io_out_per_nom - (((clk_pkt.io_out_per_nom / 100) + 1) * this.cmp_per_dev); // rounding down
421 clk_pkt.io_out_per_max = clk_pkt.io_out_per_nom + (((clk_pkt.io_out_per_nom / 100) + 1) * this.cmp_per_dev); // rounding up
422
423 clk_pkt.io2x_out_per_nom = this.sys_clk_per;
424 clk_pkt.io2x_out_per_min = clk_pkt.io2x_out_per_nom - (((clk_pkt.io2x_out_per_nom / 100) + 1) * this.cmp_per_dev); // rounding down
425 clk_pkt.io2x_out_per_max = clk_pkt.io2x_out_per_nom + (((clk_pkt.io2x_out_per_nom / 100) + 1) * this.cmp_per_dev); // rounding up
426
427 case (clk_pkt.cmp_mult) {
428 8: { clk_pkt.dr_sync_loc[0] = 0; clk_pkt.dr_sync_loc[1] = 0; clk_pkt.dr_sync_loc[2] = 0; clk_pkt.dr_sync_loc[3] = 0; } // review: not done
429 11: { clk_pkt.dr_sync_loc[0] = 0; clk_pkt.dr_sync_loc[1] = 0; clk_pkt.dr_sync_loc[2] = 0; clk_pkt.dr_sync_loc[3] = 0; } // review: not done
430 15: { clk_pkt.dr_sync_loc[0] = 0; clk_pkt.dr_sync_loc[1] = 0; clk_pkt.dr_sync_loc[2] = 0; clk_pkt.dr_sync_loc[3] = 0; } // review: not done
431 default:
432 dbg.dispmon(this.dispScope, MON_ERR, psprintf("get_expClkPkt_dtm_mode(): div2=0x%h <= bad value",
433 this.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS]));
434 }
435 get_expClkPkt_dtm_mode = clk_pkt;
436}
437
438//=============================================================
439// WHAT: print out clk pkt for info.
440// NOTE: it's ugly to put here, but we don't want 'class CCU_clk_packet'
441// requiring a StandardDisplay handle.
442//=============================================================
443task CCU_clks_states::show_clk_pkt(CCU_clk_packet pkt) {
444 dbg.dispmon(this.dispScope, MON_INFO, psprintf("----- info of %s -----", pkt.name));
445 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- operational mode: %s", pkt.get_mode_name()));
446 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- sys_clk per: %0d ticks", pkt.sys_clk_per));
447 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- PLL_CTL=0x%h", pkt.pll_ctl));
448 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- PLL_CTL: div1=0x%h, div2=0x%h, div3=0x%h, div4=0x%h, serdes_dtm1=%b, serdes_dtm2=%b, change=%b",
449 pkt.pll_ctl[CCU__PLL_CTL__PLL_DIV1__MSB : CCU__PLL_CTL__PLL_DIV1__POS],
450 pkt.pll_ctl[CCU__PLL_CTL__PLL_DIV2__MSB : CCU__PLL_CTL__PLL_DIV2__POS],
451 pkt.pll_ctl[CCU__PLL_CTL__PLL_DIV3__MSB : CCU__PLL_CTL__PLL_DIV3__POS],
452 pkt.pll_ctl[CCU__PLL_CTL__PLL_DIV4__MSB : CCU__PLL_CTL__PLL_DIV4__POS],
453 pkt.pll_ctl[CCU__PLL_CTL__SERDES_DTM1__POS],
454 pkt.pll_ctl[CCU__PLL_CTL__SERDES_DTM2__POS],
455 pkt.pll_ctl[CCU__PLL_CTL__CHANGE__POS]));
456 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- cmp-to-sys clk ratio : %0d.%0d", pkt.cmp_mult, (pkt.cmp_mult_frac)? 5 : 0));
457 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- dr-to-sys clk ratio: dr_mult: %0d", pkt.dr_mult));
458 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- cmp-to-IO clk ratio: %0d", pkt.cmp2io_ratio));
459 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- cmp-to-IO2X clk ratio: %0d", pkt.cmp2io2x_ratio));
460 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- cmp clk period deviation limit: %0d %%", pkt.cmp_per_dev));
461 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- cmp clk pw deviation limit: %0d %%", pkt.cmp_pw_dev));
462 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- iox clk period deviation limit: %0d %%", pkt.iox_per_dev));
463 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- iox clk pw deviation limit: %0d %%", pkt.iox_pw_dev));
464 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- dr clk period deviation limit: %0d %%", pkt.dr_per_dev));
465 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- dr clk pw deviation limit: %0d %%", pkt.dr_pw_dev));
466 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- cmp clk period: nom=%0d, min=%0d, max=%0d", pkt.cmp_clk_per_nom, pkt.cmp_clk_per_min, pkt.cmp_clk_per_max));
467 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- dr clk period: nom=%0d, min=%0d, max=%0d", pkt.dr_clk_per_nom, pkt.dr_clk_per_min, pkt.dr_clk_per_max));
468 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- io clk period: nom=%0d, min=%0d, max=%0d", pkt.io_out_per_nom, pkt.io_out_per_min, pkt.io_out_per_max));
469 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- io2x clk period: nom=%0d, min=%0d, max=%0d", pkt.io2x_out_per_nom, pkt.io2x_out_per_min, pkt.io2x_out_per_max));
470 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- DR sync locations at cluster header outputs: %0d, %0d, %0d and %0d",
471 pkt.dr_sync_loc[0], pkt.dr_sync_loc[1], pkt.dr_sync_loc[2], pkt.dr_sync_loc[3]));
472 dbg.dispmon(this.dispScope, MON_INFO, psprintf("- pllbypass mode: %0d, pllbypass_virtual_div2=0x%h, pllbypass_virtual_div4=0x%h",
473 pllbypass_mode, pllbypass_virtual_div2, pllbypass_virtual_div4));
474 dbg.dispmon(this.dispScope, MON_INFO, "\n");
475}
476
477//################################################################
478//### subroutines to put/get local vars
479//################################################################
480task CCU_clks_states::put_per_pw_dev(integer cmp_per_dev, integer cmp_pw_dev,
481 integer iox_per_dev, integer iox_pw_dev,
482 integer dr_per_dev, integer dr_pw_dev) {
483 this.cmp_per_dev = cmp_per_dev;
484 this.cmp_pw_dev = cmp_pw_dev;
485 this.iox_per_dev = iox_per_dev;
486 this.iox_pw_dev = iox_pw_dev;
487 this.dr_per_dev = dr_per_dev;
488 this.dr_pw_dev = dr_pw_dev;
489}
490
491
492
493