OpenCores
URL https://opencores.org/ocsvn/uart2bus_testbench/uart2bus_testbench/trunk

Subversion Repositories uart2bus_testbench

[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [reg/] [uvm_reg_field.svh] - Blame information for rev 16

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 HanySalah
//
2
// -------------------------------------------------------------
3
//    Copyright 2004-2009 Synopsys, Inc.
4
//    Copyright 2010-2011 Mentor Graphics Corporation
5
//    Copyright 2010-2011 Cadence Design Systems, Inc.
6
//    Copyright 2013 Semifore, Inc.
7
//    All Rights Reserved Worldwide
8
//
9
//    Licensed under the Apache License, Version 2.0 (the
10
//    "License"); you may not use this file except in
11
//    compliance with the License.  You may obtain a copy of
12
//    the License at
13
//
14
//        http://www.apache.org/licenses/LICENSE-2.0
15
//
16
//    Unless required by applicable law or agreed to in
17
//    writing, software distributed under the License is
18
//    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
19
//    CONDITIONS OF ANY KIND, either express or implied.  See
20
//    the License for the specific language governing
21
//    permissions and limitations under the License.
22
// -------------------------------------------------------------
23
//
24
 
25
typedef class uvm_reg_cbs;
26
 
27
 
28
//-----------------------------------------------------------------
29
// CLASS: uvm_reg_field
30
// Field abstraction class
31
//
32
// A field represents a set of bits that behave consistently
33
// as a single entity.
34
//
35
// A field is contained within a single register, but may
36
// have different access policies depending on the address map
37
// use the access the register (thus the field).
38
//-----------------------------------------------------------------
39
class uvm_reg_field extends uvm_object;
40
 
41
   // Variable: value
42
   // Mirrored field value.
43
   // This value can be sampled in a functional coverage model
44
   // or constrained when randomized.
45
   rand  uvm_reg_data_t  value; // Mirrored after randomize()
46
 
47
   local uvm_reg_data_t  m_mirrored; // What we think is in the HW
48
   local uvm_reg_data_t  m_desired;  // Mirrored after set()
49
   local string          m_access;
50
   local uvm_reg         m_parent;
51
   local int unsigned    m_lsb;
52
   local int unsigned    m_size;
53
   local bit             m_volatile;
54
   local uvm_reg_data_t  m_reset[string];
55
   local bit             m_written;
56
   local bit             m_read_in_progress;
57
   local bit             m_write_in_progress;
58
   local string          m_fname;
59
   local int             m_lineno;
60
   local int             m_cover_on;
61
   local bit             m_individually_accessible;
62
   local uvm_check_e     m_check;
63
 
64
   local static int m_max_size;
65
   local static bit m_policy_names[string];
66
 
67
   constraint uvm_reg_field_valid {
68
      if (`UVM_REG_DATA_WIDTH > m_size) {
69
         value < (`UVM_REG_DATA_WIDTH'h1 << m_size);
70
      }
71
   }
72
 
73
   `uvm_object_utils(uvm_reg_field)
74
 
75
   //----------------------
76
   // Group: Initialization
77
   //----------------------
78
 
79
   // Function: new
80
   //
81
   // Create a new field instance
82
   //
83
   // This method should not be used directly.
84
   // The ~uvm_reg_field::type_id::create()~ factory method
85
   // should be used instead.
86
   //
87
   extern function new(string name = "uvm_reg_field");
88
 
89
 
90
   // Function: configure
91
   //
92
   // Instance-specific configuration
93
   //
94
   // Specify the ~parent~ register of this field, its
95
   // ~size~ in bits, the position of its least-significant bit
96
   // within the register relative to the least-significant bit
97
   // of the register, its ~access~ policy, volatility,
98
   // "HARD" ~reset~ value,
99
   // whether the field value is actually reset
100
   // (the ~reset~ value is ignored if ~FALSE~),
101
   // whether the field value may be randomized and
102
   // whether the field is the only one to occupy a byte lane in the register.
103
   //
104
   // See  for a specification of the pre-defined
105
   // field access policies.
106
   //
107
   // If the field access policy is a pre-defined policy and NOT one of
108
   // "RW", "WRC", "WRS", "WO", "W1", or "WO1",
109
   // the value of ~is_rand~ is ignored and the rand_mode() for the
110
   // field instance is turned off since it cannot be written.
111
   //
112
   extern function void configure(uvm_reg        parent,
113
                                  int unsigned   size,
114
                                  int unsigned   lsb_pos,
115
                                  string         access,
116
                                  bit            volatile,
117
                                  uvm_reg_data_t reset,
118
                                  bit            has_reset,
119
                                  bit            is_rand,
120
                                  bit            individually_accessible);
121
 
122
 
123
   //---------------------
124
   // Group: Introspection
125
   //---------------------
126
 
127
   // Function: get_name
128
   //
129
   // Get the simple name
130
   //
131
   // Return the simple object name of this field
132
   //
133
 
134
 
135
   // Function: get_full_name
136
   //
137
   // Get the hierarchical name
138
   //
139
   // Return the hierarchal name of this field
140
   // The base of the hierarchical name is the root block.
141
   //
142
   extern virtual function string get_full_name();
143
 
144
 
145
   // Function: get_parent
146
   //
147
   // Get the parent register
148
   //
149
   extern virtual function uvm_reg get_parent();
150
   extern virtual function uvm_reg get_register();
151
 
152
 
153
   // Function: get_lsb_pos
154
   //
155
   // Return the position of the field
156
   //
157
   // Returns the index of the least significant bit of the field
158
   // in the register that instantiates it.
159
   // An offset of 0 indicates a field that is aligned with the
160
   // least-significant bit of the register.
161
   //
162
   extern virtual function int unsigned get_lsb_pos();
163
 
164
 
165
   // Function: get_n_bits
166
   //
167
   // Returns the width, in number of bits, of the field.
168
   //
169
   extern virtual function int unsigned get_n_bits();
170
 
171
   //
172
   // FUNCTION: get_max_size
173
   // Returns the width, in number of bits, of the largest field.
174
   //
175
   extern static function int unsigned get_max_size();
176
 
177
 
178
   // Function: set_access
179
   //
180
   // Modify the access policy of the field
181
   //
182
   // Modify the access policy of the field to the specified one and
183
   // return the previous access policy.
184
   //
185
   // The pre-defined access policies are as follows.
186
   // The effect of a read operation are applied after the current
187
   // value of the field is sampled.
188
   // The read operation will return the current value,
189
   // not the value affected by the read operation (if any).
190
   //
191
   // "RO"       - W: no effect, R: no effect
192
   // "RW"       - W: as-is, R: no effect
193
   // "RC"       - W: no effect, R: clears all bits
194
   // "RS"       - W: no effect, R: sets all bits
195
   // "WRC"      - W: as-is, R: clears all bits
196
   // "WRS"      - W: as-is, R: sets all bits
197
   // "WC"       - W: clears all bits, R: no effect
198
   // "WS"       - W: sets all bits, R: no effect
199
   // "WSRC"     - W: sets all bits, R: clears all bits
200
   // "WCRS"     - W: clears all bits, R: sets all bits
201
   // "W1C"      - W: 1/0 clears/no effect on matching bit, R: no effect
202
   // "W1S"      - W: 1/0 sets/no effect on matching bit, R: no effect
203
   // "W1T"      - W: 1/0 toggles/no effect on matching bit, R: no effect
204
   // "W0C"      - W: 1/0 no effect on/clears matching bit, R: no effect
205
   // "W0S"      - W: 1/0 no effect on/sets matching bit, R: no effect
206
   // "W0T"      - W: 1/0 no effect on/toggles matching bit, R: no effect
207
   // "W1SRC"    - W: 1/0 sets/no effect on matching bit, R: clears all bits
208
   // "W1CRS"    - W: 1/0 clears/no effect on matching bit, R: sets all bits
209
   // "W0SRC"    - W: 1/0 no effect on/sets matching bit, R: clears all bits
210
   // "W0CRS"    - W: 1/0 no effect on/clears matching bit, R: sets all bits
211
   // "WO"       - W: as-is, R: error
212
   // "WOC"      - W: clears all bits, R: error
213
   // "WOS"      - W: sets all bits, R: error
214
   // "W1"       - W: first one after ~HARD~ reset is as-is, other W have no effects, R: no effect
215
   // "WO1"      - W: first one after ~HARD~ reset is as-is, other W have no effects, R: error
216
   // "NOACCESS" - W: no effect, R: no effect
217
   //
218
   // It is important to remember that modifying the access of a field
219
   // will make the register model diverge from the specification
220
   // that was used to create it.
221
   //
222
   extern virtual function string set_access(string mode);
223
 
224
 
225
   // Function: define_access
226
   //
227
   // Define a new access policy value
228
   //
229
   // Because field access policies are specified using string values,
230
   // there is no way for SystemVerilog to verify if a specific access
231
   // value is valid or not.
232
   // To help catch typing errors, user-defined access values
233
   // must be defined using this method to avoid begin reported as an
234
   // invalid access policy.
235
   //
236
   // The name of field access policies are always converted to all uppercase.
237
   //
238
   // Returns TRUE if the new access policy was not previously
239
   // defined.
240
   // Returns FALSE otherwise but does not issue an error message.
241
   //
242
   extern static function bit define_access(string name);
243
   local static bit m_predefined = m_predefine_policies();
244
   extern local static function bit m_predefine_policies();
245
 
246
   // Function: get_access
247
   //
248
   // Get the access policy of the field
249
   //
250
   // Returns the current access policy of the field
251
   // when written and read through the specified address ~map~.
252
   // If the register containing the field is mapped in multiple
253
   // address map, an address map must be specified.
254
   // The access policy of a field from a specific
255
   // address map may be restricted by the register's access policy in that
256
   // address map.
257
   // For example, a RW field may only be writable through one of
258
   // the address maps and read-only through all of the other maps.
259
   // If the field access contradicts the map's access value
260
   // (field access of WO, and map access value of RO, etc), the
261
   // method's return value is NOACCESS.
262
 
263
   extern virtual function string get_access(uvm_reg_map map = null);
264
 
265
 
266
   // Function: is_known_access
267
   //
268
   // Check if access policy is a built-in one.
269
   //
270
   // Returns TRUE if the current access policy of the field,
271
   // when written and read through the specified address ~map~,
272
   // is a built-in access policy.
273
   //
274
   extern virtual function bit is_known_access(uvm_reg_map map = null);
275
 
276
   //
277
   // Function: set_volatility
278
   // Modify the volatility of the field to the specified one.
279
   //
280
   // It is important to remember that modifying the volatility of a field
281
   // will make the register model diverge from the specification
282
   // that was used to create it.
283
   //
284
   extern virtual function void set_volatility(bit volatile);
285
 
286
   //
287
   // Function: is_volatile
288
   // Indicates if the field value is volatile
289
   //
290
   // UVM uses the IEEE 1685-2009 IP-XACT definition of "volatility".
291
   // If TRUE, the value of the register is not predictable because it
292
   // may change between consecutive accesses.
293
   // This typically indicates a field whose value is updated by the DUT.
294
   // The nature or cause of the change is not specified.
295
   // If FALSE, the value of the register is not modified between
296
   // consecutive accesses.
297
   //
298
   extern virtual function bit is_volatile();
299
 
300
 
301
   //--------------
302
   // Group: Access
303
   //--------------
304
 
305
 
306
   // Function: set
307
   //
308
   // Set the desired value for this field
309
   //
310
   // It sets the desired value of the field to the specified ~value~
311
   // modified by the field access policy.
312
   // It does not actually set the value of the field in the design,
313
   // only the desired value in the abstraction class.
314
   // Use the  method to update the actual register
315
   // with the desired value or the  method
316
   // to actually write the field and update its mirrored value.
317
   //
318
   // The final desired value in the mirror is a function of the field access
319
   // policy and the set value, just like a normal physical write operation
320
   // to the corresponding bits in the hardware.
321
   // As such, this method (when eventually followed by a call to
322
   // )
323
   // is a zero-time functional replacement for the 
324
   // method.
325
   // For example, the desired value of a read-only field is not modified
326
   // by this method and the desired value of a write-once field can only
327
   // be set if the field has not yet been
328
   // written to using a physical (for example, front-door) write operation.
329
   //
330
   // Use the  to modify the mirrored value of
331
   // the field.
332
   //
333
   extern virtual function void set(uvm_reg_data_t  value,
334
                                    string          fname = "",
335
                                    int             lineno = 0);
336
 
337
   // Function: get
338
   //
339
   // Return the desired value of the field
340
   //
341
   // It does not actually read the value
342
   // of the field in the design, only the desired value
343
   // in the abstraction class. Unless set to a different value
344
   // using the , the desired value
345
   // and the mirrored value are identical.
346
   //
347
   // Use the  or 
348
   // method to get the actual field value.
349
   //
350
   // If the field is write-only, the desired/mirrored
351
   // value is the value last written and assumed
352
   // to reside in the bits implementing it.
353
   // Although a physical read operation would something different,
354
   // the returned value is the actual content.
355
   //
356
   extern virtual function uvm_reg_data_t get(string fname = "",
357
                                              int    lineno = 0);
358
 
359
 
360
   // Function: get_mirrored_value
361
   //
362
   // Return the mirrored value of the field
363
   //
364
   // It does not actually read the value of the field in the design, only the mirrored value
365
   // in the abstraction class.
366
   //
367
   // If the field is write-only, the desired/mirrored
368
   // value is the value last written and assumed
369
   // to reside in the bits implementing it.
370
   // Although a physical read operation would something different,
371
   // the returned value is the actual content.
372
   //
373
   extern virtual function uvm_reg_data_t get_mirrored_value(string fname = "",
374
                                              int    lineno = 0);
375
 
376
   // Function: reset
377
   //
378
   // Reset the desired/mirrored value for this field.
379
   //
380
   // It sets the desired and mirror value of the field
381
   // to the reset event specified by ~kind~.
382
   // If the field does not have a reset value specified for the
383
   // specified reset ~kind~ the field is unchanged.
384
   //
385
   // It does not actually reset the value of the field in the design,
386
   // only the value mirrored in the field abstraction class.
387
   //
388
   // Write-once fields can be modified after
389
   // a "HARD" reset operation.
390
   //
391
   extern virtual function void reset(string kind = "HARD");
392
 
393
 
394
   // Function: get_reset
395
   //
396
   // Get the specified reset value for this field
397
   //
398
   // Return the reset value for this field
399
   // for the specified reset ~kind~.
400
   // Returns the current field value is no reset value has been
401
   // specified for the specified reset event.
402
   //
403
   extern virtual function uvm_reg_data_t get_reset(string kind = "HARD");
404
 
405
 
406
   // Function: has_reset
407
   //
408
   // Check if the field has a reset value specified
409
   //
410
   // Return TRUE if this field has a reset value specified
411
   // for the specified reset ~kind~.
412
   // If ~delete~ is TRUE, removes the reset value, if any.
413
   //
414
   extern virtual function bit has_reset(string kind = "HARD",
415
                                         bit    delete = 0);
416
 
417
 
418
   // Function: set_reset
419
   //
420
   // Specify or modify the reset value for this field
421
   //
422
   // Specify or modify the reset value for this field corresponding
423
   // to the cause specified by ~kind~.
424
   //
425
   extern virtual function void set_reset(uvm_reg_data_t value,
426
                                          string kind = "HARD");
427
 
428
 
429
   // Function: needs_update
430
   //
431
   // Check if the abstract model contains different desired and mirrored values.
432
   //
433
   // If a desired field value has been modified in the abstraction class
434
   // without actually updating the field in the DUT,
435
   // the state of the DUT (more specifically what the abstraction class
436
   // ~thinks~ the state of the DUT is) is outdated.
437
   // This method returns TRUE
438
   // if the state of the field in the DUT needs to be updated
439
   // to match the desired value.
440
   // The mirror values or actual content of DUT field are not modified.
441
   // Use the  to actually update the DUT field.
442
   //
443
   extern virtual function bit needs_update();
444
 
445
 
446
   // Task: write
447
   //
448
   // Write the specified value in this field
449
   //
450
   // Write ~value~ in the DUT field that corresponds to this
451
   // abstraction class instance using the specified access
452
   // ~path~.
453
   // If the register containing this field is mapped in more
454
   //  than one address map,
455
   // an address ~map~ must be
456
   // specified if a physical access is used (front-door access).
457
   // If a back-door access path is used, the effect of writing
458
   // the field through a physical access is mimicked. For
459
   // example, read-only bits in the field will not be written.
460
   //
461
   // The mirrored value will be updated using the 
462
   // method.
463
   //
464
   // If a front-door access is used, and
465
   // if the field is the only field in a byte lane and
466
   // if the physical interface corresponding to the address map used
467
   // to access the field support byte-enabling,
468
   // then only the field is written.
469
   // Otherwise, the entire register containing the field is written,
470
   // and the mirrored values of the other fields in the same register
471
   // are used in a best-effort not to modify their value.
472
   //
473
   // If a backdoor access is used, a peek-modify-poke process is used.
474
   // in a best-effort not to modify the value of the other fields in the
475
   // register.
476
   //
477
   extern virtual task write (output uvm_status_e       status,
478
                              input  uvm_reg_data_t     value,
479
                              input  uvm_path_e         path = UVM_DEFAULT_PATH,
480
                              input  uvm_reg_map        map = null,
481
                              input  uvm_sequence_base  parent = null,
482
                              input  int                prior = -1,
483
                              input  uvm_object         extension = null,
484
                              input  string             fname = "",
485
                              input  int                lineno = 0);
486
 
487
 
488
   // Task: read
489
   //
490
   // Read the current value from this field
491
   //
492
   // Read and return ~value~ from the DUT field that corresponds to this
493
   // abstraction class instance using the specified access
494
   // ~path~.
495
   // If the register containing this field is mapped in more
496
   // than one address map, an address ~map~ must be
497
   // specified if a physical access is used (front-door access).
498
   // If a back-door access path is used, the effect of reading
499
   // the field through a physical access is mimicked. For
500
   // example, clear-on-read bits in the field will be set to zero.
501
   //
502
   // The mirrored value will be updated using the 
503
   // method.
504
   //
505
   // If a front-door access is used, and
506
   // if the field is the only field in a byte lane and
507
   // if the physical interface corresponding to the address map used
508
   // to access the field support byte-enabling,
509
   // then only the field is read.
510
   // Otherwise, the entire register containing the field is read,
511
   // and the mirrored values of the other fields in the same register
512
   // are updated.
513
   //
514
   // If a backdoor access is used, the entire containing register is peeked
515
   // and the mirrored value of the other fields in the register is updated.
516
   //
517
   extern virtual task read  (output uvm_status_e       status,
518
                              output uvm_reg_data_t     value,
519
                              input  uvm_path_e         path = UVM_DEFAULT_PATH,
520
                              input  uvm_reg_map        map = null,
521
                              input  uvm_sequence_base  parent = null,
522
                              input  int                prior = -1,
523
                              input  uvm_object         extension = null,
524
                              input  string             fname = "",
525
                              input  int                lineno = 0);
526
 
527
 
528
   // Task: poke
529
   //
530
   // Deposit the specified value in this field
531
   //
532
   // Deposit the value in the DUT field corresponding to this
533
   // abstraction class instance, as-is, using a back-door access.
534
   // A peek-modify-poke process is used
535
   // in a best-effort not to modify the value of the other fields in the
536
   // register.
537
   //
538
   // The mirrored value will be updated using the 
539
   // method.
540
   //
541
   extern virtual task poke  (output uvm_status_e       status,
542
                              input  uvm_reg_data_t     value,
543
                              input  string             kind = "",
544
                              input  uvm_sequence_base  parent = null,
545
                              input  uvm_object         extension = null,
546
                              input  string             fname = "",
547
                              input  int                lineno = 0);
548
 
549
 
550
   // Task: peek
551
   //
552
   // Read the current value from this field
553
   //
554
   // Sample the value in the DUT field corresponding to this
555
   // abstraction class instance using a back-door access.
556
   // The field value is sampled, not modified.
557
   //
558
   // Uses the HDL path for the design abstraction specified by ~kind~.
559
   //
560
   // The entire containing register is peeked
561
   // and the mirrored value of the other fields in the register
562
   // are updated using the  method.
563
   //
564
   //
565
   extern virtual task peek  (output uvm_status_e       status,
566
                              output uvm_reg_data_t     value,
567
                              input  string             kind = "",
568
                              input  uvm_sequence_base  parent = null,
569
                              input  uvm_object         extension = null,
570
                              input  string             fname = "",
571
                              input  int                lineno = 0);
572
 
573
 
574
   // Task: mirror
575
   //
576
   // Read the field and update/check its mirror value
577
   //
578
   // Read the field and optionally compared the readback value
579
   // with the current mirrored value if ~check~ is .
580
   // The mirrored value will be updated using the 
581
   // method based on the readback value.
582
   //
583
   // The ~path~ argument specifies whether to mirror using
584
   // the   () or
585
   //  ().
586
   //
587
   // If ~check~ is specified as ,
588
   // an error message is issued if the current mirrored value
589
   // does not match the readback value, unless  was used
590
   // disable the check.
591
   //
592
   // If the containing register is mapped in multiple address maps and physical
593
   // access is used (front-door access), an address ~map~ must be specified.
594
   // For write-only fields, their content is mirrored and optionally
595
   // checked only if a UVM_BACKDOOR
596
   // access path is used to read the field.
597
   //
598
   extern virtual task mirror(output uvm_status_e      status,
599
                              input  uvm_check_e       check = UVM_NO_CHECK,
600
                              input  uvm_path_e        path = UVM_DEFAULT_PATH,
601
                              input  uvm_reg_map       map = null,
602
                              input  uvm_sequence_base parent = null,
603
                              input  int               prior = -1,
604
                              input  uvm_object        extension = null,
605
                              input  string            fname = "",
606
                              input  int               lineno = 0);
607
 
608
 
609
   // Function: set_compare
610
   //
611
   // Sets the compare policy during a mirror update.
612
   // The field value is checked against its mirror only when both the
613
   // ~check~ argument in , ,
614
   // or  and the compare policy for the
615
   // field is .
616
   //
617
   extern function void set_compare(uvm_check_e check=UVM_CHECK);
618
 
619
 
620
   // Function: get_compare
621
   //
622
   // Returns the compare policy for this field.
623
   //
624
   extern function uvm_check_e get_compare();
625
 
626
 
627
   // Function: is_indv_accessible
628
   //
629
   // Check if this field can be written individually, i.e. without
630
   // affecting other fields in the containing register.
631
   //
632
   extern function bit is_indv_accessible (uvm_path_e  path,
633
                                           uvm_reg_map local_map);
634
 
635
 
636
   // Function: predict
637
   //
638
   // Update the mirrored and desired value for this field.
639
   //
640
   // Predict the mirror and desired value of the field based on the specified
641
   // observed ~value~ on a bus using the specified address ~map~.
642
   //
643
   // If ~kind~ is specified as , the value
644
   // was observed in a read transaction on the specified address ~map~ or
645
   // backdoor (if ~path~ is ).
646
   // If ~kind~ is specified as , the value
647
   // was observed in a write transaction on the specified address ~map~ or
648
   // backdoor (if ~path~ is ).
649
   // If ~kind~ is specified as , the value
650
   // was computed and is updated as-is, without regard to any access policy.
651
   // For example, the mirrored value of a read-only field is modified
652
   // by this method if ~kind~ is specified as .
653
   //
654
   // This method does not allow an update of the mirror (or desired)
655
   // when the register containing this field is busy executing
656
   // a transaction because the results are unpredictable and
657
   // indicative of a race condition in the testbench.
658
   //
659
   // Returns TRUE if the prediction was successful.
660
   //
661
   extern function bit predict (uvm_reg_data_t    value,
662
                                uvm_reg_byte_en_t be = -1,
663
                                uvm_predict_e     kind = UVM_PREDICT_DIRECT,
664
                                uvm_path_e        path = UVM_FRONTDOOR,
665
                                uvm_reg_map       map = null,
666
                                string            fname = "",
667
                                int               lineno = 0);
668
 
669
 
670
 
671
   /*local*/
672
   extern virtual function uvm_reg_data_t XpredictX (uvm_reg_data_t cur_val,
673
                                                     uvm_reg_data_t wr_val,
674
                                                     uvm_reg_map    map);
675
 
676
   /*local*/
677
   extern virtual function uvm_reg_data_t XupdateX();
678
 
679
   /*local*/
680
   extern function bit Xcheck_accessX (input uvm_reg_item rw,
681
                                       output uvm_reg_map_info map_info,
682
                                       input string caller);
683
 
684
   extern virtual task do_write(uvm_reg_item rw);
685
   extern virtual task do_read(uvm_reg_item rw);
686
   extern virtual function void do_predict
687
                                  (uvm_reg_item rw,
688
                                   uvm_predict_e kind=UVM_PREDICT_DIRECT,
689
                                   uvm_reg_byte_en_t be = -1);
690
 
691
 
692
   extern function void pre_randomize();
693
   extern function void post_randomize();
694
 
695
 
696
   //-----------------
697
   // Group: Callbacks
698
   //-----------------
699
 
700
   `uvm_register_cb(uvm_reg_field, uvm_reg_cbs)
701
 
702
 
703
   // Task: pre_write
704
   //
705
   // Called before field write.
706
   //
707
   // If the specified data value, access ~path~ or address ~map~ are modified,
708
   // the updated data value, access path or address map will be used
709
   // to perform the register operation.
710
   // If the ~status~ is modified to anything other than ,
711
   // the operation is aborted.
712
   //
713
   // The field callback methods are invoked after the callback methods
714
   // on the containing register.
715
   // The registered callback methods are invoked after the invocation
716
   // of this method.
717
   //
718
   virtual task pre_write  (uvm_reg_item rw); endtask
719
 
720
 
721
   // Task: post_write
722
   //
723
   // Called after field write.
724
   //
725
   // If the specified ~status~ is modified,
726
   // the updated status will be
727
   // returned by the register operation.
728
   //
729
   // The field callback methods are invoked after the callback methods
730
   // on the containing register.
731
   // The registered callback methods are invoked before the invocation
732
   // of this method.
733
   //
734
   virtual task post_write (uvm_reg_item rw); endtask
735
 
736
 
737
   // Task: pre_read
738
   //
739
   // Called before field read.
740
   //
741
   // If the access ~path~ or address ~map~ in the ~rw~ argument are modified,
742
   // the updated access path or address map will be used to perform
743
   // the register operation.
744
   // If the ~status~ is modified to anything other than ,
745
   // the operation is aborted.
746
   //
747
   // The field callback methods are invoked after the callback methods
748
   // on the containing register.
749
   // The registered callback methods are invoked after the invocation
750
   // of this method.
751
   //
752
   virtual task pre_read (uvm_reg_item rw); endtask
753
 
754
 
755
   // Task: post_read
756
   //
757
   // Called after field read.
758
   //
759
   // If the specified readback data or~status~ in the ~rw~ argument is
760
   // modified, the updated readback data or status will be
761
   // returned by the register operation.
762
   //
763
   // The field callback methods are invoked after the callback methods
764
   // on the containing register.
765
   // The registered callback methods are invoked before the invocation
766
   // of this method.
767
   //
768
   virtual task post_read  (uvm_reg_item rw); endtask
769
 
770
 
771
   extern virtual function void do_print (uvm_printer printer);
772
   extern virtual function string convert2string;
773
   extern virtual function uvm_object clone();
774
   extern virtual function void do_copy   (uvm_object rhs);
775
   extern virtual function bit  do_compare (uvm_object  rhs,
776
                                            uvm_comparer comparer);
777
   extern virtual function void do_pack (uvm_packer packer);
778
   extern virtual function void do_unpack (uvm_packer packer);
779
 
780
endclass: uvm_reg_field
781
 
782
 
783
//------------------------------------------------------------------------------
784
// IMPLEMENTATION
785
//------------------------------------------------------------------------------
786
 
787
// new
788
 
789
function uvm_reg_field::new(string name = "uvm_reg_field");
790
   super.new(name);
791
endfunction: new
792
 
793
 
794
// configure
795
 
796
function void uvm_reg_field::configure(uvm_reg        parent,
797
                                       int unsigned   size,
798
                                       int unsigned   lsb_pos,
799
                                       string         access,
800
                                       bit            volatile,
801
                                       uvm_reg_data_t reset,
802
                                       bit            has_reset,
803
                                       bit            is_rand,
804
                                       bit            individually_accessible);
805
   m_parent = parent;
806
   if (size == 0) begin
807
      `uvm_error("RegModel",
808
         $sformatf("Field \"%s\" cannot have 0 bits", get_full_name()));
809
      size = 1;
810
   end
811
 
812
   m_size      = size;
813
   m_volatile  = volatile;
814
   m_access    = access.toupper();
815
   m_lsb       = lsb_pos;
816
   m_cover_on  = UVM_NO_COVERAGE;
817
   m_written   = 0;
818
   m_check     = volatile ? UVM_NO_CHECK : UVM_CHECK;
819
   m_individually_accessible = individually_accessible;
820
 
821
   if (has_reset)
822
      set_reset(reset);
823
   else
824
      uvm_resource_db#(bit)::set({"REG::", get_full_name()},
825
                                 "NO_REG_HW_RESET_TEST", 1);
826
 
827
   m_parent.add_field(this);
828
 
829
   if (!m_policy_names.exists(m_access)) begin
830
      `uvm_error("RegModel", {"Access policy '",access,
831
       "' for field '",get_full_name(),"' is not defined. Setting to RW"})
832
      m_access = "RW";
833
   end
834
 
835
   if (size > m_max_size)
836
      m_max_size = size;
837
 
838
   // Ignore is_rand if the field is known not to be writeable
839
   // i.e. not "RW", "WRC", "WRS", "WO", "W1", "WO1"
840
   case (access)
841
    "RO", "RC", "RS", "WC", "WS",
842
      "W1C", "W1S", "W1T", "W0C", "W0S", "W0T",
843
      "W1SRC", "W1CRS", "W0SRC", "W0CRS", "WSRC", "WCRS",
844
      "WOC", "WOS": is_rand = 0;
845
   endcase
846
 
847
   if (!is_rand)
848
     value.rand_mode(0);
849
 
850
endfunction: configure
851
 
852
 
853
// get_parent
854
 
855
function uvm_reg uvm_reg_field::get_parent();
856
   return m_parent;
857
endfunction: get_parent
858
 
859
 
860
// get_full_name
861
 
862
function string uvm_reg_field::get_full_name();
863
   return {m_parent.get_full_name(), ".", get_name()};
864
endfunction: get_full_name
865
 
866
 
867
// get_register
868
 
869
function uvm_reg uvm_reg_field::get_register();
870
   return m_parent;
871
endfunction: get_register
872
 
873
 
874
// get_lsb_pos
875
 
876
function int unsigned uvm_reg_field::get_lsb_pos();
877
   return m_lsb;
878
endfunction: get_lsb_pos
879
 
880
 
881
// get_n_bits
882
 
883
function int unsigned uvm_reg_field::get_n_bits();
884
   return m_size;
885
endfunction: get_n_bits
886
 
887
 
888
// get_max_size
889
 
890
function int unsigned uvm_reg_field::get_max_size();
891
   return m_max_size;
892
endfunction: get_max_size
893
 
894
 
895
// is_known_access
896
 
897
function bit uvm_reg_field::is_known_access(uvm_reg_map map = null);
898
   string acc = get_access(map);
899
   case (acc)
900
    "RO", "RW", "RC", "RS", "WC", "WS",
901
      "W1C", "W1S", "W1T", "W0C", "W0S", "W0T",
902
      "WRC", "WRS", "W1SRC", "W1CRS", "W0SRC", "W0CRS", "WSRC", "WCRS",
903
      "WO", "WOC", "WOS", "W1", "WO1" : return 1;
904
   endcase
905
   return 0;
906
endfunction
907
 
908
 
909
// get_access
910
 
911
function string uvm_reg_field::get_access(uvm_reg_map map = null);
912
   string field_access = m_access;
913
 
914
   if (map == uvm_reg_map::backdoor())
915
     return field_access;
916
 
917
   // Is the register restricted in this map?
918
   case (m_parent.get_rights(map))
919
     "RW":
920
       // No restrictions
921
       return field_access;
922
 
923
     "RO":
924
       case (field_access)
925
        "RW", "RO", "WC", "WS",
926
          "W1C", "W1S", "W1T", "W0C", "W0S", "W0T",
927
          "W1"
928
        : field_access = "RO";
929
 
930
        "RC", "WRC", "W1SRC", "W0SRC", "WSRC"
931
        : field_access = "RC";
932
 
933
        "RS", "WRS", "W1CRS", "W0CRS", "WCRS"
934
        : field_access = "RS";
935
 
936
         "WO", "WOC", "WOS", "WO1": begin
937
            field_access = "NOACCESS";
938
         end
939
 
940
         // No change for the other modes
941
       endcase
942
 
943
     "WO":
944
       case (field_access)
945
         "RW",
946
         "WO": field_access = "WO";
947
         default: begin
948
            field_access = "NOACCESS";
949
         end
950
 
951
         // No change for the other modes
952
       endcase
953
 
954
     default:
955
       begin
956
         field_access = "NOACCESS";
957
         `uvm_warning("RegModel", {"Register '",m_parent.get_full_name(),
958
                      "' containing field '",get_name(),"' is mapped in map '",
959
                      map.get_full_name(),"' with unknown access right '", m_parent.get_rights(map), "'"})
960
       end
961
   endcase
962
   return field_access;
963
endfunction: get_access
964
 
965
 
966
// set_access
967
 
968
function string uvm_reg_field::set_access(string mode);
969
   set_access = m_access;
970
   m_access = mode.toupper();
971
   if (!m_policy_names.exists(m_access)) begin
972
      `uvm_error("RegModel", {"Access policy '",m_access,
973
                              "' is not a defined field access policy"})
974
      m_access = set_access;
975
   end
976
endfunction: set_access
977
 
978
 
979
// define_access
980
 
981
function bit uvm_reg_field::define_access(string name);
982
   if (!m_predefined) m_predefined = m_predefine_policies();
983
 
984
   name = name.toupper();
985
 
986
   if (m_policy_names.exists(name)) return 0;
987
 
988
   m_policy_names[name] = 1;
989
   return 1;
990
endfunction
991
 
992
 
993
// m_predefined_policies
994
 
995
function bit uvm_reg_field::m_predefine_policies();
996
   if (m_predefined) return 1;
997
 
998
   m_predefined = 1;
999
 
1000
   void'(define_access("RO"));
1001
   void'(define_access("RW"));
1002
   void'(define_access("RC"));
1003
   void'(define_access("RS"));
1004
   void'(define_access("WRC"));
1005
   void'(define_access("WRS"));
1006
   void'(define_access("WC"));
1007
   void'(define_access("WS"));
1008
   void'(define_access("WSRC"));
1009
   void'(define_access("WCRS"));
1010
   void'(define_access("W1C"));
1011
   void'(define_access("W1S"));
1012
   void'(define_access("W1T"));
1013
   void'(define_access("W0C"));
1014
   void'(define_access("W0S"));
1015
   void'(define_access("W0T"));
1016
   void'(define_access("W1SRC"));
1017
   void'(define_access("W1CRS"));
1018
   void'(define_access("W0SRC"));
1019
   void'(define_access("W0CRS"));
1020
   void'(define_access("WO"));
1021
   void'(define_access("WOC"));
1022
   void'(define_access("WOS"));
1023
   void'(define_access("W1"));
1024
   void'(define_access("WO1"));
1025
   return 1;
1026
endfunction
1027
 
1028
 
1029
// set_volatility
1030
 
1031
function void uvm_reg_field::set_volatility(bit volatile);
1032
   m_volatile = volatile;
1033
endfunction
1034
 
1035
 
1036
// is_volatile
1037
 
1038
function bit uvm_reg_field::is_volatile();
1039
   return m_volatile;
1040
endfunction
1041
 
1042
 
1043
// XpredictX
1044
 
1045
function uvm_reg_data_t uvm_reg_field::XpredictX (uvm_reg_data_t cur_val,
1046
                                                  uvm_reg_data_t wr_val,
1047
                                                  uvm_reg_map    map);
1048
   uvm_reg_data_t mask = ('b1 << m_size)-1;
1049
 
1050
   case (get_access(map))
1051
     "RO":    return cur_val;
1052
     "RW":    return wr_val;
1053
     "RC":    return cur_val;
1054
     "RS":    return cur_val;
1055
     "WC":    return '0;
1056
     "WS":    return mask;
1057
     "WRC":   return wr_val;
1058
     "WRS":   return wr_val;
1059
     "WSRC":  return mask;
1060
     "WCRS":  return '0;
1061
     "W1C":   return cur_val & (~wr_val);
1062
     "W1S":   return cur_val | wr_val;
1063
     "W1T":   return cur_val ^ wr_val;
1064
     "W0C":   return cur_val & wr_val;
1065
     "W0S":   return cur_val | (~wr_val & mask);
1066
     "W0T":   return cur_val ^ (~wr_val & mask);
1067
     "W1SRC": return cur_val | wr_val;
1068
     "W1CRS": return cur_val & (~wr_val);
1069
     "W0SRC": return cur_val | (~wr_val & mask);
1070
     "W0CRS": return cur_val & wr_val;
1071
     "WO":    return wr_val;
1072
     "WOC":   return '0;
1073
     "WOS":   return mask;
1074
     "W1":    return (m_written) ? cur_val : wr_val;
1075
     "WO1":   return (m_written) ? cur_val : wr_val;
1076
     "NOACCESS": return cur_val;
1077
     default: return wr_val;
1078
   endcase
1079
 
1080
   `uvm_fatal("RegModel", "uvm_reg_field::XpredictX(): Internal error");
1081
   return 0;
1082
endfunction: XpredictX
1083
 
1084
 
1085
 
1086
// predict
1087
 
1088
function bit uvm_reg_field::predict (uvm_reg_data_t    value,
1089
                                     uvm_reg_byte_en_t be = -1,
1090
                                     uvm_predict_e     kind = UVM_PREDICT_DIRECT,
1091
                                     uvm_path_e        path = UVM_FRONTDOOR,
1092
                                     uvm_reg_map       map = null,
1093
                                     string            fname = "",
1094
                                     int               lineno = 0);
1095
  uvm_reg_item rw = new;
1096
  rw.value[0] = value;
1097
  rw.path = path;
1098
  rw.map = map;
1099
  rw.fname = fname;
1100
  rw.lineno = lineno;
1101
  do_predict(rw, kind, be);
1102
  predict = (rw.status == UVM_NOT_OK) ? 0 : 1;
1103
endfunction: predict
1104
 
1105
 
1106
// do_predict
1107
 
1108
function void uvm_reg_field::do_predict(uvm_reg_item      rw,
1109
                                        uvm_predict_e     kind = UVM_PREDICT_DIRECT,
1110
                                        uvm_reg_byte_en_t be = -1);
1111
 
1112
   uvm_reg_data_t field_val = rw.value[0] & ((1 << m_size)-1);
1113
 
1114
   if (rw.status != UVM_NOT_OK)
1115
     rw.status = UVM_IS_OK;
1116
 
1117
   // Assume that the entire field is enabled
1118
   if (!be[0])
1119
     return;
1120
 
1121
   m_fname = rw.fname;
1122
   m_lineno = rw.lineno;
1123
 
1124
   case (kind)
1125
 
1126
     UVM_PREDICT_WRITE:
1127
       begin
1128
         uvm_reg_field_cb_iter cbs = new(this);
1129
 
1130
         if (rw.path == UVM_FRONTDOOR || rw.path == UVM_PREDICT)
1131
            field_val = XpredictX(m_mirrored, field_val, rw.map);
1132
 
1133
         m_written = 1;
1134
 
1135
         for (uvm_reg_cbs cb = cbs.first(); cb != null; cb = cbs.next())
1136
            cb.post_predict(this, m_mirrored, field_val,
1137
                            UVM_PREDICT_WRITE, rw.path, rw.map);
1138
 
1139
         field_val &= ('b1 << m_size)-1;
1140
 
1141
       end
1142
 
1143
     UVM_PREDICT_READ:
1144
       begin
1145
         uvm_reg_field_cb_iter cbs = new(this);
1146
 
1147
         if (rw.path == UVM_FRONTDOOR || rw.path == UVM_PREDICT) begin
1148
 
1149
            string acc = get_access(rw.map);
1150
 
1151
            if (acc == "RC" ||
1152
                acc == "WRC" ||
1153
                acc == "WSRC" ||
1154
                acc == "W1SRC" ||
1155
                acc == "W0SRC")
1156
              field_val = 0;  // (clear)
1157
 
1158
            else if (acc == "RS" ||
1159
                     acc == "WRS" ||
1160
                     acc == "WCRS" ||
1161
                     acc == "W1CRS" ||
1162
                     acc == "W0CRS")
1163
              field_val = ('b1 << m_size)-1; // all 1's (set)
1164
 
1165
            else if (acc == "WO" ||
1166
                     acc == "WOC" ||
1167
                     acc == "WOS" ||
1168
                     acc == "WO1" ||
1169
                     acc == "NOACCESS")
1170
              return;
1171
         end
1172
 
1173
         for (uvm_reg_cbs cb = cbs.first(); cb != null; cb = cbs.next())
1174
            cb.post_predict(this, m_mirrored, field_val,
1175
                            UVM_PREDICT_READ, rw.path, rw.map);
1176
 
1177
         field_val &= ('b1 << m_size)-1;
1178
 
1179
       end
1180
 
1181
     UVM_PREDICT_DIRECT:
1182
       begin
1183
         if (m_parent.is_busy()) begin
1184
           `uvm_warning("RegModel", {"Trying to predict value of field '",
1185
              get_name(),"' while register '",m_parent.get_full_name(),
1186
              "' is being accessed"})
1187
           rw.status = UVM_NOT_OK;
1188
         end
1189
       end
1190
   endcase
1191
 
1192
   // update the mirror with predicted value
1193
   m_mirrored = field_val;
1194
   m_desired  = field_val;
1195
   this.value = field_val;
1196
 
1197
endfunction: do_predict
1198
 
1199
 
1200
// XupdateX
1201
 
1202
function uvm_reg_data_t  uvm_reg_field::XupdateX();
1203
   // Figure out which value must be written to get the desired value
1204
   // given what we think is the current value in the hardware
1205
   XupdateX = 0;
1206
 
1207
   case (m_access)
1208
      "RO":    XupdateX = m_desired;
1209
      "RW":    XupdateX = m_desired;
1210
      "RC":    XupdateX = m_desired;
1211
      "RS":    XupdateX = m_desired;
1212
      "WRC":   XupdateX = m_desired;
1213
      "WRS":   XupdateX = m_desired;
1214
      "WC":    XupdateX = m_desired;  // Warn if != 0
1215
      "WS":    XupdateX = m_desired;  // Warn if != 1
1216
      "WSRC":  XupdateX = m_desired;  // Warn if != 1
1217
      "WCRS":  XupdateX = m_desired;  // Warn if != 0
1218
      "W1C":   XupdateX = ~m_desired;
1219
      "W1S":   XupdateX = m_desired;
1220
      "W1T":   XupdateX = m_desired ^ m_mirrored;
1221
      "W0C":   XupdateX = m_desired;
1222
      "W0S":   XupdateX = ~m_desired;
1223
      "W0T":   XupdateX = ~(m_desired ^ m_mirrored);
1224
      "W1SRC": XupdateX = m_desired;
1225
      "W1CRS": XupdateX = ~m_desired;
1226
      "W0SRC": XupdateX = ~m_desired;
1227
      "W0CRS": XupdateX = m_desired;
1228
      "WO":    XupdateX = m_desired;
1229
      "WOC":   XupdateX = m_desired;  // Warn if != 0
1230
      "WOS":   XupdateX = m_desired;  // Warn if != 1
1231
      "W1":    XupdateX = m_desired;
1232
      "WO1":   XupdateX = m_desired;
1233
      default: XupdateX = m_desired;
1234
   endcase
1235
   XupdateX &= (1 << m_size) - 1;
1236
 
1237
endfunction: XupdateX
1238
 
1239
 
1240
// set
1241
 
1242
function void uvm_reg_field::set(uvm_reg_data_t  value,
1243
                                 string          fname = "",
1244
                                 int             lineno = 0);
1245
   uvm_reg_data_t mask = ('b1 << m_size)-1;
1246
 
1247
   m_fname = fname;
1248
   m_lineno = lineno;
1249
   if (value >> m_size) begin
1250
      `uvm_warning("RegModel",
1251
         $sformatf("Specified value (0x%h) greater than field \"%s\" size (%0d bits)",
1252
             value, get_name(), m_size));
1253
      value &= mask;
1254
   end
1255
 
1256
   if (m_parent.is_busy()) begin
1257
      `uvm_warning("UVM/FLD/SET/BSY",
1258
                   $sformatf("Setting the value of field \"%s\" while containing register \"%s\" is being accessed may result in loss of desired field value. A race condition between threads concurrently accessing the register model is the likely cause of the problem.",
1259
                             get_name(), m_parent.get_full_name()))
1260
   end
1261
 
1262
   case (m_access)
1263
      "RO":    m_desired = m_desired;
1264
      "RW":    m_desired = value;
1265
      "RC":    m_desired = m_desired;
1266
      "RS":    m_desired = m_desired;
1267
      "WC":    m_desired = '0;
1268
      "WS":    m_desired = mask;
1269
      "WRC":   m_desired = value;
1270
      "WRS":   m_desired = value;
1271
      "WSRC":  m_desired = mask;
1272
      "WCRS":  m_desired = '0;
1273
      "W1C":   m_desired = m_desired & (~value);
1274
      "W1S":   m_desired = m_desired | value;
1275
      "W1T":   m_desired = m_desired ^ value;
1276
      "W0C":   m_desired = m_desired & value;
1277
      "W0S":   m_desired = m_desired | (~value & mask);
1278
      "W0T":   m_desired = m_desired ^ (~value & mask);
1279
      "W1SRC": m_desired = m_desired | value;
1280
      "W1CRS": m_desired = m_desired & (~value);
1281
      "W0SRC": m_desired = m_desired | (~value & mask);
1282
      "W0CRS": m_desired = m_desired & value;
1283
      "WO":    m_desired = value;
1284
      "WOC":   m_desired = '0;
1285
      "WOS":   m_desired = mask;
1286
      "W1":    m_desired = (m_written) ? m_desired : value;
1287
      "WO1":   m_desired = (m_written) ? m_desired : value;
1288
      default: m_desired = value;
1289
   endcase
1290
   this.value = m_desired;
1291
endfunction: set
1292
 
1293
 
1294
// get
1295
 
1296
function uvm_reg_data_t  uvm_reg_field::get(string  fname = "",
1297
                                            int     lineno = 0);
1298
   m_fname = fname;
1299
   m_lineno = lineno;
1300
   get = m_desired;
1301
endfunction: get
1302
 
1303
 
1304
// get_mirrored_value
1305
 
1306
function uvm_reg_data_t  uvm_reg_field::get_mirrored_value(string  fname = "",
1307
                                            int     lineno = 0);
1308
   m_fname = fname;
1309
   m_lineno = lineno;
1310
   get_mirrored_value = m_mirrored;
1311
endfunction: get_mirrored_value
1312
 
1313
 
1314
// reset
1315
 
1316
function void uvm_reg_field::reset(string kind = "HARD");
1317
 
1318
   if (!m_reset.exists(kind))
1319
      return;
1320
 
1321
   m_mirrored = m_reset[kind];
1322
   m_desired  = m_mirrored;
1323
   value      = m_mirrored;
1324
 
1325
   if (kind == "HARD")
1326
      m_written  = 0;
1327
 
1328
endfunction: reset
1329
 
1330
 
1331
// has_reset
1332
 
1333
function bit uvm_reg_field::has_reset(string kind = "HARD",
1334
                                      bit    delete = 0);
1335
 
1336
   if (!m_reset.exists(kind)) return 0;
1337
 
1338
   if (delete) m_reset.delete(kind);
1339
 
1340
   return 1;
1341
endfunction: has_reset
1342
 
1343
 
1344
// get_reset
1345
 
1346
function uvm_reg_data_t
1347
   uvm_reg_field::get_reset(string kind = "HARD");
1348
 
1349
   if (!m_reset.exists(kind))
1350
      return m_desired;
1351
 
1352
   return m_reset[kind];
1353
 
1354
endfunction: get_reset
1355
 
1356
 
1357
// set_reset
1358
 
1359
function void uvm_reg_field::set_reset(uvm_reg_data_t value,
1360
                                       string kind = "HARD");
1361
   m_reset[kind] = value & ((1<
1362
endfunction: set_reset
1363
 
1364
 
1365
// needs_update
1366
 
1367
function bit uvm_reg_field::needs_update();
1368
   needs_update = (m_mirrored != m_desired) | m_volatile;
1369
endfunction: needs_update
1370
 
1371
 
1372
typedef class uvm_reg_map_info;
1373
 
1374
 
1375
// Xcheck_accessX
1376
 
1377
function bit uvm_reg_field::Xcheck_accessX(input uvm_reg_item rw,
1378
                                           output uvm_reg_map_info map_info,
1379
                                           input string caller);
1380
 
1381
 
1382
   if (rw.path == UVM_DEFAULT_PATH) begin
1383
     uvm_reg_block blk = m_parent.get_block();
1384
     rw.path = blk.get_default_path();
1385
   end
1386
 
1387
   if (rw.path == UVM_BACKDOOR) begin
1388
      if (m_parent.get_backdoor() == null && !m_parent.has_hdl_path()) begin
1389
         `uvm_warning("RegModel",
1390
            {"No backdoor access available for field '",get_full_name(),
1391
            "' . Using frontdoor instead."})
1392
         rw.path = UVM_FRONTDOOR;
1393
      end
1394
      else
1395
        rw.map = uvm_reg_map::backdoor();
1396
   end
1397
 
1398
   if (rw.path != UVM_BACKDOOR) begin
1399
 
1400
     rw.local_map = m_parent.get_local_map(rw.map,caller);
1401
 
1402
     if (rw.local_map == null) begin
1403
        `uvm_error(get_type_name(),
1404
           {"No transactor available to physically access memory from map '",
1405
            rw.map.get_full_name(),"'"})
1406
        rw.status = UVM_NOT_OK;
1407
        return 0;
1408
     end
1409
 
1410
     map_info = rw.local_map.get_reg_map_info(m_parent);
1411
 
1412
     if (map_info.frontdoor == null && map_info.unmapped) begin
1413
        `uvm_error("RegModel", {"Field '",get_full_name(),
1414
                   "' in register that is unmapped in map '",
1415
                   rw.map.get_full_name(),
1416
                   "' and does not have a user-defined frontdoor"})
1417
        rw.status = UVM_NOT_OK;
1418
        return 0;
1419
     end
1420
 
1421
     if (rw.map == null)
1422
       rw.map = rw.local_map;
1423
   end
1424
 
1425
   return 1;
1426
endfunction
1427
 
1428
 
1429
// write
1430
 
1431
task uvm_reg_field::write(output uvm_status_e       status,
1432
                          input  uvm_reg_data_t     value,
1433
                          input  uvm_path_e         path = UVM_DEFAULT_PATH,
1434
                          input  uvm_reg_map        map = null,
1435
                          input  uvm_sequence_base  parent = null,
1436
                          input  int                prior = -1,
1437
                          input  uvm_object         extension = null,
1438
                          input  string             fname = "",
1439
                          input  int                lineno = 0);
1440
 
1441
   uvm_reg_item rw;
1442
   rw = uvm_reg_item::type_id::create("field_write_item",,get_full_name());
1443
   rw.element      = this;
1444
   rw.element_kind = UVM_FIELD;
1445
   rw.kind         = UVM_WRITE;
1446
   rw.value[0]     = value;
1447
   rw.path         = path;
1448
   rw.map          = map;
1449
   rw.parent       = parent;
1450
   rw.prior        = prior;
1451
   rw.extension    = extension;
1452
   rw.fname        = fname;
1453
   rw.lineno       = lineno;
1454
 
1455
   do_write(rw);
1456
 
1457
   status = rw.status;
1458
 
1459
endtask
1460
 
1461
 
1462
// do_write
1463
 
1464
task uvm_reg_field::do_write(uvm_reg_item rw);
1465
 
1466
   uvm_reg_data_t   value_adjust;
1467
   uvm_reg_map_info map_info;
1468
   uvm_reg_field    fields[$];
1469
   bit bad_side_effect;
1470
 
1471
   m_parent.XatomicX(1);
1472
   m_fname  = rw.fname;
1473
   m_lineno = rw.lineno;
1474
 
1475
   if (!Xcheck_accessX(rw,map_info,"write()"))
1476
     return;
1477
 
1478
   m_write_in_progress = 1'b1;
1479
 
1480
   if (rw.value[0] >> m_size) begin
1481
      `uvm_warning("RegModel", {"uvm_reg_field::write(): Value greater than field '",
1482
                          get_full_name(),"'"})
1483
      rw.value[0] &= ((1<
1484
   end
1485
 
1486
   // Get values to write to the other fields in register
1487
   m_parent.get_fields(fields);
1488
   foreach (fields[i]) begin
1489
 
1490
      if (fields[i] == this) begin
1491
         value_adjust |= rw.value[0] << m_lsb;
1492
         continue;
1493
      end
1494
 
1495
      // It depends on what kind of bits they are made of...
1496
      case (fields[i].get_access(rw.local_map))
1497
        // These...
1498
        "RO", "RC", "RS", "W1C", "W1S", "W1T", "W1SRC", "W1CRC":
1499
          // Use all 0's
1500
          value_adjust |= 0;
1501
 
1502
        // These...
1503
        "W0C", "W0S", "W0T", "W0SRC", "W0CRS":
1504
          // Use all 1's
1505
          value_adjust |= ((1<
1506
 
1507
        // These might have side effects! Bad!
1508
        "WC", "WS", "WCRS", "WSRC", "WOC", "WOS":
1509
           bad_side_effect = 1;
1510
 
1511
        default:
1512
           value_adjust |= fields[i].m_mirrored << fields[i].get_lsb_pos();
1513
 
1514
      endcase
1515
   end
1516
 
1517
`ifdef UVM_REG_NO_INDIVIDUAL_FIELD_ACCESS
1518
   rw.element_kind = UVM_REG;
1519
   rw.element = m_parent;
1520
   rw.value[0] = value_adjust;
1521
   m_parent.do_write(rw);
1522
`else
1523
 
1524
   if (!is_indv_accessible(rw.path,rw.local_map)) begin
1525
      rw.element_kind = UVM_REG;
1526
      rw.element = m_parent;
1527
      rw.value[0] = value_adjust;
1528
      m_parent.do_write(rw);
1529
 
1530
      if (bad_side_effect) begin
1531
         `uvm_warning("RegModel", $sformatf("Writing field \"%s\" will cause unintended side effects in adjoining Write-to-Clear or Write-to-Set fields in the same register", this.get_full_name()));
1532
      end
1533
   end
1534
   else begin
1535
 
1536
     uvm_reg_map system_map = rw.local_map.get_root_map();
1537
     uvm_reg_field_cb_iter cbs = new(this);
1538
 
1539
     m_parent.Xset_busyX(1);
1540
 
1541
     rw.status = UVM_IS_OK;
1542
 
1543
     pre_write(rw);
1544
     for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
1545
        cb.pre_write(rw);
1546
 
1547
     if (rw.status != UVM_IS_OK) begin
1548
        m_write_in_progress = 1'b0;
1549
        m_parent.Xset_busyX(0);
1550
        m_parent.XatomicX(0);
1551
 
1552
        return;
1553
     end
1554
 
1555
     rw.local_map.do_write(rw);
1556
 
1557
     if (system_map.get_auto_predict())
1558
        // ToDo: Call parent.XsampleX();
1559
        do_predict(rw, UVM_PREDICT_WRITE);
1560
 
1561
     post_write(rw);
1562
     for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
1563
        cb.post_write(rw);
1564
 
1565
     m_parent.Xset_busyX(0);
1566
 
1567
   end
1568
 
1569
`endif
1570
 
1571
   m_write_in_progress = 1'b0;
1572
   m_parent.XatomicX(0);
1573
 
1574
endtask: do_write
1575
 
1576
 
1577
// read
1578
 
1579
task uvm_reg_field::read(output uvm_status_e       status,
1580
                         output uvm_reg_data_t     value,
1581
                         input  uvm_path_e         path = UVM_DEFAULT_PATH,
1582
                         input  uvm_reg_map        map = null,
1583
                         input  uvm_sequence_base  parent = null,
1584
                         input  int                prior = -1,
1585
                         input  uvm_object         extension = null,
1586
                         input  string             fname = "",
1587
                         input  int                lineno = 0);
1588
 
1589
   uvm_reg_item rw;
1590
   rw = uvm_reg_item::type_id::create("field_read_item",,get_full_name());
1591
   rw.element      = this;
1592
   rw.element_kind = UVM_FIELD;
1593
   rw.kind         = UVM_READ;
1594
   rw.value[0]     = 0;
1595
   rw.path         = path;
1596
   rw.map          = map;
1597
   rw.parent       = parent;
1598
   rw.prior        = prior;
1599
   rw.extension    = extension;
1600
   rw.fname        = fname;
1601
   rw.lineno       = lineno;
1602
 
1603
   do_read(rw);
1604
 
1605
   value = rw.value[0];
1606
   status = rw.status;
1607
 
1608
endtask: read
1609
 
1610
 
1611
// do_read
1612
 
1613
task uvm_reg_field::do_read(uvm_reg_item rw);
1614
 
1615
   uvm_reg_map_info map_info;
1616
   bit bad_side_effect;
1617
 
1618
   m_parent.XatomicX(1);
1619
   m_fname  = rw.fname;
1620
   m_lineno = rw.lineno;
1621
   m_read_in_progress = 1'b1;
1622
 
1623
   if (!Xcheck_accessX(rw,map_info,"read()"))
1624
     return;
1625
 
1626
`ifdef UVM_REG_NO_INDIVIDUAL_FIELD_ACCESS
1627
   rw.element_kind = UVM_REG;
1628
   rw.element = m_parent;
1629
   m_parent.do_read(rw);
1630
   rw.value[0] = (rw.value[0] >> m_lsb) & ((1<
1631
   bad_side_effect = 1;
1632
`else
1633
 
1634
   if (!is_indv_accessible(rw.path,rw.local_map)) begin
1635
      rw.element_kind = UVM_REG;
1636
      rw.element = m_parent;
1637
      bad_side_effect = 1;
1638
      m_parent.do_read(rw);
1639
      rw.value[0] = (rw.value[0] >> m_lsb) & ((1<
1640
   end
1641
   else begin
1642
 
1643
     uvm_reg_map system_map = rw.local_map.get_root_map();
1644
     uvm_reg_field_cb_iter cbs = new(this);
1645
 
1646
     m_parent.Xset_busyX(1);
1647
 
1648
     rw.status = UVM_IS_OK;
1649
 
1650
     pre_read(rw);
1651
     for (uvm_reg_cbs cb = cbs.first(); cb != null; cb = cbs.next())
1652
        cb.pre_read(rw);
1653
 
1654
     if (rw.status != UVM_IS_OK) begin
1655
        m_read_in_progress = 1'b0;
1656
        m_parent.Xset_busyX(0);
1657
        m_parent.XatomicX(0);
1658
 
1659
        return;
1660
     end
1661
 
1662
     rw.local_map.do_read(rw);
1663
 
1664
 
1665
     if (system_map.get_auto_predict())
1666
        // ToDo: Call parent.XsampleX();
1667
        do_predict(rw, UVM_PREDICT_READ);
1668
 
1669
     post_read(rw);
1670
     for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
1671
        cb.post_read(rw);
1672
 
1673
     m_parent.Xset_busyX(0);
1674
 
1675
   end
1676
 
1677
`endif
1678
 
1679
   m_read_in_progress = 1'b0;
1680
   m_parent.XatomicX(0);
1681
 
1682
   if (bad_side_effect) begin
1683
      uvm_reg_field fields[$];
1684
      m_parent.get_fields(fields);
1685
      foreach (fields[i]) begin
1686
         string mode;
1687
         if (fields[i] == this)
1688
            continue;
1689
         mode = fields[i].get_access();
1690
         if (mode == "RC" ||
1691
             mode == "RS" ||
1692
             mode == "WRC" ||
1693
             mode == "WRS" ||
1694
             mode == "WSRC" ||
1695
             mode == "WCRS" ||
1696
             mode == "W1SRC" ||
1697
             mode == "W1CRS" ||
1698
             mode == "W0SRC" ||
1699
             mode == "W0CRS") begin
1700
            `uvm_warning("RegModel", {"Reading field '",get_full_name(),
1701
                "' will cause unintended side effects in adjoining ",
1702
                "Read-to-Clear or Read-to-Set fields in the same register"})
1703
         end
1704
      end
1705
   end
1706
 
1707
endtask: do_read
1708
 
1709
 
1710
// is_indv_accessible
1711
 
1712
function bit uvm_reg_field::is_indv_accessible(uvm_path_e  path,
1713
                                               uvm_reg_map local_map);
1714
   if (path == UVM_BACKDOOR) begin
1715
      `uvm_warning("RegModel",
1716
         {"Individual BACKDOOR field access not available for field '",
1717
         get_full_name(), "'. Accessing complete register instead."})
1718
      return 0;
1719
   end
1720
 
1721
   if (!m_individually_accessible) begin
1722
         `uvm_warning("RegModel",
1723
            {"Individual field access not available for field '",
1724
            get_full_name(), "'. Accessing complete register instead."})
1725
      return 0;
1726
   end
1727
 
1728
   // Cannot access individual fields if the container register
1729
   // has a user-defined front-door
1730
   if (m_parent.get_frontdoor(local_map) != null) begin
1731
      `uvm_warning("RegModel",
1732
                   {"Individual field access not available for field '",
1733
                    get_name(), "' because register '", m_parent.get_full_name(), "' has a user-defined front-door. Accessing complete register instead."})
1734
      return 0;
1735
   end
1736
 
1737
   begin
1738
     uvm_reg_map system_map = local_map.get_root_map();
1739
     uvm_reg_adapter adapter = system_map.get_adapter();
1740
     if (adapter.supports_byte_enable)
1741
       return 1;
1742
   end
1743
 
1744
   begin
1745
     int fld_idx;
1746
     int bus_width = local_map.get_n_bytes();
1747
     uvm_reg_field fields[$];
1748
     bit sole_field;
1749
 
1750
     m_parent.get_fields(fields);
1751
 
1752
     if (fields.size() == 1) begin
1753
        sole_field = 1;
1754
     end
1755
     else begin
1756
        int prev_lsb,this_lsb,next_lsb;
1757
        int prev_sz,this_sz,next_sz;
1758
        int bus_sz = bus_width*8;
1759
 
1760
        foreach (fields[i]) begin
1761
           if (fields[i] == this) begin
1762
              fld_idx = i;
1763
              break;
1764
           end
1765
        end
1766
 
1767
        this_lsb = fields[fld_idx].get_lsb_pos();
1768
        this_sz  = fields[fld_idx].get_n_bits();
1769
 
1770
        if (fld_idx>0) begin
1771
          prev_lsb = fields[fld_idx-1].get_lsb_pos();
1772
          prev_sz  = fields[fld_idx-1].get_n_bits();
1773
        end
1774
 
1775
        if (fld_idx < fields.size()-1) begin
1776
          next_lsb = fields[fld_idx+1].get_lsb_pos();
1777
          next_sz  = fields[fld_idx+1].get_n_bits();
1778
        end
1779
 
1780
        // if first field in register
1781
        if (fld_idx == 0 &&
1782
           ((next_lsb % bus_sz) == 0 ||
1783
            (next_lsb - this_sz) > (next_lsb % bus_sz)))
1784
           return 1;
1785
 
1786
        // if last field in register
1787
        else if (fld_idx == (fields.size()-1) &&
1788
            ((this_lsb % bus_sz) == 0 ||
1789
             (this_lsb - (prev_lsb + prev_sz)) >= (this_lsb % bus_sz)))
1790
           return 1;
1791
 
1792
        // if somewhere in between
1793
        else begin
1794
           if ((this_lsb % bus_sz) == 0) begin
1795
              if ((next_lsb % bus_sz) == 0 ||
1796
                  (next_lsb - (this_lsb + this_sz)) >= (next_lsb % bus_sz))
1797
                 return 1;
1798
           end
1799
           else begin
1800
              if ( (next_lsb - (this_lsb + this_sz)) >= (next_lsb % bus_sz) &&
1801
                  ((this_lsb - (prev_lsb + prev_sz)) >= (this_lsb % bus_sz)) )
1802
                 return 1;
1803
           end
1804
        end
1805
     end
1806
   end
1807
 
1808
   `uvm_warning("RegModel",
1809
       {"Target bus does not support byte enabling, and the field '",
1810
       get_full_name(),"' is not the only field within the entire bus width. ",
1811
       "Individual field access will not be available. ",
1812
       "Accessing complete register instead."})
1813
 
1814
   return 0;
1815
 
1816
endfunction
1817
 
1818
 
1819
// poke
1820
 
1821
task uvm_reg_field::poke(output uvm_status_e      status,
1822
                         input  uvm_reg_data_t    value,
1823
                         input  string            kind = "",
1824
                         input  uvm_sequence_base parent = null,
1825
                         input  uvm_object        extension = null,
1826
                         input  string            fname = "",
1827
                         input  int               lineno = 0);
1828
   uvm_reg_data_t  tmp;
1829
 
1830
   m_fname = fname;
1831
   m_lineno = lineno;
1832
 
1833
   if (value >> m_size) begin
1834
      `uvm_warning("RegModel",
1835
         {"uvm_reg_field::poke(): Value exceeds size of field '",
1836
          get_name(),"'"})
1837
      value &= value & ((1<
1838
   end
1839
 
1840
 
1841
   m_parent.XatomicX(1);
1842
   m_parent.m_is_locked_by_field = 1'b1;
1843
 
1844
   tmp = 0;
1845
 
1846
   // What is the current values of the other fields???
1847
   m_parent.peek(status, tmp, kind, parent, extension, fname, lineno);
1848
 
1849
   if (status == UVM_NOT_OK) begin
1850
      `uvm_error("RegModel", {"uvm_reg_field::poke(): Peek of register '",
1851
         m_parent.get_full_name(),"' returned status ",status.name()})
1852
      m_parent.XatomicX(0);
1853
      m_parent.m_is_locked_by_field = 1'b0;
1854
      return;
1855
   end
1856
 
1857
   // Force the value for this field then poke the resulting value
1858
   tmp &= ~(((1<
1859
   tmp |= value << m_lsb;
1860
   m_parent.poke(status, tmp, kind, parent, extension, fname, lineno);
1861
 
1862
   m_parent.XatomicX(0);
1863
   m_parent.m_is_locked_by_field = 1'b0;
1864
endtask: poke
1865
 
1866
 
1867
// peek
1868
 
1869
task uvm_reg_field::peek(output uvm_status_e      status,
1870
                         output uvm_reg_data_t    value,
1871
                         input  string            kind = "",
1872
                         input  uvm_sequence_base parent = null,
1873
                         input  uvm_object        extension = null,
1874
                         input  string            fname = "",
1875
                         input  int               lineno = 0);
1876
   uvm_reg_data_t  reg_value;
1877
 
1878
   m_fname = fname;
1879
   m_lineno = lineno;
1880
 
1881
   m_parent.peek(status, reg_value, kind, parent, extension, fname, lineno);
1882
   value = (reg_value >> m_lsb) & ((1<
1883
 
1884
endtask: peek
1885
 
1886
 
1887
// mirror
1888
 
1889
task uvm_reg_field::mirror(output uvm_status_e      status,
1890
                           input  uvm_check_e       check = UVM_NO_CHECK,
1891
                           input  uvm_path_e        path = UVM_DEFAULT_PATH,
1892
                           input  uvm_reg_map       map = null,
1893
                           input  uvm_sequence_base parent = null,
1894
                           input  int               prior = -1,
1895
                           input  uvm_object        extension = null,
1896
                           input  string            fname = "",
1897
                           input  int               lineno = 0);
1898
   m_fname = fname;
1899
   m_lineno = lineno;
1900
   m_parent.mirror(status, check, path, map, parent, prior, extension,
1901
                      fname, lineno);
1902
endtask: mirror
1903
 
1904
 
1905
// set_compare
1906
 
1907
function void uvm_reg_field::set_compare(uvm_check_e check=UVM_CHECK);
1908
  m_check = check;
1909
endfunction
1910
 
1911
 
1912
// get_compare
1913
 
1914
function uvm_check_e uvm_reg_field::get_compare();
1915
  return m_check;
1916
endfunction
1917
 
1918
// pre_randomize
1919
 
1920
function void uvm_reg_field::pre_randomize();
1921
   // Update the only publicly known property with the current
1922
   // desired value so it can be used as a state variable should
1923
   // the rand_mode of the field be turned off.
1924
   value = m_desired;
1925
endfunction: pre_randomize
1926
 
1927
 
1928
// post_randomize
1929
 
1930
function void uvm_reg_field::post_randomize();
1931
   m_desired = value;
1932
endfunction: post_randomize
1933
 
1934
 
1935
// do_print
1936
 
1937
function void uvm_reg_field::do_print (uvm_printer printer);
1938
  printer.print_generic(get_name(), get_type_name(), -1, convert2string());
1939
endfunction
1940
 
1941
 
1942
// convert2string
1943
 
1944
function string uvm_reg_field::convert2string();
1945
   string fmt;
1946
   string res_str;
1947
   string t_str;
1948
   bit with_debug_info;
1949
   string prefix;
1950
   uvm_reg reg_=get_register();
1951
 
1952
   $sformat(fmt, "%0d'h%%%0dh", get_n_bits(),
1953
            (get_n_bits()-1)/4 + 1);
1954
   $sformat(convert2string, {"%s %s %s[%0d:%0d]=",fmt,"%s"}, prefix,
1955
            get_access(),
1956
            reg_.get_name(),
1957
            get_lsb_pos() + get_n_bits() - 1,
1958
            get_lsb_pos(), m_desired,
1959
            (m_desired != m_mirrored) ? $sformatf({" (Mirror: ",fmt,")"},
1960
               m_mirrored) : "");
1961
 
1962
   if (m_read_in_progress == 1'b1) begin
1963
      if (m_fname != "" && m_lineno != 0)
1964
         $sformat(res_str, " from %s:%0d",m_fname, m_lineno);
1965
      convert2string = {convert2string, "\n", "currently being read", res_str};
1966
   end
1967
   if (m_write_in_progress == 1'b1) begin
1968
      if (m_fname != "" && m_lineno != 0)
1969
         $sformat(res_str, " from %s:%0d",m_fname, m_lineno);
1970
      convert2string = {convert2string, "\n", res_str, "currently being written"};
1971
   end
1972
endfunction: convert2string
1973
 
1974
 
1975
// clone
1976
 
1977
function uvm_object uvm_reg_field::clone();
1978
  `uvm_fatal("RegModel","RegModel field cannot be cloned")
1979
  return null;
1980
endfunction
1981
 
1982
// do_copy
1983
 
1984
function void uvm_reg_field::do_copy(uvm_object rhs);
1985
  `uvm_warning("RegModel","RegModel field copy not yet implemented")
1986
  // just a set(rhs.get()) ?
1987
endfunction
1988
 
1989
 
1990
// do_compare
1991
 
1992
function bit uvm_reg_field::do_compare (uvm_object  rhs,
1993
                                        uvm_comparer comparer);
1994
  `uvm_warning("RegModel","RegModel field compare not yet implemented")
1995
  // just a return (get() == rhs.get()) ?
1996
  return 0;
1997
endfunction
1998
 
1999
 
2000
// do_pack
2001
 
2002
function void uvm_reg_field::do_pack (uvm_packer packer);
2003
  `uvm_warning("RegModel","RegModel field cannot be packed")
2004
endfunction
2005
 
2006
 
2007
// do_unpack
2008
 
2009
function void uvm_reg_field::do_unpack (uvm_packer packer);
2010
  `uvm_warning("RegModel","RegModel field cannot be unpacked")
2011
endfunction
2012
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.