UVM学习知识点

UVM构建

    • include 和 import pkg区别
    • .sv .svh
    • hdl_top.sv和hvl_top.sv
    • 回顾uvm_config,以及自定义uvm_config
    • verilog:parameter、defparam与 localparam
    • test_base
      • build_phase
      • end_of_elaboration_phase
      • function void configure_agent
      • set_seqs
      • end_of_elaboration_phase
      • uvm_comfig_db#()set
    • env_config
      • do_cm_agent_cfg()
      • function cm_env_config get_config(uvm_component c)
    • cm_defines.svh
    • cm_cfg_pkg.svh
    • cm_ad_random_test
      • run_phase
    • hdl_top.sv
    • hvl_top
    • cm_env.svh
      • build
      • connect_phase
    • cm_env_pkg.svh
    • cm_virtual_sequencer
    • cm_agent
      • build
      • connect
    • cm_agent_config
    • cm_scoreboard
      • build
      • run
      • report_phase
    • cm _reference_model
    • driver
      • build
      • run
      • `get_config
      • driver 参数
    • cm_driver_bfm
    • cm_monitor
      • build
      • run
      • function
    • cm_monitor_bfm
    • cm_sequencer
    • Virtual Sequence & Virtual Sequencer
    • ?
      • 1
    • set 与 get 函数的参数

include 和 import pkg区别

1.作用
`include与C语言中类似,用于在一个文件中插入另一个文件;import用于在一个作用域中引入一个package(或其中的内容),使得这些内容在当前作用域中可以不添加其所在的package就能被识别。

2.用途
`include把一个文件平铺在插入的文件中,这个过程发生在编译前。

与verilog中类似,可以把宏定义的参数放在一个文件中,再使用`include插入所需的文件中,使代码更加整洁。

也可以将一个类写在一个头文件中,使用extern方法,在另一个文件中定义类中的方法,方便管理和加密,最后再将所有的文件统一`include到顶层,
而import发生在编译后,将已编译的package的作用域扩展到import的域中,例如文章开头的通过import引入uvm_pkg,从而使自己的验证环境可以使用UVM的特性和机制
在编程中,include 和 import 是两个常用的关键字,但它们在不同的编程语言和上下文中具有不同的含义和用法。

include:

include 是 C 和 C++ 编程语言中的预处理指令。它用于在源代码中包含外部文件的内容,通常用于包含头文件(header files)。
头文件通常包含函数声明、宏定义和数据结构的定义等内容,可以在多个源文件中共享和重用。
include 指令会在预处理阶段将被包含的文件的内容插入到当前文件中,相当于将文件内容复制粘贴到当前位置。
import:

import 是许多编程语言中用于导入外部模块或包的关键字,例如 Python、Java、JavaScript 等。
在不同的语言中,import 的用法和功能可能会有所不同。一般而言,它用于引入其他模块或包的定义,使得你可以在当前代码中使用这些定义。
在 UVM(Universal Verification Methodology)中,include 和 import 也有一些不同的用法和含义。
include 在 UVM 中:
在 UVM 中,include 通常用于包含 UVM 的库文件、基类和一些通用定义,例如 UVM 中的基类(uvm_object、uvm_component 等)和一些宏定义。
include 在 UVM 中用于将这些共享的定义引入到你的测试环境或测试用例中,以便你可以使用 UVM 提供的功能和方法。
import 在 UVM 中:
在 UVM 中,import 关键字用于引入 UVM 命名空间中的类或函数,以便在你的代码中可以直接使用它们的名称,而无需使用完整的命名空间路径。
UVM 使用了一系列的命名空间,例如 uvm_pkg 命名空间。通过 import 可以简化代码中对 UVM 类和方法的引用。
` include将文件中所有文本原样插入包含的文件中。这是一个预处理语句

