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

Subversion Repositories uart2bus_testbench

[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [reg/] [uvm_vreg.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 Mentor Graphics Corporation
5
//    All Rights Reserved Worldwide
6
//
7
//    Licensed under the Apache License, Version 2.0 (the
8
//    "License"); you may not use this file except in
9
//    compliance with the License.  You may obtain a copy of
10
//    the License at
11
//
12
//        http://www.apache.org/licenses/LICENSE-2.0
13
//
14
//    Unless required by applicable law or agreed to in
15
//    writing, software distributed under the License is
16
//    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17
//    CONDITIONS OF ANY KIND, either express or implied.  See
18
//    the License for the specific language governing
19
//    permissions and limitations under the License.
20
// -------------------------------------------------------------
21
//
22
 
23
//------------------------------------------------------------------------------
24
// Title: Virtual Registers
25
//------------------------------------------------------------------------------
26
//
27
// A virtual register is a collection of fields,
28
// overlaid on top of a memory, usually in an array.
29
// The semantics and layout of virtual registers comes from
30
// an agreement between the software and the hardware,
31
// not any physical structures in the DUT.
32
//
33
//------------------------------------------------------------------------------
34
 
35
typedef class uvm_mem_region;
36
typedef class uvm_mem_mam;
37
 
38
typedef class uvm_vreg_cbs;
39
 
40
 
41
//------------------------------------------------------------------------------
42
// Class: uvm_vreg
43
//
44
// Virtual register abstraction base class
45
//
46
// A virtual register represents a set of fields that are
47
// logically implemented in consecutive memory locations.
48
//
49
// All virtual register accesses eventually turn into memory accesses.
50
//
51
// A virtual register array may be implemented on top of
52
// any memory abstraction class and possibly dynamically
53
// resized and/or relocated.
54
//
55
//------------------------------------------------------------------------------
56
 
57
class uvm_vreg extends uvm_object;
58
 
59
   `uvm_register_cb(uvm_vreg, uvm_vreg_cbs)
60
 
61
   local bit locked;
62
   local uvm_reg_block parent;
63
   local int unsigned  n_bits;
64
   local int unsigned  n_used_bits;
65
 
66
   local uvm_vreg_field fields[$];   // Fields in LSB to MSB order
67
 
68
   local uvm_mem          mem;     // Where is it implemented?
69
   local uvm_reg_addr_t   offset;  // Start of vreg[0]
70
   local int unsigned     incr;    // From start to start of next
71
   local longint unsigned size;    //number of vregs
72
   local bit              is_static;
73
 
74
   local uvm_mem_region   region;    // Not NULL if implemented via MAM
75
 
76
   local semaphore atomic;   // Field RMW operations must be atomic
77
   local string fname;
78
   local int lineno;
79
   local bit read_in_progress;
80
   local bit write_in_progress;
81
 
82
   //
83
   // Group: Initialization
84
   //
85
 
86
   //
87
   // FUNCTION: new
88
   // Create a new instance and type-specific configuration
89
   //
90
   // Creates an instance of a virtual register abstraction class
91
   // with the specified name.
92
   //
93
   // ~n_bits~ specifies the total number of bits in a virtual register.
94
   // Not all bits need to be mapped to a virtual field.
95
   // This value is usually a multiple of 8.
96
   //
97
   extern function new(string       name,
98
                       int unsigned n_bits);
99
 
100
 
101
   //
102
   // Function: configure
103
   // Instance-specific configuration
104
   //
105
   // Specify the ~parent~ block of this virtual register array.
106
   // If one of the other parameters are specified, the virtual register
107
   // is assumed to be dynamic and can be later (re-)implemented using
108
   // the  method.
109
   //
110
   // If ~mem~ is specified, then the virtual register array is assumed
111
   // to be statically implemented in the memory corresponding to the specified
112
   // memory abstraction class and ~size~, ~offset~ and ~incr~
113
   // must also be specified.
114
   // Static virtual register arrays cannot be re-implemented.
115
   //
116
   extern function void configure(uvm_reg_block     parent,
117
                                  uvm_mem       mem    = null,
118
                                  longint unsigned  size   = 0,
119
                                  uvm_reg_addr_t    offset = 0,
120
                                  int unsigned      incr   = 0);
121
 
122
   //
123
   // FUNCTION: implement
124
   // Dynamically implement, resize or relocate a virtual register array
125
   //
126
   // Implement an array of virtual registers of the specified
127
   // ~size~, in the specified memory and ~offset~.
128
   // If an offset increment is specified, each
129
   // virtual register is implemented at the specified offset increment
130
   // from the previous one.
131
   // If an offset increment of 0 is specified,
132
   // virtual registers are packed as closely as possible
133
   // in the memory.
134
   //
135
   // If no memory is specified, the virtual register array is
136
   // in the same memory, at the same base offset using the same
137
   // offset increment as originally implemented.
138
   // Only the number of virtual registers in the virtual register array
139
   // is modified.
140
   //
141
   // The initial value of the newly-implemented or
142
   // relocated set of virtual registers is whatever values
143
   // are currently stored in the memory now implementing them.
144
   //
145
   // Returns TRUE if the memory
146
   // can implement the number of virtual registers
147
   // at the specified base offset and offset increment.
148
   // Returns FALSE otherwise.
149
   //
150
   // The memory region used to implement a virtual register array
151
   // is reserved in the memory allocation manager associated with
152
   // the memory to prevent it from being allocated for another purpose.
153
   //
154
   extern virtual function bit implement(longint unsigned  n,
155
                                         uvm_mem       mem    = null,
156
                                         uvm_reg_addr_t    offset = 0,
157
                                         int unsigned      incr   = 0);
158
 
159
   //
160
   // FUNCTION: allocate
161
   // Randomly implement, resize or relocate a virtual register array
162
   //
163
   // Implement a virtual register array of the specified
164
   // size in a randomly allocated region of the appropriate size
165
   // in the address space managed by the specified memory allocation manager.
166
   // If a memory allocation policy is specified, it is passed to the
167
   // uvm_mem_mam::request_region() method.
168
   //
169
   // The initial value of the newly-implemented
170
   // or relocated set of virtual registers is whatever values are
171
   // currently stored in the
172
   // memory region now implementing them.
173
   //
174
   // Returns a reference to a  memory region descriptor
175
   // if the memory allocation manager was able to allocate a region
176
   // that can implement the virtual register array with the specified allocation policy.
177
   // Returns ~null~ otherwise.
178
   //
179
   // A region implementing a virtual register array
180
   // must not be released using the  method.
181
   // It must be released using the  method.
182
   //
183
   extern virtual function uvm_mem_region allocate(longint unsigned   n,
184
                                                   uvm_mem_mam        mam,
185
                                                   uvm_mem_mam_policy alloc = null);
186
 
187
   //
188
   // FUNCTION: get_region
189
   // Get the region where the virtual register array is implemented
190
   //
191
   // Returns a reference to the  memory region descriptor
192
   // that implements the virtual register array.
193
   //
194
   // Returns ~null~ if the virtual registers array
195
   // is not currently implemented.
196
   // A region implementing a virtual register array
197
   // must not be released using the  method.
198
   // It must be released using the  method.
199
   //
200
   extern virtual function uvm_mem_region get_region();
201
 
202
   //
203
   // FUNCTION: release_region
204
   // Dynamically un-implement a virtual register array
205
   //
206
   // Release the memory region used to implement a virtual register array
207
   // and return it to the pool of available memory
208
   // that can be allocated by the memory's default allocation manager.
209
   // The virtual register array is subsequently considered as unimplemented
210
   // and can no longer be accessed.
211
   //
212
   // Statically-implemented virtual registers cannot be released.
213
   //
214
   extern virtual function void release_region();
215
 
216
 
217
   /*local*/ extern virtual function void set_parent(uvm_reg_block parent);
218
   /*local*/ extern function void Xlock_modelX();
219
 
220
   /*local*/ extern function void add_field(uvm_vreg_field field);
221
   /*local*/ extern task XatomicX(bit on);
222
 
223
   //
224
   // Group: Introspection
225
   //
226
 
227
   //
228
   // Function: get_name
229
   // Get the simple name
230
   //
231
   // Return the simple object name of this register.
232
   //
233
 
234
   //
235
   // Function: get_full_name
236
   // Get the hierarchical name
237
   //
238
   // Return the hierarchal name of this register.
239
   // The base of the hierarchical name is the root block.
240
   //
241
   extern virtual function string        get_full_name();
242
 
243
   //
244
   // FUNCTION: get_parent
245
   // Get the parent block
246
   //
247
   extern virtual function uvm_reg_block get_parent();
248
   extern virtual function uvm_reg_block get_block();
249
 
250
 
251
   //
252
   // FUNCTION: get_memory
253
   // Get the memory where the virtual register array is implemented
254
   //
255
   extern virtual function uvm_mem get_memory();
256
 
257
   //
258
   // Function: get_n_maps
259
   // Returns the number of address maps this virtual register array is mapped in
260
   //
261
   extern virtual function int             get_n_maps      ();
262
 
263
   //
264
   // Function: is_in_map
265
   // Return TRUE if this virtual register array is in the specified address ~map~
266
   //
267
   extern function         bit             is_in_map       (uvm_reg_map map);
268
 
269
   //
270
   // Function: get_maps
271
   // Returns all of the address ~maps~ where this virtual register array is mapped
272
   //
273
   extern virtual function void            get_maps        (ref uvm_reg_map maps[$]);
274
 
275
   //
276
   // FUNCTION: get_rights
277
   // Returns the access rights of this virtual register array
278
   //
279
   // Returns "RW", "RO" or "WO".
280
   // The access rights of a virtual register array is always "RW",
281
   // unless it is implemented in a shared memory
282
   // with access restriction in a particular address map.
283
   //
284
   // If no address map is specified and the memory is mapped in only one
285
   // address map, that address map is used. If the memory is mapped
286
   // in more than one address map, the default address map of the
287
   // parent block is used.
288
   //
289
   // If an address map is specified and
290
   // the memory is not mapped in the specified
291
   // address map, an error message is issued
292
   // and "RW" is returned.
293
   //
294
   extern virtual function string get_rights(uvm_reg_map map = null);
295
 
296
   //
297
   // FUNCTION: get_access
298
   // Returns the access policy of the virtual register array
299
   // when written and read via an address map.
300
   //
301
   // If the memory implementing the virtual register array
302
   // is mapped in more than one address map,
303
   // an address ~map~ must be specified.
304
   // If access restrictions are present when accessing a memory
305
   // through the specified address map, the access mode returned
306
   // takes the access restrictions into account.
307
   // For example, a read-write memory accessed
308
   // through an address map with read-only restrictions would return "RO".
309
   //
310
   extern virtual function string get_access(uvm_reg_map map = null);
311
 
312
   //
313
   // FUNCTION: get_size
314
   // Returns the size of the virtual register array.
315
   //
316
   extern virtual function int unsigned get_size();
317
 
318
   //
319
   // FUNCTION: get_n_bytes
320
   // Returns the width, in bytes, of a virtual register.
321
   //
322
   // The width of a virtual register is always a multiple of the width
323
   // of the memory locations used to implement it.
324
   // For example, a virtual register containing two 1-byte fields
325
   // implemented in a memory with 4-bytes memory locations is 4-byte wide.
326
   //
327
   extern virtual function int unsigned get_n_bytes();
328
 
329
   //
330
   // FUNCTION: get_n_memlocs
331
   // Returns the number of memory locations used
332
   // by a single virtual register.
333
   //
334
   extern virtual function int unsigned get_n_memlocs();
335
 
336
   //
337
   // FUNCTION: get_incr
338
   // Returns the number of memory locations
339
   // between two individual virtual registers in the same array.
340
   //
341
   extern virtual function int unsigned get_incr();
342
 
343
   //
344
   // FUNCTION: get_fields
345
   // Return the virtual fields in this virtual register
346
   //
347
   // Fills the specified array with the abstraction class
348
   // for all of the virtual fields contained in this virtual register.
349
   // Fields are ordered from least-significant position to most-significant
350
   // position within the register.
351
   //
352
   extern virtual function void get_fields(ref uvm_vreg_field fields[$]);
353
 
354
   //
355
   // FUNCTION: get_field_by_name
356
   // Return the named virtual field in this virtual register
357
   //
358
   // Finds a virtual field with the specified name in this virtual register
359
   // and returns its abstraction class.
360
   // If no fields are found, returns ~null~.
361
   //
362
   extern virtual function uvm_vreg_field get_field_by_name(string name);
363
 
364
   //
365
   // FUNCTION: get_offset_in_memory
366
   // Returns the offset of a virtual register
367
   //
368
   // Returns the base offset of the specified virtual register,
369
   // in the overall address space of the memory
370
   // that implements the virtual register array.
371
   //
372
   extern virtual function uvm_reg_addr_t  get_offset_in_memory(longint unsigned idx);
373
 
374
   //
375
   // FUNCTION: get_address
376
   // Returns the base external physical address of a virtual register
377
   //
378
   // Returns the base external physical address of the specified
379
   // virtual register if accessed through the specified address ~map~.
380
   //
381
   // If no address map is specified and the memory implementing
382
   // the virtual register array is mapped in only one
383
   // address map, that address map is used. If the memory is mapped
384
   // in more than one address map, the default address map of the
385
   // parent block is used.
386
   //
387
   // If an address map is specified and
388
   // the memory is not mapped in the specified
389
   // address map, an error message is issued.
390
   //
391
   extern virtual function uvm_reg_addr_t  get_address(longint unsigned idx,
392
                                                       uvm_reg_map map = null);
393
 
394
   //
395
   // Group: HDL Access
396
   //
397
 
398
   //
399
   // TASK: write
400
   // Write the specified value in a virtual register
401
   //
402
   // Write ~value~ in the DUT memory location(s) that implements
403
   // the virtual register array that corresponds to this
404
   // abstraction class instance using the specified access
405
   // ~path~.
406
   //
407
   // If the memory implementing the virtual register array
408
   // is mapped in more than one address map,
409
   // an address ~map~ must be
410
   // specified if a physical access is used (front-door access).
411
   //
412
   // The operation is eventually mapped into set of
413
   // memory-write operations at the location where the virtual register
414
   // specified by ~idx~ in the virtual register array is implemented.
415
   //
416
   extern virtual task write(input  longint unsigned   idx,
417
                             output uvm_status_e  status,
418
                             input  uvm_reg_data_t     value,
419
                             input  uvm_path_e    path = UVM_DEFAULT_PATH,
420
                             input  uvm_reg_map     map = null,
421
                             input  uvm_sequence_base  parent = null,
422
                             input  uvm_object         extension = null,
423
                             input  string             fname = "",
424
                             input  int                lineno = 0);
425
 
426
   //
427
   // TASK: read
428
   // Read the current value from a virtual register
429
   //
430
   // Read from the DUT memory location(s) that implements
431
   // the virtual register array that corresponds to this
432
   // abstraction class instance using the specified access
433
   // ~path~ and return the readback ~value~.
434
   //
435
   // If the memory implementing the virtual register array
436
   // is mapped in more than one address map,
437
   // an address ~map~ must be
438
   // specified if a physical access is used (front-door access).
439
   //
440
   // The operation is eventually mapped into set of
441
   // memory-read operations at the location where the virtual register
442
   // specified by ~idx~ in the virtual register array is implemented.
443
   //
444
   extern virtual task read(input  longint unsigned    idx,
445
                            output uvm_status_e   status,
446
                            output uvm_reg_data_t      value,
447
                            input  uvm_path_e     path = UVM_DEFAULT_PATH,
448
                            input  uvm_reg_map      map = null,
449
                            input  uvm_sequence_base   parent = null,
450
                            input  uvm_object          extension = null,
451
                            input  string              fname = "",
452
                            input  int                 lineno = 0);
453
 
454
   //
455
   // TASK: poke
456
   // Deposit the specified value in a virtual register
457
   //
458
   // Deposit ~value~ in the DUT memory location(s) that implements
459
   // the virtual register array that corresponds to this
460
   // abstraction class instance using the memory backdoor access.
461
   //
462
   // The operation is eventually mapped into set of
463
   // memory-poke operations at the location where the virtual register
464
   // specified by ~idx~ in the virtual register array is implemented.
465
   //
466
   extern virtual task poke(input  longint unsigned    idx,
467
                            output uvm_status_e   status,
468
                            input  uvm_reg_data_t      value,
469
                            input  uvm_sequence_base   parent = null,
470
                            input  uvm_object          extension = null,
471
                            input  string              fname = "",
472
                            input  int                 lineno = 0);
473
 
474
   //
475
   // TASK: peek
476
   // Sample the current value in a virtual register
477
   //
478
   // Sample the DUT memory location(s) that implements
479
   // the virtual register array that corresponds to this
480
   // abstraction class instance using the memory backdoor access,
481
   // and return the sampled ~value~.
482
   //
483
   // The operation is eventually mapped into set of
484
   // memory-peek operations at the location where the virtual register
485
   // specified by ~idx~ in the virtual register array is implemented.
486
   //
487
   extern virtual task peek(input  longint unsigned    idx,
488
                            output uvm_status_e   status,
489
                            output uvm_reg_data_t      value,
490
                            input  uvm_sequence_base   parent = null,
491
                            input  uvm_object          extension = null,
492
                            input  string              fname = "",
493
                            input  int                 lineno = 0);
494
 
495
   //
496
   // Function: reset
497
   // Reset the access semaphore
498
   //
499
   // Reset the semaphore that prevents concurrent access
500
   // to the virtual register.
501
   // This semaphore must be explicitly reset if a thread accessing
502
   // this virtual register array was killed in before the access
503
   // was completed
504
   //
505
   extern function void reset(string kind = "HARD");
506
 
507
 
508
   //
509
   // Group: Callbacks
510
   //
511
 
512
   //
513
   // TASK: pre_write
514
   // Called before virtual register write.
515
   //
516
   // If the specified data value, access ~path~ or address ~map~ are modified,
517
   // the updated data value, access path or address map will be used
518
   // to perform the virtual register operation.
519
   //
520
   // The registered callback methods are invoked after the invocation
521
   // of this method.
522
   // All register callbacks are executed after the corresponding
523
   // field callbacks
524
   // The pre-write virtual register and field callbacks are executed
525
   // before the corresponding pre-write memory callbacks
526
   //
527
   virtual task pre_write(longint unsigned     idx,
528
                          ref uvm_reg_data_t   wdat,
529
                          ref uvm_path_e  path,
530
                          ref uvm_reg_map      map);
531
   endtask: pre_write
532
 
533
   //
534
   // TASK: post_write
535
   // Called after virtual register write.
536
   //
537
   // If the specified ~status~ is modified,
538
   // the updated status will be
539
   // returned by the virtual register operation.
540
   //
541
   // The registered callback methods are invoked before the invocation
542
   // of this method.
543
   // All register callbacks are executed before the corresponding
544
   // field callbacks
545
   // The post-write virtual register and field callbacks are executed
546
   // after the corresponding post-write memory callbacks
547
   //
548
   virtual task post_write(longint unsigned       idx,
549
                           uvm_reg_data_t         wdat,
550
                           uvm_path_e        path,
551
                           uvm_reg_map            map,
552
                           ref uvm_status_e  status);
553
   endtask: post_write
554
 
555
   //
556
   // TASK: pre_read
557
   // Called before virtual register read.
558
   //
559
   // If the specified access ~path~ or address ~map~ are modified,
560
   // the updated access path or address map will be used to perform
561
   // the register operation.
562
   //
563
   // The registered callback methods are invoked after the invocation
564
   // of this method.
565
   // All register callbacks are executed after the corresponding
566
   // field callbacks
567
   // The pre-read virtual register and field callbacks are executed
568
   // before the corresponding pre-read memory callbacks
569
   //
570
   virtual task pre_read(longint unsigned     idx,
571
                         ref uvm_path_e  path,
572
                         ref uvm_reg_map      map);
573
   endtask: pre_read
574
 
575
   //
576
   // TASK: post_read
577
   // Called after virtual register read.
578
   //
579
   // If the specified readback data or ~status~ is modified,
580
   // the updated readback data or status will be
581
   // returned by the register operation.
582
   //
583
   // The registered callback methods are invoked before the invocation
584
   // of this method.
585
   // All register callbacks are executed before the corresponding
586
   // field callbacks
587
   // The post-read virtual register and field callbacks are executed
588
   // after the corresponding post-read memory callbacks
589
   //
590
   virtual task post_read(longint unsigned       idx,
591
                          ref uvm_reg_data_t     rdat,
592
                          input uvm_path_e  path,
593
                          input uvm_reg_map      map,
594
                          ref uvm_status_e  status);
595
   endtask: post_read
596
 
597
   extern virtual function void do_print (uvm_printer printer);
598
   extern virtual function string convert2string;
599
   extern virtual function uvm_object clone();
600
   extern virtual function void do_copy   (uvm_object rhs);
601
   extern virtual function bit do_compare (uvm_object  rhs,
602
                                          uvm_comparer comparer);
603
   extern virtual function void do_pack (uvm_packer packer);
604
   extern virtual function void do_unpack (uvm_packer packer);
605
 
606
endclass: uvm_vreg
607
 
608
 
609
 
610
//------------------------------------------------------------------------------
611
// Class: uvm_vreg_cbs
612
//
613
// Pre/post read/write callback facade class
614
//
615
//------------------------------------------------------------------------------
616
 
617
class uvm_vreg_cbs extends uvm_callback;
618
 
619
   string fname;
620
   int    lineno;
621
 
622
   function new(string name = "uvm_reg_cbs");
623
      super.new(name);
624
   endfunction
625
 
626
 
627
   //
628
   // Task: pre_write
629
   // Callback called before a write operation.
630
   //
631
   // The registered callback methods are invoked after the invocation
632
   // of the  method.
633
   // All virtual register callbacks are executed after the corresponding
634
   // virtual field callbacks
635
   // The pre-write virtual register and field callbacks are executed
636
   // before the corresponding pre-write memory callbacks
637
   //
638
   // The written value ~wdat~, access ~path~ and address ~map~,
639
   // if modified, modifies the actual value, access path or address map
640
   // used in the virtual register operation.
641
   //
642
   virtual task pre_write(uvm_vreg         rg,
643
                          longint unsigned     idx,
644
                          ref uvm_reg_data_t   wdat,
645
                          ref uvm_path_e  path,
646
                          ref uvm_reg_map   map);
647
   endtask: pre_write
648
 
649
 
650
   //
651
   // TASK: post_write
652
   // Called after register write.
653
   //
654
   // The registered callback methods are invoked before the invocation
655
   // of the  method.
656
   // All register callbacks are executed before the corresponding
657
   // virtual field callbacks
658
   // The post-write virtual register and field callbacks are executed
659
   // after the corresponding post-write memory callbacks
660
   //
661
   // The ~status~ of the operation,
662
   // if modified, modifies the actual returned status.
663
   //
664
   virtual task post_write(uvm_vreg           rg,
665
                           longint unsigned       idx,
666
                           uvm_reg_data_t         wdat,
667
                           uvm_path_e        path,
668
                           uvm_reg_map         map,
669
                           ref uvm_status_e  status);
670
   endtask: post_write
671
 
672
 
673
   //
674
   // TASK: pre_read
675
   // Called before register read.
676
   //
677
   // The registered callback methods are invoked after the invocation
678
   // of the  method.
679
   // All register callbacks are executed after the corresponding
680
   // virtual field callbacks
681
   // The pre-read virtual register and field callbacks are executed
682
   // before the corresponding pre-read memory callbacks
683
   //
684
   // The access ~path~ and address ~map~,
685
   // if modified, modifies the actual access path or address map
686
   // used in the register operation.
687
   //
688
   virtual task pre_read(uvm_vreg         rg,
689
                         longint unsigned     idx,
690
                         ref uvm_path_e  path,
691
                         ref uvm_reg_map   map);
692
   endtask: pre_read
693
 
694
 
695
   //
696
   // TASK: post_read
697
   // Called after register read.
698
   //
699
   // The registered callback methods are invoked before the invocation
700
   // of the  method.
701
   // All register callbacks are executed before the corresponding
702
   // virtual field callbacks
703
   // The post-read virtual register and field callbacks are executed
704
   // after the corresponding post-read memory callbacks
705
   //
706
   // The readback value ~rdat~ and the ~status~ of the operation,
707
   // if modified, modifies the actual returned readback value and status.
708
   //
709
   virtual task post_read(uvm_vreg           rg,
710
                          longint unsigned       idx,
711
                          ref uvm_reg_data_t     rdat,
712
                          input uvm_path_e  path,
713
                          input uvm_reg_map   map,
714
                          ref uvm_status_e  status);
715
   endtask: post_read
716
endclass: uvm_vreg_cbs
717
 
718
 
719
//
720
// Type: uvm_vreg_cb
721
// Convenience callback type declaration
722
//
723
// Use this declaration to register virtual register callbacks rather than
724
// the more verbose parameterized class
725
//
726
typedef uvm_callbacks#(uvm_vreg, uvm_vreg_cbs) uvm_vreg_cb;
727
 
728
//
729
// Type: uvm_vreg_cb_iter
730
// Convenience callback iterator type declaration
731
//
732
// Use this declaration to iterate over registered virtual register callbacks
733
// rather than the more verbose parameterized class
734
//
735
typedef uvm_callback_iter#(uvm_vreg, uvm_vreg_cbs) uvm_vreg_cb_iter;
736
 
737
 
738
 
739
//------------------------------------------------------------------------------
740
// IMPLEMENTATION
741
//------------------------------------------------------------------------------
742
 
743
function uvm_vreg::new(string       name,
744
                           int unsigned n_bits);
745
   super.new(name);
746
 
747
   if (n_bits == 0) begin
748
      `uvm_error("RegModel", $sformatf("Virtual register \"%s\" cannot have 0 bits", this.get_full_name()));
749
      n_bits = 1;
750
   end
751
   if (n_bits > `UVM_REG_DATA_WIDTH) begin
752
      `uvm_error("RegModel", $sformatf("Virtual register \"%s\" cannot have more than %0d bits (%0d)", this.get_full_name(), `UVM_REG_DATA_WIDTH, n_bits));
753
      n_bits = `UVM_REG_DATA_WIDTH;
754
   end
755
   this.n_bits = n_bits;
756
 
757
   this.locked    = 0;
758
endfunction: new
759
 
760
function void uvm_vreg::configure(uvm_reg_block      parent,
761
                                      uvm_mem        mem = null,
762
                                      longint unsigned   size = 0,
763
                                      uvm_reg_addr_t     offset = 0,
764
                                      int unsigned       incr = 0);
765
   this.parent = parent;
766
 
767
   this.n_used_bits = 0;
768
 
769
   if (mem != null) begin
770
      void'(this.implement(size, mem, offset, incr));
771
      this.is_static = 1;
772
   end
773
   else begin
774
      this.mem = null;
775
      this.is_static = 0;
776
   end
777
   this.parent.add_vreg(this);
778
 
779
   this.atomic = new(1);
780
endfunction: configure
781
 
782
 
783
 
784
function void uvm_vreg::Xlock_modelX();
785
   if (this.locked) return;
786
 
787
   this.locked = 1;
788
endfunction: Xlock_modelX
789
 
790
 
791
function void uvm_vreg::add_field(uvm_vreg_field field);
792
   int offset;
793
   int idx;
794
 
795
   if (this.locked) begin
796
      `uvm_error("RegModel", "Cannot add virtual field to locked virtual register model");
797
      return;
798
   end
799
 
800
   if (field == null) `uvm_fatal("RegModel", "Attempting to register NULL virtual field");
801
 
802
   // Store fields in LSB to MSB order
803
   offset = field.get_lsb_pos_in_register();
804
 
805
   idx = -1;
806
   foreach (this.fields[i]) begin
807
      if (offset < this.fields[i].get_lsb_pos_in_register()) begin
808
         int j = i;
809
         this.fields.insert(j, field);
810
         idx = i;
811
         break;
812
      end
813
   end
814
   if (idx < 0) begin
815
      this.fields.push_back(field);
816
      idx = this.fields.size()-1;
817
   end
818
 
819
   this.n_used_bits += field.get_n_bits();
820
 
821
   // Check if there are too many fields in the register
822
   if (this.n_used_bits > this.n_bits) begin
823
      `uvm_error("RegModel", $sformatf("Virtual fields use more bits (%0d) than available in virtual register \"%s\" (%0d)",
824
                                     this.n_used_bits, this.get_full_name(), this.n_bits));
825
   end
826
 
827
   // Check if there are overlapping fields
828
   if (idx > 0) begin
829
      if (this.fields[idx-1].get_lsb_pos_in_register() +
830
          this.fields[idx-1].get_n_bits() > offset) begin
831
         `uvm_error("RegModel", $sformatf("Field %s overlaps field %s in virtual register \"%s\"",
832
                                        this.fields[idx-1].get_name(),
833
                                        field.get_name(),
834
                                        this.get_full_name()));
835
      end
836
   end
837
   if (idx < this.fields.size()-1) begin
838
      if (offset + field.get_n_bits() >
839
          this.fields[idx+1].get_lsb_pos_in_register()) begin
840
         `uvm_error("RegModel", $sformatf("Field %s overlaps field %s in virtual register \"%s\"",
841
                                        field.get_name(),
842
                                        this.fields[idx+1].get_name(),
843
 
844
                                        this.get_full_name()));
845
      end
846
   end
847
endfunction: add_field
848
 
849
 
850
task uvm_vreg::XatomicX(bit on);
851
   if (on) this.atomic.get(1);
852
   else begin
853
      // Maybe a key was put back in by a spurious call to reset()
854
      void'(this.atomic.try_get(1));
855
      this.atomic.put(1);
856
   end
857
endtask: XatomicX
858
 
859
 
860
function void uvm_vreg::reset(string kind = "HARD");
861
   // Put back a key in the semaphore if it is checked out
862
   // in case a thread was killed during an operation
863
   void'(this.atomic.try_get(1));
864
   this.atomic.put(1);
865
endfunction: reset
866
 
867
 
868
function string uvm_vreg::get_full_name();
869
   uvm_reg_block blk;
870
 
871
   get_full_name = this.get_name();
872
 
873
   // Do not include top-level name in full name
874
   blk = this.get_block();
875
   if (blk == null) return get_full_name;
876
   if (blk.get_parent() == null) return get_full_name;
877
 
878
   get_full_name = {this.parent.get_full_name(), ".", get_full_name};
879
endfunction: get_full_name
880
 
881
function void uvm_vreg::set_parent(uvm_reg_block parent);
882
   this.parent = parent;
883
endfunction: set_parent
884
 
885
function uvm_reg_block uvm_vreg::get_parent();
886
   get_parent = this.parent;
887
endfunction: get_parent
888
 
889
function uvm_reg_block uvm_vreg::get_block();
890
   get_block = this.parent;
891
endfunction: get_block
892
 
893
 
894
function bit uvm_vreg::implement(longint unsigned n,
895
                                     uvm_mem      mem = null,
896
                                     uvm_reg_addr_t   offset = 0,
897
                                     int unsigned     incr = 0);
898
 
899
   uvm_mem_region region;
900
 
901
   if(n < 1)
902
   begin
903
     `uvm_error("RegModel", $sformatf("Attempting to implement virtual register \"%s\" with a subscript less than one doesn't make sense",this.get_full_name()));
904
      return 0;
905
   end
906
 
907
   if (mem == null) begin
908
      `uvm_error("RegModel", $sformatf("Attempting to implement virtual register \"%s\" using a NULL uvm_mem reference", this.get_full_name()));
909
      return 0;
910
   end
911
 
912
   if (this.is_static) begin
913
      `uvm_error("RegModel", $sformatf("Virtual register \"%s\" is static and cannot be dynamically implemented", this.get_full_name()));
914
      return 0;
915
   end
916
 
917
   if (mem.get_block() != this.parent) begin
918
      `uvm_error("RegModel", $sformatf("Attempting to implement virtual register \"%s\" on memory \"%s\" in a different block",
919
                                     this.get_full_name(),
920
                                     mem.get_full_name()));
921
      return 0;
922
   end
923
 
924
   begin
925
      int min_incr = (this.get_n_bytes()-1) / mem.get_n_bytes() + 1;
926
      if (incr == 0) incr = min_incr;
927
      if (min_incr > incr) begin
928
         `uvm_error("RegModel", $sformatf("Virtual register \"%s\" increment is too small (%0d): Each virtual register requires at least %0d locations in memory \"%s\".",
929
                                        this.get_full_name(), incr,
930
                                        min_incr, mem.get_full_name()));
931
         return 0;
932
      end
933
   end
934
 
935
   // Is the memory big enough for ya?
936
   if (offset + (n * incr) > mem.get_size()) begin
937
      `uvm_error("RegModel", $sformatf("Given Offset for Virtual register \"%s[%0d]\" is too big for memory %s@'h%0h", this.get_full_name(), n, mem.get_full_name(), offset));
938
      return 0;
939
   end
940
 
941
   region = mem.mam.reserve_region(offset,n*incr*mem.get_n_bytes());
942
 
943
   if (region == null) begin
944
      `uvm_error("RegModel", $sformatf("Could not allocate a memory region for virtual register \"%s\"", this.get_full_name()));
945
      return 0;
946
   end
947
 
948
   if (this.mem != null) begin
949
      `uvm_info("RegModel", $sformatf("Virtual register \"%s\" is being moved re-implemented from %s@'h%0h to %s@'h%0h",
950
                                 this.get_full_name(),
951
                                 this.mem.get_full_name(),
952
                                 this.offset,
953
                                 mem.get_full_name(), offset),UVM_MEDIUM);
954
      this.release_region();
955
   end
956
 
957
   this.region = region;
958
   this.mem    = mem;
959
   this.size   = n;
960
   this.offset = offset;
961
   this.incr   = incr;
962
   this.mem.Xadd_vregX(this);
963
 
964
   return 1;
965
endfunction: implement
966
 
967
 
968
function uvm_mem_region uvm_vreg::allocate(longint unsigned   n,
969
                                           uvm_mem_mam        mam,
970
                                           uvm_mem_mam_policy alloc=null);
971
 
972
   uvm_mem mem;
973
 
974
   if(n < 1)
975
   begin
976
     `uvm_error("RegModel", $sformatf("Attempting to implement virtual register \"%s\" with a subscript less than one doesn't make sense",this.get_full_name()));
977
      return null;
978
   end
979
 
980
   if (mam == null) begin
981
      `uvm_error("RegModel", $sformatf("Attempting to implement virtual register \"%s\" using a NULL uvm_mem_mam reference", this.get_full_name()));
982
      return null;
983
   end
984
 
985
   if (this.is_static) begin
986
      `uvm_error("RegModel", $sformatf("Virtual register \"%s\" is static and cannot be dynamically allocated", this.get_full_name()));
987
      return null;
988
   end
989
 
990
   mem = mam.get_memory();
991
   if (mem.get_block() != this.parent) begin
992
      `uvm_error("RegModel", $sformatf("Attempting to allocate virtual register \"%s\" on memory \"%s\" in a different block",
993
                                     this.get_full_name(),
994
                                     mem.get_full_name()));
995
      return null;
996
   end
997
 
998
   begin
999
      int min_incr = (this.get_n_bytes()-1) / mem.get_n_bytes() + 1;
1000
      if (incr == 0) incr = min_incr;
1001
      if (min_incr < incr) begin
1002
         `uvm_error("RegModel", $sformatf("Virtual register \"%s\" increment is too small (%0d): Each virtual register requires at least %0d locations in memory \"%s\".",
1003
                                        this.get_full_name(), incr,
1004
                                        min_incr, mem.get_full_name()));
1005
         return null;
1006
      end
1007
   end
1008
 
1009
   // Need memory at least of size num_vregs*sizeof(vreg) in bytes.
1010
   allocate = mam.request_region(n*incr*mem.get_n_bytes(), alloc);
1011
   if (allocate == null) begin
1012
      `uvm_error("RegModel", $sformatf("Could not allocate a memory region for virtual register \"%s\"", this.get_full_name()));
1013
      return null;
1014
   end
1015
 
1016
   if (this.mem != null) begin
1017
     `uvm_info("RegModel", $sformatf("Virtual register \"%s\" is being moved from %s@'h%0h to %s@'h%0h",
1018
                                this.get_full_name(),
1019
                                this.mem.get_full_name(),
1020
                                this.offset,
1021
                                mem.get_full_name(),
1022
                                allocate.get_start_offset()),UVM_MEDIUM);
1023
 
1024
      this.release_region();
1025
   end
1026
 
1027
   this.region = allocate;
1028
 
1029
   this.mem    = mam.get_memory();
1030
   this.offset = allocate.get_start_offset();
1031
   this.size   = n;
1032
   this.incr   = incr;
1033
 
1034
   this.mem.Xadd_vregX(this);
1035
endfunction: allocate
1036
 
1037
 
1038
function uvm_mem_region uvm_vreg::get_region();
1039
   return this.region;
1040
endfunction: get_region
1041
 
1042
 
1043
function void uvm_vreg::release_region();
1044
   if (this.is_static) begin
1045
      `uvm_error("RegModel", $sformatf("Virtual register \"%s\" is static and cannot be dynamically released", this.get_full_name()));
1046
      return;
1047
   end
1048
 
1049
   if (this.mem != null)
1050
      this.mem.Xdelete_vregX(this);
1051
 
1052
   if (this.region != null) begin
1053
      this.region.release_region();
1054
   end
1055
 
1056
   this.region = null;
1057
   this.mem    = null;
1058
   this.size   = 0;
1059
   this.offset = 0;
1060
 
1061
   this.reset();
1062
endfunction: release_region
1063
 
1064
 
1065
function uvm_mem uvm_vreg::get_memory();
1066
   return this.mem;
1067
endfunction: get_memory
1068
 
1069
 
1070
function uvm_reg_addr_t  uvm_vreg::get_offset_in_memory(longint unsigned idx);
1071
   if (this.mem == null) begin
1072
      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg::get_offset_in_memory() on unimplemented virtual register \"%s\"",
1073
                                     this.get_full_name()));
1074
      return 0;
1075
   end
1076
 
1077
   return this.offset + idx * this.incr;
1078
endfunction
1079
 
1080
 
1081
function uvm_reg_addr_t  uvm_vreg::get_address(longint unsigned idx,
1082
                                                   uvm_reg_map map = null);
1083
   if (this.mem == null) begin
1084
      `uvm_error("RegModel", $sformatf("Cannot get address of of unimplemented virtual register \"%s\".", this.get_full_name()));
1085
      return 0;
1086
   end
1087
 
1088
   return this.mem.get_address(this.get_offset_in_memory(idx), map);
1089
endfunction: get_address
1090
 
1091
 
1092
function int unsigned uvm_vreg::get_size();
1093
   if (this.size == 0) begin
1094
      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg::get_size() on unimplemented virtual register \"%s\"",
1095
                                     this.get_full_name()));
1096
      return 0;
1097
   end
1098
 
1099
   return this.size;
1100
endfunction: get_size
1101
 
1102
 
1103
function int unsigned uvm_vreg::get_n_bytes();
1104
   return ((this.n_bits-1) / 8) + 1;
1105
endfunction: get_n_bytes
1106
 
1107
 
1108
function int unsigned uvm_vreg::get_n_memlocs();
1109
   if (this.mem == null) begin
1110
      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg::get_n_memlocs() on unimplemented virtual register \"%s\"",
1111
                                     this.get_full_name()));
1112
      return 0;
1113
   end
1114
 
1115
   return (this.get_n_bytes()-1) / this.mem.get_n_bytes() + 1;
1116
endfunction: get_n_memlocs
1117
 
1118
 
1119
function int unsigned uvm_vreg::get_incr();
1120
   if (this.incr == 0) begin
1121
      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg::get_incr() on unimplemented virtual register \"%s\"",
1122
                                     this.get_full_name()));
