SyoSil ApS UVM Scoreboard  1.0.3.0
cl_scb_test_iterator_correctness.svh
1 //Defining the actions that each iterator can take in the test
2 typedef enum { NEXT, PREV, FIRST, LAST, INSERT, DELETE } iterator_action_t;
3 
4 //A helper object to use in the test defined below
5 //Used to keep track of operations happening on the queue, allowing us to reconstruct and validate that all queues performed correctly
6 class cl_scb_test_iterator_correctness_helper_object extends uvm_object;
7  int index;
8  iterator_action_t op;
9 
10  `uvm_object_utils_begin(cl_scb_test_iterator_correctness_helper_object)
11  `uvm_field_int(index, UVM_DEFAULT)
12  `uvm_field_enum(iterator_action_t, op, UVM_DEFAULT)
13  `uvm_object_utils_end
14 
15  function new(string name = "cl_scb_test_iterato_deadlock_helper_object");
16  super.new(name);
17  endfunction: new
18 
19  function string convert2string();
20  return {this.op.name(), $sformatf(" %3d", this.index)};
21  endfunction: convert2string
22 endclass
23 
24 /// Test to ensure that multiple iterators on the same queue won't deadlock and are performing correctly.
25 /// At the end, validates that the correct items have been removed/inserted
26 //Note that on test finish, number of Q1 insertions/matches won't match number of Q2 insertions/matches
27 //This is on purpose, since every deleted item counts as a "match" for the SCB
28 class cl_scb_test_iterator_correctness extends cl_scb_test_single_scb;
29  //-------------------------------------
30  // Non randomizable variables
31  //-------------------------------------
32 
33  //All operations that are performed on the queue
34  cl_scb_test_iterator_correctness_helper_object operations[$];
35 
36  int NUM_ITEMS; //Number of items to start with
37  int NUM_ITERS; //Number of iterators to create
38  int NUM_ACTIONS; //Number of actions each iterator should perform
39 
40  //-------------------------------------
41  // UVM Macros
42  //-------------------------------------
43  `uvm_component_utils_begin(cl_scb_test_iterator_correctness)
44 
45  `uvm_component_utils_end
46 
47  //-------------------------------------
48  // Constructor
49  //-------------------------------------
50  function new(string name = "cl_scb_test_iterator_correctness", uvm_component parent = null);
51  super.new(name, parent);
52  endfunction: new
53 
54  //-------------------------------------
55  // Functions
56  //-------------------------------------
57  extern task main_phase(uvm_phase phase);
58  extern task use_iterator(int id);
59 
60 
62 
63 //Spin up an iterator, use it to perform a series of operations on the queue.
64 //Tracks all insert/delete operations in this.operations
65 task cl_scb_test_iterator_correctness::use_iterator(int id);
66  iterator_action_t action;
68  cl_syoscb_queue_base q = this.syoscb_cfgs.syoscb_cfg[0].get_queue("Q1");
69 
70  #($urandom_range(100, 1)); //Wait for some random amount before creating the iterator
71  iter = q.create_iterator();
72 
73  for(int i=0; i<this.NUM_ACTIONS; i++) begin
74  if(!std::randomize(action)) begin
75  `uvm_fatal("RAND", "Unable to randomize action to take")
76  end
77 
78  case (action)
79  NEXT: if(iter.has_next()) void'(iter.next());
80  PREV: if(iter.has_previous()) void'(iter.previous());
81  FIRST: void'(iter.first());
82  LAST: void'(iter.last());
83  INSERT: begin
84  //Create sequence item and tracker object, track operation and insert item
85  cl_tb_seq_item ctsi = cl_tb_seq_item::type_id::create("ctsi");
86  cl_scb_test_iterator_correctness_helper_object help = new;
87  help.index = this.operations.size(); //use operations.size() to get a unique index for every value
88  help.op = INSERT;
89  ctsi.int_a = this.operations.size();
90 
91  this.operations.push_back(help);
92  this.scb_env.syoscb[0].add_item("Q1", "P1", ctsi);
93  end
94  DELETE: begin
95  cl_syoscb_proxy_item_base proxy;
96  cl_scb_test_iterator_correctness_helper_object help;
97 
98  //When deleting, we try to remove the item in front.
99  //Only if that is impossible do we step back once and then delete the item
100  if(iter.has_next()) begin
101  proxy = iter.next();
102  end else begin
103  void'(iter.previous());
104  proxy = iter.next();
105  end
106 
107  //Create tracker object, track operation and delete item at current iterator index
108  help = new;
109  help.index = iter.previous_index(); //TODO: Requires reworking
110  help.op = DELETE;
111  this.operations.push_back(help);
112  void'(q.delete_item(proxy));
113  end
114  endcase
115  //Below line commented out on purpose. Uncomment for debug printout if test breaks
116  // $display("[%0d](%3t) %s, %0d/%0d", id, $time, action.name, iter.next_index(), q.get_size()-1);
117 
118  #($urandom_range(10,1)); //Wait for some random amount
119  end
120 
121 endtask: use_iterator
122 
123 task cl_scb_test_iterator_correctness::main_phase(uvm_phase phase);
124  int result[$];
125 
126  phase.raise_objection(this);
127  super.main_phase(phase);
128 
129  NUM_ITEMS = 50;
130  NUM_ITERS = 10;
131  NUM_ACTIONS = 100;
132 
133  //Add some starting items to Q1 that we can iterate over
134  //Also track all of these items so we can reconstruct later
135  for(int i=0; i<this.NUM_ITEMS; i++) begin
136  cl_tb_seq_item ctsi = cl_tb_seq_item::type_id::create("ctsi");
137  cl_scb_test_iterator_correctness_helper_object help = new;
138 
139  help.index = i;
140  help.op = INSERT;
141  this.operations.push_back(help);
142 
143  ctsi.int_a = i;
144  this.scb_env.syoscb[0].add_item("Q1", "P1", ctsi);
145  end
146 
147  //Spin up multiple threads iterating over Q1, performing random operations
148  for(int i=0; i<this.NUM_ITERS; i++) begin
149  fork
150  //Must create new value k such that it is not bound to the value of i declared outside of fork
151  automatic int k = i;
152  this.use_iterator(k);
153  join_none
154  end
155  wait fork; //Must wait after join_none to ensure main_phase doesn't end prematurely
156 
157  //Reconstruct all operations
158  //After this foreach loop, result should contain all indices still present in queue
159  foreach(this.operations[i]) begin
160  if(this.operations[i].op == INSERT) begin //insertion
161  result.push_back(this.operations[i].index);
162  end else if(this.operations[i].op == DELETE) begin
163  result.delete(this.operations[i].index);
164  end else begin
165  `uvm_error("TEST", $sformatf("Bad enum in helper object. str=%s, value=%0d", this.operations[i].op.name(), this.operations[i].op))
166  end
167  end
168 
169  //For all remaining indices, add to Q2
170  //Everything should hopefully match up
171  foreach(result[i]) begin
172  cl_tb_seq_item ctsi = cl_tb_seq_item::type_id::create("ctsi");
173  ctsi.int_a = result[i];
174  this.scb_env.syoscb[0].add_item("Q2", "P1", ctsi);
175  end
176 
177  phase.drop_objection(this);
178 endtask: main_phase
Test to ensure that multiple iterators on the same queue won&#39;t deadlock and are performing correctly...
Queue iterator base class defining the iterator API used for iterating over queues.
Class which represents the base concept of a queue.

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:37:39
Find a documentation bug? Report bugs to: scoreboard@syosil.com