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

Subversion Repositories uart2bus_testbench

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 HanySalah
// -------------------------------------------------------------
2
//    Copyright 2004-2011 Synopsys, Inc.
3
//    Copyright 2010-2011 Mentor Graphics Corporation
4
//    Copyright 2010-2011 Cadence Design Systems, Inc.
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
class uvm_reg_map_info;
24
   uvm_reg_addr_t         offset;
25
   string                 rights;
26
   bit                    unmapped;
27
   uvm_reg_addr_t         addr[];
28
   uvm_reg_frontdoor      frontdoor;
29
   uvm_reg_map_addr_range mem_range;
30
 
31
   // if set marks the uvm_reg_map_info as initialized, prevents using an uninitialized map (for instance if the model
32
   // has not been locked accidently and the maps have not been computed before)
33
   bit                    is_initialized;
34
endclass
35
 
36
 
37
// Class: uvm_reg_transaction_order_policy
38
virtual class uvm_reg_transaction_order_policy extends uvm_object;
39
    function new(string name = "policy");
40
        super.new(name);
41
    endfunction
42
 
43
    // Function: order
44
    // the order() function may reorder the sequence of bus transactions
45
    // produced by a single uvm_reg transaction (read/write).
46
    // This can be used in scenarios when the register width differs from
47
    // the bus width and one register access results in a series of bus transactions.
48
    // the first item (0) of the queue will be the first bus transaction (the last($)
49
    // will be the final transaction
50
    pure virtual function void order(ref uvm_reg_bus_op q[$]);
51
endclass
52
 
53
//------------------------------------------------------------------------------
54
//
55
// Class: uvm_reg_map
56
//
57
// :Address map abstraction class
58
//
59
// This class represents an address map.
60
// An address map is a collection of registers and memories
61
// accessible via a specific physical interface.
62
// Address maps can be composed into higher-level address maps.
63
//
64
// Address maps are created using the 
65
// method.
66
//------------------------------------------------------------------------------
67
 
68
class uvm_reg_map extends uvm_object;
69
 
