[SystemVerilog语法拾遗] SystemVerilog中的宏使用详解

systemverilog 宏定义 `define 本文首先记录了在systemverilog中,标准文档对于宏定义的描述,以及几个特殊符号的使用;其次,着重介绍了带参数的宏的使用,解决了如何将变量作为一个参数传递给宏,并通过一个例子,演示了这样做带来的好处。 阅读详情
AI摘要

本文详细介绍了SystemVerilog中宏的使用。阐述了宏的定义、使用原因,说明了宏语法规范,包括宏名称规则、常用符号(反引号、双引号等)的使用,还提及宏的参数传递、风格指引等内容,强调使用宏要谨慎,避免影响代码可读性。

[SystemVerilog语法拾遗] SystemVerilog中的宏使用详解

引言

刚刚写了一篇 数字验证大头兵:[SystemVerilog语法拾遗] 宏函数实例讲解,本想着过一段时间再好好研究研究宏函数的语法再写一篇详细点的解析文档,奈何求知欲过于强烈的我还是决定现在就好好研究下宏函数的语法,正巧看到一篇写的不错的宏函数讲解文章,这里就用我有限的英文翻译水平加之对宏函数的一点理解共享给大家,原文链接如下:SystemVerilog Macros - SystemVerilog.io
下面是全文翻译

前言

合理的使用宏可以大大简化我们在使用SystemVerilog编写代码的工作量,如果你不熟悉宏的使用,不仅降低写代码的效率,同时在阅读别人写的代码时也会产生诸多困惑,这里的例子将揭开, ", \"这些宏中常用的符号的含义以及如何使用它们的神秘面纱。
我们还将探索UVM源代码中的一些宏,并建立编写宏的风格指南。
在我们开始之前有一个警告:过度使用宏可能会导致代码可读性降低,所以使用宏一定要尽可能的再简化代码的前提下不要因为对代码的过度封装而影响其可读性。
本文中涉及到的所有代码示例都可以从下面的链接下载使用:All code presented here can be downloaded from GitHub

介绍

什么是宏?

宏是使用define编译器指令创建的代码段。它们主要包含三部分:名称、文本和可选参数,如下所示。

`define macroname(ARGS) macrotext

在编译预处理阶段,代码中每次出现`macroname都会替换为字符串macrotext,ARGS是可以在macrotext中使用的变量。

为什么要使用宏?

在编写测试平台和测试用例时,有时候会重复使用某些代码段,如下所示。

//1
for (int ii=0; ii<numbytes; ii++) begin
    if ((ii !=0) && (ii % 16 == 0))
        $display("\n");
    $display("0x%x ", bytearray[ii]);
end 
//2
for (int ii=20; ii<100; ii++) begin
    if (ii % 16 == 0)
        $display("\n");
    $display("0x%x ", pkt[ii]);
end

代码段1和2有着高度的相似性,我们可以从中提取公共部分辅之以参数化的形式将其抽象成如下所示的宏,从而大大简化了代码量,并且后期如果需要更改其中的打印控制只需修改一处就可以了。

`define print_bytes(ARR, STARTBYTE, NUMBYTES) \
    for (int ii=STARTBYTE; ii<STARTBYTE+NUMBYTES; ii++) begin
        if ((ii != 0) && (ii % 16 == 0))
            $display("\n");
        $display("0x%x ", ARR[ii]);
    end

// When someone reads this code, they'll know
// it prints a formatted array of bytes
`print_bytes(bytearray, 0, numbytes)
`print_bytes(pkt, 20, 80)

我喜欢使用宏,尤其是用于特殊的打印功能,而`uvm_info是不够的。如果您的所有团队成员都使用这个宏,那么就统一了团队的打印风格,这样使得每个人都更容易阅读log信息。
以下是使用宏的推荐方法:
您和您的团队可以建立一个宏库
对此库中的宏使用特定的命名规则,例如<*>_utils(print_byte_utils等)。
将其放入名为macro_utils.sv的文件中,并将其包含在一个公共包中
在设计/验证需要的场景中导入这个宏文件,避免重复造轮子的情况
以上便是宏存在的价值。

宏语法规范

宏名称

宏名称的唯一规则是,除编译器指令外,您可以使用任何名称,即不能使用关键字,如“define”、“ifdef”、“endif”、“else”、”elseif“、”include“等。如果你最终错误地使用了编译器指令,你会得到如下错误提示。

Mentor Graphics Questa
----------------------
    ** Error: macros_one.sv(4): (vlog-2264) Cannot redefine compiler directives:
    `include.

