test_lib.py
1 ################################################################################################## 2 # BSD 3-Clause License 3 # 4 # Copyright (c) 2022, Jose R. Garcia 5 # All rights reserved. 6 # 7 # Redistribution and use in source and binary forms, with or without 8 # modification, are permitted provided that the following conditions are met: 9 # 10 # 1. Redistributions of source code must retain the above copyright notice, this 11 # list of conditions and the following disclaimer. 12 # 13 # 2. Redistributions in binary form must reproduce the above copyright notice, 14 # this list of conditions and the following disclaimer in the documentation 15 # and/or other materials provided with the distribution. 16 # 17 # 3. Neither the name of the copyright holder nor the names of its 18 # contributors may be used to endorse or promote products derived from 19 # this software without specific prior written permission. 20 # 21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 # 32 ################################################################################################## 33 # File name : test_lib.py 34 # Author : Jose R Garcia (jg-fossh@protonmail.com) 35 # Project Name : Goldschmidt Integer Divider 36 # Class Name : test_lib 37 # Description : Collection of tests available for this module. 38 # 39 # Additional Comments: 40 # Contains the test base and tests. 41 ################################################################################################## 42 # Framework Libs 43 import cocotb 44 from cocotb.triggers import Timer 45 # UVM Libs 46 from uvm import * 47 from wb4s_seq import * 48 from wb4s_agent import * 49 from wb4s_config import * 50 from tb_env_config import * 51 from tb_env import * 52 from predictor import * 53 # General Python Libs 54 import math 55 import random as rnd 56 57 class test_base(UVMTest): 58 """ 59 Class: Test Base 60 61 Definition: Contains functions, tasks and methods. 62 """ 63 64 def __init__(self, name="test_base", parent=None): 65 super().__init__(name, parent) 66 self.test_pass = True 67 self.err_msg = "" 68 self.tb_env = None 69 self.tb_env_config = None 70 self.wb4s_agent_cfg = None 71 self.printer = None 72 73 def build_phase(self, phase): 74 super().build_phase(phase) 75 # Enable transaction recording for everything 76 UVMConfigDb.set(self, "*", "recording_detail", UVM_FULL) 77 78 # create this test test bench environment config 79 arr = [] 80 if UVMConfigDb.get(None, "dut", "DUT_SLAVE_DATA_IN_LENGTH", arr) is True: 81 UVMConfigDb.set(None, "*", "DUT_SLAVE_DATA_IN_LENGTH", arr[0]) 82 83 self.tb_env_config = tb_env_config.type_id.create("tb_env_config", self) 84 self.tb_env_config.has_scoreboard = True 85 self.tb_env_config.has_predictor = True 86 self.tb_env_config.has_functional_coverage = False 87 self.tb_env_config.DUT_SLAVE_DATA_IN_LENGTH = arr[0] 88 self.tb_env_config.data_bins_range = [0, 0xFFFFFFFF] 89 90 # Create the Mem Read agent 91 self.wb4s_agent_cfg = wb4s_config.type_id.create("wb4s_agent_cfg", self) 92 arr = [] 93 # Get the instruction interface created at top 94 if UVMConfigDb.get(None, "*", "vif_slave", arr) is True: 95 UVMConfigDb.set(self, "*", "vif_slave", arr[0]) 96 # Make this agent's interface the interface connected at top 97 self.wb4s_agent_cfg.vif = arr[0] 98 self.wb4s_agent_cfg.has_driver = 1 99 self.wb4s_agent_cfg.has_monitor = 1 100 else: 101 uvm_fatal("NOVIF", "Could not get vif_slave from config DB") 102 103 # Make this instruction agent the test bench config agent 104 self.tb_env_config.wb4s_agent_cfg = self.wb4s_agent_cfg 105 106 # Place the tn_env_config in the Db. The tb_env will fetch this in its build phase . 107 UVMConfigDb.set(self, "*", "tb_env_config", self.tb_env_config) 108 109 # Create the test bench environment 110 self.tb_env = tb_env.type_id.create("tb_env", self) 111 112 # Create a specific depth printer for printing the created topology 113 self.printer = UVMTablePrinter() 114 self.printer.knobs.depth = 3 115 116 117 def end_of_elaboration_phase(self, phase): 118 # Print topology 119 uvm_info(self.get_type_name(), 120 sv.sformatf("Printing the test topology :\n%s", self.sprint(self.printer)), UVM_LOW) 121 122 123 def extract_phase(self, phase): 124 if(self.tb_env.scoreboard.m_mismatches == 0): 125 self.test_pass = True 126 else: 127 self.test_pass = False 128 self.err_msg += '\nMatches : ' + str(self.tb_env.scoreboard.m_matches) 129 self.err_msg += '\nMismatches : ' + str(self.tb_env.scoreboard.m_mismatches) 130 131 132 def report_phase(self, phase): 133 if self.test_pass: 134 uvm_info(self.get_type_name(), 135 sv.sformatf("\n\n-----------------------------------\n UVM Test : %s\n Matches : %d\n Mismatches : %d\n Pass/Fail : Pass\n-----------------------------------\n", self.get_type_name(), self.tb_env.scoreboard.m_matches, self.tb_env.scoreboard.m_mismatches), UVM_NONE) 136 else: 137 uvm_fatal(self.get_type_name(), "UVM TEST FAIL\n" + 138 self.err_msg) 139 140 cov_print = 0 # 141 # Coverage Report 142 if (cov_print == 1): 143 # Print coverage bins at the end of the sim 144 coverage.coverage_db.report_coverage(print, bins=False) 145 coverage.coverage_db.report_coverage(print, bins=True) 146 147 if (self.tb_env_config.has_functional_coverage): 148 coverage.coverage_db.export_to_yaml(filename="coverage_result.yml") 149 150 151 uvm_component_utils(test_base) 152 153 154 class default_test(test_base): 155 """ 156 Class: Default Test 157 158 Definition: Contains functions, tasks and methods. 159 """ 160 161 def __init__(self, name="default_test", parent=test_base): 162 super().__init__(name, parent) 163 # This class' variables initial state. 164 self.count = 0 165 self.stall = 1 166 self.acknowledge = 0 167 168 169 async def run_phase(self, phase): 170 phase.raise_objection(self, "default_test raise objection") 171 172 # Call and fork the methods that create sequences to feed the sequencers 173 slave_proc = cocotb.fork(self.random_stimulat_intfc()) 174 #slave_proc = cocotb.fork(self.stimulate_slave_intfc()) 175 176 await Timer(16, "NS") # Allow some clocks for evething to settle 177 178 uvm_info(self.get_type_name(), 179 sv.sformatf("\nSim Started\n"), UVM_LOW) 180 await sv.fork_join_any([slave_proc]) 181 182 uvm_info(self.get_type_name(), 183 sv.sformatf("\nSim Finished\n"), UVM_LOW) 184 185 phase.drop_objection(self, "default_test drop objection") 186 187 188 189 async def random_stimulat_intfc(self): 190 # 191 top_rng = int(pow(2, (self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH)/2)) 192 #top_rng = int(pow(2, (self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH)/4)) 193 stop_count = 25 194 wb4s_sqr = self.tb_env.wb4s_agent.sqr 195 196 # de-assert the CYC and STB signals 197 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 198 increment_sum_seq.data = 51966 #0xCAFE 199 increment_sum_seq.cycle = 0 200 increment_sum_seq.strobe = 0 201 increment_sum_seq.cycle_tag = 1 202 203 await increment_sum_seq.start(wb4s_sqr) 204 205 while (stop_count > 0): 206 stop_count -= 1 207 wb4s_sqr = self.tb_env.wb4s_agent.sqr 208 209 # Create transactions to stimulate the slave interface (calc division) 210 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 211 increment_sum_seq.data = (rnd.randint(0,top_rng) << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + rnd.randint(0,top_rng) 212 #increment_sum_seq.data = ((top_rng-1-(stop_count*stop_count*10000)) << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + (top_rng-stop_count-1) 213 increment_sum_seq.strobe = 1 # rnd.randint(0,2) 214 increment_sum_seq.cycle = 1 #rnd.randint(0,2) 215 increment_sum_seq.cycle_tag = 1#rnd.randint(0,4) 216 217 await increment_sum_seq.start(wb4s_sqr) 218 219 # de-assert the CYC and STB signals 220 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 221 increment_sum_seq.data = 51966 #0xCAFE 222 increment_sum_seq.cycle = 0 223 increment_sum_seq.strobe = 0 224 increment_sum_seq.cycle_tag = 0 225 226 await increment_sum_seq.start(wb4s_sqr) 227 228 229 async def stimulate_slave_intfc(self): 230 # 231 self.count = int(pow(2, (self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH)/2)-1) 232 data_inc = 3 233 stop_count = self.count + (self.tb_env.cfg.data_bins_range[1] - self.tb_env.cfg.data_bins_range[0])/data_inc 234 wb4s_sqr = self.tb_env.wb4s_agent.sqr 235 236 # de-assert the CYC and STB signals 237 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 238 increment_sum_seq.data = 51966 #0xCAFE 239 increment_sum_seq.cycle = 0 240 increment_sum_seq.strobe = 0 241 increment_sum_seq.cycle_tag = 0 242 243 await increment_sum_seq.start(wb4s_sqr) 244 245 # Create transactions to stimulate the slave interface (calc division) 246 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 247 increment_sum_seq.data = 0 248 increment_sum_seq.strobe = 1 249 increment_sum_seq.cycle = 1 250 increment_sum_seq.cycle_tag = 0 251 252 await increment_sum_seq.start(wb4s_sqr) 253 254 # Create transactions to stimulate the slave interface (calc division) 255 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 256 increment_sum_seq.data = 1 257 increment_sum_seq.strobe = 1 258 increment_sum_seq.cycle = 1 259 increment_sum_seq.cycle_tag = 0 260 261 await increment_sum_seq.start(wb4s_sqr) 262 263 # Create transactions to stimulate the slave interface (calc division) 264 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 265 increment_sum_seq.data = 1 << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2) 266 increment_sum_seq.strobe = 1 267 increment_sum_seq.cycle = 1 268 increment_sum_seq.cycle_tag = 0 269 270 await increment_sum_seq.start(wb4s_sqr) 271 272 # Create transactions to stimulate the slave interface (calc division) 273 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 274 increment_sum_seq.data = (1 << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 1 275 increment_sum_seq.strobe = 1 276 increment_sum_seq.cycle = 1 277 increment_sum_seq.cycle_tag = 0 278 279 await increment_sum_seq.start(wb4s_sqr) 280 281 # Create transactions to stimulate the slave interface (calc division) 282 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 283 increment_sum_seq.data = (0xFFFFFFFF << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 1 284 increment_sum_seq.strobe = 1 285 increment_sum_seq.cycle = 1 286 increment_sum_seq.cycle_tag = 3 287 288 await increment_sum_seq.start(wb4s_sqr) 289 290 # Create transactions to stimulate the slave interface (calc division) 291 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 292 increment_sum_seq.data = (0xFFFFFFFF << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 10 293 increment_sum_seq.strobe = 1 294 increment_sum_seq.cycle = 1 295 increment_sum_seq.cycle_tag = 3 296 297 await increment_sum_seq.start(wb4s_sqr) 298 299 # Create transactions to stimulate the slave interface (calc division) 300 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 301 increment_sum_seq.data = (3145727 << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 4195835 302 increment_sum_seq.strobe = 1 303 increment_sum_seq.cycle = 1 304 increment_sum_seq.cycle_tag = 1 305 306 await increment_sum_seq.start(wb4s_sqr) 307 308 # Create transactions to stimulate the slave interface (calc division) 309 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 310 increment_sum_seq.data = (3145727 << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 4195835 311 increment_sum_seq.strobe = 1 312 increment_sum_seq.cycle = 1 313 increment_sum_seq.cycle_tag = 3 314 315 await increment_sum_seq.start(wb4s_sqr) 316 317 # Create transactions to stimulate the slave interface (calc division) 318 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 319 increment_sum_seq.data = (-3145727 << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 4195835 320 increment_sum_seq.strobe = 1 321 increment_sum_seq.cycle = 1 322 increment_sum_seq.cycle_tag = 1 323 324 await increment_sum_seq.start(wb4s_sqr) 325 326 # Create transactions to stimulate the slave interface (calc division) 327 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 328 increment_sum_seq.data = (-3145727 << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 4195835 329 increment_sum_seq.strobe = 1 330 increment_sum_seq.cycle = 1 331 increment_sum_seq.cycle_tag = 3 332 333 await increment_sum_seq.start(wb4s_sqr) 334 335 # Create transactions to stimulate the slave interface (calc division) 336 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 337 increment_sum_seq.data = (112 << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 5058 338 increment_sum_seq.strobe = 1 339 increment_sum_seq.cycle = 1 340 increment_sum_seq.cycle_tag = 1 341 342 await increment_sum_seq.start(wb4s_sqr) 343 344 # Create transactions to stimulate the slave interface (calc division) 345 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 346 increment_sum_seq.data = (112 << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 5058 347 increment_sum_seq.strobe = 1 348 increment_sum_seq.cycle = 1 349 increment_sum_seq.cycle_tag = 3 350 351 await increment_sum_seq.start(wb4s_sqr) 352 353 # Create transactions to stimulate the slave interface (calc division) 354 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 355 increment_sum_seq.data = (96 << math.floor(self.tb_env.cfg.DUT_SLAVE_DATA_IN_LENGTH/2)) + 1024 356 increment_sum_seq.strobe = 1 357 increment_sum_seq.cycle = 1 358 increment_sum_seq.cycle_tag = 3 359 360 await increment_sum_seq.start(wb4s_sqr) 361 362 # de-assert the CYC and STB signals 363 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 364 increment_sum_seq.data = 0 365 increment_sum_seq.cycle = 1 366 increment_sum_seq.strobe = 0 367 increment_sum_seq.cycle_tag = 0 368 369 await increment_sum_seq.start(wb4s_sqr) 370 371 # de-assert the CYC and STB signals 372 increment_sum_seq = wb4s_single_write_seq("increment_sum_seq") 373 increment_sum_seq.data = 51966 #0xCAFE 374 increment_sum_seq.cycle = 0 375 increment_sum_seq.strobe = 0 376 increment_sum_seq.cycle_tag = 0 377 378 await increment_sum_seq.start(wb4s_sqr) 379 380 381 uvm_component_utils(default_test)