70
   `uvm_object_utils(uvm_reg_map)
71
 
72
   // info that is valid only if top-level map
73
   local uvm_reg_addr_t     m_base_addr;
74
   local int unsigned       m_n_bytes;
75
   local uvm_endianness_e   m_endian;
76
   local bit                m_byte_addressing;
77
   local uvm_object_wrapper m_sequence_wrapper;
78
   local uvm_reg_adapter    m_adapter;
79
   local uvm_sequencer_base m_sequencer;
80
   local bit                m_auto_predict;
81
   local bit                m_check_on_read;
82
 
83
   local uvm_reg_block      m_parent;
84
 
85
   local int unsigned       m_system_n_bytes;
86
 
87
   local uvm_reg_map        m_parent_map;
88
   local uvm_reg_addr_t     m_parent_maps[uvm_reg_map];   // value=offset of this map at parent level
89
   local uvm_reg_addr_t     m_submaps[uvm_reg_map];       // value=offset of submap at this level
90
   local string             m_submap_rights[uvm_reg_map]; // value=rights of submap at this level
91
 
92
   local uvm_reg_map_info   m_regs_info[uvm_reg];
93
   local uvm_reg_map_info   m_mems_info[uvm_mem];
94
 
95
   local uvm_reg            m_regs_by_offset[uvm_reg_addr_t];
96
                            // Use only in addition to above if a RO and a WO
97
                            // register share the same address.
98
   local uvm_reg            m_regs_by_offset_wo[uvm_reg_addr_t];
99
   local uvm_mem            m_mems_by_offset[uvm_reg_map_addr_range];
100
 
101
   local uvm_reg_transaction_order_policy policy;
102
 
103
   extern /*local*/ function void Xinit_address_mapX();
104
 
105
   static local uvm_reg_map   m_backdoor;
106
 
107
   // Function: backdoor
108
   // Return the backdoor pseudo-map singleton
109
   //
110
   // This pseudo-map is used to specify or configure the backdoor
111
   // instead of a real address map.
112
   //
113
   static function uvm_reg_map backdoor();
114
      if (m_backdoor == null)
115
        m_backdoor = new("Backdoor");
116
      return m_backdoor;
117
   endfunction
118
 
119
 
120
   //----------------------
121
   // Group: Initialization
122
   //----------------------
123
 
124
 
125
   // Function: new
126
   //
127
   // Create a new instance
128
   //
129
   extern function new(string name="uvm_reg_map");
130
 
131
 
132
   // Function: configure
133
   //
134
   // Instance-specific configuration
135
   //
136
   // Configures this map with the following properties.
137
   //
138
   // parent    - the block in which this map is created and applied
139
   //
140
   // base_addr - the base address for this map. All registers, memories,
141
   //             and sub-blocks will be at offsets to this address
142
   //
143
   // n_bytes   - the byte-width of the bus on which this map is used
144
   //
145
   // endian    - the endian format. See  for possible
146
   //             values
147
   //
148
   // byte_addressing - specifies whether the address increment is on a
149
   //             per-byte basis. For example, consecutive memory locations
150
   //             with ~n_bytes~=4 (32-bit bus) are 4 apart: 0, 4, 8, and
151
   //             so on. Default is TRUE.
152
   //
153
   extern function void configure(uvm_reg_block     parent,
154
                                  uvm_reg_addr_t    base_addr,
155
                                  int unsigned      n_bytes,
156
                                  uvm_endianness_e  endian,
157
                                  bit byte_addressing = 1);
158
 
159
   // Function: add_reg
160
   //
161
   // Add a register
162
   //
163
   // Add the specified register instance ~rg~ to this address map.
164
   //
165
   // The register is located at the specified address ~offset~ from
166
   // this maps configured base address.
167
   //
168
   // The ~rights~ specify the register's accessibility via this map.
169
   // Valid values are "RW", "RO", and "WO". Whether a register field
170
   // can be read or written depends on both the field's configured access
171
   // policy (see  and the register's rights in
172
   // the map being used to access the field.
173
   //
174
   // The number of consecutive physical addresses occupied by the register
175
   // depends on the width of the register and the number of bytes in the
176
   // physical interface corresponding to this address map.
177
   //
178
   // If ~unmapped~ is TRUE, the register does not occupy any
179
   // physical addresses and the base address is ignored.
180
   // Unmapped registers require a user-defined ~frontdoor~ to be specified.
181
   //
182
   // A register may be added to multiple address maps
183
   // if it is accessible from multiple physical interfaces.
184
   // A register may only be added to an address map whose parent block
185
   // is the same as the register's parent block.
186
   //
187
   extern virtual function void add_reg (uvm_reg           rg,
188
                                         uvm_reg_addr_t    offset,
189
                                         string            rights = "RW",
190
                                         bit               unmapped=0,
191
                                         uvm_reg_frontdoor frontdoor=null);
192
 
193
 
194
   // Function: add_mem
195
   //
196
   // Add a memory
197
   //
198
   // Add the specified memory instance to this address map.
199
   // The memory is located at the specified base address and has the
200
   // specified access rights ("RW", "RO" or "WO").
201
   // The number of consecutive physical addresses occupied by the memory
202
   // depends on the width and size of the memory and the number of bytes in the
203
   // physical interface corresponding to this address map.
204
   //
205
   // If ~unmapped~ is TRUE, the memory does not occupy any
206
   // physical addresses and the base address is ignored.
207
   // Unmapped memories require a user-defined ~frontdoor~ to be specified.
208
   //
209
   // A memory may be added to multiple address maps
210
   // if it is accessible from multiple physical interfaces.
211
   // A memory may only be added to an address map whose parent block
212
   // is the same as the memory's parent block.
213
   //
214
   extern virtual function void add_mem (uvm_mem        mem,
215
                                         uvm_reg_addr_t offset,
216
                                         string         rights = "RW",
217
                                         bit            unmapped=0,
218
                                         uvm_reg_frontdoor frontdoor=null);
219
 
220
 
221
   // Function: add_submap
222
   //
223
   // Add an address map
224
   //
225
   // Add the specified address map instance to this address map.
226
   // The address map is located at the specified base address.
227
   // The number of consecutive physical addresses occupied by the submap
228
   // depends on the number of bytes in the physical interface
229
   // that corresponds to the submap,
230
   // the number of addresses used in the submap and
231
   // the number of bytes in the
232
   // physical interface corresponding to this address map.
233
   //
234
   // An address map may be added to multiple address maps
235
   // if it is accessible from multiple physical interfaces.
236
   // An address map may only be added to an address map
237
   // in the grand-parent block of the address submap.
238
   //
239
   extern virtual function void add_submap (uvm_reg_map    child_map,
240
                                            uvm_reg_addr_t offset);
241
 
242
 
243
   // Function: set_sequencer
244
   //
245
   // Set the sequencer and adapter associated with this map. This method
246
   // ~must~ be called before starting any sequences based on uvm_reg_sequence.
247
 
248
   extern virtual function void set_sequencer (uvm_sequencer_base sequencer,
249
                                               uvm_reg_adapter    adapter=null);
250
 
251
 
252
 
253
   // Function: set_submap_offset
254
   //
255
   // Set the offset of the given ~submap~ to ~offset~.
256
 
257
   extern virtual function void set_submap_offset (uvm_reg_map submap,
258
                                                   uvm_reg_addr_t offset);
259
 
260
 
261
   // Function: get_submap_offset
262
   //
263
   // Return the offset of the given ~submap~.
264
 
265
   extern virtual function uvm_reg_addr_t get_submap_offset (uvm_reg_map submap);
266
 
267
 
268
   // Function: set_base_addr
269
   //
270
   // Set the base address of this map.
271
 
272
   extern virtual function void   set_base_addr (uvm_reg_addr_t  offset);
273
 
274
 
275
   // Function: reset
276
   //
277
   // Reset the mirror for all registers in this address map.
278
   //
279
   // Sets the mirror value of all registers in this address map
280
   // and all of its submaps
281
   // to the reset value corresponding to the specified reset event.
282
   // See  for more details.
283
   // Does not actually set the value of the registers in the design,
284
   // only the values mirrored in their corresponding mirror.
285
   //
286
   // Note that, unlike the other reset() method, the default
287
   // reset event for this method is "SOFT".
288
   //
289
   extern virtual function void reset(string kind = "SOFT");
290
 
291
 
292
   /*local*/ extern virtual function void add_parent_map(uvm_reg_map  parent_map,
293
                                                         uvm_reg_addr_t offset);
294
 
295
   /*local*/ extern virtual function void Xverify_map_configX();
296
 
297
   /*local*/ extern virtual function void m_set_reg_offset(uvm_reg   rg,
298
                                                           uvm_reg_addr_t offset,
299
                                                           bit unmapped);
300
 
301
   /*local*/ extern virtual function void m_set_mem_offset(uvm_mem mem,
302
                                                           uvm_reg_addr_t offset,
303
                                                           bit unmapped);
304
 
305
 
306
   //---------------------
307
   // Group: Introspection
308
   //---------------------
309
 
310
   // Function: get_name
311
   //
312
   // Get the simple name
313
   //
314
   // Return the simple object name of this address map.
315
   //
316
 
317
   // Function: get_full_name
318
   //
319
   // Get the hierarchical name
320
   //
321
   // Return the hierarchal name of this address map.
322
   // The base of the hierarchical name is the root block.
323
   //
324
   extern virtual function string get_full_name();
325
 
326
 
327
   // Function: get_root_map
328
   //
329
   // Get the externally-visible address map
330
   //
331
   // Get the top-most address map where this address map is instantiated.
332
   // It corresponds to the externally-visible address map that can
333
   // be accessed by the verification environment.
334
   //
335
   extern virtual function uvm_reg_map get_root_map();
336
 
337
 
338
   // Function: get_parent
339
   //
340
   // Get the parent block
341
   //
342
   // Return the block that is the parent of this address map.
343
   //
344
   extern virtual function uvm_reg_block get_parent();
345
 
346
 
347
   // Function: get_parent_map
348
   // Get the higher-level address map
349
   //
350
   // Return the address map in which this address map is mapped.
351
   // returns ~null~ if this is a top-level address map.
352
   //
353
   extern virtual function uvm_reg_map           get_parent_map();
354
 
355
 
356
   // Function: get_base_addr
357
   //
358
   // Get the base offset address for this map. If this map is the
359
   // root map, the base address is that set with the ~base_addr~ argument
360
   // to . If this map is a submap of a higher-level map,
361
   // the base address is offset given this submap by the parent map.
362
   // See .
363
   //
364
   extern virtual function uvm_reg_addr_t get_base_addr (uvm_hier_e hier=UVM_HIER);
365
 
366
 
367
   // Function: get_n_bytes
368
   //
369
   // Get the width in bytes of the bus associated with this map. If ~hier~
370
   // is ~UVM_HIER~, then gets the effective bus width relative to the system
371
   // level. The effective bus width is the narrowest bus width from this
372
   // map to the top-level root map. Each bus access will be limited to this
373
   // bus width.
374
   //
375
   extern virtual function int unsigned get_n_bytes (uvm_hier_e hier=UVM_HIER);
376
 
377
 
378
   // Function: get_addr_unit_bytes
379
   //
380
   // Get the number of bytes in the smallest addressable unit in the map.
381
   // Returns 1 if the address map was configured using byte-level addressing.
382
   // Returns  otherwise.
383
   //
384
   extern virtual function int unsigned get_addr_unit_bytes();
385
 
386
 
387
   // Function: get_base_addr
388
   //
389
   // Gets the endianness of the bus associated with this map. If ~hier~ is
390
   // set to ~UVM_HIER~, gets the system-level endianness.
391
   //
392
   extern virtual function uvm_endianness_e get_endian (uvm_hier_e hier=UVM_HIER);
393
 
394
 
395
   // Function: get_sequencer
396
   //
397
   // Gets the sequencer for the bus associated with this map. If ~hier~ is
398
   // set to ~UVM_HIER~, gets the sequencer for the bus at the system-level.
399
   // See .
400
   //
401
   extern virtual function uvm_sequencer_base get_sequencer (uvm_hier_e hier=UVM_HIER);
402
 
403
 
404
   // Function: get_adapter
405
   //
406
   // Gets the bus adapter for the bus associated with this map. If ~hier~ is
407
   // set to ~UVM_HIER~, gets the adapter for the bus used at the system-level.
408
   // See .
409
   //
410
   extern virtual function uvm_reg_adapter get_adapter (uvm_hier_e hier=UVM_HIER);
411
 
412
 
413
   // Function: get_submaps
414
   //
415
   // Get the address sub-maps
416
   //
417
   // Get the address maps instantiated in this address map.
418
   // If ~hier~ is ~UVM_HIER~, recursively includes the address maps,
419
   // in the sub-maps.
420
   //
421
   extern virtual function void  get_submaps (ref uvm_reg_map maps[$],
422
                                              input uvm_hier_e hier=UVM_HIER);
423
 
424
 
425
   // Function: get_registers
426
   //
427
   // Get the registers
428
   //
429
   // Get the registers instantiated in this address map.
430
   // If ~hier~ is ~UVM_HIER~, recursively includes the registers
431
   // in the sub-maps.
432
   //
433
   extern virtual function void  get_registers (ref uvm_reg regs[$],
434
                                                input uvm_hier_e hier=UVM_HIER);
435
 
436
 
437
   // Function: get_fields
438
   //
439
   // Get the fields
440
   //
441
   // Get the fields in the registers instantiated in this address map.
442
   // If ~hier~ is ~UVM_HIER~, recursively includes the fields of the registers
443
   // in the sub-maps.
444
   //
445
   extern virtual function void  get_fields (ref uvm_reg_field fields[$],
446
                                             input uvm_hier_e hier=UVM_HIER);
447
 
448
 
449
   // Function: get_memories
450
   //
451
   // Get the memories
452
   //
453
   // Get the memories instantiated in this address map.
454
   // If ~hier~ is ~UVM_HIER~, recursively includes the memories
455
   // in the sub-maps.
456
   //
457
   extern virtual function void  get_memories (ref uvm_mem mems[$],
458
                                               input uvm_hier_e hier=UVM_HIER);
459
 
460
 
461
   // Function: get_virtual_registers
462
   //
463
   // Get the virtual registers
464
   //
465
   // Get the virtual registers instantiated in this address map.
466
   // If ~hier~ is ~UVM_HIER~, recursively includes the virtual registers
467
   // in the sub-maps.
468
   //
469
   extern virtual function void  get_virtual_registers (ref uvm_vreg regs[$],
470
                                                        input uvm_hier_e hier=UVM_HIER);
471
 
472
 
473
   // Function: get_virtual_fields
474
   //
475
   // Get the virtual fields
476
   //
477
   // Get the virtual fields from the virtual registers instantiated
478
   // in this address map.
479
   // If ~hier~ is ~UVM_HIER~, recursively includes the virtual fields
480
   // in the virtual registers in the sub-maps.
481
   //
482
   extern virtual function void  get_virtual_fields (ref uvm_vreg_field fields[$],
483
                                                     input uvm_hier_e hier=UVM_HIER);
484
 
485
 
486
   extern virtual function uvm_reg_map_info get_reg_map_info(uvm_reg rg,  bit error=1);
487
   extern virtual function uvm_reg_map_info get_mem_map_info(uvm_mem mem, bit error=1);
488
   extern virtual function int unsigned get_size();
489
 
490
 
491
   // Function: get_physical_addresses
492
   //
493
   // Translate a local address into external addresses
494
   //
495
   // Identify the sequence of addresses that must be accessed physically
496
   // to access the specified number of bytes at the specified address
497
   // within this address map.
498
   // Returns the number of bytes of valid data in each access.
499
   //
500
   // Returns in ~addr~ a list of address in little endian order,
501
   // with the granularity of the top-level address map.
502
   //
503
   // A register is specified using a base address with ~mem_offset~ as 0.
504
   // A location within a memory is specified using the base address
505
   // of the memory and the index of the location within that memory.
506
   //
507
 
508
   extern virtual function int get_physical_addresses(uvm_reg_addr_t        base_addr,
509
                                                      uvm_reg_addr_t        mem_offset,
510
                                                      int unsigned          n_bytes,
511
                                                      ref uvm_reg_addr_t    addr[]);
512
 
513
 
514
   // Function: get_reg_by_offset
515
   //
516
   // Get register mapped at offset
517
   //
518
   // Identify the register located at the specified offset within
519
   // this address map for the specified type of access.
520
   // Returns ~null~ if no such register is found.
521
   //
522
   // The model must be locked using 
523
   // to enable this functionality.
524
   //
525
   extern virtual function uvm_reg get_reg_by_offset(uvm_reg_addr_t offset,
526
                                                     bit            read = 1);
527
 
528
   //
529
   // Function: get_mem_by_offset
530
   // Get memory mapped at offset
531
   //
532
   // Identify the memory located at the specified offset within
533
   // this address map. The offset may refer to any memory location
534
   // in that memory.
535
   // Returns ~null~ if no such memory is found.
536
   //
537
   // The model must be locked using 
538
   // to enable this functionality.
539
   //
540
   extern virtual function uvm_mem    get_mem_by_offset(uvm_reg_addr_t offset);
541
 
542
 
543
   //------------------
544
   // Group: Bus Access
545
   //------------------
546
 
547
   // Function: set_auto_predict
548
   //
549
   // Sets the auto-predict mode for his map.
550
   //
551
   // When ~on~ is ~TRUE~,
552
   // the register model will automatically update its mirror
553
   // (what it thinks should be in the DUT) immediately after
554
   // any bus read or write operation via this map. Before a 
555
   // or  operation returns, the register's 
556
   // method is called to update the mirrored value in the register.
557
   //
558
   // When ~on~ is ~FALSE~, bus reads and writes via this map do not
559
   // automatically update the mirror. For real-time updates to the mirror
560
   // in this mode, you connect a  instance to the bus
561
   // monitor. The predictor takes observed bus transactions from the
562
   // bus monitor, looks up the associated  register given
563
   // the address, then calls that register's  method.
564
   // While more complex, this mode will capture all register read/write
565
   // activity, including that not directly descendant from calls to
566
   //  and .
567
   //
568
   // By default, auto-prediction is turned off.
569
   //
570
   function void set_auto_predict(bit on=1); m_auto_predict = on; endfunction
571
 
572
 
573
   // Function: get_auto_predict
574
   //
575
   // Gets the auto-predict mode setting for this map.
576
   //
577
   function bit  get_auto_predict(); return m_auto_predict; endfunction
578
 
579
 
580
   // Function: set_check_on_read
581
   //
582
   // Sets the check-on-read mode for his map
583
   // and all of its submaps.
584
   //
585
   // When ~on~ is ~TRUE~,
586
   // the register model will automatically check any value read back from
587
   // a register or field against the current value in its mirror
588
   // and report any discrepancy.
589
   // This effectively combines the functionality of the
590
   //  and ~uvm_reg::mirror(UVM_CHECK)~ method.
591
   // This mode is useful when the register model is used passively.
592
   //
593
   // When ~on~ is ~FALSE~, no check is made against the mirrored value.
594
   //
595
   // At the end of the read operation, the mirror value is updated based
596
   // on the value that was read regardless of this mode setting.
597
   //
598
   // By default, auto-prediction is turned off.
599
   //
600
   function void set_check_on_read(bit on=1);
601
      m_check_on_read = on;
602
      foreach (m_submaps[submap]) begin
603
         submap.set_check_on_read(on);
604
      end
605
   endfunction
606
 
607
 
608
   // Function: get_check_on_read
609
   //
610
   // Gets the check-on-read mode setting for this map.
611
   //
612
   function bit  get_check_on_read(); return m_check_on_read; endfunction
613
 
614
 
615
 
616
   // Task: do_bus_write
617
   //
618
   // Perform a bus write operation.
619
   //
620
   extern virtual task do_bus_write (uvm_reg_item rw,
621
                                     uvm_sequencer_base sequencer,
622
                                     uvm_reg_adapter adapter);
623
 
624
 
625
   // Task: do_bus_read
626
   //
627
   // Perform a bus read operation.
628
   //
629
   extern virtual task do_bus_read (uvm_reg_item rw,
630
                                    uvm_sequencer_base sequencer,
631
                                    uvm_reg_adapter adapter);
632
 
633
 
634
   // Task: do_write
635
   //
636
   // Perform a write operation.
637
   //
638
   extern virtual task do_write(uvm_reg_item rw);
639
 
640
 
641
   // Task: do_read
642
   //
643
   // Perform a read operation.
644
   //
645
   extern virtual task do_read(uvm_reg_item rw);
646
 
647
   extern function void Xget_bus_infoX (uvm_reg_item rw,
648
                                        output uvm_reg_map_info map_info,
649
                                        output int size,
650
                                        output int lsb,
651
                                        output int addr_skip);
652
 
653
   extern virtual function string      convert2string();
654
   extern virtual function uvm_object  clone();
655
   extern virtual function void        do_print (uvm_printer printer);
656
   extern virtual function void        do_copy   (uvm_object rhs);
657
   //extern virtual function bit       do_compare (uvm_object rhs, uvm_comparer comparer);
658
   //extern virtual function void      do_pack (uvm_packer packer);
659
   //extern virtual function void      do_unpack (uvm_packer packer);
660
 
661
 
662
    // Function: set_transaction_order_policy
663
    // set the transaction order policy
664
    function void set_transaction_order_policy(uvm_reg_transaction_order_policy pol);
665
        policy = pol;
666
    endfunction
667
 
668
    // Function: get_transaction_order_policy
669
    // set the transaction order policy
670
    function uvm_reg_transaction_order_policy get_transaction_order_policy();
671
        return policy;
672
    endfunction
673
 
674
endclass: uvm_reg_map
675
 
676
 
677
 
678
//---------------
679
// Initialization
680
//---------------
681
 
682
// new
683
 
684
function uvm_reg_map::new(string name = "uvm_reg_map");
685
   super.new((name == "") ? "default_map" : name);
686
   m_auto_predict = 0;
687
   m_check_on_read = 0;
688
endfunction
689
 
690
 
691
// configure
692
 
693
function void uvm_reg_map::configure(uvm_reg_block    parent,
694
                                     uvm_reg_addr_t   base_addr,
695
                                     int unsigned     n_bytes,
696
                                     uvm_endianness_e endian,
697
                                     bit              byte_addressing=1);
698
   m_parent     = parent;
699
   m_n_bytes    = n_bytes;
700
   m_endian     = endian;
701
   m_base_addr  = base_addr;
702
   m_byte_addressing = byte_addressing;
703
endfunction: configure
704
 
705
 
706
// add_reg
707
 
708
function void uvm_reg_map::add_reg(uvm_reg rg,
709
                                   uvm_reg_addr_t offset,
710
                                   string rights = "RW",
711
                                   bit unmapped=0,
712
                                   uvm_reg_frontdoor frontdoor=null);
713
 
714
   if (m_regs_info.exists(rg)) begin
715
      `uvm_error("RegModel", {"Register '",rg.get_name(),
716
                 "' has already been added to map '",get_name(),"'"})