1123
      return 0;
1124
   end
1125
 
1126
   return this.incr;
1127
endfunction: get_incr
1128
 
1129
 
1130
function int uvm_vreg::get_n_maps();
1131
   if (this.mem == null) begin
1132
      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg::get_n_maps() on unimplemented virtual register \"%s\"",
1133
                                     this.get_full_name()));
1134
      return 0;
1135
   end
1136
 
1137
   return this.mem.get_n_maps();
1138
endfunction: get_n_maps
1139
 
1140
 
1141
function void uvm_vreg::get_maps(ref uvm_reg_map maps[$]);
1142
   if (this.mem == null) begin
1143
      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg::get_maps() on unimplemented virtual register \"%s\"",
1144
                                     this.get_full_name()));
1145
      return;
1146
   end
1147
 
1148
   this.mem.get_maps(maps);
1149
endfunction: get_maps
1150
 
1151
 
1152
function bit uvm_vreg::is_in_map(uvm_reg_map map);
1153
   if (this.mem == null) begin
1154
      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg::is_in_map() on unimplemented virtual register \"%s\"",
1155
                                  this.get_full_name()));
1156
      return 0;
1157
   end
1158
 
1159
   return this.mem.is_in_map(map);
1160
endfunction
1161
 
1162
 
1163
function string uvm_vreg::get_access(uvm_reg_map map = null);
1164
   if (this.mem == null) begin
