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

SystemVerilog之接口详解

1.入门实例

测试平台连接到 arbiter的例子:包括测试平台, arbiter仲裁器, 时钟发生器 和连接的信号。

ㅤㅤㅤ ㅤ ㅤㅤㅤㅤㅤ在这里插入图片描述

Arbiter里面可以自定义发送的权重, 是轮询还是自定义

grant表示仲裁出来的是哪一个,也即只有0,1,因此图中grant的取值只有00 01 10 不可能出现11。

grant_valid表示grant是否有效。

  • 使用端口

    • 顶层连接
    module top;logic[1:0] grant, request;logic grant_valid;bit clk,rst;always #5 clk=~clk;arb_port a1(grant, grant_valid, request, rst, clk);test t1(grant, grant_valid, request, rst, clk);
    endmodule
    
    • 仲裁器模型
    module arb_port(output logic [1:0] grant,output logic grant_valid,input logic [1:0] request,input logic rst,input logic clk);…always@(posedge clk or posedge rst) beginif(rst)grant <=2'b00;else…end
    endmodule
    
    • 测试平台
    module test(input logic [1:0] grant,input logic grant_valid,output logic [1:0] request,input logic rst,input logic clk);initial begin@(posedge clk) request <=2'b01;// 驱动了request01$display("@%05: Drove req=01",$time);repeat(2) @(posedge clk )if(grant_valid &&(grant!=2'b01))// 通常情况下 request是01,那么grant也是01$display("@%0t:a1:grant!=2’b01",$time);…$finish;end
    endmodule
    

这种方法的缺点就是若DUT arb_port的端口需要改变,在test和top中的声明都要改变。

在真实的设计中, 往往含有数百个端口信号,因此,sv中推荐使用一种interface的结构。

2.接口定义

使用接口简化连接。

逻辑设计日益复杂,模块之间的通信必须分割成独立的实体。

SV使用接口来连接不同模块。接口可以看作一捆智能连线,它连接了DUT和验证平台, 它包括了连接,同步(clocking block)。

时钟可以是接口的一部分或者是一个独立的端口。

ㅤㅤㅤ ㅤㅤㅤ ㅤㅤㅤ 在这里插入图片描述

  • 接口声明
interface arb_if(input bit clk);logic[1:0] grant,request;logic grant_valid;logic rst;
endinterface
  • 采用接口的顶层模块
module top;bit clk;always #5 clk=~clk;arb_if arbif(clk);// 例化接口arb a1(arbif);    // 连接DUTtest t1(arbif);   // 连接tb
endmodule:top

若仲裁器的端口无法修改为接口,则需要连接验证人员自己定义的接口到端口上:

module top;bit clk;always #5 clk=~clk;arb_if arbif(clk); 							//例化接口arb_port a1(.grant(arbif.grant), 			//连接DUT.grant_valid(arbif.grant_valid),.request(arbif.request),.rst (arbif.rst),.clk (arbif.clk));test t1(arbif); 							//连接tb
endmodule:top
  • 使用接口的仲裁器,接口信号必须使用非阻塞赋值来驱动
// arbif是例化名称	
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:frant!=2'b01",$time);$finish;end
endmodule:test

问题:上述的接口定义中没有指明方向

interface arb_if( input bit clk);logic[1:0] grant,request;logic grant_valid;logic rst;
endinterface

没有指定方向,默认是inout,引入modport给信号分组,可以根据不同的module去定义不同的端口方向

一般情况下TB与DUT端口方向相反,除了clk与rst复位信号

例:使用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

使用时钟同步块将request与grant优化后:

interface arb_if(input bit clk);logic [1:0] grant, request;logic rst;// 声明一个时钟模块cbclocking cb @(posedge clk);output request;input grant;endclocking// 调用cbmodport TEST (clocking cb,output rst);modport DUT (input request, rst, output grant);
endinterface

则module定义的时候端口例化就变成:注意观察括号中的变化

module arb(arb_if.DUT arbif);…
endmodule
module test(arb_if.TEST arbif); …
endmodule
module monitor(arb_if.MONITOR arbif); …
endmodule

