当前位置: 首页 > news >正文

SystemVerilog之覆盖率详解

文章目录

  • 1.0 覆盖率前言
  • 1.1 覆盖率类型
  • 1.2 覆盖策略及覆盖组
  • 1.3 覆盖率数据采样
    • 1.3.1 bin的创建与使用
    • 1.3.2 条件覆盖率
    • 1.3.3 翻转覆盖率
    • 1.3.4 wildcard覆盖率
    • 1.3.5 忽略bin与非法bin
  • 1.4 交叉覆盖率
    • 1.4.1 排除部分cross bin
    • 1.4.2 精细化交叉覆盖率
    • 1.4.3 单个实例的覆盖率
    • 1.4.4 注释
    • 1.4.5 覆盖率次数限定与目标
    • 1.4.6 covergroup方法总结
    • 1.4.7 案例

1.0 覆盖率前言

覆盖率是用来衡量设计验证完备性。随着测试逐步覆盖各种合理的组合,覆盖率用来衡量测试进行的程度。覆盖率工具会在仿真过程中收集信息,然后进行后续处理并且得到覆盖率报告。通过报告找出覆盖盲区,然后修改现有test或者创建新的test来填补这些盲区。

覆盖率反馈环路:

在这里插入图片描述

带约束的随机测试与定向测试这两种环路一直迭代,直到达到要求

收集覆盖率:最简单的办法就是改变随机种子seed,就可以反复运行同一个随机测试平台来产生新的激励。每一次仿真都会产生一个带有覆盖率信息的数据库,将这些信息全部合并在一起就可以得到功能覆盖率。

在这里插入图片描述

1.1 覆盖率类型

  • 代码覆盖率:直接去检查RTL Code

    代码覆盖率衡量的是测试对于硬件设计描述的“实现”究竟测试得有多彻底,而非针对验证计划。

    • line coverage:所有行是否都运行到
    • paths coverage:所有路径是否以cover到
    • toggle coverage:所有变量都有过0,1翻转
    • FSM coverage:状态机中所有状态都已运行到

    很多的仿真工具都带有代码覆盖率工具,而得到的最终结果就是检测对设计代码运行程度的衡量。代码覆盖率最终的结果用于衡量所有testcase执行了设计中的多少代码。 关注点在设计代码RTL的分析上,而不是测试平台。

    未经测试的设计代码里可能隐藏硬件漏洞,也可能是冗余代码。

    代码覆盖率达到了100%,并不意味着验证的工作已经完成,但代码覆盖率100%是验证工作完备性的必要条件

  • 功能覆盖率:

    验证的目的: 确保设计在实际环境中的行为正确。功能描述文档详细说明了设计应该如何运行,而验证计划则列出了相应的功能应该如何激 励、验证和测量。功能覆盖率是和功能设计紧密相连的,而代码覆盖率则是衡量设计的实现情况。若某个功能在设计中被遗漏,代码覆盖率不能发现这个错误,但是功能覆盖率可以。

  • 断言覆盖率

    断言:用于一次性地或在一段时间内核对两个或两个以上设计信号之间关系的声明性代码。断言覆盖率可以测量某断言被触发的频繁程度。断言可以跟随设计和测试平台一起仿真,也可以被形式验证工具所证实。可以使用SV的程序性代码编写等效性检查,但使用SVA(SV断言)来表达会更容易。断言最常用于查找错误,例如两个信号间的相位关系,是否应该互斥或者请求与许可信号之间的时序等。

    一旦检测到问题,仿真就可以立即停止。

    断言可以用于查找感兴趣的信号的值或者状态。 可以使用cover property来测量这些关心的信号的值或者状态是否发生。在仿真结束时,仿真工具可以自动生成断言覆盖率数据。断言覆盖率数据以及其它覆盖率数据都会被集成在同一个覆盖率数据库中,verifier可以对其展开分析。

漏洞率以及漏洞曲线:

