System Verilog的接口、程序块与断言解析

接口、程序块与断言

1 接口

1.1 使用接口简化连接

// 接口
interface arb_if(input bit clk);logic [1:0] grant,request;logic rst;
endinterface// 使用了简单接口的仲裁器
module arb (arb_if arbif);...always@(posedge arbif.clk or posedge arbif.rst)beginif(arbif.rst)arbif.grant <= 2'b00;elsearbif.grant <= next_grant;...end
endmodule// 使用简单仲裁器接口的测试平台
module test(arb_if arbif);...initial begin...@(posedge arbif.clk);arbif.request <= 2'b01;$display("@%0t:Drove req=01",$time);repeat(2)@(posedge arbif.clk);if(arbif.grant != 2'b01)$display("@%0t:a1:grant!=2'b01",$time);$finishend
endmodule// top模块
module top;bit clk;always #5 clk = ~clk;arb_if arbif(clk);arb a1(arbif);test t1(arbif);
endmodule

1.2 使用modport将接口中的信号分组

在接口中使用modport结构能够将信号分组并指定方向

// 带有modport的接口
interface arb_if(input bit clk);logic [1:0] grant, request;logic rst;modport TEST (output request, rst, input grant, clk);modport DUT (input request, rst, clk, output grant);modport MONITOR (input request, grant, rst, clk);
endinterface// 接口中使用modport的仲裁器模型
module arb (arb_if.DUT arbif);
...
endmodule// 接口中使用modport的测试平台
module test (arb_if.TEST arbif);
...
endmodule// 接口中使用modport的仲裁器监视模块
module monitor(arb_if.MONITOR arbif);always@(posedge arbif.request[0]) begin$display("@%0t:request[0] asserted",$time);@(posedge arbif.grant[0]);$display("@%0t:grant[0] asserted",$time);endalways@(posedge arbif.request[1]) begin$display("@%0t:request[1] asserted",$time);@(posedge arbif.grant[1]);$display("@%0t:grant[1] asserted",$time);end
endmodule

1.3 使用时钟块

采样时发生竞争(delta cycle的存在),会导致采样数据错误。为了避免在RTL仿真中发生信号竞争的问题,建议通过非阻塞赋值或者特定的信号延迟来解决同步问题。这里我们介绍使用clocking时钟块来决定信号的驱动和采样的方式。

delta cycle存在的问题:

  • 在RTL仿真时,由于无法确定具体电路的延迟时间,默认情况下时钟驱动电路时会添加一个**无限最小的时间(delta cycle)**的延迟,这个延迟要比最小时间单位精度还要小(可以理解成远小于1ps)。
  • 由于各种可能性,clk与被采样数据之间如果只存在若干个delta-cycle的延迟,那么采样就会出问题。

在这里插入图片描述

在时钟上升沿采样信号,只看vld信号(1->0)就会疑惑采样到的是1还是0,在RTL仿真时,是看不到真实的物理时序信息的,但实际采样到的是1;真实电路对应的时vld_actual信号,它的变化会较clk有一个detal-cycle的延迟,这样看在时钟上升沿采集到的是1。

还有一种方法就是,设置采样vld信号的时间,设置在时钟上升沿之前 #t 采样,这样采出来的数据也是准确的;同样也可以设置信号输出时间,设置在时钟上升沿之后 #t 输出,这样输出的数据也是准确的;

interface chnl_intf(input clk, input rstn);logic [31:0] ch_data; logic        ch_valid;logic        ch_ready;logic [ 5:0] ch_margin;// 定义时钟块clocking drv_ck @(posedge clk);//采样时间default input #1ns output #1ns; //在clk上升沿的前1ns对其进行输入采样,在事件的后1ns进行输出驱动//声明变量方向output ch_data, ch_valid;input ch_ready, ch_margin;endclocking
endinterface

在SystemVerilog中引入时钟块是为了解决在写testbench时对于特定时序和同步处理的要求而设计的。

时钟块是在一个特定的时钟上的一系列同步的信号,它基本上能够将testbench中与时序相关的结构、函数和过程块分开,能够帮助设计人员根据transaction 和 cycle完善testbench,时钟块只能在module、interface或program中声明

