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

一种解决SoC总线功能验证完备性的技术

1. 前言

通过总线将各个IP通过总线连接起来的SoC芯片是未来的大趋势,也是缩短芯片开发周期,抢先进入市场的常用方法。如何确保各个IP是否正确连接到总线上,而且各IP的地址空间分配是否正确,是一件很棘手的事情。本文提出了一种新方法,可以解决SoC总线验证的诸多困难,既简单又快速地完成SoC总线功能验证。

2. SoC总线功能验证难点

在SoC芯片开发过程中,SoC总线功能验证是确保各IP能否顺畅互动的关键,可以把每个IP比较一座座房子,总线就是房子和房子之间的路,路没修好或者修错了,房子建得再稳固再漂亮都没有什么用。以往的SoC总线面临诸多困难,导致TB代码又长又难以继承复用。主要的困难点有:

  • 总线的地址空间(memory map)频繁改动,TB需要实时适配;
  • 需要定义和维护大量的宏;
  • 不方便遍历整个地址空间的全部各区间;
  • 区间和区间之间的从属关系在TB中很难反应出来;
  • 激励完备性难以保证,只能挑选一些典型的场景和区间去测试;

3. 解决方案

本文提出的一种SoC总线功能验证方法完美解决了上述问题,非常使用,而且在真实项目中也实践过了。它有以下优点:

  • 减少TB代码修改;
  • 无需大量宏定义;
  • 方便使用;
  • 确保完备性;
  • 可复用性强;

第2节的困难点主要是因为总线的memory map区间划分数量繁多和变化频繁引起的,因此解决方法的思路也是从memory map映射到TB的格式入手。好的TB memory map格式可以起到事半功倍的效果,思路请看下文。

3.1 文件准备

假设有以下一个用Excel表示的简单总线memory map表格,它有三级,表1为全部的地址空间大小,表2为表1中IO区间的更小粒度划分区间(Region),表3为表2中SYS区间的更小粒度划分区间。

图1 Memory map在Excel中呈现的形式

Memory map表格的呈现形式具体可以和Designer讨论确定一种形式就好了,不一定要按上面的罗列的形式。

有了这个Excel表格的话,我们就可以写个脚本把每个区间的信息提取处理,包括区间的名字(Region name),起始地址(Start Address)和终止地址(End Address),以及区间和区间之间的所属关系等,比如表2中的TPIU/UART/…/SYS是IO区间的子区间,而表3的EWM/PLL/SDIO/BOOT是表2的子区间。

提取了这些信息有什么用呢?我们可以把每个区间或子区间都看作是一个SystemVerilog中的类(class)。如下图所示,这个类(Class: region)应包含了以下基本属性和方法。

图2 memory map转换成class表示的形式

Region class包含起止地址(start_addr, end_addr)和下一个子region(sub_region)的连接信息,如果一个区间没有再细分子区间,那么sub_region队列的大小为0。反之则不为0,比如图1中表1的IO区间下有5个子区间,那么IO类的sub_regions的大小将为5。然后IO区间下面的SYS子区间有更细分为4个子区间,那么SYS类的sub_regions的大小将为4。以此类推,层层嵌套。再比如表1的ROM区间没有被细分,那么ROM类的sub_regions的大小将为0。很简单,是吧。

每个紫色方框可以代表是图1中表1 Main region的一个区间,这样的话,会有5个紫色方框,map[enum]中的enum是表示enum类型,它的值是表1区间名的集合。

按以上方式形式的一个类似于金字塔的结果,最上面的是主区间,然后一层层往下细分为更新的区间,上级的区间拥有下一级区间的class句柄链接。而且所有区间都是使用region class来实现的,很方便TB通过嵌套方式来使用memory map。

另外既然memory map的每个区间都抽象为类了,那么SystemVerilog的所有语法可以用于操控它了,比如可以在start_addr和end_addr之间生成任意的地址访问。而且TB可以在class里实现诸多使用的方法(task, function)去处理数据,大大减少了重复代码。

另外通过将Excel的内容全部抽取转换为TB格式的mem_map类,TB可以逐级遍历去测试每个区间,再也不用担心漏了哪些地址区间没测了,也不怕RTL频繁改动。

当然,有一个小难点就是需要将Excel转换为图2形式的mem_map,这个我就不多讲了,脚本大家可以自己写,而且根据这个思路,可以实现很多有意思的功能,亲测实用。

3.2 效果展示

使用脚本把图1的Excel内容转成TB代码的参考代码如下:

