SyoSil ApS UVM Scoreboard  1.0.3.0
cl_syoscb_queue_iterator_hash.svh
1 /// Queue iterator class defining the iterator API used for iterating hash queues.
2 /// \param HASH_DIGEST_WIDTH Number of bits used in the hash digest for the chosen hash algorithm
3 class cl_syoscb_queue_iterator_hash#(int unsigned HASH_DIGEST_WIDTH = 1) extends cl_syoscb_queue_iterator_base;
4 
5  /// Holds the value of the most recently accessed hash digest
6  local cl_syoscb_hash_base#(HASH_DIGEST_WIDTH)::tp_hash_digest digest;
7 
8  /// Field indicating which cl_syoscb_hash_item index we're currently looking at
9  protected int unsigned hash_index = 0;
10 
11  //-------------------------------------
12  // UVM Macros
13  //-------------------------------------
14  `uvm_object_param_utils_begin(cl_syoscb_queue_iterator_hash#(HASH_DIGEST_WIDTH))
15  `uvm_field_int(digest, UVM_DEFAULT)
16  `uvm_field_int(hash_index, UVM_DEFAULT)
17  `uvm_object_utils_end
18 
19  function new(string name = "cl_syoscb_queue_iterator_hash");
20  super.new(name);
21  endfunction: new
22 
23  //-------------------------------------
24  // Iterator API
25  //-------------------------------------
26  extern virtual function cl_syoscb_proxy_item_base next();
27  extern virtual function bit has_next();
28  extern virtual function cl_syoscb_proxy_item_base previous();
29  extern virtual function bit has_previous();
30  extern virtual function bit first();
31  extern virtual function bit last();
32  extern virtual function bit set_queue(cl_syoscb_queue_base owner);
33  extern protected virtual function cl_syoscb_proxy_item_base get_item_proxy();
35 
36 
37 /// <b>Iterator API:</b> See cl_syoscb_queue_iterator_base#next for details
39  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH) qh;
40  cl_syoscb_proxy_item_hash#(HASH_DIGEST_WIDTH) proxy_item_hash;
41  cl_syoscb_hash_aa_wrapper#(HASH_DIGEST_WIDTH) hash;
42 
43  void'($cast(qh,this.get_queue()));
44 
45  //1: Get item
46  //2: Move pointer
47 
48  if(this.has_next()) begin
49  void'($cast(proxy_item_hash, this.get_item_proxy()));
50  hash = qh.get_hash();
51 
52  //Increment position, update this.digest and this.hash_index to reflect current item
53  this.position++;
54  if(this.cfg.get_ordered_next() == 1) begin
55  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH)::tp_queue_of_keys key_queue;
56 
57  //Firstly, get handle to item currently pointed to
58  key_queue = qh.get_key_queue();
59 
60  this.digest = key_queue[this.position].digest;
61  if(hash.get_size(this.digest) == 1) begin
62  //If only one item has that hash, set idx=0
63  this.hash_index = 0;
64  end else begin
65  //In case of hash collision, go through items and manually compare
66  cl_syoscb_item item1, item2;
67  item1 = key_queue[this.position].item;
68  for(int i=0; i<hash.get_size(this.digest); i++) begin
69  item2 = hash.get_item(this.digest, i);
70  if(item1.compare(item2)) begin
71  this.hash_index = i;
72  break;
73  end
74  end
75  end
76  end else begin //ordered_next == 0
77  //To avoid hash collisions, we must increment hash index if there are multiple items with given digest
78  //The check for position != qh.get_size() is required to correctly iterate past the final element in the queue
79  //If pos == qh.get_size(), we increase hash_index, ensuring it is non-zero
80  //When previous() is called, it only decrements hash_index, returning a valid index
81  if(hash.get_size(this.digest)-1 == this.hash_index && this.position != qh.get_size()) begin
82  this.hash_index = 0;
83  void'(hash.next(this.digest));
84  end else begin
85  this.hash_index++;
86  end
87  end
88 
89  return proxy_item_hash;
90  end else begin
91  `uvm_error("ITER_ERROR", $sformatf("Cannot get next item for hash-queue %0s with %0d elements. Already pointing to last element", qh.get_name(), qh.get_size()))
92  return null;
93  end
94 endfunction: next
95 
96 /// <b>Iterator API:</b> See cl_syoscb_queue_iterator_base#has_next for details
97 function bit cl_syoscb_queue_iterator_hash::has_next();
98  cl_syoscb_queue_base qh = this.get_queue();
99  return this.position < qh.get_size();
100 endfunction: has_next
101 
102 /// <b>Iterator API:</b> See cl_syoscb_queue_iterator_base#previous for details
103 function cl_syoscb_proxy_item_base cl_syoscb_queue_iterator_hash::previous();
104  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH) qh;
105  cl_syoscb_hash_aa_wrapper#(HASH_DIGEST_WIDTH) hash;
106 
107  void'($cast(qh,this.get_queue()));
108 
109  if(!this.has_previous()) begin
110  `uvm_error("ITER_ERROR", $sformatf("Cannot get previous item for hash-queue %0s with %0d elements. Already pointing to first element", qh.get_name(), qh.get_size()))
111  return null;
112  end
113 
114  hash = qh.get_hash();
115 
116  //Decrement position, update this.digest and this.hash_index to reflect current item
117  this.position--;
118  if(this.cfg.get_ordered_next() == 1) begin
119  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH)::tp_queue_of_keys key_queue;
120  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH)::tp_digest digest;
121 
122  //Firstly, get handle to item currently pointed to
123  key_queue = qh.get_key_queue();
124 
125  this.digest = key_queue[this.position].digest;
126  if(hash.get_size(this.digest) == 1) begin
127  //If only one item has that hash, set idx=0
128  this.hash_index = 0;
129  end else begin
130  //In case of hash collision, go through items and manually compare
131  cl_syoscb_item item1, item2;
132  item1 = key_queue[this.position].item;
133  for(int i=0; i<hash.get_size(this.digest); i++) begin
134  item2 = hash.get_item(this.digest, i);
135  if(item1.compare(item2)) begin
136  this.hash_index = i;
137  break;
138  end
139  end
140  end
141  end else begin //ordered_next == 0
142  if(this.hash_index == 0) begin
143  void'(hash.prev(this.digest));
144  this.hash_index = hash.get_size(this.digest)-1;
145  end else begin
146  this.hash_index--;
147  end
148  end
149 
150  return this.get_item_proxy();
151 endfunction: previous
152 
153 /// <b>Iterator API:</b> See cl_syoscb_queue_iterator_base#has_previous for details
154 function bit cl_syoscb_queue_iterator_hash::has_previous();
155  cl_syoscb_queue_base qh = this.get_queue();
156  return (this.position > 0);
157 endfunction: has_previous
158 
159 /// <b>Iterator API:</b> See cl_syoscb_queue_iterator_base#first for details
160 function bit cl_syoscb_queue_iterator_hash::first();
161  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH) qh;
162  cl_syoscb_hash_aa_wrapper#(HASH_DIGEST_WIDTH) hash;
163 
164  void'($cast(qh,this.owner));
165 
166  if(qh.get_size() == 0) begin
167  return 1'b0;
168  end
169 
170  this.position = 0;
171  this.hash_index = 0;
172  //when ordered_next == 0, we must also update the value of this.digest, as it is required for next/previous
173  //if ordered_next == 1, this is not necessary as it only depends on this.position when calling next/previous
174  if(!this.cfg.get_ordered_next()) begin
175  hash = qh.get_hash();
176  void'(hash.first(this.digest));
177  end
178  return 1'b1;
179 endfunction: first
180 
181 /// <b>Iterator API:</b> See cl_syoscb_queue_iterator_base#last for details
182 function bit cl_syoscb_queue_iterator_hash::last();
183  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH) qh;
184  cl_syoscb_hash_aa_wrapper#(HASH_DIGEST_WIDTH) hash;
185 
186  void'($cast(qh,this.owner));
187  if(qh.get_size() == 0) begin
188  return 1'b0;
189  end
190 
191  this.position = qh.get_size();
192  //Same reasons for only updating digest/hash_index when ordered_next == 0 as stated above in first()
193  if (!this.cfg.get_ordered_next()) begin
194  hash = qh.get_hash();
195  void'(hash.last(this.digest));
196  //By setting hash_index = hash.get_size(), it is one larger than the number of items with that hash value
197  //When iter.previous() is called, hash_index is decremented, pointing us to the actually final element
198  this.hash_index = hash.get_size(this.digest);
199  end
200  return 1'b1;
201 endfunction: last
202 
203 /// <b>Iterator API:</b> See cl_syoscb_queue_iterator_base#set_queue for details
204 function bit cl_syoscb_queue_iterator_hash::set_queue(cl_syoscb_queue_base owner);
205  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH) qh;
206 
207  if(owner == null) begin
208  // An iterator should always have an associated queue
209  `uvm_error("ITER_ERROR", "Unable to associate queue with iterator as argument was null")
210  return 1'b0;
211  end else if(this.owner != null) begin
212  //An iterator's owner should not be re-assignable
213  `uvm_error("ITER_ERROR", $sformatf("Cannot reassign queue owner. Use create_iterator() to create an iterator for queue %s", owner.get_name()))
214  return 1'b0;
215  end else if(!$cast(qh, owner)) begin
216  `uvm_error("ITER_ERROR", $sformatf({"Cannot assign queue %0s to iterator %0s, as the types do not match.\n",
217  "Expected a queue of type cl_syoscb_queue_hash#(%0d), got %0s"}, owner.get_name(), this.get_name(), HASH_DIGEST_WIDTH, owner.get_type_name()))
218  return 1'b0;
219  end else begin
220  this.owner = owner;
221  this.cfg = owner.get_cfg();
222  return 1'b1;
223  end
224 endfunction: set_queue
225 
226 /// <b>Iterator API:</b> See cl_syoscb_queue_iterator_base#get_item_proxy for details
228  cl_syoscb_proxy_item_hash#(HASH_DIGEST_WIDTH) proxy_item_hash;
229  cl_syoscb_hash_aa_wrapper#(HASH_DIGEST_WIDTH) hash;
230 
231  proxy_item_hash = cl_syoscb_proxy_item_hash#(HASH_DIGEST_WIDTH)::type_id::create("proxy_item_hash");
232 
233  //When calling next() the first time, this line will get executed, initializing this.digest and this.hash_index
234  if(this.position == 0) begin
235  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH) qh;
236  void'($cast(qh, this.get_queue()));
237  this.hash_index = 0;
238 
239  if(this.cfg.get_ordered_next()) begin
240  cl_syoscb_queue_hash#(HASH_DIGEST_WIDTH)::tp_queue_of_keys key_queue = qh.get_key_queue();
241  this.digest = key_queue[this.position].digest;
242  end else begin
243  cl_syoscb_hash_aa_wrapper#(HASH_DIGEST_WIDTH) hash = qh.get_hash();
244  void'(hash.first(this.digest));
245  end
246  end
247 
248  proxy_item_hash.digest = this.digest;
249  proxy_item_hash.idx = this.hash_index;
250  proxy_item_hash.set_queue(this.owner);
251 
252  return proxy_item_hash;
253 endfunction: get_item_proxy
cl_syoscb_hash_base< HASH_DIGEST_WIDTH >::tp_hash_digest digest
Holds the value of the most recently accessed hash digest.
cl_syoscb_queue_base owner
The owner of this iterator.
virtual bit has_next()
Iterator API: See cl_syoscb_queue_iterator_base::has_next for details
virtual bit first()
Iterator API: See cl_syoscb_queue_iterator_base::first for details
The UVM scoreboard item which wraps uvm_sequence_item .
uvm_sequence_item item
Handle to the wrapped uvm_sequence_item.
virtual cl_syoscb_queue_base get_queue()
Iterator API: Internal API: Returns the queue over which this iterator is iterating.
virtual cl_syoscb_proxy_item_base previous()
Iterator API: See cl_syoscb_queue_iterator_base::previous for details
Base class for all proxy items.
virtual tp_queue_of_keys get_key_queue()
Get the list of hash values of items in the queue.
cl_syoscb_cfg cfg
Local handle to the SCB cfg.
int unsigned hash_index
Field indicating which cl_syoscb_hash_item index we&#39;re currently looking at.
Queue iterator base class defining the iterator API used for iterating over queues.
int unsigned position
Current position in the queue.
Class which represents the base concept of a queue.
virtual bit set_queue(cl_syoscb_queue_base owner)
Iterator API: See cl_syoscb_queue_iterator_base::set_queue for details
virtual bit get_ordered_next()
Configuration API: Get the value of the ordered_next member variable.
virtual cl_syoscb_proxy_item_base get_item_proxy()
Iterator API: See cl_syoscb_queue_iterator_base::get_item_proxy for details
virtual bit last()
Iterator API: See cl_syoscb_queue_iterator_base::last for details
virtual cl_syoscb_item get_item(cl_syoscb_proxy_item_base proxy_item)
Queue API: See cl_syoscb_queue_base::get_item for more details
Queue iterator class defining the iterator API used for iterating hash queues.
Class which defines the base concept of a hash algorithm.
A wrapper around an associative array, used for storing hash queues.
virtual cl_syoscb_proxy_item_base next()
Iterator API: See cl_syoscb_queue_iterator_base::next for details
Proxy item implementation for hash queues.
Class which represents the base concept of a hash queue.
virtual bit has_previous()
Iterator API: See cl_syoscb_queue_iterator_base::has_previous for details

Project: SyoSil ApS UVM Scoreboard, Revision: 1.0.3.0

Copyright 2014-2022 SyoSil ApS
All Rights Reserved Worldwide

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
doxygen
Doxygen Version: 1.8.14
Generated with IDV SV Filter Version: 2.6.3
Fri Sep 2 2022 14:39:46
Find a documentation bug? Report bugs to: scoreboard@syosil.com