IC验证学习笔记(AHB-RAM)08addr、bsize都随机,主要做地址偏移操作

news2024/11/26 5:25:40

rkv_ahbram_haddr_word_unaligned_virt_seq:

 对addr和bsize都随机化操作

`ifndef RKV_AHBRAM_HADDR_WORD_UNALIGNED_VIRT_SEQ_SV
`define RKV_AHBRAM_HADDR_WORD_UNALIGNED_VIRT_SEQ_SV


class rkv_ahbram_haddr_word_unaligned_virt_seq extends rkv_ahbram_base_virtual_sequence;
  `uvm_object_utils(rkv_ahbram_haddr_word_unaligned_virt_seq)

  function new (string name = "rkv_ahbram_haddr_word_unaligned_virt_seq");
    super.new(name);
  endfunction

  virtual task body();
    bit [31:0] addr, data;
    burst_size_enum bsize;
    super.body();
    `uvm_info("body", "Entered...", UVM_LOW)
    for(int i=0; i<100; i++) begin
      std::randomize(bsize) with {bsize inside {BURST_SIZE_8BIT, BURST_SIZE_16BIT, BURST_SIZE_32BIT};};
      std::randomize(addr) with {addr inside {['h1000:'h1FFF]};
                                 bsize == BURST_SIZE_16BIT -> addr[0] == 0;//为了地址对齐
                                 bsize == BURST_SIZE_32BIT -> addr[1:0] == 0;
                                };
      std::randomize(wr_val) with {wr_val == (i << 24) + (i << 16) + (i << 8) + i;};//使每一个byte位都有数据
      data = wr_val;
      `uvm_do_with(single_write, {addr == local::addr; data == local::data; bsize == local::bsize;})
      `uvm_do_with(single_read, {addr == local::addr; bsize == local::bsize;})
    end
    `uvm_info("body", "Exiting...", UVM_LOW)
  endtask

endclass


`endif 

monitor获取过来原始数据给scb;但是scoreboard没有做地址对齐,需要修改

问题在于:按之前的情况如果存入`h10=`hFFAABBCC;

                  之后如果在`h11中存入`h11=`hEE;

                  则输出保存的结果为`h10`=`hFFAAEECC;会被覆盖掉

所以要做地址操作,保证传输过来的数据都被保存在scoreboard中:

`ifndef RKV_AHBRAM_SCOREBOARD_SV
`define RKV_AHBRAM_SCOREBOARD_SV