Synopsys VCS
------------
    Error-[IUCD] Illegal use of compiler directive
      Illegal use of compiler directive: `include is illegal in this context.
      "macros_one.sv", 28
      Source info:         $display(`include(clock));

此外,宏的作用域为“全局”的,宏的使用只跟编译顺序有关,一旦在某个某件中定义了宏,随后编译的文件中都可以使用这个宏,不管这个宏是定义在在类内还是在类外。一旦编译器获取了一个定义,它就可以在任何地方使用。如果你重新定义宏,你会得到如下错误提示。

** Warning: macros2.sv(7): (vlog-2263) Redefinition of macro: 
    'debug' (previously defined near macros2.sv(3)) .

    Parsing design file 'macros4.sv'

    Warning-[TMR] Text macro redefined
    macros2.sv, 7
      Text macro (debug) is redefined. The last definition will override previous 
      ones.
      In macros2.sv, 3, it was defined as $display("%s, %0d: %s", `__FILE__, 
      `__LINE__, msg)

反引号——``, ", `"

常用的符号主要有三类。
1、反引号和双引号 " 如果宏文本用双引号“ 括起来,它本质上就是一个字符串。双引号内的参数不会被替换,如果宏文本嵌入了其他宏,它们也不会展开。如果在双引号前面加一个反引号,那么双引号的意义就被替换了,使得宏在展开时需要遵循以下原则:
包含双引号"与"
两个双引号内的参数需要被替换
两个双引号内嵌入的宏都应该展开
我们看下面这个例子

/* Example 1.1 */
`define append_front_bad(MOD) "MOD.master"
`define append_front_good(MOD) `"MOD.master`"

program automatic test;
    initial begin
        $display(`append_front_bad(clock1));
        $display(`append_front_good(clock1));
    end
endprogram: test

运行结果如下所示

CONSOLE OUTPUT
# MOD.master
# clock1.master

append_front_bad—— 接受一个参数MOD,期望宏将两个字符串(MOD和“.master”)串联起来,但由于使用了双引号,输出结果为字符串“MOD.master”,参数并未被替换。
append_front_good——这是append_front_bad的正确版本。通过在双引号前使用反引号,进而告诉编译器,当宏展开时,需要替换参数MOD。
2、双反引号 ``
本质上是一个标记分隔符,它有助于编译器清楚地区分参数和宏文本中字符串的其余部分,可以用在需要分隔的字符串前面或者后面来对字符串做分隔。
参考如下的代码例子

/* Example 1.2 */
`define append_front_2a(MOD) `"MOD.master`"
`define append_front_2b(MOD) `"MOD master`"
`define append_front_2c_bad(MOD) `"MOD_master`"
`define append_front_2c_good(MOD) `"MOD``_master`"
`define append_middle(MOD) `"top_``MOD``_master`"
`define append_end(MOD) `"top_``MOD`"
`define append_front_3(MOD) `"MOD``.master`"