// ==================================================================
// Main region: ROM
// ==================================================================
main[ROM] = region::type_id::create("ROM");
main[ROM].start_addr  = 'h8A0000000;
main[ROM].end_addr    = 'h99FFFFFFF;// ==================================================================
// Main region: DDR
// ==================================================================
main[DDR] = region::type_id::create("DDR");
main[DDR].start_addr  = 'h120000000;
main[DDR].end_addr    = 'h89FFFFFFF;// ==================================================================
// Main region: RESERVED_A
// ==================================================================
main[RESERVED_A] = region::type_id::create("RESERVED_A");
main[RESERVED_A].start_addr  = 'h41000000;
main[RESERVED_A].end_addr    = 'h11FFFFFFF;// ==================================================================
// Main region: USB
// ==================================================================
main[USB] = region::type_id::create("USB");
main[USB].start_addr  = 'h40000000;
main[USB].end_addr    = 'h040FFFFFF;// ==================================================================
// Main region: IO
// ==================================================================
main[IO] = region::type_id::create("IO");
main[IO].start_addr  = 'h0;
main[IO].end_addr    = 'h03FFFFFFF;
// Sub: TPIU  (IO -> TPIU)
sub_rgn = region::type_id::create("TPIU");
sub_rgn.start_addr  = 'h3D000000;
sub_rgn.end_addr    = 'h3FFFFFFF;
main[IO].sub_rgn.push_back(sub_rgn);
// Sub: UART  (IO -> UART)
sub_rgn = region::type_id::create("UART");
sub_rgn.start_addr  = 'h3C000000;
sub_rgn.end_addr    = 'h3CFFFFFF;
main[IO].sub_rgn.push_back(sub_rgn);
// Sub: GPU_REGISTER  (IO -> GPU_REGISTER)
sub_rgn = region::type_id::create("GPU_REGISTER");
sub_rgn.start_addr  = 'h3B000000;
sub_rgn.end_addr    = 'h3BFFFFFF;
main[IO].sub_rgn.push_back(sub_rgn);
// Sub: DMC_REGISTER  (IO -> DMC_REGISTER)
sub_rgn = region::type_id::create("DMC_REGISTER");
sub_rgn.start_addr  = 'h30000000;
sub_rgn.end_addr    = 'h3AFFFFFF;
main[IO].sub_rgn.push_back(sub_rgn);
// Sub: SYS  (IO -> SYS)
sub_rgn = region::type_id::create("SYS");
sub_rgn.start_addr  = 'h0;
sub_rgn.end_addr    = 'h2FFFFFFF;
main[IO].sub_rgn.push_back(sub_rgn);
// SubSub: EWM  (IO -> SYS -> EWM)
sub_rgn = region::type_id::create("EWM");
sub_rgn.start_addr  = 'h25000000;
sub_rgn.end_addr    = 'h2FFFFFFF;
main[IO].sub_rgn[$].sub_rgn.push_back(sub_rgn);
// SubSub: PLL  (IO -> SYS -> PLL)
sub_rgn = region::type_id::create("PLL");
sub_rgn.start_addr  = 'h21000000;
sub_rgn.end_addr    = 'h24FFFFFF;
main[IO].sub_rgn[$].sub_rgn.push_back(sub_rgn);
// SubSub: SDIO  (IO -> SYS -> SDIO)
sub_rgn = region::type_id::create("SDIO");
sub_rgn.start_addr  = 'h200000;
sub_rgn.end_addr    = 'h20FFFFFF;
main[IO].sub_rgn[$].sub_rgn.push_back(sub_rgn);
// SubSub: BOOT  (IO -> SYS -> BOOT)
sub_rgn = region::type_id::create("BOOT");
sub_rgn.start_addr  = 'h0;
sub_rgn.end_addr    = 'h001FFFFF;
main[IO].sub_rgn[$].sub_rgn.push_back(sub_rgn);

相关文章:

一种解决SoC总线功能验证完备性的技术

1. 前言 通过总线将各个IP通过总线连接起来的SoC芯片是未来的大趋势,也是缩短芯片开发周期,抢先进入市场的常用方法。如何确保各个IP是否正确连接到总线上,而且各IP的地址空间分配是否正确,是一件很棘手的事情。本文提出了一种新…...

Web3 与区块链:开启透明、安全的网络新时代

在这个信息爆炸的时代,我们对网络的透明性、安全性和隐私保护的需求日益增长。Web3,作为新一代互联网的代表,正携手区块链技术,引领我们走向一个更加透明、安全和去中心化的网络世界。本文将深入探讨 Web3 的基本概念、区块链技术…...

c#中Thread.Join()方法的经典示例

在 C# 中,Thread.Join 是一个非常有用的方法,它可以让主线程(调用线程)等待子线程(被调用线程)执行完毕后再继续执行。 1、经典示例1 using System; using System.Threading;public class Example {stati…...

深入了解越权漏洞:概念、危害与防范

前言 越权漏洞作为一种常见且极具威胁的安全隐患,就像隐藏在暗处的 “黑客帮凶”,时刻威胁着我们的数据安全和隐私。就让我们一起揭开越权漏洞的神秘面纱,深入了解它的来龙去脉、危害以及应对之策。 一、什么是越权漏洞 想象一下&#xff0…...

MySQL 数据库编程-C++

目录 1 数据库基本知识 1.1 MYSQL常见命令 1.2 SQL注入 1.3 ORM框架 1 数据库基本知识 MySQL 为关系型数据库(Relational Database Management System), 这种所谓的"关系型"可以理解为"表格"的概念, 一个关系型数据库由一个或数个表格组成&#xff1a…...

