SystemVerilog随机化:仅用约束生成无序不重叠内存区域
仅通过SystemVerilog约束实现不重叠且顺序随机的内存区域
现有代码的问题
你当前代码里的if(i<j) (regions[i].addr_e < regions[j].addr_s)约束,直接把数组里索引小的区域强制排在索引大的前面,导致区域顺序固定死了,根本没法随机排列。
关于你提到的约束的分析
你注释掉的那个约束if(i!=j) !((regions[i].addr_s >= regions[j].addr_s) && (regions[i].addr_s <= regions[j].addr_e)),功能上确实能保证区域不重叠,但有两个明显问题:
- 重复检查,浪费资源:遍历所有
i≠j的时候,会把同一对区域检查两次(比如i=0,j=1和i=1,j=0是同一组),区域数量多了之后,求解器要做的额外计算会变多,随机效率会下降。 - 逻辑绕弯子:这个约束是靠禁止一个区域的起始地址落在另一个区域里来避免重叠,虽然能覆盖所有重叠情况,但不如直接说“两个区域要么完全在前面,要么完全在后面”来得直白,后续维护也麻烦。
推荐的约束写法
要实现“不重叠+顺序随机”,直接把原有约束换成下面这种更高效也更易懂的写法就行:
constraint c_regions{ regions.size() == 3; foreach(regions[i]) { regions[i].sz inside {10, 20}; // 每个区域的大小可选10或20 regions[i].addr_e == regions[i].addr_s + regions[i].sz - 1; regions[i].addr_s < regions[i].addr_e; regions[i].addr_e < 60; // 所有区域的结束地址都小于60 foreach(regions[j]) { if(i < j) { // 核心约束:每对区域必须完全不重叠,顺序随便 (regions[i].addr_e < regions[j].addr_s) || (regions[j].addr_e < regions[i].addr_s); } } } }
这么写的好处:
- 只遍历
i<j的区域对,比原来少一半的约束检查,求解器跑起来更快。 - 逻辑一眼就能看懂,直接说明白“区域之间不能重叠,谁在前谁在后都可以”,后续改需求也方便。
- 生成出来的数组里,内存区域的地址顺序是随机的,完全符合你的要求。
另外,如果你不需要indx字段来标记原索引,要么把regions[i].indx == i这个约束删掉,要么干脆把结构体里的indx成员去掉,代码更简洁。
内容的提问来源于stack exchange,提问作者Mohan
相关产品推荐
相关产品推荐