在一个项目实施期间,应该保持追踪每周有多少个漏洞被发现。一开始,当创建测试程序时,通过观察可能就会发现很多漏洞。当设计逐渐稳定时,需要利用自动化的检查方式来协助发现可能的漏洞。在设计临近流片时,漏洞率会下降,甚至有望为零。即便如此,验证工作仍然不能结束。每次漏洞率下降时,就应该寻找各种不同的办法去测试可能的边界情况(corner case)

漏洞率可能每周都有变化,这跟很多因素都有关。不过漏洞率如果出现意外的变化,可能预示着潜在的问题。

在这里插入图片描述

1.2 覆盖策略及覆盖组

  • 覆盖策略:只测量需要的内容,例如初始化阶段不需要测试

    • 只测试需要的内容:验证工程师需要懂得,在使能覆盖率收集时,这一特性会降低很大的仿真性能。由于收集功能覆盖率数据的开销很大,所以应该只测量你会用来分析并且改进测试的那部分数据。同时也需要设定合理的覆盖率采样的事件,一方面提升采样效率,一方面也可以降低收集覆盖率的开销。

    • 验证的完备性:完备的覆盖率测量结果和漏洞增长曲线,可以帮助确认设计是否被完整地验证过。如果功能覆盖率高但代码覆盖率低,这说明验证计划不完整,测试没有执行设计的所有代码。如果代码覆盖率高但功能覆盖率低,这说明即使测试平台很好地执行了设计的所有代码,但是测试还是没有把设计定位到所有感兴趣的状态上。

      你的目标是同时驱动高的代码覆盖率和功能覆盖率。

    • 覆盖率比较:

      在这里插入图片描述

  • 覆盖组covergroup

覆盖组与类相似,一次定义就可以多次实例化且全都在同一时间采集。一个覆盖组包含覆盖点,选项,形式参数和可触发(trigger),一个或多个数据点。

covergroup可以定义在类中,也可以定义在interface或者module中,一个类里可以包含多个covergroupcovergroup可以采样任何可见的变量,例如程序变量、接口信号或者设计端口。

当你拥有多个独立的covergroup时,每个covergroup可以根据需要自行使能或者禁止。每个covergroup可以定义单独的触发采样事件,允许从多个源头收集数据。covergroup必须被例化才可以用来收集数据。

  • 入门案例:一个简单对象的功能覆盖率,测试程序使用CovPort覆盖组对port字段的数值进行采样,八种可能的数值,32次随机。

    interface busifc;logic clk;logic [31:0] data;logic [2:0] port;
    endinterfaceclass Transaction;rand bit [31:0] data; rand bit [2:0] port; // 八种端口数据
    endclass program automatic test(busifc.TB ifc);covergroup CovPortcoverpoint ifc.port; //测试覆盖率:检测8个port是否都出现过endgroup initial begin Transaction tr; CovPort ck; ck = new(); // 实例化组tr = new(); repeat (32) begin 		  // 运行几个周期assert(tr.randomize); ifc.port <= tr.port;  // 发送到接口上ifc.data <= tr.data;  ck.sample(); 		  // 收集覆盖率@ifc.clk; 		      // 等待一个周期end end 
    endprogram
    

    8中可能,32次随机,该例的VCS的覆盖率报告(一部分)如下:

    Coverage:87.50..........
    bin         #hit       at least
    :::::::::::::::::::::::::::::::::::
    auto[1]       7           1
    auto[2]       7           1
    auto[3]       1           1
    auto[4]       5           1
    auto[5]       4           1
    auto[6]       2           1
    auto[7]       6           1
    
  • 例:在类里使用功能覆盖率

    class Transaction;rand bit [31:0] data; rand bit [2:0] port;
    endclass class Transactor;Transaction tr; mailbox mbx_in;virtual busifc ifc;covergroup CovPort;coverpoint tr.port;endgroup // 由于覆盖组实例化在new里面,因此在program不需要实例化function new(mailbox mbx_in, virtual busifc ifc); CovPort = new(); this.mbx_in = mbx_in; this.ifc = ifc;endfunction task main; beginmbx_in.get(tr); ifc.port <= tr.port;ifc.data <= tr.data; CovPort.sample();end endtask 
    endclassinterface busifc;logic clk;logic [31:0] data;logic [2:0] port;
    endinterfaceprogram automatic test(busifc ifc);Transaction tr;Transactor tr_c;mailbox mbx_in;initial begintr = new();mbx_in = new();tr_c = new(mbx_in,ifc);repeat (32) begin assert(tr.randomize); mbx_in.put(tr);tr_c.main();@(posedge ifc.clk);endend
    endprogrammodule top;busifc ifc();initial beginifc.clk=0;forever #10 ifc.clk=~ifc.clk;endtest test_u(ifc);
    endmodule
    