program automatic test;
    initial begin
        /* Example 1.2 */
        $display(`append_front_2a(clock2a));
        $display(`append_front_2b(clock2b));
        $display(`append_front_2c_bad(clock2c));
        $display(`append_front_2c_good(clock2c));
        $display(`append_front_3(clock3));
        $display(`append_middle(clock4));
        $display(`append_end(clock5));
    end
endprogram: test

运行结果如下所示

CONSOLE OUTPUT
    # clock2a.master
    # clock2b master
    # MOD_master
    # clock2c_master
    # clock3.master
    # top_clock4_master
    # top_clock5

append_front_2a和2b——空格和句点都是自然的标记分隔符,即编译器可以清楚地识别宏文本中的参数_2a在参数MOD和字符串master之间使用“句点”2b在参数MOD和字符串master之间使用了一个“空格”,。
append_front_2c_bad——如果参数附加了非空格或非句点字符,例如“MOD_master”中的下划线(
),则编译器无法确定参数字符串MOD的结束位置,因而就不会对MOD进行替换而将MOD_master作为一个整体进行解析。
append_front_2c_good——双反引号在MOD和_master之间创建了一个分隔符,这就是为什么MOD被正确识别和替换的原因append_middle和append_end是另外两个例子。
append_front_3——在自然标记分隔符(即空格或句点)之前或之后放置“”是可以的,但属于冗余操作。
3、反引号、反斜杠和双引号 \"
宏展开时会解析为 " ,如果需要嵌套的使用双引号,可以使用此选项,代码示例如下

/* Example 1.3 */
`define complex_string(ARG1, ARG2) \
    `"This `\`"Blue``ARG1`\`" is Really `\`"ARG2`\`"`"

program automatic test;
    initial begin
        $display(`complex_string(Beast, Black));
    end
endprogram: test

运行结果如下

CONSOLE OUTPUT
    # This "BlueBeast" is Really "Black"

如果以上这些例子还不足以解释清除这几个符号的意义的话,还可以通过下面的链接下载更多的实例:Download the example code from this section

其他应用

嵌套使用宏
宏中也可以使用注释
宏中也可以使用ifdefs 这类宏

传递参数

在使用宏参数时以下几点需要铭记于心:
参数允许有缺省值。
您可以通过将该位置留空来跳过参数,即使它没有缺省值(这一点跟函数/任务调用不同),下面的代码示例中test2(,)打印结果验证无缺省值的变量参数空缺时宏会把它替换为空字符。
观察下免示例中的debug1和debug2这两个宏,如果参数是字符串,则是否需要将参数用双引号括起来取决于参数在宏文本中的替换位置。在debug1中,MODNAME位于宏文本的引号内,因此在调用宏时,我没有用引号括起字符串program-block。而对于debug2,传递的参数是用引号括起来的“program-block”,因为MODNAME出现在宏文本的引号外。
代码示例如下

/* Example 2 */
`define test1(A) $display(`"1 Color A`")
`define test2(A=blue, B, C=green) $display(`"3 Colors A, B, C`")
`define test3(A=str1, B, C=green) \
    if (A == "orange")$display("Oooo .. I received an Orange!"); \
    else $display(`"3 Colors %s, B, C`", A);

`define debug1(MODNAME, MSG) \
    $display(`" ``MODNAME`` >> %s, %0d: %s`", `__FILE__, `__LINE__, MSG)
`define debug2(MODNAME, MSG) \
    $display(`"%s >> %s, %0d: %s`", MODNAME, `__FILE__, `__LINE__, MSG)

program automatic test;
    initial begin
        string str1, str2;
        str1 = "gray";
        str2 = "orange";

        // No args provided even without default value
        `test1();
        `test2(,,);

        // Passing some args
        `test1(black);
        `test2(,pink,);

        // Passing a var (str1, str2) as an arg
        `test3(str1,mistygreen,babypink);
        `test3(str2,mistygreen,babypink);

        `debug1(program-block, "this is a debug message");
        `debug2("program-block", "this is a debug message");

        /* The following will result in an Error
        * `test2(); // no args provided
        * `test2(,); // insufficient args provided
        *
        * // arg1 is used as a var in an if statement,
        * // This will compile fail because the macro
        * // will expand to *if ( == "orange")*
        * `test(, blue, pink)
        */
    end
endprogram: test

运行结果如下

CONSOLE OUTPUT

    # 1 Color
    # 3 Colors blue, , green
    # 1 Color black
    # 3 Colors blue, pink, green
    # 3 Colors gray, mistygreen, babypink
    # Oooo .. I received an Orange!
    #  program-block >> macros2.sv, 31: this is a debug message
    # program-block >> macros2.sv, 32: this is a debug message

宏风格指引

在整个团队中遵循一致的宏命名风格是非常有用的。由于UVM现在被广泛用作验证方法,我们可以从他们的源代码中借用一段,并使用他们宏编码风格。如果您查看UVM库的源代码,您将看到以下内容:
如果宏定义函数或任务,请使用大写宏名称和小写参数名称
如果宏定义了类、代码段等内容,请使用小写宏名称和大写作为参数
用下划线分隔宏名称中的单词
在下一节中,我从UVM库中挑选了一些宏,它们很好的彰显了上述命名规则。

参考示例

通常,你只需要看一堆例子便可以刷新你对如何使用宏的认知,下面是我从UVM库的源代码中挑选的一些示例,你应该能够从我们上面讲解的内容中很好的理解这些示例。

//> src/base/uvm_phase.svh
`define UVM_PH_TRACE(ID,MSG,PH,VERB) \
   `uvm_info(ID, {$sformatf("Phase '%0s' (id=%0d) ", \
       PH.get_full_name(), PH.get_inst_id()),MSG}, VERB);

