一、实验室任务

        本章的实验任务是 PS 将数据写入BRAM,然后从 BRAM 中读出数据,并通过串口打印出来;与此同时,PL 从通过自定义ip核从BRAM中同样读出数据,并通过ILA 来观察读出的数据与串口打印的数据是否一致。这里是通过PS写入进的只有数据信息,而无法读数据,因此通过ILA观察数据。

二、实验整体架构

三、自定义ip写进ram的控制ip核

        这个ip核呢是将我们通过AXI输入进BRAM的数据通过自定义的ip核转为合适的ram接口信息接到ramip核上,这样就可以通过ps端输入的读使能,读地址读数据长度信息转化为ram的读使能,读地址,保证时序正确。

四、设计流程

一、自定义ip核。

1、创建IP管理器

2、选择AXI接口的ip核,然后一直保持默认最后点击完成,

3、编辑这个ip,右键ip核,然后选择编辑选项,进入编辑页面,然后默认ok就行

4、添加一个控制文件(.v)如下

        为什么要写这个模块呢?为什么不能通过ps侧输入读使能,读数据直接连接到ram的ip核上呢?在我看来这是因为ps侧的逻辑无法精准控制时钟逻辑,也就是ps侧无法做到像pl侧的严格时序控制。pl侧的逻辑是在每个时钟内做自己的事情,每个时钟周期都有严格的要求,因此我们在PS侧无法做到如此严格的时序要求。所以通过一个自定义控制模块对输入的信号进行处理,使得时序要求满足我们pl侧的逻辑。

