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

Subversion Repositories uart2bus_testbench

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 HanySalah
//
2
// -------------------------------------------------------------
3
//    Copyright 2010 Synopsys, Inc.
4
//    Copyright 2010 Cadence Design Systems, Inc.
5
//    Copyright 2011 Mentor Graphics Corporation
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
typedef class uvm_reg_indirect_ftdr_seq;
25
 
26
//-----------------------------------------------------------------
27
// CLASS: uvm_reg_indirect_data
28
// Indirect data access abstraction class
29
//
30
// Models the behavior of a register used to indirectly access
31
// a register array, indexed by a second ~address~ register.
32
//
33
// This class should not be instantiated directly.
34
// A type-specific class extension should be used to
35
// provide a factory-enabled constructor and specify the
36
// ~n_bits~ and coverage models.
37
//-----------------------------------------------------------------
38
 
39
class uvm_reg_indirect_data extends uvm_reg;
40
 
41
   protected uvm_reg m_idx;
42
   protected uvm_reg m_tbl[];
43
 
44
   // Function: new
45
   // Create an instance of this class
46
   //
47
   // Should not be called directly,
48
   // other than via super.new().
49
   // The value of ~n_bits~ must match the number of bits
50
   // in the indirect register array.
51
   function new(string name = "uvm_reg_indirect",
52
                int unsigned n_bits,
53
                int has_cover);
54
      super.new(name,n_bits,has_cover);
55
   endfunction: new
56
 
57
   virtual function void build();
58
   endfunction: build
59
 
60
   // Function: configure
61
   // Configure the indirect data register.
62
   //
63
   // The ~idx~ register specifies the index,
64
   // in the ~reg_a~ register array, of the register to access.
65
   // The ~idx~ must be written to first.
66
   // A read or write operation to this register will subsequently
67
   // read or write the indexed register in the register array.
68
   //
69
   // The number of bits in each register in the register array must be
70
   // equal to ~n_bits~ of this register.
71
   //
72
   // See  for the remaining arguments.
73
   function void configure (uvm_reg idx,
74
                            uvm_reg reg_a[],
75
                            uvm_reg_block blk_parent,
76
                            uvm_reg_file regfile_parent = null);
77
      super.configure(blk_parent, regfile_parent, "");
78
      m_idx = idx;
79
      m_tbl = reg_a;
80
 
81
      // Not testable using pre-defined sequences
82
      uvm_resource_db#(bit)::set({"REG::", get_full_name()},
83
                                 "NO_REG_TESTS", 1);
84
 
85
      // Add a frontdoor to each indirectly-accessed register
86
      // for every address map this register is in.
87
      foreach (m_maps[map]) begin
88
         add_frontdoors(map);
89
      end
90
   endfunction
91
 
92
   /*local*/ virtual function void add_map(uvm_reg_map map);
93
      super.add_map(map);
94
      add_frontdoors(map);
95
   endfunction
96
 
97
 
98
   local function void add_frontdoors(uvm_reg_map map);
99
      foreach (m_tbl[i]) begin
100
         uvm_reg_indirect_ftdr_seq fd;
101
         if (m_tbl[i] == null) begin
102
            `uvm_error(get_full_name(),
103
                       $sformatf("Indirect register #%0d is NULL", i));
104
            continue;
105
         end
106
         fd = new(m_idx, i, this);
107
         if (m_tbl[i].is_in_map(map))
108
            m_tbl[i].set_frontdoor(fd, map);
109
         else
110
            map.add_reg(m_tbl[i], -1, "RW", 1, fd);
111
      end
112
   endfunction
113
 
114
   virtual function void do_predict (uvm_reg_item      rw,
115
                                     uvm_predict_e     kind = UVM_PREDICT_DIRECT,
116
                                     uvm_reg_byte_en_t be = -1);
117
      if (m_idx.get() >= m_tbl.size()) begin
118
         `uvm_error(get_full_name(), $sformatf("Address register %s has a value (%0d) greater than the maximum indirect register array size (%0d)", m_idx.get_full_name(), m_idx.get(), m_tbl.size()));
