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

Subversion Repositories uart2bus_testbench

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 HanySalah
//
2
// -------------------------------------------------------------
3
//    Copyright 2004-2009 Synopsys, Inc.
4
//    Copyright 2010-2011 Mentor Graphics Corporation
5
//    Copyright 2010-2011 Cadence Design Systems, Inc.
6
//    All Rights Reserved Worldwide
7
//
8
//    Licensed under the Apache License, Version 2.0 (the
9
//    "License"); you may not use this file except in
10
//    compliance with the License.  You may obtain a copy of
11
//    the License at
12
//
13
//        http://www.apache.org/licenses/LICENSE-2.0
14
//
15
//    Unless required by applicable law or agreed to in
16
//    writing, software distributed under the License is
17
//    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
18
//    CONDITIONS OF ANY KIND, either express or implied.  See
19
//    the License for the specific language governing
20
//    permissions and limitations under the License.
21
// -------------------------------------------------------------
22
//
23
 
24
 
25
//------------------------------------------------------------------------------
26
// TITLE: Explicit Register Predictor
27
//------------------------------------------------------------------------------
28
//
29
// The  class defines a predictor component,
30
// which is used to update the register model's mirror values
31
// based on transactions explicitly observed on a physical bus.
32
//------------------------------------------------------------------------------
33
 
34
class uvm_predict_s;
35
   bit addr[uvm_reg_addr_t];
36
   uvm_reg_item reg_item;
37
endclass
38
 
39
//------------------------------------------------------------------------------
40
//
41
// CLASS: uvm_reg_predictor
42
//
43
// Updates the register model mirror based on observed bus transactions
44
//
45
// This class converts observed bus transactions of type ~BUSTYPE~ to generic
46
// registers transactions, determines the register being accessed based on the
47
// bus address, then updates the register's mirror value with the observed bus
48
// data, subject to the register's access mode. See  for details.
49
//
50
// Memories can be large, so their accesses are not predicted.
51
//
52
//------------------------------------------------------------------------------
53
 
54
class uvm_reg_predictor #(type BUSTYPE=int) extends uvm_component;
55
 
56
  `uvm_component_param_utils(uvm_reg_predictor#(BUSTYPE))
57
 
58
  // Variable: bus_in
59
  //
60
  // Observed bus transactions of type ~BUSTYPE~ are received from this
61
  // port and processed.
62
  //
63
  // For each incoming transaction, the predictor will attempt to get the
64
  // register or memory handle corresponding to the observed bus address.
65
  //
66
  // If there is a match, the predictor calls the register or memory's
67
  // predict method, passing in the observed bus data. The register or
68
  // memory mirror will be updated with this data, subject to its configured
69
  // access behavior--RW, RO, WO, etc. The predictor will also convert the
70
  // bus transaction to a generic  and send it out the
71
  // ~reg_ap~ analysis port.
72
  //
73
  // If the register is wider than the bus, the
74
  // predictor will collect the multiple bus transactions needed to
75
  // determine the value being read or written.
76
  //
77
  uvm_analysis_imp #(BUSTYPE, uvm_reg_predictor #(BUSTYPE)) bus_in;
78
 
79
 
80
  // Variable: reg_ap
81
  //
82
  // Analysis output port that publishes  transactions
83
  // converted from bus transactions received on ~bus_in~.
84
  uvm_analysis_port #(uvm_reg_item) reg_ap;
85
 
86
 
87
  // Variable: map
88
  //
89
  // The map used to convert a bus address to the corresponding register
90
  // or memory handle. Must be configured before the run phase.
91
  //
92
  uvm_reg_map map;
93
 
94
 
95
  // Variable: adapter
96
  //
97
  // The adapter used to convey the parameters of a bus operation in
98
  // terms of a canonical  datum.
99
  // The  must be configured before the run phase.
100
  //
101
  uvm_reg_adapter adapter;
102
 
103
 
104
  // Function: new
105
  //
106
  // Create a new instance of this type, giving it the optional ~name~
107
  // and ~parent~.
108
  //
109
  function new (string name, uvm_component parent);
110
    super.new(name, parent);
111
    bus_in = new("bus_in", this);
112
    reg_ap = new("reg_ap", this);
113
  endfunction
114
 
115
  // This method is documented in uvm_object
116
  static string type_name = "";
117
  virtual function string get_type_name();
118
    if (type_name == "") begin
119
      BUSTYPE t;
120
      t = BUSTYPE::type_id::create("t");
121
      type_name = {"uvm_reg_predictor #(", t.get_type_name(), ")"};
122
    end
123
    return type_name;
124
  endfunction
125
 
126
  // Function: pre_predict
127
  //
128
  // Override this method to change the value or re-direct the
129
  // target register
130
  //
131
  virtual function void pre_predict(uvm_reg_item rw);
132
  endfunction
133
 
134
  local uvm_predict_s m_pending[uvm_reg];
135
 
136
 
137
  // Function- write
138
  //
139
  // not a user-level method. Do not call directly. See documentation
140
  // for the ~bus_in~ member.
141
  //
142
  virtual function void write(BUSTYPE tr);
143
     uvm_reg rg;
144
     uvm_reg_bus_op rw;
145
    if (adapter == null)
146
     `uvm_fatal("REG/WRITE/NULL","write: adapter handle is null")
