芯片验证从零开始系列(二)——SystemVerilog数据结构

2024-03-09 02:48

本文主要是介绍芯片验证从零开始系列(二)——SystemVerilog数据结构,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

芯片验证从零开始系列(二)——SystemVerilog数据结构

  • SystemVerilog的数据类型
    • 二值逻辑
    • 定宽数组
    • 合并数组
    • 队列
    • 关联数组
    • 数组的方法
    • 数据类型选择的经验
      • 灵活性
      • 存储量
      • 排序
    • 自定义类型
    • 联合
    • 合并结构
    • 类型转换
      • 静态转换
      • 流操作符
    • 枚举
    • 字符串

🔈声明:
🔑未经作者允许,禁止转载
🚩推荐一个IC、FPGA新手入门的好网站:👉快 点 击 进 入 学 习 吧👈



IC验证行业中主流的语言就是SystemVerilog,其占比高达70%以上。而验证方法学主流是UVM,占比也是碾压姿态,并且两者还有不断增长的趋势。
所以要想学好IC验证,SystemVerilog和UVM是必学的。

所以笔者从SV开始学习。

SystemVerilog的数据类型

二值逻辑

SV添加了二值逻辑数据类型,帮助更高抽象级建模。

  • bit : 1位二值变量
  • byte :8位二值变量(等同于C的char)
  • shortint:16位二值变量(等同于C的short)
  • int:32位二值变量(等同于C的int)
  • longint:64位二值变量(等同于C的longlong)

logic或bit构成的vector是无符号的,其余均是有符号的(所以要避免混用)

四值逻辑(reg,integer,logic)仿真开始时为X;二值逻辑(bit,byte)仿真开始时为0。
并且如果四值逻辑和二值逻辑的数据类型之间发送转换,Z和X会转换为0

定宽数组

SV允许数组的紧凑定义,例如以下两种方式都是定义8行4列的二维数组,但是后者书写更为方便。

int array[7:0][3:0] = int array[8][4];

输入数组越界,四值逻辑会返回X;二值逻辑会返回0。

非合并数组中,低位放数据,高位不使用(如下图所示),所以用四值逻辑放同样数据要比二值逻辑多一倍的存储空间。

在这里插入图片描述

  • 在SV中for和foreach都可以用来遍历数组,但是foreach用来遍历数组极为方便(不用考虑停止条件),例子如下:
initial begin
bit src[10];
foreach(src[j])src[j]=j;
end

在SV中可以直接复制和比较两个数组,但是只有**==和!=**两种结果,并且其余的数组运算要通过循环来实现。

在SV中还可以同时使用数组下标和位下标,如:

initial beginbit[31:0]src[5]='{5{5}};  //赋值5个 32‘d5$display(src[0][2:1];
end

这里显示的就是10.。

合并数组

合并数组可以将多个小字节组装成一个大的,这种数据类型较为紧凑。如:

bit[3:0][7:0]bytes;

这样的写法就是合并数组的写法,可以将4个8bit的数组合并地放在一起,就不会出现像前文图中的将高位浪费的现象出现。

队列

SV中的队列像C++中的双端队列。
可以使用内置函数插入删除,也可以用拼接的方法进行操作。

int	j = 1, q2[$]={3,4},q[$]={0,2,5};
initial beginq.insert(1,j);      //{0,1,2,5}q.insert(3,q2);		//{0,1,2,3,4,5}q.delete(1);		//{0,2,3,4,5}
end

关联数组

如果有一个稀疏矩阵需要存储,直接用数组来做肯定十分浪费存储空间。SV为这种情况提供了关联数组。(个人感觉很像哈希表)

  • 如果想从一个关联数组中随机选取一个元素,你需要逐个访问它之前的元素,因为没有办法直接访问第N个元素。

数组的方法

在SV中数组的函数返回的都是队列而不是标量。

SV中没有提供专门的随机选取元素的办法,所以对于定宽数组,队列,动态数组和关联数组可以用¥urandom_range($siz(array)-1)。

