当前位置: 首页 > news >正文

如何验证 AXI5 原子操作

如何验证 AXI5 原子操作

       摘要:在 UVM (Universal Verification Methodology) 验证环境中,验证 AXI5 协议的原子操作 (Atomic Operations) 是一项重要的任务,特别是在验证支持高并发和数据一致性的 SoC (System on Chip) 设计时。AXI5 引入了原子操作以支持无锁并发机制,确保多主设备或多核系统中的数据一致性。以下是一个详细的 UVM 验证代码示例,展示如何验证 AXI5 原子操作(如 Compare-and-Swap),包括验证策略、环境搭建和具体实现。


1. AXI5 原子操作验证策略

1.1 原子操作简介

  • 定义:AXI5 中的原子操作是一种特殊的事务类型,允许在单次总线事务中执行读-修改-写操作,确保操作过程中数据不被其他事务中断。常见的原子操作包括:
    • Compare-and-Swap (CAS):比较内存值与预期值,若相等则更新为新值。
    • Fetch-and-Add:读取内存值并加上一个增量,返回原值。
    • Swap:交换内存值和新值。
  • 信号与机制:AXI5 使用 ATOP (Atomic Operation) 字段在写通道 (AW) 上指示原子操作类型,结合 AWIDARID 等字段追踪事务。

1.2 验证目标

  • 功能正确性:验证原子操作是否按预期执行(如 CAS 仅在值匹配时更新)。
  • 数据一致性:验证多事务并发时,原子操作是否保证数据完整性。
  • 并发处理:验证在多主设备或多 ID 事务交错时,原子操作的隔离性。
  • 错误处理:验证非法原子操作或超时情况下的 DUT (Design Under Test) 行为。
  • 覆盖率:确保测试覆盖不同原子操作类型、数据值组合和并发场景。

1.3 验证策略

  1. 事务生成
    • 使用 uvm_sequence 生成随机原子操作事务,覆盖不同类型(如 CAS、Fetch-and-Add)和数据值。
    • 生成多 ID 事务,模拟并发访问。
  2. 事务追踪
    • 在 Driver 中记录发送的原子操作事务,包含 ID、预期值和新值。
    • 在 Monitor 中捕获 DUT 响应,记录操作结果。
  3. 检查机制
    • 在 Scoreboard 中实现预期值计算逻辑,验证原子操作结果是否符合预期(如 CAS 成功或失败)。
    • 检查并发事务是否影响原子操作的数据一致性。
  4. 错误注入
    • 注入错误事务(如非法 ATOP 值、预期值不匹配),验证 DUT 错误处理。
  5. 覆盖率收集
    • 使用 covergroup 覆盖原子操作类型、ID 组合、数据值范围和并发场景。

2. UVM 验证代码示例:验证 AXI5 原子操作

       以下是一个完整的 UVM 验证环境代码示例,展示如何验证 AXI5 总线的原子操作。假设验证目标是一个支持 Compare-and-Swap (CAS) 原子操作的 AXI5 总线接口。

2.1 事务类定义

定义 AXI5 事务类,包含原子操作相关字段。

class Axi5Transaction extends uvm_sequence_item;`uvm_object_utils(Axi5Transaction)rand bit [3:0] id;          // 事务 ID,用于追踪rand bit [31:0] addr;       // 地址rand bit [31:0] data;       // 数据 (新值)rand bit [31:0] expected_data; // 预期数据 (用于 CAS)rand bit is_write;          // 1 for write, 0 for readrand bit is_atomic;         // 是否为原子操作rand bit [5:0] atop;        // 原子操作类型 (ATOP 字段,假设 CAS 为 6'h10)bit sent;                   // 是否已发送bit completed;              // 是否已完成bit [31:0] read_data;      // 读回数据 (用于 CAS 结果)constraint atomic_c {if (is_atomic) {is_write == 1; // 原子操作通常是写事务atop == 6'h10; // 假设 CAS 类型} else {atop == 0;}}function new(string name = "Axi5Transaction");super.new(name);sent = 0;completed = 0;is_atomic = 0;endfunctionfunction string convert2string();return $sformatf("ID=%0d, Addr=0x%h, Data=0x%h, Expected=0x%h, IsWrite=%b, IsAtomic=%b, ATop=0x%h, Sent=%b, Completed=%b, ReadData=0x%h", id, addr, data, expected_data, is_write, is_atomic, atop, sent, completed, read_data);endfunction
endclass

2.2 UVM Agent 定义

定义 AXI5 Agent,包含 Sequencer、Driver 和 Monitor。

class Axi5Agent extends uvm_agent;`uvm_component_utils(Axi5Agent)uvm_sequencer #(Axi5Transaction) sequencer;Axi5Driver driver;Axi5Monitor monitor;uvm_analysis_port #(Axi5Transaction) ap;function new(string name, uvm_component parent);super.new(name, parent);ap = new("ap", this);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);sequencer = uvm_sequencer #(Axi5Transaction)::type_id::create("sequencer", this);driver = Axi5Driver::type_id::create("driver", this);monitor = Axi5Monitor::type_id::create("monitor", this);endfunctionfunction void connect_phase(uvm_phase phase);driver.seq_item_port.connect(sequencer.seq_item_export);monitor.ap.connect(ap);endfunction
endclass