module ram_ip
(input 		 		 pl_rst_n		,input		 		 pl_clk			,input		 		 ps_read_en		,//开始读的使能input		 [31:0]	 ps_start_addar	,//开始读的起始地址input		 [31:0]	 ps_data_num	,//需要读取的数量//bram接口output               ram_clk    	,//RAM时钟input        [31:0]  ram_rd_data	,//RAM中读出的数据,这个接口是读出来的数据需要我们通过该控制器输出到ps端。output  reg          ram_en     	,//RAM使能信号,这个接口是读使能信号,需要根据我们ps侧输入的几个信息给出合适的读信号。output  reg  [31:0]  ram_addr   	,//RAM地址,这个也需要通过ps侧输入的起始地址和需要读取的数量来生成的。output  reg  [3 :0]  ram_we     	,//RAM读写控制信号output  reg  [31:0]  ram_wr_data	,//RAM写数据output               ram_rst     	 //RAM复位信号,高电平有效);assign ram_clk=pl_clk;
assign ram_rst=1'b0;always @(posedge pl_clk)
if(!pl_rst_n)ram_we<=4'd0;
else ram_we<=ram_we;always @(posedge pl_clk)
if(!pl_rst_n)ram_wr_data<=32'd0;
else ram_wr_data<=ram_wr_data;reg		ps_read_en_reg;
always @(posedge pl_clk)
if(!pl_rst_n)ps_read_en_reg<=1'b0;
else ps_read_en_reg<=ps_read_en;wire ps_read_en_pos=ps_read_en&~ps_read_en_reg;parameter 		A_EDA=3'd0,A_ADD=3'd1,A_DOW=3'd2;reg 	[2:0]	state;
always @(posedge pl_clk)if(!pl_rst_n)state<=A_EDA;else case(state)A_EDA:state<=(ps_read_en_pos)	?	A_ADD	:	A_EDA;A_ADD:state<=(ram_addr-ps_start_addar+2'd2==ps_data_num)	?	A_DOW	:	A_ADD;A_DOW:state<=A_EDA;default:state<=A_EDA;endcasealways @(posedge pl_clk)if(!pl_rst_n)ram_en<=1'b0;else case(state)A_EDA:if(ps_read_en_pos) ram_en<=1'b1;A_ADD:ram_en<=1'b1;default:ram_en<=1'b0; endcasealways @(posedge pl_clk)if(!pl_rst_n)ram_addr<=32'd0;else case(state)A_EDA:if(ps_read_en_pos) ram_addr<=ps_start_addar;A_ADD:ram_addr<=ram_addr+1'b1;default:ram_addr<=32'd0;endcaseendmodule

        上面是我们的需要添加进我们ip核的verilog代码。下面是systemverilog仿真代码和仿真图。由图可知在我们的pl侧受到来自ps的使能和读数据信息时候,会产生一个高脉冲,然后通过状态机完成对读数据信息的转化,转化成我们pl侧ram接口可以识别的信息,比如读使能,使能对应的读地址。由仿真图也可以看出:当我们的pl侧检测到来自ps侧的上升沿时就会立马进入ram接口时序生成状态,依据起始地址,读数量等生成我们需要的接口时序。

`timescale 1ns/1ns
module ram_ip_sim();reg 	 	 	   pl_rst_n			;
reg		  		   pl_clk			;
reg		  		   ps_read_en		;
reg		  [31:0]   ps_start_addar	;
reg		  [31:0]   ps_data_num		;//bram接口
wire               ram_clk    		;
reg        [31:0]  ram_rd_data		;
wire               ram_en     		;
wire       [31:0]  ram_addr   		;
wire       [3 :0]  ram_we     		;
wire       [31:0]  ram_wr_data		;
wire               ram_rst     	    ;initial beginpl_clk<=1'b0;forever #10 pl_clk=~pl_clk;
endinitial beginpl_rst_n=1'b0;repeat(3) @(posedge pl_clk);pl_rst_n=1'b1;
endinitial beginps_read_en		=1'b0 ;ps_start_addar	=32'd0;ps_data_num		=32'd0;ram_rd_data		=32'd0;
endtask data_send;repeat(3) @(posedge pl_clk);ps_read_en		=1'b1  ;ps_start_addar	=32'd0 ;ps_data_num		=32'd10;repeat(15) @(posedge pl_clk);ps_read_en		=1'b0 ;ps_start_addar	=32'd0;ps_data_num		=32'd0;endtask :	data_send;initial beginwait(pl_rst_n);fork beginrepeat(1) @(posedge pl_clk);data_send;endjoin
endram_ip  ram_ip_un
(.pl_rst_n		(pl_rst_n		),.pl_clk			(pl_clk			),.ps_read_en		(ps_read_en		),//开始读的使能.ps_start_addar	(ps_start_addar	),//开始读的起始地址.ps_data_num	(ps_data_num	),//需要读取的数量.ram_clk    	(ram_clk    	),//RAM时钟.ram_rd_data	(ram_rd_data	),//RAM中读出的数据,这个接口是读出来的数据需要我们通过该控制器输出到ps端。.ram_en     	(ram_en     	),//RAM使能信号,这个接口是读使能信号,需要根据我们ps侧输入的几个信息给出合适的读信号。.ram_addr   	(ram_addr   	),//RAM地址,这个也需要通过ps侧输入的起始地址和需要读取的数量来生成的。.ram_we     	(ram_we     	),//RAM读写控制信号.ram_wr_data	(ram_wr_data	),//RAM写数据.ram_rst     	(ram_rst     	) //RAM复位信号,高电平有效);endmodule

 5、需要修改的地方

在顶层模块添加输出端口

在顶层例化的模块添加例化模块修改的端口。

在AXI接口模块添加输出接口,然后例化我们的bram控制器

在例化我们添加的模块可知,我们例化模块的使能信号,我存在寄存器0的第一位,因此我们需要在ps侧C语言代码中操作该寄存器就可以给该bram控制模块输出想要的信息,同理我们用到了寄存器1和2分别接收来自ps侧的起始地址和读数据量,然后由该信息就可以让bram控制模块输出满足时序要求的读使能端口和读地址。

6、点击文件组,这里就是我们添加和修改文件后需要刷新

7、这里是常量刷新(如果你是替换的代码就先进代码随便打个空格然后保存就会刷新)

8、按照如下操作分别将信号接口从时钟和复位接口移出去ram_rst和ram_clk

9、这里有两个警告,这是因为我们顶层的输出端口没有和其他的ip核端口和形成映射关系,因此这里会有警告不知道对应的接口是哪个,因此我们添加输出端口映射。

10、添加输出端口映射。右键随便一个端口,然后点击add bus interface。

11、先修改我们要对接的端口,这里我们选择bram端口。然后添加该接口映射的总线名字,然后选择主端口,因为这个模块控制的是ram ip的读数据信息。

12、添加端口映射,点一下需要映射的端口然后点击映射即可,按照此流程将所有端口映射。这样做的目的是为了我们软件可以自动帮我们连线,不需要我们一个一个连。

13、将端口的属性添加到自适应列。这样我们连接端口时,端口的信号会自动和从机端口属性保持一致,这样不需要我们一个一个的设置。

14、点击提示信息

15、点击下面的生成ip核

二、IP组装

1、先修改我们的最小系统IP,因为在hello_word实验时将有些端口取消了,这里我们重新添加回来,如下:GP接口和时钟复位添加进来

2、添加AXI bram控制器,并按照如图修改

3、添加bram ip核,并按照如图修改两个地方

4、添加我们自己写的ip控制器,不需要修改

5、点击自动连接,然后全部选中,然后为这两个ip核的端口设置连接的ip核接口,这样这两个ip核的接口就会自动连接到我们的双端口bram上去,实现一个ip核写,一个ip核读。然后点击确定后点击重新布局。 

6、验证设计,然后验证无误点击ok即可。

7、修改ram容量大小,这里可以将两个都改为4k也可以不改。

8、生成输出文件,然后ok即可

9、生成顶层文件,这里需要记住的是在原来的hello的工程基础上的顶层没有改动,可以不生成,如果是重新建立的工程要生成顶层文件。以下是已经生成过的顶层文件重新生成,默认点击ok即可

三、添加ILA

1、点击综合

2、点击综合设计->点击step up debug

3、next后添加我们要探针的信号,如图,导航到ram ip核的U0下添加我们要探查的信号

4、为探查信号添加时钟,搜索选择ALL_CLOCK,然后选择下列时钟后点击🆗。重复刚才步骤为这三个信号都添加时钟。然后一直默认点击ok。

5、然后点击实现,然后点击生成bit流

6、导出设计文件,勾选bit流后点击🆗即可,一定要勾选bit流,因为这里用到了pl端的设计。

7、打开SDK

四、SDK设计

1、新建空项目。

2、建立一个源文件,命名main.c

3、复制如下代码

#include "stdio.h"
#include "xbram_hw.h"
#include "stdio.h"
#include "custom_pl_bram_ps.h"
#include "xparameters.h"
#include "sleep.h"#define PL_BRAM_START		CUSTOM_PL_BRAM_PS_S00_AXI_SLV_REG0_OFFSET//寄存器1输出使能信号
#define PL_BRAM_START_ADDR	CUSTOM_PL_BRAM_PS_S00_AXI_SLV_REG1_OFFSET//寄存器2输出起始地址
#define PL_BRAM_LEN			CUSTOM_PL_BRAM_PS_S00_AXI_SLV_REG2_OFFSET//寄存器3输出数据长度#define PL_BRAM_BASE		XPAR_CUSTOM_PL_BRAM_PS_0_S00_AXI_BASEADDR //自定义ip的地址#define START_ADDAR			0//
#define PL_BRAM_DATA_LEN	4//每个bram的深度为4个字节char input_data[1024]="www.com.lzs"	;
int  num_data			;int main()
{//通过调试发现如果没初值,那会将数据写入到系统分配的初始地址位置。int wr_cnt=START_ADDAR;printf("test start!");sleep(5);//while(1)//{//scanf("please input data: %s",input_data);num_data=strlen(input_data);for(int i=START_ADDAR*PL_BRAM_DATA_LEN;i<(START_ADDAR+num_data)*PL_BRAM_DATA_LEN;i+=PL_BRAM_DATA_LEN){//第一个参数为写入AXIip核的地址XBram_WriteReg(XPAR_BRAM_0_BASEADDR,i,input_data[wr_cnt]);printf("w_data:%c,odata : %d\n",input_data[wr_cnt],input_data[wr_cnt]);wr_cnt++;}//}//设备ip,ip映射(寄存器2),写入数据的bram起始地址。其实就是像我们自定义的ip核里面的AXI寄存器写入数据。//这个寄存器就是连接我们自己编写的bram读控制文件的输入端口。CUSTOM_PL_BRAM_PS_mWriteReg(PL_BRAM_BASE,PL_BRAM_START_ADDR,START_ADDAR*PL_BRAM_DATA_LEN);//配置长度CUSTOM_PL_BRAM_PS_mWriteReg(PL_BRAM_BASE,PL_BRAM_LEN,(START_ADDAR+num_data)*PL_BRAM_DATA_LEN);//配置使能,让我们的自定义ip采集上升沿CUSTOM_PL_BRAM_PS_mWriteReg(PL_BRAM_BASE,PL_BRAM_START,0x00000001);CUSTOM_PL_BRAM_PS_mWriteReg(PL_BRAM_BASE,PL_BRAM_START,0x00000000);printf("\naddares,data\n");int read_data;for(int i=START_ADDAR*PL_BRAM_DATA_LEN;i<(START_ADDAR+num_data)*PL_BRAM_DATA_LEN;i+=PL_BRAM_DATA_LEN){read_data=XBram_ReadReg(XPAR_BRAM_0_BASEADDR,i);printf("addares: %d, data: %c, odata : %d\n",i/PL_BRAM_DATA_LEN,read_data,read_data);}return 0;}

4、修改报错信息,这里是因为系统生成的库是按照我们自定义ip核名字生成的,如果你是按照我的步骤来的就复制最后修改好的代码。

5、找到对应的库文件,然后找到这几个参数复制改变定义

6、找到这几个库文件的函数修改为以下函数

7、修改完后保存,如果你的自定义ip核的命名也为pl_ps_bram就可以直接复制下面的

#include "stdio.h"
#include "xbram_hw.h"
#include "stdio.h"
#include "pl_ps_bram.h"
#include "xparameters.h"
#include "sleep.h"#define PL_BRAM_START		PL_PS_BRAM_S00_AXI_SLV_REG0_OFFSET//寄存器1输出使能信号
#define PL_BRAM_START_ADDR	PL_PS_BRAM_S00_AXI_SLV_REG1_OFFSET//寄存器2输出起始地址
#define PL_BRAM_LEN			PL_PS_BRAM_S00_AXI_SLV_REG2_OFFSET//寄存器3输出数据长度#define PL_BRAM_BASE		XPAR_PL_PS_BRAM_0_S00_AXI_BASEADDR //自定义ip的地址#define START_ADDAR			0//
#define PL_BRAM_DATA_LEN	4//每个bram的深度为4个字节char input_data[1024]="www.com.lzs"	;
int  num_data			;int main()
{//通过调试发现如果没初值,那会将数据写入到系统分配的初始地址位置。int wr_cnt=START_ADDAR;printf("test start!");sleep(5);//while(1)//{//scanf("please input data: %s",input_data);num_data=strlen(input_data);for(int i=START_ADDAR*PL_BRAM_DATA_LEN;i<(START_ADDAR+num_data)*PL_BRAM_DATA_LEN;i+=PL_BRAM_DATA_LEN){//第一个参数为写入AXIip核的地址XBram_WriteReg(XPAR_BRAM_0_BASEADDR,i,input_data[wr_cnt]);printf("w_data:%c,odata : %d\n",input_data[wr_cnt],input_data[wr_cnt]);wr_cnt++;}//}//设备ip,ip映射(寄存器2),写入数据的bram起始地址。其实就是像我们自定义的ip核里面的AXI寄存器写入数据。//这个寄存器就是连接我们自己编写的bram读控制文件的输入端口。PL_PS_BRAM_mWriteReg(PL_BRAM_BASE,PL_BRAM_START_ADDR,START_ADDAR*PL_BRAM_DATA_LEN);//配置长度PL_PS_BRAM_mWriteReg(PL_BRAM_BASE,PL_BRAM_LEN,(START_ADDAR+num_data)*PL_BRAM_DATA_LEN);//配置使能,让我们的自定义ip采集上升沿PL_PS_BRAM_mWriteReg(PL_BRAM_BASE,PL_BRAM_START,0x00000001);PL_PS_BRAM_mWriteReg(PL_BRAM_BASE,PL_BRAM_START,0x00000000);printf("\naddares,data\n");int read_data;for(int i=START_ADDAR*PL_BRAM_DATA_LEN;i<(START_ADDAR+num_data)*PL_BRAM_DATA_LEN;i+=PL_BRAM_DATA_LEN){read_data=XBram_ReadReg(XPAR_BRAM_0_BASEADDR,i);printf("addares: %d, data: %c, odata : %d\n",i/PL_BRAM_DATA_LEN,read_data,read_data);}return 0;}

五、SDK验证

1、打开板子供电、连接串口

2、右键项目,打开运行配置

3、双击GDB,打开烧录bit流和复位

4、点击运行

5、我们发现AXIbram控制器ip核读写一致

六、ILA验证

        这里我们需要注意,由于我的设计用不了scanf输入函数,因此我加了一个延迟然后马上回到ILA界面运行,等待enb拉高,触发逻辑分析仪。如果你的scanf能用就不用加延迟,就可以通过串口输入写入信息后,SDK程序会立马运行到拉高enb的信号函数。

还有一点就是如果你调不出ILA界面请点击以下链接,查看原因和解决方法

vivado 下载程序后没有ILA界面

1、点击设备管理器后点击自动连接,进入ila界面

2、设置触发条件,选择enb,选择上升沿触发。

3、回到SDK烧录界面,烧录后马上回到ILA界面点击运行。这里一定要马上回到这个界面点运行,然后等待触发。前面说过如果你的scanf能用就可以在SDK 终端输入后这里就会触发。而这里由于我的scanf用不了,我就加了个延迟,等几秒钟后会按顺序执行到SDK设置上升沿的使能程序。然后ILA界面就会触发,如下图

4、对比写入数据。将数据以ASCLL码的形式展现

5、对比发现我们逻辑分析仪捕捉到的自定义ip核读数据转为ASCLL码后和我们SDK PS侧写进PS侧RAM的数据是一致的。因此我们的设计正确。

 

 

 

 

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

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

相关文章

LinuxC++项目开发日志——高并发内存池(5-page cache框架开发)

PageCachepage cache 设计逻辑一、PageCache 的核心定位&#xff1a;理解它与 CentralCache 的本质区别二、PageCache 的内存分配流程&#xff1a;从 “精确匹配” 到 “拆分适配”三、PageCache 的内存释放流程&#xff1a;合并小 Span&#xff0c;解决内存碎片问题page cache…

Matplotlib:绘制你的第一张折线图与散点图

Matplotlib入门&#xff1a;绘制你的第一张折线图与散点图导语 欢迎来到 Matplotlib 的世界&#xff01;对于任何使用 Python 进行数据分析或机器学习的人来说&#xff0c;数据可视化都是一项至关重要的技能。Matplotlib 是 Python 中最流行、最基础的可视化库&#xff0c;它功…

MySQL保姆级安装教程

MySQL 安装详细文档&#xff0c;适用于 Windows、macOS 和 Linux 系统&#xff0c;包含了从下载到验证安装的完整步骤&#xff1a; 一、Windows 系统安装 MySQL 1. 下载 MySQL 安装包 访问 MySQL 官方下载页&#xff1a;https://dev.mysql.com/downloads/installer/选择 “MySQ…

重塑你的大脑:从理解突触到掌控人生

重塑你的大脑&#xff1a;从理解突触到掌控人生你是否曾对自己的某些行为感到无力&#xff1f;明知应该早睡&#xff0c;却总忍不住刷手机&#xff1b;下定决心要锻炼&#xff0c;却常常半途而废。这些困扰我们的习惯&#xff0c;并非简单的意志力问题&#xff0c;其根源深深植…

《C++进阶之STL》【哈希表】

【哈希表】目录前言------------概念介绍------------1. 什么是哈希&#xff1f;------------核心术语------------一、哈希函数1. 哈希函数的核心特点是什么&#xff1f;2. 哈希函数的设计目标是什么&#xff1f;3. 常见的哈希函数有哪些&#xff1f;直接定址法除法散列法乘法…

机器学习-模型验证

验证泛化误差 在一个数据集上估计误差&#xff0c;数据集只能使用一次验证数据集&#xff1a;可以被使用多次 基本是训练数据集中的一部分 当使用“test”时&#xff0c;大多数时候指的是验证数据集 生成验证数据集方法 1、数据随机分入训练集或验证集 总是随机选n%的数据作为验…

Qt中自定义控件的三种实现方式

Qt中自定义控件的三种实现方式 在 Qt 应用开发中&#xff0c;标准控件往往无法满足所有需求。自定义控件允许开发者创建具有特定功能和外观的控件&#xff0c;提高代码复用性和界面一致性。Qt 提供了多种方式来开发自定义控件&#xff0c;从简单的组合现有控件到完全自定义绘制…

少儿舞蹈小程序(14)在线预约

目录1 创建数据模型2 搭建预约按钮3 搭建表单4 搭建管理功能整体效果总结目前我们的首页已经开发完毕了&#xff0c;包含轮播图、机构介绍、校区展示、作品与活动展示功能。家长在小程序了解了机构的基本情况之后&#xff0c;下一步就是参加试听&#xff0c;在线下真实体验一下…

TDengine 数据写入详细用户手册

TDengine 数据写入用户手册 概述 TDengine 提供了多种灵活的数据写入方式&#xff0c;以满足不同应用场景的需求。本手册将以智能电表场景为例&#xff0c;向初学者详细介绍各种数据写入方法的使用。 智能电表场景设定 假设我们需要为智能电表系统建立数据库&#xff1a; …

PTA 天梯赛 7-43:字符串关键字的散列映射

【题目来源】 https://pintia.cn/problem-sets/15/exam/problems/type/7?problemSetProblemId890 【题目描述】 给定一系列由大写英文字母组成的字符串关键字和素数 P&#xff0c;用移位法定义的散列函数 H(Key) 将关键字 Key 中的最后 3 个字符映射为整数&#xff0c;每个字…

Python核心技术开发指南(065)——with语句

版权声明 本文原创作者:谷哥的小弟 作者博客地址:http://blog.csdn.net/lfdfhl with语句定义 with语句是Python中用于简化资源管理的语法结构,通过上下文管理器(实现__enter__()和__exit__()方法的对象)确保资源在使用完毕后被正确释放,无论代码块是否发生异常。其核心作…

从基础到高级:一文快速认识MySQL UPDATE 语句

在数据库日常运维与开发中&#xff0c;数据更新是与数据查询同等重要的核心操作。MySQL 的 UPDATE 语句凭借其灵活的语法结构和强大的功能&#xff0c;能够满足从简单字段修改到复杂关联表更新的各类需求。然而&#xff0c;若使用不当&#xff0c;不仅可能导致数据一致性问题&a…

材料基因组计划(MGI)入门:高通量计算与数据管理最佳实践

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;注册即送-H卡级别算力&#xff0c;80G大显存&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生更享专属优惠。 摘要 材料基因组计划&#xff08;Materials Genome Ini…

Vision Transformer (ViT) :Transformer在computer vision领域的应用(一)

在图像领域,CNN卷积神经网络结构已经成为了标配,所有的模型都是基于CNN来构造的。 而在NLP领域,自从Transformer横空出世之后,基本上也统治了NLP的各个领域。 基于Transformer的强大,一些论文的工作都是将Transformer也应用到CV领域,在这篇论文:AN IMAGE IS WORTH 16X1…

自动驾驶中的传感器技术45——Radar(6)

本文详细介绍4D雷达相关解决方案&#xff0c;4D雷达关键词&#xff1a;4D Imaging Radar 1、4D雷达特点 图1 4D雷达 vs 3D雷达图2 4D雷达虚拟通道数量不断增加图3 4D雷达 vs 3D雷达 vs 摄像头和激光雷达图4 毫米波雷达在不同驾驶等级下的应用需求Ref&#xff1a;https://pdf.d…

浏览器调试工具详解

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

代码审计-PHP专题原生开发SQL注入1day分析构造正则搜索语句执行监控功能定位

挖掘技巧&#xff1a; -语句监控-数据库SQL监控排查可利用语句定向分析 -功能追踪-功能点文件SQL执行代码函数调用链追踪 -正则搜索-(update|select|insert|delete|).*?where.* 如何快速的在多个文件代码里面找脆弱&#xff1a; 1、看文件路径 2、看代码里面的变量&#…

Linux中:调试器gdb/cgdb的使用

引言在追寻光的路上不断前行&#xff0c;详细介绍Linux下gdb/cgdb的使用。一、准备• 程序的发布方式有两种&#xff0c;默认是 debug 模式和 release 模式。Linux gcc/g编译出来的二进制程序默认是release模式• 要使用gdb调试&#xff0c;必须在源代码生成⼆进制程序的时候加…

【算法】【链表】148.排序链表--通俗讲解

算法通俗讲解推荐阅读 【算法–链表】83.删除排序链表中的重复元素–通俗讲解 【算法–链表】删除排序链表中的重复元素 II–通俗讲解 【算法–链表】86.分割链表–通俗讲解 【算法】92.翻转链表Ⅱ–通俗讲解 【算法–链表】109.有序链表转换二叉搜索树–通俗讲解 【算法–链表…

计算机组成原理:存储系统概述

&#x1f4cc;目录&#x1f4be; 存储系统概述&#xff1a;计算机的“记忆中枢”&#x1f3d7;️ 一、存储系统的层次结构&#xff1a;速度与容量的“黄金平衡”&#xff08;一&#xff09;经典存储层次金字塔&#xff08;二&#xff09;层次结构的设计原则&#xff08;三&…