// 可置位的二进制计数器
module COUNTER (input Clock, Reset, Enable, Load, UpDn, input [7:0] Data, output reg[7:0] Q);always @(posedge Clock or posedge Reset)if (Reset)Q <= 0;elseif (Enable)if (Load)Q <= Data;elseif (UpDn)Q <= Q + 1;elseQ <= Q - 1;
endmodule// 不采用时钟块的testbench
module Test_Counter;timeunit 1ns;reg Clock = 0, Reset, Enable, Load, UpDn;reg [7:0] Data;wire [7:0] Q;reg OK;// Clock generatoralwaysbegin#5 Clock = 1;#5 Clock = 0;end// Test stimulusinitialbeginEnable = 0;Load = 0;UpDn = 1;Reset = 1;#10; // Should be resetReset = 0;#10; // Should do nothing - not enabledEnable = 1;    #20; // Should count up to 2UpDn = 0;#40; // Should count downto 254UpDn = 1;// etc. ...end// Instance the device-under-testCOUNTER G1 (Clock, Reset, Enable, Load, UpDn, Data, Q);// Check the resultsinitialbeginOK = 1;#9;if (Q !== 8'b00000000)OK = 0;#10;if (Q !== 8'b00000000)OK = 0;#20;if (Q !== 8'b00000010)OK = 0;#40;if (Q !== 8'b11111110)OK = 0;// etc. ...end
endmodule// 采用时钟块的testbench
module Test_Counter_w_clocking;timeunit 1ns;reg Clock = 0, Reset, Enable, Load, UpDn;reg [7:0] Data;wire [7:0] Q;// Clock generatoralwaysbegin#5 Clock = 1;#5 Clock = 0;end// Test program// 将验证部分与设计部分进行隔离(实现方式就是将软件验证部分放置program中)program test_counter;// SystemVerilog "clocking block"// Clocking outputs are DUT inputs and vice versadefault clocking cb_counter @(posedge Clock);default input #1step output #4;output negedge Reset;output Enable, Load, UpDn, Data;input Q;endclocking// Apply the test stimulusinitial begin// Set all inputs at the beginning    Enable = 0;            Load = 0;UpDn = 1;Reset = 1;// Will be applied on negedge of clock!##1 cb_counter.Reset  <= 0;// Will be applied 4ns after the clock!##1 cb_counter.Enable <= 1;##2 cb_counter.UpDn   <= 0;##4 cb_counter.UpDn   <= 1;// etc. ...      end// Check the results - could combine with stimulus blockinitial begin// Sampled 1ps (or whatever the precision is) before posedge clock##1 assert (cb_counter.Q == 8'b00000000);##1 assert (cb_counter.Q == 8'b00000000);##2 assert (cb_counter.Q == 8'b00000010);##4 assert (cb_counter.Q == 8'b11111110);// etc. ...      end// Simulation stops automatically when both initials have been completedendprogram// Instance the counterCOUNTER G1 (Clock, Reset, Enable, Load, UpDn, Data, Q);// Instance the test program - not required, because program will be instanced implicitly.
endmodule

2 程序块

2.1 程序块和时序区域

SystemVerilog 如何把测试平台的事件设计的事件分开调度?
SystemVerilog 引入一种新的时间片的划分方式,如下图所示。

  • 在一个时间片内首先执行的是 Active 区域,在这个区域中运行设计事件,包括 RTL 、门级代码和时钟发生器。
  • 第二个区域是 Observed 区域,执行断言。
  • 接下来就是执行测试平台的 Reactive 区域。注意到时间不是单向地前向流动 —— ObservedReactive 区域的事件可以触发本时钟周期内 Active 区域中进一步的设计事件。
  • 最后就是 Postponed 区域,它将在时间片的最后,所有设计活动都结束后的只读时间段采样信号。

在这里插入图片描述

Active:仿真模块中的设计代码
Observed:执行SystemVerilog断言
Reactive:执行程序中的测试平台部分
Postponed:为测试平台的输入采样信号