dl学习笔记(9):pytorch数据处理的完整流程

1)自动导入常用库的设置方式 在开始之前,这里介绍一下自动导入常用的你需要加载的库的操作方式。 首先在我们的目录下找到ipython文件,如下图: 然后找到里面的startup文件: 然后新建一个文本文档,输入你每…...

wps中的vba开发

推荐先学习vba语言(兰色幻想80集) 保存代码时注意保存为 .xlsm(启用宏的工作簿) 子程序SUN和函数FUNCTION: Sub 第一个程序()MsgBox "这是第一个程序"End Sub 注释Sub 第二个程序()Dim str As Stringstr "这是第二个程序&…...

力扣 LCR 078 合并K个升序链表

思路 解题过程 分治合并 与 LeetCode 21题 合并两个有序链表 相似 只是在此题的基础上增加了链表的数量。 使用递归将链表数组不断分成两半,直到分成的小组都只剩下一个链表元素为止,随后开始合并链表。 复杂度 时间复杂度: O(N * logK) K 为 链表(li…...

【hive】记一次hiveserver内存溢出排查,线程池未正确关闭导致

一、使用 MemoryAnalyzer软件打开hprof文件 很大有30G,win内存24GB,不用担心可以打开,ma软件能够生成索引文件,逐块分析内存,如下图。 大约需要4小时。 overview中开不到具体信息。 二、使用Leak Suspects功能继续…...

React Native 开发 安卓项目构建工具Gradle的配置和使用

gradle基本知识 gradle是React Native和Flutter调试、构建安卓App的打包工具。 gradle可以简单的类比为前端的webpack,webpack将源文件打包成HTML、CSS、JavaScript,而gradle将源文件打包成apk或aar(Android Assemble Bundle)。…...

IntelliJ IDEA新版本的底部version control(或git)里local change窗口显示配置修改详细教程

环境 IntelliJ IDEA 2024.3.2.2 (Ultimate Edition) Runtime version: 21.0.58-b631.30 aarch64 (JCEF 122.1.9) macOS 14.2.1 自己记录下。 步骤 设置 --> Version Control(版本控制) --> Commit(提交) --> 去掉勾选:Use non-modal commit interface…...

MySQL三大日志——binlog、redoLog、undoLog详解

日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息,能帮助我们进行很多容错及分析工作,其中有三大日志与我们这些开发者息息相关,本文将介绍binlog、redoLog、undoLog三种日志: 1. redoLog 1.1 为什么…...

MCU应用踩坑笔记(ADC 中断 / 查询法)

问题描述 IC:SC92F7596,在使用过程中,发现一个问题,就是我们使用到了ADC功能,程序的代码如下: ADC采样周期200ms ,采样个数:4 在使用过程中,因配置了ADC中断使能,在中断…...

32.日常算法

1.最大子数组和 题目来源 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组是数组中的一个连续部分。 示例 1: 输入:nums [-2,1,-3,4,-1,2,1,…...

通过docker安装部署deepseek以及python实现

前提条件 Docker 安装:确保你的系统已经安装并正确配置了 Docker。可以通过运行 docker --version 来验证 Docker 是否安装成功。 网络环境:保证设备有稳定的网络连接,以便拉取 Docker 镜像和模型文件。 步骤一:拉取 Ollama Docker 镜像 Ollama 可以帮助我们更方便地管理…...

批量提取word表格数据到一个excel

新建一个excel到word同级目录altf11打开vba窗口并新建模块粘贴下方代码(修改一些必要参数)回到excel表格界面,altf8选择执行该宏注意要在信任中心开启运行vba宏 Sub 批量提取word表格数据到excel()Dim wdApp As Object, wdDoc As ObjectDim …...

使用 Axios 获取用户数据并渲染——个人信息设置

目录 1. HTML 部分(前端页面结构) HTML 结构解析: 2. JavaScript 部分(信息渲染逻辑) JavaScript 解析: 3. 完整流程 4. 总结 5. 适用场景 本文将介绍如何通过 Axios 从服务器获取用户信息&#xff0…...

DeepSeek在FPGA/IC开发中的创新应用与未来潜力

随着人工智能技术的飞速发展,以DeepSeek为代表的大语言模型(LLM)正在逐步渗透到传统硬件开发领域。在FPGA(现场可编程门阵列)和IC(集成电路)开发这一技术密集型行业中,DeepSeek凭借其…...

【GitLab CI/CD 实践】从 0 到 1 搭建高效自动化部署流程

网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...

【DeepSeek-R1训练笔记】随手记录一些训练log

背景说明 DeepSeek系列解读请移步我的上一篇blog:【完整版】DeepSeek-R1大模型学习笔记(架构、训练、Infra)代码仓库【科大的大四老哥太太太太太值得倾佩了】:https://github.com/Unakar/Logic-RLDeepSeek-R1-Zero复现文档&#…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

如何为服务器生成TLS证书

TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

数据库分批入库

今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: ​onCreate()​​ ​调用时机​:Activity 首次创建时调用。​…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...