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

基于TimeQuest时序优化原理和方法

分析最坏路径

  通过前面对TimeQuest软件的理解,基本上可以找到关键路径,此文章主要对关键路径时序进行优化,使设计达到时序要求,以TFT屏驱动为案例,介绍插入寄存器优化时序的方法;
在这里插入图片描述

图1 将TFT驱动模块设为顶层模块

  将TFT_CTRL设置为顶层之后,ctrl+L对工程进行全编译;
在这里插入图片描述

图2 TTF_CTRL设置为顶层模块

  全编译之后打开TimeQuest,读取网表,Read SDC之后,查看最高频率为270.12MH,显然无法达到默认时钟1000MHZ,但是这就是设计的最高频率了?不能在提升了?当然可以提升。
在这里插入图片描述

图3 time quest查看最大时钟频率

  查看最坏传输路径:
在这里插入图片描述

图4 查看最坏路径

  可以在报告界面,直接选中 vcounter[2]这个节点,然后鼠标右击,依次选择“Locate-> Locate in Design File”来定位到该路径对应在代码中的位置,如下图所示:
在这里插入图片描述

图5 查看最坏路径对应的代码

  点击后,软件会自动跳转到代码的第 85 行,如下图所示。在此可以看到,vcount_r的变化是受 hcount_ov 和 vcount_ov 控制的,而 vcount_ov 则是跟随 vcount_r 的值变化的。所以起点和终点就都找到了。
在这里插入图片描述

图6 最坏路径对应代码

  在上述路径中,vcount_r 信号要想影响到 vcount_r 的变化,首先是经过一级组合逻辑构成的比较器,在该比较器中,与一个常量(vline_end)做比较,当两者相等时,输出为 1,其他情况下为 0,输出的信号名为 vcount_ov。vcount_ov 的值才来决定 vcount_r 的值是否变化,因此,整个传输路径可以总结为下图:
在这里插入图片描述

图7 最坏路径传输模型

  通过上图可以看到,vcount_r[3]要驱动 vcount_r[2]发生变化。中间一定要经过一级组合逻辑,既然经过了组合逻辑,就一定会引入组合逻辑延迟。而且,整个的路径其实不止这一个组合逻辑,事实上,vcount_ov 有效后,具体 vcount_r[2]是否发生变化,还与 vcount_r 这个寄存器中的其他位的值相关,所以理论上应该是 vcount_ov 信号还会再进入下一级组合逻辑中参与运算,然后才能最终决定 vcount_r[2]的值是否发生变化。这个组合逻辑在图中被放置在了与 D 触发器 vcount_r[2]同一个 LE 内,这种情况下理论来说延迟是最小的,但是事实上很可能这个组合逻辑并不会与 D 触发器 vcount_r[2]放置在同一个 LE 内,那样的话,延迟就更大了。所以,整个传输路径中至少有 2 级组合逻辑延迟,因为加入了产生 vcount_ov 这个信号的组合逻辑,导致传输延迟变长了。既然这样,只需要将vcount_r[3]到 vcount_r[2]之间的组合逻辑减少,应该就能提升最大运行时钟频率了。

RTL 级路径优化

  如何优化路径呢?优化路径的指导思路又是什么呢?其实思路很简单,核心思路就是减少寄存器到寄存器之间的组合逻辑链路。本例中 vcount_r[3]要驱动 vcount_r[2],中间至少经历两级组合逻辑,如果能够将寄存器到寄存器之间的组合逻辑数量减少一级,是不是就能提升运行的时钟频率了呢?

  vcount_r[3]的输出传递到 vcount_r[2],首先是经历了一级 LUT 实现的查找表,然后查找表的输出再进入另一个查找表,最后才到达 vcount_r[2],那么,如果能够让第一级查找表输出后,也经过 D 触发器后再送往下一级查找表,那么整个路径就被切为了两段,每段路径都只包含 1 级组合逻辑了,那样的话,传输延迟就会小很多了。如下图所示:
在这里插入图片描述

图8 最坏路径优化模型

  通过此图可以看到,vcount_ov 不再是直接由 LUT 直接输出,而是 LUT 之后马上进入了该 LE 的 D 触发器中,再由 D 触发器输出。也就是说,此种方式是在原本的时序路径中,插入了一级寄存器,从而将原本较长的组合逻辑链路路径切割为了两段较短的组合逻辑路径。从而让寄存器到寄存器之间的传递组合逻辑延迟更短,提升了系统运行频率。

  看上去好像很有道理的样子,那这个操作在原本代码工程中该怎么修改才能实现呢?其实方法非常简单,只需要将 vcount_ov 的产生语句改为时序逻辑即可,当然不要忘记了将该信号的定义也由 wire 改为 reg。具体修改内容为:

  1、 代码 49 行,“wire vcount_ov”改为“reg vcount_ov”,如下图所示:

在这里插入图片描述

图9 修改vcount_ov类型

2、代码 94 行对 vcount_ov 的 assign 赋值语句采用注释的方式屏蔽掉,加上新的时序逻辑描述的代码,如下图所示:
在这里插入图片描述

图10 修改Vcount_ov处代码

  这里将组合电路改为时序电路,vcount_ov 是会延迟一个时钟周期的,为什么不把条件vcount_r ==vline_end 改为vcount_r ==vline_end -1去弥补这一个时钟周期?因为 vcount_r 的变化不是每个时钟都有可能的,只有在 hcount_r 每计满一次才会变化一次,所以这一个时钟周期的延迟没有影响。

  那么,上述操作真的就能提升系统性能吗?能提升多少呢?这个嘛,就可以通过修改设计后重新编译,再对设计进行时序分析来知晓了。全编译之后再看一下,结果如下所示:
在这里插入图片描述

图11 优化结果

  300.48MHZ???哈哈,一顿操作猛如虎,之前是270.12MHZ,现在是 300.48MHZ,提升了近 30MHzZ了。

  首先来说,经过这一波操作,确实没有明显提升最大运行主频,但是这并不代表此方法错了,或者说此方法是没用的,只能说操作还没完。时序分析和约束的过程是一个“约束—>分析—>再约束/修改—>再分析”的往复循环的过程,一次操作只能解决部分问题,当执行了修改之后,也许之前的关键路径解决了,但是马上又会有新的路径成为关键路径,需要再对新的关键路径进行分析,直到最后满足设计需求或者再也无法优化。既然如此,那就继续分析吧,看看经过修改之后,成为新的影响系统运行时钟频率的关键路径是哪个。

  通过查看 Worst-Case Timing Paths 下面的 Setup ‘Clk9M’选项,可以看到,此次 vcount_r到vcount_r的这条路径,已经没有提示时序余量为负了,甚至都没有出现在Worst-Case Timing Paths 里面,那么这里,我想留个疑问在这里,供有心的童鞋去思考:此时,hcount_r 到 vcount_r的余量是多少,该怎么看,或者,问个更意外的问题,该条路径是否还在?本笔记不对该问题作答,仅供有心的童鞋去思考。

  此次 vcount_r 到 vcount_r 的这条路径,已经没有提示时序余量为负了,时序余量最小的路径是hcount_r[4]到 vcount_r[3],该路径时序余量为-2.328。
在这里插入图片描述

图12 优化后的最坏路径如上图

  定位到该路径相关的代码位置,经过分析发现,vcount_r 的计数条件除了和 vcount_ov相关以外,还和 hcount_ov 相关,而 hcount_ov 的产生方法和 vcount_ov 的完全一致,也是使用的组合逻辑直接产生的。

  既然这样,那就借鉴前面优化 vcount_ov 的思路,使用同样的方法把 hcount_ov 也优化了,既把 hcount_ov 的产生也改写为时序逻辑。

  1、 代码 48行,“wire hcount_ov”改为“reg hcount_ov”,如下图所示:
在这里插入图片描述

图13 修改hcount_ov信号类型

  2、代码 79 行对 hcount_ov 的 assign 赋值语句采用注释的方式屏蔽掉,加上新的时序逻辑描述的代码,如下图所示:
在这里插入图片描述

图14 修改hcount_ov处代码

  至于图中为啥是 hpixel_end – 1 而不是原来的 hpixel_end ,因为这是寄存器输出,会有一个时钟周期的延迟,所以为了和之前没有修改的时序一致,需要提前一个时钟周期产生该信号。

  全编译之后再看一下,结果如下所示:

在这里插入图片描述

图15 优化后系统最坏路径

  最坏路径的时序余量为-1.518ns,则:Fmax = 1 / (Tclk - Tslack) = 1 / (1 – (-1.518)) = 397.1406MHZ

  再看下报告里的 Fmax Summary,也是一样的值:

在这里插入图片描述

图16 优化后系统最大时钟频率

  此时hcount_r 到hcount_r的延迟已经不能够依靠更改RTL代码进行优化了,只能通过更改触发器内部结构才能继续优化,但是这已经不是用户该考虑的问题了;

总结

  到此为止,已经优化到了一个比较高的程度了,要再优化,就要从计数器的结构入手了,通过修改计数器的结构来优化,这就很烧脑了。对于当前这个代码,能在 Cyclone IV E 上跑出 393MHz 的频率,相信大家已经很满意了。所以呢关于优化的内容,讲到这里,也就基本差不多了。方法很简单,也就是常说的,插入寄存器大法。

