UVM环境介绍
HEAD commitID: 1f968ef
lib/uvm_agents/uvma_obi_memory/src/seq
//
// Copyright 2021 OpenHW Group
// Copyright 2021 Silicon Labs
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the "License"); you may
// not use this file except in compliance with the License, or, at your option,
// the Apache License version 2.0. You may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
`ifndef __UVMA_OBI_MEMORY_VP_DEBUG_CONTROL_SEQ_SV__
`define __UVMA_OBI_MEMORY_VP_DEBUG_CONTROL_SEQ_SV__
/**
* Virtual sequence implementing the cv32e40x virtual peripherals.
* TODO Move most of the functionality to a cv32e env base class.
*/
virtual class uvma_obi_memory_vp_debug_control_seq_c extends uvma_obi_memory_vp_base_seq_c;
`uvm_field_utils_begin(uvma_obi_memory_vp_debug_control_seq_c)
`uvm_field_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_obi_memory_vp_debug_control_seq_c");
/**
* Implement number of peripherals
*/
extern virtual function int unsigned get_num_words();
/**
* Implement sequence that will return a random number
*/
extern virtual task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
/**
* Start delayed debug thread
*/
extern virtual task debug(bit dbg_req_value,
bit request_mode,
bit rand_pulse_duration,
bit rand_start_delay,
int unsigned dbg_pulse_duration,
int unsigned start_delay);
/**
* Must be implemented in dervied class to actually assert interrupt signals
*/
pure virtual task set_debug_req(bit debug_req);
/**
* Must be implemented in dervied class to wait on appropriate clock
*/
pure virtual task wait_n_clocks(int unsigned n);
endclass : uvma_obi_memory_vp_debug_control_seq_c
function uvma_obi_memory_vp_debug_control_seq_c::new(string name="uvma_obi_memory_vp_debug_control_seq_c");
super.new(name);
endfunction : new
function int unsigned uvma_obi_memory_vp_debug_control_seq_c::get_num_words();
return 1;
endfunction : get_num_words
task uvma_obi_memory_vp_debug_control_seq_c::vp_body(uvma_obi_memory_mon_trn_c mon_trn);
uvma_obi_memory_slv_seq_item_c slv_rsp;
`uvm_create (slv_rsp)
slv_rsp.orig_trn = mon_trn;
slv_rsp.err = 1'b0;
if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_WRITE) begin
`uvm_info("VP_VSEQ", $sformatf("Call to virtual peripheral 'vp_debug_control':\n%s", mon_trn.sprint()), UVM_HIGH)
debug(.dbg_req_value (mon_trn.data[31]),
.request_mode (mon_trn.data[30]),
.rand_pulse_duration (mon_trn.data[29]),
.dbg_pulse_duration (mon_trn.data[28:16]),
.rand_start_delay (mon_trn.data[15]),
.start_delay (mon_trn.data[14:0]));
end
else if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_READ) begin
slv_rsp.rdata = 0;
end
add_r_fields(mon_trn, slv_rsp);
slv_rsp.set_sequencer(p_sequencer);
`uvm_send(slv_rsp)
endtask : vp_body
task uvma_obi_memory_vp_debug_control_seq_c::debug(bit dbg_req_value,
bit request_mode,
bit rand_pulse_duration,
bit rand_start_delay,
int unsigned dbg_pulse_duration,
int unsigned start_delay);
// SVTB.29.1.3.1 - Banned random number system functions and methods calls
// Waive-abe because we just do not need the fine tune control of
// constraints in this situation.
//@DVT_LINTER_WAIVER_START "MT20211214_9" disable SVTB.29.1.3.1
fork
begin
if (rand_start_delay) begin
wait_n_clocks($urandom_range(start_delay, 0));
end
else begin
wait_n_clocks(start_delay);
end
if (request_mode) begin
set_debug_req(dbg_req_value);
if (rand_pulse_duration) begin
if (dbg_pulse_duration == 0)
wait_n_clocks($urandom_range(128,1));
else
wait_n_clocks($urandom_range(dbg_pulse_duration, 1));
end
else begin
wait_n_clocks(dbg_pulse_duration);
end
set_debug_req(!dbg_req_value);
end
else begin
set_debug_req(dbg_req_value);
end
end
join_none
//@DVT_LINTER_WAIVER_END "MT20211214_9"
endtask : debug
`endif // __UVMA_OBI_MEMORY_VP_DEBUG_CONTROL_SEQ_SV__
uvma_obi_memory_vp_debug_control_seq.sv
1. 简要介绍
该文件是OBI内存接口调试控制虚拟外设序列类,主要功能包括:
- 提供调试请求控制功能
- 支持延迟调试信号生成
- 实现随机脉冲持续时间
- 作为调试控制虚拟外设的抽象基类
2. 接口介绍
2.1 类定义
virtual class uvma_obi_memory_vp_debug_control_seq_c extends uvma_obi_memory_vp_base_seq_c;
- 代码介绍:定义抽象调试控制虚拟外设类
- 继承关系:继承自虚拟外设基类
- 特点:使用virtual关键字声明为抽象类
3. 参数介绍
3.1 UVM自动化注册
`uvm_field_utils_begin(uvma_obi_memory_vp_debug_control_seq_c)
`uvm_field_utils_end
- 参数说明:空字段注册
- 用途:保持UVM对象标准操作
4. 模块实现介绍
4.1 调试任务
task debug(bit dbg_req_value,
bit request_mode,
bit rand_pulse_duration,
bit rand_start_delay,
int unsigned dbg_pulse_duration,
int unsigned start_delay);
- 代码分析:
- 支持多种调试模式
- 可配置延迟和持续时间
- 使用随机数生成器
- 并行执行调试操作
4.2 纯虚函数
pure virtual task set_debug_req(bit debug_req);
pure virtual task wait_n_clocks(int unsigned n);
- 代码分析:
- 定义必须实现的接口
- 强制子类提供具体实现
- 确保调试功能完整性
5. 总结
该调试控制虚拟外设序列类具有以下特点:
- 灵活的调试信号控制
- 可配置的延迟参数
- 严格的抽象接口定义
- 标准化的UVM实现
作为验证环境的高级组件,它为调试功能提供了统一的控制框架,确保能够方便地实现各类调试场景。
//
// Copyright 2021 OpenHW Group
// Copyright 2021 Silicon Labs
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the "License"); you may
// not use this file except in compliance with the License, or, at your option,
// the Apache License version 2.0. You may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
`ifndef __UVMA_OBI_MEMORY_VP_DIRECTED_SLV_RESP_SEQ_SV__
`define __UVMA_OBI_MEMORY_VP_DIRECTED_SLV_RESP_SEQ_SV__
/**
* Virtual sequence implementing the cv32e40x virtual peripherals.
* TODO Move most of the functionality to a cv32e env base class.
*/
class uvma_obi_memory_vp_directed_slv_resp_seq_c#(OBI_PERIPHS=1) extends uvma_obi_memory_vp_base_seq_c;
localparam ERR_ADDR_MIN_INDEX = 0;
localparam ERR_ADDR_MAX_INDEX = 1;
localparam ERR_VALID_INDEX = 2;
localparam EXOKAY_ADDR_MIN_INDEX = 3;
localparam EXOKAY_ADDR_MAX_INDEX = 4;
localparam EXOKAY_VALID_INDEX = 5;
localparam WORDS_PER_OBI = EXOKAY_VALID_INDEX + 1;
// An array of OBI memory configurations
// This enables a single set of virtual peripheral registers (6*OBI_PERIPHS) to control
// OBI_PERIPHS number of OBIs
// For example, in a typical OBI-I, OBI-D configuration, only the OBI-D is writable
// but we would also need to control the OBI-I as well
uvma_obi_memory_cfg_c obi_cfg[];
`uvm_object_param_utils_begin(uvma_obi_memory_vp_directed_slv_resp_seq_c#(OBI_PERIPHS))
`uvm_object_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_obi_memory_vp_directed_slv_resp_seq_c");
/**
* Implement number of peripherals
*/
extern virtual function int unsigned get_num_words();
/**
* Implement sequence that will return a random number
*/
extern virtual task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
endclass : uvma_obi_memory_vp_directed_slv_resp_seq_c
function uvma_obi_memory_vp_directed_slv_resp_seq_c::new(string name="uvma_obi_memory_vp_directed_slv_resp_seq_c");
super.new(name);
obi_cfg = new[OBI_PERIPHS];
endfunction : new
function int unsigned uvma_obi_memory_vp_directed_slv_resp_seq_c::get_num_words();
return WORDS_PER_OBI * OBI_PERIPHS;
endfunction : get_num_words
task uvma_obi_memory_vp_directed_slv_resp_seq_c::vp_body(uvma_obi_memory_mon_trn_c mon_trn);
int unsigned obi_index;
uvma_obi_memory_slv_seq_item_c slv_rsp;
`uvm_create(slv_rsp)
slv_rsp.orig_trn = mon_trn;
slv_rsp.err = 1'b0;
obi_index = get_vp_index(mon_trn) / WORDS_PER_OBI;
case (get_vp_index(mon_trn) % WORDS_PER_OBI)
ERR_ADDR_MIN_INDEX: obi_cfg[obi_index].directed_slv_err_addr_min = slv_rsp.orig_trn.data;
ERR_ADDR_MAX_INDEX: obi_cfg[obi_index].directed_slv_err_addr_max = slv_rsp.orig_trn.data;
ERR_VALID_INDEX: obi_cfg[obi_index].directed_slv_err_valid = slv_rsp.orig_trn.data[0];
EXOKAY_ADDR_MIN_INDEX: obi_cfg[obi_index].directed_slv_exokay_addr_min = slv_rsp.orig_trn.data;
EXOKAY_ADDR_MAX_INDEX: obi_cfg[obi_index].directed_slv_exokay_addr_max = slv_rsp.orig_trn.data;
EXOKAY_VALID_INDEX: obi_cfg[obi_index].directed_slv_exokay_valid = slv_rsp.orig_trn.data[0];
endcase
add_r_fields(mon_trn, slv_rsp);
slv_rsp.set_sequencer(p_sequencer);
`uvm_send(slv_rsp)
endtask : vp_body
`endif // __UVMA_OBI_MEMORY_VP_DIRECTED_SLV_RESP_SEQ_SV__
uvma_obi_memory_vp_directed_slv_resp_seq.sv
1. 简要介绍
该文件实现了一个定向从设备响应虚拟外设序列,主要功能包括:
- 提供错误和exokay响应控制
- 支持多OBI外设配置
- 实现地址范围检查
- 作为虚拟外设的具体实现
2. 接口介绍
2.1 类定义
class uvma_obi_memory_vp_directed_slv_resp_seq_c#(OBI_PERIPHS=1) extends uvma_obi_memory_vp_base_seq_c;
- 代码介绍:定义参数化定向响应虚拟外设类
- 模板参数:OBI_PERIPHS控制外设数量
- 继承关系:继承自虚拟外设基类
3. 参数介绍
3.1 本地参数
localparam ERR_ADDR_MIN_INDEX = 0;
localparam EXOKAY_VALID_INDEX = 5;
localparam WORDS_PER_OBI = EXOKAY_VALID_INDEX + 1;
- 参数说明:
- 定义寄存器索引范围
- 每个OBI外设占用6个字
- 用于地址映射计算
3.2 配置数组
uvma_obi_memory_cfg_c obi_cfg[];
- 参数说明:存储多个OBI配置
- 初始化:在构造函数中根据OBI_PERIPHS动态分配
4. 模块实现介绍
4.1 主体任务
task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
obi_index = get_vp_index(mon_trn) / WORDS_PER_OBI;
case (get_vp_index(mon_trn) % WORDS_PER_OBI)
ERR_ADDR_MIN_INDEX: obi_cfg[obi_index].directed_slv_err_addr_min = slv_rsp.orig_trn.data;
endcase
- 代码分析:
- 计算OBI外设索引
- 根据寄存器索引配置参数
- 支持错误地址范围和exokay响应配置
4.2 寄存器数量
function int unsigned get_num_words();
return WORDS_PER_OBI * OBI_PERIPHS;
endfunction
- 代码分析:
- 动态计算寄存器总数
- 基于模板参数扩展
5. 总结
该定向从设备响应序列具有以下特点:
- 灵活的多外设支持
- 精确的响应控制
- 可配置的错误注入
- 标准化的虚拟外设接口
作为验证环境的高级组件,它为复杂的OBI从设备响应场景提供了统一的控制框架。
//
// Copyright 2021 OpenHW Group
// Copyright 2021 Silicon Labs
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the "License"); you may
// not use this file except in compliance with the License, or, at your option,
// the Apache License version 2.0. You may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
`ifndef __UVMA_OBI_MEMORY_VP_INTERRUPT_TIMER_SEQ_SV__
`define __UVMA_OBI_MEMORY_VP_INTERRUPT_TIMER_SEQ_SV__
/**
* Virtual sequence implementing the cv32e40x virtual peripherals.
* TODO Move most of the functionality to a cv32e env base class.
*/
virtual class uvma_obi_memory_vp_interrupt_timer_seq_c extends uvma_obi_memory_vp_base_seq_c;
bit[31:0] interrupt_value;
int unsigned interrupt_timer_value;
event interrupt_timer_start;
`uvm_field_utils_begin(uvma_obi_memory_vp_interrupt_timer_seq_c)
`uvm_field_int(interrupt_value, UVM_DEFAULT)
`uvm_field_int(interrupt_timer_value, UVM_DEFAULT)
`uvm_field_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_obi_memory_vp_interrupt_timer_seq_c");
/**
* Body will start cycle counting thread before starting parent
*/
extern virtual task body();
/**
* Implement number of peripherals
*/
extern virtual function int unsigned get_num_words();
/**
* Implement sequence that will return a random number
*/
extern virtual task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
/**
* Implements the interrupt_timer thread
*/
extern virtual task interrupt_timer();
/**
* Must be implemented in dervied class to actually assert interrupt signals
*/
pure virtual task set_interrupt();
endclass : uvma_obi_memory_vp_interrupt_timer_seq_c
function uvma_obi_memory_vp_interrupt_timer_seq_c::new(string name="uvma_obi_memory_vp_interrupt_timer_seq_c");
super.new(name);
endfunction : new
task uvma_obi_memory_vp_interrupt_timer_seq_c::body();
fork
interrupt_timer();
join_none
super.body();
endtask : body
function int unsigned uvma_obi_memory_vp_interrupt_timer_seq_c::get_num_words();
return 2;
endfunction : get_num_words
task uvma_obi_memory_vp_interrupt_timer_seq_c::vp_body(uvma_obi_memory_mon_trn_c mon_trn);
uvma_obi_memory_slv_seq_item_c slv_rsp;
`uvm_create(slv_rsp)
slv_rsp.orig_trn = mon_trn;
slv_rsp.err = 1'b0;
if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_WRITE) begin
`uvm_info("VP_VSEQ", $sformatf("Call to virtual peripheral 'interrupt_timer_control':\n%s", mon_trn.sprint()), UVM_HIGH)
if (get_vp_index(mon_trn) == 0) begin
interrupt_value = mon_trn.data;
end
else if (get_vp_index(mon_trn) == 1) begin
interrupt_timer_value = mon_trn.data;
->interrupt_timer_start;
end
else begin
`uvm_info("VP_VSEQ", $sformatf("Call to virtual peripheral 'interrupt_timer_control':\n%s", mon_trn.sprint()), UVM_HIGH)
end
end
else if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_READ) begin
slv_rsp.rdata = 0;
end
add_r_fields(mon_trn, slv_rsp);
slv_rsp.set_sequencer(p_sequencer);
`uvm_send(slv_rsp)
endtask : vp_body
task uvma_obi_memory_vp_interrupt_timer_seq_c::interrupt_timer();
while(1) begin
@interrupt_timer_start;
`uvm_info("VP_VSEQ", "@interrupt_timer_start", UVM_HIGH)
while (interrupt_timer_value > 0) begin
@(cntxt.vif.mon_cb);
interrupt_timer_value = interrupt_timer_value - 1;
end
`uvm_info("VP_VSEQ", $sformatf("Done waiting for interrupt_timer_value to be 0, setting interrupts to 0x%08x", interrupt_value), UVM_HIGH)
set_interrupt();
end
endtask : interrupt_timer
`endif // __UVMA_OBI_MEMORY_VP_INTERRUPT_TIMER_SEQ_SV__
uvma_obi_memory_vp_interrupt_timer_seq.sv
1. 简要介绍
该文件实现了一个中断定时器虚拟外设序列,主要功能包括:
- 提供可配置的中断触发机制
- 支持定时器计数功能
- 实现中断值存储
- 作为虚拟外设的抽象基类
2. 接口介绍
2.1 类定义
virtual class uvma_obi_memory_vp_interrupt_timer_seq_c extends uvma_obi_memory_vp_base_seq_c;
- 代码介绍:定义抽象中断定时器虚拟外设类
- 继承关系:继承自虚拟外设基类
- 特点:使用virtual关键字声明为抽象类
3. 参数介绍
3.1 中断值参数
bit[31:0] interrupt_value;
- 参数说明:32位中断值
- 用途:存储要触发的中断值
3.2 定时器参数
int unsigned interrupt_timer_value;
- 参数说明:无符号定时器值
- 用途:控制中断触发时间
4. 模块实现介绍
4.1 主体任务
task body();
fork
interrupt_timer();
join_none
super.body();
endtask
- 代码分析:
- 启动中断定时器线程
- 并行执行父类body任务
- 使用fork-join_none实现非阻塞
4.2 中断定时器
task interrupt_timer();
while(1) begin
@interrupt_timer_start;
while (interrupt_timer_value > 0) begin
@(cntxt.vif.mon_cb);
interrupt_timer_value--;
end
set_interrupt();
end
endtask
- 代码分析:
- 无限循环等待启动事件
- 每个时钟周期递减定时器
- 定时器归零后触发中断
- 使用事件驱动机制
5. 总结
该中断定时器虚拟外设序列具有以下特点:
- 精确的定时中断控制
- 灵活的中断值配置
- 标准化的虚拟外设接口
- 可扩展的设计架构
作为验证环境的高级组件,它为中断测试场景提供了可靠的定时触发机制,确保能够准确验证各类中断处理逻辑。
//
// Copyright 2021 OpenHW Group
// Copyright 2021 Silicon Labs
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the "License"); you may
// not use this file except in compliance with the License, or, at your option,
// the Apache License version 2.0. You may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
`ifndef __UVMA_OBI_MEMORY_VP_RAND_NUM_SEQ_SV__
`define __UVMA_OBI_MEMORY_VP_RAND_NUM_SEQ_SV__
/**
* Virtual sequence implementing the cv32e40x virtual peripherals.
* TODO Move most of the functionality to a cv32e env base class.
*/
class uvma_obi_memory_vp_rand_num_seq_c extends uvma_obi_memory_vp_base_seq_c;
rand uvma_obi_memory_data_b_t rdata;
`uvm_object_utils_begin(uvma_obi_memory_vp_rand_num_seq_c)
`uvm_object_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_obi_memory_vp_rand_num_seq_c");
/**
* Implement number of peripherals
*/
extern virtual function int unsigned get_num_words();
/**
* Implement sequence that will return a random number
*/
extern virtual task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
endclass : uvma_obi_memory_vp_rand_num_seq_c
function uvma_obi_memory_vp_rand_num_seq_c::new(string name="uvma_obi_memory_vp_rand_num_seq_c");
super.new(name);
endfunction : new
function int unsigned uvma_obi_memory_vp_rand_num_seq_c::get_num_words();
return 1;
endfunction : get_num_words
task uvma_obi_memory_vp_rand_num_seq_c::vp_body(uvma_obi_memory_mon_trn_c mon_trn);
uvma_obi_memory_slv_seq_item_c slv_rsp;
`uvm_create(slv_rsp)
slv_rsp.orig_trn = mon_trn;
if (!this.randomize()) begin
`uvm_fatal("VPRNDSEQ", "Failed to randomize")
end
else begin
slv_rsp.rdata = this.rdata;
end
slv_rsp.err = 1'b0;
`uvm_info("VPRNDSEQ", $sformatf("Issuing a random number: 0x%08x", slv_rsp.rdata), UVM_HIGH);
add_r_fields(mon_trn, slv_rsp);
`uvm_send(slv_rsp)
endtask : vp_body
`endif // __UVMA_OBI_MEMORY_VP_RAND_NUM_SEQ_SV__
uvma_obi_memory_vp_rand_num_seq.sv
1. 简要介绍
该文件实现了一个随机数生成虚拟外设序列,主要功能包括:
- 提供随机数生成功能
- 响应主设备读取请求
- 作为虚拟外设的具体实现
- 集成到OBI内存验证环境中
2. 接口介绍
2.1 类定义
class uvma_obi_memory_vp_rand_num_seq_c extends uvma_obi_memory_vp_base_seq_c;
- 代码介绍:定义随机数生成虚拟外设类
- 继承关系:继承自虚拟外设基类
- 特点:实现具体随机数生成功能
3. 参数介绍
3.1 随机数参数
rand uvma_obi_memory_data_b_t rdata;
- 参数说明:32位随机数
- 特点:使用rand关键字声明为随机变量
- 用途:存储生成的随机数值
4. 模块实现介绍
4.1 UVM自动化注册
`uvm_object_utils_begin(uvma_obi_memory_vp_rand_num_seq_c)
`uvm_object_utils_end
- 代码分析:
- 标准UVM对象注册
- 无额外字段需要注册
- 保持UVM框架兼容性
4.2 主体任务
task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
if (!this.randomize()) begin
`uvm_fatal("VPRNDSEQ", "Failed to randomize")
end
else begin
slv_rsp.rdata = this.rdata;
end
endtask
- 代码分析:
- 调用randomize()生成随机数
- 错误处理机制
- 将随机数赋值给响应对象
- 使用UVM宏记录日志
5. 总结
该随机数生成虚拟外设序列具有以下特点:
- 简单的随机数生成功能
- 标准化的UVM实现
- 可靠的错误处理机制
- 清晰的日志记录
作为验证环境的辅助组件,它为测试场景提供了可预测的随机数据源,确保能够验证各类数据处理逻辑。
//
// Copyright 2021 OpenHW Group
// Copyright 2021 Silicon Labs
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the "License"); you may
// not use this file except in compliance with the License, or, at your option,
// the Apache License version 2.0. You may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
`ifndef __UVMA_OBI_MEMORY_VP_SIG_WRITER_SEQ_SV__
`define __UVMA_OBI_MEMORY_VP_SIG_WRITER_SEQ_SV__
/**
* Virtual sequence implementing the cv32e40x virtual peripherals.
* TODO Move most of the functionality to a cv32e env base class.
*/
virtual class uvma_obi_memory_vp_sig_writer_seq_c extends uvma_obi_memory_vp_base_seq_c;
localparam NUM_WORDS = 3;
bit[31:0] signature_start_address;
bit[31:0] signature_end_address;
string sig_file = "";
int sig_fd = 0;
bit use_sig_file = 0;
`uvm_field_utils_begin(uvma_obi_memory_vp_sig_writer_seq_c)
`uvm_field_int(signature_start_address, UVM_DEFAULT)
`uvm_field_int(signature_end_address, UVM_DEFAULT)
`uvm_field_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_obi_memory_vp_sig_writer_seq_c");
/**
* Implement number of peripherals
*/
extern virtual function int unsigned get_num_words();
/**
* Implement sequence that will return a random number
*/
extern virtual task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
/**
* Set virtual exit in core
*/
pure virtual task set_exit_valid();
endclass : uvma_obi_memory_vp_sig_writer_seq_c
function uvma_obi_memory_vp_sig_writer_seq_c::new(string name="uvma_obi_memory_vp_sig_writer_seq_c");
super.new(name);
if ($value$plusargs("signature=%s", sig_file)) begin
sig_fd = $fopen(sig_file, "w");
if (sig_fd == 0) begin
`uvm_error("VP_VSEQ", $sformatf("Could not open file %s for writing", sig_file));
use_sig_file = 0;
end
else begin
use_sig_file = 1;
end
end
endfunction : new
function int unsigned uvma_obi_memory_vp_sig_writer_seq_c::get_num_words();
return NUM_WORDS;
endfunction : get_num_words
task uvma_obi_memory_vp_sig_writer_seq_c::vp_body(uvma_obi_memory_mon_trn_c mon_trn);
uvma_obi_memory_slv_seq_item_c slv_rsp;
`uvm_create (slv_rsp)
slv_rsp.orig_trn = mon_trn;
slv_rsp.err = 1'b0;
if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_WRITE) begin
case (get_vp_index(mon_trn))
0: signature_start_address = mon_trn.data;
1: signature_end_address = mon_trn.data;
2: begin
for (int unsigned ii=signature_start_address; ii<signature_end_address; ii += 4) begin
`uvm_info("VP_SIG_WRITER", "Dumping signature", UVM_HIGH)
if (use_sig_file) begin
$fdisplay(sig_fd, "%x%x%x%x", cntxt.mem.read(ii+3),
cntxt.mem.read(ii+2),
cntxt.mem.read(ii+1),
cntxt.mem.read(ii+0));
end
else begin
`uvm_info("VP_VSEQ", $sformatf("%x%x%x%x", cntxt.mem.read(ii+3),
cntxt.mem.read(ii+2),
cntxt.mem.read(ii+1),
cntxt.mem.read(ii+0)), UVM_HIGH)
end
end
set_exit_valid();
end
endcase
end
else if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_READ) begin
slv_rsp.rdata = 0;
end
add_r_fields(mon_trn, slv_rsp);
slv_rsp.set_sequencer(p_sequencer);
`uvm_send(slv_rsp)
endtask : vp_body
`endif // __UVMA_OBI_MEMORY_VP_SIG_WRITER_SEQ_SV__
uvma_obi_memory_vp_sig_writer_seq.sv
1. 简要介绍
该文件实现了一个签名文件写入虚拟外设序列,主要功能包括:
- 提供签名文件生成功能
- 支持内存区域转储
- 实现签名地址范围配置
- 作为虚拟外设的抽象基类
2. 接口介绍
2.1 类定义
virtual class uvma_obi_memory_vp_sig_writer_seq_c extends uvma_obi_memory_vp_base_seq_c;
- 代码介绍:定义抽象签名写入虚拟外设类
- 继承关系:继承自虚拟外设基类
- 特点:使用virtual关键字声明为抽象类
3. 参数介绍
3.1 签名地址参数
bit[31:0] signature_start_address;
bit[31:0] signature_end_address;
- 参数说明:32位起始和结束地址
- 用途:定义签名转储的内存范围
3.2 文件参数
string sig_file = "";
int sig_fd = 0;
bit use_sig_file = 0;
- 参数说明:
- sig_file:签名文件路径
- sig_fd:文件描述符
- use_sig_file:文件使用标志
4. 模块实现介绍
4.1 构造函数
function new(string name="uvma_obi_memory_vp_sig_writer_seq_c");
if ($value$plusargs("signature=%s", sig_file)) begin
sig_fd = $fopen(sig_file, "w");
end
endfunction
- 代码分析:
- 通过plusargs获取签名文件路径
- 尝试打开文件写入
- 设置文件使用标志
4.2 主体任务
task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
for (int unsigned ii=signature_start_address; ii<signature_end_address; ii += 4) begin
$fdisplay(sig_fd, "%x%x%x%x", cntxt.mem.read(ii+3),
cntxt.mem.read(ii+2),
cntxt.mem.read(ii+1),
cntxt.mem.read(ii+0));
end
endtask
- 代码分析:
- 遍历指定内存范围
- 以小端格式写入文件
- 每4字节为一行输出
5. 总结
该签名文件写入虚拟外设序列具有以下特点:
- 灵活的内存转储功能
- 可配置的地址范围
- 标准化的文件输出格式
- 可扩展的设计架构
作为验证环境的高级组件,它为测试结果验证提供了可靠的签名生成机制,确保能够准确验证内存内容。
//
// Copyright 2021 OpenHW Group
// Copyright 2021 Silicon Labs
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the "License"); you may
// not use this file except in compliance with the License, or, at your option,
// the Apache License version 2.0. You may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
`ifndef __UVMA_OBI_MEMORY_VP_VIRTUAL_PRINTER_SEQ_SV__
`define __UVMA_OBI_MEMORY_VP_VIRTUAL_PRINTER_SEQ_SV__
/**
* Virtual sequence implementing the cv32e40x virtual peripherals.
* TODO Move most of the functionality to a cv32e env base class.
*/
class uvma_obi_memory_vp_virtual_printer_seq_c extends uvma_obi_memory_vp_base_seq_c;
localparam NUM_WORDS = 11;
`uvm_object_utils_begin(uvma_obi_memory_vp_virtual_printer_seq_c)
`uvm_object_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_obi_memory_vp_virtual_printer_seq_c");
/**
* Implement number of peripherals
*/
extern virtual function int unsigned get_num_words();
/**
* Implement sequence that will return a random number
*/
extern virtual task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
endclass : uvma_obi_memory_vp_virtual_printer_seq_c
function uvma_obi_memory_vp_virtual_printer_seq_c::new(string name="uvma_obi_memory_vp_virtual_printer_seq_c");
super.new(name);
endfunction : new
function int unsigned uvma_obi_memory_vp_virtual_printer_seq_c::get_num_words();
return NUM_WORDS;
endfunction : get_num_words
task uvma_obi_memory_vp_virtual_printer_seq_c::vp_body(uvma_obi_memory_mon_trn_c mon_trn);
uvma_obi_memory_slv_seq_item_c slv_rsp;
`uvm_create(slv_rsp)
slv_rsp.orig_trn = mon_trn;
if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_WRITE) begin
`uvm_info("VP_VSEQ", $sformatf("Call to virtual peripheral 'virtual_printer':\n%s", mon_trn.sprint()), UVM_DEBUG)
// Allow $write as this acts as a UART/serial printer
//@DVT_LINTER_WAIVER_START "SR20211012" disable SVTB.29.1.7
$write("%c", mon_trn.data[7:0]);
//@DVT_LINTER_WAIVER_END "SR20211012"
end
else if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_READ) begin
// If reading from virtual printer, simply return 0
slv_rsp.rdata =0;
end
add_r_fields(mon_trn, slv_rsp);
`uvm_send(slv_rsp)
endtask : vp_body
`endif // __UVMA_OBI_MEMORY_VP_VIRTUAL_PRINTER_SEQ_SV__
uvma_obi_memory_vp_virtual_printer_seq.sv
1. 简要介绍
该文件实现了一个虚拟打印机外设序列,主要功能包括:
- 模拟UART/串行打印机行为
- 响应主设备写入请求
- 支持字符输出功能
- 作为虚拟外设的具体实现
2. 接口介绍
2.1 类定义
class uvma_obi_memory_vp_virtual_printer_seq_c extends uvma_obi_memory_vp_base_seq_c;
- 代码介绍:定义虚拟打印机外设类
- 继承关系:继承自虚拟外设基类
- 特点:实现具体打印功能
3. 参数介绍
3.1 本地参数
localparam NUM_WORDS = 11;
- 参数说明:定义寄存器数量
- 用途:控制虚拟外设地址空间
4. 模块实现介绍
4.1 UVM自动化注册
`uvm_object_utils_begin(uvma_obi_memory_vp_virtual_printer_seq_c)
`uvm_object_utils_end
- 代码分析:
- 标准UVM对象注册
- 无额外字段需要注册
- 保持UVM框架兼容性
4.2 主体任务
task vp_body(uvma_obi_memory_mon_trn_c mon_trn);
if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_WRITE) begin
$write("%c", mon_trn.data[7:0]);
end
endtask
- 代码分析:
- 处理写入请求
- 提取低8位作为ASCII字符
- 使用$write系统任务输出
- 包含DVT Linter豁免注释
5. 总结
该虚拟打印机外设序列具有以下特点:
- 简单的字符输出功能
- 标准化的UVM实现
- 完善的日志记录
- 清晰的代码结构
作为验证环境的辅助组件,它为调试信息输出提供了可靠的打印功能,确保能够方便地查看测试过程中的关键信息。