717
      return;
718
   end
719
 
720
   if (rg.get_parent() != get_parent()) begin
721
      `uvm_error("RegModel",
722
         {"Register '",rg.get_full_name(),"' may not be added to address map '",
723
          get_full_name(),"' : they are not in the same block"})
724
      return;
725
   end
726
 
727
   rg.add_map(this);
728
 
729
   begin
730
   uvm_reg_map_info info = new;
731
   info.offset   = offset;
732
   info.rights   = rights;
733
   info.unmapped = unmapped;
734
   info.frontdoor = frontdoor;
735
   m_regs_info[rg] = info;
736
   end
737
endfunction
738
 
739
 
740
// m_set_reg_offset
741
 
742
function void uvm_reg_map::m_set_reg_offset(uvm_reg rg,
743
                                            uvm_reg_addr_t offset,
744
                                            bit unmapped);
745
 
746
   if (!m_regs_info.exists(rg)) begin
747
      `uvm_error("RegModel",
748
         {"Cannot modify offset of register '",rg.get_full_name(),
749
         "' in address map '",get_full_name(),
750
         "' : register not mapped in that address map"})
751
      return;
752
   end
753
 
754
   begin
755
      uvm_reg_map_info info    = m_regs_info[rg];
756
      uvm_reg_block    blk     = get_parent();
757
      uvm_reg_map      top_map = get_root_map();
758
      uvm_reg_addr_t   addrs[];
759
 
760
      // if block is not locked, Xinit_address_mapX will resolve map when block is locked
761
      if (blk.is_locked()) begin
762
 
763
         // remove any existing cached addresses
764
         if (!info.unmapped) begin
765
           foreach (info.addr[i]) begin
766
 
767
              if (!top_map.m_regs_by_offset_wo.exists(info.addr[i])) begin
768
                 top_map.m_regs_by_offset.delete(info.addr[i]);
769
              end
770
              else begin
771
                 if (top_map.m_regs_by_offset[info.addr[i]] == rg) begin
772
                    top_map.m_regs_by_offset[info.addr[i]] =
773
                      top_map.m_regs_by_offset_wo[info.addr[i]];
774
                    uvm_reg_read_only_cbs::remove(rg);
775
                    uvm_reg_write_only_cbs::remove(top_map.m_regs_by_offset[info.addr[i]]);
776
                 end
777
                 else begin
778
                    uvm_reg_write_only_cbs::remove(rg);
779
                    uvm_reg_read_only_cbs::remove(top_map.m_regs_by_offset[info.addr[i]]);
780
                 end
781
                 top_map.m_regs_by_offset_wo.delete(info.addr[i]);
782
              end
783
           end
784
         end
785
 
786
         // if we are remapping...
787
         if (!unmapped) begin
788
            string rg_acc = rg.Xget_fields_accessX(this);
789
 
790
            // get new addresses
791
            void'(get_physical_addresses(offset,0,rg.get_n_bytes(),addrs));
792
 
793
            // make sure they do not conflict with others
794
            foreach (addrs[i]) begin
795
               uvm_reg_addr_t addr = addrs[i];
796
               if (top_map.m_regs_by_offset.exists(addr)) begin
797
 
798
                  uvm_reg rg2 = top_map.m_regs_by_offset[addr];
799
                  string rg2_acc = rg2.Xget_fields_accessX(this);
800
 
801
                  // If the register at the same address is RO or WO
802
                  // and this register is WO or RO, this is OK
803
                  if (rg_acc == "RO" && rg2_acc == "WO") begin
804
                     top_map.m_regs_by_offset[addr]    = rg;
805
                     uvm_reg_read_only_cbs::add(rg);
806
                     top_map.m_regs_by_offset_wo[addr] = rg2;
807
                     uvm_reg_write_only_cbs::add(rg2);
808
                  end
809
                  else if (rg_acc == "WO" && rg2_acc == "RO") begin
810
                     top_map.m_regs_by_offset_wo[addr] = rg;
811
                     uvm_reg_write_only_cbs::add(rg);
812
                     uvm_reg_read_only_cbs::add(rg2);
813
                  end
814
                  else begin
815
                     string a;
816
                     a = $sformatf("%0h",addr);
817
                     `uvm_warning("RegModel", {"In map '",get_full_name(),"' register '",
818
                                               rg.get_full_name(), "' maps to same address as register '",
819
                                               top_map.m_regs_by_offset[addr].get_full_name(),"': 'h",a})
820
                  end
821
               end
822
               else
823
                  top_map.m_regs_by_offset[addr] = rg;
824
 
825
               foreach (top_map.m_mems_by_offset[range]) begin
826
                  if (addrs[i] >= range.min && addrs[i] <= range.max) begin
827
                    string a;
828
                    a = $sformatf("%0h",addrs[i]);
829
                    `uvm_warning("RegModel", {"In map '",get_full_name(),"' register '",
830
                        rg.get_full_name(), "' overlaps with address range of memory '",
831
                        top_map.m_mems_by_offset[range].get_full_name(),"': 'h",a})
832
                  end
833
               end
834
            end
835
            info.addr = addrs; // cache it
836
         end
837
      end
838
 
839
      if (unmapped) begin
840
        info.offset   = -1;
841
        info.unmapped = 1;
842
      end
843
      else begin
844
        info.offset   = offset;
845
        info.unmapped = 0;
846
      end
847
 
848
   end
849
endfunction
850
 
851
 
852
// add_mem
853
 
854
function void uvm_reg_map::add_mem(uvm_mem mem,
855
                                   uvm_reg_addr_t offset,
856
                                   string rights = "RW",
857
                                   bit unmapped=0,
858
                                   uvm_reg_frontdoor frontdoor=null);
859
   if (m_mems_info.exists(mem)) begin
860
      `uvm_error("RegModel", {"Memory '",mem.get_name(),
861
                 "' has already been added to map '",get_name(),"'"})
862
      return;
863
   end
864
 
865
   if (mem.get_parent() != get_parent()) begin
866
      `uvm_error("RegModel",
867
         {"Memory '",mem.get_full_name(),"' may not be added to address map '",
868
          get_full_name(),"' : they are not in the same block"})
869
      return;
870
   end
871
 
872
   mem.add_map(this);
873
 
874
   begin
875
   uvm_reg_map_info info = new;
876
   info.offset   = offset;
877
   info.rights   = rights;
878
   info.unmapped = unmapped;
879
   info.frontdoor = frontdoor;
880
   m_mems_info[mem] = info;
881
   end
882
endfunction: add_mem
883
 
884
 
885
 
886
// m_set_mem_offset
887
 