1165
      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg::get_rights() on unimplemented virtual register \"%s\"",
1166
                                     this.get_full_name()));
1167
      return "RW";
1168
   end
1169
 
1170
   return this.mem.get_access(map);
1171
endfunction: get_access
1172
 
1173
 
1174
function string uvm_vreg::get_rights(uvm_reg_map map = null);
1175
   if (this.mem == null) begin
1176
      `uvm_error("RegModel", $sformatf("Cannot call uvm_vreg::get_rights() on unimplemented virtual register \"%s\"",
1177
                                     this.get_full_name()));
1178
      return "RW";
1179
   end
1180
 
1181
   return this.mem.get_rights(map);
1182
endfunction: get_rights
1183
 
1184
 
1185
function void uvm_vreg::get_fields(ref uvm_vreg_field fields[$]);
1186
   foreach(this.fields[i])
1187
      fields.push_back(this.fields[i]);
1188
endfunction: get_fields
1189
 
1190
 
1191
function uvm_vreg_field uvm_vreg::get_field_by_name(string name);
1192
   foreach (this.fields[i]) begin
1193
      if (this.fields[i].get_name() == name) begin
1194
         return this.fields[i];
1195
      end
1196
   end
1197
   `uvm_warning("RegModel", $sformatf("Unable to locate field \"%s\" in virtual register \"%s\".",
1198
                                    name, this.get_full_name()));