119
         rw.status = UVM_NOT_OK;
120
         return;
121
      end
122
 
123
      //NOTE limit to 2**32 registers
124
      begin
125
         int unsigned idx = m_idx.get();
126
         m_tbl[idx].do_predict(rw, kind, be);
127
      end
128
   endfunction
129
 
130
 
131
   virtual function uvm_reg_map get_local_map(uvm_reg_map map, string caller="");
132
      return  m_idx.get_local_map(map,caller);
133
   endfunction
134
 
135
   //
136
   // Just for good measure, to catch and short-circuit non-sensical uses
137
   //
138
   virtual function void add_field  (uvm_reg_field field);
139
      `uvm_error(get_full_name(), "Cannot add field to an indirect data access register");
140
   endfunction
141
 
142
   virtual function void set (uvm_reg_data_t  value,
143
                              string          fname = "",
144
                              int             lineno = 0);
145
      `uvm_error(get_full_name(), "Cannot set() an indirect data access register");
146
   endfunction
147
 
148
   virtual function uvm_reg_data_t  get(string  fname = "",
149
                                        int     lineno = 0);
150
      `uvm_error(get_full_name(), "Cannot get() an indirect data access register");
151
      return 0;
152
   endfunction
153
 
154
   virtual function uvm_reg get_indirect_reg(string  fname = "",
155
                                        int     lineno = 0);
156
      int unsigned idx = m_idx.get_mirrored_value();
157
      return(m_tbl[idx]);
158
   endfunction
159
 
160
   virtual function bit needs_update();
161
      return 0;
162
   endfunction
163
 
164
   virtual task write(output uvm_status_e      status,
165
                      input  uvm_reg_data_t    value,
166
                      input  uvm_path_e        path = UVM_DEFAULT_PATH,
167
                      input  uvm_reg_map       map = null,
168
                      input  uvm_sequence_base parent = null,
169
                      input  int               prior = -1,
170
                      input  uvm_object        extension = null,
171
                      input  string            fname = "",
172
                      input  int               lineno = 0);
173
 
174
      if (path == UVM_DEFAULT_PATH) begin
175
         uvm_reg_block blk = get_parent();
176
         path = blk.get_default_path();
177
      end
178
 
179
      if (path == UVM_BACKDOOR) begin
180
         `uvm_warning(get_full_name(), "Cannot backdoor-write an indirect data access register. Switching to frontdoor.");
181
         path = UVM_FRONTDOOR;
182
      end
183
 
184
      // Can't simply call super.write() because it'll call set()
185
      begin
186
         uvm_reg_item rw;
187
 
188
         XatomicX(1);
189
 
190
         rw = uvm_reg_item::type_id::create("write_item",,get_full_name());
191
         rw.element      = this;
192
         rw.element_kind = UVM_REG;
193
         rw.kind         = UVM_WRITE;
194
         rw.value[0]     = value;
195
         rw.path         = path;
196
         rw.map          = map;
197
         rw.parent       = parent;
198
         rw.prior        = prior;
199
         rw.extension    = extension;
200
         rw.fname        = fname;
201
         rw.lineno       = lineno;
202
 
203
         do_write(rw);
204
 
205
         status = rw.status;
206
 
207
         XatomicX(0);
208
      end
209
   endtask
210
 
211
   virtual task read(output uvm_status_e      status,
212
                     output uvm_reg_data_t    value,
213
                     input  uvm_path_e        path = UVM_DEFAULT_PATH,
214
                     input  uvm_reg_map       map = null,
215
                     input  uvm_sequence_base parent = null,
216
                     input  int               prior = -1,
217
                     input  uvm_object        extension = null,
218
                     input  string            fname = "",
219
                     input  int               lineno = 0);
220
 
221
      if (path == UVM_DEFAULT_PATH) begin
222
         uvm_reg_block blk = get_parent();
223
         path = blk.get_default_path();
224
      end
225
 
