详解VHDL如何编写Testbench
1.概述
仿真测试平台文件(Testbench)是可以用来验证所设计的硬件模型正确性的 VHDL模型,它为所测试的元件提供了激励信号,可以以波形的方式显示仿真结果或把测试结果存储到文件中。这里所说的激励信号可以直接集成在测试平台文件中,也可以从外部文件中加载。
一般而言,编写 Testbench 进行测试主要有下面四个步骤
- (1)实例化需要测试的设计(DUT,Design Under Test);
- (2)产生模拟激励(波形);
- (3)将产生的激励加入到被测试模块并观察其输出响应;
- (4)将输出响应与期望进行比较,从而判断设计的正确性。
其中,输出响应可以以波形方式显示或存储测试结果到文件中。
2.Testbench程序基本结构
通常 Testbench 的基本结构包括库的调用、程序包的调用、空实体、结构体描述。在结构体描述中,一般包含有被测试元件的声明、局部信号声明、被测试元件例化、激励信号的产生,如图所示。与一般的 VHDL 程序不同的是,Testbench 里面的实体为空。

2.1 被测试元件的声明方式
先说一个被测实体vote7,代码如下:
library ieee;
use ieee.std_logic_1164.all;entity vote7 is port(vt : in std_logic_vector(6 downto 0);result : out std_logic);
end entity vote7;architecture rtl of vote7 is
beginprocess(vt)variable sum : integer range 0 to 7;beginsum := 0;for i in 0 to 6 loopif vt(i) = '1' thensum := sum + 1;if sum > 4 thenresult <= '1';elseresult <= '0';end if;end if;end loop;end process;
end architecture;
2.1.1 组件实例化
组件实例化是一种传统且常用的方法,特别适用于较早版本的VHDL(如VHDL-93)。该方法需要在测试平台中先声明一个组件,然后在架构中进行实例化。
步骤
-
组件声明:在测试平台的架构声明部分(通常在
architecture关键词之后)声明DUT的组件。 -
实例化:在架构的主体部分使用
component实例化DUT,并进行端口映射。
示例代码
假设有一个被测实体vote7,其声明如下:
library ieee;
use ieee.std_logic_1164.all;entity tb_vote7 is
end entity tb_vote7;architecture Behavioral of tb_vote7 is-- 信号声明……-- 组件声明component vote7port(vt : in std_logic_vector(6 downto 0);result : out std_logic);end component;begin-- DUT实例化DUT: vote7port map (vt => vt,result => result);-- 激励过程……
end architecture Behavioral;
2.1.2 直接实体实例化
直接实体实例化(也称为架构实例化)是VHDL-2002及更高版本中引入的一种更简洁的实例化方式。它不需要提前声明组件,直接引用实体和架构即可。
优点
- 简洁:无需组件声明,减少了代码冗余。
- 灵活:可以直接指定要使用的实体和架构。
使用与前述相同的vote7实体,测试平台采用直接实体实例化的方法如下:
library ieee;
use ieee.std_logic_1164.all;entity tb_vote7 is
end entity tb_vote7;architecture Behavioral of tb_vote7 is-- 信号声明……
begin-- DUT直接实例化DUT: entity work.vote7(rtl)port map (vt => vt,result => result);-- 激励过程……
end architecture Behavioral;
代码解析
- DUT实例化:使用
entity work.vote7(rtl)指定实体vote7和其架构rtl,然后进行端口映射。 - 无需组件声明:省略了组件的预先声明,代码更加简洁。
3.激励信号的产生
激励信号产生的方式一般有两种,一种是以一定的离散时间间隔产生激励信号,另一种是基于实体的状态产生激励信号。需要注意的是,在 Testbench 程序中一定要对所有的激励信号赋初始值。下面通过实例,讲述激励信号的产生方法。
3.1 时钟信号的产生
时钟信号属于周期性出现的信号,是同步设计中最重要的信号之一。如图所示,时钟信号分为两类,即占空比为50%的对称时钟信号与占空比不是 50%的非对称时钟信号。

Testbench 中产生时钟信号方式有两种,
- 一种是使用并行的信号赋值语句;
- 一种是使用process进程。
下面分别通过两个例子来说明如何用这两种方法来产生所需的时钟信号。
【例】用并行信号赋值语句产生如图所示的 clk1、clk2、clk3 信号。

