原创 基于VMM的寄存器抽象层验证

2009-12-16 22:54 3395 15 15 分类: FPGA/CPLD

本文介绍了Synopsys公司推出的基于VMM的寄存器抽象层验证技术和方案,简称RAL(Register Abstraction Layer)。该技术是Synopsys针对芯片验证中如何简便、高效地完成寄存器/存储器相关的验证任务这一问题而开发的解决方案。该方案构建在 Synopsys的VMM验证方法基础上,使用了VMM中的通用技术,可以在VMM的验证环境中非常方便地集成和重用。

  本文首先简述了在芯片验证中和寄存器/存储器相关的任务需求,然后介绍RAL的基本结构和相关模块,随后介绍如何在VMM的验证环境中集成RAL,最后介绍如何通过RAL完成验证过程中各种实际任务。本文中所有实例的源代码均采用SystemVerilog硬件描述验证语言。


图1RAL的基本结构




  验证需求

  和寄存器/存储器相关的验证任务主要包括两类,一类是对寄存器/存储器本身功能的验证,寄存器/存储器是芯片中控制和数据的存储场所,决定着芯片能否正常运行,因此,对寄存器/存储器本身的功能的验证,一般是整个验证过程中最先要完成的任务。另一类和寄存器/存储器相关的验证任务,是在对芯片进行其它功能验证的过程中,验证环境需要对寄存



器/存储器进行操作,例如,用写寄存器配置芯片的功能,用读寄存器检查芯片的状态。这类对寄存器/存储器进行操作的任务,是在芯片验证过程中,始终存在并且频繁出现的。

  芯片中的寄存器/存储器具有数量大和不断变化的特点。一般来说,芯片中的寄存器数目往往达到几十个,上百个,甚至近千个,有的芯片有着为数不少的存储器。而且,这些寄存器/存储器的设计规范在不断变化中,甚至在芯片的验证过程中,寄存器/存储器的设计仍在变化。这两个特点使得测试平台对寄存器/存储器的维护十分困难。一旦在设计中增加或减少了寄存器/存储器,或者修改了寄存器字段的长度、位置、属性、初始值、或者修改了存储器的容量、字长等等,工程师就必须在整个验证环境和所有测试文件中,对于发生变化的寄存器/存储器进行相应的修改。这种维护工作是非常繁琐,耗时和容易出错的。

  因此,一方面,和寄存器/存储器相关的验证任务是不可缺少的,频繁出现的;另一方面,测试平台对寄存器/存储器的维护是耗时和容易出错的。这样一来,本可以花在验证更复杂功能上的时间和精力,却被花在相对简单却很耗时的寄存器/存储器维护工作上了。这种矛盾导致了对简便,高效的寄存器/存储器验证解决方案的强烈需求。

  Synopsys正是在这种强烈需求的背景下推出了基于VMM的寄存器/存储器抽象层(RAL)验证解决方案。该方案的中心思想是,在验证环境中的一个特定模型内,进行寄存器/存储器的管理、维护和操作,一旦寄存器/存储器的设计规范发生变化,工程师对验证环境和测试文件的维护修改工作将尽可能地降低到最少的程度。

  基本结构和工作机制

  Synopsys的VMM验证环境是层次化的验证环境,分为指令层(Command Layer)、功能层(Functional Layer)、场景层(Scenario Layer)等,而RAL是隶属于Functional Layer的。RAL的基本结构包含三个部分,分别是RAL模型(RAL Model)、RAL处理器(RAL Transactor)以及RAL访问管理器(RAL Access)。如图1所示。


  ● RAL的各个组成部分

  RAL Model封装了DUT中寄存器/存储器的一切描述信息,是DUT中寄存器/存储器在测试环境中的映射,RAL Model为寄存器保存、维护镜像值。但存储器在RAL Model中是没有镜像值的,这是因为对存储器的存取相对简单,并且存储器较大的存储容量会导致较大的镜像空间,从而大大降低模拟效率。

  RAL Transactor负责把RAL Transaction转换为Command Layer Transaction并传递给Command Layer中的BFM。

  RAL Access负责管理RAL Model和RAL Transactor之间的交互,它将RAL Model中的操作封装为一个RAL Transaction传递给RAL Transactor,并根据这个Transaction完成后的结果或状态,更新RAL Model中的数据信息。

  BFM并不属于RAL的范畴,它是VMM测试环境中Command Layer的一个模块,负责将Command Layer Transaction驱动到DUT接口上实际的高低电平逻辑信号。


  ● RAL的工作机制

  测试平台对RAL Model进行的操作,会映射到对DUT内寄存器/存储器的操作。这种操作通过RAL Access,封装在RAL Transaction中,传递到RAL Transactor, RAL Transactor又将这个Transaction翻译为Command Layer的Transaction,传递给BFM,BFM将这个Transaction按照DUT的接口协议和时序,驱动DUT接口上的信号,实现对 DUT内部寄存器/存储器的存取访问。RAL Access根据这个操作的结果和状态,维护RAL Model中的数据信息。