通常情况下,还可以去monitor监视上面各种信号的行为

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. 便于设计重用;
  2. 可以替代原来需要在模块或者程序中重复声明并且位于代码内部的一系列信号,减少连接错误的可能性
  3. 要增加一个新信号时,,只需要在接口中声明一次,不需要在更高层的模块层声明, 进一步减少错误;
  4. modport允许一个模块将接口的一系列信号捆绑到一起,为信号指定方向;
  • 缺点:
  1. 对于点对点的连接,使用modport跟使用信号列表的端口一样冗余(A与B之间如果就例化了一次,就会冗余);
  2. 必须同时使用信号名和接口名,会使模块变得更加冗长;
  3. 如果连接两个模块使用的是一个不会被重用的专用协议,使用接口需要做比端口连线更多的工作;
  4. 连接两个不同的接口很困难;一个新的接口可能包含了现有接口的所有信号并新增了信号,需要拆分独立的信号并正确的驱动;

总之:瑕不掩瑜,尽量使用interface,方便后续维护修改。

端口能做的,接口90%都能做,模块里面可以例化模块,模块可以例化接口,接口可以例化接口,但是接口不能例化模块

实例:根据design,设计出test bench,分别用端口连接、接口连接实现,并体会他们的异同

  1. design

    module arb_port(output logic [1:0] grant, output logic grant_valid,input logic [1:0] request,input logic rstn,input logic clk);logic pri;// 时序逻辑always_ff @(posedge clk or negedge rstn)begin// 默认两个端口0,1,在rst复位之后,0端口的优先级高if(!rstn)pri <=0;// 每来一个clock,pri就发生翻转elsepri<=~pri;end// 组合逻辑always_comb begin// 按位或,只要request等于10 01 11,grand_valid都等于1,也即grand有效grant_valid = |request;if(request== 2'b01 || request==2'b10)grant = request;// request同时为1,就会比较优先级else if (request==2'b11)// 无优先级的caseunique case(pri)// 比较优先级,优先级为0,就输出0口1'b0: grant = 2'b01;1'b1: grant = 2'b10;endcaseelse begingrant_valid = 0;grant =0;endend
    endmodule
    
  2. 使用端口

    module test(input logic [1:0] grant,input logic rant_valid,output logic [1:0] request,input logic rstn,input logic clk);initial begin@(posedge clk) request <=2’b01;$display("@%05: Drove req=01",$time);repeat(2) @(posedge clk )...end
    endmodule
    
  3. 使用接口

    module test(arb_if.TB arbif);initial beginarbif.rstn=1;repeat(2) @(posedge arbif.clk);arbif.rstn=0; // assertrepeat(5) @(posedge arbif.clk);arbif.rstn=1; // release@(posedge arbif.clk) arbif.request <=2'b01;$display("@%05t: Drove req=01",$time);repeat(2) @(posedge arbif.clk);arbif.request <=2'b10;$display("@%05t: Drove req=10",$time);repeat(2) @(posedge arbif.clk);arbif.request <=2'b11;$display("@%05t: Drove req=11",$time);repeat(2) @(posedge arbif.clk);end
    endmodule
    
  4. 定义接口

    interface arb_if(input bit clk);logic [1:0] grant;logic [1:0] request;logic grant_valid;logic rstn;modport TB(input grant_valid,grant,clk,output request,rstn);modport DUT(input request,rstn,clk,output grant_valid,grant);
    endinterface
    
  5. 顶层模块

    module top;bit clk;always #5 clk = ~clk;arb_if arbif(clk);test u_test(arbif);// 由于端口无法修改为接口,因此手动连接定义的接口到端口上arb_port u_arb(.grand(arbif.grand),.grand_valid(arbif.grand_valid),.request(arbif.request),.rstn(arbif.rstn),.clk(clk));
    endmodule
    