触发: covergroup由采样的数据和数据被采样的事件构成。当这两个条件都准备好以后,测试平台便会触发covergroup。这个过程可以通过直接使用sample()函数完成,也可以在covergroup中采样阻塞表达式或者使用wait或@实现在信号或事件上的阻塞。如果想在代码中显式地触发covergroup采样,或者不存在采样时刻的信号或事件,又或者一个covergroup被例化为多个实例需要单独触发,那么可以使用sample()方法。如果你想借助已有的事件或者信号触发covergroup,可以在covergroup声明中使用阻塞语句。

  • 使用事件触发:

    event trans_ready;
    covergroup CovPort @(trans_ready);coverpoint ifc.cb.port;
    endgroup
    

    与直接调用sample()相比,使用事件触发的好处在于你能够借助已有的事件,来决定何时开始收集数据

1.3 覆盖率数据采样

当在覆盖点上指定一个变量或者表达式时,SV便会创建很多的仓bin来记录每个数值被捕捉到的次数。这些bin是衡量覆盖率的基本单位。为了计算出一个点上的覆盖率,首先要了解域的概念,域是所有可能值的的个数。覆盖率就是采样值的数目除以域中bin的数目。

covergroup中可以定义多个coverpoint,coverpoint中可以自定义多个cover bin或者SV帮助自动定义多个cover bin,每次covergroup采样,SV都会在一个或者多个cover bin中留下标记,用来记录采样时变量的数值和匹配的cover bin。

例如:一个3bit变量的域为0:7,正常情况下会除以8个bin,如果在仿真的过程中只有7个值被采样到,那么报告就会给出这个coverpoint点的覆盖率是7/8也即87.5%。所有这些coverpoint点组合在一起就是covergroup组的覆盖率,所有covergroup组组合在一起就是整个的仿真覆盖率。而这也仅仅是单个仿真的情况,在实际中需要追踪覆盖率随时间的变化情况,分析趋势。

1.3.1 bin的创建与使用

SV会默认为某个coverpoint创建bin,用户也可以自己定义bin的采样域。如果采样变量的域范围过大而又没有指定bin,那么系统会默认分配64个bin,将值域范围平均分配给这64个bin。用户可以通过covergroup的选项auto_bin_max来指定自动创建bin的最大数目。

实际操作中,自动创建bin的方法不实用,建议用户自行定义bin(整体的去定义,或定义单独的点),或者减小auto_bin_max的数值。

covergroup covport;// 所有coverpoint auto_bin数量=8option.auto_bin_max = 8; // 特定coverpoint auto_bin数量=2coverpoint tr.port {option.auto_bin_max = 2;} 
endgroup

延用本章的入门案例,port位宽为3,值域是0个可能的值,因此第一个仓保存的是值域范围的前半段0-3,第二个仓保存的是后半段4-7,VCS给出的覆盖率报告部分如下:

bin         #hit     at least
:::::::::::::::::::::::::::::::::::
auto[0-3]    15        1
auto[4-7]    17        1

除此之外,还可以单独命名覆盖点的仓,例如下面对一个4bit的变量kind进行采样,有16种可能,对其进行单独的覆盖采样:

第一个仓:命名为zero,对kind=0的情况进行计数

第二个仓:命名为lo,对1~3,5这四个值进行计数

第三个仓:命名为hi,将8~15保存到单独的仓里,分别为:hi_8,hi_9,hi_a,hi-b … hi_f

第四个仓:命名为misc,对前面没有出现过的值进行采样,也即4,6,7

covergroup CovKind;coverpoint tr.kind {bins zero = {0}; // 1个仓代表kind**0bins lo = {[1:3], 5}; // 1个仓代表1:35bins hi[] = {[8:$]}; // 8个独立的仓代表8:15bins misc = default; // 1个仓代表剩余的所有值} // 没有分号
endgroup

注意coverpoint定义使用{}而不是begin…end,大括号的结尾没有带分号;,VCS的部分报告如下

Bin       #hits     at least
:::::::::::::::::::::::::::::::::::
hi_8        0          1
hi_9        5          1
hi_a        3          1
hi_b        4          1
hi_c        2          1
hi_d        2          1
hi_e        9          1
hi_f        4          1
lo          16         1
misc        15         1
zero        1          1

1.3.2 条件覆盖率

可以使用关键词iff给coverpoint添加条件。这种做法常用于在复位期间关闭覆盖以忽略不合理的条件触发

例:仅收集reset=0(高电平有效)时port的值。

covergroup CoverPort;coverpoint port iff(!bus_if.reset);
endgroup

同样的,也可以使用start和stop函数来控制 covergroup各个独立实例。

initial begincovport ck = new();// 复位期间停止收集覆盖率#1ns;ck.stop();bus_if.reset = 1;#100ns bus_if.reset = 0;// 复位结束ck.start();... 
end

1.3.3 翻转覆盖率

coverpoint也可以用来记录变量从A值到B值的跳转情况。还可以确定任何长度的翻转次数。

例:查询port有没有从0变为1,2,3。

covergroup CoverPort;coverpoint port {bins t1 = {(0 => 1), (0 => 2), (0 => 3)};}
endgroup

1.3.4 wildcard覆盖率

可以使用关键字wildcard来创建多个状态或者翻转。在表达式中,任何X,Z或者?都会被当成0或1的通配符。

例如:采样偶数与奇数,两个仓分别代表奇数偶数。

bit [2:0] port;
covergroup CoverPort;coverpoint port {wildcard bins even = {3'b??0};wildcard bins odd = {3'b??1};}
endgroup

1.3.5 忽略bin与非法bin

  • 忽略bin:排除那些不用来计算覆盖率的数值

    在某些coverpoint可能始终无法得到全部的域值。对于那些不计算功能的域值可以使用ignore_bins来排除,最终它们并不会计入coverpoint的覆盖率。

    例1:使用ignore_bins的覆盖点

    bit [2:0] low_ports_0_5; // 只使用数值0-5
    covergroup CoverPort;coverpoint low_ports_0_5 {ignore_bins hi = {[6,7]}; // 忽略数值6-7}
    endgroup
    

    由于忽略了数值6-7,因此总仓数是6

    例2:使用ignore_binsauto_bin_max的覆盖点

    bit [2:0] low_ports_0_5; // 只使用数值0-5
    covergroup CoverPort;coverpoint low_ports_0_5 {options.auto_bin_max=4;   // 0:1 2:3 4:5 6:7ignore_bins hi = {[6,7]}; // 忽略数值6-7}
    endgroup
    

    创建了四个仓,但由于最后一个仓被ignore_bins所忽略,所以只有三个仓被创建,因此覆盖率只有四种可能值,分别为0%,33%,66%和100%。

  • 非法bin:有些采样值不仅应该被忽略,如果出现了还应该报错。

    这种情况可以在测试平台中监测,也可以使用illegal_bins对特定的bin进行标示。

    bit [2:0] low_ports_0_5; // 只是用数值0-5
    covergroup CoverPort;coverpoint low_ports_0_5 {illegal_bins hi = {[6,7]}; // 如果出现6-7便报错}
    endgroup
    

1.4 交叉覆盖率

coverpoint是记录单个变量或者表达式的观测值。如果像记录在某一时刻,多个变量之间值的组合情况,需要使用交叉(cross) 覆盖率。cross语句只允许带coverpoint或者简单的变量名。

class Transaction;rand bit [3:0] kind;rand bit [2:0] port;
endclassTransaction tr;
covergroup CovPort;kind: coverpoint tr.kind;port: coverpoint tr.port;cross kind, port;
endgroup

关心kind与port的组合情况的覆盖率。

1.4.1 排除部分cross bin

通过使用ignore_bins、binsof和intersect分别指定coverpoint和值域, 这样可以清除很多不关心的cross bin

covergroup Covport;port: coverpoint tr.port{bins port[] = {[0:$]};}kind: coverpoint tr.kind {bins zero = {0};bins lo = {[1:3]};bins hi[] = {[8:$]};bins misc = default;}cross kind, port {ignore_bins hi = binsof(port) intersect {7};ignore_bins md = binsof(port) intersect {0}&&binsof(kind) intersect {[9:11]};ignore_bins lo = binsof(kind.lo);}
endgroup

1.4.2 精细化交叉覆盖率

随着cross覆盖率越来越精细,需要花费不少的时间来指定哪些bin应该被使用或者被忽略。更适合的方式是不使用自动分配的cross bin,自己声明感兴趣的cross bin。假如有两个随机变量a和b,只关心下面三种状态,{a**0,b**0}、 {a**1,b**0}和{b**1}

class Transaction;rand bit a, b;
endclass
covergroup CrossBinNames;a: coverpoint tr.a{ bins a0 = {0};bins a1 = {1};// 不计算覆盖率type_option.weight=0;}b: coverpoint tr.b{ bins b0 = {0};bins b1 = {1};// 不计算覆盖率type_option.weight=0;}ab: cross a, b{ bins a0b0 = binsof(a.a0) && binsof(b.b0);bins a1b0 = binsof(a.a1) && binsof(b.b0);bins b1 = binsof(b.b1); }
endgroup

上述的代码等效于:

class Transaction;rand bit a, b;
endclass
covergroup CrossBinsofIntersect;a: coverpoint tr.a{ // 不计算覆盖率type_option.weight=0; }b: coverpoint tr.b{// 不计算覆盖率type_option.weight=0; }ab: cross a,b{ bins a0b0 = binsof(a) intersect {0} && binsof(b) intersect {0};bins a1b0 = binsof(a) intersect {1} && binsof(b) intersect {0};bins b1 = binsof(b) intersect {1}; }
endgroup

1.4.3 单个实例的覆盖率

如果对一个covergroup例化多次,那么默认情况下SV会将所有实例的覆盖率合并到一起。如果需要单独列出每个covergroup实例的覆盖率,则需要设置覆盖选项。

covergroup CoverLength;coverpoint tr.length;// 设置单个实例覆盖率option.per_instance = 1;
endgroup

1.4.4 注释

如果有多个covergroup实例,可以通过参数来对每一个实例传入单独的注释。这些注释最终会显示在覆盖率数据的总结报告中。

covergroup CoverPort(int lo,hi, string comment);option.comment = comment;option.per_instance = 1;coverpoint port{bins range = {[lo:hi]};}
endgroup
... 
CoverPort cp_lo = new(0,3,"Low port numbers");
CoverPort cp_hi = new(4,7,"High port numbers");

1.4.5 覆盖率次数限定与目标

  • 覆盖率次数限定:

    默认情况下,数值采样了1次就可以计入有效的bin。可以通过修改at_least来修改每个bin的数值最少的采样次数,如果低于at_least数值,则不会被计入bin中。

    option.at_least可以在covergroup中声明来影响所有的coverpoint,也可以在coverpoint中声明来只影响该coverpoint下所有的bin。

    一般不会更改。

  • 覆盖率目标

    一个covergroup或者一个coverpoint的目标是100%覆盖率。

    不过你也可以将其设置为低于100%的目标。这个选项只会影响覆盖率报告。

    covergroup CoverPort;coverpoint port;option.goal = 90;
    endgroup
    

    添加上之后,如果达到了90%,报告就会显示100%,一般也不会更改

1.4.6 covergroup方法总结

sample():采样。

get_coverage()/get_inst_coverage():获取覆盖率,返回0-100的real数值。

set_inst_name(string):设置covergroup的名称。

start()/stop():使能或者关闭覆盖率的收集。

  • 覆盖率分析
    1. 使用$get_coverage()可以得到总体的覆盖率。
    2. 也可以使用covergroup_inst.get_inst_coverage()来获取单个covergroup实例的覆盖 。
    3. 这些函数最实际的用处是在一个测试当中监测覆盖率的变化。
    4. 如果覆盖率水平在一段时间之后没有提高,那么这个测试就应该停止。
    5. 重启新的随机种子或者测试可能有望提高覆盖率。
    6. 如果测试可以基于功能覆盖率采取一些深入的行动,例如重新限定随机的约束,那是一件非常好的事情,但这种测试很难编写。

现在很少去用命令行分析了,都是采用图形化界面的方式去分析

1.4.7 案例

添加bins,并收集coverage信息,查看 bins的收集情况

TIPS: makefile elab的时候要添加覆盖率选项: -cm tgl+branch run中也要添加: -cm tgl+branch -cov_dir top_cov

查看报告: dve -full64 -cov -dir top_cov/top.simv.vdb

生成报告:urg -dir top_cov/top.simv.vbd -format both -report report

-dir:vbd文件

-format:生成的格式:txt或html,both是两者都要生成

-report:报告文件目录

class Transaction;rand bit [4:0] data; rand bit [2:0] port;
endclass class Transactor;Transaction tr; mailbox mbx_in;virtual busifc ifc;covergroup CovPort;port: coverpoint tr.port {bins port[] = {[0:$]};}data: coverpoint tr.data{bins zero = {0}; bins lo = {[1:3]};bins hi[] = {[8:$]};bins misc = default;}cross port,data;endgroup // 由于覆盖组实例化在new里面,因此在program不需要实例化function new(mailbox mbx_in, virtual busifc ifc); CovPort = new(); this.mbx_in = mbx_in; this.ifc = ifc;endfunction task main; beginmbx_in.get(tr); ifc.port <= tr.port;ifc.data <= tr.data; CovPort.sample();end endtask 
endclassinterface busifc;logic clk;logic [31:0] data;logic [2:0] port;
endinterfaceprogram automatic test(busifc ifc);Transaction tr;Transactor tr_c;mailbox mbx_in;initial begintr = new();mbx_in = new();tr_c = new(mbx_in,ifc);repeat (32) begin assert(tr.randomize); mbx_in.put(tr);tr_c.main();@ifc.clk;endend
endprogrammodule top;busifc ifc();initial beginifc.clk=0;forever #10 ifc.clk=~ifc.clk;endtest test_u(ifc);
endmodule

在这里插入图片描述

相关文章:

SystemVerilog之覆盖率详解

文章目录 1.0 覆盖率前言1.1 覆盖率类型1.2 覆盖策略及覆盖组1.3 覆盖率数据采样1.3.1 bin的创建与使用1.3.2 条件覆盖率1.3.3 翻转覆盖率1.3.4 wildcard覆盖率1.3.5 忽略bin与非法bin 1.4 交叉覆盖率1.4.1 排除部分cross bin1.4.2 精细化交叉覆盖率1.4.3 单个实例的覆盖率1.4.…...

Qt Designer设计的界面如何显示、即运行显示窗口界面

首先利用Qt Designer设计.ui文件&#xff0c;然后采用Tools->External Tools->PyUIC转换成.py文件。这个.py文件是.ui文件编译而来的&#xff0c;将这种文件由.ui文件编译而来的.py文件称之为界面文件。由于界面文件每次编译时候都会初始化&#xff0c;所以需要新建一个.…...

vue3的setup的使用和原理解析

setup是Vue 3中引入的一个新的组件选项。它是一个在组件实例创建之前被调用的函数&#xff0c;用于设置组件的初始状态、计算属性、方法等。setup函数是Vue 3中函数式组件的核心部分&#xff0c;它提供了一种新的方式来编写组件逻辑。 使用setup函数有以下几个步骤&#xff1a…...

Spring boot中的线程池-ThreadPoolTaskExecutor

一、jdk的阻塞队列&#xff1a; 二、Spring boot工程的有哪些阻塞队列呢&#xff1f; 1、默认注入的ThreadPoolTaskExecutor 视频解说&#xff1a; 线程池篇-springboot项目中的service层里简单注入ThreadPoolTaskExecutor并且使用_哔哩哔哩_bilibili 程序代码&#xff1a;…...

pgsql checkpoint机制(1)

检查点触发时机 检查点间隔时间由checkpoint_timeout设置pg_xlog中wall段文件总大小超过参数max_WAL_size的值postgresql服务器在smart或fast模式下关闭手动checkpoint 为什么需要检查点&#xff1f; 定期保持修改过的数据块作为实例恢复时起始位置&#xff08;问题&#xf…...

微信小程序 map地图(轨迹)

allMarkers效果图 废话少说直接上马&#xff08;最后是我遇到的问题&#xff09; cover-view是气泡弹窗&#xff0c;可以自定义弹窗&#xff0c;要配合js&#xff1a;customCallout&#xff0c;如果是非自定义的话&#xff1a;callout&#xff08;可以修改颜色、边框宽度、圆角…...

【钉钉接口】bpms_task_change、bpms_instance_change 的区别及举例

bpms_task_change&#xff1a;审批任务回调&#xff0c;是针对审批任务状态的推送。如审批人执行审批、审批人转交审批等针对具体某个审批节点的操作&#xff0c;属于 bpms_task_change 事件类型。bpms_instance_change&#xff1a;审批实例回调&#xff0c;是针对审批实例状态…...

vue左右div结构手动拉伸并且echarts图表根据拉伸宽高自适应

需求&#xff1a; 左右结构的div&#xff0c;可以根据数据抬起按下进行拉伸修改容器宽度的操作给左右结构某一图表设置拉伸自适应左右结构都设置个最小宽度&#xff0c;只能到一定区域内拉伸解决echarts的bug&#xff08;重复加载chart实例&#xff09;&#xff1a;[ECharts] …...

开发工具Eclipse的使用

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Eclipse使用的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Eclipse是什么 二.使用Eclipse的…...

DrawerLayout布局使用教程Android侧边栏导航完全指南:创建简单实用的导航抽屉

导航抽屉&#xff08;侧边栏&#xff09;在现代移动应用中扮演着关键角色&#xff0c;提供了流畅的用户导航体验。本文将带您从头开始&#xff0c;逐步创建一个基本的 Android 侧边栏导航示例&#xff0c;为您的应用增添更多交互魅力。 1. 创建新的 Android 项目 首先&#x…...

Dynamics 365 实体快速创建功能启用

这里我会先用例子讲快速创建,包含了字段创建等内容。希望直接了解配置过程的,可以根据目目录跳转查看。 1 例子 我们这里创建了两个实体,学生和选择的科目。它们的关系是一个学生可以选择多个科目,即学生和科目选择是一对多关系。所以我们在选择的科目中创建了一个学生的…...

Mybatis三剑客(一)在springboot中自动生成Mybatis【generator】

1、pom.xml中新增plugin <plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.7</version><configuration><overwrite>true</overwrite><…...

【LeetCode 热题 100】图论 专题(bfs,拓扑排序,Trie树 字典树)

from&#xff1a; https://leetcode.cn/studyplan/top-100-liked/ bfs 具有 边权为1 的最短路性质 拓扑排序&#xff0c;入度 Trie树&#xff0c; 高效存储 字符串【见鬼&#xff0c;不知道为什么写错&#xff0c;需要掌握熟练度】 文章目录 200. 岛屿数量【dfs / bfs】994. 腐…...

Jmeter压测实战:Jmeter二次开发之自定义函数

目录 1 前言 2 开发准备 3 自定义函数核心实现 3.1 新建项目 3.2 继承实现AbstractFunction类 3.3 最终项目结构 4 Jmeter加载扩展包 4.1 maven构建配置 4.2 项目打包 4.3 Jmeter加载扩展包 5 自定义函数调用调试 5.1 打开Jmeter函数助手&#xff0c;选择自定义函数…...

在python中使用nvidia的VPF库对RTSP流进行硬解码并使用opencv进行显示

解码并处理视频流的多线程应用 随着视频处理技术的不断发展&#xff0c;越来越多的应用需要对视频流进行解码和处理。在本文中&#xff0c;我们将介绍一个基于Python的多线程应用程序&#xff0c;该应用程序可以解码并处理多个RTSP视频流&#xff0c;同时利用GPU加速&#xff0…...

C++中using namespace std的作用记录

using namespace std;这句代码的作用是引入std命名空间,使得程序可以直接使用std命名空间下的标识符,而不需要加上std::前缀。 在C中,标识符被组织在不同的命名空间中,以避免命名冲突。最常见的命名空间是std,它包含了C标准库中的所有标识符,如cout、vector、string等。 默认…...

【TX 企业微信私有化历史版本 API 信息泄露】

目录 影响版本 复现过程 修复方式 影响版本 影响私有化部署&#xff1a; toB toG版微信 2.5.x 版本 2.6.930000 版本以下 危险程度&#xff1a;高危。攻击者可以进行获取企业的部门信息&#xff0c;员工信息&#xff0c;如权限较高包括应用获取&#xff0c;记录文件等等均…...

腾讯云轻量应用服务器镜像应用模板清单大全

腾讯云轻量应用服务器支持多种应用模板镜像&#xff0c;Windows和Linux镜像模板都有&#xff0c;如&#xff1a;宝塔Linux面板腾讯云专享版、WordPress、WooCommerce、LAMP、Node.js、Docker CE、K3s、宝塔Windows面板和ASP.NET等应用模板镜像&#xff0c;腾讯云服务器网分享腾…...

C语言链表操作

目录 链表基本操作 删除重复元素 查找倒数第N个节点 查找中间节点 约瑟夫环 循环链表 合并有序链表 逆置链表 逆置链表(双向链表) 链表基本操作 //linklist.c#include "linklist.h" #include <stdlib.h>struct node *head NULL; struct node *tail…...

详解拦截器和过滤器

目录 代码演示过滤器Demo拦截器Demo 过滤器自定义拦截器配置拦截器过滤器执行原理多个过滤器的执行顺序 拦截器自定义拦截器注册拦截器1&#xff09;注册拦截器2&#xff09;配置拦截的路径3&#xff09;配置不拦截的路径 多个拦截器的执行顺序 过滤器和拦截器的区别 代码演示 …...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...

Java后端检查空条件查询

通过抛出运行异常&#xff1a;throw new RuntimeException("请输入查询条件&#xff01;");BranchWarehouseServiceImpl.java // 查询试剂交易&#xff08;入库/出库&#xff09;记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...

【若依】框架项目部署笔记

参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作&#xff1a; 压缩包下载&#xff1a;http://download.redis.io/releases 1. 上传压缩包&#xff0c;并进入压缩包所在目录&#xff0c;解压到目标…...

32位寻址与64位寻址

32位寻址与64位寻址 32位寻址是什么&#xff1f; 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元&#xff08;地址&#xff09;&#xff0c;其核心含义与能力如下&#xff1a; 1. 核心定义 地址位宽&#xff1a;CPU或内存控制器用32位…...