1199
   get_field_by_name = null;
1200
endfunction: get_field_by_name
1201
 
1202
 
1203
task uvm_vreg::write(input  longint unsigned   idx,
1204
                         output uvm_status_e  status,
1205
                         input  uvm_reg_data_t     value,
1206
                         input  uvm_path_e    path = UVM_DEFAULT_PATH,
1207
                         input  uvm_reg_map     map = null,
1208
                         input  uvm_sequence_base  parent = null,
1209
                         input  uvm_object         extension = null,
1210
                         input  string             fname = "",
1211
                         input  int                lineno = 0);
1212
   uvm_vreg_cb_iter cbs = new(this);
1213
 
1214
   uvm_reg_addr_t  addr;
1215
   uvm_reg_data_t  tmp;
1216
   uvm_reg_data_t  msk;
1217
   int lsb;
1218
 
1219
   this.write_in_progress = 1'b1;
1220
   this.fname = fname;
1221
   this.lineno = lineno;
1222
   if (this.mem == null) begin
1223
      `uvm_error("RegModel", $sformatf("Cannot write to unimplemented virtual register \"%s\".", this.get_full_name()));
1224
      status = UVM_NOT_OK;
1225
      return;
1226
   end
1227
 
1228
   if (path == UVM_DEFAULT_PATH)
1229
     path = this.parent.get_default_path();
1230
 
1231
   foreach (fields[i]) begin
1232
      uvm_vreg_field_cb_iter cbs = new(fields[i]);
1233
      uvm_vreg_field f = fields[i];
1234
 
1235
      lsb = f.get_lsb_pos_in_register();
1236
      msk = ((1<
1237
      tmp = (value & msk) >> lsb;
1238
 
1239
      f.pre_write(idx, tmp, path, map);
1240
      for (uvm_vreg_field_cbs cb = cbs.first(); cb != null;
1241
           cb = cbs.next()) begin
1242
         cb.fname = this.fname;
1243
         cb.lineno = this.lineno;
1244
         cb.pre_write(f, idx, tmp, path, map);
1245
      end
1246
 
1247
      value = (value & ~msk) | (tmp << lsb);
1248
   end
1249
   this.pre_write(idx, value, path, map);
1250
   for (uvm_vreg_cbs cb = cbs.first(); cb != null;
1251
        cb = cbs.next()) begin
1252
      cb.fname = this.fname;
1253
      cb.lineno = this.lineno;
1254
      cb.pre_write(this, idx, value, path, map);
1255
   end
1256
 
1257
   addr = this.offset + (idx * this.incr);
1258
 
1259
   lsb = 0;
1260
   status = UVM_IS_OK;
1261
   for (int i = 0; i < this.get_n_memlocs(); i++) begin
1262
      uvm_status_e s;
1263
 
1264
      msk = ((1<<(this.mem.get_n_bytes()*8))-1) << lsb;
1265
      tmp = (value & msk) >> lsb;
1266
      this.mem.write(s, addr + i, tmp, path, map , parent, , extension, fname, lineno);
1267
      if (s != UVM_IS_OK && s != UVM_HAS_X) status = s;
1268
      lsb += this.mem.get_n_bytes() * 8;
1269
   end
1270
 
1271
   for (uvm_vreg_cbs cb = cbs.first(); cb != null;
1272
        cb = cbs.next()) begin
1273
      cb.fname = this.fname;
1274
      cb.lineno = this.lineno;
1275
      cb.post_write(this, idx, value, path, map, status);
1276
   end
1277
   this.post_write(idx, value, path, map, status);
1278
   foreach (fields[i]) begin
1279
      uvm_vreg_field_cb_iter cbs = new(fields[i]);
1280
      uvm_vreg_field f = fields[i];
1281
 
1282
      lsb = f.get_lsb_pos_in_register();
1283
      msk = ((1<
1284
      tmp = (value & msk) >> lsb;
1285
 
1286
      for (uvm_vreg_field_cbs cb = cbs.first(); cb != null;
1287
           cb = cbs.next()) begin
1288
         cb.fname = this.fname;
1289
         cb.lineno = this.lineno;
1290
         cb.post_write(f, idx, tmp, path, map, status);
1291
      end
1292
      f.post_write(idx, tmp, path, map, status);
1293
 
1294
      value = (value & ~msk) | (tmp << lsb);
1295
   end
1296
 
1297
   `uvm_info("RegModel", $sformatf("Wrote virtual register \"%s\"[%0d] via %s with: 'h%h",
1298
                              this.get_full_name(), idx,
1299
                              (path == UVM_FRONTDOOR) ? "frontdoor" : "backdoor",
1300
                              value),UVM_MEDIUM);
