【仿真】波形dump(vcd,shm,fsdb,saif,...)

5 篇文章 0 订阅

 IC研发过程中,可能会涉及到多种工具,过程中也可能需要不同格式的波形文件。从网上搜索情况来看,介绍saif的较少,所以这里着重介绍一下saif的dump。

 

下面粘贴了两个相关背景知识的帖子,如其中介绍,saif主要用在功耗分析中。

gPTPX功耗分析实战, VCD, SAIF, FSDB的区别_RTL2GDS的博客-CSDN博客PTPX功耗分析实战, VCD, SAIF, FSDB的区别PTPX功耗分析VCD,SAIF,FSDB的区别注:文章转载自微信公众号 RTL2GDS (微信号:rtl2gds)你好,我是老本(Benjamin)。STA系列文章定期会在微信公众号每周日晚8点更新,其它时间就先写点随笔吧,这是一篇PTPX进行功耗分析的实战文章,介绍了主要的命令和选项,以及对反标翻转率的解析,不同波形文件的比较。...https://blog.csdn.net/RTL2GDS/article/details/104957522PTPX功耗分析实战, VCD, SAIF, FSDB的区别PTPX功耗分析VCD,SAIF,FSDB的区别注:文章转载自微信公众号 RTL2GDS (微信号:rtl2gds)你好,我是老本(Benjamin)。STA系列文章定期会在微信公众号每周日晚8点更新,其它时间就先写点随笔吧,这是一篇PTPX进行功耗分析的实战文章,介绍了主要的命令和选项,以及对反标翻转率的解析,不同波形文件的比较。...https://blog.csdn.net/RTL2GDS/article/details/104957522

(二)功耗的分析_沧海一升的博客-CSDN博客_功耗分析前面学习了进行低功耗的目的个功耗的构成,今天就来分享一下功耗的分析。由于是面向数字IC前端设计的学习,所以这里的功耗分析是基于DC中的power compiler工具;更精确的功耗分析可以采用PT,关于PT的功耗分析可以查阅其他资料,这里不涉及使用PT的进行功耗分析。  (1)功耗分析与流程概述  上一个小节中讲解了功耗的构成,并且结合工艺库进行简要地介绍了功耗的计算。但是实际上,我们根本...https://blog.csdn.net/qq_21842097/article/details/88420108

1. 下面介绍一下 vcs 如何 dump saif文件

在 vcs的 user_guide中,有一章节专门介绍saif相关的选项

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_12,color_FFFFFF,t_70,g_se,x_16

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

比较推荐使用ucli的方式进行,不用修改环境。

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

2. 也可以从波形文件直接转换成 saif

比如 fsdb2saif

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

 watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16


用ucli方式进行dump,举例如下

(run xxx1 ps/ns/us....)                    //可以设置先run一段时间,再dump波形
call $fsdbDumpvars(0, xxx, "+mda")         //设置dump的层次,以及其他选项
call $fsdbDumpon                           //开始dump波形
run xxx2 ps/ns/us.....                     //再run一段时间
power -gate_level on mda                   //saif dump设置
power xxx_scope                            //saif dump 层次
power -enable                              //开始dump saif
run xxx3 ps/ns/us.....                     //再run xxx3
power -disable                             //停止dump saif
power -report xxx.saif xxx_scale xxx_scope //生成saif 报告
run xxx4 ps/ns/us.....                     //再run xxx4
call $fsdbDumpoff                          //暂停dump波形
fsdbDumpFinish                 //如果不调用此函数,那么调用call $fsdbDumpon可以接着dump 波形
run xxx5 ps/ns/us.....         //再run xxx5
exit                           //退出仿真

把以上内容保存成xxx.tcl,vcs仿真选项中加入 -ucli -i xxx.tcl,即可控制波形的dump。

上述内容,会dump  [(xxx1), (xxx1)+xxx2+xxx3+xxx4] 时间段内的fsdb。

会生成 [(xxx1)+xxx2, (xxx1)+xxx2+xxx3] 时间段内的saif。

在(xxx1)+xxx2+xxx3+xxx4+xxx5 仿真结束

针对不同的波形文件,也可以使用ucli进行dump

cb7a58ba6b2d4c2094ee521bfdd57306.jpg