class rkv_ahbram_scoreboard extends rkv_ahbram_subscriber;

  // events of scoreboard
  bit [31:0] mem [int unsigned];

  // typedef enum {CHECK_LOADCOUNTER} check_type_e;
  `uvm_component_utils(rkv_ahbram_scoreboard)

  function new (string name = "rkv_ahbram_scoreboard", uvm_component parent);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
  endfunction

  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    do_data_check();
  endtask

  virtual function void write(lvc_ahb_transaction tr);
    if(is_addr_valid(tr.addr)) begin
      case(tr.xact_type)
        WRITE : store_data_with_hburst(tr);
        READ  : check_data_with_hburst(tr);
      endcase
    end
  endfunction

  task do_listen_events();
  endtask

  virtual task do_data_check();
  endtask

  function bit is_addr_valid(bit [31:0] addr);
    if(addr >= cfg.addr_start && addr <= cfg.addr_end)
      return 1;
  endfunction

  function void store_data_with_hburst(lvc_ahb_transaction tr);
    // TODO implementation in child class
    case(tr.burst_type)
      SINGLE: begin 
                store_data_with_hsize(tr, 0);
              end
      INCR  : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      WRAP4 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      INCR4 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      WRAP8 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      INCR8 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      WRAP16: begin `uvm_error("TYPEERR", "burst type not supported yet") end
      INCR16: begin `uvm_error("TYPEERR", "burst type not supported yet") end
      default: begin `uvm_error("TYPEERR", "burst type not defined") end
    endcase
  endfunction

  function bit check_data_with_hburst(lvc_ahb_transaction tr);
    // TODO implementation in child class
    case(tr.burst_type)
      SINGLE: begin 
                check_data_with_hburst = (check_data_with_hsize(tr, 0));
              end
      INCR  : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      WRAP4 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      INCR4 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      WRAP8 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      INCR8 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
      WRAP16: begin `uvm_error("TYPEERR", "burst type not supported yet") end
      INCR16: begin `uvm_error("TYPEERR", "burst type not supported yet") end
      default: begin `uvm_error("TYPEERR", "burst type not defined") end
    endcase
    if(check_data_with_hburst)
      `uvm_info("DATACHK", $sformatf("ahbram[%0x] hburst[%s] is as expected", tr.addr, tr.burst_type), UVM_HIGH)
    else
      `uvm_error("DATACHK", $sformatf("ahbram[%0x] hburst[%s] is NOT as expected", tr.addr, tr.burst_type))
  endfunction

  function void store_data_with_hsize(lvc_ahb_transaction tr, int beat);
    case(tr.burst_size)//1:0位不管补0,地址最少相差4字节往里写,不会有覆盖现象
      BURST_SIZE_8BIT   : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);//mem接收到偏移处理后的mdata
      BURST_SIZE_16BIT  : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);
      BURST_SIZE_32BIT  : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);
      BURST_SIZE_64BIT  : begin `uvm_error("TYPEERR", "burst size not supported") end
      default : begin `uvm_error("TYPEERR", "burst size not supported") end
    endcase
  endfunction

  function bit check_data_with_hsize(lvc_ahb_transaction tr, int beat);
    bit[31:0] tdata = extract_valid_data(tr.data[beat], tr.addr, tr.burst_size);
    bit[31:0] mdata = extract_valid_data(mem[{tr.addr[31:2],2'b00}],  tr.addr, tr.burst_size);
    check_data_with_hsize = tdata == mdata ? 1 : 0;
    cfg.scb_check_count++;
    if(check_data_with_hsize)
      `uvm_info("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x = actual 'h%0x", tr.addr, mdata, tdata), UVM_HIGH)
    else begin
      cfg.scb_check_error++;
      `uvm_error("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x != actual 'h%0x", tr.addr, mdata, tdata))
    end
  endfunction

  function bit [31:0] extract_current_beat_mem_data(lvc_ahb_transaction tr, int beat);//数据进行偏移处理
    bit [31:0] mdata = mem[{tr.addr[31:2],2'b00}];
    bit [31:0] tdata = tr.data[beat];//存入data
    case(tr.burst_size)	//8BIT mdata如果addr为0存放在7:0位,addr为1存放在15:8位,addr为2存放在23:16位,addr为3存放在31:24位
      BURST_SIZE_8BIT   : mdata[(tr.addr[1:0]*8 + 7) -:  8] = tdata >> (8*tr.addr[1:0]);//不管tdata多少位只拾取低八位
	  //16BIT mdata如果addr[1]为0tdata存放在16:0位,addr[1]为1存放在31:17位
      BURST_SIZE_16BIT  : mdata[(tr.addr[1]*16 + 15) -: 16] = tdata >> (16*tr.addr[1]);
      BURST_SIZE_32BIT  : mdata = tdata;
      BURST_SIZE_64BIT  : begin `uvm_error("TYPEERR", "burst size not supported") end
      default : begin `uvm_error("TYPEERR", "burst size not supported") end
    endcase
    return mdata;//输出mdata给mem
  endfunction

endclass

`endif 

代码分解:write操作存入mem

 function void store_data_with_hsize(lvc_ahb_transaction tr, int beat);
    case(tr.burst_size)//1:0位不管补0,如195d和195e都写在同一地址195c,但是不同偏移量
      BURST_SIZE_8BIT   : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);//mem接收到偏移处理后的mdata
      BURST_SIZE_16BIT  : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);
      BURST_SIZE_32BIT  : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);
      BURST_SIZE_64BIT  : begin `uvm_error("TYPEERR", "burst size not supported") end
      default : begin `uvm_error("TYPEERR", "burst size not supported") end
    endcase
  endfunction