1301
 
1302
   this.write_in_progress = 1'b0;
1303
   this.fname = "";
1304
   this.lineno = 0;
1305
 
1306
endtask: write
1307
 
1308
 
1309
task uvm_vreg::read(input  longint unsigned   idx,
1310
                        output uvm_status_e  status,
1311
                        output uvm_reg_data_t     value,
1312
                        input  uvm_path_e    path = UVM_DEFAULT_PATH,
1313
                        input  uvm_reg_map     map = null,
1314
                        input  uvm_sequence_base  parent = null,
1315
                        input  uvm_object         extension = null,
1316
                        input  string             fname = "",
1317
                        input  int                lineno = 0);
1318
   uvm_vreg_cb_iter cbs = new(this);
1319
 
1320
   uvm_reg_addr_t  addr;
1321
   uvm_reg_data_t  tmp;
1322
   uvm_reg_data_t  msk;
1323
   int lsb;
1324
   this.read_in_progress = 1'b1;
1325
   this.fname = fname;
1326
   this.lineno = lineno;
1327
 
1328
   if (this.mem == null) begin
1329
      `uvm_error("RegModel", $sformatf("Cannot read from unimplemented virtual register \"%s\".", this.get_full_name()));
1330
      status = UVM_NOT_OK;
1331
      return;
1332
   end
1333
 
1334
   if (path == UVM_DEFAULT_PATH)
1335
     path = this.parent.get_default_path();
1336
 
1337
   foreach (fields[i]) begin
1338
      uvm_vreg_field_cb_iter cbs = new(fields[i]);
1339
      uvm_vreg_field f = fields[i];
1340
 
1341
      f.pre_read(idx, path, map);
1342
      for (uvm_vreg_field_cbs cb = cbs.first(); cb != null;
1343
           cb = cbs.next()) begin
1344
         cb.fname = this.fname;
1345
         cb.lineno = this.lineno;
1346
         cb.pre_read(f, idx, path, map);
1347
      end
1348
   end
1349
   this.pre_read(idx, path, map);
1350
   for (uvm_vreg_cbs cb = cbs.first(); cb != null;
1351
        cb = cbs.next()) begin
1352
      cb.fname = this.fname;
1353
      cb.lineno = this.lineno;
1354
      cb.pre_read(this, idx, path, map);
1355
   end
1356
 
1357
   addr = this.offset + (idx * this.incr);
1358
 
1359
   lsb = 0;
1360
   value = 0;
1361
   status = UVM_IS_OK;
1362
   for (int i = 0; i < this.get_n_memlocs(); i++) begin
1363
      uvm_status_e s;
1364
 
1365
      this.mem.read(s, addr + i, tmp, path, map, parent, , extension, fname, lineno);
1366
      if (s != UVM_IS_OK && s != UVM_HAS_X) status = s;
1367
 
1368
      value |= tmp << lsb;
1369
      lsb += this.mem.get_n_bytes() * 8;
1370
   end
1371
 
1372
   for (uvm_vreg_cbs cb = cbs.first(); cb != null;
1373
        cb = cbs.next()) begin
1374
      cb.fname = this.fname;
1375
      cb.lineno = this.lineno;
1376
      cb.post_read(this, idx, value, path, map, status);
1377
   end
1378
   this.post_read(idx, value, path, map, status);
1379
   foreach (fields[i]) begin
1380
      uvm_vreg_field_cb_iter cbs = new(fields[i]);
1381
      uvm_vreg_field f = fields[i];
1382
 
1383
      lsb = f.get_lsb_pos_in_register();
1384
 
1385
      msk = ((1<
1386
      tmp = (value & msk) >> lsb;
1387
 
1388
      for (uvm_vreg_field_cbs cb = cbs.first(); cb != null;
1389
           cb = cbs.next()) begin
1390
         cb.fname = this.fname;
1391
         cb.lineno = this.lineno;
1392
         cb.post_read(f, idx, tmp, path, map, status);
1393
      end
1394
      f.post_read(idx, tmp, path, map, status);
1395
 
1396
      value = (value & ~msk) | (tmp << lsb);
1397
   end
1398
 
1399
   `uvm_info("RegModel", $sformatf("Read virtual register \"%s\"[%0d] via %s: 'h%h",
1400
                              this.get_full_name(), idx,
1401
                              (path == UVM_FRONTDOOR) ? "frontdoor" : "backdoor",
1402
                              value),UVM_MEDIUM);