● RAL的实现

  Synopsys VMM的验证环境是基于面向对象编程方法开发的,因此,RAL是通过一系列的类(Class)来实现的。RAL库提供了一系列的类,最大限度地封装寄存器/存储器相关的通用的数据结构和方法,由此节省用户开发寄存器/存储器验证环境的工作量,而用户只需要通过扩展RAL库中的基类来定义自己所需的类,添加待测芯片中的寄存器/存储器的特定信息。


  ● 用RALF文件生成RAL Model

  虽然RAL库提供了封装寄存器/存储器描述信息的一系列的基类,但和特定的待测芯片相关的寄存器/存储器的设计规范,必须由用户添加在各个RAL基类扩展而得的子类中。用户必须对待测芯片中的每个寄存器字段,每个寄存器,每个存储器,以及由寄存器/存储器构成的集合,通过扩展相应的基类来定义新的




类,从而封装它们的设计规范信息。这个过程是比较繁琐和耗时的。

  为了最大限度节省工程师的工作量,在Synopsys RAL验证解决方案中,RAL Model不需要由用户来实现,而是由RAL模型生成器(简称ralgen)根据用户编写的RAL格式文件(采用.ralf为后缀名)自动生成的。用户只需要按照简明的RAL格式编写寄存器/存储器设计规范文件,再交给ralgen工具,就可自动生成RAL Model所需的所有的扩展类。

  验证环境集成

  将RAL集成在VMM验证环境中,只需要以下四个步骤:
  第一步,构建Command Layer中和DUT的寄存器/存储器访问有关的Data, Channel和BFM的类。
  第二步,按照寄存器/存储器设计规范,编写RALF文件,然后用ralgen工具生成RAL Model。
  第三步,构建RAL Transactor,实现RAL和CommandLayer间Transaction的翻译。
  第四步,构建顶层验证环境,该环境包含图1中所示的RAL Access、RAL Model和RAL Transactor。在验证环境的build()过程中,简化上述对象,并将RAL Model和RAL Transactor和RAL Access关联起来。最后在hw_reset()过程中,实现对DUT的reset。注意,在vmm_ral_env中,无需扩展reset_dut (),而只要扩展hw_reset(),而reset_dut()会自动调用hw_reset()。

 
  实际应用

  在将RAL集成到VMM验证环境中以后,我们就可以在测试代码中实现各种测试任务所要求的和寄存器/存储器有关的操作。这里举例说明一些最常用的应用。用户可根据自己的验证要求,利用RAL实现更多更复杂的功能。


  1.查询寄存器/存储器

  RAL Model封装了寄存器/存储器的设计规范。测试平台可以在该模型中查询寄存器/存储器信息。例如,查找所有的或特定名称/地址的寄存器,查询某个字段的长度,访问模式,查询某个存储器的容量等。这样就使得验证工程师在寄存器/存储器设计规范确定之前,或在设计规范不断变化时,仍能进行测试平台的开发,并且在寄存器/存储器设计规范发生变化时,仅仅需要重新生成RAL Model,而不需要修改先前开发的测试代码。下面是一些查询寄存器/存储器的实例。

  ● 查找所有寄存器/存储器(工程师不用关心寄存器设计规范如何,便能实现对所有寄存器/存储器的全面检查)

  vmm_ral_reg regs[];
  vmm_ral_mem mems[];
  env.ral_model.get_registers(regs);
  env.ral_model.get_memories(mems);

  ● 按名称查找寄存器或字段(工程师不用关心寄存器在哪个地址,或者字段在哪个寄存器,便能定位该寄存器或字段)

  vmm_ral_reg my_reg;
  my_reg = env.ral_model.get_reg_by_name(“myRegName”);
  vmm_ral_field my_fld;
  my_fld = env.ral_model.get_field_by_name(“myFldName”);


  ● 查询寄存器/存储器或字段的各种属性,例如字节数,比特数,访问模式等。

  int byte_count, bit_count;
  byte_count = my_reg.get_n_bytes();
  bit_count = my_fld.get_n_bits();
  vmm_ral::access_e access_mode;
  access_mode = my_fld.get_access();
  int mem_size, bits_per_loc;
  mem_size = my_mem.get_size();
  bits_per_loc = my_mem.get_n_bits();


 2.写单个字段

  一般来说,芯片中可配置的最小单位是字段,而可访问的最小单位是寄存器。这样就会导致工程师需要写一个字段而不修改其它字段时,就不得不想办法去了解这个字段所在寄存器的其他字段是什么,当前值是什么,以便写入当前值以维持其值不变,这个过程有时会很困难。而在RAL验证方案中,工程师只需关心需要被写的字段,RAL Model会完全自动管理其他字段。因为RAL Model管理着寄存器的镜像,它利用镜像来决定那些不期望被修改的字段值。

  对于在RAL Model中名称唯一的字段,可以通过block.register.field来引用,也可以直接通过block.field来引用;而对于在RAL Model中名称不唯