function bit [31:0] extract_current_beat_mem_data(lvc_ahb_transaction tr, int beat);//数据进行偏移处理
    bit [31:0] mdata = mem[{tr.addr[31:2],2'b00}];
    bit [31:0] tdata = tr.data[beat];//存入data
    case(tr.burst_size)	//8BIT mdata如果addr为0存放在7:0位,addr为1存放在15:8位,addr为2存放在23:16位,addr为3存放在31:24位
      BURST_SIZE_8BIT   : mdata[(tr.addr[1:0]*8 + 7) -:  8] = tdata >> (8*tr.addr[1:0]);//不管tdata多少位只拾取低八位
	  //16BIT mdata如果addr[1]为0tdata存放在16:0位,addr[1]为1存放在31:17位
      BURST_SIZE_16BIT  : mdata[(tr.addr[1]*16 + 15) -: 16] = tdata >> (16*tr.addr[1]);
      BURST_SIZE_32BIT  : mdata = tdata;
      BURST_SIZE_64BIT  : begin `uvm_error("TYPEERR", "burst size not supported") end
      default : begin `uvm_error("TYPEERR", "burst size not supported") end
    endcase
    return mdata;//输出mdata给mem
  endfunction

        为了防止出现覆盖,mem中存放的地址为写入地址的后两位取0,如195d和195e都在同一地址195c,但是具有不同偏移量。(先地址统一再进行偏移存放)

在8BIT中,如果后两位地址为0,则数据存放在mem的7:0位;

                  如果后两位地址位1,则数据存放在mem的15:8位;

                  如果后两位地址为2,则数据存放在mem的23:16位;

                  如果后两位地址为3,则数据存放在mem的31:24位;

在16BIT中,如果addr[1]为0,则数据存放在mem的15:0位;

                    如果addr[1]为1,则数据存放在mem的31:16位;

例子:

        195d 8BIT 数据02020202

               地址统一为195c开始存放,后两位地址为1,则存放在15:8位,为00000200;

        195e 16BIT 数据03030303

              地址统一为195c开始存放,后两位地址为3,则存放在31:16位,为03030200;

        113c 16BIT 数据04040404

              地址统一为113c开始存放,后两位地址为0,则存放在15:0位,为00000404

        17f3 8BIT   数据05050505:

              地址统一为17f0开始存放,后两位地址为3,则存放在31:24位,为05000000;

read:check_data

function bit check_data_with_hsize(lvc_ahb_transaction tr, int beat);
    bit[31:0] tdata = extract_valid_data(tr.data[beat], tr.addr, tr.burst_size);
    bit[31:0] mdata = extract_valid_data(mem[{tr.addr[31:2],2'b00}],  tr.addr, tr.burst_size);
    check_data_with_hsize = tdata == mdata ? 1 : 0;
    cfg.scb_check_count++;
    if(check_data_with_hsize)
      `uvm_info("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x = actual 'h%0x", tr.addr, mdata, tdata), UVM_HIGH)
    else begin
      cfg.scb_check_error++;
      `uvm_error("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x != actual 'h%0x", tr.addr, mdata, tdata))
    end
  endfunction
function bit [31:0] extract_valid_data([`LVC_AHB_MAX_DATA_WIDTH - 1:0] data
                                        ,[`LVC_AHB_MAX_ADDR_WIDTH - 1 : 0] addr
                                        ,burst_size_enum bsize);
  
    case(bsize)
      BURST_SIZE_8BIT   : return (data >> (8*addr[1:0])) & 8'hFF;
      BURST_SIZE_16BIT  : return (data >> (16*addr[1]) ) & 16'hFFFF;
      BURST_SIZE_32BIT  : return data & 32'hFFFF_FFFF;
      BURST_SIZE_64BIT  : begin `uvm_error("TYPEERR", "burst size not supported") end
      default : begin `uvm_error("TYPEERR", "burst size not supported") end
    endcase
  endfunction

将监测的读数据与mem的数据都进行函数extract_valid_data处理:

如读回来195d中的数据应为00000200;右移8位并&FF得到00000002;             

    mem中195d地址统一为195c,其中数据为03030200(有195e的16bit0303);右移8位 并&FF得到00000002 

        最后两个数进行对比,结果相同;                       

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/538889.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入探讨桥梁建筑中地质工程与仪器仪表应用

近期&#xff0c;随着桥梁建筑行业的不断发展&#xff0c;地质工程与仪器仪表应用成为了热议的话题。在桥梁、建筑、水利工程等领域&#xff0c;渗压计、MCU自动化测量单元、应变计、测缝计、固定测斜仪等各种先进的仪器仪表技术正在广泛应用&#xff0c;为工程施工和监测提供了…

什么是pytest自动化测试框架?如何安装和使用呢?赶快收藏起来

一、pytest是什么&#xff1f; pytest是一款强大的Python测试工具&#xff0c;可以胜任各种类型或级别的软件测试工作。实际上&#xff0c;越来越多的项目在使用pytest。因为pytest会提供更丰富的功能&#xff0c;包括assert重写、第三方插件&#xff0c;以及其他测试工具无法比…

116.【SpringBoot和Vue结合-图书馆管理系统】

前后端分离 (一)、SpringBootVue概述1.基本概述2.实现技术 (二)、Vue3.x搭建 (SpringBootVue)1.搭建Vue基本环境(1).搭建Vue项目框架(2).介绍Vue项目内容 2.搭建SpringBoot基本环境(1).创建SpringBootTest项目(2).初始化项目(3).测试SpringBoot的控制层 3.通过路由跳转访问组件…

Python+selenium自动化元素定位防踩坑

在自动化UI测试过程中常常会在元素定位阶段就踩坑&#xff0c;碰到困扰已久的问题。 以下是个人整理元素定位报错原因和解决方法。 踩坑一&#xff1a;StaleElementReferenceException selenium.common.exceptions.StaleElementReferenceException: Message: stale element re…

JavaScrip 中的 this, bind, call apply 简述

JavaScrip 中的 this, bind, call & apply 简述 this 是一个比较特殊的东西&#xff0c;基本上可以理解成 this 的指向是就近调用的指向&#xff0c;因此 this 在 JS 中也是一个比较令人困惑的知识点。 之前绕过 this 的方法基本上采用 arrow function&#xff0c;因为 a…

35、Adaptive Forms(3)Data Model

文章目录 35、Adaptive Forms&#xff08;3&#xff09;Data Model配置JDBC安装mysql-connector-j.jar在数据库中创建数据创建Data Model 35、Adaptive Forms&#xff08;3&#xff09;Data Model 在使用Mysql数据之前还需要在AEM中创建DataModel映射数据库的数据结构。也需要…

07-架构2023版-centos+docker部署nacos

1、创建nacos的数据库配置 1.1、创建数据库 1.2、创建用户nacos并授权数据库 参考 06 mysql 创建账户部分内容 1.3、执行数据库脚本 导入官方nacos sql语句。如果是历史有历史数据&#xff0c; 从历史数据sql导入 2、创建 bridge 网络并指定 IP 区间 2.1、创建自定义网络…

选择排序:20年前在谭浩强《c语言程序设计上》学习过(43)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 今日主题 什么是选择排序&#xff1f; 用Python写段代码&#xff0c;实现插入排序。 选择排序 选择排序是一种简单的排序算…

Contrastive Learning

https://towardsdatascience.com/understanding-contrastive-learning-d5b19fd96607 The Beginner’s Guide to Contrastive Learning Contrastive Representation Learning | LilLog

Visual Studio 怎样设置断点并调试

1-普通断点 设置普通断点的方法很简单&#xff0c;就是在代码行的左边栏灰色区域点击或者把光标放在某代码行&#xff0c;按下 F9。 2-调试 按F5开始调试&#xff0c;按F11是逐行调试&#xff0c;F10是逐过程调试&#xff0c;shiftF5是停止调试。 3-高级调试 见链接&#x…

学系统集成项目管理工程师(中项)系列22b_信息化知识(中)

1. 信息化 1.1. 产品信息化 1.1.1. 信息化的基础 1.2. 企业信息化 1.2.1. 国民经济信息化的基础 1.3. 产业信息化 1.3.1. 【21下选08】 1.4. 国民经济信息化 1.5. 社会生活信息化 1.6. 【22上选08】 1.7. 基本内涵 1.7.1. 信息化的主体是全体社会成员&#xff0c;包…

日语文法PPT截图16-30

16句子的构成 单句 谓语只出现了一次 重句 两个谓语 并且两个谓语是对应的关系 由多个在意义上有差距的小句共同构成的句子 叫复文 用一个句子去修饰一个名词 也是个很典型的复文 被名词化了的句子充当小句&#xff0c;这也是复文的一种情况 引用形式的复文 对于这种复文的…

Java-API简读_java.util.RandomAccess接口(基于JDK1.8)(不涉及源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/130727525 出自【进步*于辰的博客】 其实我的【Java-API】专栏内的博文对大家来说意义是不大的。…

史上最详细的SQL盲注入门教程

测试同学在做安全测试时&#xff0c;相信多少都会遇到SQL注入与盲注的漏洞&#xff0c;那么今天我们就来分享下SQL注入与盲注的相关知识&#xff0c;希望对大家有所启发。 一、SQL盲注的定义 SQL注入&#xff0c;简单理解&#xff0c;也就是将用户输的的内容当代码执行了&…

Docker的使用 (1.安装docker)

安装docker前非常重要的准备工作 请保证你的centos 操作系统为至少为7版本请关闭linux的防火墙虚拟机联网&#xff0c;安装好yum工具 安装docker # 设置docker镜像源 yum-config-manager \--add-repo \https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.reposed…

Aqua 启动管道完整性扫描以检测恶意软件

云原生安全提供商 Aqua Security 已宣布添加管道完整性扫描&#xff0c;以防止软件供应链攻击并确保 CI/CD 管道完整性。 在 eBPF 技术的支持下&#xff0c;Aqua 的管道完整性扫描器实时检测并阻止可疑行为和恶意软件&#xff0c;防止代码篡改并应对软件构建过程中的威胁。 该…

Spring Boot异常处理

目录 Spring Boot异常处理 介绍 拦截器VS 过滤器 自定义异常页面 自定义异常页面 代码实战 需求 代码实现 创建MyErrorController类来模拟异常错误 完成测试 全局异常 说明 全局异常-应用实例 创建GlobalExceptionHandler.java 创建对应的视图地址global.html 完成…

Docker的使用 (1.什么是docker)

前言 这个系列是我自己学习使用docker的记录和分享&#xff0c;作为一名开发人员&#xff0c;你需要了解这个东西并且学会它的简单使用&#xff0c;但是作为一名开发而不是运维&#xff0c;不要花过多的时间去深究它的原理&#xff0c;而是把它当作一个工具即可 docker Docke…

新的RA Group勒索软件针对美国组织进行双重勒索攻击

一个名为“RA Group”的新勒索软件组织针对美国和韩国的制药、保险、财富管理和制造公司。 新的勒索软件行动始于 2023 年 4 月&#xff0c;当时他们在暗网上启动了一个数据泄露站点&#xff0c;以发布受害者的详细信息和被盗数据&#xff0c;采用了大多数勒索软件团伙使用的典…

1.2 Kubernetes架构组件

1.2 Kubernetes架构组件 学习Kubernetes的架构组件&#xff0c;也就是说我们要搭建一个Kubernetes集群里面应该有哪些组成部分&#xff0c;里面具体会有哪些组件。如图 组建一个Kubernetes的集群至少需要包含两个部分&#xff0c;即Master和node&#xff0c;Master即主控节点&…