226
      if (path == UVM_BACKDOOR) begin
227
         `uvm_warning(get_full_name(), "Cannot backdoor-read an indirect data access register. Switching to frontdoor.");
228
         path = UVM_FRONTDOOR;
229
      end
230
 
231
      super.read(status, value, path, map, parent, prior, extension, fname, lineno);
232
   endtask
233
 
234
   virtual task poke(output uvm_status_e      status,
235
                     input  uvm_reg_data_t    value,
236
                     input  string            kind = "",
237
                     input  uvm_sequence_base parent = null,
238
                     input  uvm_object        extension = null,
239
                     input  string            fname = "",
240
                     input  int               lineno = 0);
241
      `uvm_error(get_full_name(), "Cannot poke() an indirect data access register");
242
      status = UVM_NOT_OK;
243
   endtask
244
 
245
   virtual task peek(output uvm_status_e      status,
246
                     output uvm_reg_data_t    value,
247
                     input  string            kind = "",
248
                     input  uvm_sequence_base parent = null,
249
                     input  uvm_object        extension = null,
250
                     input  string            fname = "",
251
                     input  int               lineno = 0);
252
      `uvm_error(get_full_name(), "Cannot peek() an indirect data access register");
253
      status = UVM_NOT_OK;
254
   endtask
255
 
256
   virtual task update(output uvm_status_e      status,
257
                       input  uvm_path_e        path = UVM_DEFAULT_PATH,
258
                       input  uvm_reg_map       map = null,
259
                       input  uvm_sequence_base parent = null,
260
                       input  int               prior = -1,
261
                       input  uvm_object        extension = null,
262
                       input  string            fname = "",
263
                       input  int               lineno = 0);
264
      status = UVM_IS_OK;
265
   endtask
266
 
267
   virtual task mirror(output uvm_status_e      status,
268
                       input uvm_check_e        check  = UVM_NO_CHECK,
269
                       input uvm_path_e         path = UVM_DEFAULT_PATH,
270
                       input uvm_reg_map        map = null,
271
                       input uvm_sequence_base  parent = null,
272
                       input int                prior = -1,
273
                       input  uvm_object        extension = null,
274
                       input string             fname = "",
275
                       input int                lineno = 0);
276
      status = UVM_IS_OK;
277
   endtask
278
 
279
endclass : uvm_reg_indirect_data
280
 
281
 
282
class uvm_reg_indirect_ftdr_seq extends uvm_reg_frontdoor;
283
   local uvm_reg m_addr_reg;
284
   local uvm_reg m_data_reg;
285
   local int     m_idx;
286
 
287
   function new(uvm_reg addr_reg,
288
                int idx,
289
                uvm_reg data_reg);
290
      super.new("uvm_reg_indirect_ftdr_seq");
291
      m_addr_reg = addr_reg;
292
      m_idx      = idx;
293
      m_data_reg = data_reg;
294
   endfunction: new
295
 
296
   virtual task body();
297
 
298
      uvm_reg_item rw;
299
 
300
      $cast(rw,rw_info.clone());
301
      rw.element = m_addr_reg;
302
      rw.kind    = UVM_WRITE;
303
      rw.value[0]= m_idx;
304
 
305
      m_addr_reg.XatomicX(1);
306
      m_data_reg.XatomicX(1);
307
 
308
      m_addr_reg.do_write(rw);
309
 
310
      if (rw.status == UVM_NOT_OK)
311
        return;
312
 
313
      $cast(rw,rw_info.clone());
314
      rw.element = m_data_reg;
315
 
316
      if (rw_info.kind == UVM_WRITE)
317
        m_data_reg.do_write(rw);
318
      else begin
319
        m_data_reg.do_read(rw);
320
        rw_info.value[0] = rw.value[0];
321
      end
322
 
323
      m_addr_reg.XatomicX(0);
324
      m_data_reg.XatomicX(0);
325
 
326
      rw_info.status = rw.status;
327
   endtask
328
 
329
endclass

powered by: WebSVN 2.1.0

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