system verilog学习记录2--类和随机约束

system verilog学习记录2--类和随机约束,第1张

system verilog学习记录2--类和随机约束 system verilog学习记录2–类和随机约束
    类的特点:封装,继承,多态。对象创建的初始化顺序,(有super.new())
    1). 子类实例在初始化的时候要先调用父类的new();
    2). 父类new()完成后,子类成员变量初始化;
    3). 最后才会执行子类的new()函数中的剩余代码。父类和子类如果出现两个同名的成员方法?
    默认没有任何关系
    但是如果子类中没有写该同名方法,子类默认直接继承父类的方法。
    但是子类中一旦写了和父类同名的方法,则需要用super来继承该方法,否则就是两个不同的方法。
    子类的句柄可以按就近原则或者指定访问子类的对象和父类的对象,
    而父类的句柄只能访问父类的对象。
    t为父类的句柄,wr为子类的句柄,
    若t=wr, t和wr都指向子类的对象,但是t只能索引到父类所在的小区域。相当于句柄指向的对象缩小为父类的范围。
    若wr=t,则报错。将父类句柄直接赋值给子类句柄,会报错==》会造成内存泄露
    只能通过$cast(wr,t)来将父类句柄t转化为子类句柄wr。索引范围只能缩小,不能扩大。

wr指向子类的对象,t指向父类的对象,t永远指向父类的对象;
==》要看t究竟是子类的句柄,但它只能访问父类的范围;还是t为父类的句柄真的只指向了一个父类的对象。

前缀要和包的前缀保持一致 + import regs_pkg:
==》好的习惯,如果在当前module中找不到,会到两个包中去找。前缀保持一致的优点的是,无需担心搜索时同名的的sv文件或者同名的class发生冲突。

    随机约束
    约束相关语法
    1) rand/randc + constraint xx{} + assert(x.randomize()) 想要完成随机化三者缺一不可。

    2) rand和randc的区别
    rand: 每次随机概率一样。一般都用这个。
    randc: 相当于轮询,比如64张牌,每次抽一张就不放回。在64张牌用完之前,不会抽到重复的。可以配合产生独一无二的随机数。

    3)权重分布 dist + := 或者 :/
    A. dist + := x 表示每个权重一样,都是x。
    B. dist + :/x 表示每个权重等分配,总数是x,平均分配下去。

    4). inside [min:max]

    5)x.constraint_mode(0) 关闭约束
    x.constraint_mode(1) 打开约束
    6)内嵌约束
    使用randomize() wirth 来增加额外的约束

    7)数组约束
    动态数组:A.长度可以随机约束,B.内容可以随机约束

    动态数组的大小应该给定范围,防止生成过大体积的数组。
    8) 随机化句柄数组【难点,涉及到句柄嵌套】

    class RandStuff
    Xxxxx
    endclass
    class RandArray;
    rand RandStuff array[] //存放了类的句柄的动态数组,这个动态数组中存放的都是句柄。
    Xxxxx //分配最大值,然后将每一个数组分配一个对象
    endclass
    randArray ra;
    initial begin
    ra = new(); //注意这个句柄里边嵌套有小的句柄,一旦创建了这个对象,动态数组里边 10个array的句柄也创建了。
    assert(ra.randomize()); //randomize中随机化的是什么?是array(数组)的元素的个数,可能随机化成了5个或者3个等等。
    end

    第一层:
    不仅会随机化动态数组的长度(.size在做constraint)还会随机动态化数组的内容。而当动态数组成为一个句柄时,“随机化数组的内容”就会变成“随机化数组句柄指向的对象的内容”
    而因为句柄指向的对象class中的内容vaule前没有rand修饰。所以该对象里边的内容不会被随机化。但是一旦vaule前有rand修饰,该对象里边的内容会被随机化。
    涉及内容:
    A. 句柄嵌套,这里从顶到下一共三层句柄:ra里边是array, array里边是vaule
    B. 随机化句柄数组。随机 长度 + 内容(句柄指向的对象)
    第二层:

    =>如果这里去掉,assert(ra.randomize())之后,会随机产生几个句柄,但是没有指向任何一个对象。但发现句柄是rand,会主动去向句柄指向的对象去做随机化,但是它现在找到不合理的对象,故此时randomize报错哦。
    =>如果句柄本身是rand,那么这些句柄在randomiza()之前必须要指向一些例化的对象.
    =>而这里为什么是按照最大的容量分配对象,因为这样保证了之后不管randomize()了几个,随机化出来的句柄都指向了一个对象,然后让对象里的元素都得到随机化。这样做不会不合法。
    =>当句柄被申明为rand时,他想表示接下来表示什么?表示我要randomiza(),这个句柄指向的对象以及对象里边的内容都会被随机化,前提是①这个句柄没有被悬空②这个句柄指向类有没有元素也声明了rand,若有也会被随机化.
    《66.数组约束》24分钟以后都是干货,涉及到易错点以及高阶用法,要反复听
    注意点总结:
    1)只允许类将随机的变量封装到软件的盒子里
    2) 只有当所有值都随机化求解成功,才会都随机化成功,否则全部失败。
    3)你给的约束一定要匹配你的位宽。别约束时1-12,结果位宽才给2bit, 0-3 ,那结果只能是1-3,这里容易犯错。
    4)约束也会继承,要注意。如果子类写了一个约束,在对子类进行随机化的时候,父类和子类都会生效,要注意不要两个相斥。 即子类新添加的约束不能违反父类的约束。
    我们一般在父类中的rand前增加soft(软约束),这样在子类约束和父类约束有冲突时,软约束的优先级会降低,优先使用外部约束。
    5) 易错点:以上我们用到的randomize(),都是直接这么写,括号里不加任何东西。
    但是如果我们在randomize()中写一些参数,那么只有括号中的数会被随机化,不在括号中的变量即使前面有rand修饰,也不会被随机化。
    同时,所有的约束仍然保持有效。
    6) foreach 易出错的地方

    da[i] < da[i+1]中(即i和i+1同时存在时),da.size长度是3-5,所以i是有可能扫描到4的。当foreach扫描到i=4, da[4] 如果只有da[i],那么应该是i<=da.size()-1;这个foreach默认会支持。但是你da[i],和da[i+1]同时存在。Foreach不会那么智能到去添加size-2,所以得手动加上if(i<=da.size()-2)。
    7) 怎么产生唯一的数组呢?
    法一:得用两个foreach嵌套,当u[x]除了他自己,要与其他数不同
    法二:randc+回调函数pre_randomize()

    pre_randomize()为什么叫回调函数》》》在例化创建Little。。这个句柄后,如果调用randomize()
    系统会自动先执行pre_randomize()这个函数
    思考:rc8 = new();是否可以放到foreach的begin中?不行!!
    因为放在里边意味着 每次拿出一张牌之后,你又重新洗牌,那么可有可能会拿出重复的。
    但是放在外边,永远只有一副牌,1-256才会循环一次,而拿一张少一张,64次不可能会出现重复的。
    注意:bit [7:0] ua前是不要加rand的。其实随机化是在pre_randomize中做的,在randomize()中其实什么都没做。
    法三:使用unique关键词(2012年新添加)
    8)调试常用
    #每次产生不同的随机种子,chnl_basic_test 是测试入口,可自由改变
    vsim -novopt -solvefaildebug -sv_seed random +TESTNAME=chnl_basic_test work.tb3_ref
    #保存所有波形
    log -r /*

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5718973.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存