4. 模拟地址越界访问

任务目标

构造超出存储器映射地址范围的读写请求,驱动到DUT接口,验证地址保护机制能够正确识别越界访问并产生响应(如错误应答或总线异常),同时不影响合法地址空间的正常操作。

环境与依赖

基于UVM 1.2,需要标准UVM库。DUT为带地址保护的简单存储器模型,地址空间为0x0000_0000 ~ 0x0000_0FFF(4KB),越界地址定义为超出此范围。使用UVM寄存器模型或直接sequence驱动均可,本案例采用直接sequence方式以聚焦地址越界场景。

关键完整代码

// 文件: addr_overflow_seq.sv
class addr_overflow_seq extends uvm_sequence #(bus_transaction);
    `uvm_object_utils(addr_overflow_seq)

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

    virtual task body();
        bus_transaction req;
        // 合法边界地址(应正常响应)
        req = bus_transaction::type_id::create("req");
        start_item(req);
        req.addr = 32'h0000_0FFC;  // 合法空间最后一个word
        req.kind = bus_transaction::READ;
        finish_item(req);

        // 越界地址:刚好超出4KB边界
        req = bus_transaction::type_id::create("req");
        start_item(req);
        req.addr = 32'h0000_1000;  // 越界首地址
        req.kind = bus_transaction::READ;
        finish_item(req);

        // 越界地址:远高于地址空间
        req = bus_transaction::type_id::create("req");
        start_item(req);
        req.addr = 32'hFFFF_0000;
        req.kind = bus_transaction::WRITE;
        req.data = 32'hDEAD_BEEF;
        finish_item(req);

        // 再次合法访问,验证保护机制不影响正常操作
        req = bus_transaction::type_id::create("req");
        start_item(req);
        req.addr = 32'h0000_0000;
        req.kind = bus_transaction::WRITE;
        req.data = 32'h1234_5678;
        finish_item(req);
    endtask
endclass

// 文件: addr_overflow_test.sv
class addr_overflow_test extends uvm_test;
    `uvm_component_utils(addr_overflow_test)

    function new(string name = "addr_overflow_test", uvm_component parent = null);
        super.new(name, parent);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        // 假设env已在更高层构建,此处仅做简化示例
    endfunction

    virtual task run_phase(uvm_phase phase);
        addr_overflow_seq seq;
        phase.raise_objection(this);
        seq = addr_overflow_seq::type_id::create("seq");
        seq.start(uvm_top.find("*.env.agent.sqr"));
        #100ns;
        phase.drop_objection(this);
    endtask
endclass

// 文件: bus_transaction.sv(最小定义)
class bus_transaction extends uvm_sequence_item;
    `uvm_object_utils(bus_transaction)
    rand bit [31:0] addr;
    rand bit [31:0] data;
    rand bit is_write;
    typedef enum {READ, WRITE} kind_t;
    rand kind_t kind;
    bit error_flag;  // DUT返回的越界标志

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

    `uvm_field_int(addr, UVM_ALL_ON)
    `uvm_field_int(data, UVM_ALL_ON)
    `uvm_field_enum(kind_t, kind, UVM_ALL_ON)
    `uvm_field_int(error_flag, UVM_ALL_ON)
endclass

DUT地址保护行为约定

DUT对越界读返回data=32'hFFFF_FFFF并置error_flag=1;对越界写不产生存储效应,仅置error_flag=1。合法访问时error_flag=0且数据正常读写。

运行方式

# 在UVM环境中编译并运行
vlog +incdir+$UVM_HOME/src bus_transaction.sv addr_overflow_seq.sv addr_overflow_test.sv dut.sv top.sv
vsim -c -do "run -all; quit" work.top

验证方法与判定标准

  1. 在scoreboard中检查:对0x1000和0xFFFF_0000的访问,monitor捕获到的error_flag必须为1;
  2. 对0x0FFC的读和0x0000的写,error_flag必须为0,且写后读回数据一致;
  3. 仿真结束时打印UVM_ERROR计数为0,表明所有越界访问均被正确标记,合法访问未受影响。

若DUT未置error_flag或合法访问被误判,则说明地址保护逻辑存在缺陷,测试失败。