// 使用带有时钟块接口的测试平台
program automatic test (arb_if.TEST arbif);
...initial beginarbif.cb.request <= 2'b01;$display("@%0t:Drove req=01",$time);repeat(2) @arbif.cb; // @arbif.cb 语句将等待时钟块给出的有效沿 @(posedge clk)if(arbif.cb.grant != 2'b01)$display("@%0t:a1:grant != 2'b01",$time);end
endprogram : test

2.2 仿真的结束

在verilog中,仿真在调度事件存在时会继续执行,直到遇到 $finish
SystemVerilog新增加了一种结束仿真的方法:SystemVerilog把任何一个程序块都视为含有一个测试,如果仅有一个程序块,那么当完成所有initial块中最后一个语句时,仿真就结束了,因为编译器认为这就是测试的结尾,即使还有模块或者程序块的线程在运行,仿真也会结束。如果存在多个程序块,仿真在最后一个程序块结束时结束,可以执行 $exit 提前中断任何一个程序块。

2.3 程序块(program)中不允许使用 always

在SystemVerilog中,可以在 program 中使用 initial 块,但是不能使用 always 块。SystemVerilog程序比由许多并行执行的块构成的Verilog 更接近C程序,它拥有一个(或多个)程序入口。在一个设计中,一个 always 块可能从仿真的开始就会在每一个时钟的上升沿触发执行。但是一个测试平台的执行过程是经过初始化、驱动和响应设计行为等步骤后结束仿真的。在这里,一个连续执行的 always 模块不能正常工作。
program 中最后一个initial块结束的时候,仿真实际上也就默认结束了,就像执行了 $finish 一样。如果加入了一个always块,它将永远不会结束,这样就不得不明确地调用 $exit 来发出程序块结束的信号。如果确实需要一个always块,可以使用 initial forever 来完成相同的事情。

3 断言

可以使用SystemVerilog断言(SVA)在设计中创建时序断言。断言的例化跟其他设计块的例化相似,而且在整个仿真过程中都是有效的。仿真器会跟踪哪些断言被激活,这样就可以在此基础上收集功能覆盖率的数据。

3.1 立即断言

测试平台的过程代码可以检查待测设计的信号值和测试平台的信号值,并且在存在问题的时候采取相应的行动。
例如,如果产生了总线请求,期望在两个时钟周期后产生应答,可以使用一个if语句来检查这个应答。