888
function void uvm_reg_map::m_set_mem_offset(uvm_mem mem,
889
                                            uvm_reg_addr_t offset,
890
                                            bit unmapped);
891
 
892
   if (!m_mems_info.exists(mem)) begin
893
      `uvm_error("RegModel",
894
         {"Cannot modify offset of memory '",mem.get_full_name(),
895
         "' in address map '",get_full_name(),
896
         "' : memory not mapped in that address map"})
897
      return;
898
   end
899
 
900
   begin
901
      uvm_reg_map_info info    = m_mems_info[mem];
902
      uvm_reg_block    blk     = get_parent();
903
      uvm_reg_map      top_map = get_root_map();
904
      uvm_reg_addr_t   addrs[];
905
 
906
      // if block is not locked, Xinit_address_mapX will resolve map when block is locked
907
      if (blk.is_locked()) begin
908
 
909
         // remove any existing cached addresses
910
         if (!info.unmapped) begin
911
           foreach (top_map.m_mems_by_offset[range]) begin
912
              if (top_map.m_mems_by_offset[range] == mem)
913
                 top_map.m_mems_by_offset.delete(range);
914
           end
915
         end
916
 
917
         // if we are remapping...
918
         if (!unmapped) begin
919
            uvm_reg_addr_t addrs[],addrs_max[];
920
            uvm_reg_addr_t min, max, min2, max2;
921
            int unsigned stride;
922
 
923
            void'(get_physical_addresses(offset,0,mem.get_n_bytes(),addrs));
924
            min = (addrs[0] < addrs[addrs.size()-1]) ? addrs[0] : addrs[addrs.size()-1];
925
            min2 = addrs[0];
926
 
927
            void'(get_physical_addresses(offset,(mem.get_size()-1),
928
                                         mem.get_n_bytes(),addrs_max));
929
            max = (addrs_max[0] > addrs_max[addrs_max.size()-1]) ?
930
               addrs_max[0] : addrs_max[addrs_max.size()-1];
931
            max2 = addrs_max[0];
932
            // address interval between consecutive mem locations
933
            stride = (max2 - max)/(mem.get_size()-1);
934
 
935
            // make sure new offset does not conflict with others
936
            foreach (top_map.m_regs_by_offset[reg_addr]) begin
937
               if (reg_addr >= min && reg_addr <= max) begin
938
                  string a,b;
939
                  a = $sformatf("[%0h:%0h]",min,max);
940
                  b = $sformatf("%0h",reg_addr);
941
                  `uvm_warning("RegModel", {"In map '",get_full_name(),"' memory '",
942
                      mem.get_full_name(), "' with range ",a,
943
                      " overlaps with address of existing register '",
944
                      top_map.m_regs_by_offset[reg_addr].get_full_name(),"': 'h",b})
945
               end
946
            end
947
 
948
            foreach (top_map.m_mems_by_offset[range]) begin
949
               if (min <= range.max && max >= range.max ||
950
                   min <= range.min && max >= range.min ||
951
                   min >= range.min && max <= range.max) begin
952
                 string a,b;
953
                 a = $sformatf("[%0h:%0h]",min,max);
954
                 b = $sformatf("[%0h:%0h]",range.min,range.max);
955
                 `uvm_warning("RegModel", {"In map '",get_full_name(),"' memory '",
956
                     mem.get_full_name(), "' with range ",a,
957
                     " overlaps existing memory with range '",
958
                     top_map.m_mems_by_offset[range].get_full_name(),"': ",b})
959
                 end
960
            end
961
 
962
            begin
963
              uvm_reg_map_addr_range range = '{ min, max, stride };
964
              top_map.m_mems_by_offset[range] = mem;
965
              info.addr  = addrs;
966
              info.mem_range = range;
967
            end
968
 
969
         end
970
      end
971
 
972
      if (unmapped) begin
973
        info.offset   = -1;
974
        info.unmapped = 1;
975
      end
976
      else begin
977
        info.offset   = offset;
978
        info.unmapped = 0;
979
      end
980
 
981
   end
982
endfunction
983
 
984
 
985
// add_submap
986
 
987
function void uvm_reg_map::add_submap (uvm_reg_map child_map,
988
                                       uvm_reg_addr_t offset);
989
   uvm_reg_map parent_map;
990
 
991
   if (child_map == null) begin
992
      `uvm_error("RegModel", {"Attempting to add NULL map to map '",get_full_name(),"'"})
993
      return;
994
   end
995
 
996
   parent_map = child_map.get_parent_map();
997
 
998
   // Cannot have more than one parent (currently)
999
   if (parent_map != null) begin
1000
      `uvm_error("RegModel", {"Map '", child_map.get_full_name(),
1001
                 "' is already a child of map '",
1002
                 parent_map.get_full_name(),
1003
                 "'. Cannot also be a child of map '",
1004
                 get_full_name(),
1005
                 "'"})
1006
      return;
1007
   end
1008
 
1009
   begin : parent_block_check
1010
     uvm_reg_block child_blk = child_map.get_parent();
1011
     if (child_blk == null) begin
1012
        `uvm_error("RegModel", {"Cannot add submap '",child_map.get_full_name(),
1013
                   "' because it does not have a parent block"})
1014
        return;
1015
     end
1016
     while((child_blk!=null) && (child_blk.get_parent() != get_parent()))
1017
                child_blk = child_blk.get_parent();
1018
 
1019
     if (child_blk==null) begin
1020
        `uvm_error("RegModel",
1021
          {"Submap '",child_map.get_full_name(),"' may not be added to this ",
1022
          "address map, '", get_full_name(),"', as the submap's parent block, '",
1023
          child_blk.get_full_name(),"', is neither this map's parent block nor a descendent of this map's parent block, '",
1024
          m_parent.get_full_name(),"'"})
1025
      return;
1026
     end
1027
   end
1028
 
1029
   begin : n_bytes_match_check
1030
      if (m_n_bytes > child_map.get_n_bytes(UVM_NO_HIER)) begin
1031
         `uvm_warning("RegModel",
1032
             $sformatf("Adding %0d-byte submap '%s' to %0d-byte parent map '%s'",
1033
                       child_map.get_n_bytes(UVM_NO_HIER), child_map.get_full_name(),
1034
                       m_n_bytes, get_full_name()));
1035
      end
1036
   end
1037
 
1038
   child_map.add_parent_map(this,offset);
1039
 
1040
   set_submap_offset(child_map, offset);
1041
 
1042
endfunction: add_submap
1043
 
1044
 
1045
// reset
1046
 
1047
function void uvm_reg_map::reset(string kind = "SOFT");
1048
   uvm_reg regs[$];
1049
 
1050
   get_registers(regs);
1051
 
1052
   foreach (regs[i]) begin
1053
      regs[i].reset(kind);
1054
   end
1055
endfunction
1056
 
1057
 
1058
// add_parent_map
1059
 
1060
function void uvm_reg_map::add_parent_map(uvm_reg_map parent_map, uvm_reg_addr_t offset);
1061
 
1062
   if (parent_map == null) begin
1063
      `uvm_error("RegModel",
1064
          {"Attempting to add NULL parent map to map '",get_full_name(),"'"})
1065
      return;
1066
   end
1067
 
1068
   if (m_parent_map != null) begin
1069
      `uvm_error("RegModel",
1070
          $sformatf("Map \"%s\" already a submap of map \"%s\" at offset 'h%h",
1071
                    get_full_name(), m_parent_map.get_full_name(),
1072
                    m_parent_map.get_submap_offset(this)));
1073
      return;
1074
   end
1075
 
1076
   m_parent_map = parent_map;
1077
   m_parent_maps[parent_map] = offset; // prep for multiple parents
1078
   parent_map.m_submaps[this] = offset;
1079
 
1080
endfunction: add_parent_map
1081
 
1082
 
1083
// set_sequencer
1084
 
1085
function void uvm_reg_map::set_sequencer(uvm_sequencer_base sequencer,
1086
                                         uvm_reg_adapter adapter=null);
1087
 
1088
   if (sequencer == null) begin
1089
      `uvm_error("REG_NULL_SQR", "Null reference specified for bus sequencer");
1090
      return;
1091
   end
1092
 
1093
   if (adapter == null) begin
1094
      `uvm_info("REG_NO_ADAPT", {"Adapter not specified for map '",get_full_name(),
1095
        "'. Accesses via this map will send abstract 'uvm_reg_item' items to sequencer '",
1096
        sequencer.get_full_name(),"'"},UVM_MEDIUM)
1097
   end
1098
 
1099
   m_sequencer = sequencer;
1100
   m_adapter = adapter;
1101
endfunction
1102
 
1103
 
1104
 
1105
//------------
1106
// get methods
1107
//------------
1108
 
1109
// get_parent
1110
 
1111
function uvm_reg_block uvm_reg_map::get_parent();
1112
  return m_parent;
1113
endfunction
1114
 
1115
 
1116
// get_parent_map
1117
 
1118
function uvm_reg_map uvm_reg_map::get_parent_map();
1119
  return m_parent_map;
1120
endfunction
1121
 
1122
 
1123
// get_root_map
1124
 
1125
function uvm_reg_map uvm_reg_map::get_root_map();
1126
   return (m_parent_map == null) ? this : m_parent_map.get_root_map();
1127
endfunction: get_root_map
1128
 
1129
 
1130
// get_base_addr
1131
 
1132
function uvm_reg_addr_t  uvm_reg_map::get_base_addr(uvm_hier_e hier=UVM_HIER);
1133
  uvm_reg_map child = this;
1134
  if (hier == UVM_NO_HIER || m_parent_map == null)
1135
    return m_base_addr;
1136
  get_base_addr = m_parent_map.get_submap_offset(this);
1137
  get_base_addr += m_parent_map.get_base_addr(UVM_HIER);
1138
endfunction
1139
 
1140
 
1141
// get_n_bytes
1142
 
1143
function int unsigned uvm_reg_map::get_n_bytes(uvm_hier_e hier=UVM_HIER);
1144
  if (hier == UVM_NO_HIER)
1145
    return m_n_bytes;
1146
  return m_system_n_bytes;
1147
endfunction
1148
 
1149
 
1150
// get_addr_unit_bytes
1151
 
1152
function int unsigned uvm_reg_map::get_addr_unit_bytes();
1153
   return (m_byte_addressing) ? 1 : m_n_bytes;
1154
endfunction
1155
 
1156
 
1157
// get_endian
1158
 
1159
function uvm_endianness_e uvm_reg_map::get_endian(uvm_hier_e hier=UVM_HIER);
1160
  if (hier == UVM_NO_HIER || m_parent_map == null)
1161
    return m_endian;
