├── .gitignore ├── interfaces ├── irq │ ├── jvs_irq_interfaces.sv │ └── jvs_int_if.sv └── clk_rst_group │ ├── jvs_clk_rst_group_interfaces.sv │ └── jvs_clk_ifs.sv ├── include ├── memory │ └── jvs_memory_defines.sv ├── clk_rst_group │ └── jvs_clk_rst_group_defines.sv ├── irq │ └── jvs_irq_defines.sv └── common │ └── jvs_common_defines.sv ├── pkg ├── jvs_interfaces.sv ├── jvs_defines.sv ├── jvs_files.sv └── jvs_pkg.sv ├── jarvism_cfg ├── jarvism_setup.sh └── jarvism_cfg.yaml ├── src ├── common │ ├── jvs_common_files.sv │ ├── jvs_common_type_queue.sv │ ├── jvs_common_attr.sv │ └── jvs_common_condition.sv ├── memory │ ├── jvs_memory_files.sv │ ├── jvs_memory_types.sv │ ├── jvs_memory_model.sv │ ├── jvs_memory_block.sv │ └── jvs_memory_allocator.sv ├── clk_rst_group │ ├── jvs_clk_rst_group_files.sv │ ├── jvs_clk_env.sv │ ├── jvs_clk_vir_seqr.sv │ ├── jvs_clk_agent.sv │ ├── jvs_clk_driver.sv │ └── jvs_clk_rst_trans.sv ├── register_region │ ├── jvs_register_region_files.sv │ ├── jvs_reg_region_builder.sv │ ├── jvs_reg_block_wrapper.sv │ ├── jvs_reg_region_mapper.sv │ ├── jvs_reg_tree.sv │ ├── jvs_reg_resource_manager.sv │ └── jvs_reg_region.sv └── irq │ ├── jvs_irq_files.sv │ ├── jvs_msi_monitor.sv │ ├── jvs_int_agent.sv │ ├── jvs_int_monitor.sv │ ├── jvs_int_driver.sv │ ├── jvs_irq_vir_seq.sv │ ├── jvs_irq_env.sv │ ├── jvs_irq_vir_sequencer.sv │ ├── jvs_irq_handler.sv │ └── jvs_irq_trans.sv ├── tb ├── jvs_memory_tb.sv ├── jvs_register_region_tb.sv ├── jvs_clk_rst_group_tb.sv └── jvs_irq_tb.sv ├── etc └── jvs.f ├── README.md ├── testcases ├── jvs_register_region │ ├── jvs_reg_base_test.sv │ ├── jvs_test_reg_model.sv │ └── jvs_register_region_test │ │ └── jvs_register_region_test.sv ├── jvs_clk_rst_group │ └── jvs_clk_rst_group_basic_test │ │ └── jvs_clk_rst_group_basic_test.sv ├── jvs_irq │ ├── jvs_soft_irq_test │ │ └── jvs_soft_irq_test.sv │ ├── jvs_int_simple_test │ │ └── jvs_int_simple_test.sv │ ├── jvs_msi_irq_test │ │ └── jvs_msi_irq_test.sv │ └── jvs_irq_base_test.sv └── jvs_memory │ └── jvs_memory_showcase │ └── jvs_memory_showcase.sv └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | work 2 | DVEfiles -------------------------------------------------------------------------------- /interfaces/irq/jvs_irq_interfaces.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_INTERFACES_SV__ 2 | `define __JVS_IRQ_INTERFACES_SV__ 3 | `include "jvs_int_if.sv" 4 | `endif -------------------------------------------------------------------------------- /include/memory/jvs_memory_defines.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MEMORY_DEFINES_SV__ 2 | `define __JVS_MEMORY_DEFINES_SV__ 3 | `define JVS_MEM_NULL 65'h1_00000000_00000000 4 | `endif -------------------------------------------------------------------------------- /pkg/jvs_interfaces.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_INTERFACES_SV__ 2 | `define __JVS_INTERFACES_SV__ 3 | `include "jvs_irq_interfaces.sv" 4 | `include "jvs_clk_rst_group_interfaces.sv" 5 | `endif -------------------------------------------------------------------------------- /interfaces/clk_rst_group/jvs_clk_rst_group_interfaces.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_RST_GROUP_INTERFACES_SV__ 2 | `define __JVS_CLK_RST_GROUP_INTERFACES_SV__ 3 | `include "jvs_clk_ifs.sv" 4 | `endif -------------------------------------------------------------------------------- /jarvism_cfg/jarvism_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export JVS_PRJ_HOME=$PWD 3 | export JVS_WORK_DIR=$JVS_PRJ_HOME/work 4 | 5 | if [ -z $JVSUK_HOME ] 6 | then 7 | export JVSUK_HOME=$JVS_PRJ_HOME 8 | fi -------------------------------------------------------------------------------- /interfaces/irq/jvs_int_if.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_INT_IF_SV__ 2 | `define __JVS_INT_IF_SV__ 3 | interface jvs_int_if (); 4 | logic clk; 5 | bit [`JVS_MAX_INT_PIN_NUM-1:0] interrupt; 6 | endinterface 7 | `endif -------------------------------------------------------------------------------- /src/common/jvs_common_files.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_COMMON_FILES_SV__ 2 | `define __JVS_COMMON_FILES_SV__ 3 | `include "jvs_common_attr.sv" 4 | `include "jvs_common_type_queue.sv" 5 | `include "jvs_common_condition.sv" 6 | `endif -------------------------------------------------------------------------------- /include/clk_rst_group/jvs_clk_rst_group_defines.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_RST_GROUP_DEFINES_SV__ 2 | `define __JVS_CLK_RST_GROUP_DEFINES_SV__ 3 | `ifndef JVS_MAX_CLK_GROUP_CLK_NUM 4 | `define JVS_MAX_CLK_GROUP_CLK_NUM 16 5 | `endif 6 | `endif -------------------------------------------------------------------------------- /pkg/jvs_defines.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_DEFINES_SV__ 2 | `define __JVS_DEFINES_SV__ 3 | `include "jvs_common_defines.sv" 4 | `include "jvs_memory_defines.sv" 5 | `include "jvs_irq_defines.sv" 6 | `include "jvs_clk_rst_group_defines.sv" 7 | `endif -------------------------------------------------------------------------------- /src/memory/jvs_memory_files.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MEMORY_FILES_SV__ 2 | `define __JVS_MEMORY_FILES_SV__ 3 | `include "jvs_memory_types.sv" 4 | `include "jvs_memory_model.sv" 5 | `include "jvs_memory_allocator.sv" 6 | `include "jvs_memory_block.sv" 7 | `endif -------------------------------------------------------------------------------- /pkg/jvs_files.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_FILES_SV__ 2 | `define __JVS_FILES_SV__ 3 | `include "jvs_common_files.sv" 4 | `include "jvs_memory_files.sv" 5 | `include "jvs_irq_files.sv" 6 | `include "jvs_register_region_files.sv" 7 | `include "jvs_clk_rst_group_files.sv" 8 | `endif -------------------------------------------------------------------------------- /src/common/jvs_common_type_queue.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_COMMON_TYPE_QUEUE_SV__ 2 | `define __JVS_COMMON_TYPE_QUEUE_SV__ 3 | class jvs_common_type_queue#(type T); 4 | T queue[$]; 5 | semaphore lock; 6 | function new(); 7 | lock = new(1); 8 | endfunction 9 | endclass 10 | `endif -------------------------------------------------------------------------------- /tb/jvs_memory_tb.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MEMORY_TB_SV__ 2 | `define __JVS_MEMORY_TB_SV__ 3 | `include "uvm_macros.svh" 4 | import uvm_pkg::*; 5 | import jvs_pkg::*; 6 | 7 | 8 | module jvs_memory_tb(); 9 | initial begin 10 | run_test(); 11 | end 12 | endmodule 13 | 14 | `endif -------------------------------------------------------------------------------- /src/clk_rst_group/jvs_clk_rst_group_files.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_RST_GROUP_FILES_SV__ 2 | `define __JVS_CLK_RST_GROUP_FILES_SV__ 3 | `include "jvs_clk_rst_trans.sv" 4 | `include "jvs_clk_driver.sv" 5 | `include "jvs_clk_vir_seqr.sv" 6 | `include "jvs_clk_agent.sv" 7 | `include "jvs_clk_env.sv" 8 | `endif -------------------------------------------------------------------------------- /tb/jvs_register_region_tb.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REGISTER_REGION_TB_SV__ 2 | `define __JVS_REGISTER_REGION_TB_SV__ 3 | `include "uvm_macros.svh" 4 | import uvm_pkg::*; 5 | import jvs_pkg::*; 6 | 7 | 8 | module jvs_register_region_tb(); 9 | initial begin 10 | run_test(); 11 | end 12 | endmodule 13 | 14 | `endif -------------------------------------------------------------------------------- /src/register_region/jvs_register_region_files.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REGISTER_REGION_FILES_SV__ 2 | `define __JVS_REGISTER_REGION_FILES_SV__ 3 | `include "jvs_reg_resource_manager.sv" 4 | `include "jvs_reg_tree.sv" 5 | `include "jvs_reg_block_wrapper.sv" 6 | `include "jvs_reg_region.sv" 7 | `include "jvs_reg_region_builder.sv" 8 | `include "jvs_reg_region_mapper.sv" 9 | `endif -------------------------------------------------------------------------------- /src/common/jvs_common_attr.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_COMMON_ATTR_SV__ 2 | `define __JVS_COMMON_ATTR_SV__ 3 | virtual class jvs_common_attr extends uvm_object; 4 | `uvm_field_utils_begin(jvs_common_attr) 5 | `uvm_field_utils_end 6 | 7 | function new(input string name = "jvs_common_attr"); 8 | super.new(name); 9 | endfunction // new 10 | endclass 11 | 12 | `endif -------------------------------------------------------------------------------- /src/irq/jvs_irq_files.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_FILES_SV__ 2 | `define __JVS_IRQ_FILES_SV__ 3 | `include "jvs_irq_trans.sv" 4 | `include "jvs_msi_monitor.sv" 5 | `include "jvs_int_monitor.sv" 6 | `include "jvs_int_driver.sv" 7 | `include "jvs_int_agent.sv" 8 | `include "jvs_irq_handler.sv" 9 | `include "jvs_irq_vir_sequencer.sv" 10 | `include "jvs_irq_vir_seq.sv" 11 | `include "jvs_irq_env.sv" 12 | `endif -------------------------------------------------------------------------------- /pkg/jvs_pkg.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_PKG_SV__ 2 | `define __JVS_PKG_SV__ 3 | `include "jvs_defines.sv" 4 | `include "jvs_interfaces.sv" 5 | `ifndef JVS_PKG_TIMEPRECISION 6 | `define JVS_PKG_TIMEPRECISION 1ps 7 | `endif 8 | package jvs_pkg; 9 | timeunit 1ns; 10 | timeprecision `JVS_PKG_TIMEPRECISION; 11 | import uvm_pkg::*; 12 | `include "uvm_macros.svh" 13 | `include "jvs_files.sv" 14 | endpackage 15 | 16 | `endif -------------------------------------------------------------------------------- /tb/jvs_clk_rst_group_tb.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_RST_GROUP_TB_SV__ 2 | `define __JVS_CLK_RST_GROUP_TB_SV__ 3 | `include "uvm_macros.svh" 4 | import uvm_pkg::*; 5 | import jvs_pkg::*; 6 | 7 | 8 | module jvs_clk_rst_group_tb(); 9 | jvs_clk_group_if#(.name("group")) clk_group_if(); 10 | jvs_clk_group_if#(.name("group1")) clk_group1_if(); 11 | 12 | initial begin 13 | #0; 14 | run_test(); 15 | end 16 | `JVS_WAVE(jvs_clk_rst_group_tb) 17 | endmodule 18 | 19 | `endif 20 | -------------------------------------------------------------------------------- /etc/jvs.f: -------------------------------------------------------------------------------- 1 | +incdir+$JVSUK_HOME/src/common 2 | +incdir+$JVSUK_HOME/src/memory 3 | +incdir+$JVSUK_HOME/src/irq 4 | +incdir+$JVSUK_HOME/src/register_region 5 | +incdir+$JVSUK_HOME/src/clk_rst_group 6 | 7 | +incdir+$JVSUK_HOME/include/common 8 | +incdir+$JVSUK_HOME/include/memory 9 | +incdir+$JVSUK_HOME/include/irq 10 | +incdir+$JVSUK_HOME/include/clk_rst_group 11 | 12 | +incdir+$JVSUK_HOME/interfaces/irq 13 | +incdir+$JVSUK_HOME/interfaces/clk_rst_group 14 | 15 | +incdir+$JVSUK_HOME/pkg 16 | 17 | $JVSUK_HOME/pkg/jvs_pkg.sv 18 | 19 | -------------------------------------------------------------------------------- /src/memory/jvs_memory_types.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MEMORY_TYPES_SV__ 2 | `define __JVS_MEMORY_TYPES_SV__ 3 | typedef enum {ALIGN_BYTE = 0, 4 | ALIGN_DBYTE = 1, 5 | ALIGN_WORD = 2, 6 | ALIGN_DWORD =3, 7 | ALIGN_1K = 10, 8 | ALIGN_2K = 11, 9 | ALIGN_4K = 12, 10 | ALIGN_16K = 14, 11 | ALIGN_64K = 16 12 | } e_alignment; 13 | 14 | 15 | typedef byte unsigned MEM_BYTE; 16 | typedef int unsigned MEM_INT; 17 | typedef longint unsigned MEM_LONG; 18 | typedef MEM_BYTE MEM_BARRAY []; 19 | 20 | `endif -------------------------------------------------------------------------------- /tb/jvs_irq_tb.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_TB_SV__ 2 | `define __JVS_IRQ_TB_SV__ 3 | `include "uvm_macros.svh" 4 | import uvm_pkg::*; 5 | import jvs_pkg::*; 6 | 7 | module jvs_irq_tb(); 8 | logic clk; 9 | logic rst; 10 | 11 | initial begin 12 | clk = 0; 13 | #50ns; 14 | forever begin 15 | #50ns; 16 | clk = ~clk; 17 | end 18 | end 19 | 20 | initial begin 21 | rst = 0; 22 | #1000ns; 23 | rst = 1; 24 | #100ns; 25 | rst = 0; 26 | end 27 | 28 | jvs_int_if int_if(); 29 | assign int_if.clk = clk; 30 | 31 | initial begin 32 | uvm_config_db#(virtual jvs_int_if)::set(null, "uvm_test_top.*.jvs_int_agent", "jvs_int_if", int_if); 33 | run_test(); 34 | end 35 | 36 | `JVS_WAVE(jvs_irq_tb) 37 | 38 | endmodule 39 | `endif -------------------------------------------------------------------------------- /src/common/jvs_common_condition.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_COMMON_CONDITION_SV__ 2 | `define __JVS_COMMON_CONDITION_SV__ 3 | class jvs_common_condition; 4 | local semaphore lock; 5 | local semaphore wait_queue[$]; 6 | 7 | function new(semaphore lock); 8 | this.lock = lock; 9 | endfunction 10 | 11 | task sleep(); 12 | semaphore waiter = new(0); 13 | wait_queue.push_back(waiter); 14 | lock.put(1); 15 | waiter.get(1); 16 | lock.get(1); 17 | endtask // sleep 18 | 19 | task wake(); 20 | if (wait_queue.size()!=0) begin 21 | semaphore nxt_w = wait_queue.pop_front(); 22 | nxt_w.put(1); 23 | end 24 | endtask // wake 25 | 26 | task wake_all(); 27 | while(wait_queue.size()!=0) begin 28 | wake(); 29 | end 30 | endtask 31 | endclass 32 | `endif -------------------------------------------------------------------------------- /include/irq/jvs_irq_defines.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_DEFINES_SV__ 2 | `define __JVS_IRQ_DEFINES_SV__ 3 | `ifndef JVS_MAX_INT_PIN_NUM 4 | `define JVS_MAX_INT_PIN_NUM 1024 5 | `endif 6 | 7 | `ifndef JVS_MAX_IRQ_VECTOR_WIDTH 8 | `define JVS_MAX_IRQ_VECTOR_WIDTH 64 9 | `endif 10 | 11 | `define JVS_INT_IRQ_FLAG 2'b00 12 | `define JVS_MSI_IRQ_FLAG 2'b01 13 | `define JVS_SOFT_IRQ_FLAG 2'b10 14 | `define JVS_UNDEFINED_IRQ_FLAG 2'b11 15 | 16 | `define JVS_INT_IRQ_V(x) ((x) & {(`JVS_MAX_IRQ_VECTOR_WIDTH-2){1'b1}} | {`JVS_INT_IRQ_FLAG, {(`JVS_MAX_IRQ_VECTOR_WIDTH-2){1'b0}}}) 17 | `define JVS_MSI_IRQ_V(x) ((x) & {(`JVS_MAX_IRQ_VECTOR_WIDTH-2){1'b1}} | {`JVS_MSI_IRQ_FLAG, {(`JVS_MAX_IRQ_VECTOR_WIDTH-2){1'b0}}}) 18 | `define JVS_SOFT_IRQ_V(x) ((x) & {(`JVS_MAX_IRQ_VECTOR_WIDTH-2){1'b1}} | {`JVS_SOFT_IRQ_FLAG, {(`JVS_MAX_IRQ_VECTOR_WIDTH-2){1'b0}}}) 19 | 20 | `endif -------------------------------------------------------------------------------- /src/irq/jvs_msi_monitor.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MSI_MONITOR_SV__ 2 | `define __JVS_MSI_MONITOR_SV__ 3 | virtual class jvs_msi_monitor extends uvm_monitor; 4 | `uvm_field_utils_begin(jvs_msi_monitor) 5 | `uvm_field_utils_end 6 | uvm_analysis_port #(jvs_irq_trans) ap; 7 | function new(string name = "jvs_msi_monitor", uvm_component parent); 8 | super.new(name, parent); 9 | endfunction // new 10 | 11 | virtual function void build_phase(uvm_phase phase); 12 | super.build_phase(phase); 13 | ap = new("ap", this); 14 | endfunction // build_phase 15 | 16 | virtual task main_phase(uvm_phase phase); 17 | forever begin 18 | jvs_irq_trans tr; 19 | `uvm_info(this.get_name(), "wait a msi interrupt!", UVM_HIGH); 20 | monitor_msi(tr); 21 | if (tr == null) begin 22 | `uvm_fatal(this.get_name(), "null irq_trans!"); 23 | end 24 | tr.irq_vector = `JVS_MSI_IRQ_V(tr.irq_vector); 25 | ap.write(tr); 26 | tr.end_event.wait_on(); 27 | `uvm_info(this.get_name(), "get a msi interrupt!", UVM_HIGH); 28 | end 29 | endtask // main_phase 30 | 31 | pure protected virtual task monitor_msi(output jvs_irq_trans tr); 32 | endclass 33 | `endif -------------------------------------------------------------------------------- /interfaces/clk_rst_group/jvs_clk_ifs.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_IFS_SV__ 2 | `define __JVS_CLK_IFS_SV__ 3 | interface jvs_root_clk_if(); 4 | logic clock; 5 | endinterface // jvs_root_clk_if 6 | 7 | interface jvs_gen_clk_if(); 8 | logic root_clock; 9 | logic clock; 10 | logic reset_n; 11 | logic rst_process; 12 | 13 | clocking clk_driver @(root_clock); 14 | inout clock; 15 | endclocking // clk_driver 16 | 17 | clocking ctrl_driver @(posedge clock); 18 | output rst_process; 19 | output reset_n; 20 | endclocking 21 | endinterface // jvs_gen_clk_if 22 | 23 | module jvs_clk_group_if#(parameter string name="", parameter string path="*")(); 24 | import uvm_pkg::*; 25 | jvs_root_clk_if root_clk_if(); 26 | jvs_gen_clk_if gen_clk_ifs[`JVS_MAX_CLK_GROUP_CLK_NUM-1:0](); 27 | 28 | genvar i; 29 | generate 30 | for (i = 0; i < `JVS_MAX_CLK_GROUP_CLK_NUM; i++) begin: gen_clk_loop 31 | assign gen_clk_ifs[i].root_clock = root_clk_if.clock; 32 | initial begin 33 | uvm_config_db#(virtual jvs_gen_clk_if)::set(uvm_root::get(), $sformatf("%s.%s",path, name), $sformatf("jvs_gen_clk_if[%0d]", i), gen_clk_ifs[i]); 34 | end 35 | end 36 | endgenerate 37 | initial begin 38 | uvm_config_db#(virtual jvs_root_clk_if)::set(uvm_root::get(), $sformatf("%s.%s",path, name), "jvs_root_clk_if", root_clk_if); 39 | end 40 | 41 | endmodule 42 | `endif -------------------------------------------------------------------------------- /src/irq/jvs_int_agent.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_INT_AGENT_SV__ 2 | `define __JVS_INT_AGENT_SV__ 3 | typedef uvm_sequencer#(jvs_int_drv_trans) jvs_int_sequencer; 4 | class jvs_int_agent extends uvm_agent; 5 | `uvm_component_utils(jvs_int_agent) 6 | 7 | virtual jvs_int_if int_if; 8 | jvs_int_monitor int_mon; 9 | jvs_int_driver int_drv; 10 | jvs_int_sequencer int_seqr; 11 | uvm_analysis_export #(jvs_irq_trans) irq_put_export; 12 | 13 | function new(string name = "jvs_int_agent", uvm_component parent); 14 | super.new(name, parent); 15 | this.is_active = UVM_PASSIVE; 16 | irq_put_export = new("irq_put_export", this); 17 | endfunction // new 18 | 19 | virtual function void build_phase(uvm_phase phase); 20 | super.build_phase(phase); 21 | int_mon = jvs_int_monitor::type_id::create("int_mon", this); 22 | if (is_active == UVM_ACTIVE) begin 23 | int_seqr = jvs_int_sequencer::type_id::create("int_seqr", this); 24 | int_drv = jvs_int_driver::type_id::create("int_drv", this); 25 | end 26 | 27 | if (!uvm_config_db#(virtual jvs_int_if)::get(this, "", "jvs_int_if", int_if)) begin 28 | `uvm_fatal(this.get_full_name(), "Can't get the interrupt interface!"); 29 | end 30 | 31 | uvm_config_db#(virtual jvs_int_if)::set(this, "*", "jvs_int_if", int_if); 32 | endfunction 33 | 34 | virtual function void connect_phase(uvm_phase phase); 35 | super.connect_phase(phase); 36 | if (is_active == UVM_ACTIVE) begin 37 | int_drv.seq_item_port.connect(int_seqr.seq_item_export); 38 | end 39 | int_mon.ap.connect(irq_put_export); 40 | endfunction 41 | endclass 42 | `endif -------------------------------------------------------------------------------- /src/irq/jvs_int_monitor.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_INT_MONITOR_SV__ 2 | `define __JVS_INT_MONITOR_SV__ 3 | class jvs_int_monitor extends uvm_monitor; 4 | `uvm_component_utils(jvs_int_monitor) 5 | virtual jvs_int_if vif; 6 | uvm_analysis_port #(jvs_irq_trans) ap; 7 | function new(string name = "jvs_int_monitor", uvm_component parent); 8 | super.new(name, parent); 9 | endfunction // new 10 | 11 | virtual function void build_phase(uvm_phase phase); 12 | super.build_phase(phase); 13 | ap = new("ap", this); 14 | if (!uvm_config_db#(virtual jvs_int_if)::get(this, "", "jvs_int_if", vif)) begin 15 | `uvm_fatal(get_full_name(), "Can't get the interrupt interface!"); 16 | end 17 | endfunction // build_phase 18 | 19 | virtual task main_phase(uvm_phase phase); 20 | jvs_irq_trans tr; 21 | forever begin 22 | @(posedge vif.clk); 23 | if (|vif.interrupt) begin 24 | `uvm_info(this.get_name(), "get interrupt!", UVM_HIGH); 25 | tr = jvs_irq_trans::type_id::create("tr"); 26 | tr.irq_vector = get_vector(vif.interrupt); 27 | ap.write(tr); 28 | tr.end_event.wait_on(); 29 | @(posedge vif.clk); 30 | `uvm_info(this.get_name(), "release interrupt!", UVM_HIGH); 31 | end 32 | end 33 | endtask // main_phase 34 | 35 | local function bit[`JVS_MAX_IRQ_VECTOR_WIDTH-1:0] get_vector(bit[`JVS_MAX_INT_PIN_NUM - 1 : 0] interrupt); 36 | foreach(interrupt[i]) begin 37 | if (interrupt[i]) begin 38 | return i; 39 | end 40 | end 41 | `uvm_fatal(this.get_name(), "get interrupt toggle but no valid irq, maybe interrupt is cleared illegally!"); 42 | return {`JVS_MAX_IRQ_VECTOR_WIDTH{1'b0}}; 43 | endfunction 44 | endclass 45 | `endif -------------------------------------------------------------------------------- /src/clk_rst_group/jvs_clk_env.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_ENV_SV__ 2 | `define __JVS_CLK_ENV_SV__ 3 | class jvs_clk_env extends uvm_env; 4 | local jvs_clk_top_vir_seqr seqr; 5 | local jvs_clk_group_agent groups[string]; 6 | local jvs_clk_top_cfg cfg; 7 | 8 | `uvm_component_utils(jvs_clk_env) 9 | function new(string name = "jvs_clk_env", uvm_component parent = null); 10 | super.new(name, parent); 11 | seqr = jvs_clk_top_vir_seqr::type_id::create("jvs_clk_top_vir_seqr", this); 12 | endfunction // new 13 | 14 | virtual function void build_phase(uvm_phase phase); 15 | super.build_phase(phase); 16 | if(!uvm_config_db#(jvs_clk_top_cfg)::get(this, "", "cfg", cfg)) begin 17 | `uvm_fatal(get_full_name(), "Can't get cfg!"); 18 | end 19 | foreach(cfg.groups[i]) begin 20 | string key = cfg.groups[i].get_name(); 21 | uvm_config_db#(jvs_clk_group_cfg)::set(this, key, "cfg", cfg.groups[i]); 22 | groups[key] = jvs_clk_group_agent::type_id::create(key, this); 23 | end 24 | 25 | endfunction // build_phase 26 | 27 | virtual function void connect_phase(uvm_phase phase); 28 | super.connect_phase(phase); 29 | foreach(groups[i]) begin 30 | seqr.group_seqrs[i] = groups[i].seqr; 31 | seqr.rst_ana_export.connect(groups[i].seqr.rst_ana_export); 32 | seqr.change_div_ana_export.connect(groups[i].seqr.change_div_ana_export); 33 | end 34 | endfunction 35 | 36 | task hw_reset(string pattern="*"); 37 | seqr.hw_reset(pattern); 38 | endtask 39 | 40 | task change_div(string pattern, int div_ratio); 41 | seqr.change_div(pattern, div_ratio); 42 | endtask 43 | 44 | endclass 45 | `endif 46 | -------------------------------------------------------------------------------- /src/irq/jvs_int_driver.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_INT_DRIVER_SV__ 2 | `define __JVS_INT_DRIVER_SV__ 3 | //for test 4 | 5 | class jvs_int_drv_trans extends jvs_irq_trans_base; 6 | jvs_irq_trans_attr attr; 7 | bit set; 8 | `uvm_object_utils_begin(jvs_int_drv_trans); 9 | `uvm_field_object(attr,UVM_ALL_ON) 10 | `uvm_object_utils_end 11 | function new(string name = "jvs_int_drv_trans"); 12 | super.new(name); 13 | endfunction 14 | endclass // jvs_int_drv_trans 15 | 16 | class jvs_int_driver extends uvm_driver#(jvs_int_drv_trans); 17 | `uvm_component_utils(jvs_int_driver) 18 | 19 | virtual jvs_int_if vif; 20 | int int_set_cnt[bit[`JVS_MAX_INT_PIN_NUM - 1 : 0]]; 21 | function new(string name = "jvs_int_driver", uvm_component parent); 22 | super.new(name, parent); 23 | endfunction // new 24 | 25 | virtual function void build_phase(uvm_phase phase); 26 | super.build_phase(phase); 27 | if (!uvm_config_db#(virtual jvs_int_if)::get(this, "", "jvs_int_if", vif)) begin 28 | `uvm_fatal(get_full_name(), "Can't get the interrupt interface!"); 29 | end 30 | endfunction // build_phase 31 | 32 | virtual task main_phase(uvm_phase phase); 33 | vif.interrupt <= {`JVS_MAX_INT_PIN_NUM{1'b0}}; 34 | 35 | forever begin 36 | seq_item_port.get_next_item(req); 37 | if (req.set) begin 38 | int_set_cnt[req.irq_vector] ++ ; 39 | vif.interrupt[req.irq_vector] <= 1'b1; 40 | @(posedge vif.clk); 41 | end 42 | else begin 43 | if (int_set_cnt[req.irq_vector] > 0) begin 44 | int_set_cnt[req.irq_vector]--; 45 | if (int_set_cnt[req.irq_vector] == 0) begin 46 | vif.interrupt[req.irq_vector] <= 1'b0; 47 | end 48 | @(posedge vif.clk); 49 | end 50 | end // else: !if(req.set) 51 | seq_item_port.item_done(); 52 | end 53 | endtask 54 | endclass 55 | `endif -------------------------------------------------------------------------------- /src/irq/jvs_irq_vir_seq.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_VIR_SEQ_SV__ 2 | `define __JVS_IRQ_VIR_SEQ_SV__ 3 | class jvs_irq_vir_seq extends uvm_sequence_base; 4 | `uvm_declare_p_sequencer(jvs_irq_vir_sequencer) 5 | `uvm_object_utils_begin(jvs_irq_vir_seq) 6 | `uvm_object_utils_end 7 | 8 | function new(string name = "jvs_irq_vir_seq"); 9 | super.new(name); 10 | endfunction // new 11 | 12 | task body(); 13 | forever begin 14 | irq_process(); 15 | end 16 | endtask // body 17 | 18 | protected virtual task irq_process(); 19 | jvs_irq_trans irq_tr; 20 | p_sequencer.get_irq(irq_tr); 21 | `uvm_info(this.get_name(), {"irq_tr : \n", irq_tr.sprint()}, UVM_HIGH); 22 | //no handler, finish and return 23 | if (!p_sequencer.irq_table.exists(irq_tr.irq_vector) || p_sequencer.irq_table[irq_tr.irq_vector] == null) begin 24 | irq_tr.handle_state = jvs_irq_trans::FINISH; 25 | irq_tr.end_tr(); 26 | return; 27 | end 28 | p_sequencer.irq_table[irq_tr.irq_vector].lock.get(1); 29 | foreach(p_sequencer.irq_table[irq_tr.irq_vector].queue[i]) begin 30 | p_sequencer.irq_table[irq_tr.irq_vector].queue[i].handle(irq_tr); 31 | //if one handler change tr state to finish, break 32 | if (irq_tr.handle_state == jvs_irq_trans::FINISH) begin 33 | break; 34 | end 35 | end 36 | //if all handler didn't handle this tr or all handler shared this tr, it means all done, so change state to finish 37 | if (irq_tr.handle_state == jvs_irq_trans::THROUGH || irq_tr.handle_state == jvs_irq_trans::UNHANDLED) begin 38 | irq_tr.handle_state = jvs_irq_trans::FINISH; 39 | end 40 | //if all redirected trans have been handled and can finshi, end_tr 41 | //otherwise it is resposibility of redirected trans to end_tr 42 | if (irq_tr.can_end_tr()) begin 43 | irq_tr.end_tr(); 44 | end 45 | p_sequencer.irq_table[irq_tr.irq_vector].lock.put(1); 46 | 47 | endtask 48 | endclass 49 | `endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jarvisuk 2 | Just A Really Very Impressive Systemverilog UVM Kit 3 | 4 | 5 | 6 | # tools 7 | vcs 8 | 9 | [jarvism](https://github.com/shady831213/jarvism) 10 | 11 | # usage 12 | set $JVSUK_HOME to jarvisuk home dir. 13 | 14 | add $JVSUK_HOME/jvs.f to your filelist. 15 | 16 | # test 17 | ``` 18 | source jarvism_cfg/jarvism_setup.sh 19 | jarvism run_group jvs 20 | 21 | ``` 22 | 23 | # memory allocator 24 | + support random or fix address malloc(), free() 25 | + support va2pa 26 | + support memory attributes 27 | 28 | ## test 29 | ``` 30 | source jarvism_cfg/jarvism_setup.sh 31 | jarvism run_test jvs_memory jvs_memory_showcase -seed 1 32 | ``` 33 | 34 | # interrupt 35 | + support pin interrupt 36 | + support msi irq 37 | + support soft irq 38 | + support shared irq vector 39 | + support irq vector redirection 40 | 41 | ## test 42 | pin interrupt 43 | ``` 44 | source jarvism_cfg/jarvism_setup.sh 45 | jarvism run_test jvs_memory jvs_int_simple_test 46 | ``` 47 | msi irq 48 | ``` 49 | source jarvism_cfg/jarvism_setup.sh 50 | jarvism run_test jvs_memory jvs_msi_irq_test 51 | ``` 52 | soft irq 53 | ``` 54 | source jarvism_cfg/jarvism_setup.sh 55 | jarvism run_test jvs_memory jvs_soft_irq_test 56 | ``` 57 | 58 | 59 | # register region 60 | + solve register name conflict 61 | + multiple sequencer and adapter share root_map 62 | + multiple reg_blocks with the same attribute into same reg region 63 | + thread-safe 64 | ## test 65 | ``` 66 | source jarvism_cfg/jarvism_setup.sh 67 | jarvism run_test jvs_register_region jvs_register_region_test -seed 1 68 | ``` 69 | 70 | # clock reset group 71 | + 72 | + support same source but diffrent frequency clocks 73 | + support differnt source async clocks 74 | + support global or partially reset 75 | + support sync and async reset 76 | ## test 77 | ``` 78 | source jarvism_cfg/jarvism_setup.sh 79 | jarvism run_test jvs_clk_rst_group jvs_clk_rst_group_basic_test -seed 1 -wave 80 | ``` 81 | 82 | -------------------------------------------------------------------------------- /jarvism_cfg/jarvism_cfg.yaml: -------------------------------------------------------------------------------- 1 | common_compile_option: &common_compile >- 2 | -sverilog 3 | -ntb_opts uvm-1.1 4 | -timescale=1ns/10ps 5 | -f $JVSUK_HOME/etc/jvs.f 6 | 7 | builds: 8 | jvs_memory: 9 | test_discoverer: 10 | type: "uvm_test" 11 | attr: 12 | test_dir: $JVSUK_HOME/testcases/jvs_memory 13 | compile_option: 14 | - *common_compile 15 | - $JVSUK_HOME/tb/jvs_memory_tb.sv -top jvs_memory_tb 16 | sim_option: 17 | - +UVM_VERBOSITY=UVM_HIGH 18 | 19 | jvs_irq: 20 | test_discoverer: 21 | type: "uvm_test" 22 | attr: 23 | test_dir: $JVSUK_HOME/testcases/jvs_irq 24 | compile_option: 25 | - *common_compile 26 | - $JVSUK_HOME/tb/jvs_irq_tb.sv -top jvs_irq_tb 27 | sim_option: 28 | - +UVM_VERBOSITY=UVM_HIGH 29 | 30 | jvs_register_region: 31 | test_discoverer: 32 | type: "uvm_test" 33 | attr: 34 | test_dir: $JVSUK_HOME/testcases/jvs_register_region 35 | compile_option: 36 | - *common_compile 37 | - $JVSUK_HOME/tb/jvs_register_region_tb.sv -top jvs_register_region_tb 38 | sim_option: 39 | - +UVM_VERBOSITY=UVM_HIGH 40 | 41 | jvs_clk_rst_group: 42 | test_discoverer: 43 | type: "uvm_test" 44 | attr: 45 | test_dir: $JVSUK_HOME/testcases/jvs_clk_rst_group 46 | compile_option: 47 | - *common_compile 48 | - $JVSUK_HOME/tb/jvs_clk_rst_group_tb.sv -top jvs_clk_rst_group_tb 49 | sim_option: 50 | - +UVM_VERBOSITY=UVM_HIGH 51 | 52 | 53 | 54 | groups: 55 | jvs_memory: 56 | build: 57 | jvs_memory 58 | tests: 59 | - jvs_memory_showcase: 60 | 61 | jvs_irq: 62 | build: 63 | jvs_irq 64 | tests: 65 | - jvs_int_simple_test: 66 | - jvs_msi_irq_test: 67 | - jvs_soft_irq_test: 68 | 69 | jvs_register_region: 70 | build: 71 | jvs_register_region 72 | tests: 73 | - jvs_register_region_test: 74 | 75 | jvs_clk_rst_group: 76 | build: 77 | jvs_clk_rst_group 78 | tests: 79 | - jvs_clk_rst_group_basic_test: 80 | 81 | jvs: 82 | groups: 83 | - jvs_memory 84 | - jvs_irq 85 | - jvs_register_region 86 | - jvs_clk_rst_group -------------------------------------------------------------------------------- /src/register_region/jvs_reg_region_builder.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REG_REGION_BUILDER_SV__ 2 | `define __JVS_REG_REGION_BUILDER_SV__ 3 | virtual class jvs_reg_region_builder extends uvm_object; 4 | `uvm_field_utils_begin(jvs_reg_region_builder) 5 | `uvm_field_utils_end 6 | 7 | function new(string name = "jvs_reg_region_builder"); 8 | super.new(name); 9 | endfunction // new 10 | 11 | protected function jvs_reg_region create_region(string name, 12 | bit [63:0] base_addr, 13 | bit [63:0] end_addr, 14 | jvs_reg_region parent = null, 15 | string attr_class_name = "jvs_reg_region_attr", 16 | uvm_sequencer_base seqr = null, 17 | uvm_reg_adapter adapter = null 18 | ); 19 | bit [63:0] size = end_addr - base_addr + 1; 20 | bit [63:0] offset = parent == null? base_addr : base_addr - parent.get_base(); 21 | return create_region_by_offset_and_size(name, offset, size, parent, attr_class_name, seqr, adapter); 22 | endfunction 23 | 24 | protected function jvs_reg_region create_region_by_offset_and_size(string name, 25 | bit [63:0] offset, 26 | bit [63:0] size, 27 | jvs_reg_region parent = null, 28 | string attr_class_name = "jvs_reg_region_attr", 29 | uvm_sequencer_base seqr = null, 30 | uvm_reg_adapter adapter = null 31 | ); 32 | jvs_reg_region region = jvs_reg_region::type_id::create(name); 33 | region.config_range(offset, size); 34 | $cast(region.attr, uvm_factory::get().create_object_by_name(attr_class_name)); 35 | if (parent != null) begin 36 | if (!parent.add_sub_region(region)) begin 37 | parent.print(); 38 | region.print(); 39 | `uvm_fatal(this.get_name(), $psprintf("region %0s add failed!", name)); 40 | end 41 | end 42 | region.config_seqr_adapter(jvs_reg_seqr_adapter_pair_factory::get_seqr_adapter_pair(seqr, adapter)); 43 | return region; 44 | endfunction 45 | 46 | pure virtual function jvs_reg_region build_region(); 47 | 48 | 49 | endclass 50 | `endif -------------------------------------------------------------------------------- /src/irq/jvs_irq_env.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_ENV_SV__ 2 | `define __JVS_IRQ_ENV_SV__ 3 | class jvs_irq_env extends uvm_env; 4 | jvs_irq_vir_sequencer jvs_irq_seqr; 5 | jvs_int_agent jvs_int_ag; 6 | jvs_msi_monitor jvs_msi_mon; 7 | 8 | `uvm_component_utils_begin(jvs_irq_env) 9 | `uvm_component_utils_end 10 | 11 | function new(string name = "jvs_irq_env", uvm_component parent = null); 12 | super.new(name, parent); 13 | endfunction // new 14 | 15 | virtual function void build_phase(uvm_phase phase); 16 | super.build_phase(phase); 17 | uvm_config_db#(uvm_object_wrapper)::set(this, "jvs_irq_seqr.run_phase", "default_sequence", jvs_irq_vir_seq::type_id::get()); 18 | jvs_irq_seqr = jvs_irq_vir_sequencer::type_id::create("jvs_irq_seqr", this); 19 | jvs_int_ag = jvs_int_agent::type_id::create("jvs_int_agent", this); 20 | if (!uvm_config_db#(jvs_msi_monitor)::get(this, "", "jvs_msi_monitor", jvs_msi_mon)) begin 21 | `uvm_info(this.get_name, "no msi support!", UVM_LOW); 22 | end 23 | endfunction // build_phase 24 | 25 | virtual function void connect_phase(uvm_phase phase); 26 | super.connect_phase(phase); 27 | jvs_int_ag.irq_put_export.connect(jvs_irq_seqr.irq_put_imp); 28 | if (jvs_msi_mon != null) begin 29 | jvs_msi_mon.ap.connect(jvs_irq_seqr.irq_put_imp); 30 | end 31 | endfunction // connect_phase 32 | 33 | task register_irq(bit[`JVS_MAX_IRQ_VECTOR_WIDTH-1:0] irq_vector, jvs_irq_handler handler); 34 | jvs_irq_seqr.register_irq(irq_vector, handler); 35 | endtask 36 | 37 | task unregister_irq(bit[`JVS_MAX_IRQ_VECTOR_WIDTH-1:0] irq_vector, jvs_irq_handler handler); 38 | jvs_irq_seqr.register_irq(irq_vector, handler); 39 | endtask // unregister_irq 40 | 41 | task reset(); 42 | jvs_irq_seqr.reset(); 43 | endtask // reset 44 | 45 | function void trigger_soft_irq(jvs_irq_trans tr); 46 | if (tr.get_irq_type() != jvs_irq_trans::SOFT_IRQ) begin 47 | tr.print(); 48 | `uvm_fatal(this.get_name(), "irq is not soft irq!"); 49 | end 50 | jvs_irq_seqr.write(tr); 51 | endfunction 52 | endclass 53 | `endif -------------------------------------------------------------------------------- /include/common/jvs_common_defines.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_COMMON_DEFINES_SV__ 2 | `define __JVS_COMMON_DEFINES_SV__ 3 | 4 | `define JVS_WAVE(HIER) \ 5 | function string get_wave_name(); \ 6 | string wave_name; \ 7 | if ($test$plusargs("WAVE_NAME")) begin \ 8 | void'($value$plusargs("WAVE_NAME=%s", wave_name)); \ 9 | end \ 10 | else begin \ 11 | wave_name = "test"; \ 12 | end \ 13 | return wave_name; \ 14 | endfunction \ 15 | initial begin \ 16 | `ifdef DUMP_FSDB \ 17 | `ifndef GATE_SIM \ 18 | $fsdbDumpfile($psprintf("%s.fsdb", get_wave_name())); \ 19 | `else \ 20 | $fsdbDumpfile($psprintf("%s_gate.fsdb", get_wave_name())); \ 21 | `endif \ 22 | $fsdbDumpvars(0, HIER, "+all"); \ 23 | `ifdef DUMP_MEM \ 24 | $fsdbDumpMDA; \ 25 | `endif \ 26 | `ifdef DUMP_SVA \ 27 | $fsdbDumpSVA; \ 28 | `endif \ 29 | $fsdbDumpon; \ 30 | `elsif DUMP_VPD \ 31 | `ifndef GATE_SIM \ 32 | $vcdplusfile($psprintf("%s.vpd", get_wave_name())); \ 33 | `else \ 34 | $vcdplusfile($psprintf("%s_gate.vpd", get_wave_name())); \ 35 | `endif \ 36 | $vcdpluson(0, HIER); \ 37 | `elsif DUMP_VCD \ 38 | `ifndef GATE_SIM \ 39 | $dumpfile("test.vcd"); //cadence does not support string var\ 40 | `else \ 41 | $dumpfile("test_gate.vcd"); \ 42 | `endif \ 43 | $dumpvars(0, HIER); \ 44 | `elsif DUMP_TRN \ 45 | `ifndef GATE_SIM \ 46 | $recordfile($psprintf("%s", get_wave_name())); \ 47 | `else \ 48 | $recordfile($psprintf("%s_gate", get_wave_name())); \ 49 | `endif \ 50 | $recordvars(0, HIER); \ 51 | `endif \ 52 | end 53 | 54 | `define JVS_FOR_FJ_BEGIN(ID, LOW, HIGH, STEP) \ 55 | fork begin \ 56 | for(int _i = LOW; _i < HIGH; _i = _i + STEP) begin \ 57 | automatic int ID = _i; \ 58 | fork \ 59 | begin 60 | 61 | `define JVS_FOR_FJ_END \ 62 | end \ 63 | join_none \ 64 | end \ 65 | wait fork; \ 66 | end \ 67 | join 68 | 69 | 70 | `define JVS_FOREACH_FJ_BEGIN(VAR, ID) \ 71 | fork begin \ 72 | foreach(VAR[_i]) begin \ 73 | automatic int ID = _i; \ 74 | fork \ 75 | begin 76 | 77 | `define JVS_FOREACH_FJ_END `JVS_FOR_FJ_END 78 | 79 | `endif -------------------------------------------------------------------------------- /src/register_region/jvs_reg_block_wrapper.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REG_BLOCK_WRAPPER_SV__ 2 | `define __JVS_REG_BLOCK_WRAPPER_SV__ 3 | typedef class jvs_reg_region; 4 | class jvs_reg_block_wrapper extends jvs_reg_tree_node#(jvs_reg_region); 5 | protected uvm_reg_block reg_block; 6 | `uvm_object_utils_begin(jvs_reg_block_wrapper) 7 | `uvm_object_utils_end 8 | 9 | function new(string name = "jvs_reg_block_wrapper"); 10 | super.new(name); 11 | endfunction // new 12 | 13 | function void bind_reg_block(uvm_reg_block reg_block); 14 | this.reg_block = reg_block; 15 | endfunction // bind_reg_block 16 | 17 | virtual function bit[63:0] get_base(); 18 | return reg_block.get_default_map().get_base_addr(); 19 | endfunction // get_base 20 | 21 | virtual function bit[63:0] get_size(); 22 | return reg_block.get_default_map().get_size(); 23 | endfunction 24 | 25 | function jvs_reg_block_wrapper get_reg_block(string name); 26 | uvm_reg_block block = reg_block.get_block_by_name(name); 27 | jvs_reg_block_wrapper wrapper = jvs_reg_block_wrapper::type_id::create(name); 28 | wrapper.parent = this.parent; 29 | wrapper.bind_reg_block(block); 30 | return wrapper; 31 | endfunction // get_reg_block 32 | 33 | function bit get_reg(string name, output jvs_reg_block_wrapper reg_block, output uvm_reg register); 34 | uvm_reg _register = this.reg_block.get_reg_by_name(name); 35 | if (_register != null) begin 36 | register = _register; 37 | reg_block = this; 38 | return 1; 39 | end 40 | return 0; 41 | endfunction // get_reg 42 | 43 | //for bit bash and reset value 44 | task request_access(); 45 | jvs_reg_resource_manager::get_manager().request_reg_map(parent.get_seqr_adapter(), reg_block.get_default_map().get_root_map()); 46 | endtask // request_access 47 | 48 | task release_access(); 49 | jvs_reg_resource_manager::get_manager().release_reg_map(parent.get_seqr_adapter(), reg_block.get_default_map().get_root_map()); 50 | endtask // release_access 51 | 52 | function uvm_reg_block get_uvm_reg_block(); 53 | return this.reg_block; 54 | endfunction 55 | endclass 56 | `endif -------------------------------------------------------------------------------- /src/clk_rst_group/jvs_clk_vir_seqr.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_VIR_SEQR_SV__ 2 | `define __JVS_CLK_VIR_SEQR_SV__ 3 | class jvs_clk_vir_seqr extends uvm_virtual_sequencer; 4 | uvm_analysis_export#(jvs_clk_rst_trans) rst_ana_export; 5 | uvm_analysis_export#(jvs_clk_change_div) change_div_ana_export; 6 | `uvm_component_utils(jvs_clk_vir_seqr) 7 | function new(string name = "jvs_clk_vir_seqr", uvm_component parent = null); 8 | super.new(name, parent); 9 | rst_ana_export = new("rst_ana_export", this); 10 | change_div_ana_export = new("change_div_ana_export", this); 11 | endfunction // new 12 | endclass // jvs_clk_vir_seqr 13 | 14 | class jvs_clk_group_vir_seqr extends jvs_clk_vir_seqr; 15 | jvs_clk_vir_seqr clk_seqrs[string]; 16 | 17 | `uvm_component_utils_begin(jvs_clk_group_vir_seqr) 18 | `uvm_field_aa_object_string(clk_seqrs, UVM_ALL_ON) 19 | `uvm_component_utils_end 20 | function new(string name = "jvs_clk_group_vir_seqr", uvm_component parent = null); 21 | super.new(name, parent); 22 | endfunction // new 23 | endclass // jvs_clk_group_vir_seqr 24 | 25 | class jvs_clk_top_vir_seqr extends jvs_clk_vir_seqr; 26 | jvs_clk_group_vir_seqr group_seqrs[string]; 27 | 28 | `uvm_component_utils_begin(jvs_clk_top_vir_seqr) 29 | `uvm_field_aa_object_string(group_seqrs, UVM_ALL_ON) 30 | `uvm_component_utils_end 31 | function new(string name = "jvs_clk_top_vir_seqr", uvm_component parent = null); 32 | super.new(name, parent); 33 | endfunction // new 34 | 35 | virtual task hw_reset(string pattern = "*"); 36 | jvs_clk_rst_trans tr = new(); 37 | tr.pattern = pattern; 38 | rst_ana_export.write(tr); 39 | tr.wait_end(); 40 | `uvm_info(this.get_name(), $psprintf("@%0t hw_reset %0s done!", $realtime, pattern), UVM_LOW); 41 | endtask // hw_global_reset 42 | 43 | virtual task change_div(string pattern = "*", int div_ratio); 44 | jvs_clk_change_div tr = new(); 45 | tr.pattern = pattern; 46 | tr.div_ratio = div_ratio; 47 | change_div_ana_export.write(tr); 48 | tr.wait_end(); 49 | `uvm_info(this.get_name(), $psprintf("@%0t change div_ratio %0s to %0d done!", $realtime, pattern, div_ratio), UVM_LOW); 50 | endtask 51 | 52 | 53 | endclass 54 | `endif 55 | -------------------------------------------------------------------------------- /src/irq/jvs_irq_vir_sequencer.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_SEQUENCER_SV__ 2 | `define __JVS_IRQ_SEQUENCER_SV__ 3 | typedef jvs_common_type_queue#(jvs_irq_handler) jvs_irq_handler_queue; 4 | class jvs_irq_vir_sequencer extends uvm_virtual_sequencer; 5 | jvs_irq_handler_queue irq_table[bit[`JVS_MAX_IRQ_VECTOR_WIDTH-1:0]]; 6 | 7 | uvm_analysis_imp#(jvs_irq_trans, jvs_irq_vir_sequencer) irq_put_imp; 8 | local uvm_tlm_analysis_fifo #(jvs_irq_trans) irq_fifo; 9 | 10 | `uvm_component_utils(jvs_irq_vir_sequencer) 11 | function new(string name = "jvs_irq_vir_sequencer", uvm_component parent = null); 12 | super.new(name, parent); 13 | irq_put_imp = new("irq_put_imp", this); 14 | irq_fifo = new("irq_fifo", this); 15 | endfunction // new 16 | 17 | function void write(jvs_irq_trans tr); 18 | if (irq_fifo == null) begin 19 | tr.end_tr(); 20 | return; 21 | end 22 | irq_fifo.write(tr); 23 | endfunction // write 24 | 25 | task get_irq(output jvs_irq_trans tr); 26 | wait(irq_fifo != null); 27 | irq_fifo.get(tr); 28 | endtask // get_irq 29 | 30 | task register_irq(bit[`JVS_MAX_IRQ_VECTOR_WIDTH-1:0] irq_vector, jvs_irq_handler handler); 31 | if (!irq_table.exists(irq_vector) || irq_table[irq_vector] == null) begin 32 | irq_table[irq_vector] = new(); 33 | end 34 | irq_table[irq_vector].lock.get(1); 35 | irq_table[irq_vector].queue.push_back(handler); 36 | irq_table[irq_vector].lock.put(1); 37 | endtask // register_irq 38 | 39 | task unregister_irq(bit[`JVS_MAX_IRQ_VECTOR_WIDTH-1:0] irq_vector, jvs_irq_handler handler); 40 | irq_table[irq_vector].lock.get(1); 41 | foreach(irq_table[irq_vector].queue[i]) begin 42 | if (irq_table[irq_vector].queue[i] == handler) begin 43 | irq_table[irq_vector].queue.delete(i); 44 | break; 45 | end 46 | end 47 | irq_table[irq_vector].lock.put(1); 48 | endtask // unregister_irq 49 | 50 | virtual task reset(); 51 | //clear fifo 52 | irq_fifo = null; 53 | //clear irq_table 54 | foreach(irq_table[i]) begin 55 | if (irq_table[i] != null) begin 56 | irq_table[i].lock.get(1); 57 | irq_table[i] = null; 58 | irq_table[i].lock.put(1); 59 | end 60 | end 61 | //start fifo 62 | irq_fifo = new("irq_fifo", this); 63 | endtask 64 | endclass 65 | `endif -------------------------------------------------------------------------------- /src/memory/jvs_memory_model.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MEMORY_MODEL_SV__ 2 | `define __JVS_MEMORY_MODEL_SV__ 3 | virtual class jvs_memory_model extends uvm_object; 4 | `uvm_field_utils_begin(jvs_memory_model) 5 | `uvm_field_utils_end 6 | function new(input string name = "jvs_memory_model"); 7 | super.new(name); 8 | endfunction // new 9 | pure virtual function void write_byte(input bit[63:0]addr, input MEM_BYTE data); 10 | pure virtual function MEM_BYTE read_byte(input bit[63:0]addr); 11 | 12 | virtual function void write_int(input bit[63:0]addr, input MEM_INT data); 13 | for(bit[2:0] i = 0; i < 4; i++) begin 14 | write_byte({addr[63:2], i[1:0]}, data[i*8 +: 8]); 15 | end 16 | endfunction 17 | 18 | virtual function MEM_INT read_int(input bit[63:0]addr); 19 | MEM_INT data; 20 | for(bit[2:0] i = 0; i < 4; i++) begin 21 | data[i*8 +: 8] = read_byte({addr[63:2], i[1:0]}); 22 | end 23 | return data; 24 | endfunction 25 | 26 | virtual function void write_long(input bit[63:0]addr, input MEM_LONG data); 27 | for(bit[3:0] i = 0; i < 8; i++) begin 28 | write_byte({addr[63:3], i[2:0]}, data[i*8 +: 8]); 29 | end 30 | endfunction 31 | 32 | virtual function MEM_LONG read_long(input bit[63:0]addr); 33 | MEM_LONG data; 34 | for(bit[3:0] i = 0; i < 8; i++) begin 35 | data[i*8 +: 8] = read_byte({addr[63:3], i[2:0]}); 36 | end 37 | return data; 38 | endfunction 39 | 40 | virtual function void delete(input bit[63:0] addr, input bit[63:0] size); 41 | for (bit[63:0] i = 0; i < size; i++) begin 42 | write_byte(addr + i, 0); 43 | end 44 | endfunction 45 | endclass 46 | 47 | class jvs_memory_aa_model extends jvs_memory_model; 48 | protected MEM_BYTE mem[bit[63:0]]; 49 | 50 | `uvm_object_utils_begin(jvs_memory_aa_model) 51 | `uvm_object_utils_end 52 | function new(input string name = "jvs_memory_aa_model"); 53 | super.new(name); 54 | endfunction // new 55 | 56 | virtual function void write_byte(input bit[63:0]addr, input MEM_BYTE data); 57 | mem[addr] = data; 58 | endfunction // write_byte 59 | 60 | virtual function MEM_BYTE read_byte(input bit[63:0]addr); 61 | return mem[addr]; 62 | endfunction 63 | 64 | virtual function void delete(input bit[63:0] addr, input bit[63:0] size); 65 | for (bit[63:0] i = 0; i < size; i++) begin 66 | mem.delete(addr + i); 67 | end 68 | endfunction 69 | 70 | endclass 71 | `endif -------------------------------------------------------------------------------- /src/register_region/jvs_reg_region_mapper.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REG_REGION_MAPPER_SV__ 2 | `define __JVS_REG_REGION_MAPPER_SV_ 3 | 4 | class jvs_reg_region_catcher extends uvm_report_catcher; 5 | function new(input string name = "jvs_reg_region_catcher"); 6 | super.new(name); 7 | endfunction // new 8 | 9 | function action_e catch(); 10 | if (get_severity() == UVM_WARNING && get_id() == "RegModel") begin 11 | if (uvm_is_match("*Unable to locat*", get_message())) begin 12 | return CAUGHT; 13 | end 14 | end 15 | return THROW; 16 | endfunction 17 | endclass // jvs_reg_region_catcher 18 | 19 | class jvs_reg_region_mapper extends uvm_object; 20 | `uvm_object_utils_begin(jvs_reg_region_mapper) 21 | `uvm_object_utils_end 22 | 23 | function new(string name = "jvs_reg_region_mapper"); 24 | jvs_reg_region_catcher catcher; 25 | super.new(name); 26 | catcher = new("jvs_reg_region_catcher"); 27 | `ifdef UVM_VERSION_1_2 28 | uvm_report_cb::add(uvm_get_report_object(), catcher); 29 | `else 30 | uvm_report_cb::add(null, catcher); 31 | `endif 32 | endfunction // new 33 | 34 | 35 | local function void map_rec(uvm_reg_block root_reg_block, jvs_reg_region raw_region); 36 | uvm_reg_block all_blocks[$]; 37 | root_reg_block.get_blocks(all_blocks, UVM_NO_HIER); 38 | foreach(all_blocks[i]) begin 39 | add_to_region(all_blocks[i], raw_region); 40 | map_rec(all_blocks[i], raw_region); 41 | end 42 | endfunction // map_rec 43 | 44 | function void map(uvm_reg_block root_reg_block, jvs_reg_region raw_region); 45 | add_to_region(root_reg_block, raw_region); 46 | map_rec(root_reg_block, raw_region); 47 | endfunction // map 48 | 49 | function void unmap(uvm_reg_block root_reg_block, jvs_reg_region raw_region); 50 | uvm_reg_block all_blocks[$]; 51 | jvs_reg_region parent; 52 | jvs_reg_block_wrapper reg_wrapper = raw_region.get_reg_block(root_reg_block.get_full_name()); 53 | if (reg_wrapper == null) begin 54 | return; 55 | end 56 | parent = reg_wrapper.get_parent(); 57 | parent.remove_reg_block(root_reg_block.get_full_name()); 58 | root_reg_block.get_blocks(all_blocks, UVM_HIER); 59 | foreach(all_blocks[i]) begin 60 | parent.remove_reg_block(all_blocks[i].get_full_name()); 61 | end 62 | endfunction // unmap 63 | 64 | local function void add_to_region(uvm_reg_block reg_block, jvs_reg_region raw_region); 65 | jvs_reg_block_wrapper reg_wrapper = jvs_reg_block_wrapper::type_id::create(reg_block.get_full_name()); 66 | reg_wrapper.bind_reg_block(reg_block); 67 | if (!raw_region.add_reg_block(reg_wrapper)) begin 68 | raw_region.print(); 69 | `uvm_fatal(this.get_name(), $psprintf("%0s add failed!", reg_block.get_full_name())); 70 | end 71 | endfunction 72 | endclass 73 | 74 | `endif -------------------------------------------------------------------------------- /testcases/jvs_register_region/jvs_reg_base_test.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REG_BASE_TEST_SV__ 2 | `define __JVS_REG_BASE_TEST_SV__ 3 | class jvs_reg_test_trans extends uvm_sequence_item; 4 | bit w_nr; 5 | bit [63:0] addr; 6 | bit [31:0] data; 7 | 8 | `uvm_object_utils_begin(jvs_reg_test_trans) 9 | `uvm_field_int(w_nr, UVM_ALL_ON) 10 | `uvm_field_int(addr, UVM_ALL_ON) 11 | `uvm_field_int(data, UVM_ALL_ON) 12 | `uvm_object_utils_end 13 | 14 | function new(string name = "jvs_reg_test_trans"); 15 | super.new(name); 16 | endfunction // new 17 | 18 | endclass // jvs_reg_test_trans 19 | 20 | class jvs_reg_test_adapter extends uvm_reg_adapter; 21 | `uvm_object_utils_begin(jvs_reg_test_adapter) 22 | `uvm_object_utils_end 23 | 24 | function new(string name = "jvs_reg_test_adapter"); 25 | super.new(name); 26 | endfunction // new 27 | 28 | virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw); 29 | jvs_reg_test_trans tr = jvs_reg_test_trans::type_id::create("tr"); 30 | tr.addr = rw.addr; 31 | if (rw.kind == UVM_READ) begin 32 | tr.w_nr = 0; 33 | tr.print(); 34 | return tr; 35 | end 36 | tr.w_nr = 1; 37 | tr.data = rw.data; 38 | tr.print(); 39 | return tr; 40 | endfunction // reg2bus 41 | 42 | virtual function void bus2reg(uvm_sequence_item bus_item, 43 | ref uvm_reg_bus_op rw); 44 | jvs_reg_test_trans tr; 45 | if (!$cast(tr, bus_item)) begin 46 | `uvm_fatal(this.get_name(), "Wrong type!"); 47 | return; 48 | end 49 | rw.kind = (tr.w_nr == 0) ? UVM_READ: UVM_WRITE; 50 | rw.addr = tr.addr; 51 | if (tr.w_nr == 0) begin 52 | rw.data = tr.data; 53 | end 54 | endfunction 55 | endclass // jvs_reg_test_adapter 56 | 57 | typedef uvm_sequencer #(jvs_reg_test_trans) jvs_reg_test_sequencer; 58 | 59 | class jvs_reg_test_driver extends uvm_driver#(jvs_reg_test_trans); 60 | bit[31:0] map[bit[31:0]]; 61 | 62 | `uvm_component_utils(jvs_reg_test_driver) 63 | 64 | function new(string name = "jvs_reg_test_driver", uvm_component parent); 65 | super.new(name,parent); 66 | endfunction // new 67 | 68 | virtual task run_phase(uvm_phase phase); 69 | while(1) begin 70 | seq_item_port.get_next_item(req); 71 | if (!req.w_nr) begin 72 | req.data = map[req.addr[31:0]]; 73 | end 74 | else begin 75 | map[req.addr[31:0]] = req.data; 76 | end 77 | `uvm_info(this.get_name(), "get_trans!", UVM_LOW); 78 | req.print(); 79 | seq_item_port.item_done(); 80 | end 81 | endtask 82 | endclass // jvs_reg_test_driver 83 | 84 | class jvs_reg_base_test extends uvm_test; 85 | jvs_reg_region_mapper region_mapper; 86 | `uvm_component_utils(jvs_reg_base_test) 87 | function new(string name = "jvs_reg_base_test", uvm_component parent); 88 | super.new(name,parent); 89 | region_mapper = jvs_reg_region_mapper::type_id::create("region_mapper"); 90 | endfunction // new 91 | 92 | endclass 93 | `endif -------------------------------------------------------------------------------- /src/irq/jvs_irq_handler.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_HANDLER_SV__ 2 | `define __JVS_IRQ_HANDLER_SV__ 3 | typedef jvs_common_type_queue#(jvs_irq_result_trans) jvs_irq_result_queue; 4 | 5 | virtual class jvs_irq_handler extends uvm_object; 6 | protected jvs_irq_result_queue irq_result_fifo; 7 | protected int fifo_size = 1000; 8 | `uvm_field_utils_begin(jvs_irq_handler) 9 | `uvm_field_int(fifo_size, UVM_ALL_ON) 10 | `uvm_field_utils_end 11 | 12 | function new(string name = "jvs_irq_handler"); 13 | super.new(name); 14 | irq_result_fifo = new(); 15 | endfunction // new 16 | 17 | pure virtual task do_handle(jvs_irq_trans irq_tr); 18 | 19 | pure virtual function jvs_irq_result_trans gen_result(jvs_irq_trans irq_tr); 20 | 21 | task handle(jvs_irq_trans irq_tr); 22 | do_handle(irq_tr); 23 | put_result(gen_result(irq_tr)); 24 | endtask // handle 25 | 26 | local task put_result(jvs_irq_result_trans result); 27 | if (result != null) begin 28 | irq_result_fifo.lock.get(1); 29 | if (irq_result_fifo.queue.size() >= fifo_size) begin 30 | `uvm_fatal(this.get_name(), "result queue overflow! too many unhandled results!"); 31 | irq_result_fifo.lock.put(1); 32 | return; 33 | end 34 | irq_result_fifo.queue.push_back(result); 35 | irq_result_fifo.lock.put(1); 36 | `uvm_info(this.get_name(), "generated a result!",UVM_HIGH); 37 | end 38 | endtask 39 | 40 | //default timeout:100ms 41 | task get_irq_result(output jvs_irq_result_trans tr, input int timeout = 100000000, input int polling_period = 100); 42 | int timer_cnt; 43 | do begin 44 | irq_result_fifo.lock.get(1); 45 | if (irq_result_fifo.queue.size() > 0) begin 46 | tr = irq_result_fifo.queue.pop_front(); 47 | irq_result_fifo.lock.put(1); 48 | `uvm_info(this.get_name(), "got a result!", UVM_HIGH); 49 | return; 50 | end 51 | irq_result_fifo.lock.put(1); 52 | timer_cnt += polling_period; 53 | #(polling_period * 1ns); 54 | end while(timer_cnt <= timeout); // UNMATCHED !! 55 | `uvm_info(this.get_name(), "getting result timeout!", UVM_HIGH); 56 | endtask // get_irq_result 57 | 58 | task get_n_irq_results(int n, ref jvs_irq_result_trans tr_q[$], input int timeout = 100000000, input int polling_period = 100); 59 | int timer_cnt; 60 | int tr_cnt = n; 61 | do begin 62 | int remain_tr_num; 63 | int _tr_cnt; 64 | irq_result_fifo.lock.get(1); 65 | remain_tr_num = irq_result_fifo.queue.size(); 66 | _tr_cnt = tr_cnt < remain_tr_num ? tr_cnt : remain_tr_num; 67 | for (int i = 0; i < _tr_cnt; i++) begin 68 | tr_q.push_back(irq_result_fifo.queue.pop_front()); 69 | end 70 | tr_cnt -= _tr_cnt; 71 | irq_result_fifo.lock.put(1); 72 | if (tr_cnt == 0) begin 73 | `uvm_info(this.get_name(), $psprintf("got %0d results!", n), UVM_HIGH); 74 | return; 75 | end 76 | timer_cnt += polling_period; 77 | #(polling_period * 1ns); 78 | end while (timer_cnt <= timeout); // UNMATCHED !! 79 | `uvm_info(this.get_name(), $psprintf("getting %0d results timeout! got %0d results finally!", n, n - tr_cnt), UVM_HIGH); 80 | endtask 81 | endclass 82 | 83 | `endif -------------------------------------------------------------------------------- /testcases/jvs_register_region/jvs_test_reg_model.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_TEST_REG_MODEL_SV__ 2 | `define __JVS_TEST_REG_MODEL_SV__ 3 | class jvs_test_reg extends uvm_reg; 4 | `uvm_object_utils(jvs_test_reg) 5 | rand uvm_reg_field test_field; 6 | function new(string name = "jvs_test_reg"); 7 | super.new(name, 32, (UVM_NO_COVERAGE)); 8 | endfunction // new 9 | 10 | virtual function void build(); 11 | this.test_field = uvm_reg_field::type_id::create("test_field",, get_full_name()); 12 | this.test_field.configure(this, 32, 0, "RW", 0, 32'b0, 1, 1, 1); 13 | endfunction 14 | endclass // jvs_test_reg 15 | 16 | class jvs_test_block extends uvm_reg_block; 17 | `uvm_object_utils(jvs_test_block) 18 | rand jvs_test_reg test_reg; 19 | 20 | function new(string name = "jvs_test_block"); 21 | super.new(name,(UVM_NO_COVERAGE)); 22 | endfunction // new 23 | 24 | virtual function void build(); 25 | this.default_map = create_map("", 0, 4, UVM_LITTLE_ENDIAN, 0); 26 | this.test_reg = jvs_test_reg::type_id::create("test_reg",, get_full_name()); 27 | this.test_reg.configure(this, null, ""); 28 | this.test_reg.build(); 29 | this.default_map.add_reg(this.test_reg, `UVM_REG_ADDR_WIDTH'h4, "RW", 0); 30 | endfunction 31 | 32 | endclass // jvs_test_block 33 | 34 | class jvs_test_sub_top_block extends uvm_reg_block; 35 | rand jvs_test_block block[2]; 36 | 37 | `uvm_object_utils(jvs_test_sub_top_block) 38 | function new(string name = "jvs_test_sub_top_block"); 39 | super.new(name); 40 | endfunction // new 41 | 42 | virtual function void build(); 43 | this.default_map = create_map("", 0, 4, UVM_LITTLE_ENDIAN, 0); 44 | foreach(this.block[i]) begin 45 | this.block[i] = jvs_test_block::type_id::create($psprintf("block[%0d]", i)); 46 | this.block[i].configure(this); 47 | this.block[i].build(); 48 | this.default_map.add_submap(this.block[i].default_map, i << 16); 49 | end 50 | endfunction 51 | 52 | endclass 53 | 54 | class jvs_test_top_block extends uvm_reg_block; 55 | rand jvs_test_sub_top_block sub_top_block; 56 | rand jvs_test_block block[2]; 57 | rand jvs_test_reg test_reg; 58 | 59 | `uvm_object_utils(jvs_test_top_block) 60 | function new(string name = "jvs_test_top_block"); 61 | super.new(name); 62 | endfunction // new 63 | 64 | virtual function void build(); 65 | this.default_map = create_map("", 0, 4, UVM_LITTLE_ENDIAN, 0); 66 | foreach(this.block[i]) begin 67 | this.block[i] = jvs_test_block::type_id::create($psprintf("block[%0d]", i)); 68 | this.block[i].configure(this); 69 | this.block[i].build(); 70 | this.default_map.add_submap(this.block[i].default_map, i << 24); 71 | end 72 | 73 | this.sub_top_block = jvs_test_sub_top_block::type_id::create("sub_top_block"); 74 | this.sub_top_block.configure(this); 75 | this.sub_top_block.build(); 76 | this.default_map.add_submap(this.sub_top_block.default_map, 3 << 24); 77 | 78 | this.test_reg = jvs_test_reg::type_id::create("top_reg",, get_full_name()); 79 | this.test_reg.configure(this, null, ""); 80 | this.test_reg.build(); 81 | this.default_map.add_reg(this.test_reg, 4 << 24, "RW", 0); 82 | endfunction 83 | 84 | endclass 85 | `endif -------------------------------------------------------------------------------- /testcases/jvs_clk_rst_group/jvs_clk_rst_group_basic_test/jvs_clk_rst_group_basic_test.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_RST_GROUP_BASIC_TEST_SV__ 2 | `define __JVS_CLK_RST_GROUP_BASIC_TEST_SV_ 3 | class jvs_clk_basic_group_cfg extends jvs_clk_group_cfg; 4 | `uvm_object_utils(jvs_clk_basic_group_cfg) 5 | 6 | function new(string name = "jvs_clk_basic_group_cfg"); 7 | jvs_gen_clk_cfg clk2div_cfg, clk6div_cfg; 8 | super.new(name); 9 | root_clk = jvs_root_clk_cfg::type_id::create("root"); 10 | root_clk.randomize(); 11 | root_clk.period = 10; 12 | 13 | clk2div_cfg = jvs_gen_clk_cfg::type_id::create("clk2div"); 14 | clk2div_cfg.div_ratio = 2; 15 | clk2div_cfg.sync_rst = 1; 16 | this.add_gen_clk(clk2div_cfg); 17 | 18 | clk6div_cfg = jvs_gen_clk_cfg::type_id::create("clk6div"); 19 | clk6div_cfg.div_ratio = 6; 20 | this.add_gen_clk(clk6div_cfg); 21 | endfunction 22 | endclass 23 | 24 | class jvs_clk_basic_group1_cfg extends jvs_clk_group_cfg; 25 | `uvm_object_utils(jvs_clk_basic_group1_cfg) 26 | 27 | function new(string name = "jvs_clk_basic_group1_cfg"); 28 | jvs_gen_clk_cfg clk2div_cfg, clk3div_cfg; 29 | super.new(name); 30 | root_clk = jvs_root_clk_cfg::type_id::create("root"); 31 | root_clk.randomize(); 32 | root_clk.period = 2.5; 33 | 34 | clk2div_cfg = jvs_gen_clk_cfg::type_id::create("clk2div"); 35 | clk2div_cfg.div_ratio = 2; 36 | this.add_gen_clk(clk2div_cfg); 37 | 38 | clk3div_cfg = jvs_gen_clk_cfg::type_id::create("clk3div"); 39 | clk3div_cfg.div_ratio = 3; 40 | this.add_gen_clk(clk3div_cfg); 41 | endfunction 42 | endclass // jvs_clk_basic_group1_cfg 43 | 44 | class jvs_clk_basic_top_cfg extends jvs_clk_top_cfg; 45 | `uvm_object_utils(jvs_clk_basic_top_cfg) 46 | 47 | function new(string name = "jvs_clk_basic_top_cfg"); 48 | jvs_clk_basic_group_cfg group_cfg = jvs_clk_basic_group_cfg::type_id::create("group"); 49 | jvs_clk_basic_group1_cfg group1_cfg = jvs_clk_basic_group1_cfg::type_id::create("group1"); 50 | super.new(name); 51 | add_group(group_cfg); 52 | add_group(group1_cfg); 53 | endfunction 54 | endclass // jvs_clk_basic_top_cfg 55 | 56 | class jvs_clk_rst_group_basic_test extends uvm_test; 57 | jvs_clk_env env; 58 | jvs_clk_basic_top_cfg cfg; 59 | `uvm_component_utils(jvs_clk_rst_group_basic_test) 60 | 61 | function new(string name = "jvs_clk_rst_group_basic_test", uvm_component parent = null); 62 | super.new(name, parent); 63 | endfunction 64 | 65 | virtual function void build_phase(uvm_phase phase); 66 | super.build_phase(phase); 67 | env = jvs_clk_env::type_id::create("env", this); 68 | cfg = jvs_clk_basic_top_cfg::type_id::create("cfg"); 69 | cfg.print(); 70 | 71 | uvm_config_db#(jvs_clk_top_cfg)::set(this, "*", "cfg", cfg); 72 | endfunction // build_phase 73 | 74 | virtual task reset_phase(uvm_phase phase); 75 | phase.raise_objection(this); 76 | super.reset_phase(phase); 77 | env.hw_reset(); 78 | phase.drop_objection(this); 79 | endtask 80 | 81 | virtual task main_phase(uvm_phase phase); 82 | phase.raise_objection(this); 83 | #10000ns; 84 | env.hw_reset("group.*"); 85 | #10000ns; 86 | env.hw_reset("*.clk2div"); 87 | #10000ns; 88 | phase.drop_objection(this); 89 | endtask 90 | endclass 91 | `endif -------------------------------------------------------------------------------- /testcases/jvs_irq/jvs_soft_irq_test/jvs_soft_irq_test.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_SOFT_IRQ_TEST_SV__ 2 | `define __JVS_SOFT_IRQ_TEST_SV__ 3 | `include "jvs_irq_base_test.sv" 4 | class jvs_soft_irq_test extends jvs_irq_base_test; 5 | `uvm_component_utils(jvs_soft_irq_test) 6 | 7 | function new(string name = "jvs_soft_irq_test", uvm_component parent); 8 | super.new(name, parent); 9 | endfunction // new 10 | 11 | virtual task do_main_task(); 12 | int_test_redirect_int_handler int0_redirect_handler, int1_redirect_handler, int0_soft_redirect_handler; 13 | int_test_finish_int_handler int10_finish_handler; 14 | int_test_shared_int_handler int11_shared_handler; 15 | int repeat_times = $urandom_range(3,10); 16 | `uvm_info(this.get_name(), $psprintf("should trigger %0d ints each vector!", repeat_times), UVM_LOW); 17 | //int0: should be triggerd and redirect to soft irq 0 18 | int0_redirect_handler = int_test_redirect_int_handler::type_id::create("int0_redirect_handler"); 19 | int0_redirect_handler.action = jvs_irq_trans::THROUGH; 20 | int0_redirect_handler.env = env; 21 | int0_redirect_handler.redirect_vector = `JVS_SOFT_IRQ_V(0); 22 | env.register_irq(`JVS_INT_IRQ_V(0), int0_redirect_handler); 23 | 24 | //int1: should be triggerd and redirect to soft irq 1 25 | int1_redirect_handler = int_test_redirect_int_handler::type_id::create("int1_redirect_handler"); 26 | int1_redirect_handler.action = jvs_irq_trans::FINISH; 27 | int1_redirect_handler.env = env; 28 | int1_redirect_handler.redirect_vector = `JVS_SOFT_IRQ_V(1); 29 | env.register_irq(`JVS_INT_IRQ_V(1), int1_redirect_handler); 30 | 31 | //soft int0: should be triggerd and redirect to soft irq 1 32 | int0_soft_redirect_handler = int_test_redirect_int_handler::type_id::create("int0_soft_redirect_handler"); 33 | int0_soft_redirect_handler.action = jvs_irq_trans::THROUGH; 34 | int0_soft_redirect_handler.env = env; 35 | int0_soft_redirect_handler.redirect_vector = `JVS_SOFT_IRQ_V(1); 36 | env.register_irq(`JVS_SOFT_IRQ_V(0), int0_soft_redirect_handler); 37 | 38 | //soft int1: 10 should be trigger but 11 should be not 39 | int10_finish_handler = int_test_finish_int_handler::type_id::create("int10_finish_handler"); 40 | env.register_irq(`JVS_SOFT_IRQ_V(1), int10_finish_handler); 41 | int11_shared_handler = int_test_shared_int_handler::type_id::create("int11_shared_handler"); 42 | env.register_irq(`JVS_SOFT_IRQ_V(1), int11_shared_handler); 43 | 44 | fork 45 | begin 46 | repeat(repeat_times) begin 47 | `uvm_info(this.get_name(), "trigger int 0", UVM_LOW); 48 | irq_drv_seq::get_irq_drv_seq().trigger_int(0); 49 | #($urandom_range(1,100) * 1ns); 50 | `uvm_info(this.get_name(), "trigger int 1", UVM_LOW); 51 | irq_drv_seq::get_irq_drv_seq().trigger_int(1); 52 | #($urandom_range(1,100) * 1ns); 53 | end 54 | end 55 | join_none 56 | 57 | 58 | //1 int0 redirect: repeat_times = repeat_times 59 | //1 int1 redirect: repeat_times = repeat_times+repeat_times 60 | repeat(2*repeat_times) begin 61 | jvs_irq_result_trans tr; 62 | int10_finish_handler.get_irq_result(tr); 63 | tr.print(); 64 | end 65 | 66 | //should be timeout 67 | begin 68 | jvs_irq_result_trans tr; 69 | int10_finish_handler.get_irq_result(tr); 70 | if (tr != null) begin 71 | `uvm_error(this.get_name(), "get result more than expected!"); 72 | end 73 | end 74 | endtask 75 | endclass 76 | `endif -------------------------------------------------------------------------------- /src/register_region/jvs_reg_tree.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REG_TREE_SV__ 2 | `define __JVS_REG_TREE_SV__ 3 | virtual class jvs_reg_tree_node#(type NONLEAF_TYPE = jvs_reg_tree_node) extends uvm_object; 4 | typedef jvs_reg_tree_node#(NONLEAF_TYPE) THIS_TYPE; 5 | protected NONLEAF_TYPE parent; 6 | `uvm_field_utils_begin(jvs_reg_tree_node#(NONLEAF_TYPE)) 7 | `uvm_field_object(parent, UVM_ALL_ON) 8 | `uvm_field_utils_end 9 | 10 | function new(string name = "jvs_reg_tree_node"); 11 | super.new(name); 12 | endfunction // new 13 | 14 | function void set_parent(NONLEAF_TYPE parent); 15 | this.parent = parent; 16 | endfunction // set_parent 17 | 18 | function NONLEAF_TYPE get_parent(); 19 | return this.parent; 20 | endfunction // get_parent 21 | 22 | function bit[63:0] get_max(); 23 | return get_base()+get_size()-1; 24 | endfunction // get_max 25 | 26 | protected function bit in_region(THIS_TYPE node); 27 | return get_base() >= node.get_base() && get_max() <= node.get_max(); 28 | endfunction // in_region 29 | 30 | function bit is_overlapped(THIS_TYPE node); 31 | return get_base() >= node.get_base() && get_base() <= node.get_max() || get_max() >= node.get_base() && get_max() <= node.get_max(); 32 | endfunction // is_overlapped 33 | 34 | protected function bit check_in_region(THIS_TYPE node); 35 | if (!node.in_region(node.parent)) begin 36 | `uvm_info(this.get_name(), $psprintf("%0s is not in this region!", node.get_name()), UVM_LOW); 37 | return 0; 38 | end 39 | return 1; 40 | endfunction // check_in_region 41 | 42 | pure virtual function bit[63:0] get_base(); 43 | pure virtual function bit[63:0] get_size(); 44 | 45 | endclass // jvs_reg_tree_node 46 | 47 | class jvs_reg_tree_nodes#(type NODE_TYPE = jvs_reg_tree_node#(jvs_reg_tree_node)) extends uvm_object; 48 | protected NODE_TYPE node_table[string]; 49 | `uvm_object_param_utils_begin(jvs_reg_tree_nodes#(NODE_TYPE)) 50 | `uvm_field_aa_object_string(node_table,UVM_ALL_ON) 51 | `uvm_object_utils_end 52 | function new(string name = "jvs_reg_tree_nodes"); 53 | super.new(name); 54 | endfunction // new 55 | 56 | function bit check_exist_name(NODE_TYPE node); 57 | if (node_table.exists(node.get_name())) begin 58 | `uvm_info(this.get_name(), $psprintf("%0s is existed!", node.get_name()), UVM_LOW); 59 | return 0; 60 | end 61 | return 1; 62 | endfunction 63 | 64 | function bit check_overlap(NODE_TYPE node); 65 | foreach(node_table[i]) begin 66 | if (node.is_overlapped(node_table[i])) begin 67 | `uvm_info(this.get_name(), $psprintf("%0s is overlapped with %0s!", node.get_name(), node_table[i].get_name()), UVM_LOW); 68 | return 0; 69 | end 70 | end 71 | return 1; 72 | endfunction 73 | 74 | function bit remove_node(string key); 75 | if (!node_table.exists(key)) begin 76 | return 0; 77 | end 78 | node_table[key].set_parent(null); 79 | node_table.delete(key); 80 | return 1; 81 | endfunction 82 | 83 | function void add_node(NODE_TYPE node); 84 | node_table[node.get_name()] = node; 85 | endfunction // add_node 86 | 87 | function NODE_TYPE get_node(string key); 88 | if (!node_table.exists(key)) begin 89 | return null; 90 | end 91 | return node_table[key]; 92 | endfunction // get_node 93 | 94 | function void get_nodes(ref NODE_TYPE nodes[$]); 95 | foreach(node_table[i]) begin 96 | nodes.push_back(node_table[i]); 97 | end 98 | endfunction 99 | endclass 100 | `endif -------------------------------------------------------------------------------- /testcases/jvs_irq/jvs_int_simple_test/jvs_int_simple_test.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_INT_SIMPLE_TEST_SV__ 2 | `define __JVS_INT_SIMPLE_TEST_SV__ 3 | `include "jvs_irq_base_test.sv" 4 | class jvs_int_simple_test extends jvs_irq_base_test; 5 | `uvm_component_utils(jvs_int_simple_test) 6 | 7 | function new(string name = "jvs_int_simple_test", uvm_component parent); 8 | super.new(name, parent); 9 | endfunction // new 10 | 11 | virtual task do_main_task(); 12 | int_test_finish_int_handler int01_finish_handler, int10_finish_handler; 13 | int_test_shared_int_handler int00_shared_handler, int11_shared_handler; 14 | int repeat_times = $urandom_range(3,10); 15 | `uvm_info(this.get_name(), $psprintf("should trigger %0d ints each vector!", repeat_times), UVM_LOW); 16 | //int0: 00 and 01 should be triggerd 17 | int00_shared_handler = int_test_shared_int_handler::type_id::create("int00_shared_handler"); 18 | env.register_irq(`JVS_INT_IRQ_V(0), int00_shared_handler); 19 | int01_finish_handler = int_test_finish_int_handler::type_id::create("int01_finish_handler"); 20 | env.register_irq(`JVS_INT_IRQ_V(0), int01_finish_handler); 21 | 22 | //int1: 10 should be trigger but 11 should be not 23 | int10_finish_handler = int_test_finish_int_handler::type_id::create("int10_finish_handler"); 24 | env.register_irq(`JVS_INT_IRQ_V(1), int10_finish_handler); 25 | int11_shared_handler = int_test_shared_int_handler::type_id::create("int11_shared_handler"); 26 | env.register_irq(`JVS_INT_IRQ_V(1), int11_shared_handler); 27 | 28 | fork 29 | begin 30 | repeat(repeat_times) begin 31 | `uvm_info(this.get_name(), "trigger int 0", UVM_LOW); 32 | irq_drv_seq::get_irq_drv_seq().trigger_int(0); 33 | #($urandom_range(1,100) * 1ns); 34 | `uvm_info(this.get_name(), "trigger int 1", UVM_LOW); 35 | irq_drv_seq::get_irq_drv_seq().trigger_int(1); 36 | #($urandom_range(1,100) * 1ns); 37 | end 38 | end 39 | join_none 40 | 41 | 42 | 43 | 44 | fork 45 | begin 46 | repeat(repeat_times) begin 47 | jvs_irq_result_trans tr; 48 | int00_shared_handler.get_irq_result(tr); 49 | tr.print(); 50 | end 51 | end 52 | begin 53 | repeat(repeat_times) begin 54 | jvs_irq_result_trans tr; 55 | int01_finish_handler.get_irq_result(tr); 56 | tr.print(); 57 | end 58 | end 59 | begin 60 | repeat(repeat_times) begin 61 | jvs_irq_result_trans tr; 62 | int10_finish_handler.get_irq_result(tr); 63 | tr.print(); 64 | end 65 | end 66 | join 67 | 68 | fork 69 | begin 70 | jvs_irq_result_trans tr; 71 | int00_shared_handler.get_irq_result(tr); 72 | if (tr != null) begin 73 | `uvm_error(this.get_name(), "get result more than expected!"); 74 | end 75 | end 76 | begin 77 | jvs_irq_result_trans tr; 78 | int01_finish_handler.get_irq_result(tr); 79 | if (tr != null) begin 80 | `uvm_error(this.get_name(), "get result more than expected!"); 81 | end 82 | end 83 | begin 84 | jvs_irq_result_trans tr; 85 | int10_finish_handler.get_irq_result(tr); 86 | if (tr != null) begin 87 | `uvm_error(this.get_name(), "get result more than expected!"); 88 | end 89 | end 90 | begin 91 | jvs_irq_result_trans tr; 92 | int11_shared_handler.get_irq_result(tr); 93 | if (tr != null) begin 94 | `uvm_error(this.get_name(), "get result more than expected!"); 95 | end 96 | end 97 | join 98 | endtask 99 | endclass 100 | `endif -------------------------------------------------------------------------------- /src/irq/jvs_irq_trans.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_TRANS_SV__ 2 | `define __JVS_IRQ_TRANS_SV__ 3 | typedef jvs_common_attr jvs_irq_trans_attr; 4 | 5 | /* 6 | irq_vecotr[`JVS_MAX_IRQ_VECTOR_WIDTH-1:`JVS_MAX_IRQ_VECTOR_WIDTH-2] 7 | 00: int_irq 8 | 01: msi_irq 9 | 10: soft_irq/exception 10 | 11: unsupport type 11 | */ 12 | 13 | virtual class jvs_irq_trans_base extends uvm_sequence_item; 14 | typedef enum {INT_IRQ, 15 | MSI_IRQ, 16 | SOFT_IRQ} irq_type_e; 17 | rand bit [`JVS_MAX_IRQ_VECTOR_WIDTH-1:0] irq_vector; 18 | `uvm_field_utils_begin(jvs_irq_trans_base) 19 | `uvm_field_int(irq_vector, UVM_ALL_ON) 20 | `uvm_field_utils_end 21 | 22 | function new(string name = "jvs_irq_trans_base"); 23 | super.new(name); 24 | endfunction // new 25 | 26 | function irq_type_e get_irq_type(); 27 | case(irq_vector[`JVS_MAX_IRQ_VECTOR_WIDTH-1:`JVS_MAX_IRQ_VECTOR_WIDTH-2]) 28 | `JVS_INT_IRQ_FLAG: return INT_IRQ; 29 | `JVS_MSI_IRQ_FLAG: return MSI_IRQ; 30 | `JVS_SOFT_IRQ_FLAG: return SOFT_IRQ; 31 | endcase 32 | endfunction // get_irq_type 33 | 34 | endclass // jvs_irq_trans_base 35 | 36 | /* 37 | UNHANDLED: bypass this irq 38 | THROUGH: handled and pass to other handlers shared the same vector 39 | FINISH: handled as end point 40 | redirected: has benn redirected to other vecotr 41 | */ 42 | 43 | class jvs_irq_trans extends jvs_irq_trans_base; 44 | typedef enum {UNHANDLED, 45 | THROUGH, 46 | FINISH 47 | } irq_handle_state_e; 48 | irq_handle_state_e handle_state; 49 | protected jvs_irq_trans pre_irq_trans; 50 | protected jvs_irq_trans redirected_trans[$]; 51 | jvs_irq_trans_attr attr; 52 | 53 | `uvm_object_utils_begin(jvs_irq_trans); 54 | `uvm_field_object(attr, UVM_ALL_ON) 55 | `uvm_field_object(pre_irq_trans, UVM_ALL_ON| UVM_REFERENCE | UVM_NOCOPY) 56 | `uvm_field_enum(irq_handle_state_e, handle_state, UVM_ALL_ON | UVM_NOCOPY) 57 | `uvm_field_queue_object(redirected_trans, UVM_ALL_ON | UVM_NOCOPY) 58 | `uvm_object_utils_end 59 | 60 | function new(string name = "jvs_irq_trans"); 61 | super.new(name); 62 | handle_state = UNHANDLED; 63 | endfunction // new 64 | 65 | function jvs_irq_trans redirect([`JVS_MAX_IRQ_VECTOR_WIDTH - 1:0] irq_vector); 66 | jvs_irq_trans redirect_trans = jvs_irq_trans::type_id::create({"redirect_", this.get_name()}); 67 | redirect_trans.copy(this); 68 | redirect_trans.irq_vector = irq_vector; 69 | redirect_trans.pre_irq_trans = this; 70 | redirected_trans.push_back(redirect_trans); 71 | return redirect_trans; 72 | endfunction // redirect 73 | 74 | function bit is_redirected(); 75 | return redirected_trans.size() > 0; 76 | endfunction 77 | 78 | //only when all redirected_trans can_end_tr and self is in FINISH state 79 | function bit can_end_tr(); 80 | bit redirected_trans_all_done = 1; 81 | foreach(redirected_trans[i]) begin 82 | redirected_trans_all_done = redirected_trans_all_done & redirected_trans[i].can_end_tr(); 83 | end 84 | return redirected_trans_all_done && handle_state == FINISH; 85 | endfunction // can_end_tr 86 | 87 | //the last ended redirected_trans ends pre_irq_trans 88 | virtual function void do_end_tr(); 89 | if (pre_irq_trans != null && pre_irq_trans.is_redirected() && pre_irq_trans.can_end_tr()) begin 90 | pre_irq_trans.end_tr(); 91 | end 92 | endfunction // do_end_tr 93 | 94 | function jvs_irq_trans get_root_irq_source(); 95 | return pre_irq_trans == null ? this : pre_irq_trans.get_root_irq_source(); 96 | endfunction 97 | endclass // jvs_irq_trans 98 | 99 | class jvs_irq_result_trans extends jvs_irq_trans_base; 100 | jvs_irq_trans_attr attr; 101 | `uvm_object_utils_begin(jvs_irq_result_trans) 102 | `uvm_field_object(attr, UVM_ALL_ON) 103 | `uvm_object_utils_end 104 | 105 | function new(string name = "jvs_irq_result_trans"); 106 | super.new(name); 107 | endfunction 108 | endclass 109 | `endif -------------------------------------------------------------------------------- /src/clk_rst_group/jvs_clk_agent.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_AGENT_SV__ 2 | `define __JVS_CLK_AGENT_SV__ 3 | virtual class jvs_clk_agent_base#(type CFG_CLASS = jvs_clk_cfg_base) extends uvm_agent; 4 | jvs_clk_driver_base#(CFG_CLASS) driver; 5 | `uvm_field_utils_begin(jvs_clk_agent_base#(CFG_CLASS)) 6 | `uvm_field_utils_end 7 | 8 | function new(string name = "jvs_clk_agent_base", uvm_component parent); 9 | super.new(name, parent); 10 | endfunction 11 | endclass // jvs_clk_agent_base 12 | 13 | class jvs_root_clk_agent extends jvs_clk_agent_base#(jvs_root_clk_cfg); 14 | `uvm_component_utils_begin(jvs_root_clk_agent) 15 | `uvm_component_utils_end 16 | 17 | function new(string name = "jvs_root_clk_agent", uvm_component parent); 18 | super.new(name, parent); 19 | endfunction 20 | 21 | virtual function void build_phase(uvm_phase phase); 22 | super.build_phase(phase); 23 | driver = jvs_root_clk_driver::type_id::create("jvs_root_clk_driver", this); 24 | endfunction // build_phase 25 | endclass 26 | 27 | class jvs_gen_clk_agent extends jvs_clk_agent_base#(jvs_gen_clk_cfg); 28 | jvs_clk_vir_seqr seqr; 29 | `uvm_component_utils_begin(jvs_gen_clk_agent) 30 | `uvm_component_utils_end 31 | 32 | function new(string name = "jvs_gen_clk_agent", uvm_component parent); 33 | super.new(name, parent); 34 | endfunction 35 | 36 | virtual function void build_phase(uvm_phase phase); 37 | super.build_phase(phase); 38 | seqr = jvs_clk_vir_seqr::type_id::create("jvs_clk_vir_seqr", this); 39 | driver = jvs_gen_clk_driver::type_id::create("jvs_gen_clk_driver", this); 40 | endfunction // build_phase 41 | 42 | virtual function void connect_phase(uvm_phase phase); 43 | jvs_gen_clk_driver _driver; 44 | super.connect_phase(phase); 45 | $cast(_driver, driver); 46 | seqr.rst_ana_export.connect(_driver.rst_ana_imp); 47 | seqr.change_div_ana_export.connect(_driver.change_div_ana_imp); 48 | endfunction 49 | endclass // jvs_gen_clk_agent 50 | 51 | 52 | class jvs_clk_group_agent extends uvm_agent; 53 | jvs_root_clk_agent root_clk; 54 | jvs_clk_group_vir_seqr seqr; 55 | jvs_gen_clk_agent gen_clks[string]; 56 | jvs_clk_group_cfg cfg; 57 | `uvm_component_utils_begin(jvs_clk_group_agent) 58 | `uvm_component_utils_end 59 | 60 | function new(string name = "jvs_clk_group_agent", uvm_component parent); 61 | super.new(name, parent); 62 | endfunction 63 | 64 | virtual function void build_phase(uvm_phase phase); 65 | virtual jvs_root_clk_if root_vif; 66 | super.build_phase(phase); 67 | if(!uvm_config_db#(virtual jvs_root_clk_if)::get(this, "", "jvs_root_clk_if", root_vif)) begin 68 | `uvm_fatal(get_full_name(), "Can't get root clk rst interface!"); 69 | end 70 | uvm_config_db#(virtual jvs_root_clk_if)::set(this, "jvs_root_clk.*", "jvs_root_clk_if", root_vif); 71 | 72 | if(!uvm_config_db#(jvs_clk_group_cfg)::get(this, "", "cfg", cfg)) begin 73 | `uvm_fatal(get_full_name(), "Can't get cfg!"); 74 | end 75 | uvm_config_db#(jvs_root_clk_cfg)::set(this, "jvs_root_clk.*", "cfg", cfg.root_clk); 76 | root_clk = jvs_root_clk_agent::type_id::create("jvs_root_clk", this); 77 | 78 | seqr = jvs_clk_group_vir_seqr::type_id::create("jvs_clk_group_vir_seqr", this); 79 | 80 | foreach(cfg.gen_clks[i]) begin 81 | string key = cfg.gen_clks[i].get_name(); 82 | virtual jvs_gen_clk_if gen_vif; 83 | if(!uvm_config_db#(virtual jvs_gen_clk_if)::get(this, "", $sformatf("jvs_gen_clk_if[%0d]", i), gen_vif)) begin 84 | `uvm_fatal(get_full_name(), $sformatf("Can't get gen clk rst interface for %s!", key)); 85 | end 86 | uvm_config_db#(virtual jvs_gen_clk_if)::set(this, {key, ".*"}, "jvs_gen_clk_if",gen_vif); 87 | uvm_config_db#(jvs_gen_clk_cfg)::set(this, {key, ".*"}, "cfg", cfg.gen_clks[i]); 88 | gen_clks[key] = jvs_gen_clk_agent::type_id::create(key, this); 89 | end 90 | 91 | endfunction // build_phase 92 | 93 | virtual function void connect_phase(uvm_phase phase); 94 | super.connect_phase(phase); 95 | foreach(gen_clks[i]) begin 96 | seqr.clk_seqrs[i] = gen_clks[i].seqr; 97 | seqr.rst_ana_export.connect(gen_clks[i].seqr.rst_ana_export); 98 | seqr.change_div_ana_export.connect(gen_clks[i].seqr.change_div_ana_export); 99 | end 100 | endfunction 101 | 102 | endclass 103 | 104 | `endif -------------------------------------------------------------------------------- /testcases/jvs_irq/jvs_msi_irq_test/jvs_msi_irq_test.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MSI_IRQ_TEST_SV__ 2 | `define __JVS_MSI_IRQ_TEST_SV__ 3 | `include "jvs_irq_base_test.sv" 4 | class msi_irq_test_msi_monitor extends jvs_msi_monitor; 5 | semaphore sem_p, sem_c; 6 | local jvs_irq_trans tr_input; 7 | 8 | `uvm_component_utils(msi_irq_test_msi_monitor) 9 | 10 | function new(string name = "msi_irq_test_msi_monitor", uvm_component parent); 11 | super.new(name, parent); 12 | sem_p = new(0); 13 | sem_c = new(0); 14 | endfunction // new 15 | 16 | task trigger_msi(bit[`JVS_MAX_INT_PIN_NUM-1:0] vector); 17 | sem_p.get(1); 18 | tr_input = jvs_irq_trans::type_id::create("msi_irq"); 19 | tr_input.irq_vector = vector; 20 | sem_c.put(1); 21 | endtask 22 | 23 | protected virtual task monitor_msi(output jvs_irq_trans tr); 24 | sem_p.put(1); 25 | sem_c.get(1); 26 | tr = tr_input; 27 | endtask 28 | endclass 29 | 30 | class jvs_msi_irq_test extends jvs_irq_base_test; 31 | msi_irq_test_msi_monitor msi_monitor; 32 | 33 | `uvm_component_utils(jvs_msi_irq_test) 34 | 35 | function new(string name = "jvs_msi_irq_test", uvm_component parent); 36 | super.new(name, parent); 37 | msi_monitor = msi_irq_test_msi_monitor::type_id::create("msi_irq_test_msi_monitor", this); 38 | uvm_config_db#(jvs_msi_monitor)::set(this, "jvs_irq_env", "jvs_msi_monitor", msi_monitor); 39 | endfunction // new 40 | 41 | virtual task do_main_task(); 42 | int_test_redirect_int_handler int0_redirect_handler, int1_redirect_handler, int0_soft_redirect_handler; 43 | int_test_finish_int_handler int10_finish_handler; 44 | int_test_shared_int_handler int11_shared_handler; 45 | int repeat_times = $urandom_range(3,10); 46 | `uvm_info(this.get_name(), $psprintf("should trigger %0d ints each vector!", repeat_times), UVM_LOW); 47 | //int0: should be triggerd and redirect to soft irq 0 48 | int0_redirect_handler = int_test_redirect_int_handler::type_id::create("int0_redirect_handler"); 49 | int0_redirect_handler.action = jvs_irq_trans::THROUGH; 50 | int0_redirect_handler.env = env; 51 | int0_redirect_handler.redirect_vector = `JVS_SOFT_IRQ_V(0); 52 | env.register_irq(`JVS_MSI_IRQ_V(0), int0_redirect_handler); 53 | 54 | //int1: should be triggerd and redirect to soft irq 1 55 | int1_redirect_handler = int_test_redirect_int_handler::type_id::create("int1_redirect_handler"); 56 | int1_redirect_handler.action = jvs_irq_trans::FINISH; 57 | int1_redirect_handler.env = env; 58 | int1_redirect_handler.redirect_vector = `JVS_SOFT_IRQ_V(1); 59 | env.register_irq(`JVS_MSI_IRQ_V(1), int1_redirect_handler); 60 | 61 | //soft int0: should be triggerd and redirect to soft irq 1 62 | int0_soft_redirect_handler = int_test_redirect_int_handler::type_id::create("int0_soft_redirect_handler"); 63 | int0_soft_redirect_handler.action = jvs_irq_trans::THROUGH; 64 | int0_soft_redirect_handler.env = env; 65 | int0_soft_redirect_handler.redirect_vector = `JVS_SOFT_IRQ_V(1); 66 | env.register_irq(`JVS_SOFT_IRQ_V(0), int0_soft_redirect_handler); 67 | 68 | //soft int1: 10 should be trigger but 11 should be not 69 | int10_finish_handler = int_test_finish_int_handler::type_id::create("int10_finish_handler"); 70 | env.register_irq(`JVS_SOFT_IRQ_V(1), int10_finish_handler); 71 | int11_shared_handler = int_test_shared_int_handler::type_id::create("int11_shared_handler"); 72 | env.register_irq(`JVS_SOFT_IRQ_V(1), int11_shared_handler); 73 | 74 | fork 75 | begin 76 | repeat(repeat_times) begin 77 | `uvm_info(this.get_name(), "trigger int 0", UVM_LOW); 78 | msi_monitor.trigger_msi(0); 79 | #($urandom_range(1,100) * 1ns); 80 | `uvm_info(this.get_name(), "trigger int 1", UVM_LOW); 81 | msi_monitor.trigger_msi(1); 82 | #($urandom_range(1,100) * 1ns); 83 | end 84 | end 85 | join_none 86 | 87 | 88 | //1 int0 redirect: repeat_times = repeat_times 89 | //1 int1 redirect: repeat_times = repeat_times+repeat_times 90 | repeat(2*repeat_times) begin 91 | jvs_irq_result_trans tr; 92 | int10_finish_handler.get_irq_result(tr); 93 | tr.print(); 94 | end 95 | 96 | //should be timeout 97 | begin 98 | jvs_irq_result_trans tr; 99 | int10_finish_handler.get_irq_result(tr); 100 | if (tr != null) begin 101 | `uvm_error(this.get_name(), "get result more than expected!"); 102 | end 103 | end 104 | endtask 105 | endclass 106 | `endif -------------------------------------------------------------------------------- /testcases/jvs_memory/jvs_memory_showcase/jvs_memory_showcase.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MEMORY_SHOWCASE_SV__ 2 | `define __JVS_MEMORY_SHOWCASE_SV__ 3 | class jvs_memory_showcase_component extends uvm_component; 4 | jvs_memory_allocator allocator; 5 | jvs_memory_acc_block share_acc_block; 6 | 7 | `uvm_component_utils_begin(jvs_memory_showcase_component) 8 | `uvm_component_utils_end 9 | 10 | function new(string name="jvs_memory_showcase_component", uvm_component parent = null); 11 | super.new(name, parent); 12 | endfunction // new 13 | 14 | task write_case1(); 15 | jvs_memory_acc_block acc_block; 16 | allocator.malloc(acc_block, 1, ALIGN_BYTE, 65'b1); 17 | acc_block.write_byte(64'b0, 8'h5a); 18 | endtask // write_case1 19 | 20 | task read_case1(); 21 | jvs_memory_acc_block acc_block; 22 | MEM_BYTE data; 23 | allocator.malloc(acc_block, 1, ALIGN_BYTE, 65'b1); 24 | data = acc_block.read_byte(64'b0); 25 | if (data != 8'h5a) begin 26 | `uvm_error(this.get_name(), $psprintf("read_case1: data expect 0x5a data is 0x%0x", data)); 27 | return; 28 | end 29 | `uvm_info(this.get_name(), $psprintf("read_case1: data expect 0x5a data is 0x%0x", data), UVM_LOW); 30 | endtask 31 | 32 | task write_case2(); 33 | jvs_memory_model model = allocator.model; 34 | model.write_byte(64'h10, 8'ha5); 35 | endtask 36 | 37 | 38 | task read_case2(); 39 | jvs_memory_acc_block acc_block; 40 | MEM_BYTE data; 41 | allocator.malloc(acc_block, 10, ALIGN_BYTE, 65'h10); 42 | acc_block.print(); 43 | data = acc_block.read_byte(64'h0); 44 | if (data != 8'ha5) begin 45 | `uvm_error(this.get_name(), $psprintf("read_case2: data expect 0xa5 data is 0x%0x", data)); 46 | return; 47 | end 48 | `uvm_info(this.get_name(), $psprintf("read_case2: data expect 0xa5 data is 0x%0x", data), UVM_LOW); 49 | endtask 50 | 51 | 52 | task write_case3(); 53 | MEM_BARRAY array; 54 | array = new[share_acc_block.get_size()]; 55 | foreach(array[i]) begin 56 | array[i] = i; 57 | end 58 | share_acc_block.data2mem(array); 59 | endtask // write_case1 60 | 61 | task read_case3(); 62 | MEM_BARRAY array; 63 | share_acc_block.mem2data(array); 64 | `uvm_info(this.get_name(), $psprintf("read_case3: array size is %0d", array.size()), UVM_LOW); 65 | foreach(array[i]) begin 66 | if (array[i] != i) begin 67 | `uvm_error(this.get_name(), $psprintf("read_case3: array[%0d] expect %0d data is %0d", i, i, array[i])); 68 | return; 69 | end 70 | `uvm_info(this.get_name(), $psprintf("read_case3: array[%0d] expect %0d data is %0d", i, i, array[i]), UVM_LOW); 71 | end 72 | endtask 73 | 74 | endclass 75 | 76 | 77 | class jvs_memory_showcase_cfg extends jvs_memory_cfg; 78 | `uvm_object_utils_begin(jvs_memory_showcase_cfg) 79 | `uvm_object_utils_end 80 | function new(string name="jvs_memory_showcase_cfg"); 81 | super.new(name); 82 | this.range = jvs_memory_range::type_id::create(); 83 | this.model = jvs_memory_aa_model::type_id::create("model"); 84 | endfunction // new 85 | 86 | endclass 87 | 88 | class jvs_memory_showcase extends uvm_test; 89 | jvs_memory_showcase_cfg cfg; 90 | jvs_memory_allocator allocator1; 91 | jvs_memory_allocator allocator2; 92 | jvs_memory_allocator allocator3; 93 | 94 | jvs_memory_showcase_component producer; 95 | jvs_memory_showcase_component consumer; 96 | 97 | 98 | `uvm_component_utils_begin(jvs_memory_showcase) 99 | `uvm_component_utils_end 100 | 101 | function new(string name="jvs_memory_showcase", uvm_component parent = null); 102 | super.new(name, parent); 103 | endfunction // new 104 | 105 | virtual function void build_phase(uvm_phase phase); 106 | super.build_phase(phase); 107 | cfg = jvs_memory_showcase_cfg::type_id::create("cfg"); 108 | 109 | //individual allocator, for case1&case2 110 | allocator1 = jvs_memory_allocator::type_id::create("allocator1"); 111 | allocator1.configurate(cfg); 112 | allocator2 = jvs_memory_allocator::type_id::create("allocator2"); 113 | allocator2.configurate(cfg); 114 | //share allocator, for case3 115 | allocator3 = jvs_memory_allocator::type_id::create("allocator3"); 116 | allocator3.configurate(cfg); 117 | 118 | producer = jvs_memory_showcase_component::type_id::create("producer", this); 119 | consumer = jvs_memory_showcase_component::type_id::create("consumer", this); 120 | producer.allocator = allocator1; 121 | consumer.allocator = allocator3; 122 | 123 | endfunction // build_phase 124 | 125 | task run_phase(uvm_phase phase); 126 | phase.raise_objection(this); 127 | super.run_phase(phase); 128 | //case1 129 | producer.write_case1(); 130 | consumer.read_case1(); 131 | //case2 132 | producer.write_case2(); 133 | consumer.read_case2(); 134 | //case3 135 | allocator3.malloc(producer.share_acc_block, 9, ALIGN_BYTE); 136 | consumer.share_acc_block = producer.share_acc_block; 137 | producer.write_case3(); 138 | consumer.read_case3(); 139 | phase.drop_objection(this); 140 | endtask 141 | endclass 142 | 143 | `endif -------------------------------------------------------------------------------- /testcases/jvs_irq/jvs_irq_base_test.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_IRQ_BASE_TEST_SV__ 2 | `define __JVS_IRQ_BASE_TEST_SV__ 3 | class irq_drv_seq extends uvm_sequence_base; 4 | local static irq_drv_seq inst; 5 | jvs_int_sequencer int_seqr; 6 | `uvm_object_utils_begin(irq_drv_seq) 7 | `uvm_object_utils_end 8 | 9 | function new(string name = "irq_drv_seq"); 10 | super.new(name); 11 | endfunction // new 12 | 13 | static function irq_drv_seq get_irq_drv_seq(); 14 | if (inst == null) begin 15 | inst = irq_drv_seq::type_id::create("irq_drv_seq"); 16 | end 17 | return inst; 18 | endfunction // get_irq_drv_seq 19 | 20 | task trigger_int(bit[`JVS_MAX_INT_PIN_NUM-1:0] vector); 21 | jvs_int_drv_trans trans; 22 | `uvm_create_on(trans, int_seqr) 23 | trans.irq_vector = vector; 24 | trans.set = 1; 25 | `uvm_send(trans); 26 | endtask // trigger_int 27 | 28 | task clear_int(bit[`JVS_MAX_INT_PIN_NUM-1:0] vector); 29 | jvs_int_drv_trans trans; 30 | `uvm_create_on(trans, int_seqr) 31 | trans.irq_vector = vector; 32 | trans.set = 0; 33 | `uvm_send(trans); 34 | endtask 35 | endclass // irq_drv_seq 36 | 37 | class int_test_finish_int_handler extends jvs_irq_handler; 38 | int irq_cnt; 39 | `uvm_object_utils_begin(int_test_finish_int_handler) 40 | `uvm_object_utils_end 41 | function new(string name = "int_test_finish_int_handler"); 42 | super.new(name); 43 | endfunction // new 44 | 45 | virtual task do_handle(jvs_irq_trans irq_tr); 46 | `uvm_info(this.get_name(), $psprintf("get %0d irq!", irq_cnt), UVM_LOW); 47 | irq_tr.print(); 48 | if (irq_tr.get_root_irq_source().get_irq_type() == jvs_irq_trans::INT_IRQ) begin 49 | `uvm_info(this.get_name(), $psprintf("clear %0d irq!", irq_cnt), UVM_LOW); 50 | irq_drv_seq::get_irq_drv_seq().clear_int(irq_tr.get_root_irq_source().irq_vector); 51 | end 52 | irq_cnt++; 53 | irq_tr.handle_state = jvs_irq_trans::FINISH; 54 | `uvm_info(this.get_name(), "finish irq_trans", UVM_LOW); 55 | endtask // do_handle 56 | 57 | virtual function jvs_irq_result_trans gen_result(jvs_irq_trans irq_tr); 58 | jvs_irq_result_trans result = jvs_irq_result_trans::type_id::create($psprintf("%0s_result_%0d", this.get_name(), irq_cnt)); 59 | result.irq_vector = irq_tr.irq_vector; 60 | return result; 61 | endfunction 62 | endclass 63 | 64 | class int_test_shared_int_handler extends jvs_irq_handler; 65 | int irq_cnt; 66 | `uvm_object_utils_begin(int_test_shared_int_handler) 67 | `uvm_object_utils_end 68 | function new(string name = "int_test_shared_int_handler"); 69 | super.new(name); 70 | endfunction // new 71 | 72 | virtual task do_handle(jvs_irq_trans irq_tr); 73 | `uvm_info(this.get_name(), $psprintf("get %0d irq!", irq_cnt), UVM_LOW); 74 | irq_tr.print(); 75 | irq_cnt++; 76 | irq_tr.handle_state = jvs_irq_trans::THROUGH; 77 | `uvm_info(this.get_name(), "through irq_trans", UVM_LOW); 78 | endtask // do_handle 79 | 80 | virtual function jvs_irq_result_trans gen_result(jvs_irq_trans irq_tr); 81 | jvs_irq_result_trans result = jvs_irq_result_trans::type_id::create($psprintf("%0s_result_%0d", this.get_name(), irq_cnt)); 82 | result.irq_vector = irq_tr.irq_vector; 83 | return result; 84 | endfunction 85 | endclass // int_test_shared_int_handler 86 | 87 | class int_test_redirect_int_handler extends jvs_irq_handler; 88 | int irq_cnt; 89 | jvs_irq_env env; 90 | bit [`JVS_MAX_IRQ_VECTOR_WIDTH-1:0] redirect_vector; 91 | jvs_irq_trans::irq_handle_state_e action; 92 | 93 | `uvm_object_utils_begin(int_test_redirect_int_handler) 94 | `uvm_object_utils_end 95 | function new(string name = "int_test_redirect_int_handler"); 96 | super.new(name); 97 | endfunction // new 98 | 99 | virtual task do_handle(jvs_irq_trans irq_tr); 100 | `uvm_info(this.get_name(), $psprintf("get %0d irq!", irq_cnt), UVM_LOW); 101 | irq_tr.print(); 102 | irq_cnt++; 103 | irq_tr.handle_state = action; 104 | env.trigger_soft_irq(irq_tr.redirect(redirect_vector)); 105 | `uvm_info(this.get_name(), "redirect irq_trans", UVM_LOW); 106 | endtask // do_handle 107 | 108 | virtual function jvs_irq_result_trans gen_result(jvs_irq_trans irq_tr); 109 | return null; 110 | endfunction 111 | endclass 112 | 113 | virtual class jvs_irq_base_test extends uvm_test; 114 | jvs_irq_env env; 115 | `uvm_field_utils_begin(jvs_irq_base_test) 116 | `uvm_field_utils_end 117 | 118 | function new(string name = "jvs_irq_base_test", uvm_component parent); 119 | super.new(name, parent); 120 | endfunction // new 121 | 122 | virtual function void build_phase(uvm_phase phase); 123 | super.build_phase(phase); 124 | uvm_config_db#(int)::set(this, "*.jvs_int_agent", "is_active", UVM_ACTIVE); 125 | env= jvs_irq_env::type_id::create("jvs_irq_env", this); 126 | endfunction // build_phase 127 | 128 | virtual function void connect_phase(uvm_phase phase); 129 | super.connect_phase(phase); 130 | irq_drv_seq::get_irq_drv_seq().int_seqr = env.jvs_int_ag.int_seqr; 131 | endfunction // connect_phase 132 | 133 | virtual task main_phase(uvm_phase phase); 134 | phase.raise_objection(phase); 135 | super.main_phase(phase); 136 | do_main_task(); 137 | phase.drop_objection(phase); 138 | endtask // main_phase 139 | 140 | pure virtual task do_main_task(); 141 | 142 | endclass 143 | `endif -------------------------------------------------------------------------------- /testcases/jvs_register_region/jvs_register_region_test/jvs_register_region_test.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REGISTER_REGION_TEST_SV__ 2 | `define __JVS_REGISTER_REGION_TEST_SV__ 3 | `include "jvs_reg_base_test.sv" 4 | `include "jvs_test_reg_model.sv" 5 | class jvs_test_region_builder extends jvs_reg_region_builder; 6 | jvs_reg_test_sequencer sub_block_sequencer, top_block_sequencer; 7 | jvs_reg_test_adapter sub_block_adapter, top_block_adapter; 8 | 9 | `uvm_object_utils(jvs_test_region_builder) 10 | 11 | function new(string name = "jvs_test_region_builder"); 12 | super.new(name); 13 | endfunction // new 14 | 15 | function jvs_reg_region build_region(); 16 | jvs_reg_region root_region = create_region("top_region", 0, (1 << 27) - 1); 17 | create_region("top_block", 0, (3 << 24) - 1, root_region, .seqr(top_block_sequencer), .adapter(top_block_adapter)); 18 | create_region("sub_block", 3 << 24, (4 << 24) - 1, root_region, .seqr(sub_block_sequencer), .adapter(sub_block_adapter)); 19 | return root_region; 20 | endfunction 21 | endclass // jvs_test_region_builder 22 | 23 | class jvs_register_region_test extends jvs_reg_base_test; 24 | jvs_reg_test_driver top_reg_driver, sub_block_driver, top_block_driver; 25 | jvs_reg_test_sequencer top_reg_sequencer, sub_block_sequencer, top_block_sequencer; 26 | jvs_reg_test_adapter top_reg_adapter, sub_block_adapter, top_block_adapter; 27 | jvs_reg_region root_region; 28 | `uvm_component_utils(jvs_register_region_test) 29 | 30 | function new(string name = "jvs_register_region_test", uvm_component parent); 31 | super.new(name, parent); 32 | endfunction // new 33 | 34 | virtual function void build_phase(uvm_phase phase); 35 | jvs_test_region_builder region_builder; 36 | jvs_test_top_block root_block; 37 | 38 | super.build_phase(phase); 39 | top_reg_driver = jvs_reg_test_driver::type_id::create("top_reg_driver", this); 40 | sub_block_driver = jvs_reg_test_driver::type_id::create("sub_block_driver", this); 41 | top_block_driver = jvs_reg_test_driver::type_id::create("top_block_driver", this); 42 | 43 | top_reg_sequencer = jvs_reg_test_sequencer::type_id::create("top_reg_sequencer", this); 44 | sub_block_sequencer = jvs_reg_test_sequencer::type_id::create("sub_block_sequencer", this); 45 | top_block_sequencer = jvs_reg_test_sequencer::type_id::create("top_block_sequencer", this); 46 | 47 | top_reg_adapter = jvs_reg_test_adapter::type_id::create("top_reg_adapter", this); 48 | sub_block_adapter = jvs_reg_test_adapter::type_id::create("sub_block_adapter", this); 49 | top_block_adapter = jvs_reg_test_adapter::type_id::create("top_block_adapter", this); 50 | 51 | `uvm_info(this.get_name(), "build and map ...", UVM_LOW); 52 | region_builder = jvs_test_region_builder::type_id::create("region_builder"); 53 | //could config sequencer and adapter when create region 54 | region_builder.sub_block_sequencer = sub_block_sequencer; 55 | region_builder.top_block_sequencer = top_block_sequencer; 56 | region_builder.sub_block_adapter = sub_block_adapter; 57 | region_builder.top_block_adapter = top_block_adapter; 58 | root_region = region_builder.build_region(); 59 | root_block = jvs_test_top_block::type_id::create("jvs_test_top_block"); 60 | root_block.build(); 61 | root_block.lock_model(); 62 | region_mapper.map(root_block, root_region); 63 | root_region.print(); 64 | 65 | `uvm_info(this.get_name(), "unmap ...", UVM_LOW); 66 | region_mapper.unmap(root_block, root_region); 67 | root_region.print(); 68 | 69 | `uvm_info(this.get_name(), "remap ...", UVM_LOW); 70 | region_mapper.map(root_block, root_region); 71 | root_region.print(); 72 | 73 | `uvm_info(this.get_name(), "unmap partial 1...", UVM_LOW); 74 | region_mapper.unmap(root_block.get_block_by_name("block[1]"), root_region.get_sub_region("top_block")); 75 | root_region.print(); 76 | 77 | `uvm_info(this.get_name(), "unmap partial 2...", UVM_LOW); 78 | region_mapper.unmap(root_block.get_block_by_name("sub_top_block"), root_region); 79 | root_region.print(); 80 | 81 | `uvm_info(this.get_name(), "remap ...", UVM_LOW); 82 | region_mapper.map(root_block.get_block_by_name("sub_top_block"), root_region); 83 | region_mapper.map(root_block.get_block_by_name("block[1]"), root_region.get_sub_region("top_block")); 84 | root_region.print(); 85 | 86 | //could config sequencer and adapter outside builder 87 | root_region.config_seqr_adapter(jvs_reg_seqr_adapter_pair_factory::get_seqr_adapter_pair(top_reg_sequencer, top_reg_adapter)); 88 | 89 | endfunction 90 | 91 | virtual function void connect_phase(uvm_phase phase); 92 | super.connect_phase(phase); 93 | top_reg_driver.seq_item_port.connect(top_reg_sequencer.seq_item_export); 94 | sub_block_driver.seq_item_port.connect(sub_block_sequencer.seq_item_export); 95 | top_block_driver.seq_item_port.connect(top_block_sequencer.seq_item_export); 96 | endfunction // connect_phase 97 | 98 | virtual task run_phase(uvm_phase phase); 99 | phase.raise_objection(this); 100 | super.run_phase(phase); 101 | fork 102 | access_reg("top_region", "top_reg", 32'h5a); 103 | access_reg("sub_block", "test_reg", 32'ha5); 104 | access_reg("top_block", "test_reg", 32'h5500); 105 | join 106 | phase.drop_objection(this); 107 | endtask 108 | 109 | 110 | task access_reg(string region, string reg_name, bit[31:0] data); 111 | uvm_status_e status; 112 | bit [31:0] _data = data; 113 | 114 | repeat($urandom_range(1, 3)) begin 115 | bit[31:0] rdata; 116 | `uvm_info(this.get_name(), $psprintf("write @ %0s in region %0s", reg_name, region), UVM_LOW); 117 | root_region.get_region(region).write_fd(reg_name, _data, status); 118 | `uvm_info(this.get_name(), $psprintf("write complete @ %0s in region %0s", reg_name, region), UVM_LOW); 119 | `uvm_info(this.get_name(), $psprintf("read @ %0s in region %0s", reg_name, region), UVM_LOW); 120 | root_region.get_region(region).read_fd(reg_name, rdata, status); 121 | `uvm_info(this.get_name(), $psprintf("read complete @ %0s in region %0s", reg_name, region), UVM_LOW); 122 | if (rdata != _data) begin 123 | `uvm_error(this.get_name(), $psprintf("access error @ %0s in region %0s, expect data = 0x%0x, but get 0x%0x!", reg_name, region, _data, rdata)); 124 | end 125 | _data = ~_data; 126 | end 127 | endtask 128 | endclass 129 | `endif -------------------------------------------------------------------------------- /src/register_region/jvs_reg_resource_manager.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REG_RESOURCE_MANAGER_SV__ 2 | `define __JVS_REG_RESOURCE_MANAGER_SV__ 3 | class jvs_reg_seqr_adapter_pair extends uvm_object; 4 | uvm_reg_adapter adapter; 5 | uvm_sequencer_base sequencer; 6 | `uvm_object_utils_begin(jvs_reg_seqr_adapter_pair) 7 | `uvm_field_object(adapter, UVM_ALL_ON | UVM_REFERENCE) 8 | `uvm_field_object(sequencer, UVM_ALL_ON | UVM_REFERENCE) 9 | `uvm_object_utils_end 10 | 11 | function new(string name = "jvs_reg_seqr_adapter_pair"); 12 | super.new(name); 13 | endfunction // new 14 | 15 | function bit check(); 16 | return sequencer != null && adapter != null; 17 | endfunction 18 | endclass // jvs_reg_seqr_adapter_pair 19 | 20 | //all pairs must created by factory, to garentee (root_map, ref of sequencer) 1 on 1 map 21 | class jvs_reg_seqr_adapter_pair_factory; 22 | local static jvs_reg_seqr_adapter_pair pairs[$]; 23 | 24 | static function jvs_reg_seqr_adapter_pair get_seqr_adapter_pair(uvm_sequencer_base sequencer, uvm_reg_adapter adapter); 25 | jvs_reg_seqr_adapter_pair pairs_found[$]; 26 | jvs_reg_seqr_adapter_pair pair; 27 | //check null 28 | if (adapter == null || sequencer == null) begin 29 | return null; 30 | end 31 | //check exist 32 | pairs_found = pairs.find_first with (item.adapter == adapter && item.sequencer == sequencer); 33 | if (pairs_found.size() == 1) begin 34 | return pairs_found.pop_front(); 35 | end 36 | //add new ref 37 | pair = jvs_reg_seqr_adapter_pair::type_id::create({sequencer.get_name(), "___", adapter.get_name()}); 38 | pair.sequencer = sequencer; 39 | pair.adapter = adapter; 40 | pairs.push_front(pair); 41 | return pair; 42 | endfunction 43 | endclass // jvs_reg_seqr_adapter_pair_factory 44 | 45 | class jvs_reg_resource_manager extends uvm_object; 46 | local static jvs_reg_resource_manager inst; 47 | local semaphore lock; 48 | local jvs_common_condition cond; 49 | //one hot and atomic 50 | local jvs_reg_seqr_adapter_pair map_table[uvm_reg_map]; 51 | local int seqr_adapter_ref[jvs_reg_seqr_adapter_pair]; 52 | local int root_map_ref[uvm_reg_map]; 53 | `uvm_object_utils_begin(jvs_reg_resource_manager) 54 | `uvm_object_utils_end 55 | 56 | function new(string name = "jvs_reg_resource_manager"); 57 | super.new(name); 58 | endfunction // new 59 | 60 | static function jvs_reg_resource_manager get_manager(); 61 | if(jvs_reg_resource_manager::inst == null) begin 62 | jvs_reg_resource_manager::inst = jvs_reg_resource_manager::type_id::create("jvs_reg_resource_manager"); 63 | jvs_reg_resource_manager::inst.lock = new(1); 64 | jvs_reg_resource_manager::inst.cond = new(jvs_reg_resource_manager::inst.lock); 65 | end 66 | return jvs_reg_resource_manager::inst; 67 | endfunction // get_manager 68 | 69 | local function bit change_pair(jvs_reg_seqr_adapter_pair seqr_adapter, uvm_reg_map root_map); 70 | if (root_map == null) begin 71 | `uvm_info(this.get_name(), "root_map is null!", UVM_LOW); 72 | return 0; 73 | end 74 | if (root_map.get_root_map() != root_map) begin 75 | `uvm_info(this.get_name(), "root_map is not root!", UVM_LOW); 76 | return 0; 77 | end 78 | if (!seqr_adapter.check()) begin 79 | `uvm_info(this.get_name(), "seqr_adapter is illegal!", UVM_LOW); 80 | return 0; 81 | end 82 | if (map_table[root_map] != seqr_adapter) begin 83 | root_map.set_sequencer(seqr_adapter.sequencer, seqr_adapter.adapter); 84 | map_table[root_map] = seqr_adapter; 85 | end 86 | seqr_adapter_ref[seqr_adapter]++; 87 | root_map_ref[root_map]++; 88 | return 1; 89 | endfunction // change_pair 90 | 91 | task request_reg_map(jvs_reg_seqr_adapter_pair seqr_adapter, uvm_reg_map root_map); 92 | lock.get(1); 93 | //already in use 94 | `uvm_info(this.get_name(), $psprintf("request seq_adapter %0s and root_map %0s", seqr_adapter.get_name(), root_map.get_name()), UVM_HIGH); 95 | if (map_table[root_map] == seqr_adapter) begin 96 | seqr_adapter_ref[seqr_adapter] ++; 97 | root_map_ref[root_map] ++; 98 | `uvm_info(this.get_name(), $psprintf("seq_adapter %0s and root_map %0s in use!, seqr_adapter ref %0d, root_map ref %0d", seqr_adapter.get_name(), root_map.get_name(), seqr_adapter_ref[seqr_adapter], root_map_ref[root_map]), UVM_HIGH); 99 | lock.put(1); 100 | return; 101 | end 102 | `uvm_info(this.get_name(), $psprintf("seq_adapter %0s and root_map %0s not in use, waiting!, seqr_adapter ref %0d, root_map ref %0d", seqr_adapter.get_name(), root_map.get_name(), seqr_adapter_ref[seqr_adapter], root_map_ref[root_map]), UVM_HIGH); 103 | while((root_map_ref[root_map] != 0 || seqr_adapter_ref[seqr_adapter] != 0) && map_table[root_map] != seqr_adapter) begin 104 | `uvm_info(this.get_name(), $psprintf("cur process seq_adapter %0s and root_map %0s go to sleep!", seqr_adapter.get_name(), root_map.get_name()), UVM_HIGH); 105 | cond.sleep(); 106 | end 107 | `uvm_info(this.get_name(), $psprintf("cur process seq_adapter %0s and root_map %0s waked up!", seqr_adapter.get_name(), root_map.get_name()), UVM_HIGH); 108 | if (!change_pair(seqr_adapter, root_map)) begin 109 | `uvm_fatal(this.get_name(), $psprintf("change seqr_adapter pair %0s fail!", seqr_adapter.get_name())); 110 | end 111 | lock.put(1); 112 | endtask 113 | 114 | task release_reg_map(jvs_reg_seqr_adapter_pair seqr_adapter, uvm_reg_map root_map); 115 | lock.get(1); 116 | if (!map_table.exists(root_map) || map_table[root_map] != seqr_adapter) begin 117 | `uvm_fatal(this.get_name(), $psprintf("seqr_adapter pair %0s try to release root_map %0s, but it's not owner of root_map!", seqr_adapter.get_name(), root_map.get_name())); 118 | lock.put(1); 119 | return; 120 | end 121 | if (seqr_adapter_ref[seqr_adapter] < 1 || root_map_ref[root_map] < 1) begin 122 | `uvm_fatal(this.get_name(), $psprintf("seqr_adapter pair %0s or root_map %0s no ref, they are %0d, %0d !", seqr_adapter.get_name(), root_map.get_name(), seqr_adapter_ref[seqr_adapter], root_map_ref[root_map])); 123 | lock.put(1); 124 | return; 125 | end 126 | seqr_adapter_ref[seqr_adapter]--; 127 | root_map_ref[root_map]--; 128 | `uvm_info(this.get_name(), $psprintf("release seq_adapter %0s and root_map %0s!, seqr_adapter ref %0d, root_map ref %0d", seqr_adapter.get_name(), root_map.get_name(), seqr_adapter_ref[seqr_adapter], root_map_ref[root_map]), UVM_HIGH); 129 | if (seqr_adapter_ref[seqr_adapter] == 0 || root_map_ref[root_map] == 0) begin 130 | `uvm_info(this.get_name(), $psprintf("seq_adapter %0s and root_map %0s wake up all process!", seqr_adapter.get_name(), root_map.get_name()), UVM_HIGH); 131 | cond.wake_all(); 132 | end 133 | lock.put(1); 134 | endtask 135 | 136 | endclass // jvs_reg_resource_manager 137 | 138 | 139 | `endif -------------------------------------------------------------------------------- /src/clk_rst_group/jvs_clk_driver.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_DRIVER_SV__ 2 | `define __JVS_CLK_DRIVER_SV__ 3 | virtual class jvs_clk_driver_base#(type CFG_CLASS= jvs_clk_cfg_base) extends uvm_driver#(jvs_clk_trans_base#(CFG_CLASS)); 4 | CFG_CLASS cfg; 5 | `uvm_field_utils_begin(jvs_clk_driver_base#(CFG_CLASS)) 6 | `uvm_field_object(cfg,UVM_ALL_ON) 7 | `uvm_field_utils_end 8 | 9 | function new(string name = "jvs_clk_driver_base", uvm_component parent); 10 | super.new(name, parent); 11 | endfunction // new 12 | 13 | virtual function void build_phase(uvm_phase phase); 14 | super.build_phase(phase); 15 | if(!uvm_config_db#(CFG_CLASS)::get(this, "", "cfg", cfg)) begin 16 | `uvm_fatal(get_full_name(), "Can't get cfg!"); 17 | end 18 | endfunction 19 | endclass // jvs_clk_driver_base 20 | 21 | class jvs_root_clk_driver extends jvs_clk_driver_base#(jvs_root_clk_cfg); 22 | jvs_root_clk_trans trans; 23 | virtual jvs_root_clk_if vif; 24 | `uvm_component_utils_begin(jvs_root_clk_driver) 25 | `uvm_field_object(trans, UVM_ALL_ON) 26 | `uvm_component_utils_end 27 | 28 | function new(string name = "jvs_root_clk_driver", uvm_component parent); 29 | super.new(name, parent); 30 | endfunction // new 31 | 32 | virtual function void build_phase(uvm_phase phase); 33 | super.build_phase(phase); 34 | if(!uvm_config_db#(virtual jvs_root_clk_if)::get(this, "", "jvs_root_clk_if", vif)) begin 35 | `uvm_fatal(get_full_name(), "Can't get root clk interface!"); 36 | end 37 | trans = jvs_root_clk_trans::type_id::create("jvs_root_clk"); 38 | trans.cfg = cfg; 39 | endfunction // build_phase 40 | 41 | virtual task run_phase(uvm_phase phase); 42 | realtime delay; 43 | bit [7:0] last_jitter = 0; 44 | bit last_jitter_flag = 0; 45 | 46 | super.run_phase(phase); 47 | vif.clock = 0; 48 | delay = cfg.get_init_delay(); 49 | #(delay); 50 | forever begin 51 | realtime half_period; 52 | vif.clock = ~vif.clock; 53 | trans.randomize(); 54 | trans.compensate(~last_jitter_flag, last_jitter); 55 | half_period = trans.get_half_period(); 56 | last_jitter = trans.jitter; 57 | last_jitter_flag = trans.jitter_flag; 58 | #(half_period); 59 | end 60 | endtask 61 | endclass // jvs_root_clk_driver 62 | 63 | `uvm_analysis_imp_decl(_clk_rst_driver) 64 | `uvm_analysis_imp_decl(_clk_change_div_driver) 65 | 66 | class jvs_gen_clk_driver extends jvs_clk_driver_base#(jvs_gen_clk_cfg); 67 | uvm_analysis_imp_clk_rst_driver#(jvs_clk_rst_trans, jvs_gen_clk_driver) rst_ana_imp; 68 | uvm_analysis_imp_clk_change_div_driver#(jvs_clk_change_div, jvs_gen_clk_driver) change_div_ana_imp; 69 | uvm_tlm_fifo#(jvs_clk_rst_trans) rst_fifo; 70 | uvm_tlm_fifo#(jvs_clk_change_div) change_div_fifo; 71 | virtual jvs_gen_clk_if vif; 72 | `uvm_component_utils_begin(jvs_gen_clk_driver) 73 | `uvm_component_utils_end 74 | 75 | function new(string name = "jvs_gen_clk_driver", uvm_component parent); 76 | super.new(name, parent); 77 | rst_fifo = new("rst_fifo", this); 78 | change_div_fifo = new("change_div_fifo", this); 79 | rst_ana_imp = new("rst_ana_imp", this); 80 | change_div_ana_imp = new("change_div_ana_imp", this); 81 | endfunction // new 82 | 83 | virtual function void build_phase(uvm_phase phase); 84 | super.build_phase(phase); 85 | cfg.check_div_ratio(); 86 | if(!uvm_config_db#(virtual jvs_gen_clk_if)::get(this, "", "jvs_gen_clk_if", vif)) begin 87 | `uvm_fatal(get_full_name(), "Can't get gen clk rst interface!"); 88 | end 89 | endfunction // build_phase 90 | 91 | local task drive_clk(); 92 | bit [31:0] cycle_cnt; 93 | int i; 94 | forever begin 95 | @vif.clk_driver; 96 | if(cycle_cnt == cfg.div_ratio - 1) begin 97 | vif.clock <= ~vif.clock; 98 | cycle_cnt = 0; 99 | end 100 | else begin 101 | cycle_cnt++; 102 | end 103 | end 104 | endtask // drive_clk 105 | 106 | local task reset(); 107 | if (cfg.sync_rst) begin 108 | vif.ctrl_driver.reset_n <= 0; 109 | end 110 | else begin 111 | realtime delay = cfg.root_clk.get_period() * real'($urandom_range(1,255))/255; 112 | #(delay); 113 | vif.reset_n = 0; 114 | end 115 | repeat(cfg.rst_cycle) begin 116 | @vif.ctrl_driver; 117 | end 118 | vif.ctrl_driver.reset_n <= 1; 119 | @vif.ctrl_driver; 120 | endtask // reset 121 | 122 | local task reset_begin(); 123 | vif.rst_process = 1; 124 | repeat(3) begin 125 | @vif.clk_driver; 126 | end 127 | endtask // reset_begin 128 | 129 | local task reset_end(); 130 | repeat(2) begin 131 | @vif.ctrl_driver; 132 | end 133 | vif.ctrl_driver.rst_process <= 0; 134 | @vif.ctrl_driver; 135 | endtask // reset_end 136 | 137 | local task reset_process(); 138 | jvs_clk_rst_trans tr; 139 | uvm_event begin_e; 140 | uvm_event rst_e; 141 | uvm_event end_e; 142 | forever begin 143 | rst_fifo.peek(tr); 144 | begin_e = tr.begin_event_pool.get(this.get_name()); 145 | end_e = tr.end_event_pool.get(this.get_name()); 146 | rst_e = tr.rst_event_pool.get(this.get_name()); 147 | 148 | reset_begin(); 149 | begin_e.trigger(); 150 | tr.wait_begin(); 151 | reset(); 152 | rst_e.trigger(); 153 | tr.wait_rst(); 154 | reset_end(); 155 | end_e.trigger(); 156 | 157 | rst_fifo.get(tr); 158 | end 159 | endtask // reset_process 160 | 161 | local task change_div_process(); 162 | jvs_clk_change_div change_div; 163 | uvm_event end_e; 164 | forever begin 165 | change_div_fifo.peek(change_div); 166 | end_e = change_div.end_event_pool.get(this.get_name()); 167 | @(negedge vif.clock); 168 | this.cfg.div_ratio = change_div.div_ratio; 169 | end_e.trigger(); 170 | change_div_fifo.get(change_div); 171 | end 172 | endtask // reset_process 173 | 174 | virtual task run_phase(uvm_phase phase); 175 | vif.clock = 0; 176 | vif.reset_n = 1; 177 | vif.rst_process= 0; 178 | repeat(cfg.div_ratio) begin 179 | @vif.clk_driver; 180 | end 181 | fork 182 | reset_process(); 183 | join_none 184 | fork 185 | change_div_process(); 186 | join_none 187 | drive_clk(); 188 | endtask // run_phase 189 | 190 | virtual function void write_clk_rst_driver (jvs_clk_rst_trans tr); 191 | if (uvm_is_match(tr.pattern, {cfg.parent.get_name(), ".", cfg.get_name()})) begin 192 | if (!rst_fifo.try_put(tr)) begin 193 | `uvm_fatal(this.get_name(), "hw reset occurs while previous hw reset in processing!"); 194 | end 195 | end 196 | else begin 197 | uvm_event end_e = tr.end_event_pool.get(this.get_name()); 198 | end_e.trigger(); 199 | end 200 | endfunction 201 | 202 | virtual function void write_clk_change_div_driver (jvs_clk_change_div tr); 203 | if (uvm_is_match(tr.pattern, {cfg.parent.get_name(), ".", cfg.get_name()})) begin 204 | if (!change_div_fifo.try_put(tr)) begin 205 | `uvm_fatal(this.get_name(), "change div occurs while previous change div in processing!"); 206 | end 207 | end 208 | else begin 209 | uvm_event end_e = tr.end_event_pool.get(this.get_name()); 210 | end_e.trigger(); 211 | end 212 | endfunction 213 | 214 | endclass 215 | `endif 216 | -------------------------------------------------------------------------------- /src/memory/jvs_memory_block.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MEMORY_BLOCK_SV__ 2 | `define __JVS_MEMORY_BLOCK_SV__ 3 | typedef class jvs_memory_model; 4 | typedef class jvs_memory_allocator; 5 | 6 | virtual class jvs_memory_block extends uvm_object; 7 | rand protected bit[63:0] s_addr; 8 | rand protected bit[63:0] size; 9 | `uvm_field_utils_begin(jvs_memory_block) 10 | `uvm_field_int(s_addr, UVM_ALL_ON) 11 | `uvm_field_int(size, UVM_ALL_ON) 12 | `uvm_field_utils_end 13 | 14 | function new(input string name = "jvs_memory_block"); 15 | super.new(name); 16 | endfunction // new 17 | 18 | function bit[63:0] get_s_addr(); 19 | return this.s_addr; 20 | endfunction // get_s_addr 21 | 22 | function bit[64:0] get_size(); 23 | return this.size + 1; 24 | endfunction 25 | 26 | function bit[63:0] get_e_addr(); 27 | return this.s_addr + this.size; 28 | endfunction 29 | 30 | function bit[1:0] check_boundary(input bit[63:0] addr, input bit[63:0] size = 1); 31 | bit uf = addr < this.s_addr; 32 | bit of = addr + size - 1 > this.get_e_addr(); 33 | return {uf, of}; 34 | endfunction // check_boundary 35 | 36 | function void configurate(input bit[63:0] s_addr, input bit[64:0] size); 37 | this.s_addr = s_addr; 38 | this.size = size - 1; 39 | endfunction 40 | endclass // jvs_memory_block 41 | 42 | class jvs_memory_free_block extends jvs_memory_block; 43 | `uvm_object_utils_begin(jvs_memory_free_block) 44 | `uvm_object_utils_end 45 | 46 | function new(input string name = "jvs_memory_free_block"); 47 | super.new(name); 48 | endfunction 49 | 50 | local function bit[63:0] get_align_s_addr(input e_alignment align); 51 | bit [63:0] _s_addr = this.s_addr + ((1< this.get_e_addr() || 78 | e_addr_req < this.get_s_addr() || 79 | s_addr_aligned > this.get_e_addr() || 80 | s_addr_aligned < this.get_s_addr() || 81 | e_addr_req[64]) begin 82 | return 0; 83 | end 84 | 85 | begin 86 | bit [63:0] _s_addr = s_addr_aligned; 87 | bit [63:0] _e_addr = this.get_e_addr(); 88 | bit [63:0] _size = size_req; 89 | 90 | if (fixed_s_addr) begin 91 | assert(output_block.randomize() with { 92 | s_addr == _s_addr; 93 | size == _size - 1; 94 | s_addr + size inside {[_s_addr : _e_addr]}; 95 | }) else begin 96 | `uvm_fatal(this.get_name(), "gen_block failed!"); 97 | end 98 | end 99 | else begin 100 | bit[63:0] _output_block_s_addr; 101 | assert(output_block.randomize() with { 102 | s_addr inside {[_s_addr : _e_addr]}; 103 | size == _size - 1; 104 | s_addr + size inside {[_s_addr : _e_addr]}; 105 | }) else begin 106 | `uvm_fatal(this.get_name(), "gen_block failed!"); 107 | end 108 | _output_block_s_addr = output_block.get_s_addr(); 109 | foreach(_output_block_s_addr[i]) begin 110 | if (i < align) begin 111 | _output_block_s_addr[i] = 0; 112 | end 113 | end 114 | output_block.configurate(_output_block_s_addr, output_block.get_size()); 115 | end // else: !if(fixed_s_addr) 116 | 117 | 118 | if (this.get_s_addr() != output_block.get_s_addr()) begin 119 | jvs_memory_free_block _lower_block = jvs_memory_free_block::type_id::create(); 120 | _lower_block.configurate(this.get_s_addr(), output_block.get_s_addr() - this.get_s_addr()); 121 | lower_block = _lower_block; 122 | end 123 | else begin 124 | lower_block = null; 125 | end 126 | 127 | if (_e_addr != output_block.get_e_addr()) begin 128 | jvs_memory_free_block _upper_block = jvs_memory_free_block::type_id::create(); 129 | _upper_block.configurate(output_block.get_e_addr() + 1, _e_addr - output_block.get_e_addr()); 130 | upper_block = _upper_block; 131 | end 132 | else begin 133 | upper_block = null; 134 | end 135 | end // begin 136 | return 1; 137 | endfunction 138 | 139 | endclass // jvs_memory_free_block 140 | 141 | 142 | class jvs_memory_acc_block extends jvs_memory_block; 143 | protected jvs_memory_allocator p_allocator; 144 | `uvm_object_utils_begin(jvs_memory_acc_block) 145 | `uvm_field_object(p_allocator, UVM_ALL_ON) 146 | `uvm_object_utils_end 147 | 148 | function new(input string name = "jvs_memory_acc_block"); 149 | super.new(name); 150 | endfunction 151 | 152 | function void set_p_allocator(jvs_memory_allocator p_allocator); 153 | this.p_allocator = p_allocator; 154 | endfunction // set_p_allocator 155 | 156 | function jvs_memory_allocator get_p_allocator(); 157 | return this.p_allocator; 158 | endfunction // set_p_allocator 159 | 160 | 161 | local function void check_before_access(input bit[63:0] addr, input bit[63:0] size_req = 1); 162 | bit[1:0] status; 163 | status = check_boundary(addr, size_req); 164 | if (status[1]) begin 165 | `uvm_fatal(this.get_name(), $psprintf("addr 0x%0x is underflow! s_addr is 0x%0x", addr, s_addr)); 166 | end 167 | if (status[0]) begin 168 | `uvm_fatal(this.get_name(), $psprintf("addr 0x%0x is overflow! s_addr is 0x%0x", addr, this.get_e_addr)); 169 | end 170 | endfunction 171 | 172 | function void write_long(input bit[63:0] addr, input MEM_LONG data); 173 | check_before_access(s_addr + addr, 8); 174 | this.p_allocator.write_long(s_addr+addr, data); 175 | endfunction 176 | 177 | function void write_int(input bit[63:0] addr, input MEM_INT data); 178 | check_before_access(s_addr + addr, 4); 179 | this.p_allocator.write_int(s_addr+addr, data); 180 | endfunction 181 | 182 | function void write_byte(input bit[63:0] addr, input MEM_BYTE data); 183 | check_before_access(s_addr + addr, 1); 184 | this.p_allocator.write_byte(s_addr+addr, data); 185 | endfunction 186 | 187 | function MEM_LONG read_long(input bit[63:0] addr); 188 | check_before_access(s_addr + addr, 8); 189 | return this.p_allocator.read_long(s_addr+addr); 190 | endfunction 191 | 192 | function MEM_INT read_int(input bit[63:0] addr); 193 | check_before_access(s_addr + addr, 4); 194 | return this.p_allocator.read_int(s_addr+addr); 195 | endfunction 196 | 197 | function MEM_BYTE read_byte(input bit[63:0] addr); 198 | check_before_access(s_addr + addr, 1); 199 | return this.p_allocator.read_byte(s_addr+addr); 200 | endfunction 201 | 202 | function void data2mem(input MEM_BYTE data[], input bit[63:0] offset = 0); 203 | foreach(data[i]) begin 204 | write_byte(offset + i, data[i]); 205 | end 206 | endfunction 207 | 208 | function void data2mem_stream(uvm_bitstream_t value, input int size_req, input bit[63:0] offset = 0); 209 | if ((size_req % 8) != 0) begin 210 | `uvm_fatal(this.get_name(), $psprintf("mem2data_stream size %0d is not byte aligned!", size_req)); 211 | end 212 | if (size_req > `UVM_MAX_STREAMBITS) begin 213 | `uvm_fatal(this.get_name(), $psprintf("mem2data_stream size %0d is larger than UVM_MAX_STREAMBITS %0d!", size_req, `UVM_MAX_STREAMBITS)); 214 | end 215 | 216 | for(int i = 0; i < (size_req/8); i++) begin 217 | write_byte(offset+i, value[i*8 +:8]); 218 | end 219 | endfunction 220 | 221 | 222 | function void mem2data(ref MEM_BYTE data[], input bit[63:0] offset = 0); 223 | data = new[this.get_size() -offset]; 224 | foreach(data[i]) begin 225 | data[i] = read_byte(offset + i); 226 | end 227 | endfunction 228 | 229 | function void mem2data_stream(output uvm_bitstream_t value, input int size_req, input bit[63:0] offset = 0); 230 | if ((size_req % 8) != 0) begin 231 | `uvm_fatal(this.get_name(), $psprintf("mem2data_stream size %0d is not byte aligned!", size_req)); 232 | end 233 | if (size_req > `UVM_MAX_STREAMBITS) begin 234 | `uvm_fatal(this.get_name(), $psprintf("mem2data_stream size %0d is larger than UVM_MAX_STREAMBITS %0d!", size_req, `UVM_MAX_STREAMBITS)); 235 | end 236 | for(int i = 0; i < (size_req/8); i++) begin 237 | value[i*8 +:8] = read_byte(offset+i); 238 | end 239 | endfunction 240 | 241 | endclass 242 | `endif -------------------------------------------------------------------------------- /src/register_region/jvs_reg_region.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_REG_REGION_SV__ 2 | `define __JVS_REG_REGION_SV__ 3 | class jvs_reg_region_attr extends jvs_common_attr; 4 | `uvm_object_utils(jvs_reg_region_attr); 5 | function new(string name = "jvs_reg_region_attr"); 6 | super.new(name); 7 | endfunction // new 8 | endclass // jvs_reg_region_attr 9 | 10 | class jvs_reg_region extends jvs_reg_tree_node#(jvs_reg_region); 11 | typedef jvs_reg_tree_node#(jvs_reg_region) NODE_TYPE; 12 | rand jvs_reg_region_attr attr; 13 | local jvs_reg_seqr_adapter_pair seqr_adapter; 14 | protected jvs_reg_tree_nodes#(jvs_reg_block_wrapper) reg_block_table; 15 | protected jvs_reg_tree_nodes#(jvs_reg_region) sub_region_table; 16 | protected bit[63:0] offset; 17 | protected bit [63:0] size; 18 | 19 | `uvm_object_utils_begin(jvs_reg_region) 20 | `uvm_field_object(attr, UVM_ALL_ON) 21 | `uvm_field_object(seqr_adapter, UVM_ALL_ON) 22 | `uvm_field_object(reg_block_table, UVM_ALL_ON) 23 | `uvm_field_object(sub_region_table, UVM_ALL_ON) 24 | `uvm_field_int(offset, UVM_ALL_ON) 25 | `uvm_field_int(size, UVM_ALL_ON) 26 | `uvm_object_utils_end 27 | 28 | function new(string name = "jvs_reg_region"); 29 | super.new(name); 30 | reg_block_table = jvs_reg_tree_nodes#(jvs_reg_block_wrapper)::type_id::create("reg_block_table"); 31 | sub_region_table = jvs_reg_tree_nodes#(jvs_reg_region)::type_id::create("sub_region_table"); 32 | endfunction // new 33 | 34 | virtual function bit[63:0] get_base(); 35 | if (parent == null) begin 36 | return offset; 37 | end 38 | return parent.get_base() + offset; 39 | endfunction // get_base 40 | 41 | virtual function bit[63:0] get_size(); 42 | return size; 43 | endfunction // get_size 44 | 45 | function void config_range(bit[63:0] offset, bit[63:0] size); 46 | this.offset = offset; 47 | this.size =size; 48 | endfunction // config_range 49 | 50 | function void config_seqr_adapter(jvs_reg_seqr_adapter_pair seqr_adapter); 51 | this.seqr_adapter = seqr_adapter; 52 | endfunction // config_seqr_adapter 53 | 54 | //path compression 55 | function jvs_reg_seqr_adapter_pair get_seqr_adapter(); 56 | if (this.seqr_adapter == null) begin 57 | this.seqr_adapter = parent.get_seqr_adapter(); 58 | end 59 | if (this.seqr_adapter == null) begin 60 | `uvm_fatal(this.get_name(), "not set seqr_adapter!"); 61 | end 62 | return this.seqr_adapter; 63 | endfunction // get_seqr_adapter 64 | 65 | function bit add_reg_block(jvs_reg_block_wrapper reg_block); 66 | jvs_reg_region sub_regions[$]; 67 | jvs_reg_block_wrapper reg_blocks[$]; 68 | //check if exist 69 | if (!reg_block_table.check_exist_name(reg_block)) begin 70 | return 0; 71 | end 72 | reg_block_table.get_nodes(reg_blocks); 73 | sub_region_table.get_nodes(sub_regions); 74 | //if exists sub region, add to it 75 | foreach(sub_regions[i]) begin 76 | if (reg_block.in_region(sub_regions[i])) begin 77 | return sub_regions[i].add_reg_block(reg_block); 78 | end 79 | end 80 | reg_block.set_parent(this); 81 | if (!check_in_region(reg_block)) begin 82 | reg_block.set_parent(null); 83 | return 0; 84 | end 85 | //if exist a reg_block is child of one another, use the one has larger range 86 | foreach(reg_blocks[i]) begin 87 | if (reg_block.in_region(reg_blocks[i])) begin 88 | return 1; 89 | end 90 | end 91 | if (!reg_block_table.check_overlap(reg_block)) begin 92 | reg_block.set_parent(null); 93 | return 0; 94 | end 95 | reg_block_table.add_node(reg_block); 96 | return 1; 97 | endfunction // add_reg_block 98 | 99 | function bit add_sub_region(jvs_reg_region region); 100 | jvs_reg_region sub_regions[$]; 101 | //check if exist 102 | if (!sub_region_table.check_exist_name(region))begin 103 | return 0; 104 | end 105 | sub_region_table.get_nodes(sub_regions); 106 | //if existes sub region, add to it 107 | foreach(sub_regions[i]) begin 108 | if (region.in_region(sub_regions[i])) begin 109 | return sub_regions[i].add_sub_region(region); 110 | end 111 | end 112 | region.set_parent(this); 113 | if (!check_in_region(region))begin 114 | region.set_parent(null); 115 | return 0; 116 | end 117 | if (!sub_region_table.check_overlap(region)) begin 118 | region.set_parent(null); 119 | return 0; 120 | end 121 | sub_region_table.add_node(region); 122 | return 1; 123 | endfunction // add_sub_region 124 | 125 | function jvs_reg_block_wrapper get_reg_block(string key); 126 | jvs_reg_region sub_regions[$]; 127 | jvs_reg_block_wrapper reg_blocks[$]; 128 | jvs_reg_block_wrapper reg_block; 129 | 130 | reg_block_table.get_nodes(reg_blocks); 131 | foreach(reg_blocks[i]) begin 132 | reg_block = reg_blocks[i].get_reg_block(key); 133 | if (reg_block!=null) begin 134 | return reg_block; 135 | end 136 | end 137 | sub_region_table.get_nodes(sub_regions); 138 | foreach(sub_regions[i]) begin 139 | reg_block = sub_regions[i].get_reg_block(key); 140 | if(reg_block != null) begin 141 | return reg_block; 142 | end 143 | end 144 | return null; 145 | endfunction // get_reg_block 146 | 147 | function bit remove_reg_block(string key); 148 | jvs_reg_region sub_regions[$]; 149 | if (reg_block_table.remove_node(key)) begin 150 | return 1; 151 | end 152 | sub_region_table.get_nodes(sub_regions); 153 | foreach(sub_regions[i]) begin 154 | if (sub_regions[i].remove_reg_block(key)) begin 155 | return 1; 156 | end 157 | end 158 | return 0; 159 | endfunction // remove_reg_block 160 | 161 | local function bit get_reg(string name, output jvs_reg_block_wrapper reg_block, output uvm_reg register); 162 | jvs_reg_region sub_regions[$]; 163 | jvs_reg_block_wrapper reg_blocks[$]; 164 | jvs_reg_block_wrapper _reg_block; 165 | uvm_reg _register; 166 | sub_region_table.get_nodes(sub_regions); 167 | foreach(sub_regions[i]) begin 168 | if (sub_regions[i].get_reg(name, _reg_block, _register)) begin 169 | reg_block = _reg_block; 170 | register = _register; 171 | return 1; 172 | end 173 | end 174 | reg_block_table.get_nodes(reg_blocks); 175 | foreach(reg_blocks[i]) begin 176 | if(reg_blocks[i].get_reg(name, _reg_block, _register)) begin 177 | reg_block = _reg_block; 178 | register = _register; 179 | return 1; 180 | end 181 | end 182 | return 0; 183 | endfunction // get_reg 184 | 185 | function jvs_reg_region get_region(string key); 186 | if (key == this.get_name()) begin 187 | return this; 188 | end 189 | return this.get_sub_region(key); 190 | endfunction 191 | 192 | function jvs_reg_region get_sub_region(string key); 193 | jvs_reg_region sub_regions[$]; 194 | jvs_reg_region node = sub_region_table.get_node(key); 195 | if (node != null) begin 196 | return node; 197 | end 198 | sub_region_table.get_nodes(sub_regions); 199 | foreach(sub_regions[i])begin 200 | node = sub_regions[i].get_sub_region(key); 201 | if (node != null) begin 202 | return node; 203 | end 204 | end 205 | return null; 206 | endfunction // get_sub_region 207 | 208 | //for normal case access 209 | local task write(string name, uvm_reg_data_t value, output uvm_status_e status, input uvm_path_e path = UVM_DEFAULT_PATH); 210 | uvm_reg match_reg; 211 | jvs_reg_block_wrapper reg_block; 212 | if (get_reg(name, reg_block, match_reg)) begin 213 | `uvm_info(this.get_name(), "write begin request!", UVM_HIGH); 214 | jvs_reg_resource_manager::get_manager().request_reg_map(get_seqr_adapter(), match_reg.get_default_map().get_root_map()); 215 | `uvm_info(this.get_name(), "begin write!", UVM_HIGH); 216 | match_reg.write(.status(status), .value(value), .path(path), .extension(attr)); 217 | `uvm_info(this.get_name(), "after write!", UVM_HIGH); 218 | jvs_reg_resource_manager::get_manager().release_reg_map(get_seqr_adapter(), match_reg.get_default_map().get_root_map()); 219 | `uvm_info(this.get_name(), "write after release!", UVM_HIGH); 220 | end 221 | endtask // write 222 | 223 | task write_fd(string name, uvm_reg_data_t value, output uvm_status_e status); 224 | this.write(name, value, status, UVM_FRONTDOOR); 225 | endtask 226 | 227 | task write_bd(string name, uvm_reg_data_t value, output uvm_status_e status); 228 | this.write(name, value, status, UVM_BACKDOOR); 229 | endtask // write_bd 230 | 231 | local task read(string name, output uvm_reg_data_t value, output uvm_status_e status, input uvm_path_e path = UVM_DEFAULT_PATH); 232 | uvm_reg match_reg; 233 | jvs_reg_block_wrapper reg_block; 234 | if (get_reg(name, reg_block, match_reg)) begin 235 | `uvm_info(this.get_name(), "read begin request!", UVM_HIGH); 236 | jvs_reg_resource_manager::get_manager().request_reg_map(get_seqr_adapter(), match_reg.get_default_map().get_root_map()); 237 | `uvm_info(this.get_name(), "begin read!", UVM_HIGH); 238 | match_reg.read(.status(status), .value(value), .path(path), .extension(attr)); 239 | `uvm_info(this.get_name(), "after read!", UVM_HIGH); 240 | jvs_reg_resource_manager::get_manager().release_reg_map(get_seqr_adapter(), match_reg.get_default_map().get_root_map()); 241 | `uvm_info(this.get_name(), "read after release!", UVM_HIGH); 242 | end 243 | endtask // read 244 | 245 | task read_fd(string name, output uvm_reg_data_t value, output uvm_status_e status); 246 | this.read(name, value, status, UVM_FRONTDOOR); 247 | endtask 248 | 249 | task read_bd(string name, output uvm_reg_data_t value, output uvm_status_e status); 250 | this.read(name, value, status, UVM_BACKDOOR); 251 | endtask // read_bd 252 | 253 | task mirror(string name, output uvm_status_e status); 254 | uvm_reg match_reg; 255 | jvs_reg_block_wrapper reg_block; 256 | if (get_reg(name, reg_block, match_reg)) begin 257 | `uvm_info(this.get_name(), "mirror begin request!", UVM_HIGH); 258 | jvs_reg_resource_manager::get_manager().request_reg_map(get_seqr_adapter(), match_reg.get_default_map().get_root_map()); 259 | `uvm_info(this.get_name(), "begin mirror!", UVM_HIGH); 260 | match_reg.mirror(.status(status), .check(UVM_CHECK), .extension(attr)); 261 | `uvm_info(this.get_name(), "after mirror!", UVM_HIGH); 262 | jvs_reg_resource_manager::get_manager().release_reg_map(get_seqr_adapter(), match_reg.get_default_map().get_root_map()); 263 | `uvm_info(this.get_name(), "mirror after release!", UVM_HIGH); 264 | end 265 | endtask // mirror 266 | 267 | task predict(string name, uvm_reg_data_t value); 268 | uvm_reg match_reg; 269 | jvs_reg_block_wrapper reg_block; 270 | if (get_reg(name, reg_block, match_reg)) begin 271 | `uvm_info(this.get_name(), "predict begin request!", UVM_HIGH); 272 | jvs_reg_resource_manager::get_manager().request_reg_map(get_seqr_adapter(), match_reg.get_default_map().get_root_map()); 273 | `uvm_info(this.get_name(), "begin predict!", UVM_HIGH); 274 | match_reg.predict(value); 275 | `uvm_info(this.get_name(), "after predict!", UVM_HIGH); 276 | jvs_reg_resource_manager::get_manager().release_reg_map(get_seqr_adapter(), match_reg.get_default_map().get_root_map()); 277 | `uvm_info(this.get_name(), "predict after release!", UVM_HIGH); 278 | end 279 | endtask // predict 280 | 281 | endclass 282 | `endif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2019 Li Yang 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/clk_rst_group/jvs_clk_rst_trans.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_CLK_RST_TRANS_SV__ 2 | `define __JVS_CLK_RST_TRANS_SV__ 3 | interface class jvs_clk_period_freq_if; 4 | pure virtual function realtime get_period(); 5 | pure virtual function realtime get_max_period(); 6 | pure virtual function realtime get_min_period(); 7 | pure virtual function real get_freq(); 8 | pure virtual function real get_max_freq(); 9 | pure virtual function real get_min_freq(); 10 | pure virtual function realtime get_init_delay(); 11 | endclass // jvs_clk_period_freq_if 12 | 13 | virtual class jvs_clk_cfg_base extends uvm_object; 14 | int rst_cycle = 5; 15 | `uvm_field_utils_begin(jvs_clk_cfg_base) 16 | `uvm_field_int(rst_cycle, UVM_ALL_ON) 17 | `uvm_field_utils_end 18 | 19 | function new(string name = "jvs_clk_cfg_base"); 20 | super.new(name); 21 | endfunction 22 | endclass // jvs_clk_cfg_base 23 | 24 | class jvs_root_clk_cfg extends jvs_clk_cfg_base implements jvs_clk_period_freq_if; 25 | //should be 1ns, 1ps, 1us, 1ms 26 | realtime timescale; 27 | real period; 28 | rand bit [7:0] jitter; 29 | rand bit [7:0] init_delay; 30 | 31 | constraint c_jitter { 32 | jitter inside {[0:63]}; 33 | } 34 | 35 | constraint c_init_delay { 36 | init_delay inside {[1:255]}; 37 | } 38 | 39 | `uvm_object_utils_begin(jvs_root_clk_cfg) 40 | `uvm_field_real(timescale, UVM_ALL_ON) 41 | `uvm_field_int(jitter, UVM_ALL_ON) 42 | `uvm_field_int(init_delay, UVM_ALL_ON) 43 | `uvm_object_utils_end 44 | 45 | function new(string name = "jvs_root_clk_cfg"); 46 | super.new(name); 47 | timescale = 1ns; 48 | period = 1.0; 49 | endfunction 50 | 51 | virtual function realtime get_period(); 52 | return (this.period * this.timescale) / 2.0; 53 | endfunction 54 | 55 | virtual function realtime get_max_period(); 56 | return this.get_period() * (1.0 + real'(this.jitter)/255); 57 | endfunction 58 | 59 | virtual function realtime get_min_period(); 60 | return this.get_period() * (1.0 - real'(this.jitter)/255); 61 | endfunction 62 | 63 | virtual function real get_freq(); 64 | return 2.0 / this.period; 65 | endfunction 66 | 67 | virtual function real get_max_freq(); 68 | return this.get_freq() / (1.0 - real'(this.jitter)/255); 69 | endfunction 70 | 71 | virtual function real get_min_freq(); 72 | return this.get_freq() / (1.0 + real'(this.jitter)/255); 73 | endfunction 74 | 75 | virtual function realtime get_init_delay(); 76 | return (real'(init_delay/255)) * this.get_period(); 77 | endfunction 78 | endclass // jvs_root_clk_cfg 79 | 80 | typedef class jvs_clk_group_cfg; 81 | 82 | class jvs_gen_clk_cfg extends jvs_clk_cfg_base implements jvs_clk_period_freq_if; 83 | jvs_root_clk_cfg root_clk; 84 | jvs_clk_group_cfg parent; 85 | int div_ratio; 86 | bit sync_rst; 87 | 88 | `uvm_object_utils_begin(jvs_gen_clk_cfg) 89 | `uvm_field_object(root_clk, UVM_ALL_ON) 90 | `uvm_field_object(parent, UVM_ALL_ON) 91 | `uvm_field_int(div_ratio, UVM_ALL_ON) 92 | `uvm_object_utils_end 93 | 94 | function new(string name = "jvs_gen_clk_cfg"); 95 | super.new(name); 96 | div_ratio = 1; 97 | endfunction 98 | 99 | function void check_div_ratio(); 100 | if (div_ratio < 1) begin 101 | `uvm_fatal(this.get_name(), "div ratio must be at least 1!"); 102 | end 103 | endfunction 104 | 105 | virtual function realtime get_period(); 106 | return root_clk.get_period() * div_ratio; 107 | endfunction 108 | 109 | virtual function realtime get_max_period(); 110 | return root_clk.get_max_period() * div_ratio; 111 | endfunction 112 | 113 | virtual function realtime get_min_period(); 114 | return root_clk.get_min_period() * div_ratio; 115 | endfunction 116 | 117 | virtual function real get_freq(); 118 | return root_clk.get_freq() / div_ratio; 119 | endfunction 120 | 121 | virtual function real get_max_freq(); 122 | return root_clk.get_max_freq() / div_ratio; 123 | endfunction 124 | 125 | virtual function real get_min_freq(); 126 | return root_clk.get_min_freq() / div_ratio; 127 | endfunction 128 | 129 | virtual function realtime get_init_delay(); 130 | return root_clk.get_init_delay(); 131 | endfunction 132 | 133 | endclass // jvs_gen_clk_cfg 134 | 135 | class jvs_clk_group_cfg extends jvs_clk_cfg_base; 136 | jvs_root_clk_cfg root_clk; 137 | jvs_gen_clk_cfg gen_clks[$]; 138 | 139 | `uvm_object_utils_begin(jvs_clk_group_cfg) 140 | `uvm_field_object(root_clk, UVM_ALL_ON) 141 | `uvm_field_queue_object(gen_clks, UVM_ALL_ON) 142 | `uvm_object_utils_end 143 | 144 | function new(string name = "jvs_clk_group_cfg"); 145 | super.new(name); 146 | endfunction 147 | 148 | function void add_gen_clk(jvs_gen_clk_cfg clk); 149 | clk.root_clk = this.root_clk; 150 | clk.parent = this; 151 | gen_clks.push_back(clk); 152 | endfunction 153 | endclass // jvs_clk_group_cfg 154 | 155 | class jvs_clk_top_cfg extends jvs_clk_cfg_base; 156 | jvs_clk_group_cfg groups[string]; 157 | `uvm_object_utils_begin(jvs_clk_top_cfg) 158 | `uvm_field_aa_object_string(groups, UVM_ALL_ON) 159 | `uvm_object_utils_end 160 | 161 | function new(string name = "jvs_clk_top_cfg"); 162 | super.new(name); 163 | endfunction 164 | 165 | function void add_group(jvs_clk_group_cfg group); 166 | this.groups[group.get_name()] = group; 167 | endfunction 168 | 169 | endclass // jvs_clk_top_cfg 170 | 171 | virtual class jvs_clk_trans_base#(type CFG_CLASS = jvs_clk_period_freq_if) extends uvm_sequence_item; 172 | CFG_CLASS cfg; 173 | int cycle_cnt; 174 | bit is_root; 175 | realtime start_time; 176 | realtime cur_time; 177 | 178 | `uvm_field_utils_begin(jvs_clk_trans_base) 179 | `uvm_field_real(start_time, UVM_ALL_ON) 180 | `uvm_field_real(cur_time, UVM_ALL_ON) 181 | `uvm_field_int(cycle_cnt, UVM_ALL_ON) 182 | `uvm_field_int(is_root, UVM_ALL_ON) 183 | `uvm_field_utils_end 184 | 185 | function new(string name = "jvs_clk_trans_base"); 186 | super.new(name); 187 | endfunction 188 | 189 | virtual function void start_clk(); 190 | start_time = $realtime; 191 | cycle_cnt = 0; 192 | endfunction 193 | 194 | virtual function void sample_clk(input int cycle_cnt); 195 | cur_time = $realtime; 196 | this.cycle_cnt += cycle_cnt; 197 | endfunction 198 | 199 | virtual function realtime get_sampled_mean_period(); 200 | return (cur_time - start_time)/cycle_cnt; 201 | endfunction 202 | 203 | virtual function realtime get_sampled_mean_freq(); 204 | return 1.0 / this.get_sampled_mean_period(); 205 | endfunction 206 | 207 | endclass // jvs_clk_trans_base 208 | 209 | class jvs_root_clk_trans extends jvs_clk_trans_base#(jvs_root_clk_cfg); 210 | rand bit [7:0] jitter; 211 | rand bit jitter_flag; 212 | local bit[7:0] compensation; 213 | local bit compensation_flag; 214 | 215 | constraint c_period { 216 | jitter inside{[0:cfg.jitter]}; 217 | } 218 | 219 | `uvm_object_utils_begin(jvs_root_clk_trans) 220 | `uvm_field_object(cfg, UVM_ALL_ON) 221 | `uvm_field_int(jitter, UVM_ALL_ON) 222 | `uvm_field_int(jitter_flag, UVM_ALL_ON) 223 | `uvm_object_utils_end 224 | 225 | function new(string name = "jvs_root_clk_trans"); 226 | super.new(name); 227 | is_root = 1; 228 | compensation = 0; 229 | compensation_flag = 0; 230 | endfunction 231 | 232 | local function real jitter_value(); 233 | return real'(this.jitter)/255; 234 | endfunction 235 | 236 | local function bit[8:0] jitter_comp(); 237 | bit [8:0] jitter_comped; 238 | bit flag_comped; 239 | 240 | if (jitter_flag == compensation_flag) begin 241 | jitter_comped = this.jitter + this.compensation; 242 | if (jitter_comped[8]) begin 243 | `uvm_fatal("jvs_clk", $psprintf("unexpect jitter value: jitter_comped:0x%x, compensation:0x%x, jitter_origin:0x%x", jitter_comped, this.compensation, this.jitter)) 244 | end 245 | jitter_comped[8] = jitter_flag; 246 | end 247 | else begin 248 | if (this.jitter > this.compensation) begin 249 | jitter_comped = this.jitter - this.compensation; 250 | jitter_comped[8] = jitter_flag; 251 | end 252 | else begin 253 | jitter_comped = this.compensation - this.jitter; 254 | jitter_comped[8] = compensation_flag; 255 | end 256 | end // else: !if(jitter_flag == compensation_flag) 257 | return jitter_comped; 258 | endfunction // jitter_comp 259 | 260 | virtual function realtime get_half_period(); 261 | bit [8:0] jitter_comped = jitter_comp(); 262 | if (jitter_comped[8]) begin 263 | return (cfg.get_period()/2.0) * (1.0 - real'(jitter_comped[7:0])/255); 264 | end 265 | return (cfg.get_period()/2.0) * (1.0 + real'(jitter_comped[7:0])/255); 266 | 267 | endfunction // get_half_period 268 | 269 | virtual function compensate(bit compensation_flag, bit[7:0] compensation); 270 | this.compensation_flag = compensation_flag; 271 | this.compensation = compensation; 272 | endfunction 273 | endclass // jvs_root_clk_trans 274 | 275 | class jvs_gen_clk_trans extends jvs_clk_trans_base#(jvs_gen_clk_cfg); 276 | `uvm_object_utils_begin(jvs_gen_clk_trans) 277 | `uvm_field_object(cfg, UVM_ALL_ON) 278 | `uvm_object_utils_end 279 | function new(string name = "jvs_gen_clk_trans"); 280 | super.new(name); 281 | is_root = 0; 282 | endfunction 283 | endclass // jvs_gen_clk_trans 284 | 285 | 286 | virtual class jvs_clk_cmd extends uvm_sequence_item; 287 | uvm_event_pool end_event_pool; 288 | string pattern; 289 | `uvm_field_utils_begin(jvs_clk_cmd) 290 | `uvm_field_object(end_event_pool, UVM_ALL_ON) 291 | `uvm_field_string(pattern, UVM_ALL_ON) 292 | `uvm_field_utils_end 293 | 294 | function new(string name = "jvs_clk_cmd"); 295 | super.new(name); 296 | end_event_pool = new(); 297 | endfunction 298 | 299 | task wait_end(); 300 | wait_event_pool(this.end_event_pool); 301 | endtask 302 | 303 | protected task wait_event_pool(uvm_event_pool event_pool); 304 | string key; 305 | //wait to start 306 | while(!event_pool.num()) begin 307 | #1ns; 308 | end 309 | while(event_pool.next(key)) begin 310 | uvm_event e = event_pool.get(key); 311 | e.wait_on(); 312 | end 313 | endtask 314 | 315 | endclass 316 | class jvs_clk_rst_trans extends jvs_clk_cmd; 317 | uvm_event_pool rst_event_pool; 318 | uvm_event_pool begin_event_pool; 319 | 320 | `uvm_object_utils_begin(jvs_clk_rst_trans) 321 | `uvm_field_object(rst_event_pool, UVM_ALL_ON) 322 | `uvm_field_object(begin_event_pool, UVM_ALL_ON) 323 | `uvm_object_utils_end 324 | 325 | function new(string name = "jvs_clk_rst_trans"); 326 | super.new(name); 327 | rst_event_pool = new(); 328 | begin_event_pool = new(); 329 | endfunction 330 | 331 | task wait_rst(); 332 | wait_event_pool(this.rst_event_pool); 333 | endtask 334 | 335 | task wait_begin(); 336 | wait_event_pool(this.begin_event_pool); 337 | endtask 338 | 339 | endclass 340 | 341 | class jvs_clk_change_div extends jvs_clk_cmd; 342 | int div_ratio; 343 | `uvm_object_utils_begin(jvs_clk_change_div) 344 | `uvm_field_int(div_ratio, UVM_ALL_ON) 345 | `uvm_object_utils_end 346 | 347 | function new(string name = "jvs_clk_change_div"); 348 | super.new(name); 349 | endfunction 350 | 351 | endclass 352 | 353 | `endif 354 | -------------------------------------------------------------------------------- /src/memory/jvs_memory_allocator.sv: -------------------------------------------------------------------------------- 1 | `ifndef __JVS_MEMORY_ALLOCATOR_SV__ 2 | `define __JVS_MEMORY_ALLOCATOR_SV__ 3 | 4 | typedef jvs_common_attr jvs_memory_attr; 5 | typedef class jvs_memory_block; 6 | typedef class jvs_memory_free_block; 7 | typedef class jvs_memory_acc_block; 8 | 9 | 10 | class jvs_memory_range extends jvs_memory_block; 11 | `uvm_object_utils_begin(jvs_memory_range) 12 | `uvm_object_utils_end 13 | function new(input string name = "jvs_memory_range"); 14 | super.new(name); 15 | this.size = 64'hffffffff_ffffffff; 16 | endfunction // new 17 | endclass 18 | 19 | virtual class jvs_memory_mmu extends uvm_object; 20 | `uvm_field_utils_begin(jvs_memory_mmu) 21 | `uvm_field_utils_end 22 | 23 | function new(input string name = "jvs_memory_mmu"); 24 | super.new(name); 25 | endfunction // new 26 | 27 | pure virtual function bit[63:0] va2pa(bit[63:0] va, jvs_memory_attr attr); 28 | pure virtual function bit[63:0] pa2va(bit[63:0] pa, jvs_memory_attr attr); 29 | 30 | endclass 31 | 32 | class jvs_memory_cfg extends uvm_object; 33 | jvs_memory_mmu mmu; 34 | 35 | jvs_memory_range range; 36 | 37 | jvs_memory_model model; 38 | 39 | jvs_memory_attr attr; 40 | 41 | `uvm_object_utils_begin(jvs_memory_cfg) 42 | `uvm_field_object(range, UVM_ALL_ON | UVM_REFERENCE) 43 | `uvm_field_object(model, UVM_ALL_ON | UVM_REFERENCE) 44 | `uvm_field_object(mmu, UVM_ALL_ON | UVM_REFERENCE) 45 | `uvm_field_object(attr, UVM_ALL_ON | UVM_REFERENCE) 46 | `uvm_object_utils_end 47 | 48 | function new(input string name = "jvs_memory_cfg"); 49 | super.new(name); 50 | endfunction // new 51 | 52 | endclass 53 | 54 | 55 | class jvs_memory_allocator extends jvs_memory_cfg; 56 | protected semaphore mutex; 57 | 58 | protected jvs_memory_block alloc_q[$]; 59 | protected jvs_memory_free_block free_q[$]; 60 | 61 | `uvm_object_utils_begin(jvs_memory_allocator) 62 | `uvm_field_queue_object(alloc_q, UVM_ALL_ON) 63 | `uvm_field_queue_object(free_q, UVM_ALL_ON) 64 | `uvm_object_utils_end 65 | 66 | function new(input string name = "jvs_memory_allocator"); 67 | super.new(name); 68 | mutex = new(1); 69 | endfunction // new 70 | 71 | function void configurate(input jvs_memory_cfg cfg); 72 | jvs_memory_free_block free_range = jvs_memory_free_block::type_id::create(); 73 | if (cfg == null) begin 74 | `uvm_fatal(this.get_name(), "jvs_memory_cfg is null!"); 75 | end 76 | if (cfg.range == null) begin 77 | `uvm_fatal(this.get_name(), "range of jvs_memory_cfg is null!"); 78 | end 79 | this.copy(cfg); 80 | free_range.configurate(range.get_s_addr(), range.get_size()); 81 | this.free_q.push_back(free_range); 82 | endfunction 83 | 84 | local function bit alloc(input bit[63:0] size, input e_alignment align = ALIGN_BYTE, input jvs_memory_block output_block, input bit[64:0] s_addr = `JVS_MEM_NULL); 85 | jvs_memory_free_block lower_block, upper_block; 86 | foreach (this.free_q[i]) begin 87 | if (this.free_q[i].gen_block(size, align, output_block, lower_block, upper_block, s_addr)) begin 88 | this.alloc_q.push_back(output_block); 89 | this.free_q.delete(i); 90 | if (lower_block) begin 91 | this.free_q.push_back(lower_block); 92 | end 93 | if (upper_block) begin 94 | this.free_q.push_back(upper_block); 95 | end 96 | 97 | if (s_addr != `JVS_MEM_NULL && s_addr[63:0] != output_block.get_s_addr()) begin 98 | `uvm_fatal(this.get_name(), $psprintf("fixed address alloc failed! req addr = 0x%0x, but get_addr = 0x%0x", s_addr, output_block.get_s_addr())) 99 | end 100 | return 1; 101 | end // if (this.free_q[i].gen_block(size, align, output_block, lower_block, upper_block, s_addr)) 102 | end 103 | return 0; 104 | endfunction // alloc 105 | 106 | task malloc(ref jvs_memory_acc_block acc_block, input bit[63:0] size, input e_alignment align = ALIGN_BYTE, input bit[64:0] s_addr = `JVS_MEM_NULL); 107 | mutex.get(); 108 | begin 109 | jvs_memory_acc_block _acc_block = jvs_memory_acc_block::type_id::create(); 110 | if (!this.alloc(size, align, _acc_block, s_addr)) begin 111 | `uvm_info(this.get_name(), $psprintf("malloc failed! out of memory! size = 0x%0s", size), UVM_LOW); 112 | acc_block = null; 113 | mutex.put(); 114 | return; 115 | end 116 | _acc_block.set_p_allocator(this); 117 | `uvm_info(this.get_name(), $psprintf("malloc success! \n%s", _acc_block.sprint()), UVM_HIGH); 118 | acc_block = _acc_block; 119 | end 120 | mutex.put(); 121 | endtask // malloc 122 | 123 | task free(ref jvs_memory_acc_block acc_block); 124 | mutex.get(); 125 | begin 126 | int alloc_block_index[$]; 127 | int lower_block_index_in_free_q[$]; 128 | int upper_block_index_in_free_q[$]; 129 | int lower_block_index_in_alloc_q[$]; 130 | int upper_block_index_in_alloc_q[$]; 131 | jvs_memory_block lower_block, upper_block; 132 | jvs_memory_free_block free_block; 133 | 134 | alloc_block_index = this.alloc_q.find_first_index with (item.get_s_addr() == acc_block.get_s_addr()); 135 | 136 | if (!alloc_block_index.size()) begin 137 | acc_block.print(); 138 | `uvm_fatal(this.get_name(), "free failed! the memory block is not malloced!"); 139 | mutex.put(); 140 | return; 141 | end 142 | 143 | this.alloc_q.delete(alloc_block_index[0]); 144 | 145 | if (!this.free_q.size()) begin 146 | free_block = jvs_memory_free_block::type_id::create(); 147 | free_block.configurate(acc_block.get_s_addr(), acc_block.get_size()); 148 | end 149 | else begin 150 | lower_block_index_in_free_q = this.free_q.find_first_index with (item.get_e_addr() == acc_block.get_s_addr() - 1); 151 | if (!lower_block_index_in_free_q.size()) begin 152 | lower_block_index_in_alloc_q = this.alloc_q.find_first_index with (item.get_e_addr() == acc_block.get_s_addr() - 1); 153 | if (lower_block_index_in_alloc_q.size()) begin 154 | lower_block = this.alloc_q[lower_block_index_in_alloc_q[0]]; 155 | end 156 | end 157 | else begin 158 | lower_block = this.free_q[lower_block_index_in_free_q[0]]; 159 | this.free_q.delete(lower_block_index_in_free_q[0]); 160 | end 161 | 162 | upper_block_index_in_free_q = this.free_q.find_first_index with (item.get_s_addr() == acc_block.get_e_addr() + 1); 163 | if (!upper_block_index_in_free_q.size()) begin 164 | upper_block_index_in_alloc_q = this.alloc_q.find_first_index with (item.get_s_addr() == acc_block.get_e_addr() + 1); 165 | if (upper_block_index_in_alloc_q.size()) begin 166 | upper_block = this.alloc_q[upper_block_index_in_alloc_q[0]]; 167 | end 168 | end 169 | else begin 170 | upper_block = this.free_q[upper_block_index_in_free_q[0]]; 171 | this.free_q.delete(upper_block_index_in_free_q[0]); 172 | end 173 | 174 | if (!lower_block && !upper_block) begin 175 | acc_block.print(); 176 | `uvm_fatal(this.get_name(), "free failed! can't find continuous block lower or upper block!"); 177 | mutex.put(); 178 | return; 179 | end 180 | 181 | free_block = jvs_memory_free_block::type_id::create(); 182 | if (lower_block) begin 183 | jvs_memory_free_block lower_free_block; 184 | if ($cast(lower_free_block, lower_block)) begin 185 | free_block.configurate(lower_block.get_s_addr(), lower_block.get_size() + acc_block.get_size()); 186 | end 187 | else begin 188 | free_block.configurate(lower_block.get_s_addr(), acc_block.get_size()); 189 | end 190 | end 191 | 192 | if (upper_block) begin 193 | jvs_memory_free_block upper_free_block; 194 | if ($cast(upper_free_block, upper_block)) begin 195 | free_block.configurate(free_block.get_s_addr(), free_block.get_size() + upper_block.get_size()); 196 | end 197 | end 198 | end 199 | this.free_q.push_back(free_block); 200 | delete(acc_block); 201 | acc_block = null; 202 | end 203 | mutex.put(); 204 | endtask 205 | 206 | function bit[63:0] va2pa(bit[63:0] va); 207 | if (this.mmu == null) begin 208 | return va; 209 | end 210 | return mmu.va2pa(va, this.attr); 211 | endfunction 212 | 213 | function bit[63:0] pa2va(bit[63:0] pa); 214 | if (this.mmu == null) begin 215 | return pa; 216 | end 217 | return mmu.pa2va(pa, this.attr); 218 | endfunction 219 | 220 | function void write_long(bit[63:0] va, MEM_LONG data); 221 | `uvm_info(this.get_name(), $psprintf("write long begin: 0x%0x @(addr 0x%0x -> 0x%0x)", data, va, this.va2pa(va)), UVM_HIGH); 222 | this.model.write_long(this.va2pa(va), data); 223 | `uvm_info(this.get_name(), $psprintf("write long done: 0x%0x @(addr 0x%0x -> 0x%0x)", data, va, this.va2pa(va)), UVM_HIGH); 224 | endfunction 225 | 226 | function void write_int(bit[63:0] va, MEM_INT data); 227 | `uvm_info(this.get_name(), $psprintf("write int begin: 0x%0x @(addr 0x%0x -> 0x%0x)", data, va, this.va2pa(va)), UVM_HIGH); 228 | this.model.write_int(this.va2pa(va), data); 229 | `uvm_info(this.get_name(), $psprintf("write int done: 0x%0x @(addr 0x%0x -> 0x%0x)", data, va, this.va2pa(va)), UVM_HIGH); 230 | endfunction 231 | 232 | function void write_byte(bit[63:0] va, MEM_BYTE data); 233 | `uvm_info(this.get_name(), $psprintf("write byte begin: 0x%0x @(addr 0x%0x -> 0x%0x)", data, va, this.va2pa(va)), UVM_HIGH); 234 | this.model.write_byte(this.va2pa(va), data); 235 | `uvm_info(this.get_name(), $psprintf("write byte done: 0x%0x @(addr 0x%0x -> 0x%0x)", data, va, this.va2pa(va)), UVM_HIGH); 236 | endfunction 237 | 238 | function MEM_LONG read_long(bit[63:0] va); 239 | MEM_LONG data; 240 | `uvm_info(this.get_name(), $psprintf("read long begin: @(addr 0x%0x -> 0x%0x)", va, this.va2pa(va)), UVM_HIGH); 241 | data = this.model.read_long(this.va2pa(va)); 242 | `uvm_info(this.get_name(), $psprintf("read long done: 0x%0x @(addr 0x%0x -> 0x%0x)", data, va, this.va2pa(va)), UVM_HIGH); 243 | return data; 244 | endfunction 245 | 246 | function MEM_INT read_int(bit[63:0] va); 247 | MEM_INT data; 248 | `uvm_info(this.get_name(), $psprintf("read int begin: @(addr 0x%0x -> 0x%0x)", va, this.va2pa(va)), UVM_HIGH); 249 | data = this.model.read_int(this.va2pa(va)); 250 | `uvm_info(this.get_name(), $psprintf("read int done: 0x%0x @(addr 0x%0x -> 0x%0x)", data, va, this.va2pa(va)), UVM_HIGH); 251 | return data; 252 | endfunction 253 | 254 | function MEM_BYTE read_byte(bit[63:0] va); 255 | MEM_BYTE data; 256 | `uvm_info(this.get_name(), $psprintf("read byte begin: @(addr 0x%0x -> 0x%0x)", va, this.va2pa(va)), UVM_HIGH); 257 | data = this.model.read_byte(this.va2pa(va)); 258 | `uvm_info(this.get_name(), $psprintf("read byte done: 0x%0x @(addr 0x%0x -> 0x%0x)", data, va, this.va2pa(va)), UVM_HIGH); 259 | return data; 260 | endfunction 261 | 262 | function void delete(jvs_memory_acc_block acc_block); 263 | if (acc_block.get_p_allocator != this) begin 264 | acc_block.print(); 265 | `uvm_fatal(this.get_name(), "can not delete block is not allocated for this allocator!"); 266 | end 267 | `uvm_info(this.get_name(), $psprintf("delete begin: @(addr 0x%0x -> 0x%0x) to @(addr 0x%0x -> 0x%0x)", acc_block.get_s_addr(), this.va2pa(acc_block.get_s_addr()), acc_block.get_e_addr(), this.va2pa(acc_block.get_e_addr())), UVM_HIGH); 268 | this.model.delete(this.va2pa(acc_block.get_s_addr()), acc_block.get_size()); 269 | `uvm_info(this.get_name(), $psprintf("delete done: @(addr 0x%0x -> 0x%0x) to @(addr 0x%0x -> 0x%0x)", acc_block.get_s_addr(), this.va2pa(acc_block.get_s_addr()), acc_block.get_e_addr(), this.va2pa(acc_block.get_e_addr())), UVM_HIGH); 270 | 271 | endfunction 272 | 273 | function bit[63:0] memcopy(jvs_memory_acc_block src_acc_block, jvs_memory_acc_block dst_acc_block); 274 | bit[63:0] size; 275 | if (src_acc_block.get_p_allocator != this) begin 276 | src_acc_block.print(); 277 | `uvm_fatal(this.get_name(), "can not copy block is not allocated for this allocator!"); 278 | end 279 | if (dst_acc_block.get_p_allocator != this) begin 280 | dst_acc_block.print(); 281 | `uvm_fatal(this.get_name(), "can not copy block is not allocated for this allocator!"); 282 | end 283 | size = src_acc_block.get_size() < dst_acc_block.get_size() ? src_acc_block.get_size() : dst_acc_block.get_size(); 284 | `uvm_info(this.get_name(), $psprintf("copy size %0d begin: @(addr 0x%0x -> 0x%0x) to @(addr 0x%0x -> 0x%0x)", size, src_acc_block.get_s_addr(), this.va2pa(src_acc_block.get_s_addr()), dst_acc_block.get_s_addr(), this.va2pa(dst_acc_block.get_s_addr())), UVM_HIGH); 285 | for (int i = 0; i < size; i++) begin 286 | this.model.write_byte(this.va2pa(dst_acc_block.get_s_addr()) + i, this.model.read_byte(this.va2pa(src_acc_block.get_s_addr()) + i)); 287 | end 288 | `uvm_info(this.get_name(), $psprintf("copy size %0d done: @(addr 0x%0x -> 0x%0x) to @(addr 0x%0x -> 0x%0x)", size, src_acc_block.get_s_addr(), this.va2pa(src_acc_block.get_s_addr()), dst_acc_block.get_s_addr(), this.va2pa(dst_acc_block.get_s_addr())), UVM_HIGH); 289 | return size; 290 | endfunction 291 | 292 | 293 | endclass 294 | 295 | `endif --------------------------------------------------------------------------------