//> src/macros/uvm_tlm_defines.svh
// Check out the MacroStyleGuide in use here
// [ 1.] If the Macro defines a function or a task,
// use UPPERCASE for macro name and lower case for args    
`define UVM_BLOCKING_TRANSPORT_IMP_SFX(SFX, imp, REQ, RSP, req_arg, rsp_arg) \
  task transport( input REQ req_arg, output RSP rsp_arg); \
    imp.transport``SFX(req_arg, rsp_arg); \
  endtask

// [ 2a.] For everything else (i.e., if Macro defines 
// a snippet of code, class or a convenience definition),
// use lowercase with UPPERCASE args
`define uvm_analysis_imp_decl(SFX) \
    class uvm_analysis_imp``SFX #(type T=int, type IMP=int) \
      extends uvm_port_base #(uvm_tlm_if_base #(T,T)); \
      `UVM_IMP_COMMON(`UVM_TLM_ANALYSIS_MASK,`"uvm_analysis_imp``SFX`",IMP) \
      function void write( input T t); \
        m_imp.write``SFX( t); \
      endfunction \
      \
    endclass

// [ 2b.] Examples of lowercase+uppercase with snippets
`define uvm_error(ID, MSG) \
   begin \
     if (uvm_report_enabled(UVM_NONE,UVM_ERROR,ID)) \
       uvm_report_error (ID, MSG, UVM_NONE, `uvm_file, `uvm_line, "", 1); \
   end
// [ 3.] Separate words with underscores, don't use camelCase
`define uvm_non_blocking_transport_imp_decl(SFX) \
    `uvm_nonblocking_transport_imp_decl(SFX)

//> src/macros/uvm_sequence_defines.svh
`define uvm_do(SEQ_OR_ITEM) \
  `uvm_do_on_pri_with(SEQ_OR_ITEM, m_sequencer, -1, {})

`define uvm_do_with(SEQ_OR_ITEM, CONSTRAINTS) \
  `uvm_do_on_pri_with(SEQ_OR_ITEM, m_sequencer, -1, CONSTRAINTS)

 `define uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, PRIORITY, CONSTRAINTS) \
  begin \
  uvm_sequence_base __seq; \
  `uvm_create_on(SEQ_OR_ITEM, SEQR) \
  if (!$cast(__seq,SEQ_OR_ITEM)) start_item(SEQ_OR_ITEM, PRIORITY);\
  if ((__seq == null || !__seq.do_not_randomize) && !SEQ_OR_ITEM.randomize() with CONSTRAINTS ) begin \
    `uvm_warning("RNDFLD", "Randomization failed in uvm_do_with action") \
  end\
  if (!$cast(__seq,SEQ_OR_ITEM)) finish_item(SEQ_OR_ITEM, PRIORITY); \
  else __seq.start(SEQR, this, PRIORITY, 0); \
  end

`define uvm_create_on(SEQ_OR_ITEM, SEQR) \
  begin \
  uvm_object_wrapper w_; \
  w_ = SEQ_OR_ITEM.get_type(); \
  $cast(SEQ_OR_ITEM , create_item(w_, SEQR, `"SEQ_OR_ITEM`"));\
  end

总结

遵循统一的宏编码风格,确保整个团队的一致性
函数和任务的大写宏名称和小写参数
用下划线分隔单词
其他所有内容(如类、代码片段等)的小写宏名称和大写参数
使用宏时要谨慎,过度使用可能会导致代码可读性变差
知道何时使用以下符号 "、`` 和 `"
宏强制在全局命名空间有效,在类中定义宏并不意味着它只对该类可见。
注意编译log中的宏重新定义的警告
编写宏时,请使用本文中的示例作为参考

疑问与评论

可以通过如下链接与作者进行交流讨论:please use this GitHub Discussions link

Verilog Systemverilog define宏定义 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档。 阅读详情

相关推荐

Verilog带参数的`define用法

Verilog带参数的`define用法

qq_33300585的博客 7639

System Verilog 宏

宏是使用`define编译器指令创建的代码片段。它们基本上由三部分组成–名称、文本和可选参数。在编译时,代码中的每个`macroname都会被替换为字符串macrotext,而ARGS是可以在macrotext中使用的变量。遵循编码风格指南,以追求团队一致性知道`"```\的用法宏的作用域为全局命名空间。在一个类内定义的宏,不代表仅对这个类可见在编译日志中留意重复定义宏的警告。

千村雪的博客 4508

[SystemVerilog语法拾遗] systemverilog中各种延时方式详解

systemverilog中各种延时

sunstat的博客 5001

system verilog 宏

1、在双引号里面不能直接使用宏; “`xx_define”:这种是会被视为文本,不会把宏的文本替换过来? `“`xx_define ` ”:要采用这种形式;(参考黄皮书P30)

