Professional Documents
Culture Documents
Tom Fitzpatrick
Verification Evangelist DVT
October 2011
A Guiding Methodology
Provides Freedom From Choice Avoids Chaos and Repetition Ease of Use APIs Not just for Super-heroes!
2011 Mentor Graphics Corp. Company Confidential
www.mentor.com
UVM Foundations
Objective
Justification
Separation of stimulus generation from delivery Raise the abstraction level of stimulus and checking Test bench configuration Interoperability Reuse
Standard class library & API
Several people can develop stimulus Increase productivity Avoid expensive recompilation Important for intra and inter company development Key to productivity
www.mentor.com
DUT
SPI I/F
IRQ For the Design: What does it do? What are the use cases? Which test cases are required? What type of stimulus scenarios are required? What represents correct behavior? What kind of functional coverage do I need?
4 TF - UVM Recipe of the Month 10/11 www.mentor.com
UVC(agent)
Configuration Object Sequencer Monitor One per interface
seq_item
Driver
DUT
Stimulus
www.mentor.com
UVC(agent)
Configuration Object Sequencer Monitor
Driver
DUT
www.mentor.com
Registers contain bits & fields Register Map contains Registers Register Block contains Maps One Map per physical interface Blocks are hierarchical
31:14
Reserved
13
ASS
12
IE
11
10
7 R
6:0
Char_Len
R/W
www.mentor.com
SQR
SQR
Sequencer
Driver
DUT
www.mentor.com
Stimulus Generation
Stimulus reuse
Abstraction of stimulus:
i.e. Set this bit in this register rather than write x to address y If the bus agent changes, the stimulus still works Front door is via an agent Back door is directly to the hardware via the simulator database
Configuration
Register model reflects hardware programmable registers Set up desired configuration in register model then dump to DUT
Randomization with configuration constraints
Analysis Mirror
Current state of the register model matches the DUT hardware Useful for scoreboards and functional coverage monitors
2011 Mentor Graphics Corp. Company Confidential
10
www.mentor.com
virtual function void build(); ratio = uvm_reg_field::type_id::create("ratio"); ratio.configure(this, 16, 0, "RW", 0, 16'hffff, 1, 1, 1); endfunction endclass
#bits
Coverage
function new(string name = "spi_reg_block"); super.new(name, build_coverage(UVM_CVR_ADDR_MAP)); endfunction virtual function void build(); divider_reg = divider::type_id::create("divider"); divider_reg.build(); divider_reg.configure(this, null, ""); divider_reg.add_hdl_path_slice("divider", 0, 16); APB_map = create_map("APB_map", 'h800, 4, UVM_LITTLE_ENDIAN); APB_map.add_reg(divider_reg, 32'h00000014, "RW"); add_hdl_path("DUT", "RTL"); lock_model(); endfunction: build endclass: spi_reg_block
11 TF - UVM Recipe of the Month 10/11
#bits
lsb
mode
reset
www.mentor.com
UVM_NO_COVERAGE UVM_CVR_REG_BITS virtual function void build(); ratio = uvm_reg_field::type_id::create("ratio"); rand divider divider_reg; UVM_CVR_ADDR_MAP ratio.configure(this, 16, 0, "RW", 0, 16'hffff, 1, endfunction uvm_reg_map APB_map; // Block map UVM_CVR_FIELD_VALS endclass function new(string name = "spi_reg_block"); UVM_CVR_ALL
super.new(name, build_coverage(UVM_CVR_ADDR_MAP)); endfunction virtual function void build(); divider_reg = divider::type_id::create("divider"); divider_reg.build(); divider_reg.configure(this, null, ""); divider_reg.add_hdl_path_slice("divider", 0, 16); APB_map = create_map("APB_map", 'h800, 4, UVM_LITTLE_ENDIAN); APB_map.add_reg(divider_reg, 32'h00000014, "RW");
1, 1);
www.mentor.com
www.mentor.com
Generate the UVM/OVM register model Generate the DUT registers Use Certe templates to generate UVM sequences, adaptor class & the bus agent
Template Generated
SQR
UVC(agent)
Template-Generated
RegSeq Sequencer
Monitor
Driver
DUT
14
www.mentor.com
Customer Example
Register Definitions
Early in project:
15
www.mentor.com
Communicate the register layer to all team members Final documents auto-generated Customizable content & style
16
www.mentor.com
Control File
Reg. Definitions
Documentation
Blocks
A Readers P I
Datamodel
A P I
Writers
RTL
Block Map
OVM/UVM Pkg.
Checks
17
www.mentor.com
UVM Coverage
You can specify the coverage model you wish to generate for instances in a block Simply add a column to your spreadsheet
18
www.mentor.com
Access the hardware register and update the register database Can specify front or back door access
Front door access takes time and may create side effects
Uses bus agent and consumes clock cycles Uses simulation database and access API (VPI)
Back door access is instant and does not cause side effects
For back door accesses, register model updated with result Can be used for individual fields Desired value
19
www.mentor.com
Good news most of these fields have defaults! A typical register access only needs a few of these:
spi_rm.ctrl.write(status, wdata, .parent(this));
2011 Mentor Graphics Corp. Company Confidential
20
www.mentor.com
Sequence base class contains variables common to all register sequences: handle) data, status register model handle
// Properties used by the various register access methods: rand uvm_reg_data_t data; // For passing data uvm_status_e status; // Returning access status // Common functionality: // Getting a handle to the register model task body; m_cfg = spi_env_config::get_config(m_sequencer); spi_rm = m_cfg.spi_rm; endtask: body endclass: spi_bus_base_seq
21
www.mentor.com
// Interesting divisor values: constraint div_values {data[15:0] inside {16'h0, 16'h1, 16'h2, 16'h4, 16'h8, 16'h10, 16'h20, 16'h40, 16'h80};} task body; super.body; // Randomize the local data value assert(this.randomize()); // Write to the divider register spi_rm.divider_reg.write(status, data, .parent(this)); endtask: body endclass: div_load_seq
Extends base sequence Randomizes data value with specific constraint Writes data to divider register
22
www.mentor.com
uvm_reg data_regs[]; // Array of registers task body; Gets an array of register handles super.body; // Set up the data register handle array data_regs = '{spi_rm.rxtx0_reg, spi_rm.rxtx1_reg, spi_rm.rxtx2_reg, spi_rm.rxtx3_reg}; Randomizes the array index order // Randomize order data_regs.shuffle(); Foreach reg in the array: foreach(data_regs[i]) begin Randomize the content // Randomize register content and then update Updates the register assert(data_regs[i].randomize()); data_regs[i].update(status, .path(UVM_FRONTDOOR), .parent(this)); end endtask: body endclass: data_load_seq
23
www.mentor.com
The register access method forms a generic register command: This is then sent through a layering to the target bus agent
B
SQR
Reg
Sequencer
Driver
DUT
24
www.mentor.com
reg2bus() converts register item to bus item note single access only
virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw); ahb_seq_item ahb = ahb_seq_item::type_id::create("ahb"); ahb.HWRITE = (rw.kind == UVM_READ) ? AHB_READ : AHB_WRITE; ahb.HADDR = rw.addr; ahb.DATA = rw.data; return ahb; endfunction
virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw); ahb_seq_item ahb; if (!$cast(ahb, bus_item)) begin `uvm_fatal("NOT_AHB_TYPE","Provided bus_item is not of the correct type") return; end rw.kind = (ahb.HWRITE == AHB_READ) ? UVM_READ : UVM_WRITE; rw.addr = ahb.HADDR; rw.data = ahb.DATA; rw.status = UVM_IS_OK; endfunction endclass: reg2ahb_adapter
25
www.mentor.com
Two ways:
Register model updates based on value written or read back OK in simple situations where only one way to access the DUT registers Requires no additional components A predictor component:
www.mentor.com
Auto Prediction
Only sequences accessing the bus agent are register sequences Register can only be accessed via one bus Based on value read or written to the register
UVC(agent)
Monitor RegSeq Sequencer
Reg
www.mentor.com
Driver
reg
27
UVC(agent)
Predictor RegSeq Monitor
Reg
Sequencer Breq
Driver
Breq
reg
28
www.mentor.com
UVC(agent)
Monitor
SQR
SQR
reg
UVC(agent)
Predictor RegSeq Sequencer Driver Monitor
reg
30
www.mentor.com
function void spi_env::connect_phase(uvm_phase phase); if(m_cfg.m_apb_agent_cfg.active == UVM_ACTIVE) begin reg2apb = reg2apb_adapter::type_id::create("reg2apb"); // Register sequencer layering part: m_cfg.ss_rm.TOP_map.set_sequencer(m_apb_agent.m_sequencer, reg2apb); // Set the predictor map: apb2reg_predictor.map = m_cfg.ss_rm.TOP_map; Predictor is integrated during // Set the predictor adapter: the connect phase apb2reg_predictor.adapter = reg2apb; // Connect the predictor to the bus agent monitor analysis port m_apb_agent.ap.connect(apb2reg_predictor.bus_in); end endfunction: connect
31
www.mentor.com
After
mirrored value
desired value
desired value
hardware value
hardware value Mirrored and desired value updated at the end of the bus read cycle
32
www.mentor.com
During
mirrored value
After
mirrored value
desired value
desired value
desired value
hardware value Mirrored and desired value updated at the end of the write cycle
33
www.mentor.com
Indirect methods:
Only access the register database Can be used on registers and fields set/get the register or field reset value
reg.get(), reg.set(),
reg.reset(), reg.get_reset()
reg.update()
Cause the hardware to be updated if register model content has changed via reg.set(), reg.reset() or reg.randomize() Can specify front or back door access
34
www.mentor.com
set()
mirrored value
update()
mirrored value
After
mirrored value
desired value
desired value
desired value
desired value
hardware value Desired value changed by indirect access method (e.g. set())
hardware value Update() transfers desired value to HW via a write bus cycle
hardware value Mirrored value updated at the end of the write cycle
35
www.mentor.com
Built-In Sequences
Low overhead to use Useful for initial sanity checks on bus connectivity
e.g. Read only registers are not bit bashed Read only memories are not tested
e.g. Clock enable bit Mechanism is to use the uvm_resource_db to set an attribute for the register
36
www.mentor.com
37
www.mentor.com
SPI master is integrated inside an AHB peripheral block Host bus sequences can reused as is Testbench structure changes
AHB to APB Bridge SPI Master
APB
SPI
Another DUT
Another DUT
38
www.mentor.com
39
www.mentor.com
40
www.mentor.com
SPI Master
APB
SPI
41
www.mentor.com
42
www.mentor.com
class sys_env extends uvm_env; axi_agent m_axi_agent; sys_env_config m_cfg; // Register layering adapter: reg2ahb_adapter reg2axi; // Register predictor: uvm_reg_predictor #(axi_seq_item) axi2reg_predictor; function void spi_env::connect_phase(uvm_phase phase); if(m_cfg.m_axi_agent_cfg.active == UVM_ACTIVE) begin reg2axi = reg2axi_adapter::type_id::create("reg2axi"); // Register sequencer layering part: m_cfg.sys_rm.TOP_map.set_sequencer(m_axi_agent.m_sequencer, reg2axi); // Set the predictor map: axi2reg_predictor.map = m_cfg.sys_rm.TOP_map; // Set the predictor adapter: axi2reg_predictor.adapter = reg2axi; // Connect the predictor to the bus agent monitor analysis port m_axi_agent.ap.connect(axi2reg_predictor.bus_in); end endfunction: connect
2011 Mentor Graphics Corp. Company Confidential
43
www.mentor.com
44
www.mentor.com
45
Use explicit prediction Built in sequences available for initial testing Works with OVM
2011 Mentor Graphics Corp. Company Confidential
www.mentor.com
46
www.mentor.com
www.mentor.com