2.3 UVM Driver 定义

Driver 发送事务,包括原子操作事务。

class Axi5Driver extends uvm_driver #(Axi5Transaction);`uvm_component_utils(Axi5Driver)virtual axi5_if vif; // 假设接口定义Axi5Transaction pending_tx[bit [3:0]]; // 按 ID 存储待完成事务function new(string name, uvm_component parent);super.new(name, parent);endfunctiontask run_phase(uvm_phase phase);super.run_phase(phase);forever beginAxi5Transaction tx;seq_item_port.get_next_item(tx);tx.sent = 1;pending_tx[tx.id] = tx;// 模拟驱动 DUT (简化版)// 实际中需根据 AXI5 协议驱动 vif 信号,包括 ATOP 字段if (tx.is_atomic) begin`uvm_info(get_type_name(), {"Driving Atomic Transaction: ", tx.convert2string()}, UVM_LOW)// 假设驱动 ATOP 字段// vif.atop = tx.atop;// vif.awid = tx.id;// vif.awaddr = tx.addr;// 等等...end else begin`uvm_info(get_type_name(), {"Driving Normal Transaction: ", tx.convert2string()}, UVM_LOW)endseq_item_port.item_done();endendtask
endclass

2.4 UVM Monitor 定义

Monitor 捕获 DUT 输出,记录事务完成。

class Axi5Monitor extends uvm_monitor;`uvm_component_utils(Axi5Monitor)uvm_analysis_port #(Axi5Transaction) ap;virtual axi5_if vif; // 假设接口定义function new(string name, uvm_component parent);super.new(name, parent);ap = new("ap", this);endfunctiontask run_phase(uvm_phase phase);super.run_phase(phase);forever begin@(posedge vif.clk);if (vif.valid_resp) begin // 假设 valid_resp 表示响应完成Axi5Transaction tx = Axi5Transaction::type_id::create("tx");tx.id = vif.id; // 假设从接口获取 IDtx.addr = vif.addr;tx.data = vif.data;tx.is_write = vif.is_write;tx.is_atomic = (vif.atop != 0);tx.atop = vif.atop;tx.completed = 1;if (vif.is_read_resp) begin // 假设 is_read_resp 表示读响应tx.read_data = vif.rdata; // 读回数据endap.write(tx); // 广播事务`uvm_info(get_type_name(), {"Monitored transaction: ", tx.convert2string()}, UVM_LOW)endendendtask
endclass

2.5 UVM Scoreboard 定义

Scoreboard 验证原子操作的正确性。