下面介绍一些fsdb dump的技巧

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAc3RtMzJzdHU=,size_20,color_FFFFFF,t_70,g_se,x_16


其中,+fsdb+force对于force信号的调试比较有帮助,下面的内容引自

verdi中如何查看force信号信息 | 骏的世界

verdi中如何查看force信号信息

发表于2020年3月8日卢 骏

在仿真中,我们会有对信号进行force的操作,从而实现某些特定的功能。但是在仿真波形中,不能直接从波形上看出,这些信号的驱动,是因为前级电路的驱动,还是因为force的原因的驱动。从而使debug非常的不友好。

其实在verdi中,是可以直接看到force信号的信息的。这样的话,就会方便我们去debug force的信号。

要想要verdi中,查看force信号,就需要vcs在仿真时候,生成fsdb波形时,加入force信号的波形信息。只需要在仿真参数中,加入 +fsdb+force 参数即可。当fsdb波形生成后,就可以在verdi中,直接查看到信号的force信息。

如以下代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

module tb_top();

    reg a;

    reg b;

    wire c;

  

    my_and u_my_and(a, b, c);

  

    initial begin

        a = 1;

        b = 0;

        #10;

        force u_my_and.a = 1'b1;

        force u_my_and.b = 1'b1;

        #10;

        force u_my_and.a = 1'b0;

        force u_my_and.b = 1'b0;

        #10;

        release u_my_and.a;

        release u_my_and.b;

        #10;

        $finish();

    end

  

    initial begin

        $fsdbDumpfile("force.fsdb");

        $fsdbDumpvars(0, "tb_top");

    end

endmodule: tb_top

其中my_and模块,代码如下:

1

2

3

4

5

6

7

module my_and(

    input a,

    input b,

    output c

);

    assign c = a & b;

endmodule

编译仿真的Makefile如下:

1

2

3

4

5

6

7

8

compile:

    vcs -full64 -sverilog  -debug_acces=all my_and.v tb_top.sv -kdb

  

run:

    ./simv +fsdb+force

  

verdi:

    verdi -dbdir simv.daidir -ssf force.fsdb

在仿真的时候,加上+fsdb+force选项。

打开verdi,查看信号。

cce3994a19082b3b88dfdac1f9271557.png

从波形上,能够清晰的看到force信号的信息。用紫色虚线标识的波形,就表示这一段时间内,信号是被force驱动的。

  • 向下的紫色箭头,表示这个时候,有force语句针对该信号

  • 向上的紫色箭头,表示这个时候,有release语句针对该信号

    通过特殊的紫色波形标记,就可以很清晰的知道信号的force信息了。

在一个环境中,可能force的信号比较多,通过上面的波形方式,去把每一个信号给拉出来,判断信号是否有force,效率就会比较低了。

此时,我们可以使用fsdbreport命令,从波形里面,把所有的信号force的信息,全部给抓出来,保存在一个文件中,这样,我们通过该文件,就可以知道仿真过程中的所有信号force信息。

命令如下:

1

fsdbreport xxx.fsdb -find_forces -s "/*" -level level_number -o xxx.txt

