├── .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
--------------------------------------------------------------------------------