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

Subversion Repositories uart2bus_testbench

[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [reg/] [uvm_mem.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
//    All Rights Reserved Worldwide
7
//
8
//    Licensed under the Apache License, Version 2.0 (the
9
//    "License"); you may not use this file except in
10
//    compliance with the License.  You may obtain a copy of
11
//    the License at
12
//
13
//        http://www.apache.org/licenses/LICENSE-2.0
14
//
15
//    Unless required by applicable law or agreed to in
16
//    writing, software distributed under the License is
17
//    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
18
//    CONDITIONS OF ANY KIND, either express or implied.  See
19
//    the License for the specific language governing
20
//    permissions and limitations under the License.
21
// -------------------------------------------------------------
22
 
23
 
24
//------------------------------------------------------------------------------
25
// CLASS: uvm_mem
26
//------------------------------------------------------------------------------
27
// Memory abstraction base class
28
//
29
// A memory is a collection of contiguous locations.
30
// A memory may be accessible via more than one address map.
31
//
32
// Unlike registers, memories are not mirrored because of the potentially
33
// large data space: tests that walk the entire memory space would negate
34
// any benefit from sparse memory modelling techniques.
35
// Rather than relying on a mirror, it is recommended that
36
// backdoor access be used instead.
37
//
38
//------------------------------------------------------------------------------
39
 
40
class uvm_mem extends uvm_object;
41
 
42
   typedef enum {UNKNOWNS, ZEROES, ONES, ADDRESS, VALUE, INCR, DECR} init_e;
43
 
44
   local bit               m_locked;
45
   local bit               m_read_in_progress;
46
   local bit               m_write_in_progress;
47
   local string            m_access;
48
   local longint unsigned  m_size;
49
   local uvm_reg_block     m_parent;
50
   local bit               m_maps[uvm_reg_map];
51
   local int unsigned      m_n_bits;
52
   local uvm_reg_backdoor  m_backdoor;
53
   local bit               m_is_powered_down;
54
   local int               m_has_cover;
55
   local int               m_cover_on;
56
   local string            m_fname;
57
   local int               m_lineno;
58
   local bit               m_vregs[uvm_vreg];
59
   local uvm_object_string_pool
60
               #(uvm_queue #(uvm_hdl_path_concat)) m_hdl_paths_pool;
61
 
62
   local static int unsigned  m_max_size;
63
 
64
   //----------------------
65
   // Group: Initialization
66
   //----------------------
67
 
68
   // Function: new
69
   //
70
   // Create a new instance and type-specific configuration
71
   //
72
   // Creates an instance of a memory abstraction class with the specified
73
   // name.
74
   //
75
   // ~size~ specifies the total number of memory locations.
76
   // ~n_bits~ specifies the total number of bits in each memory location.
77
   // ~access~ specifies the access policy of this memory and may be
78
   // one of "RW for RAMs and "RO" for ROMs.
79
   //
80
   // ~has_coverage~ specifies which functional coverage models are present in
81
   // the extension of the register abstraction class.
82
   // Multiple functional coverage models may be specified by adding their
83
   // symbolic names, as defined by the  type.
84
   //
85
   extern function new (string           name,
86
                        longint unsigned size,
87
                        int unsigned     n_bits,
88
                        string           access = "RW",
89
                        int              has_coverage = UVM_NO_COVERAGE);
90
 
91
 
92
   // Function: configure
93
   //
94
   // Instance-specific configuration
95
   //
96
   // Specify the parent block of this memory.
97
   //
98
   // If this memory is implemented in a single HDL variable,
99
   // its name is specified as the ~hdl_path~.
100
   // Otherwise, if the memory is implemented as a concatenation
101
   // of variables (usually one per bank), then the HDL path
102
   // must be specified using the  or
103
   //  method.
104
   //
105
   extern function void configure (uvm_reg_block parent,
106
                                   string        hdl_path = "");
107
 
108
 
109
   // Function: set_offset
110
   //
111
   // Modify the offset of the memory
112
   //
113
   // The offset of a memory within an address map is set using the
114
   //  method.
115
   // This method is used to modify that offset dynamically.
116
   //
117
   // Note: Modifying the offset of a memory will make the abstract model
118
   // diverge from the specification that was used to create it.
119
   //
120
   extern virtual function void set_offset (uvm_reg_map    map,
121
                                            uvm_reg_addr_t offset,
122
                                            bit            unmapped = 0);
123
 
124
 
125
   /*local*/ extern virtual function void set_parent(uvm_reg_block parent);
126
   /*local*/ extern function void add_map(uvm_reg_map map);
127
   /*local*/ extern function void Xlock_modelX();
128
   /*local*/ extern function void Xadd_vregX(uvm_vreg vreg);
129
   /*local*/ extern function void Xdelete_vregX(uvm_vreg vreg);
130
 
131
 
132
   // variable: mam
133
   //
134
   // Memory allocation manager
135
   //
136
   // Memory allocation manager for the memory corresponding to this
137
   // abstraction class instance.
138
   // Can be used to allocate regions of consecutive addresses of
139
   // specific sizes, such as DMA buffers,
140
   // or to locate virtual register array.
141
   //
142
   uvm_mem_mam mam;
143
 
144
 
145
   //---------------------
146
   // Group: Introspection
147
   //---------------------
148
 
149
   // Function: get_name
150
   //
151
   // Get the simple name
152
   //
153
   // Return the simple object name of this memory.
154
   //
155
 
156
   // Function: get_full_name
157
   //
158
   // Get the hierarchical name
159
   //
160
   // Return the hierarchal name of this memory.
161
   // The base of the hierarchical name is the root block.
162
   //
163
   extern virtual function string get_full_name();
164
 
165
 
166
   // Function: get_parent
167
   //
168
   // Get the parent block
169
   //
170
   extern virtual function uvm_reg_block get_parent ();
171
   extern virtual function uvm_reg_block get_block  ();
172
 
173
 
174
   // Function: get_n_maps
175
   //
176
   // Returns the number of address maps this memory is mapped in
177
   //
178
   extern virtual function int get_n_maps ();
179
 
180
 
181
   // Function: is_in_map
182
   //
183
   // Return TRUE if this memory is in the specified address ~map~
184
   //
185
   extern function bit is_in_map (uvm_reg_map map);
186
 
187
 
188
   // Function: get_maps
189
   //
190
   // Returns all of the address ~maps~ where this memory is mapped
191
   //
192
   extern virtual function void get_maps (ref uvm_reg_map maps[$]);
193
 
194
 
195
   /*local*/ extern function uvm_reg_map get_local_map   (uvm_reg_map map,
196
                                                          string caller = "");
197
 
198
   /*local*/ extern function uvm_reg_map get_default_map (string caller = "");
199
 
200
 
201
   // Function: get_rights
202
   //
203
   // Returns the access rights of this memory.
204
   //
205
   // Returns "RW", "RO" or "WO".
206
   // The access rights of a memory is always "RW",
207
   // unless it is a shared memory
208
   // with access restriction in a particular address map.
209
   //
210
   // If no address map is specified and the memory is mapped in only one
211
   // address map, that address map is used. If the memory is mapped
212
   // in more than one address map, the default address map of the
213
   // parent block is used.
214
   //
215
   // If an address map is specified and
216
   // the memory is not mapped in the specified
217
   // address map, an error message is issued
218
   // and "RW" is returned.
219
   //
220
   extern virtual function string get_rights (uvm_reg_map map = null);
221
 
222
 
223
   // Function: get_access
224
   //
225
   // Returns the access policy of the memory when written and read
226
   // via an address map.
227
   //
228
   // If the memory is mapped in more than one address map,
229
   // an address ~map~ must be specified.
230
   // If access restrictions are present when accessing a memory
231
   // through the specified address map, the access mode returned
232
   // takes the access restrictions into account.
233
   // For example, a read-write memory accessed
234
   // through a domain with read-only restrictions would return "RO".
235
   //
236
   extern virtual function string get_access(uvm_reg_map map = null);
237
 
238
 
239
   // Function: get_size
240
   //
241
   // Returns the number of unique memory locations in this memory.
242
   //
243
   extern function longint unsigned get_size();
244
 
245
 
246
   // Function: get_n_bytes
247
   //
248
   // Return the width, in number of bytes, of each memory location
249
   //
250
   extern function int unsigned get_n_bytes();
251
 
252
 
253
   // Function: get_n_bits
254
   //
255
   // Returns the width, in number of bits, of each memory location
256
   //
257
   extern function int unsigned get_n_bits();
258
 
259
 
260
   // Function: get_max_size
261
   //
262
   // Returns the maximum width, in number of bits, of all memories
263
   //
264
   extern static function int unsigned    get_max_size();
265
 
266
 
267
   // Function: get_virtual_registers
268
   //
269
   // Return the virtual registers in this memory
270
   //
271
   // Fills the specified array with the abstraction class
272
   // for all of the virtual registers implemented in this memory.
273
   // The order in which the virtual registers are located in the array
274
   // is not specified.
275
   //
276
   extern virtual function void get_virtual_registers(ref uvm_vreg regs[$]);
277
 
278
 
279
   // Function: get_virtual_fields
280
   //
281
   // Return  the virtual fields in the memory
282
   //
283
   // Fills the specified dynamic array with the abstraction class
284
   // for all of the virtual fields implemented in this memory.
285
   // The order in which the virtual fields are located in the array is
286
   // not specified.
287
   //
288
   extern virtual function void get_virtual_fields(ref uvm_vreg_field fields[$]);
289
 
290
 
291
   // Function: get_vreg_by_name
292
   //
293
   // Find the named virtual register
294
   //
295
   // Finds a virtual register with the specified name
296
   // implemented in this memory and returns
297
   // its abstraction class instance.
298
   // If no virtual register with the specified name is found, returns ~null~.
299
   //
300
   extern virtual function uvm_vreg get_vreg_by_name(string name);
301
 
302
 
303
   // Function: get_vfield_by_name
304
   //
305
   // Find the named virtual field
306
   //
307
   // Finds a virtual field with the specified name
308
   // implemented in this memory and returns
309
   // its abstraction class instance.
310
   // If no virtual field with the specified name is found, returns ~null~.
311
   //
312
   extern virtual function uvm_vreg_field  get_vfield_by_name(string name);
313
 
314
 
315
   // Function: get_vreg_by_offset
316
   //
317
   // Find the virtual register implemented at the specified offset
318
   //
319
   // Finds the virtual register implemented in this memory
320
   // at the specified ~offset~ in the specified address ~map~
321
   // and returns its abstraction class instance.
322
   // If no virtual register at the offset is found, returns ~null~.
323
   //
324
   extern virtual function uvm_vreg get_vreg_by_offset(uvm_reg_addr_t offset,
325
                                                       uvm_reg_map    map = null);
326
 
327
 
328
   // Function: get_offset
329
   //
330
   // Returns the base offset of a memory location
331
   //
332
   // Returns the base offset of the specified location in this memory
333
   // in an address ~map~.
334
   //
335
   // If no address map is specified and the memory is mapped in only one
336
   // address map, that address map is used. If the memory is mapped
337
   // in more than one address map, the default address map of the
338
   // parent block is used.
339
   //
340
   // If an address map is specified and
341
   // the memory is not mapped in the specified
342
   // address map, an error message is issued.
343
   //
344
   extern virtual function uvm_reg_addr_t  get_offset (uvm_reg_addr_t offset = 0,
345
                                                       uvm_reg_map    map = null);
346
 
347
 
348
   // Function: get_address
349
   //
350
   // Returns the base external physical address of a memory location
351
   //
352
   // Returns the base external physical address of the specified location
353
   // in this memory if accessed through the specified address ~map~.
354
   //
355
   // If no address map is specified and the memory is mapped in only one
356
   // address map, that address map is used. If the memory is mapped
357
   // in more than one address map, the default address map of the
358
   // parent block is used.
359
   //
360
   // If an address map is specified and
361
   // the memory is not mapped in the specified
362
   // address map, an error message is issued.
363
   //
364
   extern virtual function uvm_reg_addr_t  get_address(uvm_reg_addr_t  offset = 0,
365
                                                       uvm_reg_map   map = null);
366
 
367
 
368
   // Function: get_addresses
369
   //
370
   // Identifies the external physical address(es) of a memory location
371
   //
372
   // Computes all of the external physical addresses that must be accessed
373
   // to completely read or write the specified location in this memory.
374
   // The addressed are specified in little endian order.
375
   // Returns the number of bytes transferred on each access.
376
   //
377
   // If no address map is specified and the memory is mapped in only one
378
   // address map, that address map is used. If the memory is mapped
379
   // in more than one address map, the default address map of the
380
   // parent block is used.
381
   //
382
   // If an address map is specified and
383
   // the memory is not mapped in the specified
384
   // address map, an error message is issued.
385
   //
386
   extern virtual function int get_addresses(uvm_reg_addr_t     offset = 0,
387
                                             uvm_reg_map        map=null,
388
                                             ref uvm_reg_addr_t addr[]);
389
 
390
 
391
   //------------------
392
   // Group: HDL Access
393
   //------------------
394
 
395
   // Task: write
396
   //
397
   // Write the specified value in a memory location
398
   //
399
   // Write ~value~ in the memory location that corresponds to this
400
   // abstraction class instance at the specified ~offset~
401
   // using the specified access ~path~.
402
   // If the memory is mapped in more than one address map,
403
   // an address ~map~ must be
404
   // specified if a physical access is used (front-door access).
405
   // If a back-door access path is used, the effect of writing
406
   // the register through a physical access is mimicked. For
407
   // example, a read-only memory will not be written.
408
   //
409
   extern virtual task write(output uvm_status_e       status,
410
                             input  uvm_reg_addr_t     offset,
411
                             input  uvm_reg_data_t     value,
412
                             input  uvm_path_e         path   = UVM_DEFAULT_PATH,
413
                             input  uvm_reg_map        map = null,
414
                             input  uvm_sequence_base  parent = null,
415
                             input  int                prior = -1,
416
                             input  uvm_object         extension = null,
417
                             input  string             fname = "",
418
                             input  int                lineno = 0);
419
 
420
 
421
   // Task: read
422
   //
423
   // Read the current value from a memory location
424
   //
425
   // Read and return ~value~ from the memory location that corresponds to this
426
   // abstraction class instance at the specified ~offset~
427
   // using the specified access ~path~.
428
   // If the register is mapped in more than one address map,
429
   // an address ~map~ must be
430
   // specified if a physical access is used (front-door access).
431
   //
432
   extern virtual task read(output uvm_status_e        status,
433
                            input  uvm_reg_addr_t      offset,
434
                            output uvm_reg_data_t      value,
435
                            input  uvm_path_e          path   = UVM_DEFAULT_PATH,
436
                            input  uvm_reg_map         map = null,
437
                            input  uvm_sequence_base   parent = null,
438
                            input  int                 prior = -1,
439
                            input  uvm_object          extension = null,
440
                            input  string              fname = "",
441
                            input  int                 lineno = 0);
442
 
443
 
444
   // Task: burst_write
445
   //
446
   // Write the specified values in memory locations
447
   //
448
   // Burst-write the specified ~values~ in the memory locations
449
   // beginning at the specified ~offset~.
450
   // If the memory is mapped in more than one address map,
451
   // an address ~map~ must be specified if not using the backdoor.
452
   // If a back-door access path is used, the effect of writing
453
   // the register through a physical access is mimicked. For
454
   // example, a read-only memory will not be written.
455
   //
456
   extern virtual task burst_write(output uvm_status_e      status,
457
                                   input  uvm_reg_addr_t    offset,
458
                                   input  uvm_reg_data_t    value[],
459
                                   input  uvm_path_e        path = UVM_DEFAULT_PATH,
460
                                   input  uvm_reg_map       map = null,
461
                                   input  uvm_sequence_base parent = null,
462
                                   input  int               prior = -1,
463
                                   input  uvm_object        extension = null,
464
                                   input  string            fname = "",
465
                                   input  int               lineno = 0);
466
 
467
 
468
   // Task: burst_read
469
   //
470
   // Read values from memory locations
471
   //
472
   // Burst-read into ~values~ the data the memory locations
473
   // beginning at the specified ~offset~.
474
   // If the memory is mapped in more than one address map,
475
   // an address ~map~ must be specified if not using the backdoor.
476
   // If a back-door access path is used, the effect of writing
477
   // the register through a physical access is mimicked. For
478
   // example, a read-only memory will not be written.
479
   //
480
   extern virtual task burst_read(output uvm_status_e      status,
481
                                  input  uvm_reg_addr_t    offset,
482
                                  ref    uvm_reg_data_t    value[],
483
                                  input  uvm_path_e        path = UVM_DEFAULT_PATH,
484
                                  input  uvm_reg_map       map = null,
485
                                  input  uvm_sequence_base parent = null,
486
                                  input  int               prior = -1,
487
                                  input  uvm_object        extension = null,
488
                                  input  string            fname = "",
489
                                  input  int               lineno = 0);
490
 
491
 
492
   // Task: poke
493
   //
494
   // Deposit the specified value in a memory location
495
   //
496
   // Deposit the value in the DUT memory location corresponding to this
497
   // abstraction class instance at the specified ~offset~, as-is,
498
   // using a back-door access.
499
   //
500
   // Uses the HDL path for the design abstraction specified by ~kind~.
501
   //
502
   extern virtual task poke(output uvm_status_e       status,
503
                            input  uvm_reg_addr_t     offset,
504
                            input  uvm_reg_data_t     value,
505
                            input  string             kind = "",
506
                            input  uvm_sequence_base  parent = null,
507
                            input  uvm_object         extension = null,
508
                            input  string             fname = "",
509
                            input  int                lineno = 0);
510
 
511
 
512
   // Task: peek
513
   //
514
   // Read the current value from a memory location
515
   //
516
   // Sample the value in the DUT memory location corresponding to this
517
   // abstraction class instance at the specified ~offset~
518
   // using a back-door access.
519
   // The memory location value is sampled, not modified.
520
   //
521
   // Uses the HDL path for the design abstraction specified by ~kind~.
522
   //
523
   extern virtual task peek(output uvm_status_e       status,
524
                            input  uvm_reg_addr_t     offset,
525
                            output uvm_reg_data_t     value,
526
                            input  string             kind = "",
527
                            input  uvm_sequence_base  parent = null,
528
                            input  uvm_object         extension = null,
529
                            input  string             fname = "",
530
                            input  int                lineno = 0);
531
 
532
 
533
 
534
   extern protected function bit Xcheck_accessX (input uvm_reg_item rw,
535
                                                 output uvm_reg_map_info map_info,
536
                                                 input string caller);
537
 
538
 
539
   extern virtual task do_write (uvm_reg_item rw);
540
   extern virtual task do_read  (uvm_reg_item rw);
541
 
542
 
543
   //-----------------
544
   // Group: Frontdoor
545
   //-----------------
546
 
547
   // Function: set_frontdoor
548
   //
549
   // Set a user-defined frontdoor for this memory
550
   //
551
   // By default, memories are mapped linearly into the address space
552
   // of the address maps that instantiate them.
553
   // If memories are accessed using a different mechanism,
554
   // a user-defined access
555
   // mechanism must be defined and associated with
556
   // the corresponding memory abstraction class
557
   //
558
   // If the memory is mapped in multiple address maps, an address ~map~
559
   // must be specified.
560
   //
561
   extern function void set_frontdoor(uvm_reg_frontdoor ftdr,
562
                                      uvm_reg_map map = null,
563
                                      string fname = "",
564
                                      int lineno = 0);
565
 
566
 
567
   // Function: get_frontdoor
568
   //
569
   // Returns the user-defined frontdoor for this memory
570
   //
571
   // If ~null~, no user-defined frontdoor has been defined.
572
   // A user-defined frontdoor is defined
573
   // by using the  method.
574
   //
575
   // If the memory is mapped in multiple address maps, an address ~map~
576
   // must be specified.
577
   //
578
   extern function uvm_reg_frontdoor get_frontdoor(uvm_reg_map map = null);
579
 
580
 
581
   //----------------
582
   // Group: Backdoor
583
   //----------------
584
 
585
   // Function: set_backdoor
586
   //
587
   // Set a user-defined backdoor for this memory
588
   //
589
   // By default, memories are accessed via the built-in string-based
590
   // DPI routines if an HDL path has been specified using the
591
   //  or  method.
592
   // If this default mechanism is not suitable (e.g. because
593
   // the memory is not implemented in pure SystemVerilog)
594
   // a user-defined access
595
   // mechanism must be defined and associated with
596
   // the corresponding memory abstraction class
597
   //
598
   extern function void set_backdoor (uvm_reg_backdoor bkdr,
599
                                      string fname = "",
600
                                      int lineno = 0);
601
 
602
 
603
   // Function: get_backdoor
604
   //
605
   // Returns the user-defined backdoor for this memory
606
   //
607
   // If ~null~, no user-defined backdoor has been defined.
608
   // A user-defined backdoor is defined
609
   // by using the  method.
610
   //
611
   // If ~inherit~ is TRUE, returns the backdoor of the parent block
612
   // if none have been specified for this memory.
613
   //
614
   extern function uvm_reg_backdoor get_backdoor(bit inherited = 1);
615
 
616
 
617
   // Function: clear_hdl_path
618
   //
619
   // Delete HDL paths
620
   //
621
   // Remove any previously specified HDL path to the memory instance
622
   // for the specified design abstraction.
623
   //
624
   extern function void clear_hdl_path (string kind = "RTL");
625
 
626
 
627
   // Function: add_hdl_path
628
   //
629
   // Add an HDL path
630
   //
631
   // Add the specified HDL path to the memory instance for the specified
632
   // design abstraction. This method may be called more than once for the
633
   // same design abstraction if the memory is physically duplicated
634
   // in the design abstraction
635
   //
636
   extern function void add_hdl_path (uvm_hdl_path_slice slices[],
637
                                      string kind = "RTL");
638
 
639
 
640
   // Function: add_hdl_path_slice
641
   //
642
   // Add the specified HDL slice to the HDL path for the specified
643
   // design abstraction.
644
   // If ~first~ is TRUE, starts the specification of a duplicate
645
   // HDL implementation of the memory.
646
   //
647
   extern function void add_hdl_path_slice(string name,
648
                                           int offset,
649
                                           int size,
650
                                           bit first = 0,
651
                                           string kind = "RTL");
652
 
653
 
654
   // Function: has_hdl_path
655
   //
656
   // Check if a HDL path is specified
657
   //
658
   // Returns TRUE if the memory instance has a HDL path defined for the
659
   // specified design abstraction. If no design abstraction is specified,
660
   // uses the default design abstraction specified for the parent block.
661
   //
662
   extern function bit  has_hdl_path (string kind = "");
663
 
664
 
665
   // Function: get_hdl_path
666
   //
667
   // Get the incremental HDL path(s)
668
   //
669
   // Returns the HDL path(s) defined for the specified design abstraction
670
   // in the memory instance.
671
   // Returns only the component of the HDL paths that corresponds to
672
   // the memory, not a full hierarchical path
673
   //
674
   // If no design abstraction is specified, the default design abstraction
675
   // for the parent block is used.
676
   //
677
   extern function void get_hdl_path (ref uvm_hdl_path_concat paths[$],
678
                                      input string kind = "");
679
 
680
 
681
   // Function: get_full_hdl_path
682
   //
683
   // Get the full hierarchical HDL path(s)
684
   //
685
   // Returns the full hierarchical HDL path(s) defined for the specified
686
   // design abstraction in the memory instance.
687
   // There may be more than one path returned even
688
   // if only one path was defined for the memory instance, if any of the
689
   // parent components have more than one path defined for the same design
690
   // abstraction
691
   //
692
   // If no design abstraction is specified, the default design abstraction
693
   // for each ancestor block is used to get each incremental path.
694
   //
695
   extern function void get_full_hdl_path (ref uvm_hdl_path_concat paths[$],
696
                                           input string kind = "",
697
                                           input string separator = ".");
698
 
699
   // Function: get_hdl_path_kinds
700
   //
701
   // Get design abstractions for which HDL paths have been defined
702
   //
703
   extern function void get_hdl_path_kinds (ref string kinds[$]);
704
 
705
   // Function: backdoor_read
706
   //
707
   // User-define backdoor read access
708
   //
709
   // Override the default string-based DPI backdoor access read
710
   // for this memory type.
711
   // By default calls .
712
   //
713
   extern virtual protected task backdoor_read(uvm_reg_item rw);
714
 
715
 
716
   // Function: backdoor_write
717
   //
718
   // User-defined backdoor read access
719
   //
720
   // Override the default string-based DPI backdoor access write
721
   // for this memory type.
722
   //
723
   extern virtual task backdoor_write(uvm_reg_item rw);
724
 
725
 
726
   // Function: backdoor_read_func
727
   //
728
   // User-defined backdoor read access
729
   //
730
   // Override the default string-based DPI backdoor access read
731
   // for this memory type.
732
   //
733
   extern virtual function uvm_status_e backdoor_read_func(uvm_reg_item rw);
734
 
735
 
736
   //-----------------
737
   // Group: Callbacks
738
   //-----------------
739
   `uvm_register_cb(uvm_mem, uvm_reg_cbs)
740
 
741
 
742
   // Task: pre_write
743
   //
744
   // Called before memory write.
745
   //
746
   // If the ~offset~, ~value~, access ~path~,
747
   // or address ~map~ are modified, the updated offset, data value,
748
   // access path or address map will be used to perform the memory operation.
749
   // If the ~status~ is modified to anything other than ,
750
   // the operation is aborted.
751
   //
752
   // The registered callback methods are invoked after the invocation
753
   // of this method.
754
   //
755
   virtual task pre_write(uvm_reg_item rw); endtask
756
 
757
 
758
   // Task: post_write
759
   //
760
   // Called after memory write.
761
   //
762
   // If the ~status~ is modified, the updated status will be
763
   // returned by the memory operation.
764
   //
765
   // The registered callback methods are invoked before the invocation
766
   // of this method.
767
   //
768
   virtual task post_write(uvm_reg_item rw); endtask
769
 
770
 
771
   // Task: pre_read
772
   //
773
   // Called before memory read.
774
   //
775
   // If the ~offset~, access ~path~ or address ~map~ are modified,
776
   // the updated offset, access path or address map will be used to perform
777
   // the memory operation.
778
   // If the ~status~ is modified to anything other than ,
779
   // the operation is aborted.
780
   //
781
   // The registered callback methods are invoked after the invocation
782
   // of this method.
783
   //
784
   virtual task pre_read(uvm_reg_item rw); endtask
785
 
786
 
787
   // Task: post_read
788
   //
789
   // Called after memory read.
790
   //
791
   // If the readback data or ~status~ is modified,
792
   // the updated readback //data or status will be
793
   // returned by the memory operation.
794
   //
795
   // The registered callback methods are invoked before the invocation
796
   // of this method.
797
   //
798
   virtual task post_read(uvm_reg_item rw); endtask
799
 
800
 
801
   //----------------
802
   // Group: Coverage
803
   //----------------
804
 
805
   // Function: build_coverage
806
   //
807
   // Check if all of the specified coverage model must be built.
808
   //
809
   // Check which of the specified coverage model must be built
810
   // in this instance of the memory abstraction class,
811
   // as specified by calls to .
812
   //
813
   // Models are specified by adding the symbolic value of individual
814
   // coverage model as defined in .
815
   // Returns the sum of all coverage models to be built in the
816
   // memory model.
817
   //
818
   extern protected function uvm_reg_cvr_t build_coverage(uvm_reg_cvr_t models);
819
 
820
 
821
   // Function: add_coverage
822
   //
823
   // Specify that additional coverage models are available.
824
   //
825
   // Add the specified coverage model to the coverage models
826
   // available in this class.
827
   // Models are specified by adding the symbolic value of individual
828
   // coverage model as defined in .
829
   //
830
   // This method shall be called only in the constructor of
831
   // subsequently derived classes.
832
   //
833
   extern virtual protected function void add_coverage(uvm_reg_cvr_t models);
834
 
835
 
836
   // Function: has_coverage
837
   //
838
   // Check if memory has coverage model(s)
839
   //
840
   // Returns TRUE if the memory abstraction class contains a coverage model
841
   // for all of the models specified.
842
   // Models are specified by adding the symbolic value of individual
843
   // coverage model as defined in .
844
   //
845
   extern virtual function bit has_coverage(uvm_reg_cvr_t models);
846
 
847
 
848
   // Function: set_coverage
849
   //
850
   // Turns on coverage measurement.
851
   //
852
   // Turns the collection of functional coverage measurements on or off
853
   // for this memory.
854
   // The functional coverage measurement is turned on for every
855
   // coverage model specified using  symbolic
856
   // identifiers.
857
   // Multiple functional coverage models can be specified by adding
858
   // the functional coverage model identifiers.
859
   // All other functional coverage models are turned off.
860
   // Returns the sum of all functional
861
   // coverage models whose measurements were previously on.
862
   //
863
   // This method can only control the measurement of functional
864
   // coverage models that are present in the memory abstraction classes,
865
   // then enabled during construction.
866
   // See the  method to identify
867
   // the available functional coverage models.
868
   //
869
   extern virtual function uvm_reg_cvr_t set_coverage(uvm_reg_cvr_t is_on);
870
 
871
 
872
   // Function: get_coverage
873
   //
874
   // Check if coverage measurement is on.
875
   //
876
   // Returns TRUE if measurement for all of the specified functional
877
   // coverage models are currently on.
878
   // Multiple functional coverage models can be specified by adding the
879
   // functional coverage model identifiers.
880
   //
881
   // See  for more details.
882
   //
883
   extern virtual function bit get_coverage(uvm_reg_cvr_t is_on);
884
 
885
 
886
   // Function: sample
887
   //
888
   // Functional coverage measurement method
889
   //
890
   // This method is invoked by the memory abstraction class
891
   // whenever an address within one of its address map
892
   // is successfully read or written.
893
   // The specified offset is the offset within the memory,
894
   // not an absolute address.
895
   //
896
   // Empty by default, this method may be extended by the
897
   // abstraction class generator to perform the required sampling
898
   // in any provided functional coverage model.
899
   //
900
   protected virtual function void  sample(uvm_reg_addr_t offset,
901
                                           bit            is_read,
902
                                           uvm_reg_map    map);
903
   endfunction
904
 
905
   /*local*/ function void XsampleX(uvm_reg_addr_t addr,
906
                                    bit            is_read,
907
                                    uvm_reg_map    map);
908
      sample(addr, is_read, map);
909
   endfunction
910
 
911
   // Core ovm_object operations
912
 
913
   extern virtual function void do_print (uvm_printer printer);
914
   extern virtual function string convert2string();
915
   extern virtual function uvm_object clone();
916
   extern virtual function void do_copy   (uvm_object rhs);
917
   extern virtual function bit do_compare (uvm_object  rhs,
918
                                          uvm_comparer comparer);
919
   extern virtual function void do_pack (uvm_packer packer);
920
   extern virtual function void do_unpack (uvm_packer packer);
921
 
922
 
923
endclass: uvm_mem
924
 
925
 
926
 
927
//------------------------------------------------------------------------------
928
// IMPLEMENTATION
929
//------------------------------------------------------------------------------
930
 
931
 
932
// new
933
 
934
function uvm_mem::new (string           name,
935
                       longint unsigned size,
936
                       int unsigned     n_bits,
937
                       string           access = "RW",
938
                       int              has_coverage = UVM_NO_COVERAGE);
939
 
940
   super.new(name);
941
   m_locked = 0;
942
   if (n_bits == 0) begin
943
      `uvm_error("RegModel", {"Memory '",get_full_name(),"' cannot have 0 bits"})
944
      n_bits = 1;
945
   end
946
   m_size      = size;
947
   m_n_bits    = n_bits;
948
   m_backdoor  = null;
949
   m_access    = access.toupper();
950
   m_has_cover = has_coverage;
951
   m_hdl_paths_pool = new("hdl_paths");
952
 
953
   if (n_bits > m_max_size)
954
      m_max_size = n_bits;
955
 
956
endfunction: new
957
 
958
 
959
// configure
960
 
961
function void uvm_mem::configure(uvm_reg_block  parent,
962
                                 string         hdl_path="");
963
 
964
   if (parent == null)
965
     `uvm_fatal("REG/NULL_PARENT","configure: parent argument is null")
966
 
967
   m_parent = parent;
968
 
969
   if (m_access != "RW" && m_access != "RO") begin
970
      `uvm_error("RegModel", {"Memory '",get_full_name(),"' can only be RW or RO"})
971
      m_access = "RW";
972
   end
973
 
974
   begin
975
      uvm_mem_mam_cfg cfg = new;
976
 
977
      cfg.n_bytes      = ((m_n_bits-1) / 8) + 1;
978
      cfg.start_offset = 0;
979
      cfg.end_offset   = m_size-1;
980
 
981
      cfg.mode     = uvm_mem_mam::GREEDY;
982
      cfg.locality = uvm_mem_mam::BROAD;
983
 
984
      mam = new(get_full_name(), cfg, this);
985
   end
986
 
987
   m_parent.add_mem(this);
988
 
989
   if (hdl_path != "") add_hdl_path_slice(hdl_path, -1, -1);
990
endfunction: configure
991
 
992
 
993
// set_offset
994
 
995
function void uvm_mem::set_offset (uvm_reg_map    map,
996
                                   uvm_reg_addr_t offset,
997
                                   bit unmapped = 0);
998
 
999
   uvm_reg_map orig_map = map;
1000
 
1001
   if (m_maps.num() > 1 && map == null) begin
1002
      `uvm_error("RegModel",{"set_offset requires a non-null map when memory '",
1003
                 get_full_name(),"' belongs to more than one map."})
1004
      return;
1005
   end
1006
 
1007
   map = get_local_map(map,"set_offset()");
1008
 
1009
   if (map == null)
1010
     return;
1011
 
1012
   map.m_set_mem_offset(this, offset, unmapped);
1013
endfunction
1014
 
1015
 
1016
// add_map
1017
 
1018
function void uvm_mem::add_map(uvm_reg_map map);
1019
  m_maps[map] = 1;
1020
endfunction
1021
 
1022
 
1023
// Xlock_modelX
1024
 
1025
function void uvm_mem::Xlock_modelX();
1026
   m_locked = 1;
1027
endfunction: Xlock_modelX
1028
 
1029
 
1030
// get_full_name
1031
 
1032
function string uvm_mem::get_full_name();
1033
   if (m_parent == null)
1034
      return get_name();
1035
 
1036
   return {m_parent.get_full_name(), ".", get_name()};
1037
 
1038
endfunction: get_full_name
1039
 
1040
 
1041
// get_block
1042
 
1043
function uvm_reg_block uvm_mem::get_block();
1044
   return m_parent;
1045
endfunction: get_block
1046
 
1047
 
1048
// get_n_maps
1049
 
1050
function int uvm_mem::get_n_maps();
1051
   return m_maps.num();
1052
endfunction: get_n_maps
1053
 
1054
 
1055
// get_maps
1056
 
1057
function void uvm_mem::get_maps(ref uvm_reg_map maps[$]);
1058
   foreach (m_maps[map])
1059
     maps.push_back(map);
1060
endfunction
1061
 
1062
 
1063
// is_in_map
1064
 
1065
function bit uvm_mem::is_in_map(uvm_reg_map map);
1066
   if (m_maps.exists(map))
1067
     return 1;
1068
   foreach (m_maps[l]) begin
1069
    uvm_reg_map local_map=l;
1070
     uvm_reg_map parent_map = local_map.get_parent_map();
1071
 
1072
     while (parent_map != null) begin
1073
       if (parent_map == map)
1074
         return 1;
1075
       parent_map = parent_map.get_parent_map();
1076
     end
1077
   end
1078
   return 0;
1079
endfunction
1080
 
1081
 
1082
// get_local_map
1083
 
1084
function uvm_reg_map uvm_mem::get_local_map(uvm_reg_map map, string caller="");
1085
   if (map == null)
1086
     return get_default_map();
1087
   if (m_maps.exists(map))
1088
     return map;
1089
   foreach (m_maps[l]) begin
1090
     uvm_reg_map local_map = l;
1091
     uvm_reg_map parent_map = local_map.get_parent_map();
1092
 
1093
     while (parent_map != null) begin
1094
       if (parent_map == map)
1095
         return local_map;
1096
       parent_map = parent_map.get_parent_map();
1097
     end
1098
   end
1099
   `uvm_warning("RegModel",
1100
       {"Memory '",get_full_name(),"' is not contained within map '",map.get_full_name(),"'",
1101
        (caller == "" ? "": {" (called from ",caller,")"})})
1102
   return null;
1103
endfunction
1104
 
1105
 
1106
// get_default_map
1107
 
1108
function uvm_reg_map uvm_mem::get_default_map(string caller="");
1109
 
1110
   // if mem is not associated with any may, return ~null~
1111
   if (m_maps.num() == 0) begin
1112
      `uvm_warning("RegModel",
1113
        {"Memory '",get_full_name(),"' is not registered with any map",
1114
         (caller == "" ? "": {" (called from ",caller,")"})})
1115
      return null;
1116
   end
1117
 
1118
   // if only one map, choose that
1119
   if (m_maps.num() == 1) begin
1120
     void'(m_maps.first(get_default_map));
1121
   end
1122
 
1123
   // try to choose one based on default_map in parent blocks.
1124
   foreach (m_maps[l]) begin
1125
     uvm_reg_map map = l;
1126
     uvm_reg_block blk = map.get_parent();
1127
     uvm_reg_map default_map = blk.get_default_map();
1128
     if (default_map != null) begin
1129
       uvm_reg_map local_map = get_local_map(default_map);
1130
       if (local_map != null)
1131
         return local_map;
1132
     end
1133
   end
1134
 
1135
   // if that fails, choose the first in this mem's maps
1136
 
1137
   void'(m_maps.first(get_default_map));
1138
 
1139
endfunction
1140
 
1141
 
1142
// get_access
1143
 
1144
function string uvm_mem::get_access(uvm_reg_map map = null);
1145
   get_access = m_access;
1146
   if (get_n_maps() == 1) return get_access;
1147
 
1148
   map = get_local_map(map, "get_access()");
1149
   if (map == null) return get_access;
1150
 
1151
   // Is the memory restricted in this map?
1152
   case (get_rights(map))
1153
     "RW":
1154
       // No restrictions
1155
       return get_access;
1156
 
1157
     "RO":
1158
       case (get_access)
1159
         "RW", "RO": get_access = "RO";
1160
 
1161
         "WO":    `uvm_error("RegModel", {"WO memory '",get_full_name(),
1162
                       "' restricted to RO in map '",map.get_full_name(),"'"})
1163
 
1164
         default: `uvm_error("RegModel", {"Memory '",get_full_name(),
1165
                       "' has invalid access mode, '",get_access,"'"})
1166
       endcase
1167
 
1168
     "WO":
1169
       case (get_access)
1170
         "RW", "WO": get_access = "WO";
1171
 
1172
         "RO":    `uvm_error("RegModel", {"RO memory '",get_full_name(),
1173
                       "' restricted to WO in map '",map.get_full_name(),"'"})
1174
 
1175
         default: `uvm_error("RegModel", {"Memory '",get_full_name(),
1176
                       "' has invalid access mode, '",get_access,"'"})
1177
       endcase
1178
 
1179
     default: `uvm_error("RegModel", {"Shared memory '",get_full_name(),
1180
                  "' is not shared in map '",map.get_full_name(),"'"})
1181
   endcase
1182
endfunction: get_access
1183
 
1184
 
1185
// get_rights
1186
 
1187
function string uvm_mem::get_rights(uvm_reg_map map = null);
1188
 
1189
   uvm_reg_map_info info;
1190
 
1191
   // No right restrictions if not shared
1192
   if (m_maps.num() <= 1) begin
1193
      return "RW";
1194
   end
1195
 
1196
   map = get_local_map(map,"get_rights()");
1197
 
1198
   if (map == null)
1199
     return "RW";
1200
 
1201
   info = map.get_mem_map_info(this);
1202
   return info.rights;
1203
 
1204
endfunction: get_rights
1205
 
1206
 
1207
// get_offset
1208
 
1209
function uvm_reg_addr_t uvm_mem::get_offset(uvm_reg_addr_t offset = 0,
1210
                                            uvm_reg_map map = null);
1211
 
1212
   uvm_reg_map_info map_info;
1213
   uvm_reg_map orig_map = map;
1214
 
1215
   map = get_local_map(map,"get_offset()");
1216
 
1217
   if (map == null)
1218
     return -1;
1219
 
1220
   map_info = map.get_mem_map_info(this);
1221
 
1222
   if (map_info.unmapped) begin
1223
      `uvm_warning("RegModel", {"Memory '",get_name(),
1224
                   "' is unmapped in map '",
1225
                   ((orig_map == null) ? map.get_full_name() : orig_map.get_full_name()),"'"})
1226
      return -1;
1227
   end
1228
 
1229
   return map_info.offset;
1230
 
1231
endfunction: get_offset
1232
 
1233
 
1234
 
1235
// get_virtual_registers
1236
 
1237
function void uvm_mem::get_virtual_registers(ref uvm_vreg regs[$]);
1238
  foreach (m_vregs[vreg])
1239
     regs.push_back(vreg);
1240
endfunction
1241
 
1242
 
1243
// get_virtual_fields
1244
 
1245
function void uvm_mem::get_virtual_fields(ref uvm_vreg_field fields[$]);
1246
 
1247
  foreach (m_vregs[l])
1248
  begin
1249
    uvm_vreg vreg = l;
1250
    vreg.get_fields(fields);
1251
  end
1252
endfunction: get_virtual_fields
1253
 
1254
 
1255
// get_vfield_by_name
1256
 
1257
function uvm_vreg_field uvm_mem::get_vfield_by_name(string name);
1258
  // Return first occurrence of vfield matching name
1259
  uvm_vreg_field vfields[$];
1260
 
1261
  get_virtual_fields(vfields);
1262
 
1263
  foreach (vfields[i])
1264
    if (vfields[i].get_name() == name)
1265
      return vfields[i];
1266
 
1267
  `uvm_warning("RegModel", {"Unable to find virtual field '",name,
1268
                       "' in memory '",get_full_name(),"'"})
1269
   return null;
1270
endfunction: get_vfield_by_name
1271
 
1272
 
1273
// get_vreg_by_name
1274
 
1275
function uvm_vreg uvm_mem::get_vreg_by_name(string name);
1276
 
1277
  foreach (m_vregs[l])
1278
  begin
1279
    uvm_vreg vreg = l;
1280
    if (vreg.get_name() == name)
1281
      return vreg;
1282
  end
1283
 
1284
  `uvm_warning("RegModel", {"Unable to find virtual register '",name,
1285
                       "' in memory '",get_full_name(),"'"})
1286
  return null;
1287
 
1288
endfunction: get_vreg_by_name
1289
 
1290
 
1291
// get_vreg_by_offset
1292
 
1293
function uvm_vreg uvm_mem::get_vreg_by_offset(uvm_reg_addr_t offset,
1294
                                              uvm_reg_map map = null);
1295
   `uvm_error("RegModel", "uvm_mem::get_vreg_by_offset() not yet implemented")
1296
   return null;
1297
endfunction: get_vreg_by_offset
1298
 
1299
 
1300
 
1301
// get_addresses
1302
 
1303
function int uvm_mem::get_addresses(uvm_reg_addr_t offset = 0,
1304
                                    uvm_reg_map map=null,
1305
                                    ref uvm_reg_addr_t addr[]);
1306
 
1307
   uvm_reg_map_info map_info;
1308
   uvm_reg_map system_map;
1309
   uvm_reg_map orig_map = map;
1310
 
1311
   map = get_local_map(map,"get_addresses()");
1312
 
1313
   if (map == null)
1314
     return 0;
1315
 
1316
   map_info = map.get_mem_map_info(this);
1317
 
1318
   if (map_info.unmapped) begin
1319
      `uvm_warning("RegModel", {"Memory '",get_name(),
1320
                   "' is unmapped in map '",
1321
                   ((orig_map == null) ? map.get_full_name() : orig_map.get_full_name()),"'"})
1322
      return 0;
1323
   end
1324
 
1325
   addr = map_info.addr;
1326
 
1327
   foreach (addr[i])
1328
      addr[i] = addr[i] + map_info.mem_range.stride * offset;
1329
 
1330
   return map.get_n_bytes();
1331
 
1332
endfunction
1333
 
1334
 
1335
// get_address
1336
 
1337
function uvm_reg_addr_t uvm_mem::get_address(uvm_reg_addr_t offset = 0,
1338
                                             uvm_reg_map map = null);
1339
   uvm_reg_addr_t  addr[];
1340
   void'(get_addresses(offset, map, addr));
1341
   return addr[0];
1342
endfunction
1343
 
1344
 
1345
// get_size
1346
 
1347
function longint unsigned uvm_mem::get_size();
1348
   return m_size;
1349
endfunction: get_size
1350
 
1351
 
1352
// get_n_bits
1353
 
1354
function int unsigned uvm_mem::get_n_bits();
1355
   return m_n_bits;
1356
endfunction: get_n_bits
1357
 
1358
 
1359
// get_max_size
1360
 
1361
function int unsigned uvm_mem::get_max_size();
1362
   return m_max_size;
1363
endfunction: get_max_size
1364
 
1365
 
1366
// get_n_bytes
1367
 
1368
function int unsigned uvm_mem::get_n_bytes();
1369
   return (m_n_bits - 1) / 8 + 1;
1370
endfunction: get_n_bytes
1371
 
1372
 
1373
 
1374
 
1375
//---------
1376
// COVERAGE
1377
//---------
1378
 
1379
 
1380
function uvm_reg_cvr_t uvm_mem::build_coverage(uvm_reg_cvr_t models);
1381
   build_coverage = UVM_NO_COVERAGE;
1382
   void'(uvm_reg_cvr_rsrc_db::read_by_name({"uvm_reg::", get_full_name()},
1383
                                           "include_coverage",
1384
                                           build_coverage, this));
1385
   return build_coverage & models;
1386
endfunction: build_coverage
1387
 
1388
 
1389
// add_coverage
1390
 
1391
function void uvm_mem::add_coverage(uvm_reg_cvr_t models);
1392
   m_has_cover |= models;
1393
endfunction: add_coverage
1394
 
1395
 
1396
// has_coverage
1397
 
1398
function bit uvm_mem::has_coverage(uvm_reg_cvr_t models);
1399
   return ((m_has_cover & models) == models);
1400
endfunction: has_coverage
1401
 
1402
 
1403
// set_coverage
1404
 
1405
function uvm_reg_cvr_t uvm_mem::set_coverage(uvm_reg_cvr_t is_on);
1406
   if (is_on == uvm_reg_cvr_t'(UVM_NO_COVERAGE)) begin
1407
      m_cover_on = is_on;
1408
      return m_cover_on;
1409
   end
1410
 
1411
   m_cover_on = m_has_cover & is_on;
1412
 
1413
   return m_cover_on;
1414
endfunction: set_coverage
1415
 
1416
 
1417
// get_coverage
1418
 
1419
function bit uvm_mem::get_coverage(uvm_reg_cvr_t is_on);
1420
   if (has_coverage(is_on) == 0) return 0;
1421
   return ((m_cover_on & is_on) == is_on);
1422
endfunction: get_coverage
1423
 
1424
 
1425
 
1426
 
1427
//-----------
1428
// HDL ACCESS
1429
//-----------
1430
 
1431
// write
1432
//------
1433
 
1434
task uvm_mem::write(output uvm_status_e      status,
1435
                    input  uvm_reg_addr_t    offset,
1436
                    input  uvm_reg_data_t    value,
1437
                    input  uvm_path_e        path = UVM_DEFAULT_PATH,
1438
                    input  uvm_reg_map       map = null,
1439
                    input  uvm_sequence_base parent = null,
1440
                    input  int               prior = -1,
1441
                    input  uvm_object        extension = null,
1442
                    input  string            fname = "",
1443
                    input  int               lineno = 0);
1444
 
1445
   // create an abstract transaction for this operation
1446
   uvm_reg_item rw = uvm_reg_item::type_id::create("mem_write",,get_full_name());
1447
   rw.element      = this;
1448
   rw.element_kind = UVM_MEM;
1449
   rw.kind         = UVM_WRITE;
1450
   rw.offset       = offset;
1451
   rw.value[0]     = value;
1452
   rw.path         = path;
1453
   rw.map          = map;
1454
   rw.parent       = parent;
1455
   rw.prior        = prior;
1456
   rw.extension    = extension;
1457
   rw.fname        = fname;
1458
   rw.lineno       = lineno;
1459
 
1460
   do_write(rw);
1461
 
1462
   status = rw.status;
1463
 
1464
endtask: write
1465
 
1466
 
1467
// read
1468
 
1469
task uvm_mem::read(output uvm_status_e       status,
1470
                   input  uvm_reg_addr_t     offset,
1471
                   output uvm_reg_data_t     value,
1472
                   input  uvm_path_e         path = UVM_DEFAULT_PATH,
1473
                   input  uvm_reg_map        map = null,
1474
                   input  uvm_sequence_base  parent = null,
1475
                   input  int                prior = -1,
1476
                   input  uvm_object         extension = null,
1477
                   input  string             fname = "",
1478
                   input  int                lineno = 0);
1479
 
1480
   uvm_reg_item rw;
1481
   rw = uvm_reg_item::type_id::create("mem_read",,get_full_name());
1482
   rw.element      = this;
1483
   rw.element_kind = UVM_MEM;
1484
   rw.kind         = UVM_READ;
1485
   rw.value[0]     = 0;
1486
   rw.offset       = offset;
1487
   rw.path         = path;
1488
   rw.map          = map;
1489
   rw.parent       = parent;
1490
   rw.prior        = prior;
1491
   rw.extension    = extension;
1492
   rw.fname        = fname;
1493
   rw.lineno       = lineno;
1494
 
1495
   do_read(rw);
1496
 
1497
   status = rw.status;
1498
   value = rw.value[0];
1499
 
1500
endtask: read
1501
 
1502
 
1503
// burst_write
1504
 
1505
task uvm_mem::burst_write(output uvm_status_e       status,
1506
                          input  uvm_reg_addr_t     offset,
1507
                          input  uvm_reg_data_t     value[],
1508
                          input  uvm_path_e         path = UVM_DEFAULT_PATH,
1509
                          input  uvm_reg_map        map = null,
1510
                          input  uvm_sequence_base  parent = null,
1511
                          input  int                prior = -1,
1512
                          input  uvm_object         extension = null,
1513
                          input  string             fname = "",
1514
                          input  int                lineno = 0);
1515
 
1516
   uvm_reg_item rw;
1517
   rw = uvm_reg_item::type_id::create("mem_burst_write",,get_full_name());
1518
   rw.element      = this;
1519
   rw.element_kind = UVM_MEM;
1520
   rw.kind         = UVM_BURST_WRITE;
1521
   rw.offset       = offset;
1522
   rw.value        = value;
1523
   rw.path         = path;
1524
   rw.map          = map;
1525
   rw.parent       = parent;
1526
   rw.prior        = prior;
1527
   rw.extension    = extension;
1528
   rw.fname        = fname;
1529
   rw.lineno       = lineno;
1530
 
1531
   do_write(rw);
1532
 
1533
   status = rw.status;
1534
 
1535
endtask: burst_write
1536
 
1537
 
1538
// burst_read
1539
 
1540
task uvm_mem::burst_read(output uvm_status_e       status,
1541
                         input  uvm_reg_addr_t     offset,
1542
                         ref    uvm_reg_data_t     value[],
1543
                         input  uvm_path_e         path = UVM_DEFAULT_PATH,
1544
                         input  uvm_reg_map        map = null,
1545
                         input  uvm_sequence_base  parent = null,
1546
                         input  int                prior = -1,
1547
                         input  uvm_object         extension = null,
1548
                         input  string             fname = "",
1549
                         input  int                lineno = 0);
1550
 
1551
   uvm_reg_item rw;
1552
   rw = uvm_reg_item::type_id::create("mem_burst_read",,get_full_name());
1553
   rw.element      = this;
1554
   rw.element_kind = UVM_MEM;
1555
   rw.kind         = UVM_BURST_READ;
1556
   rw.offset       = offset;
1557
   rw.value        = value;
1558
   rw.path         = path;
1559
   rw.map          = map;
1560
   rw.parent       = parent;
1561
   rw.prior        = prior;
1562
   rw.extension    = extension;
1563
   rw.fname        = fname;
1564
   rw.lineno       = lineno;
1565
 
1566
   do_read(rw);
1567
 
1568
   status = rw.status;
1569
   value  = rw.value;
1570
 
1571
endtask: burst_read
1572
 
1573
 
1574
// do_write
1575
 
1576
task uvm_mem::do_write(uvm_reg_item rw);
1577
 
1578
   uvm_mem_cb_iter  cbs = new(this);
1579
   uvm_reg_map_info map_info;
1580
 
1581
   m_fname  = rw.fname;
1582
   m_lineno = rw.lineno;
1583
 
1584
   if (!Xcheck_accessX(rw, map_info, "burst_write()"))
1585
     return;
1586
 
1587
   m_write_in_progress = 1'b1;
1588
 
1589
   rw.status = UVM_IS_OK;
1590
 
1591
   // PRE-WRITE CBS
1592
   pre_write(rw);
1593
   for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
1594
      cb.pre_write(rw);
1595
 
1596
   if (rw.status != UVM_IS_OK) begin
1597
      m_write_in_progress = 1'b0;
1598
 
1599
      return;
1600
   end
1601
 
1602
   rw.status = UVM_NOT_OK;
1603
 
1604
   // FRONTDOOR
1605
   if (rw.path == UVM_FRONTDOOR) begin
1606
 
1607
      uvm_reg_map system_map = rw.local_map.get_root_map();
1608
 
1609
      if (map_info.frontdoor != null) begin
1610
         uvm_reg_frontdoor fd = map_info.frontdoor;
1611
         fd.rw_info = rw;
1612
         if (fd.sequencer == null)
1613
           fd.sequencer = system_map.get_sequencer();
1614
         fd.start(fd.sequencer, rw.parent);
1615
      end
1616
      else begin
1617
         rw.local_map.do_write(rw);
1618
      end
1619
 
1620
      if (rw.status != UVM_NOT_OK)
1621
         for (uvm_reg_addr_t idx = rw.offset;
1622
              idx <= rw.offset + rw.value.size();
1623
              idx++) begin
1624
            XsampleX(map_info.mem_range.stride * idx, 0, rw.map);
1625
            m_parent.XsampleX(map_info.offset +
1626
                             (map_info.mem_range.stride * idx),
1627
                              0, rw.map);
1628
         end
1629
   end
1630
 
1631
   // BACKDOOR
1632
   else begin
1633
      // Mimick front door access, i.e. do not write read-only memories
1634
      if (get_access(rw.map) == "RW") begin
1635
         uvm_reg_backdoor bkdr = get_backdoor();
1636
         if (bkdr != null)
1637
            bkdr.write(rw);
1638
         else
1639
            backdoor_write(rw);
1640
      end
1641
      else
1642
         rw.status = UVM_IS_OK;
1643
   end
1644
 
1645
   // POST-WRITE CBS
1646
   post_write(rw);
1647
   for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
1648
      cb.post_write(rw);
1649
 
1650
   // REPORT
1651
   if (uvm_report_enabled(UVM_HIGH, UVM_INFO, "RegModel")) begin
1652
     string path_s,value_s,pre_s,range_s;
1653
     if (rw.path == UVM_FRONTDOOR)
1654
       path_s = (map_info.frontdoor != null) ? "user frontdoor" :
1655
                                               {"map ",rw.map.get_full_name()};
1656
     else
1657
       path_s = (get_backdoor() != null) ? "user backdoor" : "DPI backdoor";
1658
 
1659
     if (rw.value.size() > 1) begin
1660
       value_s = "='{";
1661
       pre_s = "Burst ";
1662
       foreach (rw.value[i])
1663
         value_s = {value_s,$sformatf("%0h,",rw.value[i])};
1664
       value_s[value_s.len()-1]="}";
1665
       range_s = $sformatf("[%0d:%0d]",rw.offset,rw.offset+rw.value.size());
1666
     end
1667
     else begin
1668
       value_s = $sformatf("=%0h",rw.value[0]);
1669
       range_s = $sformatf("[%0d]",rw.offset);
1670
     end
1671
 
1672
     uvm_report_info("RegModel", {pre_s,"Wrote memory via ",path_s,": ",
1673
                                  get_full_name(),range_s,value_s}, UVM_HIGH);
1674
   end
1675
 
1676
   m_write_in_progress = 1'b0;
1677
 
1678
endtask: do_write
1679
 
1680
 
1681
// do_read
1682
 
1683
task uvm_mem::do_read(uvm_reg_item rw);
1684
 
1685
   uvm_mem_cb_iter cbs = new(this);
1686
   uvm_reg_map_info map_info;
1687
 
1688
   m_fname = rw.fname;
1689
   m_lineno = rw.lineno;
1690
 
1691
   if (!Xcheck_accessX(rw, map_info, "burst_read()"))
1692
     return;
1693
 
1694
   m_read_in_progress = 1'b1;
1695
 
1696
   rw.status = UVM_IS_OK;
1697
 
1698
   // PRE-READ CBS
1699
   pre_read(rw);
1700
   for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
1701
      cb.pre_read(rw);
1702
 
1703
   if (rw.status != UVM_IS_OK) begin
1704
      m_read_in_progress = 1'b0;
1705
 
1706
      return;
1707
   end
1708
 
1709
   rw.status = UVM_NOT_OK;
1710
 
1711
   // FRONTDOOR
1712
   if (rw.path == UVM_FRONTDOOR) begin
1713
 
1714
      uvm_reg_map system_map = rw.local_map.get_root_map();
1715
 
1716
      if (map_info.frontdoor != null) begin
1717
         uvm_reg_frontdoor fd = map_info.frontdoor;
1718
         fd.rw_info = rw;
1719
         if (fd.sequencer == null)
1720
           fd.sequencer = system_map.get_sequencer();
1721
         fd.start(fd.sequencer, rw.parent);
1722
      end
1723
      else begin
1724
         rw.local_map.do_read(rw);
1725
      end
1726
 
1727
      if (rw.status != UVM_NOT_OK)
1728
         for (uvm_reg_addr_t idx = rw.offset;
1729
              idx <= rw.offset + rw.value.size();
1730
              idx++) begin
1731
            XsampleX(map_info.mem_range.stride * idx, 1, rw.map);
1732
            m_parent.XsampleX(map_info.offset +
1733
                             (map_info.mem_range.stride * idx),
1734
                              1, rw.map);
1735
         end
1736
   end
1737
 
1738
   // BACKDOOR
1739
   else begin
1740
      uvm_reg_backdoor bkdr = get_backdoor();
1741
      if (bkdr != null)
1742
         bkdr.read(rw);
1743
      else
1744
         backdoor_read(rw);
1745
   end
1746
 
1747
   // POST-READ CBS
1748
   post_read(rw);
1749
   for (uvm_reg_cbs cb=cbs.first(); cb!=null; cb=cbs.next())
1750
      cb.post_read(rw);
1751
 
1752
   // REPORT
1753
   if (uvm_report_enabled(UVM_HIGH, UVM_INFO, "RegModel")) begin
1754
     string path_s,value_s,pre_s,range_s;
1755
     if (rw.path == UVM_FRONTDOOR)
1756
       path_s = (map_info.frontdoor != null) ? "user frontdoor" :
1757
                                               {"map ",rw.map.get_full_name()};
1758
     else
1759
       path_s = (get_backdoor() != null) ? "user backdoor" : "DPI backdoor";
1760
 
1761
     if (rw.value.size() > 1) begin
1762
       value_s = "='{";
1763
       pre_s = "Burst ";
1764
       foreach (rw.value[i])
1765
         value_s = {value_s,$sformatf("%0h,",rw.value[i])};
1766
       value_s[value_s.len()-1]="}";
1767
       range_s = $sformatf("[%0d:%0d]",rw.offset,(rw.offset+rw.value.size()));
1768
     end
1769
     else begin
1770
       value_s = $sformatf("=%0h",rw.value[0]);
1771
       range_s = $sformatf("[%0d]",rw.offset);
1772
     end
1773
 
1774
      uvm_report_info("RegModel", {pre_s,"Read memory via ",path_s,": ",
1775
                                   get_full_name(),range_s,value_s}, UVM_HIGH);
1776
   end
1777
 
1778
   m_read_in_progress = 1'b0;
1779
 
1780
endtask: do_read
1781
 
1782
 
1783
// Xcheck_accessX
1784
 
1785
function bit uvm_mem::Xcheck_accessX(input uvm_reg_item rw,
1786
                                     output uvm_reg_map_info map_info,
1787
                                     input string caller);
1788
 
1789
   if (rw.offset >= m_size) begin
1790
      `uvm_error(get_type_name(),
1791
         $sformatf("Offset 'h%0h exceeds size of memory, 'h%0h",
1792
           rw.offset, m_size))
1793
      rw.status = UVM_NOT_OK;
1794
      return 0;
1795
   end
1796
 
1797
   if (rw.path == UVM_DEFAULT_PATH)
1798
     rw.path = m_parent.get_default_path();
1799
 
1800
   if (rw.path == UVM_BACKDOOR) begin
1801
      if (get_backdoor() == null && !has_hdl_path()) begin
1802
         `uvm_warning("RegModel",
1803
            {"No backdoor access available for memory '",get_full_name(),
1804
            "' . Using frontdoor instead."})
1805
         rw.path = UVM_FRONTDOOR;
1806
      end
1807
      else
1808
        rw.map = uvm_reg_map::backdoor();
1809
   end
1810
 
1811
   if (rw.path != UVM_BACKDOOR) begin
1812
 
1813
     rw.local_map = get_local_map(rw.map,caller);
1814
 
1815
     if (rw.local_map == null) begin
1816
        `uvm_error(get_type_name(),
1817
           {"No transactor available to physically access memory from map '",
1818
            rw.map.get_full_name(),"'"})
1819
        rw.status = UVM_NOT_OK;
1820
        return 0;
1821
     end
1822
 
1823
     map_info = rw.local_map.get_mem_map_info(this);
1824
 
1825
     if (map_info.frontdoor == null) begin
1826
 
1827
        if (map_info.unmapped) begin
1828
           `uvm_error("RegModel", {"Memory '",get_full_name(),
1829
                      "' unmapped in map '", rw.map.get_full_name(),
1830
                      "' and does not have a user-defined frontdoor"})
1831
           rw.status = UVM_NOT_OK;
1832
           return 0;
1833
        end
1834
 
1835
        if ((rw.value.size() > 1)) begin
1836
           if (get_n_bits() > rw.local_map.get_n_bytes()*8) begin
1837
              `uvm_error("RegModel",
1838
                    $sformatf("Cannot burst a %0d-bit memory through a narrower data path (%0d bytes)",
1839
                    get_n_bits(), rw.local_map.get_n_bytes()*8));
1840
              rw.status = UVM_NOT_OK;
1841
              return 0;
1842
           end
1843
           if (rw.offset + rw.value.size() > m_size) begin
1844
              `uvm_error("RegModel",
1845
                  $sformatf("Burst of size 'd%0d starting at offset 'd%0d exceeds size of memory, 'd%0d",
1846
                      rw.value.size(), rw.offset, m_size))
1847
              return 0;
1848
           end
1849
        end
1850
     end
1851
 
1852
     if (rw.map == null)
1853
       rw.map = rw.local_map;
1854
   end
1855
 
1856
   return 1;
1857
endfunction
1858
 
1859
 
1860
//-------
1861
// ACCESS
1862
//-------
1863
 
1864
// poke
1865
 
1866
task uvm_mem::poke(output uvm_status_e      status,
1867
                   input  uvm_reg_addr_t    offset,
1868
                   input  uvm_reg_data_t    value,
1869
                   input  string            kind = "",
1870
                   input  uvm_sequence_base parent = null,
1871
                   input  uvm_object        extension = null,
1872
                   input  string            fname = "",
1873
                   input  int               lineno = 0);
1874
   uvm_reg_item rw;
1875
   uvm_reg_backdoor bkdr = get_backdoor();
1876
 
1877
   m_fname = fname;
1878
   m_lineno = lineno;
1879
 
1880
   if (bkdr == null && !has_hdl_path(kind)) begin
1881
      `uvm_error("RegModel", {"No backdoor access available in memory '",
1882
                             get_full_name(),"'"})
1883
      status = UVM_NOT_OK;
1884
      return;
1885
   end
1886
 
1887
   // create an abstract transaction for this operation
1888
   rw = uvm_reg_item::type_id::create("mem_poke_item",,get_full_name());
1889
   rw.element      = this;
1890
   rw.path         = UVM_BACKDOOR;
1891
   rw.element_kind = UVM_MEM;
1892
   rw.kind         = UVM_WRITE;
1893
   rw.offset       = offset;
1894
   rw.value[0]     = value & ((1 << m_n_bits)-1);
1895
   rw.bd_kind      = kind;
1896
   rw.parent       = parent;
1897
   rw.extension    = extension;
1898
   rw.fname        = fname;
1899
   rw.lineno       = lineno;
1900
 
1901
   if (bkdr != null)
1902
     bkdr.write(rw);
1903
   else
1904
     backdoor_write(rw);
1905
 
1906
   status = rw.status;
1907
 
1908
   `uvm_info("RegModel", $sformatf("Poked memory '%s[%0d]' with value 'h%h",
1909
                              get_full_name(), offset, value),UVM_HIGH);
1910
 
1911
endtask: poke
1912
 
1913
 
1914
// peek
1915
 
1916
task uvm_mem::peek(output uvm_status_e      status,
1917
                   input  uvm_reg_addr_t    offset,
1918
                   output uvm_reg_data_t    value,
1919
                   input  string            kind = "",
1920
                   input  uvm_sequence_base parent = null,
1921
                   input  uvm_object        extension = null,
1922
                   input  string            fname = "",
1923
                   input  int               lineno = 0);
1924
   uvm_reg_backdoor bkdr = get_backdoor();
1925
   uvm_reg_item rw;
1926
 
1927
   m_fname = fname;
1928
   m_lineno = lineno;
1929
 
1930
   if (bkdr == null && !has_hdl_path(kind)) begin
1931
      `uvm_error("RegModel", {"No backdoor access available in memory '",
1932
                 get_full_name(),"'"})
1933
      status = UVM_NOT_OK;
1934
      return;
1935
   end
1936
 
1937
   // create an abstract transaction for this operation
1938
   rw = uvm_reg_item::type_id::create("mem_peek_item",,get_full_name());
1939
   rw.element      = this;
1940
   rw.path         = UVM_BACKDOOR;
1941
   rw.element_kind = UVM_MEM;
1942
   rw.kind         = UVM_READ;
1943
   rw.offset       = offset;
1944
   rw.bd_kind      = kind;
1945
   rw.parent       = parent;
1946
   rw.extension    = extension;
1947
   rw.fname        = fname;
1948
   rw.lineno       = lineno;
1949
 
1950
   if (bkdr != null)
1951
     bkdr.read(rw);
1952
   else
1953
     backdoor_read(rw);
1954
 
1955
   status = rw.status;
1956
   value  = rw.value[0];
1957
 
1958
   `uvm_info("RegModel", $sformatf("Peeked memory '%s[%0d]' has value 'h%h",
1959
                         get_full_name(), offset, value),UVM_HIGH);
1960
endtask: peek
1961
 
1962
 
1963
//-----------------
1964
// Group- Frontdoor
1965
//-----------------
1966
 
1967
// set_frontdoor
1968
 
1969
function void uvm_mem::set_frontdoor(uvm_reg_frontdoor ftdr,
1970
                                     uvm_reg_map       map = null,
1971
                                     string            fname = "",
1972
                                     int               lineno = 0);
1973
   uvm_reg_map_info map_info;
1974
   m_fname = fname;
1975
   m_lineno = lineno;
1976
 
1977
   map = get_local_map(map, "set_frontdoor()");
1978
 
1979
   if (map == null) begin
1980
      `uvm_error("RegModel", {"Memory '",get_full_name(),
1981
                 "' not found in map '", map.get_full_name(),"'"})
1982
      return;
1983
   end
1984
 
1985
   map_info = map.get_mem_map_info(this);
1986
   map_info.frontdoor = ftdr;
1987
 
1988
endfunction: set_frontdoor
1989
 
1990
 
1991
// get_frontdoor
1992
 
1993
function uvm_reg_frontdoor uvm_mem::get_frontdoor(uvm_reg_map map = null);
1994
   uvm_reg_map_info map_info;
1995
 
1996
   map = get_local_map(map, "set_frontdoor()");
1997
 
1998
   if (map == null) begin
1999
      `uvm_error("RegModel", {"Memory '",get_full_name(),
2000
                 "' not found in map '", map.get_full_name(),"'"})
2001
      return null;
2002
   end
2003
 
2004
   map_info = map.get_mem_map_info(this);
2005
   return map_info.frontdoor;
2006
 
2007
endfunction: get_frontdoor
2008
 
2009
 
2010
//----------------
2011
// Group- Backdoor
2012
//----------------
2013
 
2014
// set_backdoor
2015
 
2016
function void uvm_mem::set_backdoor(uvm_reg_backdoor bkdr,
2017
                                    string fname = "",
2018
                                    int lineno = 0);
2019
   m_fname = fname;
2020
   m_lineno = lineno;
2021
   m_backdoor = bkdr;
2022
endfunction: set_backdoor
2023
 
2024
 
2025
// get_backdoor
2026
 
2027
function uvm_reg_backdoor uvm_mem::get_backdoor(bit inherited = 1);
2028
 
2029
   if (m_backdoor == null && inherited) begin
2030
     uvm_reg_block blk = get_parent();
2031
     uvm_reg_backdoor bkdr;
2032
     while (blk != null) begin
2033
       bkdr = blk.get_backdoor();
2034
       if (bkdr != null) begin
2035
         m_backdoor = bkdr;
2036
         break;
2037
       end
2038
       blk = blk.get_parent();
2039
     end
2040
   end
2041
 
2042
   return m_backdoor;
2043
endfunction: get_backdoor
2044
 
2045
 
2046
// backdoor_read_func
2047
 
2048
function uvm_status_e uvm_mem::backdoor_read_func(uvm_reg_item rw);
2049
 
2050
  uvm_hdl_path_concat paths[$];
2051
  uvm_hdl_data_t val;
2052
  bit ok=1;
2053
 
2054
  get_full_hdl_path(paths,rw.bd_kind);
2055
 
2056
  foreach (rw.value[mem_idx]) begin
2057
     string idx;
2058
     idx.itoa(rw.offset + mem_idx);
2059
     foreach (paths[i]) begin
2060
        uvm_hdl_path_concat hdl_concat = paths[i];
2061
        val = 0;
2062
        foreach (hdl_concat.slices[j]) begin
2063
           string hdl_path = {hdl_concat.slices[j].path, "[", idx, "]"};
2064
 
2065
           `uvm_info("RegModel", {"backdoor_read from ",hdl_path},UVM_DEBUG)
2066
 
2067
           if (hdl_concat.slices[j].offset < 0) begin
2068
              ok &= uvm_hdl_read(hdl_path, val);
2069
              continue;
2070
           end
2071
           begin
2072
              uvm_reg_data_t slice;
2073
              int k = hdl_concat.slices[j].offset;
2074
              ok &= uvm_hdl_read(hdl_path, slice);
2075
              repeat (hdl_concat.slices[j].size) begin
2076
                 val[k++] = slice[0];
2077
                 slice >>= 1;
2078
              end
2079
           end
2080
        end
2081
 
2082
        val &= (1 << m_n_bits)-1;
2083
 
2084
        if (i == 0)
2085
           rw.value[mem_idx] = val;
2086
 
2087
        if (val != rw.value[mem_idx]) begin
2088
           `uvm_error("RegModel", $sformatf("Backdoor read of register %s with multiple HDL copies: values are not the same: %0h at path '%s', and %0h at path '%s'. Returning first value.",
2089
               get_full_name(), rw.value[mem_idx], uvm_hdl_concat2string(paths[0]),
2090
               val, uvm_hdl_concat2string(paths[i])));
2091
           return UVM_NOT_OK;
2092
         end
2093
      end
2094
  end
2095
 
2096
  rw.status = (ok) ? UVM_IS_OK : UVM_NOT_OK;
2097
 
2098
  return rw.status;
2099
endfunction
2100
 
2101
 
2102
// backdoor_read
2103
 
2104
task uvm_mem::backdoor_read(uvm_reg_item rw);
2105
  rw.status = backdoor_read_func(rw);
2106
endtask
2107
 
2108
 
2109
// backdoor_write
2110
 
2111
task uvm_mem::backdoor_write(uvm_reg_item rw);
2112
 
2113
  uvm_hdl_path_concat paths[$];
2114
  bit ok=1;
2115
 
2116
 
2117
  get_full_hdl_path(paths,rw.bd_kind);
2118
 
2119
  foreach (rw.value[mem_idx]) begin
2120
     string idx;
2121
     idx.itoa(rw.offset + mem_idx);
2122
     foreach (paths[i]) begin
2123
       uvm_hdl_path_concat hdl_concat = paths[i];
2124
       foreach (hdl_concat.slices[j]) begin
2125
          `uvm_info("RegModel", $sformatf("backdoor_write to %s ",hdl_concat.slices[j].path),UVM_DEBUG);
2126
 
2127
          if (hdl_concat.slices[j].offset < 0) begin
2128
             ok &= uvm_hdl_deposit({hdl_concat.slices[j].path,"[", idx, "]"},rw.value[mem_idx]);
2129
             continue;
2130
          end
2131
          begin
2132
            uvm_reg_data_t slice;
2133
            slice = rw.value[mem_idx] >> hdl_concat.slices[j].offset;
2134
            slice &= (1 << hdl_concat.slices[j].size)-1;
2135
            ok &= uvm_hdl_deposit({hdl_concat.slices[j].path, "[", idx, "]"}, slice);
2136
          end
2137
       end
2138
     end
2139
  end
2140
  rw.status = (ok ? UVM_IS_OK : UVM_NOT_OK);
2141
endtask
2142
 
2143
 
2144
 
2145
 
2146
// clear_hdl_path
2147
 
2148
function void uvm_mem::clear_hdl_path(string kind = "RTL");
2149
  if (kind == "ALL") begin
2150
    m_hdl_paths_pool = new("hdl_paths");
2151
    return;
2152
  end
2153
 
2154
  if (kind == "")
2155
    kind = m_parent.get_default_hdl_path();
2156
 
2157
  if (!m_hdl_paths_pool.exists(kind)) begin
2158
    `uvm_warning("RegModel",{"Unknown HDL Abstraction '",kind,"'"})
2159
    return;
2160
  end
2161
 
2162
  m_hdl_paths_pool.delete(kind);
2163
endfunction
2164
 
2165
 
2166
// add_hdl_path
2167
 
2168
function void uvm_mem::add_hdl_path(uvm_hdl_path_slice slices[], string kind = "RTL");
2169
    uvm_queue #(uvm_hdl_path_concat) paths = m_hdl_paths_pool.get(kind);
2170
    uvm_hdl_path_concat concat = new();
2171
 
2172
    concat.set(slices);
2173
    paths.push_back(concat);
2174
endfunction
2175
 
2176
 
2177
// add_hdl_path_slice
2178
 
2179
function void uvm_mem::add_hdl_path_slice(string name,
2180
                                          int offset,
2181
                                          int size,
2182
                                          bit first = 0,
2183
                                          string kind = "RTL");
2184
    uvm_queue #(uvm_hdl_path_concat) paths=m_hdl_paths_pool.get(kind);
2185
    uvm_hdl_path_concat concat;
2186
 
2187
    if (first || paths.size() == 0) begin
2188
       concat = new();
2189
       paths.push_back(concat);
2190
    end
2191
    else
2192
       concat = paths.get(paths.size()-1);
2193
 
2194
    concat.add_path(name, offset, size);
2195
endfunction
2196
 
2197
 
2198
// has_hdl_path
2199
 
2200
function bit  uvm_mem::has_hdl_path(string kind = "");
2201
  if (kind == "")
2202
    kind = m_parent.get_default_hdl_path();
2203
 
2204
  return m_hdl_paths_pool.exists(kind);
2205
endfunction
2206
 
2207
 
2208
// get_hdl_path
2209
 
2210
function void uvm_mem::get_hdl_path(ref uvm_hdl_path_concat paths[$],
2211
                                    input string kind = "");
2212
 
2213
  uvm_queue #(uvm_hdl_path_concat) hdl_paths;
2214
 
2215
  if (kind == "")
2216
     kind = m_parent.get_default_hdl_path();
2217
 
2218
  if (!has_hdl_path(kind)) begin
2219
    `uvm_error("RegModel",
2220
        {"Memory does not have hdl path defined for abstraction '",kind,"'"})
2221
    return;
2222
  end
2223
 
2224
  hdl_paths = m_hdl_paths_pool.get(kind);
2225
 
2226
  for (int i=0; i
2227
     uvm_hdl_path_concat t = hdl_paths.get(i);
2228
     paths.push_back(t);
2229
  end
2230
 
2231
endfunction
2232
 
2233
 
2234
// get_hdl_path_kinds
2235
 
2236
function void uvm_mem::get_hdl_path_kinds (ref string kinds[$]);
2237
  string kind;
2238
  kinds.delete();
2239
  if (!m_hdl_paths_pool.first(kind))
2240
    return;
2241
  do
2242
    kinds.push_back(kind);
2243
  while (m_hdl_paths_pool.next(kind));
2244
endfunction
2245
 
2246
// get_full_hdl_path
2247
 
2248
function void uvm_mem::get_full_hdl_path(ref uvm_hdl_path_concat paths[$],
2249
                                         input string kind = "",
2250
                                         input string separator = ".");
2251
 
2252
   if (kind == "")
2253
      kind = m_parent.get_default_hdl_path();
2254
 
2255
   if (!has_hdl_path(kind)) begin
2256
      `uvm_error("RegModel",
2257
          {"Memory does not have hdl path defined for abstraction '",kind,"'"})
2258
      return;
2259
   end
2260
 
2261
   begin
2262
      uvm_queue #(uvm_hdl_path_concat) hdl_paths = m_hdl_paths_pool.get(kind);
2263
      string parent_paths[$];
2264
 
2265
      m_parent.get_full_hdl_path(parent_paths, kind, separator);
2266
 
2267
      for (int i=0; i
2268
         uvm_hdl_path_concat hdl_concat = hdl_paths.get(i);
2269
 
2270
         foreach (parent_paths[j])  begin
2271
            uvm_hdl_path_concat t = new;
2272
 
2273
            foreach (hdl_concat.slices[k]) begin
2274
               if (hdl_concat.slices[k].path == "")
2275
                  t.add_path(parent_paths[j]);
2276
               else
2277
                  t.add_path({ parent_paths[j], separator, hdl_concat.slices[k].path },
2278
                             hdl_concat.slices[k].offset,
2279
                             hdl_concat.slices[k].size);
2280
            end
2281
            paths.push_back(t);
2282
         end
2283
      end
2284
   end
2285
endfunction
2286
 
2287
 
2288
// set_parent
2289
 
2290
function void uvm_mem::set_parent(uvm_reg_block parent);
2291
  m_parent = parent;
2292
endfunction
2293
 
2294
 
2295
// get_parent
2296
 
2297
function uvm_reg_block uvm_mem::get_parent();
2298
   return get_block();
2299
endfunction
2300
 
2301
 
2302
// convert2string
2303
 
2304
function string uvm_mem::convert2string();
2305
 
2306
   string res_str;
2307
   string prefix;
2308
 
2309
   $sformat(convert2string, "%sMemory %s -- %0dx%0d bits", prefix,
2310
            get_full_name(), get_size(), get_n_bits());
2311
 
2312
   if (m_maps.num()==0)
2313
     convert2string = {convert2string, "  (unmapped)\n"};
2314
   else
2315
     convert2string = {convert2string, "\n"};
2316
   foreach (m_maps[map]) begin
2317
     uvm_reg_map parent_map = map;
2318
     int unsigned offset;
2319
     while (parent_map != null) begin
2320
       uvm_reg_map this_map = parent_map;
2321
       uvm_endianness_e endian_name;
2322
       parent_map = this_map.get_parent_map();
2323
       endian_name=this_map.get_endian();
2324
 
2325
       offset = parent_map == null ? this_map.get_base_addr(UVM_NO_HIER) :
2326
                                     parent_map.get_submap_offset(this_map);
2327
       prefix = {prefix, "  "};
2328
       $sformat(convert2string, "%sMapped in '%s' -- buswidth %0d bytes, %s, offset 'h%0h, size 'h%0h, %s\n", prefix,
2329
            this_map.get_full_name(), this_map.get_n_bytes(), endian_name.name(), offset,get_size(),get_access(this_map));
2330
     end
2331
   end
2332
   prefix = "  ";
2333
   if (m_read_in_progress == 1'b1) begin
2334
      if (m_fname != "" && m_lineno != 0)
2335
         $sformat(res_str, "%s:%0d ",m_fname, m_lineno);
2336
      convert2string = {convert2string, "  ", res_str,
2337
                       "currently executing read method"};
2338
   end
2339
   if ( m_write_in_progress == 1'b1) begin
2340
      if (m_fname != "" && m_lineno != 0)
2341
         $sformat(res_str, "%s:%0d ",m_fname, m_lineno);
2342
      convert2string = {convert2string, "  ", res_str,
2343
                       "currently executing write method"};
2344
   end
2345
endfunction
2346
 
2347
 
2348
// do_print
2349
 
2350
function void uvm_mem::do_print (uvm_printer printer);
2351
  super.do_print(printer);
2352
  //printer.print_generic(" ", " ", -1, convert2string());
2353
  printer.print_field_int("n_bits",get_n_bits(),32, UVM_UNSIGNED);
2354
  printer.print_field_int("size",get_size(),32, UVM_UNSIGNED);
2355
endfunction
2356
 
2357
 
2358
// clone
2359
 
2360
function uvm_object uvm_mem::clone();
2361
  `uvm_fatal("RegModel","RegModel memories cannot be cloned")
2362
  return null;
2363
endfunction
2364
 
2365
// do_copy
2366
 
2367
function void uvm_mem::do_copy(uvm_object rhs);
2368
  `uvm_fatal("RegModel","RegModel memories cannot be copied")
2369
endfunction
2370
 
2371
 
2372
// do_compare
2373
 
2374
function bit uvm_mem::do_compare (uvm_object  rhs,
2375
                                        uvm_comparer comparer);
2376
  `uvm_warning("RegModel","RegModel memories cannot be compared")
2377
  return 0;
2378
endfunction
2379
 
2380
 
2381
// do_pack
2382
 
2383
function void uvm_mem::do_pack (uvm_packer packer);
2384
  `uvm_warning("RegModel","RegModel memories cannot be packed")
2385
endfunction
2386
 
2387
 
2388
// do_unpack
2389
 
2390
function void uvm_mem::do_unpack (uvm_packer packer);
2391
  `uvm_warning("RegModel","RegModel memories cannot be unpacked")
2392
endfunction
2393
 
2394
 
2395
// Xadd_vregX
2396
 
2397
function void uvm_mem::Xadd_vregX(uvm_vreg vreg);
2398
  m_vregs[vreg] = 1;
2399
endfunction
2400
 
2401
 
2402
// Xdelete_vregX
2403
 
2404
function void uvm_mem::Xdelete_vregX(uvm_vreg vreg);
2405
   if (m_vregs.exists(vreg))
2406
     m_vregs.delete(vreg);
2407
endfunction
2408
 
2409
 

powered by: WebSVN 2.1.0

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