├── .gitignore ├── .pygears.py ├── Makefile ├── README.md ├── systemc ├── .cquery ├── Makefile ├── ii_gen.py ├── rtl │ └── Makefile └── sim │ ├── .cquery │ ├── Makefile │ ├── dti_driver.cpp │ ├── dti_driver.hpp │ ├── intf.hpp │ ├── main.cpp │ ├── sequencer.cpp │ ├── sequencer.hpp │ └── top_env.hpp └── uvm └── example ├── .cquery ├── Makefile ├── data_types.hpp ├── dti_agent.hpp ├── dti_driver.hpp ├── dti_monitor.hpp ├── dti_packet.hpp ├── dti_scoreboard.hpp ├── dti_sequence.hpp ├── dti_sequencer.hpp ├── dti_subscriber.hpp ├── dti_vif.hpp ├── main.cpp ├── main_tb └── top.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # OS generated files # 30 | ###################### 31 | .DS_Store 32 | .DS_Store? 33 | ._* 34 | .Spotlight-V100 35 | .Trashes 36 | ehthumbs.db 37 | Thumbs.db 38 | 39 | ##### Python gitignore ###### 40 | # Byte-compiled / optimized / DLL files 41 | __pycache__/ 42 | *.py[cod] 43 | *$py.class 44 | 45 | # C extensions 46 | *.so 47 | 48 | # Distribution / packaging 49 | .Python 50 | build/ 51 | develop-eggs/ 52 | dist/ 53 | downloads/ 54 | eggs/ 55 | .eggs/ 56 | lib/ 57 | lib64/ 58 | parts/ 59 | sdist/ 60 | var/ 61 | wheels/ 62 | pip-wheel-metadata/ 63 | share/python-wheels/ 64 | *.egg-info/ 65 | .installed.cfg 66 | *.egg 67 | MANIFEST 68 | 69 | # PyInstaller 70 | # Usually these files are written by a python script from a template 71 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 72 | *.manifest 73 | *.spec 74 | 75 | # Installer logs 76 | pip-log.txt 77 | pip-delete-this-directory.txt 78 | 79 | # Unit test / coverage reports 80 | htmlcov/ 81 | .tox/ 82 | .nox/ 83 | .coverage 84 | .coverage.* 85 | .cache 86 | nosetests.xml 87 | coverage.xml 88 | *.cover 89 | .hypothesis/ 90 | .pytest_cache/ 91 | 92 | # Translations 93 | *.mo 94 | *.pot 95 | 96 | # Django stuff: 97 | *.log 98 | local_settings.py 99 | db.sqlite3 100 | 101 | # Flask stuff: 102 | instance/ 103 | .webassets-cache 104 | 105 | # Scrapy stuff: 106 | .scrapy 107 | 108 | # Sphinx documentation 109 | docs/_build/ 110 | 111 | # PyBuilder 112 | target/ 113 | 114 | # Jupyter Notebook 115 | .ipynb_checkpoints 116 | 117 | # IPython 118 | profile_default/ 119 | ipython_config.py 120 | 121 | # pyenv 122 | .python-version 123 | 124 | # pipenv 125 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 126 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 127 | # having no cross-platform support, pipenv may install dependencies that don’t work, or not 128 | # install all needed dependencies. 129 | #Pipfile.lock 130 | 131 | # celery beat schedule file 132 | celerybeat-schedule 133 | 134 | # SageMath parsed files 135 | *.sage.py 136 | 137 | # Environments 138 | .env 139 | .venv 140 | env/ 141 | venv/ 142 | ENV/ 143 | env.bak/ 144 | venv.bak/ 145 | 146 | # Spyder project settings 147 | .spyderproject 148 | .spyproject 149 | 150 | # Rope project settings 151 | .ropeproject 152 | 153 | # mkdocs documentation 154 | /site 155 | 156 | # mypy 157 | .mypy_cache/ 158 | .dmypy.json 159 | dmypy.json 160 | 161 | # Pyre type checker 162 | .pyre/ 163 | 164 | ##### SystemVerilog and Verilator ######### 165 | *.vcd 166 | obj_dir/ 167 | tags 168 | .elf 169 | obj-pc/ 170 | *.tmp -------------------------------------------------------------------------------- /.pygears.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pygears.conf.registry import registry, bind 3 | from cascade_classifier.pygears_impl import design as design_dir 4 | 5 | package_dir = os.path.dirname(design_dir.__file__) 6 | 7 | svlib_dir = os.path.join( 8 | package_dir, 'gears', 'svlib') 9 | registry('hdl/include_paths').append(svlib_dir) 10 | 11 | bind('hdl/debug_intfs', ['*']) 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | verilate: 3 | make -C systemc/ verilate 4 | 5 | uvm: verilate 6 | make -C uvm/example 7 | 8 | test: uvm 9 | make -C uvm/example test 10 | 11 | wave: test 12 | make -C uvm/example wave 13 | 14 | .PHONY: clean 15 | clean: 16 | make -C systemc/ clean 17 | make -C uvm/example clean 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is archived. 2 | ======================================================== 3 | 4 | Check this project instead: 5 | ======================================================== 6 | https://github.com/Risto97/systemc_uvm_env 7 | 8 | 9 | Working example for SystemC-UVM and Verilator simulation 10 | ======================================================== 11 | -------------------------------------------------------------------------------- /systemc/.cquery: -------------------------------------------------------------------------------- 1 | %clang 2 | 3 | # Includes 4 | -I/tools/verilator/include 5 | -I/tools/systemc/include -------------------------------------------------------------------------------- /systemc/Makefile: -------------------------------------------------------------------------------- 1 | TOP_MOD = wrap_ii_gen 2 | TOP_FN = $(TOP_MOD).sv 3 | 4 | all: svgen verilate testbench 5 | 6 | python_exec: 7 | python ii_gen.py 8 | 9 | rmline: python_exec 10 | $(shell bash -c 'cat rtl/build/$(TOP_FN) | sed 1d > $(TOP_MOD).tmp') 11 | $(shell bash -c 'mv $(TOP_MOD).tmp rtl/build/$(TOP_FN)') 12 | 13 | svgen: python_exec rmline 14 | 15 | verilate: svgen 16 | make -C rtl/ all 17 | 18 | testbench: verilate 19 | make -C sim/ all 20 | 21 | test: testbench 22 | make -C sim/ test 23 | 24 | wave: test 25 | make -C sim/ wave 26 | 27 | .PHONY: clean 28 | clean: 29 | rm -rf rtl/build 30 | make -C rtl/ clean 31 | make -C sim/ clean 32 | -------------------------------------------------------------------------------- /systemc/ii_gen.py: -------------------------------------------------------------------------------- 1 | from cascade_classifier.pygears_impl.design import ii_gen 2 | from cascade_classifier.pygears_impl.scripts.svlib_utils import copy_svlib 3 | 4 | from pygears.typing import Queue, Uint 5 | from pygears.lib.verif import drv 6 | from pygears.lib import shred 7 | from pygears.hdl import hdlgen 8 | from pygears.conf.registry import bind 9 | from pygears.synth import list_hdl_files 10 | 11 | from string import Template 12 | signal_spy_connect_t = Template(""" 13 | /*verilator tracing_on*/ 14 | ${intf_name}_t ${intf_name}_data; 15 | logic ${intf_name}_valid; 16 | logic ${intf_name}_ready; 17 | /*verilator tracing_off*/ 18 | 19 | assign ${intf_name}_data = ${conn_name}.data; 20 | assign ${intf_name}_valid = ${conn_name}.valid; 21 | assign ${intf_name}_ready = ${conn_name}.ready; 22 | """) 23 | 24 | din_t = Queue[Uint[8], 2] 25 | 26 | ii_gen(din=drv(t=din_t, seq=[]), frame_size=(5, 5)) 27 | 28 | bind('hdl/debug_intfs', ['']) 29 | bind('hdl/spy_connection_template', signal_spy_connect_t) 30 | hdlgen('/ii_gen', outdir="rtl/build", wrapper=True, copy_files=True) 31 | # print(list_hdl_files('/ii_gen', outdir='rtl/build', language='sv', rtl_only=True)) 32 | 33 | # copy_svlib(list_hdl_files('/ii_gen', outdir='rtl/build', language='sv', rtl_only=True)) 34 | -------------------------------------------------------------------------------- /systemc/rtl/Makefile: -------------------------------------------------------------------------------- 1 | ## Written from example by 2 | ## https://github.com/ZipCPU/dbgbus/blob/master/bench/rtl/Makefile 3 | 4 | all: 5 | OJB_DIR := obj_dir 6 | TOP_MOD = wrap_ii_gen 7 | SUBMAKE := $(MAKE) --no-print-directory -C 8 | VERILATOR := verilator 9 | 10 | VFLAGS = -sc -CFLAGS -fpic -LDFLAGS -Wno-fatal --Mdir $(OJB_DIR) -Ibuild/svlib -Ibuild --pins-sc-uint 11 | TRACE_FLAGS = --trace -no-trace-params --trace-structs 12 | 13 | .PHONY: all 14 | all: verilate library 15 | 16 | .PHONY: verilate 17 | verilate: $(OJB_DIR)/V$(TOP_MOD).h 18 | 19 | $(OJB_DIR)/V$(TOP_MOD).h: 20 | -$(VERILATOR) $(VFLAGS) $(TRACE_FLAGS) build/$(TOP_MOD).sv 21 | 22 | .PHONY: library 23 | library: $(OJB_DIR)/V$(TOP_MOD).h 24 | $(SUBMAKE) $(OJB_DIR)/ -f V$(TOP_MOD).mk 25 | 26 | .PHONY: clean 27 | clean: 28 | rm -rf $(OJB_DIR)/ 29 | 30 | DEPS := $(wildcard $(OJB_DIR)/*.d) 31 | 32 | ifneq ($(DEPS),) 33 | include $(DEPS) 34 | endif 35 | -------------------------------------------------------------------------------- /systemc/sim/.cquery: -------------------------------------------------------------------------------- 1 | %clang 2 | 3 | # Includes 4 | -I/tools/verilator/include 5 | -I/tools/systemc/include 6 | -I/tools/work/sysGears/systemc/rtl/obj_dir -------------------------------------------------------------------------------- /systemc/sim/Makefile: -------------------------------------------------------------------------------- 1 | ## Written from example by 2 | ## https://github.com/ZipCPU/dbgbus/blob/master/bench/rtl/Makefile 3 | 4 | SYSTEMC := /tools/systemc 5 | CXX := g++ 6 | OBJDIR := obj-pc 7 | RTLD := ../rtl 8 | VOBJDR := $(RTLD)/obj_dir 9 | TOP_MOD = wrap_ii_gen 10 | SYSC_OPT = -std=c++14 -I ${SYSTEMC}/include -L${SYSTEMC}/lib-linux64 -lsystemc 11 | 12 | VERILATOR_ROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e " s/^.*=\s*//"') 13 | VROOT := $(VERILATOR_ROOT) 14 | VINCD := $(VROOT)/include 15 | VINC := -I$(VINCD) -I$(VOBJDR) -I$(SYSTEMC)/include 16 | 17 | # We'll need to build these two Verilater files, and include them with our 18 | # build 19 | VSRCRAW := verilated.cpp verilated_vcd_sc.cpp verilated_vcd_c.cpp 20 | VSRC := $(addprefix $(VINCD)/,$(VSRCRAW)) 21 | VOBJ := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(VSRCRAW))) 22 | INCS := $(VINC) 23 | CFLAGS := -Og -g -Wall $(INCS) 24 | 25 | all: main_tb 26 | SUBMAKE := $(MAKE) --no-print-directory -C 27 | 28 | SOURCES := $(wildcard *.cpp) 29 | HEADERS := $(wildcard *.hpp) 30 | OBJECTS := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(SOURCES))) $(VOBJ) 31 | 32 | PROGRAMS := main_tb 33 | 34 | all: $(PROGRAMS) 35 | 36 | # Generic build instructions for object files 37 | $(OBJDIR)/%.o: %.cpp 38 | $(mk-objdir) 39 | $(CXX) $(CFLAGS) -c $(SYSC_OPT) $< -o $@ 40 | 41 | # And we'll repeat those instructions for building object files from sources 42 | # within the Verilator directory found within $(VERILATOR_ROOT) 43 | $(OBJDIR)/%.o: $(VINCD)/%.cpp 44 | $(mk-objdir) 45 | $(CXX) $(CFLAGS) $(SYSC_OPT) -c $< -o $@ 46 | 47 | # Build our actual target. Note the dependency on the $(OBJECTS) list of 48 | # object files above 49 | main_tb: $(OBJECTS) $(VOBJDR)/V$(TOP_MOD)__ALL.a 50 | -$(CXX) $(CFLAGS) $(SYSC_OPT) $(OBJECTS) $(VOBJDR)/V$(TOP_MOD)__ALL.a -o $@ 51 | 52 | # The "test" target, just runs our test bench object 53 | # 54 | .PHONY: test 55 | test: main_tb 56 | ./main_tb 57 | 58 | .PHONY: wave 59 | wave: test 60 | gtkwave top.vcd 61 | 62 | # 63 | # The "clean" target, removing any and all remaining build (and test) products 64 | # 65 | .PHONY: clean 66 | clean: 67 | rm -f *.vcd 68 | rm -f $(PROGRAMS) 69 | rm -rf $(OBJDIR)/ 70 | 71 | # The "depends" target, to know what files things depend upon. The depends 72 | # file itself is kept in $(OBJDIR)/depends.txt 73 | # 74 | define build-depends 75 | $(mk-objdir) 76 | @echo "Building dependency file" 77 | @$(CXX) $(CFLAGS) $(SYSC_OPT) $(INCS) -MM $(SOURCES) > $(OBJDIR)/xdepends.txt 78 | @sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt 79 | @rm $(OBJDIR)/xdepends.txt 80 | endef 81 | 82 | .PHONY: depends 83 | depends: tags 84 | $(build-depends) 85 | 86 | $(OBJDIR)/depends.txt: depends 87 | 88 | # 89 | # Make sure the $(OBJDIR)/ directory exists. This has taken some work to get 90 | # right. While "mkdir -p $(OBJDIR)" could be used to do this as well, it 91 | # always bothered me that it seemed to be perpetually running. Hence, we'll 92 | # first check if the directory exists, and only create it if it does not. 93 | # Finally, by adding the @ in front of the bash command, it won't get printed 94 | # to the screen. That way ... I can run it as often as I want without getting 95 | # annoyed by it. ;) 96 | define mk-objdir 97 | @bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi" 98 | endef 99 | 100 | 101 | # 102 | # The "tags" target 103 | # 104 | tags: $(SOURCES) $(HEADERS) 105 | @echo "Generating tags" 106 | @ctags $(SOURCES) $(HEADERS) 107 | 108 | # 109 | # Include our generated dependency file. The "-" in front of the include 110 | # basically tells "make" to include it if it can, and ignore it if it cannot 111 | # be included (i.e. if it doesn't exist) 112 | -include $(OBJDIR)/depends.txt 113 | -------------------------------------------------------------------------------- /systemc/sim/dti_driver.cpp: -------------------------------------------------------------------------------- 1 | #include "dti_driver.hpp" 2 | 3 | using namespace sc_core; 4 | using namespace tlm; 5 | using namespace std; 6 | using namespace sc_dt; 7 | 8 | dti_drv::dti_drv(sc_module_name name, dti_intf *intf_ext) 9 | : sc_module(name), soc("soc") { 10 | soc.register_b_transport(this, &dti_drv::b_transport); 11 | intf = new dti_intf(intf_ext); 12 | } 13 | 14 | void dti_drv::b_transport(pl_t &pl, sc_time &offset) { 15 | tlm_command cmd = pl.get_command(); 16 | 17 | wait(clk.negedge_event()); 18 | if(rst == 0){ 19 | if(cmd == TLM_WRITE_COMMAND) { 20 | sc_uint<32> val = *((sc_uint<32> *)pl.get_data_ptr()); 21 | msg(pl); 22 | *(intf->dti_data) = val; 23 | *(intf->dti_valid) = 1; 24 | wait(clk.posedge_event()); 25 | if(*(intf->dti_ready) != 1) 26 | pl.set_response_status(TLM_INCOMPLETE_RESPONSE); 27 | else 28 | pl.set_response_status(TLM_OK_RESPONSE); 29 | } 30 | else{ 31 | pl.set_response_status(TLM_COMMAND_ERROR_RESPONSE); 32 | SC_REPORT_ERROR(sc_object::name(), "TLM bad command"); 33 | } 34 | } 35 | else 36 | pl.set_response_status(TLM_INCOMPLETE_RESPONSE); 37 | // offset = sc_time(1, SC_NS); 38 | } 39 | 40 | void dti_drv::msg(const pl_t &pl) { 41 | stringstream ss; 42 | ss << hex << pl.get_address(); 43 | sc_uint<32> val = *((sc_uint<32> *)pl.get_data_ptr()); 44 | std::cout << val << std::endl; 45 | string cmd = pl.get_command() == TLM_READ_COMMAND ? "read " : "write "; 46 | 47 | string msg = cmd + "val: " + to_string((int)val) + " adr: " + ss.str(); 48 | msg += " @ " + sc_time_stamp().to_string(); 49 | 50 | SC_REPORT_INFO(sc_object::name(), msg.c_str()); 51 | } 52 | -------------------------------------------------------------------------------- /systemc/sim/dti_driver.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_DRIVER_HPP 2 | #define DTI_DRIVER_HPP 3 | 4 | #include "systemc.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "intf.hpp" 10 | #include 11 | 12 | template struct seq_item { 13 | bool valid; 14 | bool ready; 15 | data_T data; 16 | }; 17 | 18 | // template 19 | class dti_drv : 20 | public sc_core::sc_module 21 | { 22 | public: 23 | seq_item > item; 24 | dti_intf *intf; 25 | sc_in clk; 26 | sc_in rst; 27 | 28 | 29 | dti_drv(sc_core::sc_module_name, dti_intf *intf_ext); 30 | 31 | ~dti_drv(){ 32 | } 33 | 34 | tlm_utils::simple_target_socket soc; 35 | 36 | protected: 37 | // sc_dt::sc_uint<32> val; 38 | 39 | typedef tlm::tlm_base_protocol_types::tlm_payload_type pl_t; 40 | void b_transport(pl_t&, sc_core::sc_time&); 41 | void msg(const pl_t&); 42 | 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /systemc/sim/intf.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INTF_HPP 2 | #define INTF_HPP 3 | 4 | #include "systemc.h" 5 | 6 | class dti_intf { 7 | public: 8 | sc_signal *dti_ready; 9 | sc_signal *dti_valid; 10 | sc_signal *dti_data; 11 | 12 | dti_intf(sc_signal *ready, sc_signal *valid, 13 | sc_signal *data) { 14 | dti_ready = ready; 15 | dti_valid = valid; 16 | dti_data = data; 17 | } 18 | 19 | dti_intf(dti_intf *intf_ext){ 20 | dti_ready = intf_ext->dti_ready; 21 | dti_valid = intf_ext->dti_valid; 22 | dti_data = intf_ext->dti_data; 23 | } 24 | 25 | ~dti_intf(){ 26 | 27 | } 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /systemc/sim/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Vwrap_ii_gen.h" 5 | #include "systemc.h" 6 | #include "top_env.hpp" 7 | #include 8 | #include 9 | 10 | #include "sequencer.hpp" 11 | #include "dti_driver.hpp" 12 | 13 | int sc_main(int argc, char **argv) { 14 | Verilated::commandArgs(argc, argv); 15 | TOP_ENV top_obj("aaaa", "mod1", 1000); 16 | 17 | // dti_drv drv1("drv1"); 18 | // sequencer seq("sequencer1"); 19 | // seq.isoc.bind(drv1.soc); 20 | 21 | top_obj.open_trace("top.vcd"); 22 | top_obj.start_sim(); 23 | 24 | top_obj.close_trace(); 25 | exit(EXIT_SUCCESS); 26 | } 27 | -------------------------------------------------------------------------------- /systemc/sim/sequencer.cpp: -------------------------------------------------------------------------------- 1 | #include "sequencer.hpp" 2 | #include 3 | 4 | using namespace sc_core; 5 | using namespace sc_dt; 6 | using namespace tlm; 7 | using namespace std; 8 | 9 | SC_HAS_PROCESS(sequencer); 10 | 11 | sequencer::sequencer(sc_module_name name) : 12 | sc_module(name), 13 | isoc("isoc") 14 | { 15 | SC_THREAD(gen); 16 | SC_THREAD(test); 17 | } 18 | 19 | void sequencer::gen() 20 | { 21 | for(int i = 0; i < 5; i++){ 22 | for(int j = 0; j < 5; j++){ 23 | sc_uint<32> val = j+1; 24 | if(j == 4){ 25 | val = val | 0x0100; 26 | if(i == 4) 27 | val = val | 0x0200; 28 | } 29 | data.push(val); 30 | } 31 | } 32 | 33 | } 34 | 35 | void sequencer::test() 36 | { 37 | tlm_generic_payload pl; 38 | sc_time loct; 39 | tlm_utils::tlm_quantumkeeper qk; 40 | 41 | while(!data.empty()){ 42 | sc_uint<32> val = data.front(); 43 | data.pop(); 44 | pl.set_address(0); 45 | pl.set_command(TLM_WRITE_COMMAND); 46 | pl.set_data_length(4); 47 | pl.set_data_ptr((unsigned char*)&val); 48 | // msg(pl); 49 | 50 | do 51 | isoc->b_transport(pl, loct); 52 | while(pl.get_response_status() != TLM_OK_RESPONSE); 53 | 54 | qk.set_and_sync(loct); 55 | 56 | loct = sc_time(1, SC_NS); 57 | } 58 | } 59 | 60 | void sequencer::msg(const pl_t& pl) 61 | { 62 | stringstream ss; 63 | ss << std::hex << pl.get_address(); 64 | sc_uint<32> val = *((sc_uint<32>*)pl.get_data_ptr()); 65 | string cmd = pl.get_command() == TLM_READ_COMMAND ? "read " : "write "; 66 | 67 | string msg = cmd + "val: " + to_string((int)val) + " adr: " + ss.str(); 68 | msg += " @ " + sc_time_stamp().to_string(); 69 | 70 | SC_REPORT_INFO(sc_object::name(), msg.c_str()); 71 | } 72 | -------------------------------------------------------------------------------- /systemc/sim/sequencer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SEQUENCER_HPP 2 | #define SEQUENCER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class sequencer : 12 | public sc_core::sc_module 13 | { 14 | public: 15 | sequencer(sc_core::sc_module_name); 16 | 17 | tlm_utils::simple_initiator_socket isoc; 18 | 19 | protected: 20 | // sc_dt::sc_uint<8> val; 21 | std::queue > data; 22 | 23 | void test(); 24 | void gen(); 25 | 26 | typedef tlm::tlm_base_protocol_types::tlm_payload_type pl_t; 27 | void b_transport(pl_t&, sc_core::sc_time&); 28 | void msg(const pl_t& pl); 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /systemc/sim/top_env.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TESTBENCH_H 2 | #define TESTBENCH_H 3 | 4 | #include "systemc.h" 5 | #include "verilated_vcd_sc.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "intf.hpp" 11 | #include "dti_driver.hpp" 12 | #include "sequencer.hpp" 13 | 14 | template class TOP_ENV : sc_core::sc_module { 15 | public: 16 | MODULE top_v; 17 | VerilatedVcdSc *m_trace; 18 | sc_core::sc_time T; 19 | sc_core::sc_time Tsim; 20 | 21 | /* Signal Declarations 22 | */ 23 | 24 | dti_intf *din; 25 | dti_intf *dout; 26 | 27 | dti_drv *din_drv; 28 | // dti_drv *dout_drv; 29 | 30 | sequencer *din_seq; 31 | // sequencer *dout_seq; 32 | 33 | sc_clock clk; 34 | sc_signal rst; 35 | 36 | sc_signal din_ready; 37 | sc_signal din_valid; 38 | sc_signal din_data; 39 | 40 | sc_signal dout_valid; 41 | sc_signal dout_ready; 42 | sc_signal dout_data; 43 | 44 | /// ***************************************////////// 45 | 46 | /* clang-format off */ 47 | 48 | SC_HAS_PROCESS(TOP_ENV); 49 | TOP_ENV(sc_module_name nm_top, const char *nm_mod, unsigned long Ncycle) 50 | : sc_module(nm_top), 51 | top_v(nm_mod), 52 | T(10, SC_NS), 53 | Tsim(T * Ncycle), 54 | clk("clk", T), 55 | rst("rst"), 56 | din_ready("din_ready"), 57 | din_valid("din_valid"), 58 | din_data("din_data"), 59 | dout_valid("dout_valid"), 60 | dout_ready("dout_ready"), 61 | dout_data("dout_data") 62 | { 63 | dout_ready = 1; 64 | 65 | top_v.clk(clk); 66 | top_v.rst(rst); 67 | top_v.din_ready(din_ready); 68 | top_v.din_valid(din_valid); 69 | top_v.din_data(din_data); 70 | top_v.dout_valid(dout_valid); 71 | top_v.dout_ready(dout_ready); 72 | top_v.dout_data(dout_data); 73 | 74 | din = new dti_intf(&din_ready, &din_valid, &din_data); 75 | dout = new dti_intf(&dout_ready, &dout_valid, &dout_data); 76 | 77 | din_drv = new dti_drv("din_drv", din); 78 | din_drv->clk(clk); 79 | din_drv->rst(rst); 80 | // dout_drv = new dti_drv("dout_drv", dout); 81 | 82 | din_seq = new sequencer("din_seq"); 83 | // dout_seq = new sequencer("dout_seq"); 84 | 85 | din_seq->isoc.bind(din_drv->soc); 86 | // dout_seq->isoc.bind(dout_drv->soc); 87 | 88 | m_trace = new VerilatedVcdSc; 89 | 90 | // SC_METHOD(monitor); 91 | // sensitive << clk.posedge_event(); 92 | 93 | Verilated::traceEverOn(true); 94 | } 95 | /* clang-format on */ 96 | 97 | ~TOP_ENV() { 98 | close_trace(); 99 | delete din; 100 | delete dout; 101 | delete din_drv; 102 | // delete dout_drv; 103 | delete din_seq; 104 | // delete dout_seq; 105 | } 106 | 107 | void monitor(){ 108 | std::cout << "@_" << sc_time_stamp() << "_ " << std::endl; 109 | if(sc_time_stamp() > sc_time(300, SC_NS) && sc_time_stamp() < sc_time(600, SC_NS)){ 110 | *(dout->dti_ready) = 0; 111 | } 112 | else 113 | *(dout->dti_ready) = 1; 114 | } 115 | 116 | virtual void reset(void) { 117 | rst = 1; 118 | sc_start(10 * T); 119 | rst = 0; 120 | } 121 | 122 | virtual void start_sim(void) { 123 | reset(); 124 | sc_start(Tsim); 125 | } 126 | 127 | virtual void open_trace(const char *vcdname) { 128 | top_v.trace(m_trace, 10); 129 | m_trace->open(vcdname); 130 | } 131 | 132 | virtual void close_trace(void) { 133 | m_trace->close(); 134 | m_trace = NULL; 135 | } 136 | 137 | virtual bool done(void) { return (Verilated::gotFinish()); } 138 | }; 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /uvm/example/.cquery: -------------------------------------------------------------------------------- 1 | %clang 2 | %cpp -std=gnu++14 3 | -pthread 4 | 5 | # Includes 6 | -I/tools/verilator/include 7 | -I/tools/systemc/include 8 | -I/tools/systemc/src 9 | -I/tools/systemc 10 | -I/tools/work/sysGears/systemc/rtl/obj_dir 11 | -I/tools/uvm_systemc/include -------------------------------------------------------------------------------- /uvm/example/Makefile: -------------------------------------------------------------------------------- 1 | ## Written from example by 2 | ## https://github.com/ZipCPU/dbgbus/blob/master/bench/rtl/Makefile 3 | 4 | SYSTEMC := /tools/systemc 5 | UVM_DIR = /tools/uvm_systemc 6 | UVM_INSTALL_DIR = $(UVM_DIR)/objdir 7 | CXX := g++ 8 | OBJDIR := obj-pc 9 | RTLD := ../../systemc/rtl 10 | VOBJDR := $(RTLD)/obj_dir 11 | TOP_MOD = wrap_ii_gen 12 | SYSC_OPT = -I${SYSTEMC}/include -L${SYSTEMC}/lib-linux64 -lsystemc 13 | UVM_OPT = $(UVM_INSTALL_DIR)/src/uvmsc/.libs/libuvm-systemc.so -L$(UVM_DIR)/lib-linux64 14 | UVM_SRC = -I$(UVM_DIR)/src/ -I$(UVM_INSTALL_DIR)/src/ -I$(UVM_DIR)/include 15 | 16 | VERILATOR_ROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e " s/^.*=\s*//"') 17 | VROOT := $(VERILATOR_ROOT) 18 | VINCD := $(VROOT)/include 19 | VINC := -I$(VINCD) -I$(VOBJDR) -I$(SYSTEMC)/include 20 | 21 | # We'll need to build these two Verilater files, and include them with our 22 | # build 23 | VSRCRAW := verilated.cpp verilated_vcd_sc.cpp verilated_vcd_c.cpp 24 | VSRC := $(addprefix $(VINCD)/,$(VSRCRAW)) 25 | VOBJ := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(VSRCRAW))) 26 | INCS := $(VINC) 27 | CFLAGS := -DHAVE_CONFIG_H -Wall -pedantic -Wno-long-long -Wno-variadic-macros -fmessage-length=0 -m64 -O3 -c -std=c++14 $(INCS) 28 | LINK_FLAGS = -Og -g -Wall --std=c++14 29 | 30 | all: main_tb 31 | SUBMAKE := $(MAKE) --no-print-directory -C 32 | 33 | SOURCES := $(wildcard *.cpp) 34 | HEADERS := $(wildcard *.hpp) 35 | OBJECTS := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(SOURCES))) $(VOBJ) 36 | 37 | PROGRAMS := main_tb 38 | 39 | all: $(PROGRAMS) 40 | 41 | # Generic build instructions for object files 42 | $(OBJDIR)/%.o: %.cpp 43 | $(mk-objdir) 44 | $(CXX) $(CFLAGS) -c $(SYSC_OPT) $(UVM_SRC) $< -o $@ 45 | 46 | # And we'll repeat those instructions for building object files from sources 47 | # within the Verilator directory found within $(VERILATOR_ROOT) 48 | $(OBJDIR)/%.o: $(VINCD)/%.cpp 49 | $(mk-objdir) 50 | $(CXX) $(CFLAGS) $(SYSC_OPT) -c $< -o $@ 51 | 52 | # Build our actual target. Note the dependency on the $(OBJECTS) list of 53 | # object files above 54 | main_tb: $(OBJECTS) $(VOBJDR)/V$(TOP_MOD)__ALL.a 55 | -g++ $(LINK_FLAGS) $(SYSC_OPT) $(UVM_OPT) $(OBJECTS) $(VOBJDR)/V$(TOP_MOD)__ALL.a -lpthread -pthread -Wl,-rpath -Wl,$(UVM_DIR)/lib-linux64 -Wl,-rpath -Wl,$(SYSTEMC)/lib-linux64 -o $@ 56 | 57 | # The "test" target, just runs our test bench object 58 | # 59 | .PHONY: test 60 | test: main_tb 61 | ./main_tb 62 | 63 | .PHONY: wave 64 | wave: test 65 | gtkwave top.vcd 66 | 67 | # 68 | # The "clean" target, removing any and all remaining build (and test) products 69 | # 70 | .PHONY: clean 71 | clean: 72 | rm -f *.vcd 73 | rm -f $(PROGRAMS) 74 | rm -rf $(OBJDIR)/ 75 | 76 | # The "depends" target, to know what files things depend upon. The depends 77 | # file itself is kept in $(OBJDIR)/depends.txt 78 | # 79 | define build-depends 80 | $(mk-objdir) 81 | @echo "Building dependency file" 82 | @$(CXX) $(CFLAGS) $(SYSC_OPT) $(INCS) -MM $(SOURCES) > $(OBJDIR)/xdepends.txt 83 | @sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt 84 | @rm $(OBJDIR)/xdepends.txt 85 | endef 86 | 87 | .PHONY: depends 88 | depends: tags 89 | $(build-depends) 90 | 91 | $(OBJDIR)/depends.txt: depends 92 | 93 | # 94 | # Make sure the $(OBJDIR)/ directory exists. This has taken some work to get 95 | # right. While "mkdir -p $(OBJDIR)" could be used to do this as well, it 96 | # always bothered me that it seemed to be perpetually running. Hence, we'll 97 | # first check if the directory exists, and only create it if it does not. 98 | # Finally, by adding the @ in front of the bash command, it won't get printed 99 | # to the screen. That way ... I can run it as often as I want without getting 100 | # annoyed by it. ;) 101 | define mk-objdir 102 | @bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi" 103 | endef 104 | 105 | 106 | # 107 | # The "tags" target 108 | # 109 | tags: $(SOURCES) $(HEADERS) 110 | @echo "Generating tags" 111 | @ctags $(SOURCES) $(HEADERS) 112 | 113 | # 114 | # Include our generated dependency file. The "-" in front of the include 115 | # basically tells "make" to include it if it can, and ignore it if it cannot 116 | # be included (i.e. if it doesn't exist) 117 | -include $(OBJDIR)/depends.txt -------------------------------------------------------------------------------- /uvm/example/data_types.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DATA_TYPES_HPP_ 2 | #define DATA_TYPES_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | template class queue_type { 10 | public: 11 | dt data; 12 | sc_dt::sc_uint eot; 13 | 14 | queue_type() : data(0), eot(0) {} 15 | queue_type(unsigned int d) : data(d) {} 16 | 17 | void operator=(const unsigned int rhs){ data = rhs; } 18 | void operator=(const queue_type rhs) { 19 | data = rhs.data; 20 | eot = rhs.eot; 21 | } 22 | template 23 | void operator=(const sc_dt::sc_uint rhs) { 24 | data = (dt)rhs; 25 | eot = rhs >> data.length(); 26 | } 27 | 28 | void set(const dt data_rhs, const sc_dt::sc_uint eot_rhs)const { 29 | data = data_rhs; 30 | eot = eot_rhs; 31 | } 32 | 33 | bool eos() const{ 34 | for(int i=0; i 54 | friend std::ostream& operator<<(std::ostream& out, const queue_type& q); 55 | 56 | std::string str(){ 57 | std::stringstream ss; 58 | ss << "0x" << std::hex << data; 59 | return ss.str(); 60 | } 61 | 62 | }; 63 | 64 | template 65 | std::ostream& operator<<(std::ostream& out, const queue_type& q){ 66 | out << "Data: " << q.data << " eot: " << q.eot << std::endl; 67 | return out; 68 | } 69 | 70 | #endif /* DATA_TYPES_HPP_ */ 71 | -------------------------------------------------------------------------------- /uvm/example/dti_agent.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_AGENT_HPP_ 2 | #define DTI_AGENT_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "dti_driver.hpp" 9 | #include "dti_monitor.hpp" 10 | #include "dti_sequencer.hpp" 11 | 12 | template 13 | class dti_agent : public uvm::uvm_agent { 14 | public: 15 | dti_sequencer *sequencer; 16 | dti_driver *driver; 17 | dti_monitor *monitor; 18 | 19 | UVM_COMPONENT_UTILS(dti_agent); 20 | 21 | dti_agent(uvm::uvm_component_name name) 22 | : uvm_agent(name), driver(0), sequencer(0), monitor(0) {} 23 | 24 | void build_phase(uvm::uvm_phase &phase) { 25 | uvm::uvm_agent::build_phase(phase); 26 | 27 | if (get_is_active() == uvm::UVM_ACTIVE) { 28 | UVM_INFO(get_name(), "is set to UVM_ACTIVE", uvm::UVM_HIGH); 29 | 30 | sequencer = 31 | dti_sequencer::type_id::create("sequencer", this); 32 | assert(sequencer); 33 | 34 | driver = 35 | dti_driver::type_id::create("driver", this); 36 | assert(driver); 37 | } else 38 | UVM_INFO(get_name(), "is set to UVM_PASSIVE", uvm::UVM_HIGH); 39 | 40 | monitor = dti_monitor::type_id::create("monitor", this); 41 | assert(monitor); 42 | } 43 | 44 | void connect_phase(uvm::uvm_phase &phase) { 45 | if (get_is_active() == uvm::UVM_ACTIVE) { 46 | driver->seq_item_port.connect(sequencer->seq_item_export); 47 | } 48 | } 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /uvm/example/dti_driver.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_DRIVER_HPP_ 2 | #define DTI_DRIVER_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | enum Mode_T { producer = 0, consumer = 1 }; 12 | 13 | template 14 | class dti_driver : public uvm::uvm_driver 15 | { 16 | public: 17 | vif_type *vif; 18 | Mode_T mode; 19 | 20 | dti_driver(uvm::uvm_component_name name) : uvm::uvm_driver(name) {} 21 | 22 | UVM_COMPONENT_PARAM_UTILS(dti_driver); 23 | 24 | void build_phase(uvm::uvm_phase &phase) { 25 | 26 | uvm::uvm_driver::build_phase(phase); 27 | 28 | if (!uvm::uvm_config_db::get(this, "*", "mode", mode)) 29 | UVM_FATAL(this->name(), "Mode not defined! Simulation aborted!"); 30 | } 31 | 32 | void connect_phase(uvm::uvm_phase &phase) { 33 | if (!uvm::uvm_config_db::get(this, "*", "vif", vif)) 34 | UVM_FATAL(this->name(), 35 | "Virtual interface not defined! Simulation aborted!"); 36 | } 37 | 38 | void main_phase(uvm::uvm_phase &phase) { 39 | REQ req, rsp; 40 | 41 | if (mode == consumer) 42 | vif->dti_ready=1; 43 | 44 | while (true) // execute all sequences 45 | { 46 | this->seq_item_port->get_next_item(req); 47 | 48 | if (mode == producer){ 49 | message(req); 50 | drive_transfer_producer(req); 51 | } 52 | 53 | rsp.set_id_info(req); 54 | this->seq_item_port->item_done(); 55 | this->seq_item_port->put_response(rsp); 56 | } 57 | } 58 | 59 | int return_in(int data_in){ 60 | return data_in; 61 | } 62 | void drive_transfer_producer(const REQ &p) { 63 | unsigned int tmp = p.data; 64 | vif->dti_data.write(tmp); 65 | vif->dti_valid = 1; 66 | do { 67 | sc_core::wait(vif->clk->posedge_event()); 68 | } while (vif->dti_ready == 0); 69 | 70 | if(p.eos()) 71 | vif->dti_valid = 0; 72 | } 73 | 74 | void drive_transfer_consumer(const REQ &p) { 75 | vif->dti_ready = 1; 76 | sc_core::wait(vif->clk->posedge_event()); 77 | } 78 | 79 | void message(const REQ &p) { 80 | std::stringstream ss; 81 | ss << p.data; 82 | std::string msg = ss.str(); 83 | UVM_INFO(" Driving data: ", msg, uvm::UVM_HIGH); 84 | } 85 | }; 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /uvm/example/dti_monitor.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_MONITOR_HPP_ 2 | #define DTI_MONITOR_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | template 10 | class dti_monitor : public uvm::uvm_monitor { 11 | public: 12 | uvm::uvm_analysis_port item_collected_port; 13 | 14 | vif_type *vif; 15 | bool checks_enable; 16 | bool coverage_enable; 17 | 18 | dti_monitor(uvm::uvm_component_name name) 19 | : uvm_monitor(name), item_collected_port("item_collected_port"), vif(0), 20 | checks_enable(false), coverage_enable(false) {} 21 | 22 | UVM_COMPONENT_UTILS(dti_monitor); 23 | 24 | void build_phase(uvm::uvm_phase &phase) { 25 | uvm::uvm_monitor::build_phase(phase); 26 | 27 | uvm::uvm_config_db::get(this, "*", "checks_enable", checks_enable); 28 | uvm::uvm_config_db::get(this, "*", "coverage_enable", 29 | coverage_enable); 30 | } 31 | 32 | void connect_phase(uvm::uvm_phase &phase) { 33 | if (!uvm::uvm_config_db::get(this, "*", "vif", vif)) 34 | UVM_FATAL(this->name(), 35 | "Virtual interface not defined! Simulation aborted!"); 36 | } 37 | 38 | void run_phase(uvm::uvm_phase &phase) { 39 | packet_type p; 40 | 41 | while (true) // monitor forever 42 | { 43 | sc_core::wait(vif->dti_data.default_event()); // wait for input changes 44 | p.data = vif->dti_data.read(); 45 | message(p); 46 | item_collected_port.write(p); 47 | 48 | if (checks_enable) { 49 | UVM_FATAL(this->name(), "No checks yet"); 50 | } 51 | if (coverage_enable) { 52 | UVM_FATAL(this->name(), "No checks yet"); 53 | } 54 | } 55 | } 56 | 57 | void message(const packet_type &p) { 58 | std::stringstream ss; 59 | ss << p.data; 60 | std::string msg = ss.str(); 61 | if(uvm::uvm_report_enabled(uvm::UVM_HIGH, uvm::UVM_INFO, "Test") == true) 62 | UVM_INFO(" Read data: ", msg, uvm::UVM_MEDIUM); 63 | } 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /uvm/example/dti_packet.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_PACKET_HPP_ 2 | #define DTI_PACKET_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | template 12 | class dti_packet : public uvm::uvm_sequence_item 13 | { 14 | public: 15 | UVM_OBJECT_UTILS(dti_packet); 16 | 17 | dti_packet(const std::string& name = "packet") : data(0){} 18 | dti_packet(unsigned int i) : data(i){} 19 | virtual ~dti_packet() { } 20 | 21 | virtual void do_print(const uvm::uvm_printer& printer) const 22 | { 23 | std::ostringstream ss; 24 | ss << data; 25 | printer.print_string("Packet: \n", ss.str(), "."); 26 | } 27 | 28 | bool eos() const{ 29 | return data.eos(); 30 | } 31 | // virtual void do_pack(uvm::uvm_packer& p) const 32 | // { 33 | // p << data; 34 | // } 35 | 36 | // virtual void do_unpack(uvm::uvm_packer& p) 37 | // { 38 | // p >> data; 39 | // } 40 | 41 | // virtual void do_copy(const uvm::uvm_object& rhs) 42 | // { 43 | // const dti_packet* drhs = dynamic_cast(&rhs); 44 | // if (!drhs) { std::cerr << "ERROR in do_copy" << std::endl; return; } 45 | // data = drhs->data; 46 | // } 47 | 48 | // virtual bool do_compare(const uvm_object& rhs, const uvm::uvm_comparer*) const 49 | // { 50 | // const dti_packet* drhs = dynamic_cast(&rhs); 51 | // if (!drhs) { std::cerr << "ERROR in do_compare" << std::endl; return true; } 52 | // if (!(data == drhs->data)) return false; 53 | // return true; 54 | // } 55 | 56 | std::string str() const 57 | { 58 | std::ostringstream str; 59 | str << " data: " << data; 60 | return str.str(); 61 | } 62 | 63 | 64 | public: 65 | data_type data; 66 | 67 | }; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /uvm/example/dti_scoreboard.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_SCOREBOARD_H_ 2 | #define DTI_SCOREBOARD_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "dti_subscriber.hpp" 8 | 9 | template 10 | class dti_scoreboard : public uvm::uvm_scoreboard 11 | { 12 | public: 13 | uvm::uvm_analysis_export din_listener_imp; 14 | uvm::uvm_analysis_export dout_listener_imp; 15 | 16 | void din_write(const packet_type& p) 17 | { 18 | UVM_INFO("DIN_WRITE: ", p.str(), UVM_MEDIUM); 19 | } 20 | 21 | void dout_write(const packet_type& p) 22 | { 23 | UVM_INFO("DOUT_WRITE: ", p.str(), UVM_MEDIUM); 24 | } 25 | 26 | dti_subscriber, &dti_scoreboard::din_write > * din_listener; 27 | dti_subscriber, &dti_scoreboard::dout_write > * dout_listener; 28 | 29 | dti_scoreboard( uvm::uvm_component_name name ) : uvm::uvm_scoreboard( name ){} 30 | 31 | UVM_COMPONENT_UTILS(dti_scoreboard); 32 | 33 | 34 | void build_phase(uvm::uvm_phase& phase) 35 | { 36 | uvm::uvm_scoreboard::build_phase(phase); 37 | 38 | uvm::uvm_config_db::set(this, "din_listener", "sb", this); 39 | uvm::uvm_config_db::set(this, "dout_listener", "sb", this); 40 | 41 | din_listener = dti_subscriber, &dti_scoreboard::din_write >::type_id::create("din_listener", this); 42 | assert(din_listener); 43 | 44 | dout_listener = dti_subscriber, &dti_scoreboard::dout_write >::type_id::create("dout_listener", this); 45 | assert(dout_listener); 46 | } 47 | 48 | void connect_phase(uvm::uvm_phase& phase) 49 | { 50 | din_listener_imp.connect(din_listener->analysis_export); 51 | dout_listener_imp.connect(dout_listener->analysis_export); 52 | } 53 | 54 | }; 55 | 56 | #endif /* DTI_SCOREBOARD_H_ */ 57 | -------------------------------------------------------------------------------- /uvm/example/dti_sequence.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_SEQUENCE_HPP_ 2 | #define DTI_SEQUENCE_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | template 17 | class dti_sequence : public uvm::uvm_sequence { 18 | public: 19 | std::vector > data; 20 | 21 | dti_sequence(const std::string &name) : uvm::uvm_sequence(name) {} 22 | 23 | UVM_OBJECT_PARAM_UTILS(dti_sequence); 24 | 25 | void pre_body() { 26 | // raise objection if started as a root dti_sequence 27 | if (this->starting_phase != NULL) 28 | this->starting_phase->raise_objection(this); 29 | 30 | generate_sequence(); 31 | } 32 | 33 | void body() { 34 | packet_type *req; 35 | RSP *rsp; 36 | req = new packet_type(); 37 | rsp = new RSP(); 38 | 39 | for (auto j = data.begin(); j != data.end(); ++j) { 40 | if(j+1 == data.end()) 41 | req->data.eot[1] = 1; 42 | 43 | for (auto i = j->begin(); i != j->end(); ++i){ 44 | unsigned int out_data; 45 | 46 | if(i+1 == j->end()) 47 | req->data.eot[0] = 1; 48 | else 49 | req->data.eot[0] = 0; 50 | 51 | req->data = *i; 52 | // std::cout << req << "\n"; 53 | 54 | message(*req); 55 | 56 | this->start_item(req); 57 | this->finish_item(req); 58 | this->get_response(rsp); 59 | } 60 | } 61 | UVM_INFO(this->get_name(), "Finishing sequence", uvm::UVM_MEDIUM); 62 | } 63 | 64 | void post_body() { 65 | // drop objection if started as a root dti_sequence 66 | if (this->starting_phase != NULL) 67 | this->starting_phase->drop_objection(this); 68 | } 69 | 70 | void message(const packet_type &p) { 71 | std::stringstream ss; 72 | ss << p.data; 73 | std::string msg = ss.str(); 74 | UVM_INFO(" Generated data:", msg, uvm::UVM_MEDIUM); 75 | } 76 | 77 | void generate_sequence() { 78 | 79 | for(int j = 0; j<5; j++){ 80 | std::vector lower; 81 | for(int i = 0; i<5; i++){ 82 | lower.push_back(i+1); 83 | } 84 | data.push_back(lower); 85 | } 86 | } 87 | }; 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /uvm/example/dti_sequencer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_SEQUENCER_HPP_ 2 | #define DTI_SEQUENCER_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | class dti_sequencer : public uvm::uvm_sequencer 10 | { 11 | public: 12 | dti_sequencer( uvm::uvm_component_name name ) : uvm::uvm_sequencer( name ) 13 | { 14 | } 15 | 16 | UVM_COMPONENT_PARAM_UTILS(dti_sequencer); 17 | 18 | }; 19 | 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /uvm/example/dti_subscriber.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_SUBSCRIBER_H_ 2 | #define DTI_SUBSCRIBER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "dti_scoreboard.hpp" 9 | 10 | template 11 | class dti_subscriber : public uvm::uvm_subscriber { 12 | public: 13 | sb_t *sb; 14 | uvm::uvm_object *obj; 15 | 16 | UVM_COMPONENT_UTILS(dti_subscriber); 17 | 18 | dti_subscriber(uvm::uvm_component_name name) 19 | : uvm::uvm_subscriber(name){ 20 | uvm::uvm_config_db::get(this, "", "sb", obj); 21 | 22 | sb = dynamic_cast(obj); 23 | }; 24 | 25 | virtual void write(const packet_type &p){ 26 | // sb->write(p); 27 | (sb->*F)(p); 28 | } 29 | }; 30 | 31 | #endif /* DTI_SUBSCRIBER_H_ */ 32 | -------------------------------------------------------------------------------- /uvm/example/dti_vif.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DTI_VIF_HPP_ 2 | #define DTI_VIF_HPP_ 3 | 4 | #include 5 | #include 6 | 7 | using namespace uvm; 8 | 9 | template 10 | class dti_vif 11 | { 12 | public: 13 | sc_core::sc_clock *clk; 14 | sc_core::sc_signal *rst; 15 | 16 | sc_core::sc_signal dti_valid; 17 | sc_core::sc_signal dti_ready; 18 | sc_core::sc_signal dti_data; 19 | 20 | dti_vif(sc_core::sc_clock *clk_in, sc_core::sc_signal *rst_in){ 21 | clk = clk_in; 22 | rst = rst_in; 23 | } 24 | }; 25 | 26 | #endif /* DTI_VIF_HPP_ */ 27 | -------------------------------------------------------------------------------- /uvm/example/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Vwrap_ii_gen.h" 5 | 6 | #include "top.hpp" 7 | 8 | #include 9 | #include "data_types.hpp" 10 | 11 | using namespace uvm; 12 | 13 | int sc_main(int argc, char **argv) { 14 | Verilated::commandArgs(argc, argv); 15 | 16 | uvm::uvm_config_db::set(NULL, "*", "recording_detail", uvm::UVM_LOW); 17 | uvm::uvm_set_verbosity_level(uvm::UVM_HIGH); 18 | 19 | 20 | top *mytop = new top("top", "v_top", 1000, "top.vcd"); 21 | 22 | mytop->set_report_verbosity_level(UVM_HIGH); 23 | 24 | uvm_default_printer->knobs.reference = 0; 25 | 26 | uvm::uvm_root::get()->print_topology(); 27 | 28 | uvm::run_test(); 29 | 30 | delete mytop; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /uvm/example/main_tb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Risto97/systemc_uvm_verilator/ccdd8e10801a2201aa506849180f8146162c27d4/uvm/example/main_tb -------------------------------------------------------------------------------- /uvm/example/top.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TOP_HPP_ 2 | #define TOP_HPP_ 3 | 4 | #include "verilated_vcd_sc.h" 5 | #include 6 | #include 7 | 8 | #include "dti_vif.hpp" 9 | #include "dti_packet.hpp" 10 | #include "dti_agent.hpp" 11 | #include "dti_sequence.hpp" 12 | #include "data_types.hpp" 13 | 14 | #include "dti_scoreboard.hpp" 15 | #include "dti_subscriber.hpp" 16 | 17 | #define W_DIN 10 18 | #define W_DOUT 16 19 | 20 | using vif_din_type = dti_vif >; 21 | using vif_dout_type = dti_vif >; 22 | 23 | using packet_type = dti_packet, 2> >; 24 | 25 | 26 | template class top : public uvm::uvm_env { 27 | public: 28 | MODULE dut; 29 | VerilatedVcdSc *m_trace; 30 | 31 | dti_agent *din_agent; 32 | dti_agent *dout_agent; 33 | dti_scoreboard * scoreboard0; 34 | 35 | sc_core::sc_time T; 36 | sc_core::sc_time Tsim; 37 | 38 | sc_clock clk; 39 | sc_signal rst; 40 | 41 | vif_din_type *din_vif; 42 | vif_dout_type *dout_vif; 43 | 44 | UVM_COMPONENT_UTILS(top); 45 | 46 | /* clang-format off */ 47 | top(uvm::uvm_component_name name, const char *dut_name, unsigned long Ncycle, const char *vcdname) : 48 | uvm::uvm_env(name), 49 | dut(dut_name), 50 | T(10, SC_NS), 51 | Tsim(T * Ncycle), 52 | clk("clk", T), 53 | rst("rst") 54 | { 55 | /* clang-format on */ 56 | m_trace = new VerilatedVcdSc; 57 | Verilated::traceEverOn(true); 58 | open_trace(vcdname); 59 | } 60 | 61 | void build_phase(uvm::uvm_phase& phase) 62 | { 63 | 64 | uvm::uvm_env::build_phase(phase); 65 | uvm_config_db_options::turn_on_tracing(); 66 | 67 | din_vif = new vif_din_type(&clk, &rst); 68 | dout_vif = new vif_dout_type(&clk, &rst); 69 | 70 | din_agent = dti_agent::type_id::create("din_agent", this); 71 | assert(din_agent); 72 | 73 | dout_agent = dti_agent::type_id::create("dout_agent", this); 74 | assert(dout_agent); 75 | 76 | scoreboard0 = dti_scoreboard::type_id::create("scoreboard0", this); 77 | assert(scoreboard0); 78 | 79 | uvm::uvm_config_db::set(this, "din_agent", "is_active", uvm::UVM_ACTIVE); 80 | uvm::uvm_config_db::set(this, "din_agent.*", "mode", producer); 81 | 82 | uvm::uvm_config_db::set(this, "dout_agent", "is_active", uvm::UVM_ACTIVE); 83 | uvm::uvm_config_db::set(this, "dout_agent.*", "mode", consumer); 84 | 85 | uvm::uvm_config_db::set(0, "top.din_agent.*", "vif", din_vif); 86 | uvm::uvm_config_db::set(0, "top.dout_agent.*", "vif", dout_vif); 87 | 88 | uvm::uvm_config_db 89 | ::set(this,"din_agent.sequencer.run_phase","default_sequence", 90 | dti_sequence::type_id::get()); 91 | 92 | // uvm::uvm_config_db 93 | // ::set(this,"dout_agent.sequencer.run_phase","default_sequence", 94 | // dti_sequence::type_id::get()); 95 | } 96 | 97 | 98 | void connect_phase(uvm::uvm_phase& phase){ 99 | dut.clk(clk); 100 | dut.rst(rst); 101 | 102 | dut.din_ready(din_vif->dti_ready); 103 | dut.din_valid(din_vif->dti_valid); 104 | dut.din_data(din_vif->dti_data); 105 | dut.dout_valid(dout_vif->dti_valid); 106 | dut.dout_ready(dout_vif->dti_ready); 107 | dut.dout_data(dout_vif->dti_data); 108 | 109 | din_agent->monitor->item_collected_port.connect(scoreboard0->din_listener_imp); 110 | dout_agent->monitor->item_collected_port.connect(scoreboard0->dout_listener_imp); 111 | } 112 | 113 | 114 | void reset_phase(uvm::uvm_phase &phase) { 115 | phase.raise_objection(this); 116 | reset(); 117 | phase.drop_objection(this); 118 | } 119 | 120 | void final_phase(uvm::uvm_phase &phase) { 121 | close_trace(); 122 | } 123 | 124 | virtual void main_phase(uvm::uvm_phase &phase) { 125 | phase.raise_objection(this); 126 | sc_core::wait(Tsim); // 1ms 127 | UVM_INFO("Finishing simulation", "by watchdog", UVM_LOW); 128 | phase.drop_objection(this); 129 | } 130 | 131 | virtual void reset(void) { 132 | rst = 1; 133 | sc_core::wait(2 * T); 134 | rst = 0; 135 | } 136 | 137 | virtual void open_trace(const char *vcdname) { 138 | dut.trace(m_trace, 10); 139 | m_trace->open(vcdname); 140 | } 141 | 142 | virtual void close_trace(void) { 143 | m_trace->close(); 144 | m_trace = NULL; 145 | } 146 | }; 147 | 148 | #endif /* TOP_HPP_ */ 149 | --------------------------------------------------------------------------------