1162
  return m_parent_map.get_endian(hier);
1163
endfunction
1164
 
1165
 
1166
// get_sequencer
1167
 
1168
function uvm_sequencer_base uvm_reg_map::get_sequencer(uvm_hier_e hier=UVM_HIER);
1169
  if (hier == UVM_NO_HIER || m_parent_map == null)
1170
    return m_sequencer;
1171
  return m_parent_map.get_sequencer(hier);
1172
endfunction
1173
 
1174
 
1175
// get_adapter
1176
 
1177
function uvm_reg_adapter uvm_reg_map::get_adapter(uvm_hier_e hier=UVM_HIER);
1178
  if (hier == UVM_NO_HIER || m_parent_map == null)
1179
    return m_adapter;
1180
  return m_parent_map.get_adapter(hier);
1181
endfunction
1182
 
1183
 
1184
// get_submaps
1185
 
1186
function void uvm_reg_map::get_submaps(ref uvm_reg_map maps[$], input uvm_hier_e hier=UVM_HIER);
1187
 
1188
   foreach (m_submaps[submap])
1189
     maps.push_back(submap);
1190
 
1191
 
1192
   if (hier == UVM_HIER)
1193
     foreach (m_submaps[submap_]) begin
1194
       uvm_reg_map submap=submap_;
1195
       submap.get_submaps(maps);
1196
     end
1197
endfunction
1198
 
1199
 
1200
// get_registers
1201
 
1202
function void uvm_reg_map::get_registers(ref uvm_reg regs[$], input uvm_hier_e hier=UVM_HIER);
1203
 
1204
  foreach (m_regs_info[rg])
1205
    regs.push_back(rg);
1206
 
1207
  if (hier == UVM_HIER)
1208
    foreach (m_submaps[submap_]) begin
1209
      uvm_reg_map submap=submap_;
1210
      submap.get_registers(regs);
1211
    end
1212
 
1213
endfunction
1214
 
1215
 
1216
// get_fields
1217
 
1218
function void uvm_reg_map::get_fields(ref uvm_reg_field fields[$], input uvm_hier_e hier=UVM_HIER);
1219
 
1220
   foreach (m_regs_info[rg_]) begin
1221
     uvm_reg rg = rg_;
1222
     rg.get_fields(fields);
1223
   end
1224
 
1225
   if (hier == UVM_HIER)
1226
     foreach (this.m_submaps[submap_]) begin
1227
       uvm_reg_map submap=submap_;
1228
       submap.get_fields(fields);
1229
     end
1230
 
1231
endfunction
1232
 
1233
 
1234
// get_memories
1235
 
1236
function void uvm_reg_map::get_memories(ref uvm_mem mems[$], input uvm_hier_e hier=UVM_HIER);
1237
 
1238
   foreach (m_mems_info[mem])
1239
     mems.push_back(mem);
1240
 
1241
   if (hier == UVM_HIER)
1242
     foreach (m_submaps[submap_]) begin
1243
       uvm_reg_map submap=submap_;
1244
       submap.get_memories(mems);
1245
     end
1246
 
1247
endfunction
1248
 
1249
 
1250
// get_virtual_registers
1251
 
1252
function void uvm_reg_map::get_virtual_registers(ref uvm_vreg regs[$], input uvm_hier_e hier=UVM_HIER);
1253
 
1254
  uvm_mem mems[$];
1255
  get_memories(mems,hier);
1256
 
1257
  foreach (mems[i])
1258
    mems[i].get_virtual_registers(regs);
1259
 
1260
endfunction
1261
 
1262
 
1263
// get_virtual_fields
1264
 
1265
function void uvm_reg_map::get_virtual_fields(ref uvm_vreg_field fields[$], input uvm_hier_e hier=UVM_HIER);
1266
 
1267
   uvm_vreg regs[$];
1268
   get_virtual_registers(regs,hier);
1269
 
1270
   foreach (regs[i])
1271
       regs[i].get_fields(fields);
1272
 
1273
endfunction
1274
 
1275
 
1276
 
1277
// get_full_name
1278
 
1279
function string uvm_reg_map::get_full_name();
1280
 
1281
   get_full_name = get_name();
1282
 
1283
   if (m_parent == null)
1284
     return get_full_name;
1285
 
1286
   return {m_parent.get_full_name(), ".", get_full_name};
1287
 
1288
endfunction: get_full_name
1289
 
1290
 
1291
// get_mem_map_info
1292
 
1293
function uvm_reg_map_info uvm_reg_map::get_mem_map_info(uvm_mem mem, bit error=1);
1294
  if (!m_mems_info.exists(mem)) begin
1295
    if (error)
1296
      `uvm_error("REG_NO_MAP",{"Memory '",mem.get_name(),"' not in map '",get_name(),"'"})
1297
    return null;
1298
  end
1299
  return m_mems_info[mem];
1300
endfunction
1301
 
1302
 
1303
// get_reg_map_info
1304
 
1305
function uvm_reg_map_info uvm_reg_map::get_reg_map_info(uvm_reg rg, bit error=1);
1306
  uvm_reg_map_info result;
1307
  if (!m_regs_info.exists(rg)) begin
1308
    if (error)
1309
      `uvm_error("REG_NO_MAP",{"Register '",rg.get_name(),"' not in map '",get_name(),"'"})
1310
    return null;
1311
  end
1312
  result = m_regs_info[rg];
1313
  if(!result.is_initialized)
1314
    `uvm_warning("RegModel",{"map '",get_name(),"' does not seem to be initialized correctly, check that the top register model is locked()"})
1315
 
1316
  return result;
1317
endfunction
1318
 
1319
 
1320
//----------
1321
// Size and Overlap Detection
1322
//---------
1323
 
1324
// set_base_addr
1325
 
1326
function void uvm_reg_map::set_base_addr(uvm_reg_addr_t offset);
1327
   if (m_parent_map != null) begin
1328
      m_parent_map.set_submap_offset(this, offset);
1329
   end
1330
   else begin
1331
      m_base_addr = offset;
1332
      if (m_parent.is_locked()) begin
1333
         uvm_reg_map top_map = get_root_map();
1334
         top_map.Xinit_address_mapX();
1335
      end
1336
   end
1337
endfunction
1338
 
1339
 
1340
// get_size
1341
 
1342
function int unsigned uvm_reg_map::get_size();
1343
 
1344
  int unsigned max_addr;
1345
  int unsigned addr;
1346
 
1347
  // get max offset from registers
1348
  foreach (m_regs_info[rg_]) begin
1349
    uvm_reg rg = rg_;
1350
    addr = m_regs_info[rg].offset + ((rg.get_n_bytes()-1)/m_n_bytes);
1351
    if (addr > max_addr) max_addr = addr;
1352
  end
1353
 
1354
  // get max offset from memories
1355
  foreach (m_mems_info[mem_]) begin
1356
    uvm_mem mem = mem_;
1357
    addr = m_mems_info[mem].offset + (mem.get_size() * (((mem.get_n_bytes()-1)/m_n_bytes)+1)) -1;
1358
    if (addr > max_addr) max_addr = addr;
1359
  end
1360
 
1361
  // get max offset from submaps
1362
  foreach (m_submaps[submap_]) begin
1363
    uvm_reg_map submap=submap_;
1364
    addr = m_submaps[submap] + submap.get_size();
1365
    if (addr > max_addr) max_addr = addr;
1366
  end
1367
 
1368
  return max_addr + 1;
1369
 
1370
endfunction
1371
 
1372
 
1373
 
1374
function void uvm_reg_map::Xverify_map_configX();
1375
   // Make sure there is a generic payload sequence for each map
1376
   // in the model and vice-versa if this is a root sequencer
1377
   bit error;
1378
   uvm_reg_map root_map = get_root_map();
1379
 
1380
   if (root_map.get_adapter() == null) begin
1381
      `uvm_error("RegModel", {"Map '",root_map.get_full_name(),
1382
                 "' does not have an adapter registered"})
1383
      error++;
1384
   end
1385
   if (root_map.get_sequencer() == null) begin
1386
      `uvm_error("RegModel", {"Map '",root_map.get_full_name(),
1387
                 "' does not have a sequencer registered"})
1388
      error++;
1389
   end
1390
   if (error) begin
1391
      `uvm_fatal("RegModel", {"Must register an adapter and sequencer ",
1392
                 "for each top-level map in RegModel model"});
1393
      return;
1394
   end
1395
 
1396
endfunction
1397
 
1398
 
1399
 
1400
// get_physical_addresses
1401
 
1402
function int uvm_reg_map::get_physical_addresses(uvm_reg_addr_t     base_addr,
1403
                                                 uvm_reg_addr_t     mem_offset,
1404
                                                 int unsigned       n_bytes,
1405
                                                 ref uvm_reg_addr_t addr[]);
1406
   int bus_width = get_n_bytes(UVM_NO_HIER);
1407
   uvm_reg_map  up_map;
1408
   uvm_reg_addr_t  local_addr[];
1409
   int multiplier = m_byte_addressing ? bus_width : 1;
1410
 
1411
   addr = new [0];
1412
 
1413
   if (n_bytes <= 0) begin
1414
      `uvm_fatal("RegModel", $sformatf("Cannot access %0d bytes. Must be greater than 0",
1415
                                     n_bytes));
1416
      return 0;
1417
   end
1418
 
1419
   // First, identify the addresses within the block/system
1420
   if (n_bytes <= bus_width) begin
1421
      local_addr = new [1];
1422
      local_addr[0] = base_addr + (mem_offset * multiplier);
1423
   end else begin
1424
      int n;
1425
 
1426
      n = ((n_bytes-1) / bus_width) + 1;
1427
      local_addr = new [n];
1428
 
1429
      base_addr = base_addr + mem_offset * (n * multiplier);
1430
 
1431
      case (get_endian(UVM_NO_HIER))
1432
         UVM_LITTLE_ENDIAN: begin
1433
            foreach (local_addr[i]) begin
1434
               local_addr[i] = base_addr + (i * multiplier);
1435
            end
1436
         end
1437
         UVM_BIG_ENDIAN: begin
1438
            foreach (local_addr[i]) begin
1439
               n--;
1440
               local_addr[i] = base_addr + (n * multiplier);
1441
            end
1442
         end
1443
         UVM_LITTLE_FIFO: begin
1444
            foreach (local_addr[i]) begin
1445
               local_addr[i] = base_addr;
1446
            end
1447
         end
1448
         UVM_BIG_FIFO: begin
1449
            foreach (local_addr[i]) begin
1450
               local_addr[i] = base_addr;
1451
            end
1452
         end
1453
         default: begin
1454
            `uvm_error("RegModel",
1455
               {"Map has no specified endianness. ",
1456
                $sformatf("Cannot access %0d bytes register via its %0d byte \"%s\" interface",
1457
               n_bytes, bus_width, get_full_name())})
