赞
踩
#平头哥芯片设计
##一面(视频面试)
一个64位的起始地址和一个8位的长度,需要随机这两个变量,让每次随机出来的地址空间都和之前的任意一次都没有重叠。例如第一次地址是3,长度是5,第二次地址是20,长度是10,这样就可以,但是第三次如果随机出来地址是15,长度是10就不行。因为和第二次有一部分是重叠的。请问这样的class该怎么设计?
- class addr_manager;
- // 存储所有地址范围的动态数组
- typedef struct packed {
- longint unsigned start;
- byte length;
- } addr_range;
-
- // 已分配的地址数组
- addr_range region[];
-
- // 方法用于加入新的地址段
- function new_region(longint unsigned start, byte length);
- addr_range new_region;
- new_region.start = start;
- new_region.length = length;
- if (!check_overlap(new_region)) begin
- region.push_back(new_region);
- end else begin
- $display("Overlap detected: Cannot add range start=%0d length=%0d", start, length);
- end
- endfunction
-
- // 检查新的地址区域是否与已有区域重叠
- function bit check_overlap(addr_range new_region);
- foreach (region[i]) begin
- if ((new_region.start < (region[i].start + region[i].length)) &&
- ((new_region.start + new_region.length) > region[i].start)) begin
- return 1;
- end
- end
- return 0;
- endfunction
-
- endclass
-
-
- //你可以通过以下方式使用此类:
- module test_module;
- initial begin
- addr_manager am = new;
-
- // 添加一些测试数据
- am.new_region(3, 5);
- am.new_region(20, 10);
- am.new_region(15, 10); // 这条会检测到重叠并且拒绝
- am.new_region(35, 5); // 正常添加
-
- // 确认区域数据
- foreach(am.region[i]) begin
- $display("Region %0d: Start=%0d, Length=%0d", i, am.region[i].start, am.region[i].length);
- end
- end
- endmodule
- //--------------------------------------------------------------------------------------
- //在此设计中,每次尝试添加新的地址区域能够先检查是否存在重叠。
- //如果检测到重叠,该区域不会被添加到列表中。这样可确保所有地址区域都不会重叠。
- class NonOverlappingMemoryRegionGenerator;
- localparam MAX_ADDRESS = 2**64 - 1; // Max 64-bit address
- localparam MAX_LENGTH = 2**8 - 1; // Max 8-bit length
-
- rand bit [63:0] start_address;
- rand bit [7:0] length;
-
- constraint no_overlap {
- foreach (used_regions[i]) {
- // Check that the new region does not overlap with any existing region
- !(start_address inside {[used_regions[i].start : used_regions[i].end]})
- && !(used_regions[i].start inside {[start_address : start_address + length]});
- }
- }
-
- mailbox #(region_t) used_regions;
-
- typedef struct {
- bit [63:0] start;
- bit [63:0] end;
- } region_t;
-
- function new();
- used_regions = new();
- endfunction
- task generate_memory_region();
- region_t new_region;
- new_region.start = start_address;
- new_region.end = start_address + length - 1;
-
- forever begin
- assert(start_address <= MAX_ADDRESS - length);
- assert(length <= MAX_LENGTH);
-
- if (!used_regions.try_put(new_region)) break;
- else begin
- $display("Overlap detected, retrying...");
- `uvm_info(get_type_name(), "Overlap detected, retrying...", UVM_LOW)
- end
- end
- endtask
- task get_used_regions(ref region_t regions[$]);
- region_t region;
- while (used_regions.try_get(region)) begin
- regions.push_back(region);
- end
- endtask
-
- endclass
在这个类中:
•MAX_ADDRESS 和 MAX_LENGTH 定义了最大地址和最大长度的值。
•类成员变量 start_address 和 length 分别用于存储随机生成的起始地址和长度,它们被声明为 rand 类型,以便进行随机化。
•no_overlap 约束确保新生成的内存区域与已使用的区域没有重叠。这通过遍历 used_regions 邮箱中的所有已使用区域,并检查新区域是否在其范围内,以及已使用区域是否在新区域范围内来实现。
•used_regions 是一个 mailbox 类型的变量,用于存储已生成且无重叠的内存区域。每个区域由自定义结构体 region_t 表示,包含起始地址和结束地址。
•构造函数 new() 初始化 used_regions 邮箱。
•generate_memory_region() 任务负责生成新的内存区域。它首先计算新区域的起始和结束地址,然后尝试将新区域放入 used_regions 邮箱。如果放入成功(即无重叠),则跳出循环;否则,继续尝试生成新的随机地址和长度。
•get_used_regions() 任务用于获取当前所有已生成且无重叠的内存区域,将它们存入传递的参考参数数组 regions 中。使用此类时,只需实例化一个 NonOverlappingMemoryRegionGenerator 对象,然后调用其 generate_memory_region() 任务即可生成新的不重叠内存区域。如需查看已生成的所有区域,可调用 get_used_regions() 任务并传入一个空数组来接收这些区域信息。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。