平头哥数字电路验证(DV)专家面试题收录

平头哥数字电路验证(DV)专家面试题收录

#平头哥芯片设计
##一面(视频面试)

一、SystemVerilog基础,constraint问题

       一个64位的起始地址和一个8位的长度,需要随机这两个变量,让每次随机出来的地址空间都和之前的任意一次都没有重叠。例如第一次地址是3,长度是5,第二次地址是20,长度是10,这样就可以,但是第三次如果随机出来地址是15,长度是10就不行。因为和第二次有一部分是重叠的。请问这样的class该怎么设计?

1.1 方案一

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
//--------------------------------------------------------------------------------------
//在此设计中,每次尝试添加新的地址区域能够先检查是否存在重叠。
//如果检测到重叠,该区域不会被添加到列表中。这样可确保所有地址区域都不会重叠。

1.2 方案二

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() 任务并传入一个空数组来接收这些区域信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

元直数字电路验证

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值