1458
         end
1459
      endcase
1460
   end
1461
 
1462
  up_map = get_parent_map();
1463
 
1464
   // Then translate these addresses in the parent's space
1465
   if (up_map == null) begin
1466
      // This is the top-most system/block!
1467
      addr = new [local_addr.size()] (local_addr);
1468
      foreach (addr[i]) begin
1469
         addr[i] += m_base_addr;
1470
      end
1471
   end else begin
1472
      uvm_reg_addr_t  sys_addr[];
1473
      uvm_reg_addr_t  base_addr;
1474
      int w, k;
1475
 
1476
      // Scale the consecutive local address in the system's granularity
1477
      if (bus_width < up_map.get_n_bytes(UVM_NO_HIER))
1478
        k = 1;
1479
      else
1480
        k = ((bus_width-1) / up_map.get_n_bytes(UVM_NO_HIER)) + 1;
1481
 
1482
      base_addr = up_map.get_submap_offset(this);
1483
      foreach (local_addr[i]) begin
1484
         int n = addr.size();
1485
 
1486
         w = up_map.get_physical_addresses(base_addr + local_addr[i] * k,
1487
                                           0,
1488
                                           bus_width,
1489
                                           sys_addr);
1490
 
1491
         addr = new [n + sys_addr.size()] (addr);
1492
         foreach (sys_addr[j]) begin
1493
            addr[n+j] = sys_addr[j];
1494
         end
1495
      end
1496
      // The width of each access is the minimum of this block or the system's width
1497
      if (w < bus_width)
1498
         bus_width = w;
1499
   end
1500
 
1501
   return bus_width;
1502
 
1503
endfunction: get_physical_addresses
1504
 
1505
 
1506
//--------------
1507
// Get-By-Offset
1508
//--------------
1509
 
1510
 
1511
// set_submap_offset
1512
 
1513
function void uvm_reg_map::set_submap_offset(uvm_reg_map submap, uvm_reg_addr_t offset);
1514
  if (submap == null) begin
1515
    `uvm_error("REG/NULL","set_submap_offset: submap handle is null")
1516
    return;
1517
  end
1518
  m_submaps[submap] = offset;
1519
  if (m_parent.is_locked()) begin
1520
    uvm_reg_map root_map = get_root_map();
1521
    root_map.Xinit_address_mapX();
1522
  end
1523
endfunction
1524
 
1525
 
1526
// get_submap_offset
1527
 
1528
function uvm_reg_addr_t uvm_reg_map::get_submap_offset(uvm_reg_map submap);
1529
  if (submap == null) begin
1530
    `uvm_error("REG/NULL","set_submap_offset: submap handle is null")
1531
    return -1;
1532
  end
1533
  if (!m_submaps.exists(submap)) begin
1534
    `uvm_error("RegModel",{"Map '",submap.get_full_name(),
1535
                      "' is not a submap of '",get_full_name(),"'"})
1536
    return -1;
1537
  end
1538
  return m_submaps[submap];
1539
endfunction
1540
 
1541
 
1542
// get_reg_by_offset
1543
 
1544
function uvm_reg uvm_reg_map::get_reg_by_offset(uvm_reg_addr_t offset,
1545
                                                bit            read = 1);
1546
   if (!m_parent.is_locked()) begin
1547
      `uvm_error("RegModel", $sformatf("Cannot get register by offset: Block %s is not locked.", m_parent.get_full_name()));
1548
      return null;
1549
   end
1550
 
1551
   if (!read && m_regs_by_offset_wo.exists(offset))
1552
     return m_regs_by_offset_wo[offset];
1553
 
1554
   if (m_regs_by_offset.exists(offset))
1555
     return m_regs_by_offset[offset];
1556
 
1557
   return null;
1558
endfunction
1559
 
1560
 
1561
// get_mem_by_offset
1562
 
1563
function uvm_mem uvm_reg_map::get_mem_by_offset(uvm_reg_addr_t offset);
1564
   if (!m_parent.is_locked()) begin
1565
      `uvm_error("RegModel", $sformatf("Cannot memory register by offset: Block %s is not locked.", m_parent.get_full_name()));
1566
      return null;
1567
   end
1568
 
1569
   foreach (m_mems_by_offset[range]) begin
1570
      if (range.min <= offset && offset <= range.max) begin
1571
         return m_mems_by_offset[range];
1572
      end
1573
   end
1574
 
1575
   return null;
1576
endfunction
1577
 
1578
 
1579
// Xinit_address_mapX
1580
 
1581
function void uvm_reg_map::Xinit_address_mapX();
1582
 
1583
   int unsigned bus_width;
1584
 
1585
   uvm_reg_map top_map = get_root_map();
1586
 
1587
   if (this == top_map) begin
1588
     top_map.m_regs_by_offset.delete();
1589
     top_map.m_regs_by_offset_wo.delete();
1590
     top_map.m_mems_by_offset.delete();
1591
   end
1592
 
1593
   foreach (m_submaps[l]) begin
1594
     uvm_reg_map map=l;
1595
     map.Xinit_address_mapX();
1596
   end
1597
 
1598
   foreach (m_regs_info[rg_]) begin
1599
     uvm_reg rg = rg_;
1600
     m_regs_info[rg].is_initialized=1;
1601
     if (!m_regs_info[rg].unmapped) begin
1602
        string rg_acc = rg.Xget_fields_accessX(this);
1603
       uvm_reg_addr_t addrs[];
1604
 
1605
       bus_width = get_physical_addresses(m_regs_info[rg].offset,0,rg.get_n_bytes(),addrs);
1606
 
1607
       foreach (addrs[i]) begin
1608
         uvm_reg_addr_t addr = addrs[i];
1609
 
1610
         if (top_map.m_regs_by_offset.exists(addr)) begin
1611
 
1612
            uvm_reg rg2 = top_map.m_regs_by_offset[addr];
1613
            string rg2_acc = rg2.Xget_fields_accessX(this);
1614
 
1615
            // If the register at the same address is RO or WO
1616
            // and this register is WO or RO, this is OK
1617
            if (rg_acc == "RO" && rg2_acc == "WO") begin
1618
               top_map.m_regs_by_offset[addr]    = rg;
1619
               uvm_reg_read_only_cbs::add(rg);
1620
               top_map.m_regs_by_offset_wo[addr] = rg2;
1621
               uvm_reg_write_only_cbs::add(rg2);
1622
            end
1623
            else if (rg_acc == "WO" && rg2_acc == "RO") begin
1624
               top_map.m_regs_by_offset_wo[addr] = rg;
1625
               uvm_reg_write_only_cbs::add(rg);
1626
               uvm_reg_read_only_cbs::add(rg2);
1627
            end
1628
            else begin
1629
               string a;
1630
               a = $sformatf("%0h",addr);
1631
               `uvm_warning("RegModel", {"In map '",get_full_name(),"' register '",
1632
                                         rg.get_full_name(), "' maps to same address as register '",
1633
                                         top_map.m_regs_by_offset[addr].get_full_name(),"': 'h",a})
1634
            end
1635
         end
1636
         else
1637
            top_map.m_regs_by_offset[addr] = rg;
1638
 
1639
         foreach (top_map.m_mems_by_offset[range]) begin
1640
           if (addr >= range.min && addr <= range.max) begin
1641
             string a,b;
1642
             a = $sformatf("%0h",addr);
1643
             b = $sformatf("[%0h:%0h]",range.min,range.max);
1644
             `uvm_warning("RegModel", {"In map '",get_full_name(),"' register '",
1645
                 rg.get_full_name(), "' with address ",a,
1646
                 "maps to same address as memory '",
1647
                 top_map.m_mems_by_offset[range].get_full_name(),"': ",b})
1648
             end
1649
         end
1650
       end
1651
       m_regs_info[rg].addr = addrs;
1652
     end
1653
   end
1654
 
1655
   foreach (m_mems_info[mem_]) begin
1656
     uvm_mem mem = mem_;
1657
     if (!m_mems_info[mem].unmapped) begin
1658
 
1659
       uvm_reg_addr_t addrs[],addrs_max[];
1660
       uvm_reg_addr_t min, max, min2, max2;
1661
       int unsigned stride;
1662
 
1663
       bus_width = get_physical_addresses(m_mems_info[mem].offset,0,mem.get_n_bytes(),addrs);
1664
       min = (addrs[0] < addrs[addrs.size()-1]) ? addrs[0] : addrs[addrs.size()-1];
1665
       min2 = addrs[0];
1666
 
1667
       void'(get_physical_addresses(m_mems_info[mem].offset,(mem.get_size()-1),mem.get_n_bytes(),addrs_max));
1668
       max = (addrs_max[0] > addrs_max[addrs_max.size()-1]) ? addrs_max[0] : addrs_max[addrs_max.size()-1];
1669
       max2 = addrs_max[0];
1670
       // address interval between consecutive mem offsets
1671
       stride = (max2 - min2)/(mem.get_size()-1);
1672
 
1673
       foreach (top_map.m_regs_by_offset[reg_addr]) begin
1674
         if (reg_addr >= min && reg_addr <= max) begin
1675
           string a;
1676
           a = $sformatf("%0h",reg_addr);
1677
           `uvm_warning("RegModel", {"In map '",get_full_name(),"' memory '",
1678
               mem.get_full_name(), "' maps to same address as register '",
1679
               top_map.m_regs_by_offset[reg_addr].get_full_name(),"': 'h",a})
1680
         end
1681
       end
1682
 
1683
       foreach (top_map.m_mems_by_offset[range]) begin
1684
         if (min <= range.max && max >= range.max ||
1685
             min <= range.min && max >= range.min ||
1686
             min >= range.min && max <= range.max) begin
1687
           string a;
1688
           a = $sformatf("[%0h:%0h]",min,max);
