数值类型:




byte 有符号类型,范围从0到127,-128到0。永远小于200

byte unsigned 无符号类型,范围从0到255
用 typedef 自定义类型
枚举 enum:
https://www.runoob.com/cprogramming/c-enum.html
在实际编程中,有些数据的取值往往是有限的,只能是非常少量的整数,并且最好为每个值都取一个名字,以方便在后续代码中使用,比如一个星期只有七天,一年只有十二个月,一个班每周有六门课程等
enum { valueName1, valueName2, valueName3, ...... } typeName;

enum {变量可取值} 变量名
变量只能取 { } 中的值

enum {RED, GREEN} colour; // RED = 0 , GREEN =1
变量类型:
string 字符串, 输出%s控制

数值, 输出 %d,%b,%h 等进制控制
%d是输出和系统默认位宽一致的整数,前面补 差额的空格数;%0d是根据你的实际整数位宽来输出,前面不补足。


string.touper(); // 大写输出
string.tolower(); // 小写输出
string.getc(index); // 按索引输出
string.substr(index1,index2); // 按索引输出
string.len() // string 长度
string.atoi(); // 字符串转成int
string.itoa(); // int转成字符串

读写文件:
写进文件 $fopen(); $fdisplay(); $fclose();

文件读出 $fopen(); $fgets(); $fclose();

对比
结构体 struct

利用 typedef

对比,结构体编程更加简洁
pack 将参数进行一层包装,包装后可使用%0b打印整体

赋值


$size(); // 查看变量大小
foreach; // 在数组元素上的迭代

只有单bit可以被打包
bit b_le[2:0]; // 小端模式
bit b_be[0:2]; // 大端模式
b_le = b_be; // b_le[2]=b_be[0], b_le[1]=b_be[1], b_le[0]=b_be[2]


数组
变量名之后的 ’[ ]’ 就表示这个变量代表一个动态数组。变量名之前则为所存储的数据类型。
int array[]; // 动态数组声明
array = new[2]; // 分配了内存但是没有对内存进行初始化
array[0] = 12; // 初始化
array = new[5](array); // 扩充容量的同时保留array中原有的数据
array2 = new[array.size()](array); // 动态数组的复制
array.delete(); // 删除

队列
int array[$]; // 队列声明