`include在import之前执行。他的主要作用就是在package中平铺其他文件,从而在编译时能够将多个文件中定义的类置于这个包中,形成一种逻辑上的包含关系。

import不会复制文本内容。但是import可package中内容引入import语句所在的作用域,以帮助编译器能够识别被引用的类,并共享数据。在我们的TB中,include通常分为以下几类:

1)package内的include文件:在package内,前面是import library,比如“import uvm_pkg:😗”,紧接着即使include文件,通常会把本目录下相关的文件都include进来,比如virtual sequence文件,testcase文件。

2)package外的include文件:这种用法在我们现在的环境中使用不多,目前最常用的是include interface文件,比如,在xxx_env_pkg文件的最开头,include “xxx_if.sv”

3)为了文件管理方法,将部分code写到一个单独的文件中,然后在主文件中直接include进来,相当于将多个文件合并成一个文件。比如,一个subsys要用到很多API,而这些API共有A, B,C三类,分别由3个人完成,则可以写成api_a.sv, api_b.sv, api_c.sv,在l0_basic_vseq.sv中,将这三个文件include进来。

https://blog.csdn.net/Andy_ICer/article/details/115679314

.sv .svh

.svh后缀的文件即systemverilog include文件,如其名,是为了include到其它文件里面去的文件。
.sv 文件与.svh文件没有本质区别。通常,需要被include 到package的文件定义为.svh类型, 其他的文件定义为.sv类型。
.svh后缀的文件即systemverilog include文件。
1、package内的类应该用include分隔为单独的文件。
2、按照编译顺序排列。
3、include中不应该还包含include。

hdl_top.sv和hvl_top.sv

hdl_top.sv 和 hvl_top.sv 是在硬件设计和硬件验证中经常使用的两个文件,分别用于硬件描述语言(HDL)的顶层设计和硬件验证语言(HVL)的顶层测试环境。

hdl_top.sv:
这个文件通常用于硬件描述语言(如 Verilog、VHDL)中的顶层设计。
在 hdl_top.sv 文件中,你会描述整个硬件系统的结构、功能和连接关系。这可能包括处理器、外设、数据通路等。
该文件会被综合工具用来生成实际的硬件电路。
hvl_top.sv:
这个文件通常用于硬件验证语言(如 SystemVerilog)中的顶层测试环境。
在 hvl_top.sv 文件中,你会创建和配置测试环境,生成测试用例,并驱动这些测试用例进行硬件验证。
这个文件会包括 UVM(Universal Verification Methodology)或其他验证方法学的相关代码,以及测试用例生成和管理的逻辑。
在典型的硬件验证流程中,hdl_top.sv 和 hvl_top.sv 两者协同工作。hdl_top.sv 描述了你要验证的硬件设计,而 hvl_top.sv 创建了测试环境,使用测试用例对 hdl_top.sv 中的设计进行验证。

回顾uvm_config,以及自定义uvm_config

class env_config extends uvm_object

verilog:parameter、defparam与 localparam

在 Verilog 语言中,parameter、defparam 和 localparam 都是用来定义常量的关键字,但它们有不同的用途和范围。下面我会为您解释它们的区别:

parameter:
parameter 用于在模块级别定义一个常量,该常量在编译时被确定,并可以在整个模块中使用。
它用于指定在模块实例化时需要传递的参数值,这些参数值可以在模块的内部使用。也可以用于定义宏、宏定义和一些常量值。
在模块中,parameter 常量可以直接使用,无需使用模块的实例名称来引用。

module MyModule #(parameter PARAM_VALUE = 8);// PARAM_VALUE is a parameter with default value 8// You can use PARAM_VALUE within this module
endmodule

defparam:
defparam 用于在模块实例化之外设置模块的参数值。
通常在模块实例化后,使用 defparam 可以修改模块实例的参数值。这样做可以避免在模块定义时传递参数,而在实例化时设置参数,从而更灵活地控制模块行为。
defparam 在一些情况下可能会影响代码的可读性,因此在实践中应该谨慎使用。


module Test;MyModule my_inst(); // Instantiate the module
endmodule// Change the parameter value of my_inst using defparam
defparam my_inst.PARAM_VALUE = 10;

localparam:
localparam 用于在模块中定义一个局部常量,只能在该模块内部使用。
localparam 的值在编译时确定,但是它只在定义它的模块内部可见,无法在模块实例化时传递或在其他模块中使用。


module MyModule;localparam LOCAL_PARAM = 5; // A local parameter within the module
endmodule

总结:

parameter 用于定义模块内部的常量,可以在实例化时传递。
defparam 用于在模块实例化之外修改模块的参数值。
localparam 用于定义模块内部的局部常量,只在该模块内部可见。
1、最好运用模块在端口的声明方式,参数覆盖用参数值模块例化。

2、不要用defparam去修改在实体内声明的parameter,因为不可综合,用带参数值模块例化可以。

3、localparam参数可通过parameter赋值进行间接的修改,不能用其他方法修改。

两种声明方式混用时,vivado综合工具会把parameter变成local parameter,其他工具未知。

两种parameter声明方式混用的时候,defparam与参数值模块例化两种方法vivado均会报错,因为local parameter不可被直接改变。
单独使用parameter,无local的警告
https://zhuanlan.zhihu.com/p/420873197

test_base

例化
cm_env env
cm_env_config env_cfg
cm_agent_config agt_cfg
//methods
function void configure_cm_agent
//Standard methods
new
build_phase
set_seqs
function void end_of_elaboration_phase

build_phase

env_cfg
env
cm_agt_cfg
configure_cm_agent(agt_cfg)
get cm_mon_bfm,agt_cfg.mon_bfm
get cm_drv_bfm,agt_cfg.mon_bfm
env_cfg.agent_cfg = cm_agt_cfg
set (this, " * ",“cm_env_config”,env_cfg)
set (this, " * ",“cm_agent_config”,agt_cfg)

end_of_elaboration_phase

uvm_root::get().set_report_verbosity_level_hier(UVM_HIGH);
uvm_root::get().set_report_max_quit_count(10);

function void configure_agent

function void configure_cm_agent(agent_config cfg)
配置agt_configure
agt_cfg.active = …;

set_seqs

set_seqs(cm_base_virtual+sequence seq)
seq.cfg = env.cfg

end_of_elaboration_phase

在 UVM(Universal Verification Methodology)中,end_of_elaboration_phase 是一种阶段(phase),用于表示仿真环境中的一个特定时间点,通常用于进行一些最终的配置和准备工作,以便在仿真运行开始之前完成环境的设置。

具体来说,end_of_elaboration_phase 位于 UVM 测试基类 uvm_test 中的默认构造函数中,是 UVM 生命周期中的一个重要阶段。在这个阶段,测试环境的配置和连接已经完成,但还没有开始进行实际的仿真运行。

在 end_of_elaboration_phase 阶段,您可以执行以下操作:

完成环境的配置和连接:在此阶段,可以确认环境中的各个组件是否正确连接,并根据需要进行修复或调整。

设置参数和信号:您可以在此阶段设置各个组件的参数,包括一些与实际测试相关的参数。

收集信息和报告:您可以在此阶段生成一些初始化的报告,以便在仿真运行之前检查环境的状态和配置。

进行一些前期准备工作:例如,为测试用例生成随机种子、设置文件路径等。

需要注意的是,end_of_elaboration_phase 阶段是在 UVM 生命周期的早期阶段,仅用于环境的初始化和准备工作。在这之后,会进入 run_phase 阶段,开始进行实际的仿真运行。根据您的具体测试需求,您可以在 end_of_elaboration_phase 中执行适当的操作,以确保仿真环境在运行时处于正确的状态

这段代码是在 UVM(Universal Verification Methodology)中设置报告的详细程度和最大退出计数的操作。让我为您解释一下这两个函数的作用:

uvm_root::get().set_report_verbosity_level_hier(UVM_HIGH);:

这行代码设置了报告的详细程度(verbosity level)为 UVM_HIGH,这是一种 UVM 预定义的报告详细程度。
报告详细程度用于控制报告信息的显示级别。在高详细程度下,会显示更多的报告信息,包括警告和错误信息。
uvm_root::get() 返回 UVM 根实例,通过调用 set_report_verbosity_level_hier() 方法,您可以设置整个测试环境中所有组件的报告详细程度为 UVM_HIGH。
uvm_root::get().set_report_max_quit_count(10);:

这行代码设置了最大退出计数(max quit count)为 10。这是当发生错误时,仿真环境最多允许退出的次数。
如果测试中出现了一些严重错误,导致测试环境需要退出,但测试尚未结束,系统会尝试退出一定次数后继续进行,以便收集更多的错误信息。
该函数调用可以用于设置最大退出次数,以控制在错误情况下的退出行为。
这些函数调用的目的是在测试环境中配置报告行为和退出行为,以便更好地进行调试和错误定位。您可以根据需要选择不同的报告详细程度,并设置适当的最大退出计数,以符合您的测试需求。

uvm_comfig_db#()set

set第二个参数可以使用通配符*

get种一般第一个参数为this,则第二个参数可以是“”

env_config

localparam string s_my_config_id = “cm_env_config”
localparam string s_no_config_id =
localparam string s_my_config_type_error_id =

bit has_cm_function_coverage = 0;
bit has_cm_reg_scoreboard = 0;
//bit has_cm_scoreboard = 0;
//配置下属组件
cm_agent_config cm_agent_cfg
virtual cm_if vif
注册
extern static function cm_env_config get_config(uvm_component c)
new
do_cm_agent_cfg()

do_cm_agent_cfg()

cm_agent_cfg.name = ,,,;

赋值

function cm_env_config get_config(uvm_component c)

cm_env_config t;
get(c,“”, s_my_config_id ,t)
return t;

cm_defines.svh

cm_cfg_pkg.svh

cm_ad_random_test

注册
new
build_phase
task run_phase

run_phase

cm_ad_random_virt_seq random_ad_seq = create
phase.raise_objection(this,"cm_ad_random_test’);
random_ad_seq.start(env.m_vsqr);
#100ns;
phase.drop_objection(this,"cm_ad_random_test’);

hdl_top.sv

`timescale
logic clk
logic rstn
cm_if CM(clk, rstn)

