SV学习笔记(六)

覆盖率类型

写在前面

  • 覆盖率是 衡量设计验证完备性 的一个通用词。
  • 随着测试逐步覆盖各种合理的场景,仿真过程会慢慢勾画出你的设计情况。
  • 覆盖率工具会 在仿真过程中收集信息 ,然后进行后续处理并且得到覆盖率报告。
  • 通过这个报告找出覆盖之外的盲区,然后修改现有的测试或者创建新的测试来填补这些盲区。
  • 这个过程可以一直迭代进行,直到你对覆盖率满意为止。
    • 可以使用一个反馈回路来分析覆盖率的结果,并决定采取哪种行动来达到100%的覆盖率。
    • 首要的选择是使用更多的种子来运行现有的测试程序
    • 大量种子依然对于覆盖率增长没有帮助时,需要建立新的约束。
    • 只有在确实需要的时候才会求助于创建定向测试。

代码覆盖率

  • 不添加任何额外的HDL代码,工具会通过分析源代码和增加隐藏代码来自动完成代码覆盖率的统计。

  • 当运行完所有测试,代码覆盖率工具便会创建相应的数据库。

  • 仿真器都带有代码覆盖率的工具,覆盖率数据也可被转换为可读格式。

  • 行覆盖率:多少行代码已经被执行过。

  • 路径覆盖率:在穿过代码和表达式的路径中有哪些已经被执行过。

  • 翻转覆盖率:哪些单位比特变量的值为0或1。

  • 状态机覆盖率:状态机哪些状态和状态转换已经被访问过。

  • 代码覆盖率最终的结果用于衡量你执行了设计中的多少代码。

  • 关注点应该放在设计代码的分析上,而不是测试平台。

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

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

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

断言覆盖率

  • 断言是用于一次性地或在一段时间对一个或者多个设计信号在逻辑或者时序上的声明性代码。
  • 断言可以跟随设计和测试平台一起仿真,也可以被形式验证工具所证实。
  • 你可以使用SV的程序性代码编写等效性检查, 但使用SVA(SV断言)来表达会更容易。
  • 断言最常用于查找错误,例如两个信号是否应该互斥,或者请求与许可信号之间的时序等。
  • 一旦检测到问题,仿真就可以立即停止。
  • 有些断言可以用于查找感兴趣的信号值或者设计状态。
  • 可以使用cover property来测量这些关心的信号值或者状态是否发生。
  • 在仿真结束时,仿真工具可以自动生成断言覆盖率数据。
  • 断言覆盖率数据以及其它覆盖率数据都会被集成在同一个覆盖率数据库中,verifier可以对其展开分析。

功能覆盖率

  • 验证的目的就是确保设计在实际环境中的行为正确。
  • 功能描述文档详细说明了设计应该如何运行,而验证计划则列出了相应的功能应该如何激励、验证和测量。
  • 当你收集测量数据希望找出那些功能已经被覆盖时,你其实就是在计算”设计”的覆盖率。
  • 功能覆盖率是和功能设计意图紧密相连的,有时也被称为”描述覆盖率”,而代码覆盖率则是衡量设计的实现情况。
  • 某个功能在设计中可以被遗漏,代码覆盖率不能发现这个错误,但是功能覆盖率可以。

  • 每一次仿真都会产生一个带有覆盖率信息的数据库,记录随机游走的轨迹。
  • 把这些信息全部合并在一起就可以得到功能覆盖率,从而衡量整体的进展程度。
  • 通过分析覆盖率数据可以决定如何修改回归测试集。
  • 如果覆盖率在稳步增长,那么添加新种子或者加长测试实际即可。
  • 如果覆盖率增速放缓,那么需要添加额外的约束来产生更多”有意思”的激励。
  • 如果覆盖率停止增长,然而设计某些测试点没有被覆盖到,那么就需要创建新的测试了。
  • 如果覆盖率为100%但依然有新的设计漏洞,那么覆盖率可能没有覆盖到设计中的某些设计功能区域。

漏洞率曲线

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

功能覆盖策略

收集信息而非数据

  • 比如MCDF, 你需要关心的是合法的寄存器地址和非法的寄存器地址,可写的寄存器域和非法的寄存器域,而不是具体的寄存器地址数值
  • 一旦关注的地方着眼于感兴趣的状态,而不是具体数值,那么这对于你如何定义功能覆盖率,以及如何收集信息会减轻很大的负担。
  • 设计信号如果数量范围太大,应该拆分为多个小范围再加上边界情况。