1403
 
1404
   this.read_in_progress = 1'b0;
1405
   this.fname = "";
1406
   this.lineno = 0;
1407
endtask: read
1408
 
1409
 
1410
task uvm_vreg::poke(input longint unsigned   idx,
1411
                        output uvm_status_e status,
1412
                        input  uvm_reg_data_t    value,
1413
                        input  uvm_sequence_base parent = null,
1414
                        input  uvm_object        extension = null,
1415
                        input  string            fname = "",
1416
                        input  int               lineno = 0);
1417
   uvm_reg_addr_t  addr;
1418
   uvm_reg_data_t  tmp;
1419
   uvm_reg_data_t  msk;
1420
   int lsb;
1421
   this.fname = fname;
1422
   this.lineno = lineno;
1423
 
1424
   if (this.mem == null) begin
1425
      `uvm_error("RegModel", $sformatf("Cannot poke in unimplemented virtual register \"%s\".", this.get_full_name()));
1426
      status = UVM_NOT_OK;
1427
      return;
1428
   end
1429
 
1430
   addr = this.offset + (idx * this.incr);
1431
 
1432
   lsb = 0;
1433
   status = UVM_IS_OK;
1434
   for (int i = 0; i < this.get_n_memlocs(); i++) begin
1435
      uvm_status_e s;
1436
 
1437
      msk = ((1<<(this.mem.get_n_bytes() * 8))-1) << lsb;
1438
      tmp = (value & msk) >> lsb;
1439
 
1440
      this.mem.poke(status, addr + i, tmp, "", parent, extension, fname, lineno);
1441
      if (s != UVM_IS_OK && s != UVM_HAS_X) status = s;
1442
 
1443
      lsb += this.mem.get_n_bytes() * 8;
1444
   end
1445
 
1446
   `uvm_info("RegModel", $sformatf("Poked virtual register \"%s\"[%0d] with: 'h%h",
1447
                              this.get_full_name(), idx, value),UVM_MEDIUM);