//BFM interfaces
cm_monitor_bfm cm_mon_bfm
cm_driver_bfm cm_drv_bfm
//DUT
cm_math DUT(…
)

initial begin
import uvm_pkg::uvm_config_db;
set cm_mon_bfm
set cm_drv_bfm
end

initial begin
clk
end

initial begin
rstn
repeat(4)
rstn
end

hvl_top

`time
im uvm_pkg:😗 ;
im cm_test_lib_pkg:: *

initial begin
//vcd
end

initial begin
run_test();
end

cm_env.svh

注册
//data members
cm_env_config m_env_cfg;
cm_agent m_agt;
cm_scoreboard m_scb;
cm_viryual_sequencer  m_vsqr;new
build
connect_phase

build

//env_config
get (this, " * ","cm_env_config",m_env_cfg)
//agent_config
get (this, " * ","cm_agent_cfg",m_env_cfg.cm_agent_cfg)
m_agt = cm_agent::creat
if(m_env_cfg.has_cm_scoreboard)begin
m_scb = cm_scoreboard::type_id::creat(
set(this, "m_scb", "m_env_cfg", m_env_cfg);
//vsqr
set(this, "m_vsqr", "m_env_cfg", m_env_cfg);			//???
m_vsqr = cm_virtual_sequencer::type_id::creat(

connect_phase

if(m_env_has_complex_scoreboard)begin
magt.m_monitor.scb_ap.connect(m_scb.cm_imp.analysis_export);
end

m_vsqr.sqr = m_agt.m_sequencer

cm_env_pkg.svh

cm_virtual_sequencer

cm_sequencer sqr
cm_env_config cfg

virtual cm_vif vif

new
build
get (this, " * ",“cm_env_config”,cfg)
vif = cfg.vif

cm_agent

cm_gent_cofig m_cfg
m_monitor
m_sequencer
m_driver
m_subscriber

new
build
connect

build

get (this, " * ",“cm_agent_config”,m_cfg)

m_monitor = creat
m_monitor.m_cfg = m_cfg
set m_monitor

m_driver
m_driver.m_cfg = m_cfg
set m_driver

m_sequencer
set m_sequencer

m_subscriber

connect

scb_ap = m_monitor.scb_ap
m_driver.seq_item_port.connect(m_sequencer.seq_item_export)

m_monitor.sub_ap.connect(m_subscriber.analysis_export)

cm_agent_config

localparam string s_my_config_id = “cm_env_config”
localparam string s_no_config_id =
localparam string s_my_config_type_error_id =

virtual cm_monitor_bfm mon_bfm;
virtual cm_driver_bfm drv_bfm;

uvm_active_passive_enum active = UVM_ACTIVE;

bit has_cm_function_coverage = 1;
//bit has_cm_reg_scoreboard = 0;
rand bit has_scoreboard = 1;
好几个
field
//下面是个方法,set是在test_base.
function cm_agent_config get_config(uvn_component c)
cm_agent_config t;
get(c,“”, s_my_config_id ,t)
return t;

cm_scoreboard

cm_env_config cfg
uvm_tlm_analysis_fifo #(cm_seq_item) cm imp;

cm_reference_model complex_rm;
//data buffers
cm_seq_item tr_observed[ ] ; c m s e q i t e m t r e x p e c t e d [ ]; cm_seq_item tr_expected[ ];cmseqitemtrexpected[];

//cvoreboard var
new

build

new
new
get (this, " * ",“cm_env_config”,cfg)

run

cm_compare()

report_phase

cm _reference_model

//data_buffers
//statistics
//new

function void calculate()

driver

class cm_driver extends uvm_driver#(cm_seq.item,cm_seq_item);
virtual cm_driver_bfm m_bfm;
cm_agent_config m_cfg;
new
run
build

build

`get_config(cm_agent_config, m_cfg, “am_agent_config”)
m_bfm = m_cfg.drv_bfm