qq_40571921的博客 3848

[SystemVerilog语法拾遗] 一文讲清楚SystemVerilog中的阻塞赋值与非阻塞赋值

一文讲清楚SystemVerilog中的阻塞赋值与非阻塞赋值

sunstat的博客 2713

[SystemVerilog语法拾遗] 关于process类的使用

systemverilog中process的使用

sunstat的博客 1279

[SystemVerilog语法拾遗] 关于package使用时的一些注意事项

介绍了systemverilog中package的使用

sunstat的博客 1648

[SystemVerilog语法拾遗] ===和!==运算符使用注意事项

本文讨论的四值运算符===和!==的使用场景以及注意事项,希望能对大家验证过程中写模型有所帮助。

sunstat的博客 1094

[SystemVerilog语法拾遗] 不同类型的数组作为方法参数时使用区别

不同类型的数组作为方法参数时使用区别

sunstat的博客 402

system verilog环境中使用宏的学习笔记

前言 宏定义是我们在编码时常用来减少代码量和跨文件定义常量的手段。我的师傅跟我讲如果一段代码你需要重复两次,那么就要考虑封装一下。当然了我在实践中,一般是重复到第三次的时候才会封装代码。 封装代码的方式一般就两种吧,一是封装为task或者function,二是封装为宏。如果条件允许的话,我认为还是尽量选择前者。宏定义虽然能够有效的降低编码量减少重复编码,但是会严重的降低代码可读性和定位效率,而...

moon9999的博客 9093

领域驱动设计整理——实体和值对象设计

实体引言在领域驱动设计里,实体的设计可以说是通用语言的核心,也是最开始在模型划分中需要考虑的。怎么样设计实体和怎么样划分限界上下文同样重要。实体的概念就是要保证通用语言的完整性。领域驱动让设计实体的关注点从数据的属性和表的关联转化到了富有行为的领域概念上。 实体是具有可变性的,这是一个和值对象比较明显的区分,也即实体是可以持续得变化,持续得修改,并且具有唯一的标识。在设计实体的时候需要跳出CRUD的

马猴烧酒└(┐卍^o^)卍ドゥルルル~楪詩月「YUZURIHA SHIZUKI」 2万+

[SystemVerilog语法拾遗] SV 中Hierarchy reference的动态调用

以上在interface 中实现,也可以在module 中实现。利用以上方法,大大提高代码复用性和可维护性。

sunstat的博客 801

手势控制 Python !Leap Motion Python 开发教程 (二)

手势控制 Python !Leap Motion Python 开发教程 (二) 现在进入正题,我来给大家总结一下我在使用 Leap Motion 开发过程中的经验以及学到的东西,其中我会概括以及翻译官方给出的注释,为了让这些注释更加通俗易懂,让大家更好理解。 回顾 在上一篇文章中我们讲了如何配置 Leap Motion 的 Python 2.7 的开发环境,如果您还没有配置好您的开发环境,可以参...

成畅的博客 3191

[SystemVerilog语法拾遗] 谈谈foreach使用时数组下标对遍历顺序的影响

通常我们在使用foreach遍历数组元素的时候不像for循环那么直观的知道循环变量的值的变化顺序以及step大小,foreach有自己一套遍历顺序,且默认step为1,在使用多维数组的遍历时遍历顺序有时候就会对结果产生重大影响,尤其是当我们在foreach循环中添加队列操作时,所以有必要通过一个实验来对foreach遍历顺序做个系统的总结。1、foreach的第一个维度是定义在[LSB1:MSB1],最后一个维度为[LSB0:MSB0],中间维度按顺序定义在[LSB1:MSB1]的右侧。

sunstat的博客 1065

Pixhawk变砖自救指南:从DFU模式到固件重刷全流程(附2.4.8实测)

本文详细介绍了Pixhawk飞控变砖后的自救方法,从DFU模式进入、固件重刷到高级恢复技巧全流程。特别针对国产版本boot0引脚未引出的特殊情况提供了解决方案,帮助用户通过QGC或Mission Planner地面站工具恢复飞控功能,适用于2.4.8等常见固件版本。

weixin_29168813的博客 336

64、5G 侧链通信技术详解