只测量需要的内容

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

验证的完备性

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

覆盖组

写在前面

  • 覆盖组(covergroup) 与类相似, 一次定义后便可以多次实例化。
  • covergroup可以包含一个或者多个coverpoint, 且全都在同一时间采集。
  • covergroup可以定义在类中,也可以定义在interface或者module中。
  • covergroup可以采样任何可见的变量,例如程序变量、接口信号或者设计端口。
  • 一个类里可以包含多个covergroup。
  • 当你拥有多个独立的covergroup时, 每个covergroup可以根据需要自行使能或者禁止。
  • 每个covergroup可以定义单独的触发采样事件,允许从多个源头收集数据。
  • covergroup必须被例化才可以用来收集数据。

在类里定义covergroup

class Transactor;Transaction tr;mailbox mbx_in;covergroup CovPort;coverpoint tr.port;endgroupfunction new(mailbox mbx_in) ;//CovPort = new() ;CovPort cg1 = new() ; //使用这种例化方式可以给对象设定名字this.mbx_in=mbx_in;endfunctiontask main;forever begintr=mbx_in.get;ifc.cb.port <= tr.port;ifc.cb.data <= tr.data;CovPort.sample() ;endendtask
endclass

白话一刻

  • Transaction tr;:定义一个类型为Transaction的变量tr,用来存储事务对象。

  • mailbox mbx_in;:定义一个mailbox类型的变量mbx_in,通常用于在模拟环境中作为消息队列或通道。

  • covergroup CovPort;:定义一个覆盖组CovPort,用于收集覆盖信息,常用于验证测试中。

  • coverpoint tr.port;:在CovPort覆盖组内定义一个覆盖点,用于监控tr对象的port字段的取值情况。

    function new(mailbox mbx_in) ;这是Transactor类的构造函数,当创建Transactor对象时会被调用。

  • CovPort cg1 = new() ;:创建一个新的CovPort覆盖组实例,并命名为cg1

  • this.mbx_in=mbx_in;:将传递给构造函数的mbx_in参数赋值给类的成员变量mbx_in

  • tr=mbx_in.get;:从mbx_in邮箱中获取一个事务对象,并赋值给tr

  • ifc.cb.port <= tr.port;ifc.cb.data <= tr.data;:将tr对象中的portdata字段的值分别赋给ifc.cb(可能是一个接口或组件)的portdata字段。

  • CovPort.sample() ;:对覆盖组CovPort进行采样,以收集覆盖信息。

这个Transactor类主要用于从mailbox中接收事务对象,将事务对象的数据写入某个接口或组件,并收集相关的覆盖信息。

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

数据采样

写在前面

  • 当你在coverpoint指定采样一个变量或表达式时, SV会创建很多的”仓(bin) ”来记录每个数值被捕捉到的次数。
    这些bin是衡量功能覆盖率的基本单位。
  • covergroup中可以定义多个coverpoint, coverpoint中可以自定义多个cover bin或者SV帮助自动定义多个cover bin(建议自己定义,原因有两点:一是工具可能会多定义其他的bin,二是工具定义的bin不能很好的命名,基于这两点,自己定义bin在覆盖率分析时更容易)。
  • 每次covergroup采样, SV都会在一个或者多个cover bin中留下标记, 用来记录采样时变量的数值和匹配的cover bin。
  • 在仿真之后,可以使用分析工具读取这些数据库来生成覆盖率报告,包含了各部分和总体的覆盖率。

coverpoint和bin

  • 为了计算一个coverpoint上的覆盖率, 首先需要确定可能数值的个数,这也被称为域。
  • 覆盖率就是采样值的数目除以bin的数目。例如一个3比特变量的域是0:7, 正常情况下会自动分配8个bin。如果仿真过程中有7个值被采样到, 那么最终该coverpoint的覆盖率是7/8。
  • 所有的coverpoint的覆盖率最终构成一个covergroup的覆盖率。
  • 所有的covergroup的覆盖率构成了整体的功能覆盖率。

bin的创建和应用

  • SV会默认为某个cover point创建bin, 用户也可以自己定义bin的采样域。
  • 如果采样变量的域范围过大而又没有指定bin, 那么系统会默认分配64个bin, 将值域范围平均分配给这64个bin。
  • 用户可以通过covergroup的选项auto_bin_max来指定自动创建bin的最大数目(默认64)。
  • 实际操作中, 自动创建bin的方法不实用, 建议用户自行定义bin,或者减小auto_bin_max的数值。