其中:

  • xxx.fsdb:是输入的fsdb波形文件

  • -s: 指定查找force信息的层次, /* 表示从最顶层开始

  • -level:表示从指定的层次,向下查找层次的数目。0表示指定的层次和以下所有的层次。1表示指定的层次,2表示指定的层次和下一层次。之后依次类推,一般都是直接使用0

  • -o:指定输出文件

针对刚刚上述产生的force.fsdb波形,来提取force信息。命令如下:

1

fsdbreport force.fsdb -find_forces -s "/*" -level 0 -o force.txt

生成的force.txt信息如下:

e44352f354112e171f49a360fa6a158f.png

该文件中,会打印每一个force信号的信息:

  • force信号的层次路径

  • force信号在什么时刻被force,force的值是多少

  • force信号在什么时刻被release

通过查阅该文件,就可以知道波形文件中,所有的force信号的信息,从而可以帮助我们去debug。


以下内容转载自:

interface clocking block使用 及 verdi capture delta cycle_clockingblock_劲仔小鱼的博客-CSDN博客

dump glitch 毛刺分析 及 异步复位同步释放_vcs dump glitch_劲仔小鱼的博客-CSDN博客

clocking block

Input (or inout) signals are sampled at the designated clock event. If an input skew is specified, then the signal is sampled at skew time units before the clock event. Similarly, output (or inout) signals are driven skew simulation time units after the corresponding clock event. Below Figure shows the basic sample and drive timing for a positive edge clock.

clocking block是sv中引入的语法,采样信号发生在时钟沿之前的input skew units,驱动信号发生在时钟沿之后的output skew units。避免TB与RTL接口上的冒险,相当于模拟实际器件的setup time, hold time。若实际器件timing不满足,则会产生亚稳态。实际仿真中就是X态,无法确定高低电平。
 

示例:

# top.sv
interface master_interface();
	logic pclk;
	logic prest_n;
	logic [31:0] pwdata;
	logic [31:0] prdata;
	
	clocking drv_cb @(posedge pclk);
		default input #1 output #1;
		output pwdata;
		input prdata;
	endclocking
	
	clocking mon_cb @(posedge pclk);
		default input #1 output #1;
		input pwdata;
		input prdata;
	endclocking
	
endinterface

class master;
	logic [31:0] data;
	virtual master_interface vif;
	
	task driver();
		vif.pwdata = 0;
		wait(vif.prest_n == 1);
		@(posedge vif.pclk);
		vif.pwdata <= 1;
		$display("%0t [driver]",$realtime);
		#5;
		@(posedge vif.pclk);
		vif.drv_cb.pwdata <= 2;
		$display("%0t [driver]",$realtime);
		#5;
		@(vif.drv_cb);
		vif.pwdata <= 3;
		$display("%0t [driver]",$realtime);
		#5;
		@(vif.drv_cb);
		vif.drv_cb.pwdata <= 4;
		$display("%0t [driver]",$realtime);
		#10;
	endtask
	
	task monitor();
		wait(vif.prest_n == 1);
		//@(posedge vif.pclk); // vif.pwdata = 0 | vif.mon_cb.pwdata = 0
		@(vif.mon_cb);         // vif.pwdata = 1 | vif.mon_cb.pwdata = 0
		$display("%0t [monitor] vif.pwdata:%0h",$realtime,vif.pwdata);
		$display("%0t [monitor] vif.mon_cb.pwdata:%0h",$realtime,vif.mon_cb.pwdata);
		#5;
		//@(posedge vif.pclk); // vif.pwdata = 1 | vif.mon_cb.pwdata = 0
		@(vif.mon_cb);         // vif.pwdata = 1 | vif.mon_cb.pwdata = 1
		$display("%0t [monitor] vif.pwdata:%0h",$realtime,vif.pwdata);
		$display("%0t [monitor] vif.mon_cb.pwdata:%0h",$realtime,vif.mon_cb.pwdata);
		#5;
		//@(posedge vif.pclk); // vif.pwdata = 2 | vif.mon_cb.pwdata = 1
		@(vif.mon_cb);         // vif.pwdata = 2 | vif.mon_cb.pwdata = 2
		$display("%0t [monitor] vif.pwdata:%0h",$realtime,vif.pwdata);
		$display("%0t [monitor] vif.mon_cb.pwdata:%0h",$realtime,vif.mon_cb.pwdata);
		#5;
		//@(posedge vif.pclk); // vif.pwdata = 3 | vif.mon_cb.pwdata = 2
		@(vif.mon_cb);         // vif.pwdata = 3 | vif.mon_cb.pwdata = 3
		$display("%0t [monitor] vif.pwdata:%0h",$realtime,vif.pwdata);
		$display("%0t [monitor] vif.mon_cb.pwdata:%0h",$realtime,vif.mon_cb.pwdata);
		#10;
	endtask
endclass

module top;
	logic clk;
	logic rst_n;
	logic [31:0] rdata,wdata;
	logic [31:0] cnt = 0;

	master_interface m_if();

	always @(posedge clk or negedge rst_n) begin
		if (rst_n == 1'b0) 
			wdata <= 'h0;
		else
			wdata <= m_if.pwdata;
	end
	
	always @(posedge clk or negedge rst_n) begin
		if (rst_n == 1'b0) 
			m_if.prdata <= 'h0;
		else
			m_if.prdata <= cnt++;
	end	

	always #5 clk = ~clk;

	assign m_if.pclk = clk;
	assign m_if.prest_n = rst_n;

	initial begin
		clk = 'b0;
		rst_n = 'b0;
		#12;
		rst_n = 'b1;
	end

	initial begin
		master m_inst;
		m_inst = new();
		m_inst.vif = m_if;
		fork
			m_inst.driver();
			m_inst.monitor();
		join_any
		$finish();
	end

	initial begin
		$fsdbDumpfile("wave.fsdb");
		$fsdbDumpvars;
	end
endmodule

# Makefile
all: clean comp run
clean:
	@rm .[a-zA-Z0-9]* -rf
	@ls | grep -v Makefile | grep -v top.sv | xargs rm -rf
	@echo clean done

comp:
 	vcs -full64\
 		-kdb -lca \
 		-debug_access+all \
 		-sverilog \
 		-timescale=1ns/1ns \
 		top.sv \
 		-l compile.lg
run:
 	./simv \
 	+fsdb+delta \
 	-l sim.log
 	
wave:
	verdi -ssf wave.fsdb &

如上示例:

  1. input skew,output skew各1ns。
  2. task driver() 驱动,task monitor()采样。
  3. 15ns, 25ns, 35ns, 45ns 四个观察结点。
  4. vif.pclk,vif.drv_cb,vif.mon_cb,vif.pwdata,vif.drv_cb.pwdata,vif.mon_cb.pwdata混用。

波形:

15ns:

  1. DUT中的wdata为0,采样到的是前一拍的值。
  2. Driver中的vif.drv_cb.pwdata为X态,因为task driver中15ns驱动的信号是vif.pwdata,并不会影响vif.drv_cb scope中的pwdata信号,所以是X态。
  3. Sample中vif.pwdata为1,采样发生在vif.pwdata跳变之后。而vif.mon_cb.pwdtata为0,采样时钟沿前1ns的值。

25ns:

  1. DUT中的wdata为1,采样到的是前一拍的值。
  2. Driver中vif.pwdatavif.drv_cb.pwdata晚1ns,因为clocking block drv_cboutput skew

35ns
见 delta cycle分析。

45ns

结论:

  1. interface中尽量使用clocking来sync采样和驱动信号,避免冒险。一些TB中不使用也没有出错,只能说明这种情况下没有问题,无法保证和其他RTL连接时这种方式不会出错。
  2. vif.drv_cb.pwdata,vif.mon_cb.pwdata要分别使用vif.drv_cb和vif.mon推进时间,避免与vif.pclk混用。同理vif.pwdata避免与vif.drv_cb和vif.mon_cb混用。
  3. 如果采样clocking block中的output信号,会报错。不可以采样驱动信号。可以改用inout类型。inout类型的信号相当于input output。
     

Verdi capture delta cycle

delta cycle : 时钟采样时数据发生跳变,存在冒险。比如glitch发生,nwave上显示一个实线 |,此时glitch的上升沿和下降沿的$realtime差值为delta = 0。实际仿真器根据IEEE SV协议中的Scheduling semantics章节内容进行Event simulation

使用:

对于delta cycle的debug,verdi支持三种方式,在 ./simv时加上

  1. +fsdb+glitch=0 : 查看glitch
  2. +fsdb+sequential: 查看 event sequence
  3. +fsdb+region: 查看event region

使用+fsdb+delta默认同时采集上述三种。

To enable delta cycle dumping capability in interactive mode, use the +fsdb+delta=1|2 option at runtime.
Following is the syntax:
+fsdb+delta=1|2
1: Enables delta cycle dumping capability
2: Enables delta cycle dumping, but disables cycle dumping at time 0
Use the +fsdb+delta=0 option at runtime to disable the delta cycle dumping capability.

示例:

以上述波形35ns处为例:

event region : nWave中 View - Expand Delta

第一绿色区域为Active区,第二个红色区域为NBA区,非阻塞赋值<=NBA生效。

event sequence : nWave中 Tools - Event Sequence 

clk先跳变,vif.mon_cb.pwdata采样得到2,随后DUT中wdata被2驱动,然后vif.pwdata跳变为3。
DUT中的wdata发生在vif.pwdata之前,所以被驱动时,vif.pwdata还是旧值2。

  • 1
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值