关联数组
https://www.cnblogs.com/pcc-uvm/p/14921443.html
integer i_array[*]; // 整数关联数组(未指定索引)
bit [20:0] array_b[string]; // 21位向量的关联数组,使用字符串类型作为索引
event ev_array[myClass]; // 事件类型的关联数组,使用类myClass索引
int imem[*];
imem[2'b3] = 1; // 索引index为2'b3
imem[16'hffff] = 2;
imem[4'b1000] = 3;
// num()方法返回关联数组中条目的数目。如果数组是空数组,那么它返回0
$display("%0d entries\n", imem.num); // 打印"3 entries"
// delete()方法删除特定索引的条目。如果没有指定索引,delete()方法删除数组的所有元素。
imem.delete(2'b3); // 从"imem"中删除索引为2'b3的条目
imem.delete; // 删除关联数组中的所有条目
// exists()函数检查对于指定数组中是否存在指定索引的元素。如果元素存在则返回1,否则返回0。
$display("%0d\n", imem.exists(2'b3));
string s;
// first()方法将指定的索引变量赋值为关联数组中第一个(最小的)索引的值。如果数组是空的则返回0,否则返回1。
if (map.first(s))
$display("First entry is : map[%s] = %0d\n", s, map[s]);
// last()方法将指定的索引变量赋值为关联数组中最后一个(最大的)索引的值。如果数组是空的则返回0,否则返回1。
if (map.last(s))
$display("Last entry is : map[%s] = %0d\n", s, map[s]);
// next()方法寻找索引值大于指定索引的条目。如果存在下一个条目,索引变量被赋值为下一个条目的索引,并且函数返回1。否则,索引不会发生变化,函数返回0。
if (map.first(s))
do
$display("%s : %d\n", s, map[s]);
while (map.next(s));
// prev()函数寻找索引小于指定索引的条目。如果存在前一个条目,索引变量被赋值为前一个条目的索引,并且函数返回1。否则,索引不会发生变化,并且函数返回0。
string s;
if (map.last(s))
do
$display("%s : %d\n", s, map[s]);
while (map.prev(s));

function
function 返回值类型 函数名(传入参数)
有无返回值对比
全局、局部变量对比
function 的调用,参数的连接
task
function、task对比。
task内部能处理延时,function只能外部处理延时;
funtion最多只有一个返回变量,task可以多个;
task可以调用function,function不可以调用task。

传入参数方向
task
传入参数方向为 input
b接上a后,a=1。task内部执行的是a,a++,a++ 后 a=3。外部的b仍然是1
传入参数方向为 output
a默认初值为0,a++,a++ 后 a=2。此时output,a接上b,b=2。
传入参数方向为 inout
先input,b接上a后,a=1。task内部执行的是a,a++,a++ 后 a=3。
此时output,a接上b,b=3。
传入参数方向为 ref
a完全等同b,a与b的变化同步。
b接上a后,a=b=1。
task内部执行的是a,a++ 后 a=2,b此时也 b=2。a++ 后 a=3,b此时也 b=3。

function
function至少要有一个input参数,不能有 output 和 inout 类型参数。
task可以有多个output。


fork jion 线程并发
fork … join
fork … jion 块内语句同时执行

fork … jion 与 begin … and 配合
fork … join_any

有一个子进程结束,跳出fork … join_any。此时使用 disable fork 剩余未结束子进制。
join … none

wait fork 确保所有子进程结束,才进入后续语句。
task任务中放 fork … jion
(左)task不加automatic,表明传入参数是全局变量。传入3个线程的arg都是一个arg。begin … end中语句顺序执行,到10ns时打印,最后一个语句赋值arg=2,则所有线程都打印2。
(右)task加automatic,表明传入参数是局部变量。传入3个线程的arg互相不同,分别打印。
-> 和 @



类
类中有变量和针对变量函数。

// 定义类
class A
...
endclass
// 声名变量
A a
// 分配内存
a = new();
类中修改默认的new函数,传入参数。则new()该类时,可以指定变量值

使用null释放内存
类 成员属性
calss int count
每次 new() 该类,都会int count,count是不同的count
calss static int count 静态变量
每次 new() 该类,都是同一个count

还没new(),就想该类中变量,可以:类::
不同的类,静态变量名相同。想修改某一个类的静态变量,可以:类::
class函数传入参数名和class成员变量名相同,可以用 this.成员变量名,指明该变量是成员变量。

类指针
cb.i = ca.i 不修改指针,只赋值,cb = ca 修改了指针,cb指向了ca
错误使用指针。先new(),再进入循环,即只new()了一次,循环中使用的都是这一个new出来的对象。即每次放入队列的都是同一个对象。
正确使用指针做法。进入循环再new(),则每次不同i,new了不同对象,放入队列的才是不同对象。
cn = new(),cn是句柄(其实就是个指针,指向该new出来变量)
指针作为参数 input 进 task 不是个好习惯。
myTask(cn),则 arg = cn,指针arg指向和cn相同。arg.i = 2 改变了 类cn的 i 值。arg = new() 又创建新类 ,新类的 i=0,arg.i = 3 又使得 新类的 i =3。
指针作为参数 output 进 task 。
myTask(cn),但 arg 是output,最后 指针arg 才赋给 指针cn。
首先 arg = new(),新类 arg.i = 0,又arg.i = 3。最后指针arg 才赋给 指针cn,cn.i = 3。
指针作为参数 ref 进 task 。
cn全程跟随arg变化。
myTask(cn),arg.i = 2,则 cn.i = 2,
arg = new(), arg重新指向新的类,cn跟随重新指向新的类,arg.i = 0,
arg.i = 3,则 cn.i = 3。

浅拷贝、深拷贝
当类的new函数中,又new一个新的类,cn=new(),即又创建一个指针cn。
所以 cb.cn = ca.cn 是指针赋给指针。(浅拷贝)
如果想要指针的值,赋给指针的值(值赋值),需要 cb.cn.i = ca.cn.i (深拷贝)
随机初始值
$urandom_range(int unsigned maxval,int unsigned minval = 0); // 返回一个在maxval和minval之间的32bit无符号整数
$random(seed) //种子变量seed是可选的
$random % b; // b为一个大于0的整数,表达式给出了一个范围在[-b+1 : b-1]之间的随机数;
int randval = $random % 60; // 随机产生一个-59~59之间的有符号数

随机初始化classs类内多个变量

在约束条件下,随机初始化classs类内多个变量
在约束条件下,随机初始化classs类内多个变量
by inside {0,1,2,3}; // 可以随机初始化为 0,1,2,3
by inside {[0:3]}; // 可以随机初始化为 0,1,2,3
by dist { }; // 初始化时候,各个随机值的权重

在约束条件下,随机初始化classs类内多个变量
class.variable.rand_mode(0); // 关闭随机模式
class.randomize() 自带3个默认函数:随机初始值,先验初始值,后验初始值。可以在class中修改使用
类的继承

class A extends Abase 继承类后,想在新建函数中 继承原类某函数。可以在函数中super.Abase_fuction()。
类的多态性
base类 的 指针 (cNumber arg),可以指向 继承base类的新类,也可以指向 base类自己

各自调用新旧类的函数
task (基类类型 指针),即使传入新类的指针,也只能调用基类的函数。

task (基类类型 指针),即使传入新类的指针,指向新类的方法。
类中定义函数为 virtual function
基类类型指针 可以指向继承它的类,继承的新类指针 不能指向原base类。