1448
   this.fname = "";
1449
   this.lineno = 0;
1450
 
1451
endtask: poke
1452
 
1453
 
1454
task uvm_vreg::peek(input longint unsigned   idx,
1455
                        output uvm_status_e status,
1456
                        output uvm_reg_data_t    value,
1457
                        input  uvm_sequence_base parent = null,
1458
                        input  uvm_object        extension = null,
1459
                        input  string            fname = "",
1460
                        input  int               lineno = 0);
1461
   uvm_reg_addr_t  addr;
1462
   uvm_reg_data_t  tmp;
1463
   uvm_reg_data_t  msk;
1464
   int lsb;
1465
   this.fname = fname;
1466
   this.lineno = lineno;
1467
 
1468
   if (this.mem == null) begin
1469
      `uvm_error("RegModel", $sformatf("Cannot peek in from unimplemented virtual register \"%s\".", this.get_full_name()));
1470
      status = UVM_NOT_OK;
1471
      return;
1472
   end
1473
 
1474
   addr = this.offset + (idx * this.incr);
1475
 
1476
   lsb = 0;
1477
   value = 0;
1478
   status = UVM_IS_OK;
1479
   for (int i = 0; i < this.get_n_memlocs(); i++) begin
1480
      uvm_status_e s;
1481
 
1482
      this.mem.peek(status, addr + i, tmp, "", parent, extension, fname, lineno);
1483
      if (s != UVM_IS_OK && s != UVM_HAS_X) status = s;
1484
 
1485
      value |= tmp << lsb;
1486
      lsb += this.mem.get_n_bytes() * 8;
1487
   end
1488
 
1489
   `uvm_info("RegModel", $sformatf("Peeked virtual register \"%s\"[%0d]: 'h%h",
1490
                              this.get_full_name(), idx, value),UVM_MEDIUM);