// 使用一个if语句检查一个信号
bus.cb.request <= 1;
repeat(2) @bus.cb;
if(bus.cb.grant != 2'b01)$display("Error, grant != 1");// 简单的立即断言
bus.cb.request <= 1;
repeat(2) @bus.cb;
a1: assert (bus.cb.grant == 2'b01);
// ----------------------------------
// 如果正确地产生了grant信号,那么测试继续执行,如果信号不符合期望值,仿真器将会给出一个如下所示的信息:
// "test.sv",7:top.t1.a1:started at 55ns failed at 55ns
// offending '(bus.cb.grant == 2'b1)'
// 该消息指出,在test.sv文件中的第七行,断言top.t1.a1在55ns开始检查信号bus.cb.grant,但是立即检查出了错误。

3.2 定制断言行为

一个立即断言有可选的then和else分句,如果想改变默认的消息,可以添加自己的输出信息。

// 在立即断言中创建一个定制的错误消息
a1: assert (bus.cb.grant == 2'b01)
else $error("Grant not asserted");

SystemVerilog 有四个输出消息的函数:$info, $warning, $error$fatal。这些函数仅允许在断言内部使用,而不允许在过程代码中使用。

// 使用then子句来记录断言何时成功完成
a1: assert (bus.cb.grant == 2'b01)grants_received++;  // 另一个成功的结果
else$error("Grant not asserted");

3.3 并发断言

另一种断言就是并发断言,可以认为它是一个连续运行的模块,它为整个仿真过程检查信号的值。需要在断言内指定一个采样时钟。下面是一个检查仲裁器request信号的断言。request信号除了在复位期间,其他任何时候都不能是X或Z。

interface arb_if(input bit clk);logic [1:0] grant, request;logic rst;property request_2state;@(posedge clk) disable iff(rst);$isunknown(request) == 0; // 确保没有Z或者X值存在endpropertyassert_request_2state: assert property(request_2state);
endinterface

3.4 语法之序列

序列由sequence… endsequence声明
功能特性经常由有序的行为构建,sequence功能提供了一种能力来构建和处理有序的行为。
在一系列的布尔逻辑表达式中,如果每个布尔表达式的计算都为真,那么关于这个序列的断言为真,否则为假。

sequence s1;  //无参数@(posedge clk) a ##1 b ##1 c; //##1指的是延时一个周期	
endsequence //上面的意思是先a是1,一个周期后b是1,一个周期c是1sequence s2(data,en); //带参数@(posedge clk)(!a && (data == data_bus) ##1 c[0:3] == en )
endsequence

SVA也内嵌了边缘表达式,以便用户监视信号值从一个时钟周期到另一时钟周期的跳变。这使得用户能检查边沿敏感的信号(前后信号不一致才是属于跳变)

  • $rose(boolean expression or signal name) 当信号/表达式为1时返回真。
  • $fell(boolean expression or signal_ name) 当信号/表达式为0时返回真。
  • $stable(boolean"expression or signal_ name) 当信号/表达式不发生变化时返回真。

SVA语法—时钟关系的序列
很多时候,我们关心的是检查需要几个时钟周期才能完成的事件。也就是所谓的“时序检查”。在SVA中,时钟周期延迟用"#" 来表示。例如,#3表示3个时钟周期。举个例子:

sequence s1;@(posedge clk) a ##2 b;
endsequence 	

序列s1检查信号"a"在一一个给定的时钟上升沿是否为高电平:
如果信号"a"不是高电平,序列失败,断言失败。
如果信号"a"在任何一一个给定的时钟上升沿为高电平,信号"b” 在两个时钟周期后为高电平,则断言成功。
如果信号"a"在任何一一个给定的时钟上升沿为高电平,信号"b" 在两个时钟周期后为不为高电平,断言失败。
在仿真后结果显示中,成功的序列总是标注在序列开始的位置

3.5 语法之属性

许多序列可以有序地组合起来生成更复杂的序列。SVA 提供了一个关键词property 来表示这些复杂的有序行为。属性(property)的基本语法是:

property name_ of_ property;
; or
;
endproperty

属性是在模拟过程中被验证的单元。它必须在模拟过程中被断言来发挥作用。 SVA提供了关键"assert"来检查属性。断言(assert)的基本语法是:
assertion_ name: assert property (property_ name);

interface arb_if(input bit clk);logic [1:0] grant, request;logic rst;property request_2state;@(posedge clk) disable iff(rst);$isunknown(request) == 0; // 确保没有Z或者X值存在endpropertyassert_request_2state: assert property(request_2state);
endinterface

3.6 语法之时钟定义

// 定义一个序列并不能发挥作用,它必须被断言才能发挥作用
// SVA在序列、 属性甚至一个断言的语句中都可以定义时钟。
sequence s5;a ##2 b;
endsequenceproperty p5;@(posedge clk) s5;
endpropertya5: assert property(p5);

通常情况下在sequence描述行为,在property描述时钟

3.7 语法之禁止属性

属性可以禁止发生。即我们期望属性永远为假,当属性为真时,断言失败。
序列s6检查当信号"a"在给定的时钟上升沿为高电平,那么两个时钟周期以后,信号"b"不允许是高电平。关键词"not" 用来表示属性应该永远不为真。

sequence s6;@(posedge clk) a ##2 b;
endsequenceproperty p6not s6;
endpropertya6: assert property(p6);

3.8 语法之执行块

SystemVerilog 语言被定义成每当一个断言检查失败,模拟器在默认情况下都会打印出一条错误信息。模拟器不需要对成功的断言打印任何东西。读者同样可以打印自定义自定义的成功或失败信息。

property p7@(posedge clk) a ##2 b;
endpropertya7: assert property(p7)$display("Property p7 succeeded\n");
else$display("Property p7 failed\n");

3.9 语法之蕴含操作

对于@(posedge clk) a #2 b这样的属性,它在每个时钟上升沿检查信号"a" 是否为高。寻找是否为一个断言的有效开始。
如果信号"a"在给定的任何时钟上升沿不为高,检验器将产生一个错误信息。这并不是一个有效的错误信息因为我们不只关心a,更加关心a和b的关系。这个错误只表明这个时钟周期没有得到有效起始点。它们会在一段时间内产生大量的错误信息。

蕴含
基于以上问题,SVA提供了蕴含操作。
蕴含等效于一个if-then结构。蕴含的左边叫作“先行算子”,右边叫作"后续算子”。当先行算子成功时,后续算子才会被计算。如果先行算子不成功,那么整个属性就默认地被认为成功。这叫作"空成功”
蕴含结构只能被用在属性定义中,不能在序列中使用。

蕴含分为两类:交叠蕴含和非交叠蕴含。
交叠蕴含用符号"|->” 表示。如果先行算子匹配,在同一个时钟周期计算后续算子表达式。例如:

property p8;@(posedge clk) a |-> b;
endpropertya8: assert property(p8);

当信号"a" 为高,而且信号"b" 在同一个时钟沿也为高,这是一个真正的成功。若信号"a"不为高,断言默认自动成功,称为空成功。信号"a" 为高且,并且在同一个时钟沿信号"b" 未能检测为有效的高电平,则断言失败。

非交叠蕴含用符号(“I=>”)表示。如果先行算子匹配,那么在下-一个时钟周期计算后续算子表达式。后续算子表达式的计算总是有一个时钟周期的延迟。 例如:

property p9;@(posedge clk) a|=> b;
endpropertya9: assert property(p9);

3.10 语法之时序窗口

SVA的延迟可以支持固定的正延迟,也可以支持一个时间窗口。例如:

property p10@(posedge clk) (a && b) |-> ##[1:3] c;
endproperty
// 等价于
// (a && b) |-> ##1 c 或
// (a && b) |-> ##2 c 或
// (a && b) |-> ##3 c 

p10先行算子在任何给定的时钟上升沿为真,那么在接下去的1~3周期内,信号"c" 应该至少在一个时钟周期为高,SVA允许使用时序窗口来匹配后续算子。时序窗口表达式左手边的值必须小于右手边的值。每声明一个时序窗口,就会在每个时钟沿上触发多个线程来检查所有可能的成功。p10 实际上展开了三个线程。

3.11 语法之ended结构

默认情况下,多重sequence的组合是以sequence的起始时间作为同步标志的,就是以序列的起始点作为同步点,来组合成时间上连续的检查。
SVA提供ended结构以sequence的结束时间作为序列同步点。关键字ended存储一个反映在指定时钟处序列是否匹配成功的布尔值。
ended代表匹配的完成,是匹配的结束点,而不是匹配的起点。

默认情况下,多重sequence的组合是以sequence的起始时间作为同步标志的,就是以序列的起始点作点作为同步点,来组合成时间上连续的检查。SVA还提供了另一种使用序列的结束点作为同步点的连接机制。

sequence s11a;@(posedge clk) a ##1 b;
endsequencesequence s11b;@(posedge clk) c ##1 d;
endsequenceproperty p11a;s11a |=> s11b;
endpropertyproperty p11b;s11a.ended |-> ##2 s11b.ended;
endpropertya11a: assert property(p11a);
a11b: assert property(p11b);

在这里插入图片描述

3.12 语法之$past构造

SVA提供了一个内嵌的系统任务$past, 它可以得到信号在几个时钟周期之前的值。在默认情况下,它提供信号在前一个时钟周期的值。结构的基本语法如下:
$past (signal name, number of clock cycles)
这个任务能够有效地验证设计到达当前时钟周期的状态所采用的通路是正确的。

property p12;@(posedge clk) (c && d) |-> ($past ((a  && b),2)==1'b1);
endproperty
a12: assert property(p12);

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

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

相关文章

opencv dnn模块 示例(25) 目标检测 object_detection 之 yolov9

文章目录 1、YOLOv9 介绍2、测试2.1、官方Python测试2.1.1、正确的脚本2.2、Opencv dnn测试2.2.1、导出onnx模型2.2.2、c测试代码 2.3、测试统计 3、自定义数据及训练3.1、准备工作3.2、训练3.3、模型重参数化 1、YOLOv9 介绍 YOLOv9 是 YOLOv7 研究团队推出的最新目标检测网络…

软件测试中的AI-为什么它在软件自动化测试中很重要?

通俗地说&#xff0c;人工智能&#xff08;AI&#xff09;是计算机科学的一个领域&#xff0c;它专注于使机器“智能化”。所谓智能&#xff0c;就是使系统能够像人类一样学习和做出决策。因此&#xff0c;人工智能机器将能够学习如何在特定情况下做出反应&#xff0c;然后根据…

【AIGC】重磅消息,GPT-4.5 Turbo将在6月发布?

2024 年 AI 辅助研发趋势 文章目录 强烈推荐GPT-4.5 Turbo竞争对手Anthropic的Claude 3谷歌的Gemini 1.5 Pro 总结强烈推荐专栏集锦写在最后 强烈推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击…

Cplex之新建一个项目并求解

cplex下载&#xff1a;Cplex安装教程与使用介绍-CSDN博客 链接&#xff1a;https://pan.baidu.com/s/1jD9Xved2aWPHtRd-_PLI5Q 提取码&#xff1a;n4og 补充b站上一个教程&#xff1a;快速学懂Cplex软件及其编程方法_哔哩哔哩_bilibili 一、建立并求解一个模型 step1 : 新…

【目标检测经典算法】R-CNN、Fast R-CNN和Faster R-CNN详解系列一:R-CNN图文详解

学习视频&#xff1a;Faster-RCNN理论合集 概念辨析 在目标检测中&#xff0c;proposals和anchors都是用于生成候选区域的概念&#xff0c;但它们在实现上有些许不同。 Anchors&#xff08;锚框&#xff09;&#xff1a; 锚框是在图像中预定义的一组框&#xff0c;它们通常以…

Python:函数的形参与实参

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 函数基本概念 在Python中&#xff0c;函数是一种将代码封装以进行重复使用的机制。它们允许你定义一段代码&#xff0c;以便在程序的多个位置调…

微信小程序开发系列(二十六)·小程序运行机制(启动、前后台状态、挂起、销毁)和小程序更新机制

目录 1. 小程序运行机制 1.1 启动 1.2 前台和后台状态 1.3 挂起 1.4 销毁 2. 小程序更新机制 1. 小程序运行机制 1.1 启动 小程序启动可以分为两种情况&#xff0c;一种是冷启动&#xff0c;一种是热启动。 冷启动&#xff1a;如果用户首次打开&#xff0c;或小…

OPPO后端二面,凉了!

这篇文章的问题来源于一个读者之前分享的 OPPO 后端凉经&#xff0c;我对比较典型的一些问题进行了分类并给出了详细的参考答案。希望能对正在参加面试的朋友们能够有点帮助&#xff01; Java String 为什么是不可变的? public final class String implements java.io.Seri…

阿里云服务器安全狗免费使用多引擎智能查杀引擎

云服务器具有按量付费、降低综合成本等诸多优势&#xff0c;受到很多企业的欢迎。 因此&#xff0c;目前使用的云服务器越来越多。 阿里云是目前云服务器中最具影响力的品牌&#xff0c;因此选择阿里云服务器的用户数量也是最多的。 那么阿里云服务器需要安装杀毒软件吗&#x…

Python学习:数据类型转换

数据类型转换 对数据内置的类型进行转换&#xff0c;数据类型的转换&#xff0c;一般情况下你只需要将数据类型作为函数名即可。 Python 数据类型转换可以分为两种&#xff1a; 隐式类型转换 - 自动完成显式类型转换 - 需要使用类型函数来转换 隐式类型转换 Python 会自动…

微信小程序一次性订阅requestSubscribeMessage授权和操作详解

一次性订阅&#xff1a;用户订阅一次发一次通知 一、授权 — requestSubscribeMessage Taro.requestSubscribeMessage({tmplIds: [], // 需要订阅的消息模板的id的集合success (res) {console.log("同意授权", res)},fail(res) {console.log(拒绝授权, res)}})点击或…

2001-2022年上市公司数字化转型程度指数测算数据(含原始数据+测算代码+计算结果)(无形资产衡量)

2001-2022年上市公司数字化转型程度指数测算数据&#xff08;含原始数据测算代码计算结果&#xff09; 1、时间&#xff1a;2001-2022年 2、指标&#xff1a;证券代码、证券简称、统计截止日期、是否发生ST或*ST或PT、、是否发生暂停上市、行业代码、行业名称、stkcd、year、…

mediapipe 实现姿态分析——举手检测

目录 人体姿态检测 效果展示 举手检测 行业应用 代码实现 代码分析 效果展示 代码修改&#xff0c;一只手举起即可 总结 啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦^_^啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦♪(^∇^*)啦啦啦…

【数据结构】二叉树---AVL树的实现

目录 一. 什么是AVL树 二. AVL树的结点结构定义 三. AVL树的动态平衡法 1. 左单旋转 --- RL(RotateLeft) 型调整操作 2. 右单旋转 --- RR(RotateRight) 型调整操作 3. 先左后右双旋转 --- RLR (RotateLeftRight) 型调整操作 4. 先右后左双旋转 --- RRL (RotateRightL…

Day32:安全开发-JavaEE应用Servlet路由技术JDBCMybatis数据库生命周期

目录 JavaEE-HTTP-Servlet&路由&周期 JavaEE-数据库-JDBC&Mybatis&库 思维导图 Java知识点&#xff1a; 功能&#xff1a;数据库操作&#xff0c;文件操作&#xff0c;序列化数据&#xff0c;身份验证&#xff0c;框架开发&#xff0c;第三方库使用等. 框架…

最新若依项目快速上手

最新若依项目快速上手 配套视频&#xff1a;若依项目快速上手视频 1. 下载源码 官网&#xff1a;https://ruoyi.vip/ 前端 git clone https://github.com/yangzongzhuan/RuoYi-Vue3.git后端 git clone https://gitee.com/y_project/RuoYi-Vue.git2. 数据库 创建数据库ry-vue…

考研复习C语言初阶(3)

目录 一.函数是什么? 二.C语言中函数的分类 2.1库函数 2.2自定义函数 三.函数的参数 3.1实际参数&#xff08;实参&#xff09; 3.2 形式参数&#xff08;形参&#xff09; 四.函数的调用 4.1 传值调用 4.2 传址调用 五. 函数的嵌套调用和链式访问 5.1 嵌套调用 5…

Android中单例模式正确实现方式

1. 饿汉模式 -线程安全 在类加载时进行实例化&#xff0c; 线程安全&#xff0c;但会导致类加载时间变长。饿汉模式如果使用过多&#xff0c;可能会对App启动耗时带来不利影响。 2. 懒汉模式 -线程不安全 没有加锁&#xff0c; 因此线程不安全。 3. 两次判空 加同步锁 -线程不…

Talk|麻省理工学院李晨昊:发展式腿足智能-从模仿到生成

本期为TechBeat人工智能社区第578期线上Talk。 北京时间3月13日(周三)20:00&#xff0c;麻省理工学院博士生—李晨昊的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “发展式腿足智能-从模仿到生成”&#xff0c;向大家系统地介绍了专家示范(exper…

基于四边形网格的服装设计

前言 该篇论文对算法的描述是比较详细的&#xff0c;在Unity中复现其功能。我这边的效果是这样的。 不尽人意 正文开始 Sketch-Based Garment Design with Quad Meshes 基于草图的服装设计与四边形网格 2020/02/13 Jackdos整理翻译 Abstract摘要 Garment creation cont…