观察上图,我们发现 clk1 为对称时钟信号,其初始值可以在信号定义时赋值;clk2 和 clk3为非对称时钟信号,其起始值可以在语句中赋值。这两种信号的产生方式有所不同,相对而言对称时钟信号的产生相对简单一些。
并行信号赋值语句的实现如下:
signal clk1:std_logic := '0';
signal clk2:std_logic;
signal clk3:std_logic;
……
clk1 <= not clk1 after clk_period/2;
clk2 <= '0' after clk_period/4 when clk2 = '1' else'1' after 3*clk_period/4 when clk2 = '0' else'1';
clk3 <= '0' after clk_period/4 when clk3 = '1' else'1' after 3*clk_period/4 when clk3 = '0' else'0';
……
【例】使用 process 进程产生如图所示的clk1、clk2 信号。

观察上图,可以发现 clk1 为对称时钟信号,clk2 为非对称时钟信号,但这两种信号用 process 进程实现的方法基本一致。
process 进程实现如下:
signal clk1:std_logic;
signal clk2:std_logic;
……
clk1_gen:processconstant clk_period :time := 40ns;--常量只在该进程中起作用beginclk1 <= '1';wait for clk_period/2;clk1 <= '0';wait for clk_period/2;end process;
clk2_gen:processconstant clk_period :time := 20ns; --常量只在该进程中起作用beginclk2 <= '0';wait for clk_period/4;clk2 <= '1';wait for 3*clk_period/4;end process;
……
3.2 复位信号的产生
Testbench中产生复位信号方式也是两种,一种是并行赋值语句实现,另一种是在进程中设定。下面用例加以说明。
【例 7-5】如图所示,请用并行信号赋值语句产生的reset1信号,用 process 进程产生reset2信号。

程序如下:
……
signal reset1:std_logic;
signal reset2:std_logic;
……
-- 并行信号赋值语句产生的reset1信号
reset1 <= '0','1' after 20 ns,'0' after 40ns;--用process进程产生reset2信号
reset2_gen:processbeginreset2 <= '0';wait for 20 ns;reset2 <= '1';wait for 40 ns;reset2 <= '0';wait;
end process;
……
3.3 使用delayed属性产生两相关性信号
delayed是VHDL的预定义属性,使用它可以产生两个相关性的信号。如果已经产生了一个时钟信号,在这个时钟信号的基础上,可以使用delayed来使已经产生的时钟信号延迟一点的时间,从而获得另一个时钟信号。
假设已经使用如下的语句定义了一个时钟信号W_CLK:
W_CLK<= '1' after 30 ns when W_CLK= '0' else'0' after 20 ns;
然后可以使用如下的延迟语句获得一个新的时钟信号DLY_W_CLK,它比W_CLK延迟了10 ns:
DLY_W_CLK <= W_CLK' delayed(10 ns);
以上两个时钟信号波形如图所示:

【例 】 如图所示,请编程实现信号 periodl,period2,要求用到 DELAYED 属性。

程序如下:
signal period1,period2:std_logic;
……
period1 <= '1' after 30 ns when period1 = '0' else'0' after 20 ns when period1 = '1' else'0';--利用delayed属性,由period1产生period2
period2 <= period1' delayed(10 ns);
3.4 一般激励信号
一般的激励信号通常在 process 进程中定义,而在 process 进程中一般需要使用 wait 语句。所定义的普通的激励信号常用来作模型的输入信号。
【例】 如图 7-18 所示,请编程产生信号 test vectorl 和 test vector2。

程序如下:
signal test_vector1:std_vector_logic(1 downto 0);
signal test_vector2:std_vector_logic(1 downto 0);
……
TB1:process
begintest_vector1 <= "01";wait for 10 ns;test_vector2 <= "10";wait for 20 ns;
end process;TB2:process
begintest_vector2 <= "01";wait for 10 ns;test_vector2 <= "10";wait;
end process;
【例 】 输入信号 test_ab 和 test_sel 均为 2bit,试用 VHDL 产生这两个输入信号以覆盖所有的输入情况。输入信号向量 test_ab 和 test_sel 均为 2bit,产生的输入情况共有(2x2)x(2x2)=16 种可能。
实现的程序如下
signal test_ab : std_logic_vector(1 downto 0);
signal test_sel:std_logic_vector(1 downto 0);double_loop:process
begintest_ab <= "00";test_sel <= "00";for i in 0 to 3 loopfor j in 0 to 3 loopwait for 10 ns;test_ab <= test_ab + 1;end loop;test_sel <= test_sel + 1;end loop;
end process;
程序对应的波形如图所示:

特别注意:如果同一个信号在两个进程中进行赋值,若在某些时间段内发生了冲突,就会出现不定状态,如下例所示。因此同一信号不允许在不同进程中赋值。
【例】同一个信号在两个进程中进行赋值,在某些时问段内发生了冲突,出现不定状态的情况。
程序如下:
……
signal test_vector:std_logic_vector(2 downto 0);
signal reset:std_logic;
……
gen_1:process
beginreset <= '1';wait for 100 ns;reset <= '0';test_vector <= "000";wait;
end process;gen_2:process
beginwait for 200 ns;test_vector <= "001";wait for 200 ns;test_vector <= "011";
end process;
……
对应的波形如图所示:

3.5 动态激励信号
动态激励信号,就是输入激励信号与被仿真的实体(DUT)的行为模型相关,即 DUT 的输入激励信号受模型的行为所影响。
如下信号的定义,模型的输入信号 sig_A 就和模型输出信号 count 相关。
process(count)
begincase count iswhen 2 =>sig_A <= '1' after 10 ns;when others =>sig_A <= '0' after 10 ns;end case;
end process;
3.6 测试矢量
在实际应用中,常常将一组固定的输入输出矢量值存储在一个常量表或一个 ASCI 文件中,然后将这些值应用到输入信号从而产生激励信号。这里所说的固定输入输出矢量值就称为测试矢量。矢量的值序列可以使用多维数组或使用多列记录来描述。
如下面的数据表存储了输入矢量:
constant no_of_bits:integer := 4;
constant no_of_vectors:integer := 5;
type table_type is array (1 to no_of_bits) of std_logic_vector(1 to no_of_vectors);
constant input_vectors:table_type := ("1001","1000","0010","0000","0110");signal inputs:std_logic_vector(1 to no_of_vectors);
signal A,B,C:std_logic;
signal D:std_logic_vector(0 to 1);
假设所测试的实体(DUT)具有4个输入:A、B、C和D信号,如果以一般的时间间隔应用测试矢量,则可以使用一个generate语句,例如
G1:for j in 1 to no_of_vectors generateinputs <= input_vectors(j) after (vector_period*j);
end generate;A <= inputs(1);B <= inputs(4);C <= inputs(1);D <= inputs(2 to 3);
如果将信号应用于任意时间间隔,则需要使用并行的信号赋值语句产生多个信号的波形,使用这种方法可以将一个矢量赋值给多个信号,如下面的代码:
inputs <= input_vector(1) after 10 ns;input_vector(2) after 25 ns;input_vector(3) after 30 ns;input_vector(4) after 32 ns;input_vector(5) after 40 ns;
4.高级Testbench编写
高级Testbench 是在简单 Testbench 基础上改进的,能够自动读入测试矢量文件、完成输出值和期望值的比较等功能,如图所示。相比简单Testbench,高级 Testbench 更显得智能化,也减少了人工分析的烦琐工作。

4.1 文件I/O的读写
仿真时,VHDL 允许设计人员从文件加载数据或将数据存储到文件中。比如用户定义的测试矢量可以保存在文件中,然后在仿真时从文件中读取这些测试矢量。另外,仿真的结果也可以保存在文件中。
VHDL 标准中的文件 I/O 主要是由 TEXTIO 程序包提供的,用于仿真且综合工具不能综合标准库 STD 中的 TEXTIO 定义的程序包只能使用 BIT 和 BIT_VECTOR 数据类型,其引用的格式为:
library std;
use std.textio.all;
如果要使用std_logic和std_logic_vector,则需要调用std_logic_textio,格式为:
library ieee;
use ieee.std_logic_textio.all;
4.1.1 TEXTIO介绍
TEXTIO 是 VHDL 标准库 STD 中的一个程序包(package)。在该包中定义了三个基本类型:LINE 类型、TEXT 类型以及 SIDE 类型。另外,还有一个子类型(subtype)WIDTH。此外,在该程序包中还定义了一些访问文件所必须的过程(procedure),如图所示。