1689
           `uvm_warning("RegModel", {"In map '",get_full_name(),"' memory '",
1690
               mem.get_full_name(), "' overlaps with address range of memory '",
1691
               top_map.m_mems_by_offset[range].get_full_name(),"': 'h",a})
1692
           end
1693
       end
1694
 
1695
       begin
1696
         uvm_reg_map_addr_range range = '{ min, max, stride };
1697
         top_map.m_mems_by_offset[ range ] = mem;
1698
         m_mems_info[mem].addr  = addrs;
1699
         m_mems_info[mem].mem_range = range;
1700
       end
1701
     end
1702
   end
1703
 
1704
   // If the block has no registers or memories,
1705
   // bus_width won't be set
1706
   if (bus_width == 0) bus_width = m_n_bytes;
1707
 
1708
   m_system_n_bytes = bus_width;
1709
endfunction
1710
 
1711
 
1712
//-----------
1713
// Bus Access
1714
//-----------
1715
 
1716
function void uvm_reg_map::Xget_bus_infoX(uvm_reg_item rw,
1717
                                          output uvm_reg_map_info map_info,
1718
                                          output int size,
1719
                                          output int lsb,
1720
                                          output int addr_skip);
1721
 
1722
  if (rw.element_kind == UVM_MEM) begin
1723
    uvm_mem mem;
1724
    if(rw.element == null || !$cast(mem,rw.element))
1725
      `uvm_fatal("REG/CAST", {"uvm_reg_item 'element_kind' is UVM_MEM, ",
1726
                 "but 'element' does not point to a memory: ",rw.get_name()})
1727
    map_info = get_mem_map_info(mem);
1728
    size = mem.get_n_bits();
1729
  end
1730
  else if (rw.element_kind == UVM_REG) begin
1731
    uvm_reg rg;
1732
    if(rw.element == null || !$cast(rg,rw.element))
1733
      `uvm_fatal("REG/CAST", {"uvm_reg_item 'element_kind' is UVM_REG, ",
1734
                 "but 'element' does not point to a register: ",rw.get_name()})
1735
    map_info = get_reg_map_info(rg);
1736
    size = rg.get_n_bits();
1737
  end
1738
  else if (rw.element_kind == UVM_FIELD) begin
1739
    uvm_reg_field field;
1740
    if(rw.element == null || !$cast(field,rw.element))
1741
      `uvm_fatal("REG/CAST", {"uvm_reg_item 'element_kind' is UVM_FIELD, ",
1742
                 "but 'element' does not point to a field: ",rw.get_name()})
1743
    map_info = get_reg_map_info(field.get_parent());
1744
    size = field.get_n_bits();
1745
    lsb = field.get_lsb_pos();
1746
    addr_skip = lsb/(get_n_bytes()*8);
1747
  end
1748
endfunction
1749
 
1750
 
1751
 
1752
 
1753
// do_write(uvm_reg_item rw)
1754
 
1755
task uvm_reg_map::do_write(uvm_reg_item rw);
1756
 
1757
  uvm_sequence_base tmp_parent_seq;
1758
  uvm_reg_map system_map = get_root_map();
1759
  uvm_reg_adapter adapter = system_map.get_adapter();
1760
  uvm_sequencer_base sequencer = system_map.get_sequencer();
1761
 
1762
  if (adapter != null && adapter.parent_sequence != null) begin
1763
    uvm_object o;
1764
    uvm_sequence_base seq;
1765
    o = adapter.parent_sequence.clone();
1766
    assert($cast(seq,o));
1767
    seq.set_parent_sequence(rw.parent);
1768
    rw.parent = seq;
1769
    tmp_parent_seq = seq;
1770
  end
1771
 
1772
  if (rw.parent == null) begin
1773
     rw.parent = new("default_parent_seq");
1774
     tmp_parent_seq = rw.parent;
1775
  end
1776
 
1777
  if (adapter == null) begin
1778
    rw.set_sequencer(sequencer);
1779
    rw.parent.start_item(rw,rw.prior);
1780
    rw.parent.finish_item(rw);
1781
    rw.end_event.wait_on();
1782
  end
1783
  else begin
1784
    do_bus_write(rw, sequencer, adapter);
1785
  end
1786
 
1787
  if (tmp_parent_seq != null)
1788
    sequencer.m_sequence_exiting(tmp_parent_seq);
1789
 
1790
endtask
1791
 
1792
 
1793
// do_read(uvm_reg_item rw)
1794
 
1795
task uvm_reg_map::do_read(uvm_reg_item rw);
1796
 
1797
  uvm_sequence_base tmp_parent_seq;
1798
  uvm_reg_map system_map = get_root_map();
1799
  uvm_reg_adapter adapter = system_map.get_adapter();
1800
  uvm_sequencer_base sequencer = system_map.get_sequencer();
1801
 
1802
  if (adapter != null && adapter.parent_sequence != null) begin
1803
    uvm_object o;
1804
    uvm_sequence_base seq;
1805
    o = adapter.parent_sequence.clone();
1806
    assert($cast(seq,o));
1807
    seq.set_parent_sequence(rw.parent);
1808
    rw.parent = seq;
1809
    tmp_parent_seq = seq;
1810
  end
1811
 
1812
  if (rw.parent == null) begin
1813
    rw.parent = new("default_parent_seq");
1814
    tmp_parent_seq = rw.parent;
1815
  end
1816
 
1817
  if (adapter == null) begin
1818
    rw.set_sequencer(sequencer);
1819
    rw.parent.start_item(rw,rw.prior);
1820
    rw.parent.finish_item(rw);
1821
    rw.end_event.wait_on();
1822
  end
1823
  else begin
1824
    do_bus_read(rw, sequencer, adapter);
1825
  end
1826
 
1827
  if (tmp_parent_seq != null)
1828
    sequencer.m_sequence_exiting(tmp_parent_seq);
1829
 
1830
endtask
1831
 
1832
 
1833
// do_bus_write
1834
 
1835
task uvm_reg_map::do_bus_write (uvm_reg_item rw,
1836
                                uvm_sequencer_base sequencer,
1837
                                uvm_reg_adapter adapter);
1838
 
1839
  uvm_reg_addr_t     addrs[$];
1840
  uvm_reg_map        system_map = get_root_map();
1841
  int unsigned       bus_width  = get_n_bytes();
1842
  uvm_reg_byte_en_t  byte_en    = -1;
1843
  uvm_reg_map_info   map_info;
1844
  int                n_bits;
1845
  int                lsb;
1846
  int                skip;
1847
  int unsigned       curr_byte;
1848
  int                n_access_extra, n_access;
1849
  int               n_bits_init;
1850
  uvm_reg_bus_op    accesses[$];
1851
 
1852
  Xget_bus_infoX(rw, map_info, n_bits_init, lsb, skip);
1853
  addrs=map_info.addr;
1854
 
1855
  // if a memory, adjust addresses based on offset
1856
  if (rw.element_kind == UVM_MEM)
1857
    foreach (addrs[i])
1858
      addrs[i] = addrs[i] + map_info.mem_range.stride * rw.offset;
1859
 
1860
  foreach (rw.value[val_idx]) begin: foreach_value
1861
 
1862
     uvm_reg_data_t value = rw.value[val_idx];
1863
 
1864
    /* calculate byte_enables */
1865
    if (rw.element_kind == UVM_FIELD) begin
1866
      int temp_be;
1867
      int idx;
1868
      n_access_extra = lsb%(bus_width*8);
1869
      n_access = n_access_extra + n_bits_init;
1870
      temp_be = n_access_extra;
1871
      value = value << n_access_extra;
1872
      while(temp_be >= 8) begin
1873
         byte_en[idx++] = 0;
1874
         temp_be -= 8;
1875
      end
1876
      temp_be += n_bits_init;
1877
      while(temp_be > 0) begin
1878
         byte_en[idx++] = 1;
1879
         temp_be -= 8;
1880
      end