相关文章:

基于TimeQuest时序优化原理和方法

💡 回顾基于RTL逻辑时序优化的基本思路,在关键路径中插入寄存器来优化时序 分析最坏路径 通过前面对TimeQuest软件的理解,基本上可以找到关键路径,此文章主要对关键路径时序进行优化,使设计达到时序要求,以…...

LeetCode第332场周赛

2023.2.12LeetCode第332场周赛 6354. 找出数组的串联值 思路 双指针模拟&#xff0c;两个指针相遇的时候要特判 算法 class Solution { public:long long findTheArrayConcVal(vector<int>& nums) {long long ans 0;int i 0, j nums.size() - 1;while (i <…...

2023-2-12刷题情况

字母板上的路径 题目描述 我们从一块字母板上的位置 (0, 0) 出发&#xff0c;该坐标对应的字符为 board[0][0]。 在本题里&#xff0c;字母板为board [“abcde”, “fghij”, “klmno”, “pqrst”, “uvwxy”, “z”]&#xff0c;如下所示。 我们可以按下面的指令规则行动…...

拉普拉斯矩阵

拉普拉斯算子 Δff(xi1,yj)f(xi−1,yj)f(xi,yj1)f(xi,yj−1)−4f(xi,yj)∑(k,l)∈N(i,j)(f(xk,yl)−f(xi,yj))\begin{aligned} \Delta f & f\left(x_{i1}, y_j\right) f\left(x_{i-1},y_j\right) f\left(x_i,y_{j1}\right)f\left(x_i,y_{j-1}\right) - 4f\left(x_i,y_j\r…...

Top-1错误率、Top-5错误率等常见的模型算法评估指标解析

Top-1 错误率&#xff1a;指预测输出的概率最高的类别与人工标注的类别相符的准确率&#xff0c;就是你预测的label取最后概率向量里面最大的那一个作为预测结果&#xff0c;如过你的预测结果中概率最大的那个分类正确&#xff0c;则预测正确&#xff0c;否则预测错误。比如预测…...

Urho3D 容器类型

Urho3D实现了自己的字符串类型和模板容器&#xff0c;而不是使用STL。其基本原理如下&#xff1a; 在某些情况下提高了性能&#xff0c;例如使用PODVector类时。保证字符串和容器的二进制大小&#xff0c;以允许例如嵌入Variant对象内。减少了编译时间。直接命名和实现&#x…...

C语言学习笔记(四): 循环结构程序设计

while语句 定义 While语句是C语言中的循环语句&#xff0c;它按条件循环执行语句&#xff0c;直到条件不满足为止 语法格式如下: while(condition) {//循环体内容; }使用实例 求123…100 include <stdio.h> int main(){int i 1, sum 0;while (i<100){sum i …...

02 OpenCV图像通道处理

1 通道提取与合并 在数字图像处理中&#xff0c;图像通道是指一个图像中的颜色信息被分离为不同的颜色分量。常见的图像通道包括RGB通道、灰度通道、HSV通道等。 RGB通道是指将图像分离为红色、绿色和蓝色三个颜色通道&#xff0c;每个通道表示相应颜色的亮度。这种方式是最常…...

微信小程序图书馆座位预约管理系统

开发工具&#xff1a;IDEA、微信小程序服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7前端技术&#xff1a;vue、uniapp服务端技术&#xff1a;springbootmybatis本系统分微信小程序和管理后台两部分&#xff0c;项目采用…...

有限元分析学习一

系列文章目录 有限元分析学习一 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录系列文章目录前言一、有限元方法的简单介绍1.1 有限元的基础概念1.2 有限元软件发展历史1.3 有限元软件二、弹性力学的简单介绍2.1.…...

android avb2.0 总结

1、android vbmeta结构深入解析 2、android libavb深入解读 看完结构与代码,进一步了解了avb 比如vbmeta的结构、5种描述符、hash公钥签名存储位置 多层vbmeta结构、无vbmeta分区的验证逻辑、hash计算对比、公钥验证、签名验签、5种描述符体的处理 但是还有一些问题没有解决 如…...

聊天机器人-意图识别类,开源库推荐

随着人工智能和自然语言处理技术的不断发展&#xff0c;聊天机器人在商业、教育、医疗等领域的应用越来越广泛。因此&#xff0c;开源聊天机器人代码库也逐渐成为了热门话题。 开源聊天机器人代码库可以帮助开发者快速构建功能强大的聊天机器人&#xff0c;而不必从头开始编写…...

Java 标识符以及修饰符

Java 标识符Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。关于 Java 标识符&#xff0c;有以下几点需要注意&#xff1a;所有的标识符都应该以字母&#xff08;A-Z 或者 a-z&#xff09;,美元符&#xff08;$&#xff09;、或者下划线&#xff08;_&…...

封装、继承、Super、重写、多态instanceof类型转换的使用以及个人见解

这里写目录标题封装继承supersuper和this的区别重写多态instanceof类型转换封装 之前我们调用共有的属性&#xff0c;是直接可以调用的 但是属性私有后&#xff0c;无法在直接.调用 只能通过getset调用 继承 super 可以直接调用父类中属性和方法&#xff0c;私有的无法做 其…...

day13_面向对象的三大特征之一(封装)

封装概述 为什么需要封装&#xff1f; 现实生活中&#xff0c;每一个个体与个体之间是有边界的&#xff0c;每一个团体与团体之间是有边界的&#xff0c;而同一个个体、团体内部的信息是互通的&#xff0c;只是对外有所隐瞒。例如&#xff1a;我们使用的电脑&#xff0c;内部…...

越界访问数组

越界访问是指访问&#xff08;操作修改&#xff09;了不属于自己的空间 我们以如下代码为例&#xff1a;此代码在vs中进行 #include <stdio.h> int main() {int i 0;int arr[] {1,2,3,4,5,6,7,8,9,10};for(i0; i<12; i){arr[i] 0;printf("hello\n");}r…...

软件设计(十)--计算机系统知识

软件设计&#xff08;九&#xff09;https://blog.csdn.net/ke1ying/article/details/128990035 一、效验码 奇偶效验&#xff1a;是一种最简单的效验方法。基本思想是&#xff1a;通过在编码中增加一个效验位来使编码中1的个数为奇数&#xff08;奇效验&#xff09;或者为偶…...

【不知道是啥】浅保存哈

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…...

2021 WAIC 世界人工智能大会参会总结

前言 2021 年世界人工智能大会&#xff08;WAIC&#xff09;于2021年7月7日至10日在上海世博展览馆举办&#xff0c;本届大会继续秉持「智联世界」的理念&#xff0c;以「众智成城」为主题&#xff0c;促进全球人工智能创新思想、技术、应用、人才和资本的集聚和交流&#xff…...

ThingsBoard-实现定时任务调度器批量RPC

1、概述 ThingsBoard-CE版是不支持调度器的,只有PE版才支持,但是系统中很多时候需要使用调度器来实现功能,例如:定时给设备下发rpc查询数据,我们如何来实现呢?下面我将教你使用巧妙的方法来实现。 2、使用什么实现 我们可以使用规则链提供的一个节点来实现,这个节点可…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...

React核心概念:State是什么?如何用useState管理组件自己的数据?

系列回顾&#xff1a; 在上一篇《React入门第一步》中&#xff0c;我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目&#xff0c;并修改了App.jsx组件&#xff0c;让页面显示出我们想要的文字。但是&#xff0c;那个页面是“死”的&#xff0c;它只是静态…...

Python的__call__ 方法

在 Python 中&#xff0c;__call__ 是一个特殊的魔术方法&#xff08;magic method&#xff09;&#xff0c;它允许一个类的实例像函数一样被调用。当你在一个对象后面加上 () 并执行时&#xff08;例如 obj()&#xff09;&#xff0c;Python 会自动调用该对象的 __call__ 方法…...

Redis上篇--知识点总结

Redis上篇–解析 本文大部分知识整理自网上&#xff0c;在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库&#xff0c;Redis 的键值对中的 key 就是字符串对象&#xff0c;而 val…...

Win系统权限提升篇UAC绕过DLL劫持未引号路径可控服务全检项目

应用场景&#xff1a; 1、常规某个机器被钓鱼后门攻击后&#xff0c;我们需要做更高权限操作或权限维持等。 2、内网域中某个机器被钓鱼后门攻击后&#xff0c;我们需要对后续内网域做安全测试。 #Win10&11-BypassUAC自动提权-MSF&UACME 为了远程执行目标的exe或者b…...

CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)

漏洞概述 漏洞名称&#xff1a;Apache Kafka Connect JNDI注入导致的远程代码执行漏洞 CVE编号&#xff1a;CVE-2023-25194 CVSS评分&#xff1a;8.8 影响版本&#xff1a;Apache Kafka 2.3.0 - 3.3.2 修复版本&#xff1a;≥ 3.4.0 漏洞类型&#xff1a;反序列化导致的远程代…...