本文详细解析了5G侧链通信的关键技术,包括资源感知与选择、UE间协调、混合ARQ、功率控制、信道探测与CSI报告以及侧链同步。资源感知与选择通过周期性或随机方式实现资源分配,UE间协调通过主动或被动方式避免资源冲突。混合ARQ机制确保数据传输可靠性,功率控制和信道探测优化传输质量并减少干扰。侧链同步则通过多种方式确保设备间时间一致性。这些技术相互配合,构建了高效稳定的5G侧链通信体系,适用于智能交通、物联网、应急通信等多个领域,为未来无线通信发展提供强大支撑。

oil88的博客 99

[SystemVerilog语法拾遗] 类作用符::使用总结

systemverilog中类作用符::使用总结

sunstat的博客 243

(持续更新中!)详解【计算机类&面试真题】军队文职考试 ——第二期(真题+解析)| 网络协议的三个核心要素;交互式系统中的非剥夺策略;中断和陷入的区别;可变分区管理中的硬件机制;数据库系统的优点

本篇博客将讨论军队文职面试(计算机类)的几个关键问题。我们将介绍网络协议的核心要素(帮助你理解网络通信的基本原理)、交互式系统中的非剥夺策略(解释为何这是一个优秀的策略以及其对用户体验、系统稳定性和可预测性的影响)、中断和陷入的区别(从引起原因、处理机制、权限级别和应用等方面进行阐述)、可变分区管理的硬件机制以及数据库系统与文件系统的优点比较。通过阅读本文,您将深入了解这些话题,为面试准备和实际应用提供有价值的知识。

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 1704

[SystemVerilog语法拾遗] systemverilog中task的局部变量串扰问题

systemverilog中task的局部变量串扰问题

sunstat的博客 440

33、嵌入式系统中的内存操作与实时操作系统

本博客详细探讨了嵌入式系统中的内存操作和实时操作系统(RTOS)的基本原理及应用。内容涵盖C、C++和MicroPython三种语言下的SDRAM读写示例,并结合机器人真空吸尘器的实际应用说明内存的使用场景。此外,还介绍了RTOS的核心概念、组件及其工作机制,包括任务、事件、互斥锁、信号量、队列等,并以FreeRTOS和Mbed OS为例展示了RTOS的配置与使用方法。最后,通过常见问题和实践项目加深对嵌入式系统开发的理解。

zz67890的博客 143

Pixhawk2.4.8接口及引脚定义

pixhawk2.4.8接口定义图解

加斯顿工程师的博客 8741

[SystemVerilog语法拾遗] 谈谈inout和ref区别

systemverilog中inout和ref区别

sunstat的博客 510

Vue3 - 解决报错 Uncaught (in promise) DOMException: Failed to execute ‘insertBefore‘ on ‘Node‘: The node

vue3,报错,vue3报错,Uncaught(inpromise)DOMException:Failedtoexecute'insertBefore'on'Node':Thenodebeforewhichthenewnodeistobeinsertedisnotachildofthisnode,如何解决这个错误,动态渲染,v-if,v-show,insertBefore,详细解决方法,vue3未能在“Node”上执行“insertBefore”:要插入

🏆 前端领域优质创作者 1万+

Vim配置SystemVerilog高亮:从filetype识别到UVM语义着色

SystemVerilog(SV)是一种广泛用于数字验证的硬件描述与建模语言,其语法远超传统Verilog,包含class、interface、covergroup等面向对象与断言结构。Vim默认不识别.sv后缀,根源在于filetype检测机制依赖显式映射而非后缀猜测;只有正确声明filetype=systemverilog,才能触发对应语法解析与高亮加载。该配置直接影响UVM验证环境开发效率——如uvm_env、build_phase等关键标识能否被准确识别,进而支撑语义级着色、phase函数可视化及跨

weixin_34416649的博客 286

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

c++(systemVerilog)中的virtual funtion(task)的使用场景及实现原理

c++的virtual function实现原理和systemVerilog的virtual function/task实现很相似 除了下面的一篇文章还可以参考 【C++拾遗】 从内存布局看C++虚继承的实现原理https://blog.youkuaiyun.com/xiejingfa/article/details/48028491 咱们知道,与C语言相比,C++在布局和存取时间上的额外开销主要是由虚函数(virtual function)机制和虚继承(virtual base class)机制引发的。在前面一

cy413026的博客 2397

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

systemverilog define用法

sv 宏定义用法

beidaihechangchun的博客 1592

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

上一篇: [SystemVerilog语法拾遗] ===和!==运算符使用注意事项
下一篇: [UVM源代码研究] 当我们在tb里调用run_test()时uvm环境是如何启动的
数字验证Kane陈
博客等级 码龄12年 662粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值