Initial commit
* Bare skeleton implementation of everything * Testbench builds with Verilator * Test runs
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| obj_dir | ||||
| runs | ||||
| logs | ||||
							
								
								
									
										117
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| # Logging control | ||||
| LOG_REDIR = >& | ||||
| TIME=/usr/bin/time --format "Elapsed: %E, Memory: %M KB [Swaps %W]" | ||||
|  | ||||
| # Makefile variables | ||||
| NUM_PROCS=$(shell nproc --all) | ||||
| PROJ_BASE=$(shell pwd) | ||||
|  | ||||
| # Make and run project | ||||
| UVM_HOME=$(HOME)/git/uvm-verilator | ||||
| PROJ=axi | ||||
|  | ||||
| SV_OUT=obj_dir/Vuvm_pkg__verFiles.dat | ||||
| SV_BUILD_LOG=logs/$(PROJ)_build_sv.log | ||||
|  | ||||
| CPP_OUT=$(PROJ).sim | ||||
| CPP_BUILD_LOG=logs/$(PROJ)_build_cpp.log | ||||
|  | ||||
| SIM_LOG=$(PROJ)_sim.log | ||||
|  | ||||
| SV_FILES=$(shell ls common/* src/*.sv tb/*.sv) | ||||
| SV_SRC=$(UVM_HOME)/src/uvm_pkg.sv common/common_pkg.sv src/design_pkg.sv tb/tb_types.sv tb/tb_pkg.sv | ||||
| DPI_SRC=$(UVM_HOME)/src/dpi/uvm_dpi.cc | ||||
| DPI_INC=-I/usr/share/verilator/include | ||||
| SV_DEPS=$(SV_FILES) | ||||
|  | ||||
| CPP_SRC=sim_$(PROJ).cpp | ||||
|  | ||||
| TIMESCALE= --timescale '1ns/1ns' | ||||
|  | ||||
| UVM_DEFINES=+define+UVM_NO_DPI \ | ||||
|             +define+UVM_REPORT_DISABLE_FILE_LINE | ||||
| DISABLED_WARNINGS=-Wno-WIDTHTRUNC  -Wno-WIDTHEXPAND \ | ||||
|                   -Wno-CASTCONST   -Wno-CONSTRAINTIGN \ | ||||
|                   -Wno-MISINDENT   -Wno-REALCVT \ | ||||
|                   -Wno-SYMRSVDWORD -Wno-CASEINCOMPLETE | ||||
|  | ||||
| BUILD_ARGS=-I$(UVM_HOME)/src -I. \ | ||||
|         -o $(PROJ).sim \ | ||||
|         -j $(NUM_PROCS) \ | ||||
|         --error-limit 10 \ | ||||
|         --timing $(TIMESCALE) \ | ||||
|         --trace \ | ||||
|         +define+SVA_ON \ | ||||
|         $(UVM_DEFINES) \ | ||||
|         $(DISABLED_WARNINGS) \ | ||||
|         +incdir+common +incdir+src +incdir+tb \ | ||||
|         $(SV_SRC) | ||||
|  | ||||
| ifndef TEST_NAME | ||||
|     TEST_NAME=test_basic | ||||
| endif | ||||
|  | ||||
| # | ||||
| # Full build to generate testbench executable (Default target) | ||||
| # | ||||
| build: build_cpp | ||||
| 	@echo "Build done" | ||||
|  | ||||
| prepare_area: | ||||
| 	$(info #----------------) | ||||
| 	$(info # Preparing area) | ||||
| 	$(info #----------------) | ||||
| 	@if [ ! -d $(PROJ_BASE)/logs ]; then mkdir -p $(PROJ_BASE)/logs; fi | ||||
|  | ||||
| # | ||||
| # C code generation from SystemVerilog | ||||
| # | ||||
| build_sv: prepare_area $(SV_OUT) | ||||
|  | ||||
| $(PROJ_BASE)/logs: | ||||
| 	@if [ ! -d $(PROJ_BASE)/logs ]; then mkdir -p $(PROJ_BASE)/logs; fi | ||||
|  | ||||
| $(SV_OUT): $(PROJ_BASE)/logs $(SV_DEPS) | ||||
| 	$(info #------------) | ||||
| 	$(info # Building SV) | ||||
| 	$(info #------------) | ||||
| 	@verilator --cc $(BUILD_ARGS) | ||||
|  | ||||
| # | ||||
| # C code build to generate testbench executable | ||||
| # | ||||
| build_cpp: build_sv $(CPP_OUT) | ||||
|  | ||||
| $(CPP_OUT): $(SV_OUT) | ||||
| 	$(info #-------------) | ||||
| 	$(info # Building CPP) | ||||
| 	$(info #-------------) | ||||
| 	@verilator --binary $(BUILD_ARGS) | ||||
|  | ||||
| # | ||||
| # Run just lint to detect syntax errors during development | ||||
| # | ||||
| lint: | ||||
| 	$(info #--------) | ||||
| 	$(info # Linting) | ||||
| 	$(info #--------) | ||||
| 	@verilator --lint-only $(BUILD_ARGS) | ||||
|  | ||||
| # | ||||
| # Run test. Use TEST_NAME=<test name> on make line to pick the test | ||||
| # | ||||
| run: $(CPP_OUT) | ||||
| 	$(info #---------------------) | ||||
| 	$(info # Running $(TEST_NAME)) | ||||
| 	$(info #---------------------) | ||||
| 	@if [ ! -d runs/$(TEST_NAME) ]; then mkdir -p runs/$(TEST_NAME); fi | ||||
| 	@cd runs/$(TEST_NAME) && \ | ||||
|         $(PROJ_BASE)/obj_dir/$(PROJ).sim +UVM_TESTNAME=$(TEST_NAME) +UVM_CONFIG_DB_TRACE |& tee $(SIM_LOG) | ||||
| 	notify-send "[$(PROJ)] Test run done" | ||||
|  | ||||
| # | ||||
| # Remove generated files | ||||
| # - This will not remove 'runs' directory that contains simulation run logs | ||||
| # | ||||
| clean: | ||||
| 	rm -rf obj_dir logs $(PROJ)*.log | ||||
							
								
								
									
										122
									
								
								Makefile.details
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								Makefile.details
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| # Logging control | ||||
| ifdef VERBOSE | ||||
| 	LOG_REDIR = |tee -a | ||||
| 	TIME=stdbuf -o 0 /usr/bin/time --format "Elapsed: %E, Memory: %M KB [Swaps %W]" | ||||
| else | ||||
| 	LOG_REDIR = >& | ||||
| 	TIME=/usr/bin/time --format "Elapsed: %E, Memory: %M KB [Swaps %W]" | ||||
| endif | ||||
|  | ||||
| # Makefile variables | ||||
| NUM_PROCS=$(shell nproc --all) | ||||
| PROJ_BASE=$(shell pwd) | ||||
|  | ||||
| # Make and run project | ||||
| UVM_HOME=$(HOME)/git/uvm-verilator | ||||
| PROJ=axi | ||||
|  | ||||
| SV_OUT=obj_dir/Vuvm_pkg__verFiles.dat | ||||
| SV_BUILD_LOG=logs/$(PROJ)_build_sv.log | ||||
|  | ||||
| CPP_OUT=$(PROJ).sim | ||||
| CPP_BUILD_LOG=logs/$(PROJ)_build_cpp.log | ||||
|  | ||||
| SIM_LOG=$(PROJ)_sim.log | ||||
|  | ||||
| SV_FILES=$(shell ls common/* src/*.sv tb/*.sv) | ||||
| SV_SRC=$(UVM_HOME)/src/uvm_pkg.sv common/common_pkg.sv src/design_pkg.sv tb/tb_types.sv tb/tb_pkg.sv | ||||
| DPI_SRC=$(UVM_HOME)/src/dpi/uvm_dpi.cc | ||||
| DPI_INC=-I/usr/share/verilator/include | ||||
| SV_DEPS=$(SV_FILES) | ||||
|  | ||||
| CPP_SRC=sim_$(PROJ).cpp | ||||
|  | ||||
| TIMESCALE= --timescale '1ns/1ns' | ||||
|  | ||||
| UVM_DEFINES=+define+UVM_NO_DPI \ | ||||
|             +define+UVM_REPORT_DISABLE_FILE_LINE | ||||
| DISABLED_WARNINGS=-Wno-WIDTHTRUNC  -Wno-WIDTHEXPAND \ | ||||
|                   -Wno-CASTCONST   -Wno-CONSTRAINTIGN \ | ||||
|                   -Wno-MISINDENT   -Wno-REALCVT \ | ||||
|                   -Wno-SYMRSVDWORD -Wno-CASEINCOMPLETE | ||||
|  | ||||
| BUILD_ARGS=-I$(UVM_HOME)/src -I. \ | ||||
|         -o $(PROJ).sim \ | ||||
|         -j $(NUM_PROCS) \ | ||||
|         --error-limit 10 \ | ||||
|         --timing $(TIMESCALE) \ | ||||
|         --trace \ | ||||
|         +define+SVA_ON \ | ||||
|         $(UVM_DEFINES) \ | ||||
|         $(DISABLED_WARNINGS) \ | ||||
|         +incdir+common +incdir+src +incdir+tb \ | ||||
|         $(SV_SRC) | ||||
|  | ||||
| ifndef TEST_NAME | ||||
|     TEST_NAME=test_basic | ||||
| endif | ||||
|  | ||||
| # | ||||
| # Full build to generate testbench executable (Default target) | ||||
| # | ||||
| build: build_cpp | ||||
| 	@echo "Build done" | ||||
|  | ||||
| prepare_area: | ||||
| 	$(info #----------------) | ||||
| 	$(info # Preparing area) | ||||
| 	$(info #----------------) | ||||
| 	@if [ ! -d $(PROJ_BASE)/logs ]; then mkdir -p $(PROJ_BASE)/logs; fi | ||||
|  | ||||
| # | ||||
| # C code generation from SystemVerilog | ||||
| # | ||||
| build_sv: prepare_area $(SV_OUT) | ||||
|  | ||||
| $(SV_OUT): $(PROJ_BASE)/logs $(SV_DEPS) | ||||
| 	$(info #------------) | ||||
| 	$(info # Building SV) | ||||
| 	$(info #------------) | ||||
| 	@$(TIME) verilator --cc $(BUILD_ARGS) $(LOG_REDIR) $(SV_BUILD_LOG) && \ | ||||
| 		tail -1 $(SV_BUILD_LOG) | ||||
|  | ||||
| # | ||||
| # C code build to generate testbench executable | ||||
| # | ||||
| build_cpp: build_sv $(CPP_OUT) | ||||
|  | ||||
| $(CPP_OUT): $(SV_OUT) | ||||
| 	$(info #-------------) | ||||
| 	$(info # Building CPP) | ||||
| 	$(info #-------------) | ||||
| 	@$(TIME) verilator --binary $(BUILD_ARGS) $(LOG_REDIR) $(CPP_BUILD_LOG) && \ | ||||
| 		tail -1 $(CPP_BUILD_LOG) && \ | ||||
| 		notify-send "[$(PROJ)] Build done" | ||||
|  | ||||
| # | ||||
| # Run just lint to detect syntax errors during development | ||||
| # | ||||
| lint: | ||||
| 	$(info #--------) | ||||
| 	$(info # Linting) | ||||
| 	$(info #--------) | ||||
| 	@$(TIME) verilator --lint-only $(BUILD_ARGS) | ||||
|  | ||||
| # | ||||
| # Run test. Use TEST_NAME=<test name> on make line to pick the test | ||||
| # | ||||
| run: $(CPP_OUT) | ||||
| 	$(info #---------------------) | ||||
| 	$(info # Running $(TEST_NAME)) | ||||
| 	$(info #---------------------) | ||||
| 	@if [ ! -d runs/$(TEST_NAME) ]; then mkdir -p runs/$(TEST_NAME); fi | ||||
| 	@cd runs/$(TEST_NAME) && \ | ||||
|         $(TIME) $(PROJ_BASE)/obj_dir/$(PROJ).sim +UVM_TESTNAME=$(TEST_NAME) |& tee $(SIM_LOG) | ||||
| 	@notify-send "[$(PROJ)] Test run done" | ||||
|  | ||||
| # | ||||
| # Remove generated files | ||||
| # - This will not remove 'runs' directory that contains simulation run logs | ||||
| # | ||||
| clean: | ||||
| 	rm -rf obj_dir logs $(PROJ)*.log | ||||
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| # AXI Protocol Playground | ||||
|  | ||||
| ## Introduction | ||||
|  | ||||
| * There is no RTL design here. Just validation components working as both | ||||
|   MANAGER and SUBORDINATE parts | ||||
|  | ||||
| ## Dependencies | ||||
|  | ||||
| * Verilator simulator | ||||
| * UVM that works with Verilator | ||||
|  | ||||
| ``` | ||||
| $ cd $UVM_HOME | ||||
| $ git remote -v | ||||
| origin  https://github.com/antmicro/uvm-verilator.git (fetch) | ||||
| origin  https://github.com/antmicro/uvm-verilator.git (push) | ||||
| $ git branch | ||||
|   current-patches | ||||
| * current-patches-2 | ||||
| ``` | ||||
							
								
								
									
										414
									
								
								common/axi.intf.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										414
									
								
								common/axi.intf.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,414 @@ | ||||
| // Generated AXI Interface | ||||
| // This file is automatically generated by scripts/gen_axi_intf.pl | ||||
| // Do not edit this file directly. | ||||
| // | ||||
| // Interface Name: AXI Signal List | ||||
| interface axi_intf #( | ||||
|     parameter                          ADDR_WIDTH = 1, | ||||
|     parameter                       ARSNOOP_WIDTH = 1, | ||||
|     parameter                         AWCMO_WIDTH = 1, | ||||
|     parameter                       AWSNOOP_WIDTH = 1, | ||||
|     parameter                         BRESP_WIDTH = 1, | ||||
|     parameter             CEIL_DATA_WIDTH_DIV_128 = 1, | ||||
|     parameter       CEIL_DATA_WIDTH_DIV_128_TMS_4 = 1, | ||||
|     parameter              CEIL_DATA_WIDTH_DIV_64 = 1, | ||||
|     parameter                          DATA_WIDTH = 1, | ||||
|     parameter                    DATA_WIDTH_DIV_8 = 1, | ||||
|     parameter                          ID_R_WIDTH = 1, | ||||
|     parameter                          ID_W_WIDTH = 1, | ||||
|     parameter                        LOOP_R_WIDTH = 1, | ||||
|     parameter                        LOOP_W_WIDTH = 1, | ||||
|     parameter                         MECID_WIDTH = 1, | ||||
|     parameter                          MPAM_WIDTH = 1, | ||||
|     parameter                     RCHUNKNUM_WIDTH = 1, | ||||
|     parameter                    RCHUNKSTRB_WIDTH = 1, | ||||
|     parameter                         RRESP_WIDTH = 1, | ||||
|     parameter                        SECSID_WIDTH = 1, | ||||
|     parameter                           SID_WIDTH = 1, | ||||
|     parameter                          SSID_WIDTH = 1, | ||||
|     parameter                      SUBSYSID_WIDTH = 1, | ||||
|     parameter SUM_USER_DATA_WIDTH_USER_RESP_WIDTH = 1, | ||||
|     parameter                     USER_DATA_WIDTH = 1, | ||||
|     parameter                      USER_REQ_WIDTH = 1, | ||||
|     parameter                     USER_RESP_WIDTH = 1 | ||||
| ) | ||||
|  | ||||
| ( | ||||
|     input ACLK, | ||||
|     input ARESETn | ||||
| ); | ||||
|  | ||||
|     // A2.4.1 Clock and reset signals | ||||
|     // External signal: ACLK;              // External Global clock signal [External] | ||||
|     // External signal: ARESETn;           // External Global reset signal [External] | ||||
|  | ||||
|     // A2.1.1 Write request channel | ||||
|     logic                                           AWVALID;           // Valid indicator [Manager] | ||||
|     logic                                           AWREADY;           // Ready indicator [Subordinate] | ||||
|     logic                          [ID_W_WIDTH-1:0] AWID;              // Transaction identifier for the write channels [Manager] | ||||
|     logic                          [ADDR_WIDTH-1:0] AWADDR;            // Transaction address [Manager] | ||||
|     logic                                     [3:0] AWREGION;          // Region identifier [Manager] | ||||
|     logic                                     [7:0] AWLEN;             // Transaction length [Manager] | ||||
|     logic                                     [2:0] AWSIZE;            // Transaction size [Manager] | ||||
|     logic                                     [1:0] AWBURST;           // Burst attribute [Manager] | ||||
|     logic                                           AWLOCK;            // Exclusive access indicator [Manager] | ||||
|     logic                                     [3:0] AWCACHE;           // Memory attributes [Manager] | ||||
|     logic                                     [2:0] AWPROT;            // Access attributes [Manager] | ||||
|     logic                                           AWNSE;             // Non-secure extension bit for RME [Manager] | ||||
|     logic                                     [3:0] AWQOS;             // QoS identifier [Manager] | ||||
|     logic                      [USER_REQ_WIDTH-1:0] AWUSER;            // User-defined extension to a request [Manager] | ||||
|     logic                                     [1:0] AWDOMAIN;          // Shareability domain of a request [Manager] | ||||
|     logic                       [AWSNOOP_WIDTH-1:0] AWSNOOP;           // Write request opcode [Manager] | ||||
|     logic                                    [10:0] AWSTASHNID;        // Stash Node ID [Manager] | ||||
|     logic                                           AWSTASHNIDEN;      // Stash Node ID enable [Manager] | ||||
|     logic                                     [4:0] AWSTASHLPID;       // Stash Logical Processor ID [Manager] | ||||
|     logic                                           AWSTASHLPIDEN;     // Stash Logical Processor ID enable [Manager] | ||||
|     logic                                           AWTRACE;           // Trace signal [Manager] | ||||
|     logic                        [LOOP_W_WIDTH-1:0] AWLOOP;            // Loopback signals on the write channels [Manager] | ||||
|     logic                                           AWMMUVALID;        // MMU signal qualifier [Manager] | ||||
|     logic                        [SECSID_WIDTH-1:0] AWMMUSECSID;       // Secure Stream ID [Manager] | ||||
|     logic                           [SID_WIDTH-1:0] AWMMUSID;          // StreamID [Manager] | ||||
|     logic                                           AWMMUSSIDV;        // SubstreamID valid [Manager] | ||||
|     logic                          [SSID_WIDTH-1:0] AWMMUSSID;         // SubstreamID [Manager] | ||||
|     logic                                           AWMMUATST;         // Address translated indicator [Manager] | ||||
|     logic                                     [1:0] AWMMUFLOW;         // SMMU flow type [Manager] | ||||
|     logic                                     [3:0] AWPBHA;            // Page-based Hardware Attributes [Manager] | ||||
|     logic                                     [3:0] AWNSAID;           // Non-secure Access ID [Manager] | ||||
|     logic                      [SUBSYSID_WIDTH-1:0] AWSUBSYSID;        // Subsystem ID [Manager] | ||||
|     logic                                     [5:0] AWATOP;            // Atomic transaction opcode [Manager] | ||||
|     logic                          [MPAM_WIDTH-1:0] AWMPAM;            // MPAM information with a request [Manager] | ||||
|     logic                                           AWIDUNQ;           // Unique ID indicator [Manager] | ||||
|     logic                         [AWCMO_WIDTH-1:0] AWCMO;             // CMO type [Manager] | ||||
|     logic                                     [1:0] AWTAGOP;           // Memory Tag operation for write requests [Manager] | ||||
|     logic                         [MECID_WIDTH-1:0] AWMECID;           // Memory Encryption Context identifier [Manager] | ||||
|  | ||||
|     // A2.1.1 Write request channel | ||||
|     logic                                           WVALID;            // Valid indicator [Manager] | ||||
|     logic                                           WREADY;            // Ready indicator [Subordinate] | ||||
|     logic                          [DATA_WIDTH-1:0] WDATA;             // Write data [Manager] | ||||
|     logic                    [DATA_WIDTH_DIV_8-1:0] WSTRB;             // Write data strobes [Manager] | ||||
|     logic       [CEIL_DATA_WIDTH_DIV_128_TMS_4-1:0] WTAG;              // Memory Tag [Manager] | ||||
|     logic             [CEIL_DATA_WIDTH_DIV_128-1:0] WTAGUPDATE;        // Memory Tag update [Manager] | ||||
|     logic                                           WLAST;             // Last write data [Manager] | ||||
|     logic                     [USER_DATA_WIDTH-1:0] WUSER;             // User-defined extension to write data [Manager] | ||||
|     logic              [CEIL_DATA_WIDTH_DIV_64-1:0] WPOISON;           // Poison indicator [Manager] | ||||
|     logic                                           WTRACE;            // Trace signal [Manager] | ||||
|  | ||||
|     // A2.1.3 Write response channel | ||||
|     logic                                           BVALID;            // Valid indicator [Subordinate] | ||||
|     logic                                           BREADY;            // Ready indicator [Manager] | ||||
|     logic                          [ID_W_WIDTH-1:0] BID;               // Transaction identifier for the write channels [Subordinate] | ||||
|     logic                                           BIDUNQ;            // Unique ID indicator [Subordinate] | ||||
|     logic                         [BRESP_WIDTH-1:0] BRESP;             // Write response code [Subordinate] | ||||
|     logic                                           BCOMP;             // Completion response indicator [Subordinate] | ||||
|     logic                                           BPERSIST;          // Persist response [Subordinate] | ||||
|     logic                                     [1:0] BTAGMATCH;         // Memory Tag Match response [Subordinate] | ||||
|     logic                     [USER_RESP_WIDTH-1:0] BUSER;             // User-defined extension to a write response [Subordinate] | ||||
|     logic                                           BTRACE;            // Trace signal [Subordinate] | ||||
|     logic                        [LOOP_W_WIDTH-1:0] BLOOP;             // Loopback signals on the write channels [Subordinate] | ||||
|     logic                                     [1:0] BBUSY;             // Busy indicator [Subordinate] | ||||
|  | ||||
|     // A2.2.1 Read request channel | ||||
|     logic                                           ARVALID;           // Valid indicator [Manager] | ||||
|     logic                                           ARREADY;           // Ready indicator [Subordinate] | ||||
|     logic                          [ID_R_WIDTH-1:0] ARID;              // Transaction identifier for the read channels [Manager] | ||||
|     logic                          [ADDR_WIDTH-1:0] ARADDR;            // Transaction address [Manager] | ||||
|     logic                                     [3:0] ARREGION;          // Region identifier [Manager] | ||||
|     logic                                     [7:0] ARLEN;             // Transaction length [Manager] | ||||
|     logic                                     [2:0] ARSIZE;            // Transaction size [Manager] | ||||
|     logic                                     [1:0] ARBURST;           // Burst attribute [Manager] | ||||
|     logic                                           ARLOCK;            // Exclusive access indicator [Manager] | ||||
|     logic                                     [3:0] ARCACHE;           // Memory attributes [Manager] | ||||
|     logic                                     [2:0] ARPROT;            // Access attributes [Manager] | ||||
|     logic                                           ARNSE;             // Non-secure extension bit for RME [Manager] | ||||
|     logic                                     [3:0] ARQOS;             // QoS identifier [Manager] | ||||
|     logic                      [USER_REQ_WIDTH-1:0] ARUSER;            // User-defined extension to a request [Manager] | ||||
|     logic                                     [1:0] ARDOMAIN;          // Shareability domain of a request [Manager] | ||||
|     logic                       [ARSNOOP_WIDTH-1:0] ARSNOOP;           // Read request opcode [Manager] | ||||
|     logic                                           ARTRACE;           // Trace signal [Manager] | ||||
|     logic                        [LOOP_R_WIDTH-1:0] ARLOOP;            // Loopback signals on the read channels [Manager] | ||||
|     logic                                           ARMMUVALID;        // MMU signal qualifier [Manager] | ||||
|     logic                        [SECSID_WIDTH-1:0] ARMMUSECSID;       // Secure Stream ID [Manager] | ||||
|     logic                           [SID_WIDTH-1:0] ARMMUSID;          // StreamID [Manager] | ||||
|     logic                                           ARMMUSSIDV;        // SubstreamID valid [Manager] | ||||
|     logic                          [SSID_WIDTH-1:0] ARMMUSSID;         // SubstreamID [Manager] | ||||
|     logic                                           ARMMUATST;         // Address translated indicator [Manager] | ||||
|     logic                                     [1:0] ARMMUFLOW;         // SMMU flow type [Manager] | ||||
|     logic                                     [3:0] ARPBHA;            // Page-based Hardware Attributes [Manager] | ||||
|     logic                                     [3:0] ARNSAID;           // Non-secure Access ID [Manager] | ||||
|     logic                      [SUBSYSID_WIDTH-1:0] ARSUBSYSID;        // Subsystem ID [Manager] | ||||
|     logic                                           ARCHUNKEN;         // Read data chunking enable [Manager] | ||||
|     logic                                           ARIDUNQ;           // Unique ID indicator [Manager] | ||||
|     logic                                     [1:0] ARTAGOP;           // Memory Tag operation for read requests [Manager] | ||||
|     logic                         [MECID_WIDTH-1:0] ARMECID;           // Memory Encryption Context identifier [Manager] | ||||
|  | ||||
|     // A2.2.2 Read data channel | ||||
|     logic                                           RVALID;            // Valid indicator [Subordinate] | ||||
|     logic                                           RREADY;            // Ready indicator [Manager] | ||||
|     logic                          [ID_R_WIDTH-1:0] RID;               // Transaction identifier for the read channels [Subordinate] | ||||
|     logic                                           RIDUNQ;            // Unique ID indicator [Subordinate] | ||||
|     logic                          [DATA_WIDTH-1:0] RDATA;             // Read data [Subordinate] | ||||
|     logic       [CEIL_DATA_WIDTH_DIV_128_TMS_4-1:0] RTAG;              // Memory Tag [Subordinate] | ||||
|     logic                         [RRESP_WIDTH-1:0] RRESP;             // Read response [Subordinate] | ||||
|     logic                                           RLAST;             // Last read data [Subordinate] | ||||
|     logic [SUM_USER_DATA_WIDTH_USER_RESP_WIDTH-1:0] RUSER;             // User-defined extension to read data and response [Subordinate] | ||||
|     logic              [CEIL_DATA_WIDTH_DIV_64-1:0] RPOISON;           // Poison indicator [Subordinate] | ||||
|     logic                                           RTRACE;            // Trace signal [Subordinate] | ||||
|     logic                        [LOOP_R_WIDTH-1:0] RLOOP;             // Loopback signals on the read channels [Subordinate] | ||||
|     logic                                           RCHUNKV;           // Read data chunking valid [Subordinate] | ||||
|     logic                     [RCHUNKNUM_WIDTH-1:0] RCHUNKNUM;         // Read data chunk number [Subordinate] | ||||
|     logic                    [RCHUNKSTRB_WIDTH-1:0] RCHUNKSTRB;        // Read data chunk strobe [Subordinate] | ||||
|     logic                                     [1:0] RBUSY;             // Busy indicator [Subordinate] | ||||
|  | ||||
|     // Modport for Manager role | ||||
|     modport MANAGER ( | ||||
|  | ||||
|         // A2.4.1 Clock and reset signals | ||||
|         input    ACLK, | ||||
|         input    ARESETn, | ||||
|  | ||||
|         // A2.1.1 Write request channel | ||||
|         output   AWVALID, | ||||
|         input    AWREADY, | ||||
|         output   AWID, | ||||
|         output   AWADDR, | ||||
|         output   AWREGION, | ||||
|         output   AWLEN, | ||||
|         output   AWSIZE, | ||||
|         output   AWBURST, | ||||
|         output   AWLOCK, | ||||
|         output   AWCACHE, | ||||
|         output   AWPROT, | ||||
|         output   AWNSE, | ||||
|         output   AWQOS, | ||||
|         output   AWUSER, | ||||
|         output   AWDOMAIN, | ||||
|         output   AWSNOOP, | ||||
|         output   AWSTASHNID, | ||||
|         output   AWSTASHNIDEN, | ||||
|         output   AWSTASHLPID, | ||||
|         output   AWSTASHLPIDEN, | ||||
|         output   AWTRACE, | ||||
|         output   AWLOOP, | ||||
|         output   AWMMUVALID, | ||||
|         output   AWMMUSECSID, | ||||
|         output   AWMMUSID, | ||||
|         output   AWMMUSSIDV, | ||||
|         output   AWMMUSSID, | ||||
|         output   AWMMUATST, | ||||
|         output   AWMMUFLOW, | ||||
|         output   AWPBHA, | ||||
|         output   AWNSAID, | ||||
|         output   AWSUBSYSID, | ||||
|         output   AWATOP, | ||||
|         output   AWMPAM, | ||||
|         output   AWIDUNQ, | ||||
|         output   AWCMO, | ||||
|         output   AWTAGOP, | ||||
|         output   AWMECID, | ||||
|  | ||||
|         // A2.1.1 Write request channel | ||||
|         output   WVALID, | ||||
|         input    WREADY, | ||||
|         output   WDATA, | ||||
|         output   WSTRB, | ||||
|         output   WTAG, | ||||
|         output   WTAGUPDATE, | ||||
|         output   WLAST, | ||||
|         output   WUSER, | ||||
|         output   WPOISON, | ||||
|         output   WTRACE, | ||||
|  | ||||
|         // A2.1.3 Write response channel | ||||
|         input    BVALID, | ||||
|         output   BREADY, | ||||
|         input    BID, | ||||
|         input    BIDUNQ, | ||||
|         input    BRESP, | ||||
|         input    BCOMP, | ||||
|         input    BPERSIST, | ||||
|         input    BTAGMATCH, | ||||
|         input    BUSER, | ||||
|         input    BTRACE, | ||||
|         input    BLOOP, | ||||
|         input    BBUSY, | ||||
|  | ||||
|         // A2.2.1 Read request channel | ||||
|         output   ARVALID, | ||||
|         input    ARREADY, | ||||
|         output   ARID, | ||||
|         output   ARADDR, | ||||
|         output   ARREGION, | ||||
|         output   ARLEN, | ||||
|         output   ARSIZE, | ||||
|         output   ARBURST, | ||||
|         output   ARLOCK, | ||||
|         output   ARCACHE, | ||||
|         output   ARPROT, | ||||
|         output   ARNSE, | ||||
|         output   ARQOS, | ||||
|         output   ARUSER, | ||||
|         output   ARDOMAIN, | ||||
|         output   ARSNOOP, | ||||
|         output   ARTRACE, | ||||
|         output   ARLOOP, | ||||
|         output   ARMMUVALID, | ||||
|         output   ARMMUSECSID, | ||||
|         output   ARMMUSID, | ||||
|         output   ARMMUSSIDV, | ||||
|         output   ARMMUSSID, | ||||
|         output   ARMMUATST, | ||||
|         output   ARMMUFLOW, | ||||
|         output   ARPBHA, | ||||
|         output   ARNSAID, | ||||
|         output   ARSUBSYSID, | ||||
|         output   ARCHUNKEN, | ||||
|         output   ARIDUNQ, | ||||
|         output   ARTAGOP, | ||||
|         output   ARMECID, | ||||
|  | ||||
|         // A2.2.2 Read data channel | ||||
|         input    RVALID, | ||||
|         output   RREADY, | ||||
|         input    RID, | ||||
|         input    RIDUNQ, | ||||
|         input    RDATA, | ||||
|         input    RTAG, | ||||
|         input    RRESP, | ||||
|         input    RLAST, | ||||
|         input    RUSER, | ||||
|         input    RPOISON, | ||||
|         input    RTRACE, | ||||
|         input    RLOOP, | ||||
|         input    RCHUNKV, | ||||
|         input    RCHUNKNUM, | ||||
|         input    RCHUNKSTRB, | ||||
|         input    RBUSY | ||||
|     ); | ||||
|  | ||||
|     // Modport for Subordinate role | ||||
|     modport SUBORDINATE ( | ||||
|  | ||||
|         // A2.4.1 Clock and reset signals | ||||
|         input    ACLK, | ||||
|         input    ARESETn, | ||||
|  | ||||
|         // A2.1.1 Write request channel | ||||
|         input    AWVALID, | ||||
|         output   AWREADY, | ||||
|         input    AWID, | ||||
|         input    AWADDR, | ||||
|         input    AWREGION, | ||||
|         input    AWLEN, | ||||
|         input    AWSIZE, | ||||
|         input    AWBURST, | ||||
|         input    AWLOCK, | ||||
|         input    AWCACHE, | ||||
|         input    AWPROT, | ||||
|         input    AWNSE, | ||||
|         input    AWQOS, | ||||
|         input    AWUSER, | ||||
|         input    AWDOMAIN, | ||||
|         input    AWSNOOP, | ||||
|         input    AWSTASHNID, | ||||
|         input    AWSTASHNIDEN, | ||||
|         input    AWSTASHLPID, | ||||
|         input    AWSTASHLPIDEN, | ||||
|         input    AWTRACE, | ||||
|         input    AWLOOP, | ||||
|         input    AWMMUVALID, | ||||
|         input    AWMMUSECSID, | ||||
|         input    AWMMUSID, | ||||
|         input    AWMMUSSIDV, | ||||
|         input    AWMMUSSID, | ||||
|         input    AWMMUATST, | ||||
|         input    AWMMUFLOW, | ||||
|         input    AWPBHA, | ||||
|         input    AWNSAID, | ||||
|         input    AWSUBSYSID, | ||||
|         input    AWATOP, | ||||
|         input    AWMPAM, | ||||
|         input    AWIDUNQ, | ||||
|         input    AWCMO, | ||||
|         input    AWTAGOP, | ||||
|         input    AWMECID, | ||||
|  | ||||
|         // A2.1.1 Write request channel | ||||
|         input    WVALID, | ||||
|         output   WREADY, | ||||
|         input    WDATA, | ||||
|         input    WSTRB, | ||||
|         input    WTAG, | ||||
|         input    WTAGUPDATE, | ||||
|         input    WLAST, | ||||
|         input    WUSER, | ||||
|         input    WPOISON, | ||||
|         input    WTRACE, | ||||
|  | ||||
|         // A2.1.3 Write response channel | ||||
|         output   BVALID, | ||||
|         input    BREADY, | ||||
|         output   BID, | ||||
|         output   BIDUNQ, | ||||
|         output   BRESP, | ||||
|         output   BCOMP, | ||||
|         output   BPERSIST, | ||||
|         output   BTAGMATCH, | ||||
|         output   BUSER, | ||||
|         output   BTRACE, | ||||
|         output   BLOOP, | ||||
|         output   BBUSY, | ||||
|  | ||||
|         // A2.2.1 Read request channel | ||||
|         input    ARVALID, | ||||
|         output   ARREADY, | ||||
|         input    ARID, | ||||
|         input    ARADDR, | ||||
|         input    ARREGION, | ||||
|         input    ARLEN, | ||||
|         input    ARSIZE, | ||||
|         input    ARBURST, | ||||
|         input    ARLOCK, | ||||
|         input    ARCACHE, | ||||
|         input    ARPROT, | ||||
|         input    ARNSE, | ||||
|         input    ARQOS, | ||||
|         input    ARUSER, | ||||
|         input    ARDOMAIN, | ||||
|         input    ARSNOOP, | ||||
|         input    ARTRACE, | ||||
|         input    ARLOOP, | ||||
|         input    ARMMUVALID, | ||||
|         input    ARMMUSECSID, | ||||
|         input    ARMMUSID, | ||||
|         input    ARMMUSSIDV, | ||||
|         input    ARMMUSSID, | ||||
|         input    ARMMUATST, | ||||
|         input    ARMMUFLOW, | ||||
|         input    ARPBHA, | ||||
|         input    ARNSAID, | ||||
|         input    ARSUBSYSID, | ||||
|         input    ARCHUNKEN, | ||||
|         input    ARIDUNQ, | ||||
|         input    ARTAGOP, | ||||
|         input    ARMECID, | ||||
|  | ||||
|         // A2.2.2 Read data channel | ||||
|         output   RVALID, | ||||
|         input    RREADY, | ||||
|         output   RID, | ||||
|         output   RIDUNQ, | ||||
|         output   RDATA, | ||||
|         output   RTAG, | ||||
|         output   RRESP, | ||||
|         output   RLAST, | ||||
|         output   RUSER, | ||||
|         output   RPOISON, | ||||
|         output   RTRACE, | ||||
|         output   RLOOP, | ||||
|         output   RCHUNKV, | ||||
|         output   RCHUNKNUM, | ||||
|         output   RCHUNKSTRB, | ||||
|         output   RBUSY | ||||
|     ); | ||||
| endinterface // axi_intf | ||||
							
								
								
									
										3
									
								
								common/common_pkg.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								common/common_pkg.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| `include "axi.intf.sv" | ||||
| package common_pkg; | ||||
| endpackage | ||||
							
								
								
									
										336
									
								
								scripts/gen_axi_intf.pl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										336
									
								
								scripts/gen_axi_intf.pl
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,336 @@ | ||||
| #!/usr/bin/env perl | ||||
| use strict; | ||||
| use warnings; | ||||
| use Data::Dumper; | ||||
|  | ||||
| my $app = {}; | ||||
|  | ||||
| get_axi_intf_data($app); | ||||
| augment_intf_data($app); | ||||
| #print Dumper($app->{'intf_data'}); # Debugging output | ||||
|  | ||||
| gen_intf($app); | ||||
|  | ||||
| # ----------------- | ||||
| # Subroutines | ||||
| # ----------------- | ||||
| sub gen_intf { | ||||
|     my ($app) = @_; | ||||
|  | ||||
|     print "// Generated AXI Interface\n"; | ||||
|     print "// This file is automatically generated by $0\n"; | ||||
|     print "// Do not edit this file directly.\n"; | ||||
|     print "//\n"; | ||||
|     print "// Interface Name: $app->{'intf_data'}->{'name'}\n"; | ||||
|     print "interface axi_intf #(\n"; | ||||
|  | ||||
|     my @plines = get_param_lines($app); | ||||
|     print join(",\n", @plines); | ||||
|     print "\n)\n"; | ||||
|     my @eplines = get_ext_ports_lines($app); | ||||
|     print "\n(\n"; | ||||
|     print join(",\n", @eplines); | ||||
|     print "\n);\n"; | ||||
|  | ||||
|     show_interface($app); | ||||
|  | ||||
|     show_modport($app, 'Manager'); | ||||
|     show_modport($app, 'Subordinate'); | ||||
|  | ||||
|     print "endinterface // axi_intf\n"; | ||||
| } | ||||
|  | ||||
| # ----------------- | ||||
| sub get_param_lines { | ||||
|     my ($app) = @_; | ||||
|     my @plines; | ||||
|  | ||||
|     foreach my $p (sort { $a cmp $b  } keys %{$app->{'intf_data'}->{'params'}}) { | ||||
|         my $param_value = $app->{'intf_data'}->{'params'}->{$p}->{'d'}; | ||||
|         push(@plines, sprintf("    parameter %$app->{'intf_data'}->{'info'}->{'param_width'}s = %d", | ||||
|             $p, $param_value)); | ||||
|     } | ||||
|  | ||||
|     return @plines; | ||||
| } | ||||
|  | ||||
| # ----------------- | ||||
| sub get_ext_ports_lines { | ||||
|     my ($app) = @_; | ||||
|     my @eplines; | ||||
|  | ||||
|     foreach my $p (sort { $a cmp $b  } @{$app->{'intf_data'}->{'ext_sigs'}}) { | ||||
|         push(@eplines, sprintf("    input %s", | ||||
|             $p->{'n'})); | ||||
|     } | ||||
|  | ||||
|     return @eplines; | ||||
| } | ||||
|  | ||||
| # ----------------- | ||||
| sub show_interface { | ||||
|     my ($app) = @_; | ||||
|  | ||||
|     foreach my $section (@{$app->{'intf_data'}->{'sections'}}) { | ||||
|         print "\n"; | ||||
|         print "    // $section->{'name'}\n"; | ||||
|  | ||||
|         # Display signals | ||||
|         foreach my $signal (@{$section->{'signals'}}) { | ||||
|             if ($signal->{'s'} eq 'External') { | ||||
|                 printf "    // External signal: %-$app->{'intf_data'}->{'info'}->{'sig_width'}s // $signal->{'d'} [$signal->{'s'}]\n", | ||||
|                     "$signal->{'n'};"; | ||||
|             } else { | ||||
|                 printf "    logic %$app->{'intf_data'}->{'info'}->{'dim_width'}s %-$app->{'intf_data'}->{'info'}->{'sig_width'}s // $signal->{'d'} [$signal->{'s'}]\n", | ||||
|                     get_dimension($app, $signal->{'w'}), "$signal->{'n'};"; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| # ----------------- | ||||
| sub show_modport{ | ||||
|     my ($app, $role) = @_; | ||||
|     my $last = 0; | ||||
|  | ||||
|     print "\n"; | ||||
|     print "    // Modport for $role role\n"; | ||||
|     print "    modport " . uc($role) . " (\n"; | ||||
|  | ||||
|     my $num_sections = scalar @{$app->{'intf_data'}->{'sections'}}; | ||||
|     my $section_count = 0; | ||||
|     foreach my $section (@{$app->{'intf_data'}->{'sections'}}) { | ||||
|         print "\n"; | ||||
|         print "        // $section->{'name'}\n"; | ||||
|  | ||||
|         $section_count++; | ||||
|  | ||||
|         # Display signals | ||||
|         my $num_signals = scalar @{$section->{'signals'}}; | ||||
|         my $signal_count = 0; | ||||
|         foreach my $signal (@{$section->{'signals'}}) { | ||||
|             # When role is Manager, signals with 'Manager' source are output, others are input | ||||
|             # When role is Subordinate, signals with 'Subordinate' source are output, others are input | ||||
|             my $direction = ($role eq 'Global') ? 'input' : ($role eq $signal->{'s'}) ? 'output' : 'input'; | ||||
|  | ||||
|             $signal_count++; | ||||
|  | ||||
|             $last = 1 if ($num_signals == $signal_count && $num_sections == $section_count); | ||||
|  | ||||
|             printf "        %-8s $signal->{'n'}" . (($last == 1) ? "" : ","). "\n", $direction; | ||||
|         } | ||||
|     } | ||||
|     print "    );\n"; | ||||
| } | ||||
|  | ||||
| # ----------------- | ||||
| sub augment_intf_data { | ||||
|     my ($app) = @_; | ||||
|  | ||||
|     # Pretty print widths | ||||
|     $app->{'intf_data'}->{'info'}->{'param_width'} = 0; | ||||
|     $app->{'intf_data'}->{'info'}->{'dim_width'} = 0; | ||||
|     $app->{'intf_data'}->{'info'}->{'sig_width'} = 0; | ||||
|  | ||||
|     # Capture parameters from signals | ||||
|     $app->{'intf_data'}->{'params'} = {}; | ||||
|     # Capture external signals | ||||
|     $app->{'intf_data'}->{'ext_sigs'} = []; | ||||
|     foreach my $section (@{$app->{'intf_data'}->{'sections'}}) { | ||||
|         foreach my $signal (@{$section->{'signals'}}) { | ||||
|             my $width = $signal->{'w'}; | ||||
|             if ($width !~ /^\d+$/) { | ||||
|                 unless (exists $app->{'intf_data'}->{'params'}->{$width}) { | ||||
|                     $app->{'intf_data'}->{'params'}->{$width} = { | ||||
|                         'd' => 1, # Default value for the parameter | ||||
|                     }; | ||||
|                     $app->{'intf_data'}->{'info'}->{'param_width'} = length($width) | ||||
|                         if (length($width) > $app->{'intf_data'}->{'info'}->{'param_width'}); | ||||
|                 } | ||||
|             } | ||||
|             if ($signal->{'s'} eq 'External') { | ||||
|                 push(@{$app->{'intf_data'}->{'ext_sigs'}}, $signal); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     # Find the maximum width of the parameters | ||||
|     foreach my $section (@{$app->{'intf_data'}->{'sections'}}) { | ||||
|  | ||||
|         foreach my $signal (@{$section->{'signals'}}) { | ||||
|             $app->{'intf_data'}->{'info'}->{'dim_width'} = length(get_dimension($app, $signal->{'w'})) | ||||
|                 if (length(get_dimension($app, $signal->{'w'})) > $app->{'intf_data'}->{'info'}->{'dim_width'}); | ||||
|             $app->{'intf_data'}->{'info'}->{'sig_width'} = length($signal->{'n'}) | ||||
|                 if (length($signal->{'n'}) > $app->{'intf_data'}->{'info'}->{'sig_width'}); | ||||
|         } | ||||
|         $app->{'intf_data'}->{'info'}->{'sig_width'} += 1; # Account for the semi-colon | ||||
|     } | ||||
| } | ||||
|  | ||||
| # ----------------- | ||||
| sub get_dimension { | ||||
|     my ($app, $width) = @_; | ||||
|  | ||||
|     if ($width =~ /^\d+$/) { | ||||
|         if ($width == 1) { | ||||
|             return ""; # Single bit width | ||||
|         } else { | ||||
|             return "[" . ($width-1) . ":0]"; # Specific width | ||||
|         } | ||||
|     } else { | ||||
|         return "[$width-1:0]"; # Width parameter | ||||
|     } | ||||
| } | ||||
|  | ||||
| # ----------------- | ||||
| sub get_axi_intf_data { | ||||
|     my ($app) = @_; | ||||
|  | ||||
|     $app->{'intf_data'} = { | ||||
|         'name' => "AXI Signal List", | ||||
|         'sections' => | ||||
|         [ | ||||
|             { | ||||
|                 'name' => 'A2.4.1 Clock and reset signals', | ||||
|                 'signals' => [ | ||||
|                     { 'n' => 'ACLK',    'w' => '1', 's' => 'External', 'd' => 'External Global clock signal'}, | ||||
|                     { 'n' => 'ARESETn', 'w' => '1', 's' => 'External', 'd' => 'External Global reset signal'} | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 'name' => 'A2.1.1 Write request channel', | ||||
|                 'signals' => [ | ||||
|                     # n: name, w: width, s: source, d: description | ||||
|                     {'n' =>'AWVALID','w' =>'1','s' =>'Manager','d' =>'Valid indicator' }, | ||||
|                     {'n' =>'AWREADY','w' =>'1','s' =>'Subordinate','d' =>'Ready indicator' }, | ||||
|                     {'n' =>'AWID','w' =>'ID_W_WIDTH','s' =>'Manager','d' =>'Transaction identifier for the write channels' }, | ||||
|                     {'n' =>'AWADDR','w' =>'ADDR_WIDTH','s' =>'Manager','d' =>'Transaction address' }, | ||||
|                     {'n' =>'AWREGION','w' =>'4','s' =>'Manager','d' =>'Region identifier' }, | ||||
|                     {'n' =>'AWLEN','w' =>'8','s' =>'Manager','d' =>'Transaction length' }, | ||||
|                     {'n' =>'AWSIZE','w' =>'3','s' =>'Manager','d' =>'Transaction size' }, | ||||
|                     {'n' =>'AWBURST','w' =>'2','s' =>'Manager','d' =>'Burst attribute' }, | ||||
|                     {'n' =>'AWLOCK','w' =>'1','s' =>'Manager','d' =>'Exclusive access indicator' }, | ||||
|                     {'n' =>'AWCACHE','w' =>'4','s' =>'Manager','d' =>'Memory attributes' }, | ||||
|                     {'n' =>'AWPROT','w' =>'3','s' =>'Manager','d' =>'Access attributes' }, | ||||
|                     {'n' =>'AWNSE','w' =>'1','s' =>'Manager','d' =>'Non-secure extension bit for RME' }, | ||||
|                     {'n' =>'AWQOS','w' =>'4','s' =>'Manager','d' =>'QoS identifier' }, | ||||
|                     {'n' =>'AWUSER','w' =>'USER_REQ_WIDTH','s' =>'Manager','d' =>'User-defined extension to a request' }, | ||||
|                     {'n' =>'AWDOMAIN','w' =>'2','s' =>'Manager','d' =>'Shareability domain of a request' }, | ||||
|                     {'n' =>'AWSNOOP','w' =>'AWSNOOP_WIDTH','s' =>'Manager','d' =>'Write request opcode' }, | ||||
|                     {'n' =>'AWSTASHNID','w' =>'11','s' =>'Manager','d' =>'Stash Node ID' }, | ||||
|                     {'n' =>'AWSTASHNIDEN','w' =>'1','s' =>'Manager','d' =>'Stash Node ID enable' }, | ||||
|                     {'n' =>'AWSTASHLPID','w' =>'5','s' =>'Manager','d' =>'Stash Logical Processor ID' }, | ||||
|                     {'n' =>'AWSTASHLPIDEN','w' =>'1','s' =>'Manager','d' =>'Stash Logical Processor ID enable' }, | ||||
|                     {'n' =>'AWTRACE','w' =>'1','s' =>'Manager','d' =>'Trace signal' }, | ||||
|                     {'n' =>'AWLOOP','w' =>'LOOP_W_WIDTH','s' =>'Manager','d' =>'Loopback signals on the write channels' }, | ||||
|                     {'n' =>'AWMMUVALID','w' =>'1','s' =>'Manager','d' =>'MMU signal qualifier' }, | ||||
|                     {'n' =>'AWMMUSECSID','w' =>'SECSID_WIDTH','s' =>'Manager','d' =>'Secure Stream ID' }, | ||||
|                     {'n' =>'AWMMUSID','w' =>'SID_WIDTH','s' =>'Manager','d' =>'StreamID' }, | ||||
|                     {'n' =>'AWMMUSSIDV','w' =>'1','s' =>'Manager','d' =>'SubstreamID valid' }, | ||||
|                     {'n' =>'AWMMUSSID','w' =>'SSID_WIDTH','s' =>'Manager','d' =>'SubstreamID' }, | ||||
|                     {'n' =>'AWMMUATST','w' =>'1','s' =>'Manager','d' =>'Address translated indicator' }, | ||||
|                     {'n' =>'AWMMUFLOW','w' =>'2','s' =>'Manager','d' =>'SMMU flow type' }, | ||||
|                     {'n' =>'AWPBHA','w' =>'4','s' =>'Manager','d' =>'Page-based Hardware Attributes' }, | ||||
|                     {'n' =>'AWNSAID','w' =>'4','s' =>'Manager','d' =>'Non-secure Access ID' }, | ||||
|                     {'n' =>'AWSUBSYSID','w' =>'SUBSYSID_WIDTH','s' =>'Manager','d' =>'Subsystem ID' }, | ||||
|                     {'n' =>'AWATOP','w' =>'6','s' =>'Manager','d' =>'Atomic transaction opcode' }, | ||||
|                     {'n' =>'AWMPAM','w' =>'MPAM_WIDTH','s' =>'Manager','d' =>'MPAM information with a request' }, | ||||
|                     {'n' =>'AWIDUNQ','w' =>'1','s' =>'Manager','d' =>'Unique ID indicator' }, | ||||
|                     {'n' =>'AWCMO','w' =>'AWCMO_WIDTH','s' =>'Manager','d' =>'CMO type' }, | ||||
|                     {'n' =>'AWTAGOP','w' =>'2','s' =>'Manager','d' =>'Memory Tag operation for write requests' }, | ||||
|                     {'n' =>'AWMECID','w' =>'MECID_WIDTH','s' =>'Manager','d' =>'Memory Encryption Context identifier' }, | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 'name' => 'A2.1.1 Write request channel', | ||||
|                 'signals' => [ | ||||
|                     { 'n' => 'WVALID', 'w' => '1', 's' => 'Manager', 'd' => 'Valid indicator' }, | ||||
|                     { 'n' => 'WREADY', 'w' => '1', 's' => 'Subordinate', 'd' => 'Ready indicator' }, | ||||
|                     { 'n' => 'WDATA', 'w' => 'DATA_WIDTH', 's' => 'Manager', 'd' => 'Write data' }, | ||||
|                     { 'n' => 'WSTRB', 'w' => 'DATA_WIDTH_DIV_8', 's' => 'Manager', 'd' => 'Write data strobes' }, | ||||
|                     { 'n' => 'WTAG', 'w' => 'CEIL_DATA_WIDTH_DIV_128_TMS_4', 's' => 'Manager', 'd' => 'Memory Tag' }, | ||||
|                     { 'n' => 'WTAGUPDATE', 'w' => 'CEIL_DATA_WIDTH_DIV_128', 's' => 'Manager', 'd' => 'Memory Tag update' }, | ||||
|                     { 'n' => 'WLAST', 'w' => '1', 's' => 'Manager', 'd' => 'Last write data' }, | ||||
|                     { 'n' => 'WUSER', 'w' => 'USER_DATA_WIDTH', 's' => 'Manager', 'd' => 'User-defined extension to write data' }, | ||||
|                     { 'n' => 'WPOISON', 'w' => 'CEIL_DATA_WIDTH_DIV_64', 's' => 'Manager', 'd' => 'Poison indicator' }, | ||||
|                     { 'n' => 'WTRACE', 'w' => '1', 's' => 'Manager', 'd' => 'Trace signal' }, | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 'name' => 'A2.1.3 Write response channel', | ||||
|                 'signals' => [ | ||||
|                     { 'n' => 'BVALID', 'w' => '1', 's' => 'Subordinate', 'd' => 'Valid indicator' }, | ||||
|                     { 'n' => 'BREADY', 'w' => '1', 's' => 'Manager', 'd' => 'Ready indicator' }, | ||||
|                     { 'n' => 'BID', 'w' => 'ID_W_WIDTH', 's' => 'Subordinate', 'd' => 'Transaction identifier for the write channels' }, | ||||
|                     { 'n' => 'BIDUNQ', 'w' => '1', 's' => 'Subordinate', 'd' => 'Unique ID indicator' }, | ||||
|                     { 'n' => 'BRESP', 'w' => 'BRESP_WIDTH', 's' => 'Subordinate', 'd' => 'Write response code' }, | ||||
|                     { 'n' => 'BCOMP', 'w' => '1', 's' => 'Subordinate', 'd' => 'Completion response indicator' }, | ||||
|                     { 'n' => 'BPERSIST', 'w' => '1', 's' => 'Subordinate', 'd' => "Persist response" }, | ||||
|                     { 'n' => 'BTAGMATCH', 'w' => '2', 's' => 'Subordinate', 'd' => 'Memory Tag Match response' }, | ||||
|                     { 'n' => 'BUSER', 'w' => 'USER_RESP_WIDTH', 's' => 'Subordinate', 'd' => 'User-defined extension to a write response' }, | ||||
|                     { 'n' => 'BTRACE', 'w' => '1', 's' => 'Subordinate', 'd' => 'Trace signal' }, | ||||
|                     { 'n' => 'BLOOP', 'w' => 'LOOP_W_WIDTH', 's' => 'Subordinate', 'd' => 'Loopback signals on the write channels' }, | ||||
|                     { 'n' => 'BBUSY', 'w' => '2', 's' => 'Subordinate', 'd' => "Busy indicator" }, | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 'name' => 'A2.2.1 Read request channel', | ||||
|                 'signals' => [ | ||||
|                     { 'n' => 'ARVALID', 'w' => '1', 's' => 'Manager', 'd' => 'Valid indicator' }, | ||||
|                     { 'n' => 'ARREADY', 'w' => '1', 's' => 'Subordinate', 'd' => 'Ready indicator' }, | ||||
|                     { 'n' => 'ARID', 'w' => 'ID_R_WIDTH', 's' => 'Manager', 'd' => 'Transaction identifier for the read channels' }, | ||||
|                     { 'n' => 'ARADDR', 'w' => 'ADDR_WIDTH', 's' => 'Manager', 'd' => 'Transaction address' }, | ||||
|                     { 'n' => 'ARREGION', 'w' => '4', 's' => 'Manager', 'd' => 'Region identifier' }, | ||||
|                     { 'n' => 'ARLEN',  'w' => '8',  's' => 'Manager',  'd'=> "Transaction length" }, | ||||
|                     { 'n' => 'ARSIZE',  'w' => '3',  's' => 'Manager',  'd' => 'Transaction size' }, | ||||
|                     { 'n' => 'ARBURST', 'w' => '2', 's' => 'Manager', 'd' => 'Burst attribute' }, | ||||
|                     { 'n' => 'ARLOCK', 'w' => '1', 's' => 'Manager', 'd' => 'Exclusive access indicator' }, | ||||
|                     { 'n' => 'ARCACHE', 'w' => '4', 's' => 'Manager', 'd' => 'Memory attributes' }, | ||||
|                     { 'n' => 'ARPROT', 'w' => '3', 's' => 'Manager', 'd' => 'Access attributes' }, | ||||
|                     { 'n' => 'ARNSE', 'w' => '1', 's' => 'Manager', 'd' => 'Non-secure extension bit for RME' }, | ||||
|                     { 'n' => 'ARQOS', 'w' => '4', 's' => 'Manager', 'd' => 'QoS identifier' }, | ||||
|                     { 'n' => 'ARUSER', 'w' => 'USER_REQ_WIDTH', 's' => 'Manager', 'd' => 'User-defined extension to a request' }, | ||||
|                     { 'n' => 'ARDOMAIN', 'w' => '2', 's' => 'Manager', 'd' => 'Shareability domain of a request' }, | ||||
|                     { 'n' => 'ARSNOOP', 'w' => 'ARSNOOP_WIDTH', 's' => 'Manager', 'd' => 'Read request opcode' }, | ||||
|                     { 'n' => 'ARTRACE', 'w' => '1', 's' => 'Manager', 'd' => 'Trace signal' }, | ||||
|                     { 'n' => 'ARLOOP', 'w' => 'LOOP_R_WIDTH', 's' => 'Manager', 'd' => 'Loopback signals on the read channels' }, | ||||
|                     { 'n' => 'ARMMUVALID', 'w' => '1', 's' => 'Manager', 'd' => 'MMU signal qualifier' }, | ||||
|                     { 'n' => 'ARMMUSECSID', 'w' => 'SECSID_WIDTH', 's' => 'Manager', 'd' => 'Secure Stream ID' }, | ||||
|                     { 'n' => 'ARMMUSID', 'w' => 'SID_WIDTH', 's' => 'Manager', 'd' => 'StreamID' }, | ||||
|                     { 'n' => 'ARMMUSSIDV', 'w' => '1', 's' => 'Manager', 'd' => 'SubstreamID valid' }, | ||||
|                     { 'n' => 'ARMMUSSID', 'w' => 'SSID_WIDTH', 's' => 'Manager', 'd' => 'SubstreamID' }, | ||||
|                     { 'n' => 'ARMMUATST', 'w' => '1', 's' => 'Manager', 'd' => 'Address translated indicator' }, | ||||
|                     { 'n' => 'ARMMUFLOW', 'w' => '2', 's' => 'Manager', 'd' => 'SMMU flow type' }, | ||||
|                     { 'n' => 'ARPBHA', 'w' => '4', 's' => 'Manager', 'd' => 'Page-based Hardware Attributes' }, | ||||
|                     { 'n' => 'ARNSAID', 'w' => '4', 's' => 'Manager', 'd' => 'Non-secure Access ID' }, | ||||
|                     { 'n' => 'ARSUBSYSID', 'w' => 'SUBSYSID_WIDTH', 's' => 'Manager', 'd' => 'Subsystem ID' }, | ||||
|                     { 'n' => 'ARCHUNKEN','w' => '1','s' => 'Manager','d' => 'Read data chunking enable'}, | ||||
|                     { 'n' => 'ARIDUNQ','w' => '1','s' => 'Manager','d' => 'Unique ID indicator'}, | ||||
|                     { 'n' => 'ARTAGOP','w' => '2','s' => 'Manager','d' => 'Memory Tag operation for read requests'}, | ||||
|                     { 'n' => 'ARMECID','w' => 'MECID_WIDTH','s' => 'Manager','d' => 'Memory Encryption Context identifier'}, | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 'name' => 'A2.2.2 Read data channel', | ||||
|                 'signals' => [ | ||||
|                     { 'n' => 'RVALID', 'w' => '1', 's' => 'Subordinate', 'd' => 'Valid indicator' }, | ||||
|                     { 'n' => 'RREADY', 'w' => '1', 's' => 'Manager', 'd' => 'Ready indicator' }, | ||||
|                     { 'n' => 'RID', 'w' => 'ID_R_WIDTH', 's' => 'Subordinate', 'd' => 'Transaction identifier for the read channels' }, | ||||
|                     { 'n' => 'RIDUNQ', 'w' => '1', 's' => 'Subordinate', 'd' => 'Unique ID indicator' }, | ||||
|                     { 'n' => 'RDATA', 'w' => 'DATA_WIDTH', 's' => 'Subordinate', 'd' => 'Read data' }, | ||||
|                     { 'n' => 'RTAG', 'w' => 'CEIL_DATA_WIDTH_DIV_128_TMS_4', 's' => 'Subordinate', 'd' => 'Memory Tag' }, | ||||
|                     { 'n' => 'RRESP', 'w' => 'RRESP_WIDTH', 's' => 'Subordinate', 'd' => 'Read response' }, | ||||
|                     { 'n' => 'RLAST', 'w' => '1', 's' => 'Subordinate', 'd' => 'Last read data' }, | ||||
|                     { 'n' => 'RUSER', 'w' => 'SUM_USER_DATA_WIDTH_USER_RESP_WIDTH', 's' => 'Subordinate', 'd' => 'User-defined extension to read data and response' }, | ||||
|                     { 'n' => 'RPOISON', 'w' => 'CEIL_DATA_WIDTH_DIV_64', 's' => 'Subordinate', 'd' => 'Poison indicator' }, | ||||
|                     { 'n' => 'RTRACE', 'w' => '1', 's' => 'Subordinate', 'd' => 'Trace signal' }, | ||||
|                     { 'n' => 'RLOOP', 'w' => 'LOOP_R_WIDTH', 's' => 'Subordinate', 'd' => 'Loopback signals on the read channels' }, | ||||
|                     { 'n' => 'RCHUNKV','w' => '1', 's' => 'Subordinate', 'd' => 'Read data chunking valid' }, | ||||
|                     { 'n' => 'RCHUNKNUM', 'w' => 'RCHUNKNUM_WIDTH', 's' => 'Subordinate', 'd' => 'Read data chunk number' }, | ||||
|                     { 'n' => 'RCHUNKSTRB', 'w' => 'RCHUNKSTRB_WIDTH', 's' => 'Subordinate', 'd' => 'Read data chunk strobe' }, | ||||
|                     { 'n' => 'RBUSY', 'w' => '2', 's' => 'Subordinate', 'd' => 'Busy indicator' }, | ||||
|                 ] | ||||
|             }, | ||||
|         ] | ||||
|     } | ||||
| } | ||||
							
								
								
									
										0
									
								
								src/design_pkg.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/design_pkg.sv
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										88
									
								
								tb/axi_agent.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								tb/axi_agent.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| // ---------------------------------------------------------------------- | ||||
| // Agent to operate AXI transactions | ||||
| // This agent includes a driver, monitor, and sequencer for AXI transactions | ||||
| // ---------------------------------------------------------------------- | ||||
| typedef axi_sequencer; | ||||
|  | ||||
| class axi_agent extends uvm_agent; | ||||
|     agent_type_t agent_type; | ||||
|     virtual `AXI_INTF.MANAGER m_if; | ||||
|     virtual `AXI_INTF.SUBORDINATE s_if; | ||||
|  | ||||
|     // Declare the sequencer and driver | ||||
|     axi_sequencer sequencer; | ||||
|     axi_driver driver; | ||||
|     axi_monitor monitor; | ||||
|  | ||||
|     `uvm_component_utils_begin(axi_agent) | ||||
|         `uvm_field_enum(agent_type_t, agent_type, UVM_DEFAULT) | ||||
|     `uvm_component_utils_end | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Constructor | ||||
|     function new(string name = "axi_agent", uvm_component parent = null); | ||||
|         super.new(name, parent); | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Set agent type | ||||
|     function void set_agent_type(agent_type_t atype); | ||||
|         agent_type = atype; | ||||
|         `uvm_info("set_agent_type", $sformatf("Agent type set to %s", agent_type.name()), UVM_LOW) | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Build phase | ||||
|     virtual function void build_phase(uvm_phase phase); | ||||
|         sequencer   = axi_sequencer::type_id::create("sequencer", this); | ||||
|         driver      = axi_driver::type_id::create("driver", this); | ||||
|         monitor     = axi_monitor::type_id::create("monitor", this); | ||||
|  | ||||
|         // Propagete the agent type to driver and monitor | ||||
|         driver.set_agent_type(agent_type); | ||||
|         monitor.set_agent_type(agent_type); | ||||
|  | ||||
|         if (agent_type == MANAGER) begin | ||||
|             if (!uvm_config_db#(virtual `AXI_INTF.MANAGER)::get(this, "", "axi_dvr_vif", m_if)) begin | ||||
|                 `uvm_fatal("axi_agent", "AXI agent MANAGER interface not configured") | ||||
|             end | ||||
|             `uvm_info("axi_agent", $sformatf("Using AXI agent MANAGER interface: axi_dvr_vif"), UVM_LOW) | ||||
|         end else begin // if (agent_type == SUBORDINATE) begin | ||||
|             if (!uvm_config_db#(virtual `AXI_INTF.SUBORDINATE)::get(this, "", "axi_dvr_vif", s_if)) begin | ||||
|                 `uvm_fatal("axi_agent", "AXI agent SUBORDINATE interface not configured") | ||||
|             end | ||||
|             `uvm_info("axi_agent", $sformatf("Using AXI agent SUBORDINATE interface: axi_dvr_vif"), UVM_LOW) | ||||
|         end | ||||
|  | ||||
|         driver.set_virtual_intefaces(m_if, s_if); | ||||
|         monitor.set_virtual_intefaces(m_if, s_if); | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Connect phase | ||||
|     virtual function void connect_phase(uvm_phase phase); | ||||
|         // Connect the driver to the sequencer | ||||
|         driver.seq_item_port.connect(sequencer.seq_item_export); | ||||
|         driver.rsp_port.connect(sequencer.rsp_export); | ||||
|         // Connect the monitor to the sequencer | ||||
|         // driver.rsp_port.connect(monitor.rsp_export); | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Run phase | ||||
|     virtual function void run_phase(uvm_phase phase); | ||||
|         `uvm_info("axi_agent", $sformatf("Running AXI agent: %s as %s", | ||||
|             get_full_name(), agent_type.name()), UVM_LOW) | ||||
|     endfunction | ||||
| endclass : axi_agent | ||||
|  | ||||
| // ---------------------------------------------------------------------- | ||||
| class axi_sequencer extends uvm_sequencer; | ||||
|  | ||||
|     `uvm_component_utils(axi_sequencer) | ||||
|  | ||||
|     // Constructor | ||||
|     function new(string name, uvm_component parent); | ||||
|         super.new(name, parent); | ||||
|     endfunction | ||||
| endclass : axi_sequencer | ||||
							
								
								
									
										119
									
								
								tb/axi_driver.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								tb/axi_driver.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| // ---------------------------------------------------------------------- | ||||
| // Driver for AXI transactions | ||||
| // ---------------------------------------------------------------------- | ||||
| class axi_driver extends uvm_driver; // #(axi_transaction); | ||||
|     virtual `AXI_INTF.MANAGER m_if; | ||||
|     virtual `AXI_INTF.SUBORDINATE s_if; | ||||
|     agent_type_t agent_type; | ||||
|  | ||||
|     `uvm_component_utils(axi_driver) | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Constructor | ||||
|     function new(string name = "axi_driver", uvm_component parent = null); | ||||
|         super.new(name, parent); | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Set agent type | ||||
|     function void set_agent_type(agent_type_t atype); | ||||
|         agent_type = atype; | ||||
|         `uvm_info("set_agent_type", $sformatf("Agent type set to %s", agent_type.name()), UVM_LOW) | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Set virtual interfaces | ||||
|     function void set_virtual_intefaces(virtual `AXI_INTF.MANAGER m_if_p, | ||||
|                                         virtual `AXI_INTF.SUBORDINATE s_if_p); | ||||
|         `uvm_info("set_virtual_intefaces", $sformatf("Setting virtual interfaces"), UVM_LOW) | ||||
|  | ||||
|         m_if = m_if_p; | ||||
|         s_if = s_if_p; | ||||
|  | ||||
|         // if (m_if == null && s_if == null) begin | ||||
|         //     `uvm_fatal("AXI_DRIVER", "Both MANAGER and SUBORDINATE interfaces are null") | ||||
|         // end else if ((agent_type == MANAGER) && (m_if == null)) begin | ||||
|         //     `uvm_error("AXI_DRIVER", $sformatf("MANAGER interface is null")) | ||||
|         // end else if ((agent_type == SUBORDINATE) && (s_if == null)) begin | ||||
|         //     `uvm_error("AXI_DRIVER", $sformatf("SUBORDINATE interface is null")) | ||||
|         // end | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Run phase | ||||
|     virtual task run_phase(uvm_phase phase); | ||||
|         `uvm_info("axi_driver", $sformatf("Running AXI driver: %s as %s", | ||||
|             get_full_name(), agent_type.name()), UVM_LOW) | ||||
|  | ||||
|         if (agent_type == MANAGER) begin | ||||
|             `uvm_info("axi_driver", $sformatf("Manager agent detected, driving transactions"), UVM_LOW) | ||||
|             drive_transactions(); | ||||
|         end else if (agent_type == SUBORDINATE) begin | ||||
|             `uvm_info("axi_driver", $sformatf("Subordinate agent detected, responding to transactions"), UVM_LOW) | ||||
|             respond_to_transactions(); | ||||
|         end else begin | ||||
|             `uvm_fatal("AXI_DRIVER", "Unknown agent type") | ||||
|         end | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     task drive_transactions(); | ||||
|         if (m_if == null) begin | ||||
|             `uvm_error("AXI_DRIVER", "MANAGER interface is null, cannot drive transactions") | ||||
|         end | ||||
|         forever begin | ||||
|             `uvm_info("axi_driver", $sformatf("Starting to drive transactions for %s (rst_n = %0b)", | ||||
|                 get_full_name(), m_if.ARESETn), UVM_LOW) | ||||
|  | ||||
|             if (m_if.ARESETn == 0) begin | ||||
|                 `uvm_info("axi_driver", $sformatf("Waiting for reset to be released (rst_n = %0b)", | ||||
|                     m_if.ARESETn), UVM_LOW) | ||||
|                 @(posedge m_if.ARESETn); | ||||
|             end | ||||
|  | ||||
|             `uvm_info("axi_driver", $sformatf("Starting to drive transactions for %s (rst_n = %0b)", | ||||
|                 get_full_name(), m_if.ARESETn), UVM_LOW) | ||||
|  | ||||
|             while (m_if.ARESETn != 0) begin | ||||
|                 uvm_sequence_item txn; | ||||
|  | ||||
|                 `uvm_info("axi_driver", $sformatf("Waiting for next transaction"), UVM_LOW) | ||||
|  | ||||
|                 seq_item_port.get_next_item(txn); | ||||
|                 drive_item(txn); | ||||
|                 seq_item_port.item_done(); | ||||
|             end | ||||
|         end | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     task drive_item(uvm_sequence_item txn); | ||||
|         axi_transaction req; | ||||
|  | ||||
|         if (!$cast(req, txn)) begin | ||||
|             `uvm_fatal("AXI_DRIVER", "Invalid transaction type") | ||||
|         end | ||||
|  | ||||
|         `uvm_info("drive_item", $sformatf("Driving AXI transaction:\n%s", req.sprint()), UVM_LOW) | ||||
|         @(posedge m_if.ACLK); | ||||
|         m_if.AWVALID = 1; | ||||
|         m_if.AWADDR  = req.addr; | ||||
|         @(posedge m_if.ACLK); | ||||
|         m_if.WDATA  = req.data; | ||||
|         m_if.WSTRB  = req.strb; | ||||
|         `uvm_info("drive_item", $sformatf("Driving AXI transaction done."), UVM_LOW) | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     task respond_to_transactions(); | ||||
|         forever begin | ||||
|             @(posedge s_if.ARESETn); | ||||
|  | ||||
|             while (s_if.ARESETn != 0) begin | ||||
|                 @(posedge s_if.ACLK); | ||||
|  | ||||
|                 @(negedge s_if.ACLK); | ||||
|             end | ||||
|         end | ||||
|     endtask | ||||
| endclass : axi_driver | ||||
							
								
								
									
										117
									
								
								tb/axi_monitor.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								tb/axi_monitor.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| // ---------------------------------------------------------------------- | ||||
| // Monitor for AXI transactions | ||||
| // ---------------------------------------------------------------------- | ||||
| class axi_monitor extends uvm_monitor; // #(axi_transaction); | ||||
|     virtual `AXI_INTF.MANAGER m_if; | ||||
|     virtual `AXI_INTF.SUBORDINATE s_if; | ||||
|     agent_type_t agent_type; | ||||
|  | ||||
|     // Declare the analysis export | ||||
|     uvm_analysis_port ap; | ||||
|  | ||||
|     // Filehandle for transaction tracker file | ||||
|     int trk_file; | ||||
|  | ||||
|     `uvm_component_utils(axi_monitor) | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Constructor | ||||
|     function new(string name = "axi_monitor", uvm_component parent = null); | ||||
|         super.new(name, parent); | ||||
|         ap = new("analysis_export", this); | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Set agent type | ||||
|     function void set_agent_type(agent_type_t atype); | ||||
|         agent_type = atype; | ||||
|         `uvm_info("set_agent_type", $sformatf("Agent type set to %s", agent_type.name()), UVM_LOW) | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Set virtual interfaces | ||||
|     function void set_virtual_intefaces(virtual `AXI_INTF.MANAGER m_if_p, | ||||
|                                         virtual `AXI_INTF.SUBORDINATE s_if_p); | ||||
|         `uvm_info("set_virtual_intefaces", $sformatf("Setting virtual interfaces"), UVM_LOW) | ||||
|  | ||||
|         m_if = m_if_p; | ||||
|         s_if = s_if_p; | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Run phase | ||||
|     virtual function void run_phase(uvm_phase phase); | ||||
|         // Open transaction log file | ||||
|         trk_file = $fopen($sformatf("axi_transactions.%s.log", agent_type.name()), "w"); | ||||
|         if (trk_file == 0) begin | ||||
|             `uvm_error("AXI_MONITOR", "Failed to open transaction log file") | ||||
|         end else begin | ||||
|             `uvm_info("AXI_MONITOR", "Transaction log file opened successfully", UVM_LOW) | ||||
|         end | ||||
|  | ||||
|         // Start monitoring | ||||
|         do_monitor(); | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Monitor logic to capture transactions | ||||
|     virtual task do_monitor(); | ||||
|         if (agent_type == MANAGER) begin | ||||
|             do_manager_monitor(); | ||||
|         end else if (agent_type == SUBORDINATE) begin | ||||
|             do_subordinate_monitor(); | ||||
|         end else begin | ||||
|             `uvm_fatal("AXI_MONITOR", "Unknown agent type") | ||||
|         end | ||||
|     endtask | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Monitor logic for MANAGER agent | ||||
|     virtual task do_manager_monitor(); | ||||
|         // Placeholder for actual monitoring logic | ||||
|         // This would typically involve sampling signals and creating transactions | ||||
|         forever begin | ||||
|             axi_transaction txn; | ||||
|             @(posedge m_if.ACLK); | ||||
|  | ||||
|             txn = axi_transaction::type_id::create("txn"); | ||||
|  | ||||
|             // Capture transaction details here | ||||
|  | ||||
|             ap.write(txn); | ||||
|             write_transaction_to_file(txn); | ||||
|         end | ||||
|     endtask | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Monitor logic for SUBORDINATE agent | ||||
|     virtual task do_subordinate_monitor(); | ||||
|         // Placeholder for actual monitoring logic | ||||
|         // This would typically involve sampling signals and creating transactions | ||||
|         forever begin | ||||
|             axi_transaction txn; | ||||
|             @(posedge s_if.ACLK); | ||||
|  | ||||
|             txn = axi_transaction::type_id::create("txn"); | ||||
|  | ||||
|             // Capture transaction details here | ||||
|  | ||||
|             ap.write(txn); | ||||
|             write_transaction_to_file(txn); | ||||
|         end | ||||
|     endtask | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Report phase | ||||
|     virtual function void report_phase(uvm_phase phase); | ||||
|         // Report any captured transactions or statistics | ||||
|         `uvm_info("axi_monitor", $sformatf("Reporting on %s", | ||||
|             get_full_name()), UVM_LOW) | ||||
|     endfunction | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Function to write captured transaction into a file | ||||
|     function void write_transaction_to_file(axi_transaction txn); | ||||
|         $fwrite(trk_file, "%s\n", txn.sprint()); | ||||
|     endfunction | ||||
| endclass : axi_monitor | ||||
							
								
								
									
										43
									
								
								tb/axi_transaction.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								tb/axi_transaction.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| // ---------------------------------------------------------------------- | ||||
| class axi_transaction extends uvm_sequence_item; | ||||
|     // Declare AXI transaction fields | ||||
|     rand axi_transaction_type_t txn_type; // Transaction type (read/write) | ||||
|     rand bit [31:0] addr; // Address | ||||
|     rand bit [31:0] data; // Data | ||||
|     rand bit [3:0]  strb; // Byte enable | ||||
|  | ||||
|     `uvm_object_utils_begin(axi_transaction) | ||||
|         `uvm_field_enum(axi_transaction_type_t, txn_type, UVM_DEFAULT) | ||||
|         `uvm_field_int(addr, UVM_DEFAULT) | ||||
|         `uvm_field_int(data, UVM_DEFAULT) | ||||
|         `uvm_field_int(strb, UVM_DEFAULT) | ||||
|     `uvm_object_utils_end | ||||
|  | ||||
|     // Constructor | ||||
|     function new(string name = "axi_transaction"); | ||||
|         super.new(name); | ||||
|     endfunction | ||||
|  | ||||
|     // Copy method for cloning | ||||
|     virtual function uvm_object clone(); | ||||
|         axi_transaction copy; | ||||
|         copy = axi_transaction::type_id::create(get_name()); | ||||
|         copy.txn_type = this.txn_type; | ||||
|         copy.addr = this.addr; | ||||
|         copy.data = this.data; | ||||
|         copy.strb = this.strb; | ||||
|         return copy; | ||||
|     endfunction | ||||
|  | ||||
|     // Comparison method for checking equality | ||||
|     virtual function bit compare(uvm_object rhs); | ||||
|         axi_transaction other; | ||||
|         if (!$cast(other, rhs)) return 0; // Ensure type match | ||||
|         return (this.txn_type == other.txn_type) && | ||||
|                (this.addr == other.addr) && | ||||
|                (this.data == other.data) && | ||||
|                (this.strb == other.strb); | ||||
|     endfunction | ||||
|  | ||||
| endclass : axi_transaction | ||||
|  | ||||
							
								
								
									
										40
									
								
								tb/tb_env.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								tb/tb_env.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| // Testbench environment for UVM-based verification | ||||
| class tb_env extends uvm_env; | ||||
|  | ||||
|     axi_agent axi_m; | ||||
|     axi_agent axi_s; | ||||
|  | ||||
|     `uvm_component_utils(tb_env) | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     function new(string name, uvm_component parent); | ||||
|         super.new(name, parent); | ||||
|     endfunction | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     virtual function void build_phase(uvm_phase phase); | ||||
|         axi_m = axi_agent::type_id::create("axi_m", this); | ||||
|         axi_s = axi_agent::type_id::create("axi_s", this); | ||||
|  | ||||
|         `uvm_info("tb_env", $sformatf("Building testbench environment: %s", get_full_name()), UVM_LOW) | ||||
|         // Set agent types in AXI agents | ||||
|         axi_m.set_agent_type(MANAGER); | ||||
|         axi_s.set_agent_type(SUBORDINATE); | ||||
|     endfunction | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     virtual function void connect_phase(uvm_phase phase); | ||||
|         `uvm_info("tb_env", $sformatf("Connecting testbench environment: %s", get_full_name()), UVM_LOW) | ||||
|     endfunction | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     virtual function void report_phase(uvm_phase phase); | ||||
|         `uvm_info("tb_env", $sformatf("Reporting for testbench environment: %s", get_full_name()), UVM_LOW) | ||||
|         // Add any specific report phase tasks here | ||||
|     endfunction | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     function uvm_sequencer_base get_axi_m_sequencer(); | ||||
|         return axi_m.sequencer; | ||||
|     endfunction | ||||
| endclass : tb_env | ||||
							
								
								
									
										26
									
								
								tb/tb_intf.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tb/tb_intf.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| // Testbench interface for UVM-based verification environment | ||||
| interface testbench_if ( | ||||
|     input clk, | ||||
|     virtual axi_intf #(.ADDR_WIDTH(`ADDR_WIDTH), | ||||
|                .CEIL_DATA_WIDTH_DIV_128(`CEIL_DATA_WIDTH_DIV_128), | ||||
|                .CEIL_DATA_WIDTH_DIV_128_TMS_4(`CEIL_DATA_WIDTH_DIV_128_TMS_4), | ||||
|                .CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64), | ||||
|                .DATA_WIDTH(`DATA_WIDTH), | ||||
|                .DATA_WIDTH_DIV_8(`DATA_WIDTH_DIV_8)) m_if, | ||||
|     virtual axi_intf #(.ADDR_WIDTH(`ADDR_WIDTH), | ||||
|                .CEIL_DATA_WIDTH_DIV_128(`CEIL_DATA_WIDTH_DIV_128), | ||||
|                .CEIL_DATA_WIDTH_DIV_128_TMS_4(`CEIL_DATA_WIDTH_DIV_128_TMS_4), | ||||
|                .CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64), | ||||
|                .DATA_WIDTH(`DATA_WIDTH), | ||||
|                .DATA_WIDTH_DIV_8(`DATA_WIDTH_DIV_8)) s_if); | ||||
|  | ||||
|     logic rst_n; | ||||
|  | ||||
|     initial begin | ||||
|         forever begin | ||||
|             @(clk or rst_n); | ||||
|                 $monitor("@%6t: %b %b ", $time, | ||||
|                     rst_n, clk); | ||||
|         end | ||||
|     end | ||||
| endinterface | ||||
							
								
								
									
										39
									
								
								tb/tb_params.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								tb/tb_params.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| // ---------------------------------------------------------------------- | ||||
| // Tesbench defines | ||||
| // ---------------------------------------------------------------------- | ||||
| // List of AXI parameters used in this testbench | ||||
| `define                          ADDR_WIDTH 32 | ||||
| // `define                       ARSNOOP_WIDTH 1 | ||||
| // `define                         AWCMO_WIDTH 1 | ||||
| // `define                       AWSNOOP_WIDTH 1 | ||||
| // `define                         BRESP_WIDTH 1 | ||||
| `define             CEIL_DATA_WIDTH_DIV_128 1 | ||||
| `define       CEIL_DATA_WIDTH_DIV_128_TMS_4 4 | ||||
| `define              CEIL_DATA_WIDTH_DIV_64 1 | ||||
| `define                          DATA_WIDTH 64 | ||||
| `define                    DATA_WIDTH_DIV_8 8 | ||||
| // `define                          ID_R_WIDTH 1 | ||||
| // `define                          ID_W_WIDTH 1 | ||||
| // `define                        LOOP_R_WIDTH 1 | ||||
| // `define                        LOOP_W_WIDTH 1 | ||||
| // `define                         MECID_WIDTH 1 | ||||
| // `define                          MPAM_WIDTH 1 | ||||
| // `define                     RCHUNKNUM_WIDTH 1 | ||||
| // `define                    RCHUNKSTRB_WIDTH 1 | ||||
| // `define                         RRESP_WIDTH 1 | ||||
| // `define                        SECSID_WIDTH 1 | ||||
| // `define                           SID_WIDTH 1 | ||||
| // `define                          SSID_WIDTH 1 | ||||
| // `define                      SUBSYSID_WIDTH 1 | ||||
| // `define SUM_USER_DATA_WIDTH_USER_RESP_WIDTH 1 | ||||
| // `define                     USER_DATA_WIDTH 1 | ||||
| // `define                      USER_REQ_WIDTH 1 | ||||
| // `define                     USER_RESP_WIDTH 1 | ||||
|  | ||||
| // Defines | ||||
| `define AXI_INTF axi_intf #(.ADDR_WIDTH(`ADDR_WIDTH), \ | ||||
|                     .CEIL_DATA_WIDTH_DIV_128(`CEIL_DATA_WIDTH_DIV_128), \ | ||||
|                     .CEIL_DATA_WIDTH_DIV_128_TMS_4(`CEIL_DATA_WIDTH_DIV_128_TMS_4), \ | ||||
|                     .CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64), \ | ||||
|                     .DATA_WIDTH(`DATA_WIDTH), \ | ||||
|                     .DATA_WIDTH_DIV_8(`DATA_WIDTH_DIV_8)) | ||||
							
								
								
									
										25
									
								
								tb/tb_pkg.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tb/tb_pkg.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| `include "tb_params.sv" | ||||
| `include "tb_intf.sv" | ||||
| package tb_pkg; | ||||
|     import uvm_pkg::*; | ||||
|     import tb_types::*; | ||||
|  | ||||
|     `include "uvm_macros.svh" | ||||
|  | ||||
|     // Testbench defines | ||||
|     // UVM data items | ||||
|     `include "axi_transaction.sv" | ||||
|  | ||||
|     // UVM components | ||||
|     `include "axi_driver.sv" | ||||
|     `include "axi_monitor.sv" | ||||
|     `include "axi_agent.sv" | ||||
|     `include "tb_env.sv" | ||||
|  | ||||
|     // UVM sequences | ||||
|     `include "tb_seq_base.sv" | ||||
|  | ||||
|     // Tests | ||||
|     `include "test_base.sv" | ||||
| endpackage | ||||
| `include "tb_top.sv" | ||||
							
								
								
									
										51
									
								
								tb/tb_seq_base.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tb/tb_seq_base.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| // Base sequence class for testbench sequences | ||||
| class tb_seq_base extends uvm_sequence; | ||||
|     `uvm_object_utils(tb_seq_base) | ||||
|  | ||||
|     // Constructor | ||||
|     function new(string name = "tb_seq_base"); | ||||
|         super.new(name); | ||||
|     endfunction | ||||
| endclass : tb_seq_base | ||||
|  | ||||
| // ---------------------------------------------------------------------- | ||||
| class axi_m_seq_base extends tb_seq_base; | ||||
|     tb_env env; | ||||
|  | ||||
|     `uvm_object_utils(axi_m_seq_base) | ||||
|  | ||||
|     // Constructor | ||||
|     function new(string name = "axi_m_seq_base"); | ||||
|         super.new(name); | ||||
|     endfunction | ||||
|  | ||||
|     // Task to start the sequence | ||||
|     virtual task body(); | ||||
|         bit ok = uvm_config_db#(tb_env)::get(uvm_root::get(), "*", "env", env); | ||||
|     endtask | ||||
| endclass : axi_m_seq_base | ||||
|  | ||||
| // ---------------------------------------------------------------------- | ||||
| class axi_simple_seq extends axi_m_seq_base; | ||||
|     `uvm_object_utils(axi_simple_seq) | ||||
|  | ||||
|     // Constructor | ||||
|     function new(string name = "axi_simple_seq"); | ||||
|         super.new(name); | ||||
|     endfunction | ||||
|  | ||||
|     // Task to start the sequence | ||||
|     virtual task body(); | ||||
|         axi_transaction txn; | ||||
|  | ||||
|         super.body(); | ||||
|  | ||||
|         `uvm_info("axi_simple_seq", "Starting simple AXI sequence", UVM_LOW) | ||||
|  | ||||
|         `uvm_do(txn, env.get_axi_m_sequencer(), -1, { | ||||
|             addr == 32'h0000_0000; // Example address | ||||
|             data == 32'hDEAD_BEEF; // Example data | ||||
|             strb == 'hf; // Example byte enable | ||||
|         }); | ||||
|     endtask | ||||
| endclass : axi_simple_seq | ||||
							
								
								
									
										49
									
								
								tb/tb_top.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								tb/tb_top.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| // Testbench top module for UVM-based verification environment | ||||
| import uvm_pkg::*; | ||||
|  | ||||
| module tb_top (input logic sys_clk); | ||||
|     logic clk; | ||||
|     logic rst_n; | ||||
|  | ||||
|     // AXI interface for manager and subordinate | ||||
|     `AXI_INTF a_if (.ACLK(clk), .ARESETn(rst_n)); | ||||
|  | ||||
|     // // Instantiate the UVM testbench interface | ||||
|     // testbench_if tb_if ( | ||||
|     //     .clk(clk), | ||||
|     //     .m_if(m_if), | ||||
|     //     .s_if(s_if) | ||||
|     // ); | ||||
|     // assign tb_if.rst_n = rst_n; | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     initial begin | ||||
|         uvm_config_db#(virtual     `AXI_INTF.MANAGER)::set(uvm_root::get(), "uvm_test_top.env.axi_m", "axi_dvr_vif", a_if.MANAGER); | ||||
|         uvm_config_db#(virtual `AXI_INTF.SUBORDINATE)::set(uvm_root::get(), "uvm_test_top.env.axi_s", "axi_dvr_vif", a_if.SUBORDINATE); | ||||
|  | ||||
|         run_test(); | ||||
|     end | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     initial begin | ||||
|         $dumpfile("wave.vcd"); | ||||
|         $dumpvars(); | ||||
|     end | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     // Clock generation | ||||
|     // TODO: Move to interface. Parameterize frequency | ||||
|     initial begin | ||||
|         clk = 0; // Initialize clock to 0 at time 0 | ||||
|         forever begin | ||||
|             #5ns clk = ~clk; // Toggle clock every 5 ns | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     // -------------------------------------------------- | ||||
|     initial begin | ||||
|         rst_n = 0; | ||||
|  | ||||
|         #20ns rst_n = 1; // Release reset after 20 ns | ||||
|     end | ||||
| endmodule | ||||
							
								
								
									
										13
									
								
								tb/tb_types.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tb/tb_types.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // Types | ||||
| package tb_types; | ||||
|     // Agent type | ||||
|     typedef enum { | ||||
|         MANAGER, | ||||
|         SUBORDINATE | ||||
|     } agent_type_t; | ||||
|  | ||||
|     typedef enum { | ||||
|         AXI_READ, | ||||
|         AXI_WRITE | ||||
|     } axi_transaction_type_t; | ||||
| endpackage | ||||
							
								
								
									
										129
									
								
								tb/test_base.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								tb/test_base.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| // Base class for testbench tests | ||||
| class test_base extends uvm_test; | ||||
|     `uvm_component_utils(test_base) | ||||
|  | ||||
|     tb_env env; | ||||
|     uvm_table_printer tb_printer; | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     function new(string name, uvm_component parent); | ||||
|         super.new(name, parent); | ||||
|     endfunction | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     function void build_phase(uvm_phase phase); | ||||
|         super.build_phase(phase); | ||||
|  | ||||
|         env = tb_env::type_id::create("env", this); | ||||
|         tb_printer = new("tb_printer"); | ||||
|  | ||||
|         uvm_config_db#(tb_env)::set(uvm_root::get(), "*", "env", env); | ||||
|     endfunction | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     virtual function void end_of_elaboration_phase(uvm_phase phase); | ||||
|         `uvm_info("end_of_elaboration_phase", $sformatf("Testbench topology:\n%s", this.sprint(tb_printer)), UVM_LOW) | ||||
|         display_uvm_config_db(); | ||||
|         display_uvm_config_db("uvm_test_top.env.axi_m"); | ||||
|         display_uvm_config_db("uvm_test_top.env.axi_s"); | ||||
|         dump_uvm_config_db(); | ||||
|     endfunction | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     virtual task run_phase(uvm_phase phase); | ||||
|         uvm_objection objection; | ||||
|  | ||||
|         objection = phase.get_objection(); | ||||
|  | ||||
|         `uvm_info("run_phase", $sformatf("Raising objection"), UVM_LOW) | ||||
|         phase.raise_objection(this); | ||||
|  | ||||
|         run_reset_phase(phase); | ||||
|  | ||||
|         run_test_phase(phase); | ||||
|  | ||||
|         run_flush_phase(phase); | ||||
|  | ||||
|         objection.set_drain_time(this, 20); | ||||
|         `uvm_info("run_phase", $sformatf("Dropping objection"), UVM_LOW) | ||||
|         phase.drop_objection(this); | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     virtual task run_reset_phase(uvm_phase phase); | ||||
|         `uvm_info("run_reset_phase", $sformatf("Starting reset"), UVM_LOW) | ||||
|         `uvm_info("run_reset_phase", $sformatf("Finishing reset"), UVM_LOW) | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     virtual task run_test_phase(uvm_phase phase); | ||||
|         `uvm_warning("run_test_phase", $sformatf("This content is expected to be implemented in specific tests")) | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     virtual task run_flush_phase(uvm_phase phase); | ||||
|         `uvm_info("run_flush_phase", $sformatf("Finishing test"), UVM_LOW) | ||||
|     endtask | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     // Function to traverse and display all entries in uvm_config_db | ||||
|     function void display_uvm_config_db(string scope = ".*"); | ||||
|         uvm_resource_pool rp = uvm_resource_pool::get(); | ||||
|         uvm_resource_types::rsrc_q_t resources; | ||||
|  | ||||
|         // Get all resources from the resource pool | ||||
|         resources = rp.lookup_regex(scope, get_full_name()); | ||||
|  | ||||
|         rp.print_resources(resources, 1); | ||||
|  | ||||
|         `uvm_info("CONFIG_DB", "Traversing uvm_config_db contents:", UVM_LOW) | ||||
|         if (resources.size() == 0) begin | ||||
|             `uvm_info("CONFIG_DB", "No entries found in uvm_config_db", UVM_LOW) | ||||
|             return; | ||||
|         end | ||||
|  | ||||
|         // Iterate through all resources | ||||
|         do begin | ||||
|             uvm_resource_base r = resources.pop_front(); | ||||
|  | ||||
|             if (r == null) begin | ||||
|                 `uvm_info("CONFIG_DB", "No more resources to process", UVM_LOW) | ||||
|                 break; | ||||
|             end | ||||
|  | ||||
|             `uvm_info("CONFIG_DB", $sformatf("Resource: %s", r.get_name()), UVM_LOW) | ||||
|         end while (1); | ||||
|     endfunction | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     // Function to dump all entries in uvm_config_db | ||||
|     function void dump_uvm_config_db(); | ||||
|         uvm_resource_pool rp = uvm_resource_pool::get(); | ||||
|     endfunction | ||||
|  | ||||
| endclass | ||||
|  | ||||
| // ---------------------------------------------------------------------- | ||||
| class test_basic extends test_base; | ||||
|     `uvm_component_utils(test_basic) | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     function new(string name, uvm_component parent); | ||||
|         super.new(name, parent); | ||||
|     endfunction | ||||
|  | ||||
|     // ------------------------------------------------------------ | ||||
|     virtual task run_test_phase(uvm_phase phase); | ||||
|         axi_simple_seq seq; | ||||
|  | ||||
|         `uvm_info("run_test_phase", $sformatf("Starting stimulus"), UVM_LOW) | ||||
|         #100ns; | ||||
|         seq = axi_simple_seq::type_id::create("seq"); | ||||
|         if (seq == null) begin | ||||
|             `uvm_fatal("run_test_phase", "Failed to create sequence instance") | ||||
|         end | ||||
|         seq.start(env.get_axi_m_sequencer()); | ||||
|  | ||||
|         `uvm_info("run_test_phase", $sformatf("Finishing stimulus"), UVM_LOW) | ||||
|     endtask | ||||
| endclass | ||||
		Reference in New Issue
	
	Block a user