run

complex_seq_item req;
complex_seq_item rsp;
int psel_index;

m_bfm.m_cfg = m_cfg;

`get_config

`get_config(cm_agent_config, m_cfg, “am_agent_config”)
这段代码是使用 UVM(Universal Verification Methodology)中的 uvm_config_db 工具获取配置信息的示例。让我为您解释一下这段代码的含义:

get_config:这是 uvm_config_db 工具的一个方法,用于获取配置信息。

cm_agent_config:这是配置信息的目标对象的类型。在这个例子中,cm_agent_config 是一个类或数据结构,它定义了配置信息的格式。

m_cfg:这是一个变量,用于存储从配置数据库中获取的配置信息。根据代码,它似乎是一个类的实例。

“am_agent_config”:这是一个字符串,表示要获取的配置信息的名称。配置信息通常以字符串形式进行标识,以便在数据库中查找匹配的配置。

在上述代码中,get_config 方法的目的是从配置数据库中获取名为 “am_agent_config” 的配置信息,并将其存储在 m_cfg 变量中,该变量的类型是 cm_agent_config。

driver 参数

extends uvm_driver#(cm_seq.item, cm_seq_item):通过 extends 关键字,cm_driver 类继承自 uvm_driver 类,并在括号中使用泛型参数指定了序列项类型。具体来说:

uvm_driver#(cm_seq.item, cm_seq_item) 表示 cm_driver 是一个 uvm_driver 类的子类,其中 cm_seq.item 和 cm_seq_item 是泛型参数,分别表示输入序列项类型和输出序列项类型。

cm_driver_bfm

interface cm_driver_bfm(
cm_agent_config m_cfg
function ini_sigs
functio drive
)

cm_monitor

virtual cm_driver_bfm m_bfm;
cm_agent_config m_cfg;
uvm_analysis_port#(cm_seq_item) scb_ap;
uvm_analysis_port#(cm_seq_item) sub_ap;

new
run
build
report

build

`get_config(cm_agent_config, m_cfg, “cm_agent_config”)
m_bfm = m_cfg.mon_bfm
m_bfm.mnt = this;
new
new

run

m_bfm.run()

function

void cm_monitor::mnt.notofy_transaction(item);
scb_ap.write(item);
sub_ap.write(item);

cm_monitor_bfm

interface cm_monitor_bfm(
cm_monitor mnt
function ini_sigs
functio drive

task run();

mnt.notofy_transaction(item);

)

cm_sequencer

cm_agent_config cfg
new
build
reconfigure(cm_agent_config cfg)
get_cfg(ref cm_agent_config cfg_)

Virtual Sequence & Virtual Sequencer

https://zhuanlan.zhihu.com/p/369681031#%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E9%9C%80%E8%A6%81%E4%B8%80%E4%B8%AAvirtual%20Sequencer%EF%BC%9F

?

1

extern virtual function void configure_complex_agent(complex_agent_config cfg)function void tesr_base::configure_complex_agent(complex_agent_config cfg);
agt_cfg.active = UVM_ACTIVE;

set 与 get 函数的参数

1.写信
在这里插入图片描述

1)第一个和第二个参数联合起来组成目标路径,与此路径符合的目标才能收信。

2)第一个参数必须为uvm_component 的实例的指针。

3)第二个参数是相对于此实例的路径。

2.收信

在这里插入图片描述

1)第一个参数必须为uvm_component 的实例的指针。

2)第二个参数是相对于此实例的路径。如果第一个设置为 this,第二个可以是空的字符串。
3)第三个参数必须和set中的严格一样。

3.在top_tb 中,set virtual interface 的第一个参数是null。UVM会自动把它替换成uvm_root::get(),即uvm_top。(uvm_root是全局的,get是静态的)

4.既然是第一个和第二个参数联合起来的,set 也可以是下面:
在这里插入图片描述

5 get也可以这样,比如driver的build_phase:
在这里插入图片描述

https://blog.csdn.net/tingtang13/article/details/46458869

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

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

相关文章

Shell编程——弱数据类型的脚本语言快速入门指南

目录 Linux Shell 数据类型 变量类型 运算符 算术运算符 赋值运算符 拼接运算符 比较运算符 关系运算符 控制结构 顺序结构 条件分支结构 if 条件语句 case 分支语句 循环结构 for 循环 while 循环 until 循环 break 语句 continue语句 函数 函数定义 …

【数学建模】清风数模更新5 灰色关联分析

灰色关联分析综述 诸如经济系统、生态系统、社会系统等抽象系统都包含许多因素,系统整体的发展受各个因素共同影响。 为了更好地推动系统发展,我们需要清楚哪些因素是主要的,哪些是次要的,哪些是积极的,哪些是消极的…

@RequestHeader使用

RequestHeader 请求头参数的设置 GetMapping("paramTest/requestHeader")public String requestHeaderTest(RequestHeader("name") String name){return name;} 在Postman的Headers中添加请求头参数,不过貌似不能加中文

DMA技术

先总结: DMA是指外部设备不通过CPU而直接与系统内存交换数据的接口技术 主要工作是由DMA控制器来完成的. 下面开始正文 ---------------------------------------------------------------------------- 1、DMA由来 DMA(Direct Memory Access,直接存储器访问)。在&#xf…

Java基础篇--错误处理机制

尽管人人希望自己身体健康,处理的事情都能顺利进行,但在实际生活中总会遇到各种状况,比如感冒发烧,工作时电脑蓝屏、死机等。同样,在程序运行的过程中,也会发生各种非正常状况,例如,…

【腾讯云 Cloud Studio 实战训练营】Hexo 框架 Butterfly 主题搭建个人博客

什么是Cloud Studio Cloud Studio 是基于浏览器的集成式开发环境(IDE),为开发者提供了一个永不间断的云端工作站。用户在使用 Cloud Studio 时无需安装,随时随地打开浏览器就能在线编程。 ​ Hexo 博客成品展示 本人博客如下&…

14-矩阵相乘及其运算法则

矩阵与向量的乘法 在这一篇文章中我们就将基于上一篇重新审视矩阵的这个视点来理解矩阵的乘法,那么在这一篇,我们主要来看一下矩阵和向量的乘法。这里这个线性方程组是上一小节给大家举的模拟的一个非常简单的小型经济系统的例子,我们可以把…

【JAVA】变量的作用域与生存周期

个人主页:【😊个人主页】 系列专栏:【❤️初识JAVA】 文章目录 前言变量的作用域变量的生命周期局部变量全局变量 前言 变量,我们学习过程中逃不掉的知识,无论在哪种语言中我们都需要学会去合理的运用它,今…

IP 协议的相关特性和数据链路层相关知识总结

目录 IP 协议的相关特性 一、IP协议的特性 二、 IP协议数据报格式 三、 IP协议的主要功能 1. 地址管理 动态分配 IP地址 NAT机制 NAT背景下的通信 IPV6 2. 路由控制​​​​​​​ 3.IP报文的分片与重组 数据链路层相关知识 1、以太网协议(Ethernet) 2.M…

Java:正则表达式案例:爬数据,重复数据替换,数据分割

使用正则表达式查找一段文本中的内容 需求:请把下面文本中的电话,邮箱,座机号码,热线都爬取出来。 String data "电话:1866668888,18699997777\n" "或者联系邮箱: boniuitcast.cn,\n" "座机…

Spring的三种异常处理方式

1.SpringMVC 异常的处理流程 异常分为编译时异常和运行时异常,编译时异常我们 try-cache 进行捕获,捕获后自行处理,而运行时异常是不 可预期的,就需要规范编码来避免,在SpringMVC 中,不管是编译异常还是运行…

OpenCV-Python中的图像处理-霍夫变换

OpenCV-Python中的图像处理-霍夫变换 霍夫变换霍夫直线变换霍夫圆环变换 霍夫变换 霍夫(Hough)变换在检测各种形状的技术中非常流行,如果要检测的形状可以用数学表达式描述,就可以是使用霍夫变换检测它。即使要检测的形状存在一点破坏或者扭曲也是可以使…

C++——oo的魅力之多态

文章目录 多态的概念多态的定义和实现多态的构成条件虚函数重写的两个例外协变(基类和派生类虚函数返回值类型不同)析构函数的重写(基类和派生类析构函数名字不同) c11 override 和 final关键字 重载,重写(覆盖), 隐藏(重定义)对比抽象类(纯虚函数)多态的…

docker安装及优化详解

目录 一、部署20版的docker 1.1 安装依赖包 1.2 设置阿里云镜像源 1.3 安装docker-ce 社区版 1.4 关闭增强机制 1.5 开启服务 1.6 设置镜像加速 1.7 网络优化 二、linux 系统中的命令 记10条(cd ls pwd mv cp ) 2.1 查询docker 版本 2.2 搜索镜像 2.3 技能点 2.…

实例038 设置窗体在屏幕中的位置

实例说明 在窗体中可以设置窗体居中显示,本例通过设置窗体的Left属性和Top属性可以准确设置窗体的位置。运行本例,效果如图1.38所示。 技术要点 设置窗体在屏幕中的位置,可以通过设置窗体的属性来实现。窗体的Left属性表示窗体距屏幕左侧的…

C语言 字符指针

1、介绍 概念: 字符指针,就是字符类型的指针,同整型指针,指针指向的元素表示整型一样,字符指针指向的元素表示的是字符。 假设: char ch a;char * pc &ch; pc 就是字符指针变量,字符指…

Linux安装Docker

一、Docker系统版本介绍 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 或 Windows 操作系统的机器上,也可以实现虚拟化。 容器是完全使用沙箱机制,相…

常识判断

头像 carrin~👻 产品经理 225/753 75/302.5 30/152 15/101.5 等差数列,所以最后一个是10/101 收起 60 回复 发布于 2020-02-18 16:33

学习篇之React Fiber概念及原理

什么是React Fibber? React Fiber 是 React 框架的一种底层架构,为了改进 React 的渲染引擎,使其更加高效、灵活和可扩展。 传统上,React 使用一种称为堆栈调和递归算法来处理虚拟 DOM 的更新,这种方法在大型应用或者…

React+Typescript清理项目环境

上文 创建一个 ReactTypescript 项目 我们创建出了一个 React配合Ts开发的项目环境 那么 本文 我们先将环境清理感觉 方便后续开发 我们先来聊一下React的一个目录结构 跟我们之前开发的React项目还是有一些区别 public 主要是存放一些静态资源文件 例如 html 图片 icon之类的 …