covergroup CovPort;options.auto_bin_max=8; //所有cover point auto_bin数量=8coverpoint tr.port{options.auto_bin_maxm 2; } //特定cover point auto_bin数量=2
endgroup

命名coverpoint和bin

covergroup CovKind;coverpoint tr.kind{bins zero=(0) ; //1个仓代表kind==0bins lo=([1:3] , 5) ; //1个仓代表1:3和5bins hi[] =([8:S] 1; //8个独立的仓代表8:15bins misc=default; //1个仓代表剩余的所有值}//没有分号
endgroup
  • 注意coverpoint定义使用{} 而不是begin…end。大括号的结尾没有带分号, 这和end一样。

条件覆盖率

  • 可以使用关键词iff给coverpoint添加条件。
  • 这种做法常用于在复位期间关闭覆盖以忽略不合理的条件触发。
  • 也可以使用start和stop函数来控制covergroup各个独立实例。
covergroup CoverPort;coverpoint port iff (!bus_if.reset);
endgroup//===========================================initial beginCovPort ck = new();#1ns;ck.stop();bus_if.reset=1;#100ns bus_if.reset=0;ck.start();ck.sample();
end

翻转覆盖率

  • coverpoint也可以用来记录变量从A值到B值的跳转情况。
  • 还可以确定任何长度的翻转次数。
covergroup CoverPort;coverpoint port {bins t1 = (0=>1), (0=>2), (0=>3);}
endgroup

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

忽略bin

  • 在某些coverpoint可能始终无法得到全部的域值。
  • 对于那些不计算功能的域值可以使用ignore_bins来排除, 最终它们并不会计入coverpoint的覆盖率。
bit[2:0] low_ports_0_5; //只使用数值0-5
covergroup CoverPort;coverpoint low_ports_0_5 {ignore_bins hi={[6, 7]}; //忽略数值6-7
endgroup

非法的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

交叉覆盖率

  • coverpoint是记录单个变量或者表达式的观测值。
  • 如果想记录在某一时刻,多个变量之间值的组合情况,需要使用交叉(cross) 覆盖率。
  • cross语句只允许带coverpoint或者简单的变量名。
class Transaction;rand bit[3:0] kind;rand bit[2:0] port;
endclassTransaction tr;
covergroup CovPort;kind: coverpoint tr.kind; //kind是coverpoint名称port: coverpoint tr.port; //port是coverpoint名称cross kind, port;
endgroup

排除部分cross bin

  • 通过使用ignore bins、binsof和intersect分别指定coverpoint和值域, 这样可以清除很多不关心的cross bin。
covergroup Covport;port: coverpoint tr.port {bins port[] = {[O:$]};}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
  • 原来port有8个bin,kind有11个bin,正常cross会产生88个bin,通过ignore_bins,hi排除了11个,md排除了3个,lo排除了24个。具体自行分析。

指定精细的交叉覆盖率

  • 随着cross覆盖率越来越精细, 可能需要花费不少的时间来指定哪些bin应该被使用或者被忽略。
  • 更适合的方式是不使用自动分配的cross bin, 而自己声明感兴趣的cross bin。
  • 假如有两个随机变量a和b,它们带着三种感兴趣的状态,(a0,b0)、(a1、b0)和(b==1)。
class Transaction;rand bit a, b;
endclasscovergroup CrossBinNames;a: coverpoint tr.a {bins a0 = {0};bins a1 = {1};option.weight=0; } //不计算覆盖率b: coverpoint tr.b {bins b0 = {0};bins b1 = {1};option.weight=0; } //不计算覆盖率ab: cross a, b {bins aOb0 = binsof(a.a0) && binsof(b.b0);bins a1b0 = binsof(a.a1) && binsof(b.b0);bins b1   = binsof(b.bl);}
endgroup
class Transaction;rand bit a, b;
endclasscovergroup CrossBinsofIntersect;a: coverpoint tr.a {option.weight=0; } //Do nOt count this cover pointb: coverpoint tr.b {option.weight=0; } //Do nOt count this cover pointab: cross a, b {bins aOb0 = binsof(a) intersect{O} && binsof(b) intersect{O};bins alb0 = binsof(a) intersect{1} && binsof(b) intersect{O};bins b1 = binsof(b) intersect{1}; }
endgroup

覆盖选项

单个实例的覆盖率

  • 如果对一个covergroup例化多次, **那么默认情况下SV会将所有实例的覆盖率合并到一起。**如果需要单独列出每个covergroup实例的覆盖率,需要设置覆盖选项。
covergroup CoverLength;coverpoint tr.length;option.per_instance=l; //每个实例单独收集
endgroup

注释

  • 如果有多个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次就可以计入有效的bin。可以通过修改atleast来修改每个bin的数值最少的采样次数, 如果低于at_least数值, 则不会被计入bin中。
  • option.at_least可以在covergroup中声明来影响所有的coverpoint,也可以在coverpoint中声明来只影响该coverpoint下所有的bin。
  • 一般会使用默认的1,除非有特殊要求。

覆盖率目标

  • 一个covergroup或者一个coverpoint的目标是100%覆盖率。
  • 不过你也可以将其设置为低于100%的目标。这个选项只会影响覆盖率报告。
  • 一般会使用默认的100,除非有特殊要求。
covergroup CoverPort;coverpoint port;option.goal=90;
endgroup

covergroup方法

  • sample() : 采样。
  • get_coverage() /get_inst_coverage() : 获取覆盖率,返回0-100的real数值。
  • set_inst_name(string) : 设置cover group的名称。
  • start() /stop() : 使能或者关闭覆盖率的收集。

数据分析

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

参考资料

  • Wenhui’s Rotten Pen
  • SystemVerilog
  • chipverify

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

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

相关文章

动态属性的响应式问题和行内编辑的问题

动态属性的响应式问题 通过点击给目标添加动态数据&#xff0c;该数据不具备响应式特性 如下图&#xff1a; 点击编辑&#xff0c;前面的数据框会变成输入框&#xff0c;点取消会消失 // 获取数据 async getList () {const res await xxxthis.list res.data.rows// 1. 获…

【QT+QGIS跨平台编译】074:【libdxfrw跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、libdxfrw介绍二、QGIS下载三、文件分析四、pro文件五、编译实践一、libdxfrw介绍 libdxfrw是一个用于读取和写入DXF(Drawing Exchange Format)文件的开源C++库。DXF是一种由AutoCAD开发的文件格式,用于存储CAD(计算机辅助设计)图形数据,它…

使用 LLMLingua-2 压缩 GPT-4 和 Claude 提示

原文地址&#xff1a;Compress GPT-4 and Claude prompts with LLMLingua-2 2024 年 4 月 1 日 向大型语言模型&#xff08;LLM&#xff09;发送的提示长度越短&#xff0c;推理速度就会越快&#xff0c;成本也会越低。因此&#xff0c;提示压缩已经成为LLM研究的热门领域。 …

ensp华为AC+AP上线配置

AR1配置&#xff1a; <Huawei>system-view # 进入系统视图<Huawei>sysname R1 # 设备重命名[R1]dhcp enable # 开启DHCP功能[R1]interface GigabitEthernet0/0/0 # 进入接口 [R1-GigabitEthernet0/0/0]ip address 192.168.0.1 23 # 配置接口地址 [R1-GigabitE…

SpringBoot配置文件加载的优先级顺序

SpringBoot配置文件加载的优先级顺序 1.按文件类型2.按路径比较3.按命令行参数设置 1.按文件类型 SpringBoot的配置文件可以分为.properties .yml .yaml 在同一路径下&#xff08;比如都在classpath下&#xff09;三者的优先级顺序是.properties> .yml> .yaml 2.按路径…

基于tensorflow和kereas的孪生网络推理图片相似性

一、环境搭建 基础环境&#xff1a;cuda 11.2 python3.8.13 linux ubuntu18.04 pip install tensorflow-gpu2.11.0 验证&#xff1a;# 查看tensorflow版本 import tensorflow as tf tf.__version__ # 是否能够成功启动GPU from tensorflow.python.client import device_lib pr…

jvm基础三——类加载器

类加载器 在Java中&#xff0c;类加载器&#xff08;Class Loader&#xff09;是Java虚拟机&#xff08;JVM&#xff09;的一部分&#xff0c;负责将类文件&#xff08;.class文件&#xff09;加载到JVM中&#xff0c;使得程序能够使用这些类。类加载器在Java中具有重要的作用&…

6 种事件驱动的架构模式

事件驱动架构(Event-Driven Architecture)是一种基于事件和事件处理的软件架构&#xff0c;它的核心思想是将系统的行为和逻辑抽象成一系列事件&#xff0c;这些事件在系统中按照一定的规则和顺序产生和传播&#xff0c;并被相应的处理器处理。事件驱动架构具有高度的灵活性、可…

【数据结构】考研真题攻克与重点知识点剖析 - 第 3 篇:栈、队列和数组

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

LogicFlow 在HTML中的引入与使用

LogicFlow 在HTML中的引入与使用 LogicFlow的引入与使用&#xff0c;相较于BPMNJS相对容易一些&#xff0c;更加灵活一些&#xff0c;但是扩展代码可能写得更多一些。 示例展示 使用方式 这个的使用方式就简单很多了&#xff0c;利用cdn把js下载下来&#xff0c;引入到HTML文…

c语言之向main函数传递参数

在c语言中&#xff0c;main函数也是可以传递传递参数的&#xff0c;业内向main函数传递参数的格式是 main(int argc,char *argv[]) 向main函数传递参数不是通过代码传递的&#xff0c;一般是通过dos命令传递 举个例子 #include<stdio.h> void main(int argc,char *ar…

PyTorch之计算模型推理时间

一、参考资料 如何测试模型的推理速度 Pytorch 测试模型的推理速度 二、计算PyTorch模型推理时间 1. 计算CPU推理时间 import torch import torchvision import time import tqdm from torchsummary import summarydef calcCPUTime():model torchvision.models.resnet18()…

使用pip install替代conda install将packet下载到anaconda虚拟环境

问题描述 使用conda install 下载 stable_baseline3出现问题 一番搜索下是Anaconda.org缺少源 解决方法 首先使用管理员权限打开 anaconda prompt 然后激活目标环境&#xff1a;conda activate env_name 接着使用&#xff1a;conda env list查看目标env的位置 如D:\anacon…

2023.4.7 机器学习周报

目录 引言 Abstract 文献阅读 1、题目 2、引言 3、过去方案和Motivation 4、Segment Anything模型 5、创新点 6、实验过程 7、实验结果 1、评价绩效 2、检测评价 3、跟踪评价 8、 结论 总结 引言 本周阅读了一篇关于高效的任意分割模型的文献&#xff0c;用于自…

JVM基础:类的生命周期详解

JDK版本&#xff1a;jdk8 IDEA版本&#xff1a;IntelliJ IDEA 2022.1.3 文章目录 一. 生命周期概述二. 加载阶段(Loading)2.1 加载步骤2.2 查看内存中的对象 三. 连接阶段(Linking)3.1 连接之验证3.2 连接之准备3.3 连接阶段之解析 四. 初始化阶段(Initialization)4.1 单个类的…

Arcgis Pro地理配准

目录 一、目的 二、配准 1、找到配准工具 2、添加控制点 3、选择控制点 4、添加更多控制点 5、配准完成、保存 三、附录 1、查看控制点或删除控制点 2、效果不好怎么办 一、目的 下面我们将两张地图进行配准&#xff0c;其中一张有地理位置&#xff0c;而另外一张没…

前端面试高频: 理解 React/Vue 中 Key 的作用

一: 引言 在 React 或 Vue 项目中&#xff0c;我们经常在列表组件中使用key属性。key是给每一个vnode的唯一id&#xff0c;它在列表渲染和虚拟 DOM 操作中扮演着重要的角色。 当我们在渲染一个包含多个相同子组件的列表时&#xff0c;如果没有使用 key&#xff0c;React 或 Vue…

666666666666666666

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

Linux (Ubuntu)- mysql8 部署

目录 1.基本部署 2.修改密码 3.开启root可远程连接配置 1.基本部署 01》》先查看OS类型&#xff0c;如果是Ubuntu在往下边看 rootspray:/etc/mysql/mysql.conf.d# lsb_release -a LSB Version: core-11.1.0ubuntu2-noarch:security-11.1.0ubuntu2-noarch Distributor ID: …

备战蓝桥杯---线段树应用2

来几个不那么模板的题&#xff1a; 对于删除&#xff0c;我们只要给那个元素附上不可能的值即可&#xff0c;关键问题是怎么处理序号变化的问题。 事实上&#xff0c;当我们知道每一个区间有几个元素&#xff0c;我们就可以确定出它的位置&#xff0c;因此我们可以再维护一下前…