find with语句可以指示指令如何去搜索。

  • 数组的定位是新建一个队列返回,而数组排序是在原数组上排。
  • reverse() 反向排序
  • sort() 从小到大排序
  • rsort()从大到小排序
  • shuffle()乱序

数据类型选择的经验

灵活性

  • 当数据索引不规则时,例如对于由随机数值或地址产生的稀疏分布索引,应选关联数组。
  • 关联数组也可以用来对基于内容寻址的存储器建模。
  • 对于仿真过程中元素数目变化很大的数组,用队列会较好。

存储量

因为需要额外的指针,队列的存储效率比定宽或动态数组稍差。(差在哪里呢?)
因为指针带来的额外开销,关联数组里每个元素所占用的空间可能会比定宽或动态数组大好几倍。

排序

如果元素是一次性全部加入的话,用定宽或者动态数组较好;如果元素是一个个加入的话用队列较好。

自定义类型

通过用户自定义类型,将以往Verilog的代码可以通过更少的代码来表示更多功能。

这里特别注意的是自定义数组类型的时候

typedef int fixed_arrays[5]

自定义定义数组长度时要把下标放在自定义名称后。

此外,struct只是一个数据的集合,可以被综合。但如果想生成带约束的随机数据,就应该用类

联合

待了解后补充

合并结构

合并结构是为了节约存储空间,在结构体中每个数据还是占了一个32位的长字(即使浪费),那么用合并结构就可以充分利用空间,这和合并数组是一个道理。

  • 如果经常操作整个结构用合并结构较好,如果经常操作其中成员用非合并结构较好。

类型转换

如果两个数据的比特位分布相同,可以直接赋值;如果比特位不相同,则需要流操作符重新安排。

静态转换

  • 和C++的强制类型转换差不多,但是在右值前要加’。
int i;
real r;
i=int'(10.0-0.1);
r=real'(42);

流操作符

流操作符用于把其后的数据打包成比特流(但是此处有一个数组下标赋值乱序的问题还没搞懂,有待补充)

流操作符十分好用比如:

initial beginint h;bit[7:0] j[4]='{8'ha,8'hb,8'hc,8'hd};bit[7:0] q,r,s,t;h={>>{j}};        	//0a0b0c0dh={<<{j}};			//b030d050	每一bit从右到左h={<<byte{j}};		//0d0c0b0a	按字节从右到左{>>{q,r,s,t}}=j;	//把j分散给qrst;
end
  • 操作符>>把数据从左往右变成数据流;操作符<<把数据从右往左变成数据流。

枚举

枚举类型能够自动为列表中的每个名称分配不同的数值。
并可以用内建函数name(),得到对应的字符串。

枚举类型可以直接赋值给int,但是int类型赋值给枚举类型做好用$case()检测一下是否越界。

  • 此处还有一个小技巧。
    因为枚举类型是一个环,如果大于最后一个数据后会返回头数据,所以遍历所有枚举类型时可以用do-while来实现,如:
typedef	enum {red,blue,green}	color_e;
color_e color;
color=color.first;
dobegin$display("color=%0d/%s",color,color.name);color=color.next;end
while(color!=color.first);

字符串

SV中string可以保存长度可变的字符串,不需要担心空间的问题。但是和C不同的是,SV的字符串结尾不带NULL。

此外利用$psprintf()可以将想要的信息转换成固定格式的临时字符串,如

$psprintf("%s %5d",s,42);

以上就是SV的数据类型的学习,暂时还有两个问题还没搞清楚,待后续明白后继续补充。




最后给大家安利一个好网站:
  Verilog的学习还是要多以练习为主,想要练习Verilog的同学,推荐可以去nowcoder看看,他们现在的题库内容很丰富,属于国内做的很好的了,而且是课程+刷题+面经+求职+讨论区分享一站式求职学习网站,最最最重要的里面的资源全部免费

这篇关于芯片验证从零开始系列(二)——SystemVerilog数据结构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/789323

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return