├── README.md ├── apb_project ├── Makefile.questa ├── README.md ├── apb_agent_env_config.svh ├── apb_driver_seq_mon.svh ├── apb_if.svh ├── apb_rw.svh ├── apb_sequences.svh ├── apb_test.svh └── testbench.sv ├── course_examples ├── bus_sequence_item_eg.svh ├── simple_agent.svh ├── simple_build_config_eg.svh ├── simple_build_test.svh ├── simple_driver.svh ├── simple_driver_response.svh ├── simple_monitor.svh ├── simple_sequencer.svh └── simple_tb_top_eg.svh └── uvm_report_catcher ├── env.svh ├── report_catcher.svh ├── sim ├── report_inc.f └── run.py ├── test.svh └── top.sv /README.md: -------------------------------------------------------------------------------- 1 | UVMReference 2 | ============ 3 | 4 | Reference examples and short projects using UVM Methodology 5 | 6 | 1) course_examples directory has example code for basic uvm components and sequences that are referred in the course lectures 7 | This can be referred which also has decent enough comments to understand structure 8 | 9 | 2) apb_project 10 | This containts a working copy for an APB interface protocol verification environment in UVM. Refer to this for the APB project assignment as part of the course 11 | 12 | 3) uvm_report_catcher 13 | Custom UVM Report Catcher object to demote UVM_ERROR to UVM_INFO. Uses Component ID based match (commented in report catcher code), and string based comparison with regular expression. 14 | -------------------------------------------------------------------------------- /apb_project/Makefile.questa: -------------------------------------------------------------------------------- 1 | ## ------------------------------------------------------------- 2 | ## Copyright 2010-2011 Mentor Graphics Corporation 3 | ## All Rights Reserved Worldwide 4 | ## 5 | ## Licensed under the Apache License, Version 2.0 (the 6 | ## "License"); you may not use this file except in 7 | ## compliance with the License. You may obtain a copy of 8 | ## the License at 9 | ## 10 | ## http://www.apache.org/licenses/LICENSE-2.0 11 | ## 12 | ## Unless required by applicable law or agreed to in 13 | ## writing, software distributed under the License is 14 | ## distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 15 | ## CONDITIONS OF ANY KIND, either express or implied. See 16 | ## the License for the specific language governing 17 | ## permissions and limitations under the License. 18 | ## ------------------------------------------------------------- 19 | ## 20 | 21 | USES_DPI = 1 22 | ifdef UVM_NO_DPI 23 | USES_DPI=0 24 | endif 25 | 26 | #--------------------------------------------------------------- 27 | # Define Variables 28 | #--------------------------------------------------------------- 29 | # - Change UVM_HOME if u have a different path 30 | UVM_HOME ?= ../uvm-1.2 31 | 32 | MTI_HOME = $(MODEL_HOME) 33 | LIBDIR = $(UVM_HOME)/lib 34 | #GCC = $(MTI_HOME)/gcc-4.1.2-linux/bin/g++ 35 | GCC = gcc 36 | TEST = /usr/bin/test 37 | BITS ?= 32 38 | LIBNAME = uvm_dpi 39 | DPI_SRC = $(UVM_HOME)/src/dpi/uvm_dpi.cc 40 | 41 | 42 | GCCCMD = $(GCC) \ 43 | -m$(BITS) \ 44 | -fPIC \ 45 | -DQUESTA \ 46 | -g \ 47 | -W \ 48 | -shared \ 49 | -x c \ 50 | -I$(MTI_HOME)/include \ 51 | $(DPI_SRC) \ 52 | -o $(LIBDIR)/$(LIBNAME).so 53 | 54 | GCC_WINCMD = \ 55 | $(WIN_GCC) \ 56 | -g \ 57 | -DQUESTA \ 58 | -W \ 59 | -shared \ 60 | -Bsymbolic \ 61 | -x c \ 62 | -I$(MTI_HOME)/include \ 63 | $(DPI_SRC) \ 64 | -o $(LIBDIR)/$(LIBNAME).dll \ 65 | $(MTI_HOME)/win32/mtipli.dll -lregex 66 | 67 | WIN_GCC = $(MTI_HOME)/gcc-4.2.1-mingw32vc9/bin/g++.exe 68 | 69 | VLIB = vlib work 70 | 71 | VLOG = vlog \ 72 | -timescale "1ns/1ns" \ 73 | $(DPILIB_VLOG_OPT) \ 74 | $(VLOG_OPT) \ 75 | $(OPT_C) \ 76 | -mfcu \ 77 | -suppress 2181 \ 78 | +acc=rmb \ 79 | -writetoplevels questa.tops \ 80 | +incdir+$(UVM_HOME)/src \ 81 | $(UVM_HOME)/src/uvm.sv 82 | 83 | 84 | VSIM = vsim \ 85 | $(DPILIB_VSIM_OPT) \ 86 | $(VSIM_OPT) \ 87 | $(OPT_R) \ 88 | -c \ 89 | -do "run -all; q" \ 90 | -l questa.log \ 91 | -f questa.tops 92 | 93 | N_ERRS = 0 94 | N_FATALS = 0 95 | 96 | CHECK = \ 97 | @$(TEST) \( `grep -c 'UVM_ERROR : $(N_ERRS)' questa.log` -eq 1 \) -a \ 98 | \( `grep -c 'UVM_FATAL : $(N_FATALS)' questa.log` -eq 1 \) 99 | 100 | #--------------------------------------------------------------- 101 | # If USES_DPI is set, enables compilation and loading of DPI 102 | # libraries. Enabling DPI adds +acc on command line, which 103 | # may adversely affect simulator performance. 104 | #--------------------------------------------------------------- 105 | 106 | ifeq ($(USES_DPI),1) 107 | DPILIB_VLOG_OPT = 108 | DPILIB_VSIM_OPT = -sv_lib $(LIBDIR)/uvm_dpi 109 | DPILIB_TARGET = dpi_lib$(BITS) 110 | else 111 | DPILIB_VLOG_OPT = +define+UVM_NO_DPI 112 | DPILIB_VSIM_OPT = 113 | DPILIB_TARGET = 114 | endif 115 | 116 | 117 | #--------------------------------------------------------------- 118 | # Define Targets 119 | # 120 | # vlog and vsim targets defined in individual examples 121 | #--------------------------------------------------------------- 122 | 123 | 124 | help: 125 | @echo "Usage: make -f Makefile.questa [target(s)]" 126 | @echo "" 127 | @echo "Typical: make -f Makefile.questa all" 128 | @echo "" 129 | @echo "where target is any of" 130 | @echo "" 131 | @echo " dpi_lib - compile DPI lib (use BITS=XX, def=32)" 132 | @echo " dpi_lib32 - compile DPI lib for 32-bit Linux (BITS=32)" 133 | @echo " dpi_lib64 - compile DPI lib for 64-bit Linux (BITS=64)" 134 | @echo " dpi_libWin - compile DPI lib for Windows" 135 | @echo "" 136 | @echo " clean - removes all derived files" 137 | @echo " vlib - creates work library" 138 | @echo " prepare - invokes clean, vlib, and dpi_lib targets" 139 | @echo "" 140 | @echo "When this makefile is included by a Makefile from an example" 141 | @echo "sub-directory, additional targets should be available:" 142 | @echo "" 143 | @echo " all - invokes targets prepare, vlog, and vsim" 144 | @echo " vlog - invokes the vlog compiler" 145 | @echo " vsim - invokes the vsim simulator" 146 | @echo "" 147 | @echo "Variables: specify any of the following on the make command line" 148 | @echo "" 149 | @echo " UVM_HOME - root directory of the UVM library (default:..)" 150 | @echo " UVM_VERBOSITY - verbosity level for vsim (default:UVM_MEDIUM)" 151 | @echo " BITS - the bus architecture: 32 or 64 (default:32)" 152 | @echo " LIBNAME - the root name of the dpi library (default:uvm_dpi)" 153 | @echo " LIBDIR - the location to put the dpi lib (default:UVM_HOME/lib)" 154 | @echo "" 155 | 156 | prepare: clean vlib $(DPILIB_TARGET) 157 | 158 | 159 | dpi_lib: 160 | mkdir -p $(LIBDIR) 161 | $(GCCCMD) 162 | 163 | dpi_libWin: 164 | mkdir -p $(LIBDIR) 165 | $(GCC_WINCMD) 166 | 167 | dpi_lib32: 168 | make -f Makefile.questa BITS=32 dpi_lib 169 | 170 | dpi_lib64: 171 | make -f Makefile.questa LIBNAME=uvm_dpi BITS=64 dpi_lib 172 | 173 | vlib: $(DPILIB_TARGET) 174 | vlib work 175 | 176 | clean: 177 | rm -rf *~ work vsim.wlf* *.log questa.tops transcript *.vstf 178 | 179 | 180 | all: run 181 | 182 | comp: vlib 183 | $(VLOG) +incdir+. \ 184 | testbench.sv 185 | 186 | run: comp 187 | $(VSIM) 188 | $(CHECK) 189 | -------------------------------------------------------------------------------- /apb_project/README.md: -------------------------------------------------------------------------------- 1 | APB Project 2 | ============ 3 | This is a complete APB interface project build in UVM and using only basic concepts as the motivation is to help beginners get started on understanding basic coding 4 | 5 | apb_if.sv -> Is the APB interface protocol signal interface 6 | 7 | apb_rw.svh -> Is the basic apb read/write transaction class (sequence item) 8 | 9 | apb_driver_seq_mon.svh -> Contatins the basic apb driver, sequencer and monitor component class 10 | 11 | apb_agent_env_config.svh -> Contatins the basic apb agent env and configuration class definitions 12 | 13 | apb_test.svh -> is the top level uvm_test for apb interface 14 | 15 | apb_sequences.svh -> contatins the basic sequences for testing apb_interface 16 | 17 | testbench.sv -> is the top level module that instantiates the apb physical interface and starts the top level test 18 | 19 | 20 | 21 | Since there is no real APB SLAVE DUT - once you simulate this you should be only observing apb transactions send from driver to interface and the monitor being able to see the interface toggling and reporting out those as transactions 22 | 23 | As a future enhancement - students can also extend this to include a slave bfm, score board etc but not planned for the basic level course 24 | -------------------------------------------------------------------------------- /apb_project/apb_agent_env_config.svh: -------------------------------------------------------------------------------- 1 | //----------------------------- 2 | // This file contains apb config, apb_agent and apb_env class components 3 | //----------------------------- 4 | `ifndef APB_AGENT_ENV_CFG__SV 5 | `define APB_AGENT_ENV_CFG__SV 6 | 7 | //--------------------------------------- 8 | // APB Config class 9 | // -Not really done anything as of now 10 | //--------------------------------------- 11 | class apb_config extends uvm_object; 12 | 13 | `uvm_object_utils(apb_config) 14 | virtual apb_if vif; 15 | 16 | function new(string name="apb_config"); 17 | super.new(name); 18 | endfunction 19 | 20 | endclass 21 | 22 | //--------------------------------------- 23 | // APB Agent class 24 | //--------------------------------------- 25 | class apb_agent extends uvm_agent; 26 | 27 | //Agent will have the sequencer, driver and monitor components for the APB interface 28 | apb_sequencer sqr; 29 | apb_master_drv drv; 30 | apb_monitor mon; 31 | 32 | virtual apb_if vif; 33 | 34 | `uvm_component_utils_begin(apb_agent) 35 | `uvm_field_object(sqr, UVM_ALL_ON) 36 | `uvm_field_object(drv, UVM_ALL_ON) 37 | `uvm_field_object(mon, UVM_ALL_ON) 38 | `uvm_component_utils_end 39 | 40 | function new(string name, uvm_component parent = null); 41 | super.new(name, parent); 42 | endfunction 43 | 44 | //Build phase of agent - construct sequencer, driver and monitor 45 | //get handle to virtual interface from env (parent) config_db 46 | //and pass handle down to srq/driver/monitor 47 | virtual function void build_phase(uvm_phase phase); 48 | sqr = apb_sequencer::type_id::create("sqr", this); 49 | drv = apb_master_drv::type_id::create("drv", this); 50 | mon = apb_monitor::type_id::create("mon", this); 51 | 52 | if (!uvm_config_db#(virtual apb_if)::get(this, "", "vif", vif)) begin 53 | `uvm_fatal("APB/AGT/NOVIF", "No virtual interface specified for this agent instance") 54 | end 55 | uvm_config_db#(virtual apb_if)::set( this, "sqr", "vif", vif); 56 | uvm_config_db#(virtual apb_if)::set( this, "drv", "vif", vif); 57 | uvm_config_db#(virtual apb_if)::set( this, "mon", "vif", vif); 58 | endfunction: build_phase 59 | 60 | //Connect - driver and sequencer port to export 61 | virtual function void connect_phase(uvm_phase phase); 62 | drv.seq_item_port.connect(sqr.seq_item_export); 63 | uvm_report_info("apb_agent::", "connect_phase, Connected driver to sequencer"); 64 | endfunction 65 | endclass: apb_agent 66 | 67 | //---------------------------------------------- 68 | // APB Env class 69 | //---------------------------------------------- 70 | class apb_env extends uvm_env; 71 | 72 | `uvm_component_utils(apb_env); 73 | 74 | //ENV class will have agent as its sub component 75 | apb_agent agt; 76 | //virtual interface for APB interface 77 | virtual apb_if vif; 78 | 79 | function new(string name, uvm_component parent = null); 80 | super.new(name, parent); 81 | endfunction 82 | 83 | //Build phase - Construct agent and get virtual interface handle from test and pass it down to agent 84 | function void build_phase(uvm_phase phase); 85 | agt = apb_agent::type_id::create("agt", this); 86 | if (!uvm_config_db#(virtual apb_if)::get(this, "", "vif", vif)) begin 87 | `uvm_fatal("APB/AGT/NOVIF", "No virtual interface specified for this env instance") 88 | end 89 | uvm_config_db#(virtual apb_if)::set( this, "agt", "vif", vif); 90 | endfunction: build_phase 91 | 92 | endclass : apb_env 93 | 94 | 95 | `endif 96 | -------------------------------------------------------------------------------- /apb_project/apb_driver_seq_mon.svh: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------- 2 | // This file contains the APB Driver, Sequencer and Monitor component classes defined 3 | //---------------------------------------------------- 4 | `ifndef APB_DRV_SEQ_MON_SV 5 | `define APB_DRV_SEQ_MON_SV 6 | 7 | typedef apb_config; 8 | typedef apb_agent; 9 | 10 | //--------------------------------------------- 11 | // APB master driver Class 12 | //--------------------------------------------- 13 | class apb_master_drv extends uvm_driver#(apb_rw); 14 | 15 | `uvm_component_utils(apb_master_drv) 16 | 17 | virtual apb_if vif; 18 | apb_config cfg; 19 | 20 | function new(string name,uvm_component parent = null); 21 | super.new(name,parent); 22 | endfunction 23 | 24 | //Build Phase 25 | //Get the virtual interface handle form the agent (parent ) or from config_db 26 | function void build_phase(uvm_phase phase); 27 | apb_agent agent; 28 | super.build_phase(phase); 29 | if ($cast(agent, get_parent()) && agent != null) begin 30 | vif = agent.vif; 31 | end 32 | else begin 33 | if (!uvm_config_db#(virtual apb_if)::get(this, "", "vif", vif)) begin 34 | `uvm_fatal("APB/DRV/NOVIF", "No virtual interface specified for this driver instance") 35 | end 36 | end 37 | endfunction 38 | 39 | //Run Phase 40 | //Implement the Driver -Sequencer API to get an item 41 | //Based on if it is Read/Write - drive on APB interface the corresponding pins 42 | virtual task run_phase(uvm_phase phase); 43 | super.run_phase(phase); 44 | this.vif.master_cb.psel <= '0; 45 | this.vif.master_cb.penable <= '0; 46 | 47 | forever begin 48 | apb_rw tr; 49 | @ (this.vif.master_cb); 50 | //First get an item from sequencer 51 | seq_item_port.get_next_item(tr); 52 | @ (this.vif.master_cb); 53 | uvm_report_info("APB_DRIVER ", $psprintf("Got Transaction %s",tr.convert2string())); 54 | //Decode the APB Command and call either the read/write function 55 | case (tr.apb_cmd) 56 | apb_rw::READ: drive_read(tr.addr, tr.data); 57 | apb_rw::WRITE: drive_write(tr.addr, tr.data); 58 | endcase 59 | //Handshake DONE back to sequencer 60 | seq_item_port.item_done(); 61 | end 62 | endtask: run_phase 63 | 64 | virtual protected task drive_read(input bit [31:0] addr, 65 | output logic [31:0] data); 66 | this.vif.master_cb.paddr <= addr; 67 | this.vif.master_cb.pwrite <= '0; 68 | this.vif.master_cb.psel <= '1; 69 | @ (this.vif.master_cb); 70 | this.vif.master_cb.penable <= '1; 71 | @ (this.vif.master_cb); 72 | data = this.vif.master_cb.prdata; 73 | this.vif.master_cb.psel <= '0; 74 | this.vif.master_cb.penable <= '0; 75 | endtask: drive_read 76 | 77 | virtual protected task drive_write(input bit [31:0] addr, 78 | input bit [31:0] data); 79 | this.vif.master_cb.paddr <= addr; 80 | this.vif.master_cb.pwdata <= data; 81 | this.vif.master_cb.pwrite <= '1; 82 | this.vif.master_cb.psel <= '1; 83 | @ (this.vif.master_cb); 84 | this.vif.master_cb.penable <= '1; 85 | @ (this.vif.master_cb); 86 | this.vif.master_cb.psel <= '0; 87 | this.vif.master_cb.penable <= '0; 88 | endtask: drive_write 89 | 90 | endclass: apb_master_drv 91 | 92 | //--------------------------------------------- 93 | // APB Sequencer Class 94 | // Derive form uvm_sequencer and parameterize to apb_rw sequence item 95 | //--------------------------------------------- 96 | class apb_sequencer extends uvm_sequencer #(apb_rw); 97 | 98 | `uvm_component_utils(apb_sequencer) 99 | 100 | function new(input string name, uvm_component parent=null); 101 | super.new(name, parent); 102 | endfunction : new 103 | 104 | endclass : apb_sequencer 105 | 106 | //----------------------------------------- 107 | // APB Monitor class 108 | //----------------------------------------- 109 | class apb_monitor extends uvm_monitor; 110 | 111 | virtual apb_if.passive vif; 112 | 113 | //Analysis port -parameterized to apb_rw transaction 114 | ///Monitor writes transaction objects to this port once detected on interface 115 | uvm_analysis_port#(apb_rw) ap; 116 | 117 | //config class handle 118 | apb_config cfg; 119 | 120 | `uvm_component_utils(apb_monitor) 121 | 122 | function new(string name, uvm_component parent = null); 123 | super.new(name, parent); 124 | ap = new("ap", this); 125 | endfunction: new 126 | 127 | //Build Phase - Get handle to virtual if from agent/config_db 128 | virtual function void build_phase(uvm_phase phase); 129 | apb_agent agent; 130 | if ($cast(agent, get_parent()) && agent != null) begin 131 | vif = agent.vif; 132 | end 133 | else begin 134 | virtual apb_if tmp; 135 | if (!uvm_config_db#(virtual apb_if)::get(this, "", "apb_if", tmp)) begin 136 | `uvm_fatal("APB/MON/NOVIF", "No virtual interface specified for this monitor instance") 137 | end 138 | vif = tmp; 139 | end 140 | endfunction 141 | 142 | virtual task run_phase(uvm_phase phase); 143 | super.run_phase(phase); 144 | forever begin 145 | apb_rw tr; 146 | // Wait for a SETUP cycle 147 | do begin 148 | @ (this.vif.monitor_cb); 149 | end 150 | while (this.vif.monitor_cb.psel !== 1'b1 || 151 | this.vif.monitor_cb.penable !== 1'b0); 152 | //create a transaction object 153 | tr = apb_rw::type_id::create("tr", this); 154 | 155 | //populate fields based on values seen on interface 156 | tr.apb_cmd = (this.vif.monitor_cb.pwrite) ? apb_rw::WRITE : apb_rw::READ; 157 | tr.addr = this.vif.monitor_cb.paddr; 158 | 159 | @ (this.vif.monitor_cb); 160 | if (this.vif.monitor_cb.penable !== 1'b1) begin 161 | `uvm_error("APB", "APB protocol violation: SETUP cycle not followed by ENABLE cycle"); 162 | end 163 | tr.data = (tr.apb_cmd == apb_rw::READ) ? this.vif.monitor_cb.prdata : '0; 164 | tr.data = (tr.apb_cmd == apb_rw::WRITE) ? this.vif.monitor_cb.pwdata : '0; 165 | uvm_report_info("APB_MONITOR", $psprintf("Got Transaction %s",tr.convert2string())); 166 | //Write to analysis port 167 | ap.write(tr); 168 | end 169 | endtask: run_phase 170 | 171 | endclass: apb_monitor 172 | 173 | `endif 174 | 175 | 176 | -------------------------------------------------------------------------------- /apb_project/apb_if.svh: -------------------------------------------------------------------------------- 1 | //------------------------------------ 2 | //APB (Advanced peripheral Bus) Interface 3 | // 4 | //------------------------------------ 5 | `ifndef APB_IF_SV 6 | `define APB_IF_SV 7 | 8 | interface apb_if(input bit pclk); 9 | wire [31:0] paddr; 10 | wire psel; 11 | wire penable; 12 | wire pwrite; 13 | wire [31:0] prdata; 14 | wire [31:0] pwdata; 15 | 16 | 17 | //Master Clocking block - used for Drivers 18 | clocking master_cb @(posedge pclk); 19 | output paddr, psel, penable, pwrite, pwdata; 20 | input prdata; 21 | endclocking: master_cb 22 | 23 | //Slave Clocking Block - used for any Slave BFMs 24 | clocking slave_cb @(posedge pclk); 25 | input paddr, psel, penable, pwrite, pwdata; 26 | output prdata; 27 | endclocking: slave_cb 28 | 29 | //Monitor Clocking block - For sampling by monitor components 30 | clocking monitor_cb @(posedge pclk); 31 | input paddr, psel, penable, pwrite, prdata, pwdata; 32 | endclocking: monitor_cb 33 | 34 | modport master(clocking master_cb); 35 | modport slave(clocking slave_cb); 36 | modport passive(clocking monitor_cb); 37 | 38 | endinterface: apb_if 39 | 40 | `endif 41 | -------------------------------------------------------------------------------- /apb_project/apb_rw.svh: -------------------------------------------------------------------------------- 1 | //------------------------------------ 2 | // Basic APB Read/Write Transaction class definition 3 | // This transaction will be used by Sequences, Drivers and Monitors 4 | //------------------------------------ 5 | `ifndef APB_RW_SV 6 | `define APB_RW_SV 7 | 8 | import uvm_pkg::*; 9 | 10 | //apb_rw sequence item derived from base uvm_sequence_item 11 | class apb_rw extends uvm_sequence_item; 12 | 13 | //typedef for READ/Write transaction type 14 | typedef enum {READ, WRITE} kind_e; 15 | rand bit [31:0] addr; //Address 16 | rand logic [31:0] data; //Data - For write or read response 17 | rand kind_e apb_cmd; //command type 18 | 19 | //Register with factory for dynamic creation 20 | `uvm_object_utils(apb_rw) 21 | 22 | 23 | function new (string name = "apb_rw"); 24 | super.new(name); 25 | endfunction 26 | 27 | function string convert2string(); 28 | return $psprintf("kind=%s addr=%0h data=%0h ",apb_cmd,addr,data); 29 | endfunction 30 | 31 | endclass: apb_rw 32 | 33 | `endif 34 | -------------------------------------------------------------------------------- /apb_project/apb_sequences.svh: -------------------------------------------------------------------------------- 1 | 2 | //A few flavours of apb sequences 3 | 4 | `ifndef APB_SEQUENCES_SV 5 | `define APB_SEQUENCES_SV 6 | 7 | //------------------------ 8 | //Base APB sequence derived from uvm_sequence and parameterized with sequence item of type apb_rw 9 | //------------------------ 10 | class apb_base_seq extends uvm_sequence#(apb_rw); 11 | 12 | `uvm_object_utils(apb_base_seq) 13 | 14 | function new(string name =""); 15 | super.new(name); 16 | endfunction 17 | 18 | 19 | //Main Body method that gets executed once sequence is started 20 | task body(); 21 | apb_rw rw_trans; 22 | //Create 10 random APB read/write transaction and send to driver 23 | repeat(10) begin 24 | rw_trans = apb_rw::type_id::create(.name("rw_trans"),.contxt(get_full_name())); 25 | start_item(rw_trans); 26 | assert (rw_trans.randomize()); 27 | finish_item(rw_trans); 28 | end 29 | endtask 30 | 31 | endclass 32 | 33 | 34 | 35 | `endif 36 | -------------------------------------------------------------------------------- /apb_project/apb_test.svh: -------------------------------------------------------------------------------- 1 | `ifndef APB_BASE_TEST_SV 2 | `define APB_BASE_TEST_SV 3 | 4 | //-------------------------------------------------------- 5 | //Top level Test class that instantiates env, configures and starts stimulus 6 | //-------------------------------------------------------- 7 | class apb_base_test extends uvm_test; 8 | 9 | //Register with factory 10 | `uvm_component_utils(apb_base_test); 11 | 12 | apb_env env; 13 | apb_config cfg; 14 | virtual apb_if vif; 15 | 16 | function new(string name = "apb_base_test", uvm_component parent = null); 17 | super.new(name, parent); 18 | endfunction 19 | 20 | //Build phase - Construct the cfg and env class using factory 21 | //Get the virtual interface handle from Test and then set it config db for the env component 22 | function void build_phase(uvm_phase phase); 23 | cfg = apb_config::type_id::create("cfg", this); 24 | env = apb_env::type_id::create("env", this); 25 | // 26 | if (!uvm_config_db#(virtual apb_if)::get(this, "", "vif", vif)) begin 27 | `uvm_fatal("APB/DRV/NOVIF", "No virtual interface specified for this test instance") 28 | end 29 | uvm_config_db#(virtual apb_if)::set( this, "env", "vif", vif); 30 | endfunction 31 | 32 | //Run phase - Create an abp_sequence and start it on the apb_sequencer 33 | task run_phase( uvm_phase phase ); 34 | apb_base_seq apb_seq; 35 | apb_seq = apb_base_seq::type_id::create("apb_seq"); 36 | phase.raise_objection( this, "Starting apb_base_seqin main phase" ); 37 | $display("%t Starting sequence apb_seq run_phase",$time); 38 | apb_seq.start(env.agt.sqr); 39 | #100ns; 40 | phase.drop_objection( this , "Finished apb_seq in main phase" ); 41 | endtask: run_phase 42 | 43 | 44 | endclass 45 | 46 | 47 | `endif 48 | -------------------------------------------------------------------------------- /apb_project/testbench.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------- 2 | // Top level Test module 3 | // Includes all env component and sequences files 4 | // (you could ideally create an env package and import that as well instead of including) 5 | //------------------------------------------- 6 | 7 | import uvm_pkg::*; 8 | `include "uvm_macros.svh" 9 | 10 | //Include all files 11 | `include "apb_if.svh" 12 | `include "apb_rw.svh" 13 | `include "apb_driver_seq_mon.svh" 14 | `include "apb_agent_env_config.svh" 15 | `include "apb_sequences.svh" 16 | `include "apb_test.svh" 17 | 18 | //-------------------------------------------------------- 19 | //Top level module that instantiates just a physical apb interface 20 | //No real DUT or APB slave as of now 21 | //-------------------------------------------------------- 22 | module test; 23 | 24 | logic pclk; 25 | 26 | logic [31:0] paddr; 27 | logic psel; 28 | logic penable; 29 | logic pwrite; 30 | logic [31:0] prdata; 31 | logic [31:0] pwdata; 32 | 33 | initial begin 34 | pclk=0; 35 | end 36 | 37 | //Generate a clock 38 | always begin 39 | #10 pclk = ~pclk; 40 | end 41 | 42 | //Instantiate a physical interface for APB interface 43 | apb_if apb_if(.pclk(pclk)); 44 | 45 | initial begin 46 | //Pass this physical interface to test top (which will further pass it down to env->agent->drv/sqr/mon 47 | uvm_config_db#(virtual apb_if)::set( null, "uvm_test_top", "vif", apb_if); 48 | //Call the test - but passing run_test argument as test class name 49 | //Another option is to not pass any test argument and use +UVM_TEST on command line to sepecify which test to run 50 | run_test("apb_base_test"); 51 | end 52 | 53 | 54 | endmodule 55 | 56 | 57 | -------------------------------------------------------------------------------- /course_examples/bus_sequence_item_eg.svh: -------------------------------------------------------------------------------- 1 | //Example Bus Sequence Item 2 | class bus_seq_item extends uvm_sequence_item; 3 | 4 | // Request data properties are rand 5 | rand logic[31:0] addr; 6 | rand logic[31:0] write_data; 7 | rand bit read_not_write; 8 | rand int delay; 9 | 10 | // Response data properties are NOT rand 11 | bit error; 12 | logic[31:0] read_data; 13 | 14 | //Factory registeration 15 | `uvm_object_utils(bus_seq_item) 16 | 17 | function new(string name = "bus_seq_item"); 18 | super.new(name); 19 | endfunction 20 | 21 | // Delay between bus cycles is in a sensible range 22 | constraint at_least_1 { delay inside {[1:20]};} 23 | // 32 bit aligned transfers 24 | constraint align_32 {addr[1:0] == 0; 25 | 26 | // do_copy method: 27 | function void do_copy(uvm_object rhs); 28 | bus_item rhs_; 29 | if(!$cast(rhs_, rhs)) begin 30 | uvm_report_error("do_copy:", "Cast failed"); 31 | return; 32 | end 33 | super.do_copy(rhs); // Chain the copy with parent classes 34 | delay = rhs_.delay; 35 | addr = rhs_.addr; 36 | op_code = rhs_.op_code; 37 | slave_name = rhs_.slave_name; 38 | data = rhs_.data; 39 | response = rhs_.response; 40 | endfunction: do_copy 41 | 42 | // do_compare implementation: 43 | function bit do_compare(uvm_object rhs, uvm_comparer comparer); 44 | bus_item rhs_; 45 | // If the cast fails, comparison has also failed 46 | // A check for null is not needed because that is done in the compare() 47 | // function which calls do_compare() 48 | if(!$cast(rhs_, rhs)) begin 49 | return 0; 50 | end 51 | return((super.do_compare(rhs, comparer) && 52 | (delay == rhs_.delay) && 53 | (addr == rhs.addr) && 54 | (op_code == rhs_.op_code) && 55 | (slave_name == rhs_.slave_name) && 56 | (data == rhs_.data) && 57 | (response == rhs_.response)); 58 | endfunction: do_compare 59 | 60 | 61 | // Implementation example: 62 | function string convert2string(); 63 | string s; 64 | s = super.convert2string(); 65 | // Note the use of \t (tab) and \n (newline) to format the data in columns 66 | // The enumerated op_code types .name() method returns a string corresponding to its value 67 | $sformat(s, "%s\n delay \t%0d\n addr \t%0h\n op_code \t%s\n slave_name \t%s\n", 68 | s, delay, addr, op_code.name(), slave_name); 69 | // For an array we need to iterate through the values: 70 | foreach(data[i]) begin 71 | $sformat(s, "%s data[%0d] \t%0h\n", s, i, data[i]); 72 | end 73 | $sformat(s, "%s response \t%0b\n", s, response); 74 | return s; 75 | endfunction: convert2string 76 | 77 | 78 | endclass: bus_seq_item 79 | 80 | -------------------------------------------------------------------------------- /course_examples/simple_agent.svh: -------------------------------------------------------------------------------- 1 | class simple_agent extends uvm_agent; 2 | 3 | uvm_active_passive_enum is_active; 4 | // Constructor and UVM automation macros 5 | simple_sequencer sequencer; 6 | simple_driver driver; 7 | simple_monitor monitor; 8 | 9 | // Use build() phase to create agents's subcomponents. 10 | virtual function void build_phase(uvm_phase phase); 11 | super.build_phase(phase) 12 | monitor = simple_monitor::type_id::create("monitor",this); 13 | if (is_active == UVM_ACTIVE) begin 14 | // Build the sequencer and driver. 15 | sequencer = simple_sequencer::type_id::create("sequencer",this); 16 | driver = simple_driver::type_id::create("driver",this); 17 | end 18 | endfunction : build_phase 19 | 20 | //Use connect phase to connect components together 21 | virtual function void connect_phase(uvm_phase phase); 22 | if(is_active == UVM_ACTIVE) begin 23 | driver.seq_item_port.connect(sequencer.seq_item_export); 24 | end 25 | endfunction : connect_phase 26 | 27 | endclass : simple_agent 28 | -------------------------------------------------------------------------------- /course_examples/simple_build_config_eg.svh: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------- 2 | //This is a pseudo code example for how build flow works form a test class down to env and to agents and sub components 3 | //This code also demonstrates how to use configuration objects to configure parameters for each component 4 | //and how to build first level of hierarchy. 5 | // 6 | // Before referencing this - it might be also good to refer to the simple case with no configs (simple_build_test.svh) 7 | //------------------------------------------------------------------------------ 8 | 9 | class spi_test_base extends uvm_test; 10 | // UVM Factory Registration Macro 11 | `uvm_component_utils(spi_test_base) 12 | //------------------------------------------ 13 | // Data Members 14 | //------------------------------------------ 15 | //------------------------------------------ 16 | // Component Members 17 | //------------------------------------------ 18 | 19 | // The environment class 20 | spi_env m_env; 21 | // Configuration objects 22 | spi_env_config m_env_cfg; 23 | apb_agent_config m_apb_cfg; 24 | spi_agent_config m_spi_cfg; 25 | 26 | // Build the env, create the env configuration 27 | // including any sub configurations and assigning virtual interfaces 28 | function void build_phase( uvm_phase phase ); 29 | // Create env configuration object 30 | m_env_cfg = spi_env_config::type_id::create("m_env_cfg"); 31 | // Call function to configure the env 32 | configure_env(m_env_cfg); 33 | // Create apb agent configuration object 34 | m_apb_cfg = apb_agent_config::type_id::create("m_apb_cfg"); 35 | // Call function to configure the apb_agent 36 | configure_apb_agent(m_apb_cfg); 37 | // Adding the apb virtual interface: 38 | if( !uvm_config_db #( virtual apb3_if )::get(this, "" , "APB_vif",m_apb_cfg.APB) ) 39 | `uvm_error(...) 40 | // Assign the apb_angent config handle inside the env_config: 41 | m_env_cfg.m_apb_agent_cfg = m_apb_cfg; 42 | // Repeated for the spi configuration object 43 | m_spi_cfg = spi_agent_config::type_id::create("m_spi_cfg"); 44 | configure_spi_agent(m_spi_cfg); 45 | if( !uvm_config_db #( virtual apb3_if )::get(this, "" , "SPIvif",m_spi_cfg.SPI) ) 46 | `uvm_error(...) 47 | m_env_cfg.m_spi_agent_cfg = m_spi_cfg; 48 | // Now env config is complete set it into config space: 49 | uvm_config_db #( spi_env_config )::set( this , "*m_spi_agent*", "spi_env_config", m_env_cfg) ); 50 | // Now we are ready to build the spi_env: 51 | m_env = spi_env::type_id::create("m_env", this); 52 | 53 | endfunction: build_phase 54 | 55 | //configure env config - can extend in derived tests 56 | function void configure_env(spi_env_config cfg); 57 | cfg.has_functional_coverage = 1; 58 | cfg.has_reg_scoreboard = 0; 59 | cfg.has_spi_scoreboard = 1; 60 | endfunction: configure_env 61 | 62 | 63 | // Convenience function to configure the apb agent 64 | // This can also be extended by derived classes 65 | function void configure_apb_agent(apb_agent_config cfg); 66 | cfg.active = UVM_ACTIVE; 67 | cfg.has_functional_coverage = 0; 68 | cfg.has_scoreboard = 0; 69 | endfunction: configure_apb_agent 70 | 71 | endclass: spi_test_base 72 | 73 | //--------------------------------------------------- 74 | // Env Config Class 75 | //--------------------------------------------------- 76 | class spi_env_config extends uvm_object; 77 | // UVM Factory Registration Macro 78 | `uvm_object_utils(spi_env_config) 79 | //------------------------------------------ 80 | // Data Members 81 | //------------------------------------------ 82 | // Whether env analysis components are used: 83 | bit has_functional_coverage = 1; 84 | bit has_reg_scoreboard = 0; 85 | bit has_spi_scoreboard = 1; 86 | 87 | //Configurations for the sub_components 88 | //APB Agent Config 89 | apb_config m_apb_agent_cfg; 90 | // SPI Agent Config 91 | spi_agent_config m_spi_agent_cfg; 92 | 93 | function new(string name = "spi_env_config"); 94 | super.new(name); 95 | endfunction 96 | 97 | endclass: spi_env_config 98 | 99 | endclass: spi_env_config 100 | -------------------------------------------------------------------------------- /course_examples/simple_build_test.svh: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------- 2 | //This is a pseudo code example for how build flow works form a test class down to env and to agents and sub components 3 | //This is a simplest example with no config objects to start with 4 | // 5 | //Once you get this concept and understand config object - it might be also good to refer to the 6 | //similar example with config objects as well (simple_build_config.svh) 7 | //------------------------------------------------------------------------------ 8 | 9 | class spi_test_base extends uvm_test; 10 | // UVM Factory Registration Macro 11 | `uvm_component_utils(spi_test_base) 12 | //------------------------------------------ 13 | // Data Members 14 | //------------------------------------------ 15 | //------------------------------------------ 16 | // Component Members 17 | //------------------------------------------ 18 | 19 | // The environment class 20 | spi_env m_env; 21 | 22 | // Build the env, 23 | function void build_phase( uvm_phase phase ); 24 | // Now we are ready to build the spi_env: 25 | m_env = spi_env::type_id::create("m_env", this); 26 | endfunction: build_phase 27 | 28 | endclass: spi_test_base 29 | 30 | -------------------------------------------------------------------------------- /course_examples/simple_driver.svh: -------------------------------------------------------------------------------- 1 | class simple_driver extends uvm_driver #(simple_item); 2 | simple_item s_item; 3 | virtual dut_if vif; 4 | 5 | // UVM automation macros for general components 6 | `uvm_component_utils(simple_driver) 7 | // Constructor 8 | function new (string name = "simple_driver", uvm_component parent); 9 | super.new(name, parent); 10 | endfunction : new 11 | 12 | function void build_phase(uvm_phase phase); 13 | string inst_name; 14 | super.build_phase(phase); 15 | if(!uvm_config_db#(virtual dut_if)::get(this,"","vif",vif)) begin 16 | `uvm_fatal("NOVIF", {"virtual interface must be set for: ", get_full_name(),".vif"}); 17 | end 18 | endfunction : build_phase 19 | 20 | task run_phase(uvm_phase phase); 21 | forever begin 22 | // Get the next data item from sequencer (may block). 23 | seq_item_port.get_next_item(s_item); 24 | // Execute the item. 25 | drive_item(s_item); 26 | seq_item_port.item_done(); // Consume the request. 27 | end 28 | endtask : run 29 | 30 | task drive_item (input simple_item item); 31 | // Add your logic here. 32 | endtask : drive_item 33 | 34 | endclass : simple_driver 35 | -------------------------------------------------------------------------------- /course_examples/simple_driver_response.svh: -------------------------------------------------------------------------------- 1 | //Note - a seperate response type 2 | //Byt default - response and request type are assumed same if not provided 3 | class simple_driver extends uvm_driver #(simple_item, simple_rsp); 4 | simple_item s_item; 5 | virtual dut_if vif; 6 | 7 | // UVM automation macros for general components 8 | `uvm_component_utils(simple_driver) 9 | // Constructor 10 | function new (string name = "simple_driver", uvm_component parent); 11 | super.new(name, parent); 12 | endfunction : new 13 | 14 | function void build_phase(uvm_phase phase); 15 | string inst_name; 16 | super.build_phase(phase); 17 | if(!uvm_config_db#(virtual dut_if)::get(this,"","vif",vif)) begin 18 | `uvm_fatal("NOVIF", {"virtual interface must be set for: ", get_full_name(),".vif"}); 19 | end 20 | endfunction : build_phase 21 | 22 | task run_phase(uvm_phase phase); 23 | forever begin 24 | // Get the next data item from sequencer (may block). 25 | seq_item_port.get_next_item(s_item); 26 | fork begin 27 | // Execute the item. 28 | drive_and_respond(s_item); 29 | end 30 | join_none 31 | seq_item_port.item_done(); // Consume the request. 32 | end 33 | endtask : run 34 | 35 | task drive_item (input simple_item item); 36 | // Add your logic here. 37 | endtask : drive_item 38 | 39 | endclass : simple_driver 40 | -------------------------------------------------------------------------------- /course_examples/simple_monitor.svh: -------------------------------------------------------------------------------- 1 | class master_monitor extends uvm_monitor; 2 | virtual bus_if xmi; // SystemVerilog virtual interface 3 | bit checks_enable = 1; // Control checking in monitor and interface. 4 | 5 | bit coverage_enable = 1; // Control coverage in monitor and interface. 6 | 7 | uvm_analysis_port #(simple_item) item_collected_port; 8 | 9 | event cov_transaction; // Events needed to trigger covergroups 10 | 11 | protected simple_item trans_collected; 12 | 13 | uvm_component_utils_begin(master_monitor) 14 | `uvm_field_int(checks_enable, UVM_ALL_ON) 15 | `uvm_field_int(coverage_enable, UVM_ALL_ON) 16 | uvm_component_utils_end 17 | 18 | covergroup cov_trans @cov_transaction; 19 | option.per_instance = 1; 20 | // Coverage bins definition 21 | endgroup : cov_trans 22 | 23 | function new (string name, uvm_component parent); 24 | super.new(name, parent); 25 | cov_trans = new(); 26 | cov_trans.set_inst_name({get_full_name(), ".cov_trans"}); 27 | trans_collected = new(); 28 | item_collected_port = new("item_collected_port", this); 29 | endfunction : new 30 | 31 | virtual task run_phase(uvm_phase phase); 32 | fork 33 | collect_transactions(); // Spawn collector task. 34 | join 35 | endtask : run 36 | 37 | virtual protected task collect_transactions(); 38 | forever begin @(posedge xmi.sig_clock); 39 | // Collect the data from the bus into trans_collected. 40 | if (checks_enable) 41 | perform_transfer_checks(); 42 | if (coverage_enable) 43 | perform_transfer_coverage(); 44 | item_collected_port.write(trans_collected); 45 | end 46 | endtask : collect_transactions 47 | 48 | virtual protected function void perform_transfer_coverage(); 49 | -> cov_transaction; 50 | endfunction : perform_transfer_coverage 51 | 52 | virtual protected function void perform_transfer_checks(); 53 | // Perform data checks on trans_collected. 54 | endfunction : perform_transfer_checks 55 | 56 | endclass : master_monitor 57 | -------------------------------------------------------------------------------- /course_examples/simple_sequencer.svh: -------------------------------------------------------------------------------- 1 | class simple_sequencer extends uvm_sequencer #(simple_item, simple_rsp); 2 | 3 | `uvm_component_utils(simple_sequencer); 4 | 5 | function new (input string name, uvm_component parent=null)' 6 | super.new(name, parent); 7 | endfunction 8 | 9 | endclass : simple_sequencer 10 | -------------------------------------------------------------------------------- /course_examples/simple_tb_top_eg.svh: -------------------------------------------------------------------------------- 1 | 2 | //Example to illustrate a testbench top example with DUT connections 3 | module top_tb; 4 | `include "timescale.v" 5 | import uvm_pkg::*; 6 | import spi_test_lib_pkg::*; 7 | 8 | // PCLK and PRESETn 9 | logic PCLK; 10 | logic PRESETn; 11 | 12 | // Instantiate the interfaces: 13 | apb_if APB(PCLK, PRESETn); // APB interface 14 | spi_if SPI(); // SPI Interface 15 | intr_if INTR(); // Interrupt 16 | 17 | //Instantiate DUT 18 | spi_top DUT( 19 | // APB Interface: 20 | .PCLK(PCLK), 21 | .PRESETN(PRESETn), 22 | .PSEL(APB.PSEL[0]), 23 | .PADDR(APB.PADDR[4:0]), 24 | .PWDATA(APB.PWDATA), 25 | .PRDATA(APB.PRDATA), 26 | .PENABLE(APB.PENABLE), 27 | .PREADY(APB.PREADY), 28 | .PSLVERR(), 29 | .PWRITE(APB.PWRITE), 30 | // Interrupt output 31 | .IRQ(INTR.IRQ), 32 | // SPI signals 33 | .ss_pad_o(SPI.cs), 34 | .sclk_pad_o(SPI.clk), 35 | .mosi_pad_o(SPI.mosi), 36 | .miso_pad_i(SPI.miso) 37 | ); 38 | 39 | // UVM initial block: 40 | // Virtual interface wrapping & run_test() 41 | initial begin 42 | uvm_config_db #(virtual apb_if)::set( null , "uvm_test_top" , "APB_vif" , APB); 43 | uvm_config_db #(virtual spi_if)::set( null , "uvm_test_top" , "SPI_vif" , SPI); 44 | uvm_config_db #(virtual intr_if)::set( null , "uvm_test_top" , "INTR_vif", INTR); 45 | run_test(); 46 | end 47 | 48 | // Clock and reset initial block: 49 | // 50 | initial begin 51 | PCLK = 0; 52 | PRESETn = 0; 53 | repeat(8) begin 54 | #10ns PCLK = ~PCLK; 55 | end 56 | PRESETn = 1; 57 | forever begin 58 | #10ns PCLK = ~PCLK; 59 | end 60 | end 61 | 62 | endmodule: top_tb 63 | -------------------------------------------------------------------------------- /uvm_report_catcher/env.svh: -------------------------------------------------------------------------------- 1 | //--------------------------------- 2 | // Using custom UVM Report Catcher to demote messages. 3 | // Demote using Component ID/ Message string with regex. 4 | // 5 | // - Mayur Kubavat 6 | //-------------------------------- 7 | 8 | class env extends uvm_env; 9 | `uvm_component_utils(env) 10 | 11 | function new(string name, uvm_component parent); 12 | super.new(name, parent); 13 | endfunction 14 | 15 | 16 | task run_phase(uvm_phase phase); 17 | 18 | #1; 19 | 20 | `uvm_error("MYENV", "error message 1) from env..") 21 | 22 | #50; 23 | 24 | `uvm_error("MYENV", "error message 2) from env..") 25 | 26 | #50; 27 | 28 | `uvm_error("MYENV", "error message 3) from env..") 29 | 30 | endtask 31 | 32 | endclass 33 | 34 | -------------------------------------------------------------------------------- /uvm_report_catcher/report_catcher.svh: -------------------------------------------------------------------------------- 1 | //--------------------------------- 2 | // Using custom UVM Report Catcher to demote messages. 3 | // Demote using Component ID/ Message string with regex. 4 | // 5 | // - Mayur Kubavat 6 | //-------------------------------- 7 | 8 | class report_catcher extends uvm_report_catcher; 9 | 10 | local string demoted_messages[$]; 11 | 12 | function new(string name); 13 | super.new(name); 14 | endfunction 15 | 16 | 17 | function action_e catch(); 18 | 19 | // Use this for message demote using component ID 20 | //|if(get_severity() == UVM_ERROR && get_id() == "MYENV") 21 | //| set_severity(UVM_INFO); 22 | 23 | if(get_severity() == UVM_ERROR) 24 | begin 25 | string my_message = get_message(); 26 | 27 | foreach(demoted_messages[msg]) 28 | begin 29 | // Use string match with regular expression. 30 | // Return Code == 0 is success. 31 | if(uvm_re_match(demoted_messages[msg], my_message) == 0) 32 | begin 33 | $display("Message in Demote List. Changing severity of message [%s]", my_message); 34 | set_severity(UVM_INFO); 35 | end 36 | end 37 | end 38 | 39 | return THROW; 40 | endfunction 41 | 42 | 43 | // Store messages to be demoted in regex/ full string 44 | function void demote_message(string d_message); 45 | demoted_messages.push_back(d_message); 46 | endfunction 47 | 48 | endclass 49 | 50 | -------------------------------------------------------------------------------- /uvm_report_catcher/sim/report_inc.f: -------------------------------------------------------------------------------- 1 | #+incdir+$UVM_HOME 2 | 3 | #$UVM_HOME/uvm_pkg.sv 4 | 5 | +incdir+../ 6 | 7 | ../top.sv 8 | -------------------------------------------------------------------------------- /uvm_report_catcher/sim/run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from subprocess import call 4 | from os import system 5 | 6 | import argparse 7 | 8 | #Get command line options 9 | parser = argparse.ArgumentParser(description='') 10 | 11 | #Get options from command 12 | parser.add_argument('--clean', action='store_true', help='Clean LOGs..') 13 | 14 | args = parser.parse_args() 15 | 16 | 17 | def create_lib(): 18 | system('vlib work') 19 | system('vmap work work') 20 | 21 | def compile_files(): 22 | system('vlog -work work -f report_inc.f') # +define+UVM_NO_DPI') 23 | 24 | def simulate(): 25 | system('vsim work.top -c -do "run -all; exit;"') 26 | 27 | 28 | def clean(): 29 | system('rm -r modelsim.ini transcript vsim.wlf work') 30 | 31 | 32 | def main(): 33 | if args.clean: 34 | clean() 35 | else: 36 | create_lib() 37 | compile_files() 38 | simulate() 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | 44 | -------------------------------------------------------------------------------- /uvm_report_catcher/test.svh: -------------------------------------------------------------------------------- 1 | //--------------------------------- 2 | // Using custom UVM Report Catcher to demote messages. 3 | // Demote using Component ID/ Message string with regex. 4 | // 5 | // - Mayur Kubavat 6 | //-------------------------------- 7 | 8 | class test extends uvm_test; 9 | `uvm_component_utils(test) 10 | 11 | 12 | env m_env; 13 | report_catcher m_report_catcher; 14 | 15 | function new(string name, uvm_component parent); 16 | super.new(name, parent); 17 | endfunction 18 | 19 | 20 | function void build_phase(uvm_phase phase); 21 | m_env = env::type_id::create("m_env", this); 22 | endfunction 23 | 24 | 25 | task run_phase(uvm_phase phase); 26 | phase.raise_objection(this); 27 | 28 | m_report_catcher = new("m_report_catcher"); 29 | m_report_catcher.demote_message("error message 2) from e.*"); 30 | 31 | // Register our report catcher for ENV component 32 | uvm_report_cb::add(m_env, m_report_catcher); 33 | 34 | #100; 35 | 36 | uvm_report_cb::delete(m_env, m_report_catcher); 37 | //void'(m_report_catcher.callback_mode(0)); 38 | 39 | #100; 40 | phase.drop_objection(this); 41 | endtask 42 | 43 | endclass 44 | 45 | -------------------------------------------------------------------------------- /uvm_report_catcher/top.sv: -------------------------------------------------------------------------------- 1 | //--------------------------------- 2 | // Using custom UVM Report Catcher to demote messages. 3 | // Demote using Component ID/ Message string with regex. 4 | // 5 | // - Mayur Kubavat 6 | //-------------------------------- 7 | 8 | module top; 9 | 10 | import uvm_pkg::*; 11 | `include "uvm_macros.svh" 12 | 13 | // Custom Report Catcher 14 | `include "report_catcher.svh" 15 | 16 | // Env contains run_phase() to print messages 17 | `include "env.svh" 18 | 19 | // Test uses callback to register/remove custom report catcher 20 | `include "test.svh" 21 | 22 | 23 | 24 | initial 25 | begin 26 | run_test("test"); 27 | end 28 | 29 | endmodule 30 | 31 | --------------------------------------------------------------------------------