一的字段(例如在RALF文件中,不同的寄存器中相同名称的字段),只能通过block.register.field来引用。

  VMM_rw::status_e status;
  env.ral_model.myFldName.write(status, 4’h1);
  或者env.ral_model.myRegName.myFldName.write(status, 4’h1);
  其中,“myRegName”,“myFldName”是在RALF文件中定义的寄存器和字段名称。

  3.写多个字段

  在配置芯片时,往往需要配置大量字段。如果像上例那样调用write(),就会造成对寄存器的重复写操作。例如两个字段同属一个寄存器,如果对这两个字段都调用write(),那么对同一寄存器就会有两次写的操作。这种重复操作会降低模拟效率。我们推荐“先设置RAL Model中各字段的镜像值,然后再将镜像值写入芯片”的方式来配置芯片。设置RAL Model中各字段的镜像值,就是对字段调用set()方法;而将镜像值写入芯片,就是对寄存器或整个模型调用update()方法。通过这种方式,可以避免验证环境产生重复和多余的寄存器写操作。

  vmm_rw::status_e status;
  env.ral_model.myFldName1.set(7'h3F);
  env.ral_model.myFldName2.set(4'h7);
  env.ral_model.myFldName3.set(8'hAB);
  env.ral_model.myRegName.update(status);
  或者env.ral_model.update(status);

  4.读某个字段或寄存器

  调用read()就可以进行读操作并取得该字段或寄存器的值。

  vmm_rw::status_e  status;
  bit[63:0] value;
  env.ral_model.myFldName.read(status, value);
  env.ral_model.myRegName.read(status, value);


  5.更新镜像值

  RAL Model能根据测试平台对寄存器的操作来维护其镜像值,但如果寄存器是被DUT内部逻辑更新的,RAL Model便无法探测并对镜像值进行这一更新。所以需要读取寄存器并更新镜像值。可以对字段,寄存器或者整个模型来更新镜像值。

  vmm_rw::status_e  status;
  env.ral_model.myFldName.mirror(status);
  env.ral_model.myRegName.mirror(status);
  env.ral_model.mirror(status);


  6.读取并检查字段的值

  检查字段的值,是将镜像值作为期望值,读取该字段的值,和期望值比较。如果不同,就会产生出错信息。同样调用mirror(),但其check参数的值为vmm_ral::VERB。

  vmm_rw::status_e  status;
  env.ral_model.myFldName.mirror(status, vmm_ral::VERB);

  如果当前镜像值不是期望值,我们需要将期望值设置到镜像中。有两种方式,一种是predict(),无条件地将镜像值强制设置为指定值;一种是set(),按照字段的访问模式设置为指定值。例如,如果字段为只读属性,则镜像值就不会被改变。
  vmm _rw::status_e  status;
  env.ral_model.myFldName.predict(4’hF);
  或者env.ral_model.myFldName.set(4’hF);
  env.ral_model.myFldName.mirror(status, vmm_ral::VERB);


 7.组合基本应用,实现更复杂的测试任务

  例如,将“查询”和“检查”组合起来,可以全面检查所有寄存器来验证reset值是否正确。

  env.reset_dut();
  env.ral_model.reset();
  // Iterate over all registers, checking the reset values
  VMM_ral_reg regs[];
  env.ral_model.get_registers(regs);
  foreach (regs) begin
      vmm_rw::status_e status;
    &nb



sp;  regs.mirror(status, vmm_ral::VERB);
       if (status != vmm_rw::IS_OK) `vmm_error(…);
       else `vmm_note(…);
  end

  8.读写存储器

  存储器具有规则结构,而且在RAL Model中没有镜像值,所以,对存储器的操作比较简单,主要就是调用read()和write()方法读写存储器中的某个指定地址的存储单元。

  vmm_rw::status_e status;
  bit[63:0] value;
  env.ral_model.myMem.read(status, 0x1000, value);
  env.ral_model.myMem.write(status, 0x1000, 8’hAF);


  总结

  Synopsys基于VMM的寄存器抽象层(RAL)验证解决方案为验证工程师提供了快速、高效实现寄存器/存储器验证任务的途径,它可以满足实际验证项目中关于寄存器/存储器的验证需求。同时RAL也在根据新的需求不断发展中,力争为验证工程师提供更完善更便捷的寄存器/存储器验证解决方案。


http://www.51kaifa.com/html/jswz/200708/read-8263.htm

文章评论0条评论)

登录后参与讨论
我要评论
0
15
关闭 站长推荐上一条 /2 下一条