147
 
148
     // In case they forget to set byte_en
149
     rw.byte_en = -1;
150
     adapter.bus2reg(tr,rw);
151
     rg = map.get_reg_by_offset(rw.addr, (rw.kind == UVM_READ));
152
 
153
     // ToDo: Add memory look-up and call 
154
 
155
     if (rg != null) begin
156
       bit found;
157
       uvm_reg_item reg_item;
158
       uvm_reg_map local_map;
159
       uvm_reg_map_info map_info;
160
       uvm_predict_s predict_info;
161
       uvm_reg_indirect_data ireg;
162
       uvm_reg ir;
163
 
164
       if (!m_pending.exists(rg)) begin
165
         uvm_reg_item item = new;
166
         predict_info =new;
167
         item.element_kind = UVM_REG;
168
         item.element      = rg;
169
         item.path         = UVM_PREDICT;
170
         item.map          = map;
171
         item.kind         = rw.kind;
172
         predict_info.reg_item = item;
173
         m_pending[rg] = predict_info;
174
       end
175
       predict_info = m_pending[rg];
176
       reg_item = predict_info.reg_item;
177
 
178
       if (predict_info.addr.exists(rw.addr)) begin
179
          `uvm_error("REG_PREDICT_COLLISION",{"Collision detected for register '",
180
                     rg.get_full_name(),"'"})
181
          // TODO: what to do with subsequent collisions?
182
          m_pending.delete(rg);
183
       end
184
 
185
       local_map = rg.get_local_map(map,"predictor::write()");
186
       map_info = local_map.get_reg_map_info(rg);
187
       ir=($cast(ireg, rg))?ireg.get_indirect_reg():rg;
188
 
189
       foreach (map_info.addr[i]) begin
190
         if (rw.addr == map_info.addr[i]) begin
191
            found = 1;
192
           reg_item.value[0] |= rw.data << (i * map.get_n_bytes()*8);
193
           predict_info.addr[rw.addr] = 1;
194
           if (predict_info.addr.num() == map_info.addr.size()) begin
195
              // We've captured the entire abstract register transaction.
196
              uvm_predict_e predict_kind =
197
                  (reg_item.kind == UVM_WRITE) ? UVM_PREDICT_WRITE : UVM_PREDICT_READ;
198
 
199
              if (reg_item.kind == UVM_READ &&
200
                  local_map.get_check_on_read() &&
201
                  reg_item.status != UVM_NOT_OK) begin
202
                 void'(rg.do_check(ir.get_mirrored_value(), reg_item.value[0], local_map));
203
              end
204
 
205
              pre_predict(reg_item);
206
 
207
              ir.XsampleX(reg_item.value[0], rw.byte_en,
208
                          reg_item.kind == UVM_READ, local_map);
209
              begin
210
                 uvm_reg_block blk = rg.get_parent();
211
                 blk.XsampleX(map_info.offset,
212
                              reg_item.kind == UVM_READ,
213
                              local_map);
214
              end
215
 
216
              rg.do_predict(reg_item, predict_kind, rw.byte_en);
217
              if(reg_item.kind == UVM_WRITE)
218
                `uvm_info("REG_PREDICT", {"Observed WRITE transaction to register ",
219
                         ir.get_full_name(), ": value='h",
220
                         $sformatf("%0h",reg_item.value[0]), " : updated value = 'h",
221
                         $sformatf("%0h",ir.get())},UVM_HIGH)
222
              else
223
                `uvm_info("REG_PREDICT", {"Observed READ transaction to register ",
224
                         ir.get_full_name(), ": value='h",
225
                         $sformatf("%0h",reg_item.value[0])},UVM_HIGH)
226
              reg_ap.write(reg_item);
227
              m_pending.delete(rg);
228
           end
229
           break;
230
         end
231
       end
232
       if (!found)
233
         `uvm_error("REG_PREDICT_INTERNAL",{"Unexpected failed address lookup for register '",
234
                  rg.get_full_name(),"'"})
235
     end
236
     else begin
237
       `uvm_info("REG_PREDICT_NOT_FOR_ME",
238
          {"Observed transaction does not target a register: ",
239
            $sformatf("%p",tr)},UVM_FULL)
240
     end
241
  endfunction
242
 
243
 
244
  // Function: check_phase
245
  //
246
  // Checks that no pending register transactions are still queued.
247
 
248
  virtual function void check_phase(uvm_phase phase);
249
         string q[$];
250
     super.check_phase(phase);
251
 
252
     foreach (m_pending[l]) begin
253
             uvm_reg rg=l;
254
         q.push_back($sformatf("\n%s",rg.get_full_name()));
255
     end
256
 
257
    if (m_pending.num() > 0) begin
258
      `uvm_error("PENDING REG ITEMS",
259
        $sformatf("There are %0d incomplete register transactions still pending completion:%s",m_pending.num(),`UVM_STRING_QUEUE_STREAMING_PACK(q)))
260
 
261
    end
262
  endfunction
263
 
264
endclass

powered by: WebSVN 2.1.0

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