1881
      byte_en &= (1<
1882
      for (int i=0; i
1883
        void'(addrs.pop_front());
1884
      while (addrs.size() > (n_bits_init/(bus_width*8) + 1))
1885
        void'(addrs.pop_back());
1886
    end
1887
    curr_byte=0;
1888
    n_bits= n_bits_init;
1889
 
1890
    accesses.delete();
1891
    foreach(addrs[i]) begin: foreach_addr
1892
      uvm_reg_bus_op rw_access;
1893
      uvm_reg_data_t data;
1894
 
1895
      data = (value >> (curr_byte*8)) & ((1'b1 << (bus_width * 8))-1);
1896
 
1897
      `uvm_info(get_type_name(),
1898
         $sformatf("Writing 'h%0h at 'h%0h via map \"%s\"...",
1899
              data, addrs[i], rw.map.get_full_name()), UVM_FULL);
1900
 
1901
      if (rw.element_kind == UVM_FIELD) begin
1902
        for (int z=0;z
1903
          rw_access.byte_en[z] = byte_en[curr_byte+z];
1904
      end
1905
 
1906
      rw_access.kind    = rw.kind;
1907
      rw_access.addr    = addrs[i];
1908
      rw_access.data    = data;
1909
      rw_access.n_bits  = (n_bits > bus_width*8) ? bus_width*8 : n_bits;
1910
      rw_access.byte_en = byte_en;
1911
 
1912
      accesses.push_back(rw_access);
1913
 
1914
      curr_byte += bus_width;
1915
      n_bits -= bus_width * 8;
1916
 
1917
    end: foreach_addr
1918
 
1919
    // if set utilizy the order policy
1920
    if(policy!=null)
1921
        policy.order(accesses);
1922
 
1923
    // perform accesses
1924
    foreach(accesses[i]) begin
1925
      uvm_reg_bus_op rw_access=accesses[i];
1926
      uvm_sequence_item bus_req;
1927
 
1928
      adapter.m_set_item(rw);
1929
      bus_req = adapter.reg2bus(rw_access);
1930
      adapter.m_set_item(null);
1931
 
1932
      if (bus_req == null)
1933
        `uvm_fatal("RegMem",{"adapter [",adapter.get_name(),"] didnt return a bus transaction"});
1934
 
1935
      bus_req.set_sequencer(sequencer);
1936
      rw.parent.start_item(bus_req,rw.prior);
1937
 
1938
      if (rw.parent != null && i == 0)
1939
        rw.parent.mid_do(rw);
1940
 
1941
      rw.parent.finish_item(bus_req);
1942
      bus_req.end_event.wait_on();
1943
 
1944
      if (adapter.provides_responses) begin
1945
        uvm_sequence_item bus_rsp;
1946
        uvm_access_e op;
1947
        // TODO: need to test for right trans type, if not put back in q
1948
        rw.parent.get_base_response(bus_rsp);
1949
        adapter.bus2reg(bus_rsp,rw_access);
1950
      end
1951
      else begin
1952
        adapter.bus2reg(bus_req,rw_access);
1953
      end
1954
 
1955
      if (rw.parent != null && i == addrs.size()-1)
1956
        rw.parent.post_do(rw);
1957
 
1958
      rw.status = rw_access.status;
1959
 
1960
      `uvm_info(get_type_name(),
1961
         $sformatf("Wrote 'h%0h at 'h%0h via map \"%s\": %s...",
1962
            rw_access.data, addrs[i], rw.map.get_full_name(), rw.status.name()), UVM_FULL)
1963
 
1964
      if (rw.status == UVM_NOT_OK)
1965
         break;
1966
 
1967
    end
1968
 
1969
    foreach (addrs[i])
1970
      addrs[i] = addrs[i] + map_info.mem_range.stride;
1971
 
1972
  end: foreach_value
1973
 
1974
endtask: do_bus_write
1975
 
1976
 
1977
// do_bus_read
1978
 
1979
task uvm_reg_map::do_bus_read (uvm_reg_item rw,
1980
                               uvm_sequencer_base sequencer,
1981
                               uvm_reg_adapter adapter);
1982
 
1983
  uvm_reg_addr_t addrs[$];
1984
  uvm_reg_map        system_map = get_root_map();
1985
  int unsigned       bus_width  = get_n_bytes();
1986
  uvm_reg_byte_en_t  byte_en    = -1;
1987
  uvm_reg_map_info   map_info;
1988
  int                size, n_bits;
1989
  int                skip;
1990
  int                lsb;
1991
  int unsigned       curr_byte;
1992
  int n_access_extra, n_access;
1993
  uvm_reg_bus_op accesses[$];
1994
 
1995
  Xget_bus_infoX(rw, map_info, n_bits, lsb, skip);
1996
  addrs=map_info.addr;
1997
  size = n_bits;
1998
 
1999
  // if a memory, adjust addresses based on offset
2000
  if (rw.element_kind == UVM_MEM)
2001
    foreach (addrs[i])
2002
      addrs[i] = addrs[i] + map_info.mem_range.stride * rw.offset;
2003
 
2004
  foreach (rw.value[val_idx]) begin: foreach_value
2005
 
2006
    /* calculate byte_enables */
2007
    if (rw.element_kind == UVM_FIELD) begin
2008
      int temp_be;
2009
      int idx;
2010
      n_access_extra = lsb%(bus_width*8);
2011
      n_access = n_access_extra + n_bits;
2012
      temp_be = n_access_extra;
2013
      while(temp_be >= 8) begin
2014
         byte_en[idx++] = 0;
2015
         temp_be -= 8;
2016
      end
2017
      temp_be += n_bits;
2018
      while(temp_be > 0) begin
2019
         byte_en[idx++] = 1;
2020
         temp_be -= 8;
2021
      end
2022
      byte_en &= (1<
2023
      for (int i=0; i
2024
        void'(addrs.pop_front());
2025
      while (addrs.size() > (n_bits/(bus_width*8) + 1))
2026
        void'(addrs.pop_back());
2027
    end
2028
    curr_byte=0;
2029
    rw.value[val_idx] = 0;
2030
 
2031
    accesses.delete();
2032
    foreach (addrs[i]) begin
2033
      uvm_reg_bus_op rw_access;
2034
 
2035
      `uvm_info(get_type_name(),
2036
         $sformatf("Reading address 'h%0h via map \"%s\"...",
2037
                   addrs[i], get_full_name()), UVM_FULL);
2038
 
2039
      if (rw.element_kind == UVM_FIELD)
2040
        for (int z=0;z
2041
          rw_access.byte_en[z] = byte_en[curr_byte+z];
2042
 
2043
      rw_access.kind = rw.kind;
2044
      rw_access.addr = addrs[i];
2045
      rw_access.data = curr_byte;
2046
      rw_access.byte_en = byte_en;
2047
      rw_access.n_bits = (n_bits > bus_width*8) ? bus_width*8 : n_bits;
2048
 
2049
       accesses.push_back(rw_access);
2050
 
2051
      curr_byte += bus_width;
2052
      n_bits -= bus_width * 8;
2053
    end
2054
 
2055
    // if set utilize the order policy
2056
    if(policy!=null)
2057
        policy.order(accesses);
2058
 
2059
    // perform accesses
2060
    foreach(accesses[i]) begin
2061
      uvm_reg_bus_op rw_access=accesses[i];
2062
      uvm_sequence_item bus_req;
2063
      uvm_reg_data_logic_t data;
2064
      int unsigned curr_byte_;
2065
 
2066
      curr_byte_=rw_access.data;
2067
      rw_access.data='0;
2068
      adapter.m_set_item(rw);
2069
      bus_req = adapter.reg2bus(rw_access);
2070
      adapter.m_set_item(null);
2071
      if (bus_req == null)
2072
        `uvm_fatal("RegMem",{"adapter [",adapter.get_name(),"] didnt return a bus transaction"});
2073
 
2074
      bus_req.set_sequencer(sequencer);
2075
      rw.parent.start_item(bus_req,rw.prior);
2076
 
2077
      if (rw.parent != null && i == 0) begin
2078
        rw.parent.mid_do(rw);
2079
      end
2080
 
2081
      rw.parent.finish_item(bus_req);
2082
      bus_req.end_event.wait_on();
2083
 
2084
      if (adapter.provides_responses) begin
2085
        uvm_sequence_item bus_rsp;
2086
        uvm_access_e op;
2087
        // TODO: need to test for right trans type, if not put back in q
2088
        rw.parent.get_base_response(bus_rsp);
2089
        adapter.bus2reg(bus_rsp,rw_access);
2090
      end
2091
      else begin
2092
        adapter.bus2reg(bus_req,rw_access);
2093
      end
2094
 
2095
      data = rw_access.data & ((1<
2096
 
2097
      rw.status = rw_access.status;
2098
 
2099
      if (rw.status == UVM_IS_OK && (^data) === 1'bx)
2100
        rw.status = UVM_HAS_X;
2101
 
2102
      `uvm_info(get_type_name(),
2103
         $sformatf("Read 'h%0h at 'h%0h via map \"%s\": %s...", data,
2104
                   addrs[i], get_full_name(), rw.status.name()), UVM_FULL);
2105
 
2106
      if (rw.status == UVM_NOT_OK)
2107
         break;
2108
 
2109
      rw.value[val_idx] |= data << curr_byte_*8;
2110
 
2111
      if (rw.parent != null && i == addrs.size()-1)
2112
        rw.parent.post_do(rw);
2113
    end
2114
 
2115
 
2116
    foreach (addrs[i])
2117
      addrs[i] = addrs[i] + map_info.mem_range.stride;
2118
 
2119
    if (rw.element_kind == UVM_FIELD)
2120
       rw.value[val_idx] = (rw.value[val_idx] >> (n_access_extra)) & ((1<
2121
  end
2122
 
2123
endtask: do_bus_read
2124
 
2125
 
2126
 
2127
//-------------
2128
// Standard Ops
2129
//-------------
2130
 
2131
// do_print
2132
 
2133
function void uvm_reg_map::do_print (uvm_printer printer);
2134
   uvm_reg  regs[$];
2135
   uvm_vreg vregs[$];
2136
   uvm_mem  mems[$];
2137
   uvm_endianness_e endian;
2138
   uvm_reg_map maps[$];
2139
   string prefix;
2140
   uvm_sequencer_base sqr=get_sequencer();
2141
 
2142
   super.do_print(printer);
2143
//  printer.print_generic(get_name(), get_type_name(), -1, convert2string());
2144
 
2145
   endian = get_endian(UVM_NO_HIER);
2146
//   $sformat(convert2string, "%s -- %0d bytes (%s)", convert2string,
2147
//            get_n_bytes(UVM_NO_HIER), endian.name());
2148
 
2149
   printer.print_generic("endian","",-2,endian.name());
2150
   if(sqr!=null)
2151
    printer.print_generic("effective sequencer",sqr.get_type_name(),-2,sqr.get_full_name());
2152
 
2153
   get_registers(regs,UVM_NO_HIER);
2154
   foreach (regs[j])
2155
        printer.print_generic(regs[j].get_name(), regs[j].get_type_name(),-2,$sformatf("@%0d +'h%0x",regs[j].get_inst_id(),regs[j].get_address(this)));
2156
 
2157
 
2158
   get_memories(mems);
2159
   foreach (mems[j])
2160
        printer.print_generic(mems[j].get_name(), mems[j].get_type_name(),-2,$sformatf("@%0d +'h%0x",mems[j].get_inst_id(),mems[j].get_address(0,this)));
2161
 
2162
   get_virtual_registers(vregs);
2163
   foreach (vregs[j])
2164
        printer.print_generic(vregs[j].get_name(), vregs[j].get_type_name(),-2,$sformatf("@%0d +'h%0x",vregs[j].get_inst_id(),vregs[j].get_address(0,this)));
2165
 
2166
   get_submaps(maps);
2167
   foreach (maps[j])
2168
        printer.print_object(maps[j].get_name(),maps[j]);
2169
endfunction
2170
 
2171
// convert2string
2172
 
2173
function string uvm_reg_map::convert2string();
2174
   uvm_reg  regs[$];
2175
   uvm_vreg vregs[$];
2176
   uvm_mem  mems[$];
2177
   uvm_endianness_e endian;
2178
   string prefix;
2179
 
2180
   $sformat(convert2string, "%sMap %s", prefix, get_full_name());
2181
   endian = get_endian(UVM_NO_HIER);
2182
   $sformat(convert2string, "%s -- %0d bytes (%s)", convert2string,
2183
            get_n_bytes(UVM_NO_HIER), endian.name());
2184
   get_registers(regs);
2185
   foreach (regs[j]) begin
2186
      $sformat(convert2string, "%s\n%s", convert2string,
2187
               regs[j].convert2string());//{prefix, "   "}, this));
2188
   end
2189
   get_memories(mems);
2190
   foreach (mems[j]) begin
2191
      $sformat(convert2string, "%s\n%s", convert2string,
2192
               mems[j].convert2string());//{prefix, "   "}, this));
2193
   end
2194
   get_virtual_registers(vregs);
2195
   foreach (vregs[j]) begin
2196
      $sformat(convert2string, "%s\n%s", convert2string,
2197
               vregs[j].convert2string());//{prefix, "   "}, this));
2198
   end
2199
endfunction
2200
 
2201
 
2202
// clone
2203
 
2204
function uvm_object uvm_reg_map::clone();
2205
  //uvm_rap_map me;
2206
  //me = new this;
2207
  //return me;
2208
  return null;
2209
endfunction
2210
 
2211
 
2212
// do_copy
2213
 
2214
function void uvm_reg_map::do_copy (uvm_object rhs);
2215
  //uvm_reg_map rhs_;
2216
  //assert($cast(rhs_,rhs));
2217
 
2218
  //rhs_.regs = regs;
2219
  //rhs_.mems = mems;
2220
  //rhs_.vregs = vregs;
2221
  //rhs_.blks = blks;
2222
  //... and so on
2223
endfunction
2224
 

powered by: WebSVN 2.1.0

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