在编译器中编译的顺序是有要求的,也即要先编译底层,最后再编译top顶层。同时,使用接口的时候需要确保在模块与程序块之外声明接口变量例如``include “arb_if.sv”`

3.接口同步

接口信号采样与驱动就使用到了接口同步

在RTL仿真时候会遇到信号竞争问题也即(Delta cycle仿真异常行为)。

例:b的值应该取clk上升沿之前的值0,但是却取了1

ㅤㅤㅤ ㅤㅤㅤ ㅤㅤㅤ在这里插入图片描述

为了防止Deltal cycle的发生,因此我们采用clocking block(只能在testbench里面用)

在clocking block,所有信号的采样和驱动,都是跟时钟同步的(但要注意采样与驱动的不同)

interface arb_if(input bit clk);logic [1:0] grant, request;logic reset;// 声明一个时钟模块cbclocking cb @(posedge clk);output request;input grant;endclocking// 调用cbmodport TEST (clocking cb,output reset);modport DUT (input request, reset, output grant);
endinterface

通过clocking block完成同步,也即每一步操作都是跟clock对齐的,这样就完成request与grant的同步

program automatic test(bus_if.TB bus);initial begin@bus.cb; //在时钟块的有效时钟沿触发repeat(4) @bus.cb; //等待4个有效时钟沿@bus.cb.grant; //监测grant信号的变化(上升,下降)@(posedge bus.cb.grant); //监测grant信号的上升沿@(negedge bus.cb.grant); //监测grant信号的下降沿wait (bus.cb.grant==1); // 监测一个电平值, 若监测不到, 则一直等待@(posedge bus.cb.grant or negedge bus.reset); //监测grant上升沿,reset的下降沿end
endprogram

注意:在测试模块的时钟块中,使用modport的时候,任何同步接口信号都必须加上接口名(arbif)时钟名称(cb),例如request信号,要写成arbif.cb.request

4.接口采样与驱动

  • 接口采样:当从时钟块中读取信号的时候,是在时钟沿之前得到的采样值

    test程序块对clocking cb中的输入信号grant进行采样。 采样输出为arbif.cb.grant

    // interface中定义的clocking block
    interface arb_if(input bit clk);logic [1:0] grant, request;logic reset;// 声明一个时钟模块cbclocking cb @(posedge clk);output request;input grant;endclocking// 调用cbmodport TEST (clocking cb,output reset);modport DUT (input request, reset, output grant);
    endinterfaceprogram test(arb_if.TEST arbif);initial begin$monitor("@%0d: grant=%h", $time, arbif.cb.grant);#50;end
    endprogrammodule arb(arb_if.DUT arbif);initial beginarbif.grant = 1; // @ 0ns#12 arbif.grant = 2; // @ 12ns#18 arbif.grant = 3; // @ 30nsend
    endmodule
    

    DUT的信号输出grant,clock block的cb.grant输出如波形所示。

ㅤㅤㅤ ㅤㅤㅤ在这里插入图片描述

在30ns处,DUT的grant的值在时钟沿跳变,同时TEST的cb.grant也在该时钟沿触发输出,但此时它采样的值还是该时刻之前的值2。

简而言之:采样拿旧值

  • 接口驱动:在test中驱动同步信号arbif.cb.request ,在DUT中监测arbif.request的输出

    program test(arb_if.TEST arbif);initial begin#7 arbif.cb.request <= 3;  // @ 7ns#10 arbif.cb.request <= 2; // @ 17ns#13 arbif.cb.request <= 1; // @ 30ns#15 $finish;end
    endprogrammodule arb(arb_if.DUT arbif);initial$monitor("@%0t: req=%h", $time, arbif.request);
    endmodule
    

    test中arb.cb.request,DUT中request的波形如图:

ㅤㅤㅤ ㅤㅤㅤ在这里插入图片描述

注意:30ns处arb.cb.request的变化立刻在上升沿被传送到arb.request上。因为在clocking block中输出信号的默认延迟为#0,软件在编译时, clocking block中 的输出信号要晚于被采样信号的变化,但在波形上观察不出来。

驱动也即就是test的输出,也即给DUT去使用的,由于需要立刻赋值给DUT,因而驱动是拿新值

简而言之:驱动拿新值

  • 总结:在clocking block中,采样(input)和驱动(output)信号遵循如下原则:

    同步后的采样信号,都是前一个状态的值。

    同步后的驱动信号,都是当前状态的值。

到底是驱动还是采样,是由clock中的定义的信号方向决定的,而clocking block只能用于TB,因此:

在Test中,input就是对DUT的输出进行采样,output就是对DUT进行驱动,模拟了电路的一种属性

例如按下reset按钮,就必须立刻生效,如果要采样DUT的output的值的时候,就需要使用clocking block去采样。

5.接口中的双向信号

双向信号inout:inout必须定义为wire

interface master_if(input bit clk);wire[7:0] data;clocking cb@(posedge clk);inout data;endclockingmodport TEST(clocking cb);
endinterface
program test(master_if mif);initial beginmif.cb.data <='z; 	   //高阻态@mif.cb;$display(mif.cb.data); //从总线读取@mif.cb;mif.cb.data <=7'h5a;   //驱动总线@mif.cb;mif.cb.data <='z; 	   //释放总线end
endprogram

由于SV的用户参考手册中没有明确定义如何驱动接口中的异步双向信号, 故可用以下两种方法:

  1. 连续赋值语句

  2. 虚接口 virtual interface

6.为什么在程序块中不能使用always块

testbench中,程序的运行是有序性的:初始化,驱动激励信号,收取设计对激励的反馈,最后结束。当最后一个initial模块结束后,这个仿真也结束了,就像执行了$finish一样。而 always 语句是没有结束的,需要$exit来指定结束;

如果确实需要用一个always块, 可以使用**initial forever**来完成相同的事情; 所以initial forever在testbench中可以使用,功能类似于always。

program块中不支持always语句(编译会报错)

在program可以通过initial forever来代替,后续一般会使用initial forever去产生clock。

7.时钟发生器

program bad_generator (output bit clk, out_sig);bit clk=0, out_sig=0;initialforever #5 clk <= ~clk;initial// 这里输出了两个时钟,这个out_sig看起来是clk的二分频。forever @(posedge clk)out_sig <= ~out_sig;
endprogram

上例将时钟的产生定义到了program中,这样就会产生速度问题,时钟的翻转和信号变化同时的,应该判定谁的变化在前?

可能会引起竞争状态。 所以应该在module或者class中声明clk

module clock_generator (output bit clk);bit clk = 1;always #5 clk = ~clk; // Use blocking assignment
endmodule

8.虚接口

interface 封装了modue的端口(ports)、方向(modports)、同步关系 ( clocking block)interface 简化了模块之间的连接,但是无法很好地适用于基于OOP的测试平台,无法在program ,class中进行实例化

为了解决这个问题, System Verilog引入了virtual interface的概念。 使用virtual interface是为了消除绝对路径,尽可能的减少验证代码的大面积修改。绝对路径:以前在TB里面引用都是接口.xxx等,使用虚接口之后,减少大面积的修改。

virtual interface的本质是指针,是指向interface的指针,即virtual interface是可以在class中实例化的数据类型,使用virtual interface可与被测设计(DUT)进行间接地通信,而无需使用层次结构引用。

ㅤㅤㅤ在这里插入图片描述

如图所示:interface将测试平台与DUT分开。 virtual interface在TB的不同位置操纵一组虚拟信号,而不是直接操纵实际的信号。

在测试平台使用virtual interface时,需要满足以下3个要求:

  1. 实例化的接口必须正确连接到DUT。

    // 创建一个interface简化与DUT的连接
    interface counter_if (input logic clk);logic load_valid;logic [3:0]load_value;
    endinterfacemodule tb_top;logic rstn,clk;logic [3:0]out;// 实例化接口counter_if dutif(clk);counter u_counter (.resetn(rstn),.clk(clk),.load_valid(dutif.load_valid),.load_value(dutif.load_value),.q(out));
    endmodule
    
  2. 必须在类中声明virtual interface句柄,并且有相应驱动。

    // 创建一个transaction用来生成随机激励
    class transaction;rand logic load_valid;rand logic [3:0]load_value;
    endclass// 创建一个驱动激励到DUT上
    class driver;virtual counter_if vif;transaction tr;function new(input virtual counter_if vif);this.vif=vif;endfunctiontask run (int n=10);for(int i=0;i<n;i++) begintr=new();assert(tr.randomize());$display("tr.load_valid=%d,tr.load_value=%d", tr.load valid, tr.load_value);@(posedge vif.clk) beginvif.load_valid <= tr.load_valid;vif.load_value <= tr.load_value;endendendtask
    endclass
    
  3. 必须将virtual interface指向实例化的interface

    counter_if dutif(clk);driver my_driver; // create my_driver
    initial beginmy_driver = new(dutif);
    end
    

实际案例:

counter_if.sv:定义一个接口,简化与DUT的连接。

interface counter_if (input logic clk);logic load_valid;logic [3:0]load_value;
endinterface

transaction.sv:定义了一个类,用来生成随机激励。

class transaction;rand logic load_valid;rand logic [3:0]load_value;
endclass

counter.sv:待测类型DUT,q赋初值之后就会不断的自加

module counter(input logic resetn,input logic clk,input logic [3:0] load_value,input logic load_valid, output logic [3:0] q
);always_ff @(posedge clk or negedge resetn)beginif(!resetn)q<= 4’d0;else if (load_valid)q<= load_value;elseq<= q+1;end
endmodule

driver.sv:驱动激励到DUT上

class driver;virtual counter_if vif;transaction tr;function new(input virtual counter_if vif);this.vif=vif;endfunction// 驱动interfacetask run (int n = 10);for(int i=0;i<n;i++) begintr=new();assert(tr.randomize());$display("tr.load_valid=%d,tr.load_value=%d", tr.load valid, tr.load_value);@(posedge vif.clk) begin// 通过驱动虚接口来驱动DUTvif.load_valid <= tr.load_valid;vif.load_value <= tr.load_value;endendendtask
endclass

tb_top.sv:用来将以上文件整合

module tb_top;logic clk,rstn;logic [3:0]out;counter_if dutif(clk);driver my_driver;// 接口与interface进行连接counter u_counter (.resetn(rstn),.clk(clk),.load_valid(dutif.load_valid),.load_value(dutif.load_value),.q(out) );initial begin// 连接接口my_driver=new(dutif);//实例化驱动,使虚接口句柄指向interfacerepeat(2)@(posedge clk);@(posedge rstn);repeat(5)@(posedge clk);my_driver.run(20);endinitial beginclk=1'b0; forever #5 clk=~clk;end// 驱动rstninitial beginrstn=1; repeat(2) @(posedge clk);rstn=0; repeat(5) @(posedge clk);rstn=1; repeat(50) @(posedge clk);$finish;end
endmodule

相关文章:

SystemVerilog之接口详解

1.入门实例 测试平台连接到 arbiter的例子&#xff1a;包括测试平台, arbiter仲裁器, 时钟发生器 和连接的信号。 ㅤㅤㅤ ㅤ ㅤㅤㅤㅤㅤ Arbiter里面可以自定义发送的权重&#xff0c; 是轮询还是自定义 grant表示仲裁出来的是哪一个&#xff0c;也即只有0&#xff0c;1&am…...

RabbitMq-1基础概念

RabbitMq-----分布式中的一种通信手段 1. MQ的基本概念&#xff08;message queue,消息队列&#xff09; mq:消息队列&#xff0c;存储消息的中间件 分布式系统通信的两种方式&#xff1a;直接远程调用&#xff0c;借助第三方完成间接通信 消息的发送方是生产者&#xff0c…...

深度学习1:通过模型评价指标优化训练

P(Positive)表示预测为正样本&#xff0c;N(negative)表示预测为负样本&#xff0c;T(True)表示预测正确,F(False)表示预测错误。 TP&#xff1a;正样本预测正确的数量&#xff08;正确检测&#xff09; FP&#xff1a;负样本预测正确数量&#xff08;误检测&#xff09; TN…...

excel隔行取数求和/均值

问题描述 如图有好多组数据&#xff0c;需要求每组数据对应位置的平均值 解决方法 SUM(IF(MOD(ROW(C$2:C$81), 8) MOD(ROW(C2), 8), C$2:C$81, 0))/10然后下拉右拉扩充即可&#xff0c;其中需要根据自身需要修改一些数据 SUM(IF(MOD(ROW(起始列$起始行:结束列$结束行), 每…...

批量记录收支明细,轻松通过收支占比图表轻松分析支出项目占比!

您是否希望更加直观地了解个人或企业的支出项目占比情况&#xff1f;是否想通过图表分析&#xff0c;快速定位支出的主要项目&#xff0c;并做出相应的调整&#xff1f;现在&#xff0c;我们的智能收支分析大师为您提供了一种智能化的解决方案&#xff01;只需几步操作&#xf…...

pdf怎么压缩?一分钟学会文件压缩方法

PDF文件过大一般主要原因就是内嵌大文件、重复的资源或者图片比较多&#xff0c;随之而来的问题就是占用存储空间、被平台限制发送等等&#xff0c;这时候我们可以通过压缩的方法缩小PDF文件大小&#xff0c;下面就一起来看看具体的操作方法吧。 方法一&#xff1a;嗨格式压缩大…...

信息安全:防火墙技术原理与应用.

信息安全&#xff1a;防火墙技术原理与应用. 防火墙是网络安全区域边界保护的重要技术。为了应对网络威胁&#xff0c;联网的机构或公司将自己的网络与公共的不可信任的网络进行隔离&#xff0c;其方法是根据网络的安全信任程度和需要保护的对象&#xff0c;人为地划分若干安全…...

PG-DBA培训14:PostgreSQL数据库升级与迁移

一、风哥PG-DBA培训14&#xff1a;PostgreSQL数据库升级与迁移 课程目标&#xff1a; 本课程由风哥发布的基于PostgreSQL数据库的系列课程&#xff0c;本课程属于PostgreSQL备份恢复与迁移升级阶段之PostgreSQL数据库升级与迁移&#xff0c;学完本课程可以PostgreSQL数据库升…...

selenium语法进阶+常用API

目录 浏览器操作 浏览器回退&#xff0c;前进 与刷新 浏览器窗口设置大小 浏览器设置宽高 浏览器窗口最大化 浏览器控制滚动条 信息打印 打印页面的标题和当前页面的URL 定位一组元素 鼠标和键盘事件 键盘 鼠标 下拉框操作 通过索引定位&#xff08;se…...

iOS UIAlertController控件

ios 9 以后 UIAlertController取代UIAlertView和UIActionSheet UIAlertControllerStyleAlert和UIAlertControllerStyleActionSheet。 在UIAlertController中添加按钮和关联输入框 UIAlertAction共有三种类型&#xff0c;默认&#xff08;UIAlertActionStyleDefault&#xff0…...

C语言好题解析(二)

目录 递归类型例题1例题2例题3例题4例题5例题6 递归类型 例题1 根据下面递归函数&#xff1a;调用函数Fun(2)&#xff0c;返回值是多少&#xff08; &#xff09;int Fun(int n) {if (n 5)return 2;elsereturn 2 * Fun(n 1); } A.2 B.4 C.8 D.16【答案】 D 【分析】 …...

数据结构介绍

1、什么是数据结构呢&#xff1f; 计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。数据结构是为了更方便的管理和使用数据&#xff0c;需要结合具体的业务来进行选择。一般情况下&#xff0c;精心选择的数据结构可以带来更高的运行或者存储效率。…...

Kafka基础及常见面试题

1. 用途 1. 流量削峰 2. 流计算 2. Kafka的核心组件 在Kafka中&#xff0c;Producer、Broker和Consumer是三个关键的角色&#xff0c;它们在整个消息传递过程中扮演不同的角色和功能&#xff1a;1. **Producer&#xff08;生产者&#xff09;**&#xff1a;生产者是消息的发…...

基于Java的ssm图书管理系统源码和论文

基于Java的ssm图书管理系统036 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 当今时代是飞速发展的信息时代。在各行各业中离不开信息处理&#xff0c;计算机被广泛应用于信息管理系统的环境。计算机的最大好…...

2020年9月全国计算机等级考试真题(C语言二级)

2020年9月全国计算机等级考试真题&#xff08;C语言二级&#xff09; 第1题 有下列程序&#xff1a; #include<stdio.h> main() { FILE*fp;int k,n,a[6]{1,2,3,4,5,6}; fpfopen("d2.dat","w"); fprintf(fp,"%d%d%d\n",a[0],…...

【rust/egui】(一)从编译运行template开始

说在前面 rust新手&#xff0c;egui没啥找到啥教程&#xff0c;这里自己记录下学习过程环境&#xff1a;windows11 22H2rust版本&#xff1a;rustc 1.71.1egui版本&#xff1a;0.22.0eframe版本&#xff1a;0.22.0rust windows安装参考&#xff1a;这里本文默认读者已安装相关环…...

VMware虚拟安装Ubuntu,然后切换Ubuntu内核版本

无论你选择哪种方法&#xff0c;一旦进入 GRUB 引导菜单&#xff0c;你应该能够选择需要的内核版本并启动系统。 打开终端&#xff1a;你可以通过按下 Ctrl Alt T 快捷键来打开终端。 使用 sudo&#xff1a;切换内核需要管理员权限&#xff0c;因此你需要使用 sudo 命令。首…...

爆肝整理,Python自动化测试-Pytest参数化实战封装,一篇打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 参数化&#xff1…...

西门子AI面试问答(STAR法则回答实例)

0.试题情况 0.未来三到五年的职业规划&#xff08;不计入成绩&#xff0c;测试用&#xff09;&#xff1b; 1.一些基本问题&#xff0c;目前所在城市目标薪资意向工作城市&#xff08;手动输入&#xff0c;非视频录制&#xff09;&#xff1b; 2.宝洁8大问的问题1个英文回答…...

中间平台工具 - graylog

graylog是非常好用的数据处理平台&#xff0c;可以对数据进行&#xff1a;streams分类、pipeline、正则匹配、统计汇总、定制化配置Alerts 等处理。 graylog的一些概念&#xff1a; 索引(消息存储的位置&#xff0c;默认indices default) streams(从inputs里面&#xff0c;通…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...