1491
 
1492
   this.fname = "";
1493
   this.lineno = 0;
1494
 
1495
endtask: peek
1496
 
1497
 
1498
function void uvm_vreg::do_print (uvm_printer printer);
1499
  super.do_print(printer);
1500
  printer.print_generic("initiator", parent.get_type_name(), -1, convert2string());
1501
endfunction
1502
 
1503
function string uvm_vreg::convert2string();
1504
   string res_str;
1505
   string t_str;
1506
   bit with_debug_info;
1507
   $sformat(convert2string, "Virtual register %s -- ",
1508
            this.get_full_name());
1509
 
1510
   if (this.size == 0)
1511
     $sformat(convert2string, "%sunimplemented", convert2string);
1512
   else begin
1513
      uvm_reg_map maps[$];
1514
      mem.get_maps(maps);
1515
 
1516
      $sformat(convert2string, "%s[%0d] in %0s['h%0h+'h%0h]\n", convert2string,
1517
             this.size, this.mem.get_full_name(), this.offset, this.incr);
1518
      foreach (maps[i]) begin
1519
        uvm_reg_addr_t  addr0 = this.get_address(0, maps[i]);
1520
 
1521
        $sformat(convert2string, "  Address in map '%s' -- @'h%0h+%0h",
1522
        maps[i].get_full_name(), addr0, this.get_address(1, maps[i]) - addr0);
1523
      end
1524
   end
1525
   foreach(this.fields[i]) begin
1526
      $sformat(convert2string, "%s\n%s", convert2string,
1527
               this.fields[i].convert2string());
1528
   end
1529
 
1530
endfunction: convert2string
1531
 
1532
 
1533
 
1534
//TODO - add fatal messages
1535
function uvm_object uvm_vreg::clone();
1536
  return null;
1537
endfunction
1538
 
1539
function void uvm_vreg::do_copy   (uvm_object rhs);
1540
endfunction
1541
 
1542
function bit uvm_vreg::do_compare (uvm_object  rhs,
1543
                                        uvm_comparer comparer);
1544
  return 0;
1545
endfunction
1546
 
1547
function void uvm_vreg::do_pack (uvm_packer packer);
1548
endfunction
1549
 
1550
function void uvm_vreg::do_unpack (uvm_packer packer);
1551
endfunction
1552
 
1553
 

powered by: WebSVN 2.1.0

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