其中,TEXT为ASCII文件类型。定义成TEXT类型的文件是长度可变的ASCII文件,需要注意的是VHDL’87 和 VHDL’93 在使用文件方面由较大的差异,在编译时注意选择对应的标准。
side只能有两种状态,即right和left,分别表示将数据从左边还是从右边写入行变量。该类型主要是在TEXTIO程序包包含的过程中使用。
WIDTH为自然数的子类型。所谓子类型表示其取值范围是父类型范围的子集。
TEXTIO 也提供了基本的用于访问文本文件的过程。类似于 C++,VHDL 提供了重载功能,即完成相近功能的不同过程可以有相同的过程名,但其参数列表不同,或参数类型不同或参数个数不同。
TEXTIO 提供的基本过程有:
1.procedure READLINE(文件变量;行变量);
用于从指定文件读取一行数据到行变量中。
2.procedure WRITELINE(文件变量:行变量):
用于向指定文件写入行变量所包含的数据。
3.procedure READ(…);
可重载,用于从行变量中读取相应数据类型的数据。
4.procedure WRITE(…);
可重载,用于将数据写入行变量
4.1.2 文件基本操作
1.定义文件
TEXTIO 程序包中可操作的文件主要包含两大类:integer 和 text。
integer 文件中的数据是以二进制存取的,不能被人识别,只有 integer 型的数据能够存入这类文件。
text 文件是可以读取的 ASCI 码,可以被人识别。integer 、bit vector(x downto x)、string(x downto 1)、std logic_vector(x downto 0)及 bit 等类型都可以被存入此类文件。
对文件进行操作之前,需要对将要进行操作的文件进行定义,在 93 版的 VHDL 中,文件定义的方式如下:
FIE file handle: text open read mode is"目录十文件.后缀"---(输入文件的说明)
FIE file handle: text open write mode is"目录十文件.后缀"---(输出文件的说明)
在 87 版的 VHDL 中,文件定义的方式:
FIEL file handle: text is in"目录十文件.后缀"---(输入文件的说明)
FIEL file handle: text is out"目录十文件.后缀"---(输出文件的说明)
如果在支持 93 版的 VHDL 语言中使用了 87 版的格式,仿真时会提示:
warning: FIE declaration was written using 1076-1987 syntax.
2.打开文件
定义文件句柄后就可以在程序中打开指定文件,同时指定打开模式。93 版的 VHDL 可以使用 file open()进行文件打开操作,其中文件打开操作的函数使用方法如下:
file_open(fstatus,file_handle,filename)
其中,fstatus指示当前文件状态,但是在使用前首先得定义:
variable fatatus:file_open_status;
状态一般有四种,即open_ok,status_error,name_error,mode_error。
file handle 即是上一步定义的文件句柄file handle。
filename 是以双引号括起的文件名,如"datain.txt",也可以加上文件路径。openmode 是指打开该文件的模式,文件打开有read_mode,write mode,append_mode 三种。
3.读写文件
打开文件后就可以对文件进行读写操作,其语句格式如下:
--将文件中的一行数据读至行变量中。
realine(文件变量,行变量);--行变量中保存的数据取n位放至数据变量v中,n为数据变量v的数据位数。在此之前,需要定义好行变量和数据变量。
read(行变量,数据变量);--将一个数据写到某一行中。
write(行变量,数据变量);--起始位置为left 或 righ,字符数则表示数据变量写入到行变量后占的位宽。
write(行变量,数据变量,起始位置,字符数);--将行变量包含的数据写入到指定文件;
wwriteline(文件变量,行变量);
4.关闭文件
在文件读写完毕后,需使用 file)close(file handle)关闭文件。
如果想判断在文件操作中是否读取到文件的末尾,可以使用函数endfile(file_handle)进行判断,如果到达文件末尾将返回“真(true)”,否则返回“假(false)”。
下面举一个例子,使用了上面介绍的各种语法。
【例】文件I/O读写例程
library ieee;
library std;use std.textio.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;entity testin is
end entity testin;architecture rtl of testin is
beginprocess-- 定义text类型得文件句柄file file_out1,file_in:text; -- 定义文件状态指示变量variable fstatus1,fstatus2:file_open_status;variable count:integer := 5;variable stringdata:string(5 downto 1) := "SCUTE"; --string型variable vectordata:bit_vector(5 downto 0) := "001000";variable value:std_logic_vector(3 downto 0) := "1111";variable buf,buf1:line;begin--创建并打开文件file_open(fstatus1,file_out1,"DATAIN.TXT",write_mode);write(file_out1,string'("THE FIRST PAPAMETER IS ="));readline(input,buf);write(buf,count);writeline(file_out1,buf);wait for 20 ns;write(buf,string'(THE SECOND PAPAMETER IS = "));write(buf,value);writeline(file_out1,buf);wait for 20 ns;write(buf,string'("THE THIRD PAPAMETER IS = "));write(buf,vectordata);writeline(file_out1,buf);wait for 20 ns;write(buf,string'("THE FORTH PAPAMETER IS = "));write(buf,stringdata);writeline(file_out1,buf);write(file_out1,string'("END OF FILE"));file_close(file_out1);wait for 100 ns;file_open(fstatus1,file_out1,"DATAIN.TXT",read_mode);readline(file_out1,buf);writeline(output,buf);file_close(file_out1);wait for 100 ns;file_open(fstatus1,file_in,"STD_INPUT",read_mode);file_open(fstatus2,file_out1,"STD_OUTPUT",write_mode);readline(file_in,buf);writeline(file_out1,buf);wait;end process;
end rtl;
在modelsim中运行,控制台将做如下操作:

等待数秒后,在modelsim工程目录下将会新建一个“DATAIN.TXT”文本文档,打开文档其内容如图所示:

4.2 断言语句
断言语句(Assert)语句可以在仿真的过程中,检查一个条件并报告信息,一般用于程序调试与时序仿真时的人机对话,也是不可综合的语句。
断言语句的书写格式为:
assert<条件表达式>report<出错信息>severity<错误级别>;
其中,ASSERT 后的条件表达式为布尔表达式,用于模拟执行时的真假判断。若其值为“真”则跳过下面两个子句,继续执行后面的语句;若其值为“假”,则表示出错,于是执行 REPORT报告出错信息,同时由 SEVERITY 子句给出错误等级。
ASSERT 后的条件表达式由设计人员自行拟定,没有默认格式。断言语句里面的出错信息与错误等级也都由设计者自行设计,VHDL不自动生成这些信息。而且,REPORT 后的出错信息必须是字符串,需要用双括号括起来,若缺省出错信息,则系统默认输出错误信息报告为"Assertion Violation"。SEVERITY 后的错误级别要求是预定义的四种错误之一, 预定义的四种错误类型分别是:Note(通报)、Warning(警告)、Error(错误)、Failure(失败)。若缺省,则默认为 Error。
4.2.1 断言语句的使用方法
断言语句可以在实体、结构体以及进程中使用。下面通过一个例子初步介绍断言语句在仿真时的应用。
【例】用断言语句判断仿真的时间,如果当前时间为1000ns,则仿真完成,使用 ERROR严重级别终止仿真过程。
程序如下:
process
begin
assert(now <= 1000 ns)report "simulation completed successfully"severity error;
end process;
断言语句判断条件的判断结果为 FALSE,则执行后面的报告及严重级语句,否则跳过这些错误报告语句并继续执行。
放在进程内的断言语句叫顺序断言语句,它在进程内按照顺序执行。放在进程外部的断言语句叫并行断言语句。并行断言语句本质上等同于一个进程,该进程只对条件表达式给出的所有信号敏感。
如果把断言语句单独放在一个进程里面,则该进程称为断言进程。断言进程只能放在结构体里面,且不对任何信号进行赋值操作。下例就是一个断言进程语句。
【例】 使用 ASSERT 语句设定一个判断条件,以便对仿真的某个结果或值做出响应
……
process(q)
begin
assert(q /= "1001")report "the shifter gets the result!"severity error;
end process;
在上面的程序中,如果信号q等于“1001”,则终止仿真,并输出 The shifter gets the result!。
4.2.2 断言语句的应用实例
下面以一个简单的实例来讲述使用断言语句来响应一个仿真的过程。
【例】 4位加减计数器的仿真。所述4位加减计数器的位数为4位,且带有 CLR 清零端。当 DIR 信号为高电平时,计数器为加1计数器;当 DIR 信号为低电平时,为减1计数器。
4 位加减计数器的设计程序如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;entity counter is port(clk,clr,dir:in std_logic;result :out std_logic_vector(3 downto 0));
end entity counter;architecture rtl of counter is
signal tmp:std_logic_vector(3 downto 0);
begin
process(clk,clr)
beginif(clr = '1') thentmp <= "0000";elsif(clk' event and clk = '1') thenif(dir = '1') thentmp <= tmp + 1;elsetmp <= tmp - 1;end if;end if;
end process;result <= tmp;end rtl;
4位加减计数器的仿真程序如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned;entity tb_counter is
end entity tb_counter;atchitecture rtl of tb_counter issignal clk :std_logic := '0';
signal clr :std_logic := '0';
signal dir :std_logic := '0';
signa result :std_logic_vector(3 downto 0);
constant clk_period:time := 40 ns;beginuut:entity work.counter(rtl)port map(clk => clk,clr => clr,dir => dir,result => result);clk_gen:process
beginclk <= '0';wait for clk_period/2;clk <= '1';wait for clk_period/2;
end process;TB:process
beginclr <= '1';dir <= '1';wait for 20 ns;clr <= '0';wait for 280 ns;dir <= '0';wait for 320 ns;wait;
end process;process(result)
beginassert(result /= "1001")report "THe counter gets to nine!"severity error;
end process;
end rtl;
仿真波形如下图所示:

当计数到“1001”时,在信息栏输出

相关文章:
详解VHDL如何编写Testbench
1.概述 仿真测试平台文件(Testbench)是可以用来验证所设计的硬件模型正确性的 VHDL模型,它为所测试的元件提供了激励信号,可以以波形的方式显示仿真结果或把测试结果存储到文件中。这里所说的激励信号可以直接集成在测试平台文件中,也可以从…...
冥想的实践
这是我某一天的正念和冥想实践,我对正念练习、冥想练习进行了分别的统计。 正念练习:1分钟**5次 冥想:15分钟10分钟 正念练习,基本在工作休息时间练习。当然,工作过程中,也有一部分时间会有正念的状态&am…...
STM32F103RCT6学习之四:定时器
1.基础 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、…...
如何在网页端使用 IDE 高效地阅读 GitHub 源码?
如何在网页端使用 IDE 高效地阅读 GitHub 源码? 前言什么是 GitHub1s?使用 GitHub1s 阅读 browser-use 项目源码步骤 1: 打开 GitHub 项目页面步骤 2: 修改 URL 使用 GitHub1s步骤 3: 浏览文件结构步骤 4: 使用代码高亮和智能补全功能步骤 5: 快速跳转和…...
易基因: BS+ChIP-seq揭示DNA甲基化调控非编码RNA(VIM-AS1)抑制肿瘤侵袭性|Exp Mol Med
大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 肝细胞癌(hepatocellular carcinoma,HCC)早期复发仍然是一个具有挑战性的领域,其中涉及的机制尚未完全被理解。尽管微血管侵犯(…...
欢迪迈手机商城设计与实现基于(代码+数据库+LW)
摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本欢迪迈手机商城就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息…...
数据库基础与应用:从概念到实践
数据库是信息技术中的核心组件之一,是现代计算机系统中不可或缺的部分。无论是日常应用的社交网络、电子商务网站,还是企业级的大型系统,几乎所有的信息管理都离不开数据库。那么,数据库究竟是什么?它是如何工作的&…...
jenkins集成工具(一)部署php项目
目录 什么是CI 、CD Jenkins集成工具 一、Jenkins介绍 二、jenkins的安装和部署 环境部署 安装jenkins 安装gitlab 配置镜像源进行安装 修改密码 安装git工具 上传测试代码 Jenkins部署php项目wordpress 发布php代码 安装插件 测试代码发布 实现发布成功发送邮件…...
17_HTML5 Web 存储 --[HTML5 API 学习之旅]
HTML5 Web 存储(Web Storage)是 HTML5 引入的一种在用户浏览器中存储数据的机制。它提供了比传统的 cookies 更加方便和强大的功能,包括更大的存储空间、更好的性能以及更简单的 API。Web 存储主要分为两种类型:localStorage 和 s…...
GCP Cloud Architect exam - PASS
备考指南 推荐视频课程 https://www.udemy.com/course/google-cloud-architect-certifications/?couponCodeKEEPLEARNING 推荐题库 https://www.udemy.com/course/gcp-professional-cloud-architect-exam-practice-tests-2024/?couponCodeKEEPLEARNING 错题集 http…...
【Sentinel】初识Sentinel
目录 1.1.雪崩问题及解决方案 1.1.1.雪崩问题 1.1.2.超时处理 1.1.3.仓壁模式 1.1.4.断路器 1.1.5.限流 1.1.6.总结 1.2.服务保护技术对比 1.3.Sentinel介绍和安装 1.3.1.初识Sentinel 1.3.2.安装Sentinel 1.4.微服务整合Sentinel 1.1.雪崩问题及解决方案 1.1.1.…...
java常见类库
StringBuffer类 String和StringBuffer的区别 String 不可变性:String 类是不可变的,这意味着一旦创建了一个 String 对象,其值就不能改变。每次对 String 进行修改(如连接、替换等操作)都会产生新的 String 对象&…...
Wordly Wise 3000 国际背单词01 介绍 + 测词汇量
📚 Wordly Wise 3000 国际背单词01 介绍 测词汇量 🌟 大家好!我们正式启动背Wordly Wise 3000单词,旨在利用国际资源和科学的学练方法,帮助大家更得效地坚持学练单词。我们将通过图文和Video等多种形式与大家分享经验…...
Unity Dots理论学习-2.ECS有关的模块(1)
Unity的实体组件系统(ECS)是支撑DOTS模块和技术的面向数据架构。ECS为Unity中的内存数据和runtime进程调度提供了高度的控制和确定性。 ECS for Unity 2022 LTS 配备了两个兼容的物理引擎,一个高级的Netcode package,以及一个用来…...
2021.12.28基于UDP同信的相关流程
作业 1、将TCP的CS模型再敲一遍 服务器 #include <myhead.h> #define PORT 8888 #define IP "192.168.124.123" int main(int argc, const char *argv[]) {//创建套接字//绑定本机IP和端口号//监听客户端请求//接收客户端连接请求//收发消息//创建套接字int…...
使用 Docker 搭建 Hadoop 集群
1.1. 启用 WSL 与虚拟机平台 1.1.1. 启用功能 启用 WSL并使用 Moba 连接-CSDN博客 1.2 安装 Docker Desktop 最新版本链接:Docker Desktop: The #1 Containerization Tool for Developers | Docker 指定版本链接:Docker Desktop release notes | Do…...
optuna和 lightgbm
文章目录 optuna使用1.导入相关包2.定义模型可选参数3.定义训练代码和评估代码4.定义目标函数5.运行程序6.可视化7.超参数的重要性8.查看相关信息9.可视化的一个完整示例10.lightgbm实验 optuna使用 1.导入相关包 import torch import torch.nn as nn import torch.nn.functi…...
Android 设置铃声和闹钟
Android设置铃声和闹钟使用的方法是一样的,但是要区别的去获取对应的权限。 统一权限,不管是设置闹钟还是铃声,他们都需要一个系统设置权限如下: //高版本需要WRITE_SETTINGS权限//此权限是敏感权限,无法动态申请,需要…...
自动化测试模型(一)
8.8.1 自动化测试模型概述 在自动化测试运用于测试工作的过程中,测试人员根据不同自动化测试工具、测试框架等所进行的测试活动进行了抽象,总结出线性测试、模块化驱动测试、数据驱动测试和关键字驱动测试这4种自动化测试模型。 线性测试 首先&#…...
解决nuxt3下载慢下载报错问题
在下载nuxt3时总是下不下来,最后还报错了。即使改成国内镜像源也不行。 解决方法: 直接去github上下载 https://github.com/nuxt/starter/tree/v3 解压后得到如下目录: 手动修改项目名和文件夹名 安装依赖 npm install可能会比较慢或下不…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
