Skip to content

Commit

Permalink
[uvmgen] add env config
Browse files Browse the repository at this point in the history
  • Loading branch information
Dragon-Git committed Dec 23, 2023
1 parent 510693d commit 258289d
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
---
## Introduction

uvmgen is a command-line interface (CLI) program for generating testbench structures based on a provided JSON configuration file. This user guide provides detailed information on how to use uvmgen effectively.
uvmgen is a command-line interface (CLI) program for generating testbench structures based on a provided JSON configuration file.

## Installing
<details>
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "uvmgen"
version = "0.1.0"
version = "0.2.0"
description = "A toolkit of uvm tb generate."
authors = [
{ name="Dragon-Git", email="[email protected]" },
Expand Down
14 changes: 11 additions & 3 deletions src/uvmgen/templates/env_pkg/env.mako.sv
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
`define ${env_name.upper()}_SV
typedef class ${scb_name};
typedef class ${vsqr_name};
typedef class ${env_name}_cfg;
// typedef class {reg_name};
class ${env_name} extends uvm_env;
${env_name}_cfg cfg;
${scb_name} scb;
% if has_regmodel:
${ral_block_name} regmodel;
Expand All @@ -13,7 +15,6 @@ class ${env_name} extends uvm_env;
// Declear agent
% for child_name, child_type in env_childs.items():
${child_type} ${child_name};
${child_type[:-3]}cfg ${child_name[:-3]}cfg;
% endfor

`uvm_component_utils(${env_name})
Expand All @@ -36,16 +37,23 @@ endfunction:new

function void ${env_name}::build_phase(uvm_phase phase);
super.build();
// get dv_base_env_cfg object from uvm_config_db
if (!uvm_config_db#(${env_name}_cfg)::get(this, "", "cfg", cfg)) begin
`uvm_fatal(get_full_name(), $sformatf("failed to get %s from uvm_config_db", cfg.get_type_name()))
end

% for child_name, child_type in env_childs.items():
${child_name} = ${child_type}::type_id::create("${child_name}",this);
${child_name[:-3]}cfg = ${child_type[:-3]}cfg::type_id::create("${child_name[:-3]}cfg",this);
uvm_config_db#(${child_type[:-3]}cfg)::set(this, "${child_name}", "cfg", ${child_name[:-3]}cfg);
uvm_config_db#(${child_type[:-3]}cfg)::set(this, "${child_name}", "cfg", cfg.${child_name[:-3]}cfg);

% endfor
vsqr = ${vsqr_name}::type_id::create("vsqr",this);
//ToDo: Instantiate other components,callbacks and TLM ports if added by user

// create components
scb = ${scb_name}::type_id::create("scb",this);
scb.cfg = cfg;

% if has_regmodel:
regmodel = ${ral_block_name}::type_id::create("regmodel",this);
regmodel.build();
Expand Down
135 changes: 135 additions & 0 deletions src/uvmgen/templates/env_pkg/env_cfg.mako.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
`ifndef ${env_name.upper()}_CFG__SV
`define ${env_name.upper()}_CFG__SV

class ${env_name}_cfg extends uvm_object;

bit is_active = 1;
bit en_scb = 1; // can be changed at run-time
bit en_cov = 0; // Enable via plusarg, only if coverage collection is turned on.
bit under_reset = 0;
bit is_initialized; // Indicates that the initialize() method has been called.
// The scope and runtime of a existing test can be reduced by setting this variable. This is
// useful to keep the runtime down especially in time-sensitive runs such as CI, which is meant
// to check the code health and not find design bugs. It is set via plusarg and retrieved in
// `dv_base_test`.
bit smoke_test = 0;

// bit to configure all uvcs with zero delays to create high bw test
rand bit zero_delays;
% for child_name, child_type in env_childs.items():
${child_type[:-3]}cfg ${child_name[:-3]}cfg;
% endfor

// set zero_delays 40% of the time
constraint zero_delays_c {
zero_delays dist {1'b0 := 6, 1'b1 := 4};
}
// reg model & q of valid csr addresses
${ral_block_name} ral;
${ral_block_name} ral_models[string];

// A queue of the names of RAL models that should be created in the `initialize` function
// Related agents, adapters will be created in env as well as connecting them with scb
// For example, if the IP has an additional RAL model named `ral1`, add it into the list as below
// virtual function void initialize(bit [TL_AW-1:0] csr_base_addr = '1);
// ral_model_names.push_back("ral1");
// super.initialize(csr_base_addr);
string ral_model_names[$] = {${ral_block_name}::type_name};

`uvm_object_param_utils_begin(${env_name}_cfg)
`uvm_field_int (is_active, UVM_DEFAULT)
`uvm_field_int (en_scb, UVM_DEFAULT)
`uvm_field_int (en_cov, UVM_DEFAULT)
`uvm_field_int (zero_delays, UVM_DEFAULT)
`uvm_object_utils_end

function new(string name = "");
super.new(name);
endfunction: new

virtual function void initialize(bit [31:0] csr_base_addr = '1);
is_initialized = 1'b1;

% for child_name, child_type in env_childs.items():
${child_name[:-3]}cfg = ${child_type[:-3]}cfg::type_id::create("${child_name[:-3]}cfg");
% endfor
// build the ral model
create_ral_models(csr_base_addr);

endfunction

// Set pre-build RAL knobs.
//
// This method enables setting pre-build config knobs that can be used to control how the RAL
// sub-structures are created.
protected virtual function void pre_build_ral_settings(${ral_block_name} ral);
endfunction

// Perform post-build, pre-lock modifications to the RAL.
//
// For some registers / fields, the correct access policies or reset values may not be set. Fixes
// like those can be made with this method.
protected virtual function void post_build_ral_settings(${ral_block_name} ral);
endfunction

// Creates RAL models and sets their base address based on the supplied arg.
//
// csr_base_addr is the base address to set to the RAL models. If it is all 1s, then we treat that
// as an indication to randomize the base address internally instead.
virtual function void create_ral_models(bit [31:0] csr_base_addr = '1);

foreach (ral_model_names[i]) begin
string ral_name = ral_model_names[i];
bit randomize_base_addr = &csr_base_addr;
${ral_block_name} reg_blk = create_ral_by_name(ral_name);

if (reg_blk.get_name() == ${ral_block_name}::type_name) $cast(ral, reg_blk);

// Build the register block with an arbitrary base address (we choose 0). We'll change it
// later.
pre_build_ral_settings(reg_blk);
reg_blk.build();
// reg_blk.addr_width = bus_params_pkg::BUS_AW;
// reg_blk.data_width = bus_params_pkg::BUS_DW;
// reg_blk.be_width = bus_params_pkg::BUS_DBW;
post_build_ral_settings(reg_blk);
reg_blk.lock_model();

// Now the model is locked, we know its layout. Set the base address for the register block.
// reg_blk.set_base_addr(.base_addr(`UVM_REG_ADDR_WIDTH'(csr_base_addr)),
// .randomize_base_addr(randomize_base_addr));

// // Get list of valid csr addresses (useful in seq to randomize addr as well as in scb checks)
// reg_blk.compute_mapped_addr_ranges();
// reg_blk.compute_unmapped_addr_ranges();
ral_models[ral_name] = reg_blk;
end

if (ral_model_names.size > 0) begin
if (!ral_models.exists(${ral_block_name}::type_name))
`uvm_fatal(get_full_name(), "RAL ERROR")
end
endfunction

virtual function ${ral_block_name} create_ral_by_name(string name);
uvm_object obj;
uvm_factory factory;
${ral_block_name} ral;

factory = uvm_factory::get();
obj = factory.create_object_by_name(.requested_type_name(name), .name(name));
if (obj == null) begin
// print factory overrides to help debug
factory.print();
`uvm_fatal(get_type_name(), $sformatf("could not create %0s as a RAL model, see above for a list of \
type/instance overrides", name))
end
if (!$cast(ral, obj)) begin
`uvm_fatal(get_type_name(), $sformatf("cast failed - %0s is not a ${ral_block_name}", name))
end
return ral;
endfunction:create_ral_by_name

endclass: ${env_name}_cfg

`endif // ${env_name.upper()}_CFG__SV
1 change: 1 addition & 0 deletions src/uvmgen/templates/env_pkg/scb.mako.sv
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

class ${scb_name} extends uvm_scoreboard;

${env_name}_cfg cfg;
% if diff_act:
uvm_analysis_imp_ingress #(${mst_action},${scb_name}) before_export;
uvm_analysis_imp_egress #(${slv_action},${scb_name}) after_export;
Expand Down
18 changes: 18 additions & 0 deletions src/uvmgen/templates/test_pkg/base_test.mako.sv
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ class ${test_name} extends uvm_test;

`uvm_component_utils(${test_name})

${env_name}_cfg cfg;
${env_name} env;
bit print_topology = 1'b0;

function new(string name, uvm_component parent);
super.new(name, parent);
Expand All @@ -16,12 +18,28 @@ class ${test_name} extends uvm_test;
uvm_factory factory;
super.build_phase(phase);
env = ${env_name}::type_id::create("env", this);
cfg = ${env_name}_cfg::type_id::create("cfg", this);
cfg.initialize();
uvm_config_db#(${env_name}_cfg)::set(this, "env", "cfg", cfg);

% if seq_start_method != "start_task": ## seq_start_method == "default_seq"
factory = uvm_factory::get();
void'($value$plusargs("UVM_TEST_SEQ=%0s", seq_name));
uvm_config_db #(uvm_object_wrapper)::set(this, "env.vsqr.main_phase", "default_sequence", factory.find_wrapper_by_name(seq_name));
% endif
// Enable scoreboard (and sub-scoreboard checks) via plusarg.
void'($value$plusargs("en_scb=%0b", cfg.en_scb));
// Enable fastest design performance by configuring zero delays in all agents.
void'($value$plusargs("zero_delays=%0b", cfg.zero_delays));
// Enable coverage collection.
void'($value$plusargs("en_cov=%0b", cfg.en_cov));

// Enable reduced runtime test.
void'($value$plusargs("smoke_test=%0b", cfg.smoke_test));

// Enable print_topology
void'($value$plusargs("print_topology=%0b", print_topology));
uvm_top.enable_print_topology = print_topology;
endfunction

% if seq_start_method == "start_task":
Expand Down

0 comments on commit 258289d

Please sign in to comment.