class Axi5Scoreboard extends uvm_scoreboard;`uvm_component_utils(Axi5Scoreboard)uvm_analysis_imp #(Axi5Transaction, Axi5Scoreboard) imp;Axi5Transaction sent_tx[bit [3:0]]; // 按 ID 存储发送事务bit [31:0] memory[bit [31:0]];     // 模拟内存,用于预期值计算function new(string name, uvm_component parent);super.new(name, parent);imp = new("imp", this);endfunctionfunction void write(Axi5Transaction tx);if (tx.sent && !tx.completed) begin// 记录发送事务sent_tx[tx.id] = tx;if (tx.is_atomic) begin`uvm_info(get_type_name(), {"Atomic Transaction Sent: ", tx.convert2string()}, UVM_LOW)end else begin`uvm_info(get_type_name(), {"Normal Transaction Sent: ", tx.convert2string()}, UVM_LOW)endend else if (tx.completed) begin// 检查完成事务if (sent_tx.exists(tx.id)) beginAxi5Transaction sent = sent_tx[tx.id];if (sent.is_atomic) begin// 验证原子操作 (假设 CAS)bit [31:0] mem_value = memory.exists(sent.addr) ? memory[sent.addr] : 0;if (sent.atop == 6'h10) begin // 假设 6'h10 为 CASif (mem_value == sent.expected_data) begin// CAS 成功,更新内存memory[sent.addr] = sent.data;if (tx.read_data == mem_value) begin`uvm_info(get_type_name(), {"CAS Success: Memory updated to 0x%h, Read back 0x%h for ID=%0d", sent.data, tx.read_data, tx.id}, UVM_LOW)end else begin`uvm_error(get_type_name(), {"CAS Success but Read back mismatch: Expected 0x%h, Got 0x%h for ID=%0d", mem_value, tx.read_data, tx.id})endend else begin// CAS 失败,内存不变if (tx.read_data == mem_value) begin`uvm_info(get_type_name(), {"CAS Failed: Memory unchanged, Read back 0x%h for ID=%0d", tx.read_data, tx.id}, UVM_LOW)end else begin`uvm_error(get_type_name(), {"CAS Failed but Read back mismatch: Expected 0x%h, Got 0x%h for ID=%0d", mem_value, tx.read_data, tx.id})endendendend else begin// 验证普通事务if (sent.addr == tx.addr && sent.is_write == tx.is_write && (!sent.is_write || sent.data == tx.data)) begin`uvm_info(get_type_name(), {"Normal Transaction matched: ", tx.convert2string()}, UVM_LOW)end else begin`uvm_error(get_type_name(), {"Normal Transaction mismatch: ", tx.convert2string(), " vs Sent: ", sent.convert2string()})endendend else begin`uvm_error(get_type_name(), {"Unexpected transaction completion: ", tx.convert2string()})endendendfunction
endclass

2.6 UVM Environment 定义

Environment 连接 Agent 和 Scoreboard。

class MyAxi5Env extends uvm_env;`uvm_component_utils(MyAxi5Env)Axi5Agent agent;Axi5Scoreboard scoreboard;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);agent = Axi5Agent::type_id::create("agent", this);scoreboard = Axi5Scoreboard::type_id::create("scoreboard", this);endfunctionfunction void connect_phase(uvm_phase phase);agent.ap.connect(scoreboard.imp); // 连接 Monitor 到 Scoreboardendfunction
endclass

2.7 UVM Test 和 Sequence 定义

Test 启动验证,Sequence 生成随机事务,包括原子操作。

class MyAxi5Test extends uvm_test;`uvm_component_utils(MyAxi5Test)MyAxi5Env env;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);env = MyAxi5Env::type_id::create("env", this);endfunctiontask run_phase(uvm_phase phase);MyAxi5Sequence seq;super.run_phase(phase);phase.raise_objection(this);seq = MyAxi5Sequence::type_id::create("seq");seq.start(env.agent.sequencer);phase.drop_objection(this);endtask
endclassclass MyAxi5Sequence extends uvm_sequence #(Axi5Transaction);`uvm_object_utils(MyAxi5Sequence)function new(string name = "MyAxi5Sequence");super.new(name);endfunctiontask body();Axi5Transaction tx;// 生成事务,包含原子操作和普通操作repeat (20) begintx = Axi5Transaction::type_id::create("tx");start_item(tx);if (!tx.randomize() with {id inside {[0:3]};is_atomic dist {0 := 70, 1 := 30}; // 30% 概率为原子操作if (is_atomic) {expected_data inside {[32'h0:32'hFFFF]}; // 随机预期值data inside {[32'h0:32'hFFFF]}; // 随机新值}}) begin`uvm_error(get_type_name(), "Randomization failed")endfinish_item(tx);`uvm_info(get_type_name(), {"Transaction sent: ", tx.convert2string()}, UVM_LOW)endendtask
endclass

2.8 顶层 Testbench

module tb_top;initial beginrun_test("MyAxi5Test");end
endmodule

2.9 代码说明

  • Axi5Transaction:定义 AXI5 事务,包含 is_atomicatop 字段用于表示原子操作,expected_datadata 用于 CAS 操作。
  • Axi5Driver:发送事务,区分普通事务和原子操作事务,驱动 DUT(简化版,实际需实现 AXI5 信号)。
  • Axi5Monitor:捕获 DUT 响应,记录事务完成信息,包括原子操作结果。
  • Axi5Scoreboard:验证原子操作的正确性,模拟内存值,检查 CAS 操作是否按预期更新或失败。
  • MyAxi5Sequence:生成随机事务,包含 30% 概率的原子操作,模拟并发场景。

2.10 运行结果

运行仿真后,UVM 环境生成包含原子操作的事务,日志输出示例:

UVM_INFO: Transaction sent: ID=2, Addr=0x1000, Data=0xA5A5, Expected=0x5A5A, IsWrite=1, IsAtomic=1, ATop=0x10, Sent=1, Completed=0, ReadData=0x0
UVM_INFO: Atomic Transaction Sent: ID=2, Addr=0x1000, Data=0xA5A5, Expected=0x5A5A, IsWrite=1, IsAtomic=1, ATop=0x10, Sent=1, Completed=0, ReadData=0x0
UVM_INFO: Monitored transaction: ID=2, Addr=0x1000, Data=0xA5A5, Expected=0x0, IsWrite=1, IsAtomic=1, ATop=0x10, Sent=0, Completed=1, ReadData=0x5A5A
UVM_INFO: CAS Failed: Memory unchanged, Read back 0x5A5A for ID=2

3. 验证注意事项

  1. 原子操作类型覆盖

    • 确保测试覆盖所有 AXI5 支持的原子操作类型(如 CAS、Fetch-and-Add),可扩展 atop 字段约束。
  2. 数据一致性验证

    • Scoreboard 需精确模拟内存状态,验证原子操作是否保证数据一致性。
  3. 并发测试

    • 生成多 ID、多事务并发场景,验证原子操作在高负载下的隔离性。
  4. 错误注入

    • 注入非法 atop 值、预期值不匹配或超时场景,验证 DUT 错误处理。
  5. 覆盖率收集

    • 使用 covergroup 覆盖原子操作类型、ID 组合和数据值范围。
      covergroup cg_atomic;coverpoint tx.atop { bins atop_bins[2] = {6'h10, 6'h11}; } // 假设 6'h10=CAS, 6'h11=Fetch-and-Addcoverpoint tx.id { bins id_bins[4] = {0,1,2,3}; }coverpoint tx.expected_data { bins data_bins[4] = {[0:3]*32'hFFFF_FFFF/3}; }cross tx.atop, tx.id;
      endgroup
      

4. 总结

  • 验证目标:确保 AXI5 原子操作的功能正确性、数据一致性、并发处理和错误处理能力。
  • 验证策略:通过事务生成、事务追踪、检查机制、错误注入和覆盖率收集,全面验证原子操作。
  • 代码实现:提供了完整的 UVM 验证环境,展示了如何验证 AXI5 的 Compare-and-Swap 原子操作。
  • 注意事项:关注操作类型覆盖、数据一致性、并发测试、错误注入和覆盖率收集。

       通过上述代码和策略,你可以在 UVM 环境中高效验证 AXI5 原子操作,确保 DUT 的并发处理和数据一致性符合设计要求。如果有具体的 AXI5 原子操作类型或验证场景需求,可以提供更多细节,我会进一步优化代码和方案。

http://www.xdnf.cn/news/678601.html

相关文章:

  • leetcode刷题日记——完全二叉树的节点个数
  • Java怎么实现父子线程的值传递?InheritableThreadLocal类和transmittable-thread-local类?
  • Unity3D仿星露谷物语开发53之库存管理页面
  • Introduction to SQL
  • 【键盘说明书备份】ENERGYFORT
  • 编程日志5.27
  • MySQL :MySQL基本概念
  • 高性能计算 | 硅光芯片代工厂揭秘——技术特点与未来演进
  • SpringBoot集成jwt,实现token验证
  • 鸿蒙OSUniApp 实现自定义的侧边栏菜单组件#三方框架 #Uniapp
  • SQLord: 基于反向数据生成和任务拆解的 Text-to-SQL 企业落地方案
  • CMake 在尝试下载 Boost 时失败:SHA256 校验和与预期值不匹配
  • 【第1章 基础知识】1.8 在 Canvas 中使用 HTML 元素
  • 力扣HOT100之回溯:131. 分割回文串
  • 基于Matlab实现各种光谱数据预处理
  • Turf.js:前端地理空间分析的瑞士军刀
  • 2025山东CCPC补题
  • 基于Python的简易聊天机器人实现:从原理到实践
  • 组合API-provide和inject函数
  • 多模态机器学习
  • Android 开发:从 View Activity 向 Compose Activity 传递数据的多种实现方式
  • [yolov11改进系列]基于yolov11引入可改变核卷积AKConv的python源码+训练源码
  • QCustomPlot设置曲线图中文字缩放大小
  • 微信小程序一次性订阅封装
  • Linux 权限管理基础:深入理解 root 与 sudo 的用法
  • 【监控】Spring Boot 应用监控
  • libvirt设置虚拟机mtu实现原理
  • 决策树 GBDT XGBoost LightGBM
  • ETL数据集成过程全流程优化指南
  • ICMP与TCP端口:网络层与传输层解析