Architecture Lab:Part C【流水线通用原理/Y86-64的流水线实现/实现IIADDQ指令】

目录

任务描述

知识回顾

流水线通用原理

Y86-64流水线实现(PIPE-与PIPE)

开始实验

IIADDQ指令的添加

优化 ncopy.ys

仅用第四章知识,CEP=11.55

8x1展开,CPE=9.35

8x1展开+2x1展开+消除气泡,CPE=8.10 


流水线化通过让不同的阶段并行操作,改进了系统的吞吐量性能。

在任意一个给定的时刻,多条指令被不同的阶段处理。在引入这种并行性的过程中,我们必须非常小心,以提供与程序的顺序执行相同的程序级行为。通过重新调整SEQ各个部分的顺序,引入流水线,我们得到SEQ+,接着添加流水线寄存器,创建出 PIPE-流水线。

然后,添加了转发逻辑,加速了将结果从一条指令发送到另一条指令,从而提高了流水线的性能。有几种特殊情况需要额外的流水线控制逻辑来暂停或取消一些流水线阶段。

任务描述

Your task in Part C is to modify ncopy.ys and pipe-full.hcl with the goal of making ncopy.ys
run as fast as possible.

翻译过来就是:

第一步,首先要把 pipe-full.hcl 中加入 iaddq 指令。

第二步,优化 ncopy.ys ,使CEP降到7.5

知识回顾

流水线通用原理

就像下图流水线图上方指明的那样,流水线阶段之间的指令转移是由时钟信号来控制的。每隔120ps, 信号从0上升至1,开始下一组流水线阶段的计算。

 时间=239时,是时钟上升沿到来的前一刻,此时组合逻辑A已经完成了指令I2(蓝色),正在等待寄存器打入脉冲(即时间=240时的上升沿)。同理,组合逻辑B已经完成了指令I1(深灰色),正在等待寄存器打入脉冲(即时间=240时的上升沿)。

 时间=241时,是时钟上升沿到来之后,指令I2(蓝色)的结果刚刚打入寄存器。指令I1(深灰色)的结果也刚刚打入寄存器。

 时间=300时,是时钟上升沿到来之后,指令I2(蓝色)正在组合逻辑B中进行计算。指令I1(深灰色)正在组合逻辑C中进行计算。新加入的指令I3(浅灰色)正在组合逻辑A中进行计算。

Y86-64流水线实现(PIPE-与PIPE)

首先,对顺序的SEQ处理器做一点小的改动,将 PC的计算挪到第一阶段(取指)。原因:方便流水线源源不断的给出新指令。

然后,在各个阶段之间加上流水线寄存器。

开始实验

IIADDQ指令的添加

IIADDQ指令的添加与Part B一样。唯一要注意的是记得改条件码(set_cc)。

char simname[] = "Y86-64 Processor: pipe-full.hcl";
#include <stdio.h>
#include "isa.h"
#include "pipeline.h"
#include "stages.h"
#include "sim.h"
int sim_main(int argc, char *argv[]);
int main(int argc, char *argv[]){return sim_main(argc,argv);}
long long gen_f_pc()
{return ((((ex_mem_curr->icode) == (I_JMP)) & !(ex_mem_curr->takebranch)) ? (ex_mem_curr->vala) : ((mem_wb_curr->icode) == (I_RET)) ? (mem_wb_curr->valm) : (pc_curr->pc));
}long long gen_f_icode()
{return ((imem_error) ? (I_NOP) : (imem_icode));
}long long gen_f_ifun()
{return ((imem_error) ? (F_NONE) : (imem_ifun));
}long long gen_instr_valid()
{return ((if_id_next->icode) == (I_NOP) || (if_id_next->icode) == (I_HALT) || (if_id_next->icode) == (I_RRMOVQ) || (if_id_next->icode)== (I_IRMOVQ) || (if_id_next->icode) == (I_RMMOVQ) || (if_id_next->icode) == (I_MRMOVQ) || (if_id_next->icode) == (I_ALU)|| (if_id_next->icode) == (I_JMP) || (if_id_next->icode) == (I_CALL)|| (if_id_next->icode) == (I_RET) || (if_id_next->icode) == (I_PUSHQ) || (if_id_next->icode) == (I_POPQ) || (if_id_next->icode)== (I_IADDQ));
}long long gen_f_stat()
{return ((imem_error) ? (STAT_ADR) : !(instr_valid) ? (STAT_INS) : ((if_id_next->icode) == (I_HALT)) ? (STAT_HLT) : (STAT_AOK));
}long long gen_need_regids()
{return ((if_id_next->icode) == (I_RRMOVQ) || (if_id_next->icode) == (I_ALU) || (if_id_next->icode) == (I_PUSHQ) || (if_id_next->icode)== (I_POPQ) || (if_id_next->icode) == (I_IRMOVQ) || (if_id_next->icode) == (I_RMMOVQ) || (if_id_next->icode) == (I_MRMOVQ) || (if_id_next->icode) == (I_IADDQ));
}long long gen_need_valC()
{return ((if_id_next->icode) == (I_IRMOVQ) || (if_id_next->icode) == (I_RMMOVQ) || (if_id_next->icode) == (I_MRMOVQ) || (if_id_next->icode) == (I_JMP) || (if_id_next->icode) == (I_CALL) || (if_id_next->icode) == (I_IADDQ));
}long long gen_f_predPC()
{return (((if_id_next->icode) == (I_JMP) || (if_id_next->icode) == (I_CALL)) ? (if_id_next->valc) : (if_id_next->valp));
}long long gen_d_srcA()
{return (((if_id_curr->icode) == (I_RRMOVQ) || (if_id_curr->icode) == (I_RMMOVQ) || (if_id_curr->icode) == (I_ALU) || (if_id_curr->icode)== (I_PUSHQ)) ? (if_id_curr->ra) : ((if_id_curr->icode) == (I_POPQ) || (if_id_curr->icode) == (I_RET)) ? (REG_RSP) : (REG_NONE));
}long long gen_d_srcB()
{return (((if_id_curr->icode) == (I_ALU) || (if_id_curr->icode) == (I_RMMOVQ) || (if_id_curr->icode) == (I_MRMOVQ) || (if_id_curr->icode) == (I_IADDQ)) ? (if_id_curr->rb) : ((if_id_curr->icode) == (I_PUSHQ) || (if_id_curr->icode) == (I_POPQ)|| (if_id_curr->icode) == (I_CALL) || (if_id_curr->icode) == (I_RET)) ? (REG_RSP) : (REG_NONE));
}long long gen_d_dstE()
{return (((if_id_curr->icode) == (I_RRMOVQ) || (if_id_curr->icode) == (I_IRMOVQ) || (if_id_curr->icode) == (I_ALU) || (if_id_curr->icode)== (I_IADDQ)) ? (if_id_curr->rb) : ((if_id_curr->icode) == (I_PUSHQ) || (if_id_curr->icode) == (I_POPQ) || (if_id_curr->icode)== (I_CALL) || (if_id_curr->icode) == (I_RET)) ? (REG_RSP) : (REG_NONE));
}long long gen_d_dstM()
{return (((if_id_curr->icode) == (I_MRMOVQ) || (if_id_curr->icode) == (I_POPQ)) ? (if_id_curr->ra) : (REG_NONE));
}long long gen_d_valA()
{return (((if_id_curr->icode) == (I_CALL) || (if_id_curr->icode) == (I_JMP)) ? (if_id_curr->valp) : ((id_ex_next->srca) == (ex_mem_next->deste)) ? (ex_mem_next->vale) : ((id_ex_next->srca)== (ex_mem_curr->destm)) ? (mem_wb_next->valm) : ((id_ex_next->srca) == (ex_mem_curr->deste)) ? (ex_mem_curr->vale): ((id_ex_next->srca) == (mem_wb_curr->destm)) ? (mem_wb_curr->valm): ((id_ex_next->srca) == (mem_wb_curr->deste)) ? (mem_wb_curr->vale): (d_regvala));
}long long gen_d_valB()
{return (((id_ex_next->srcb) == (ex_mem_next->deste)) ? (ex_mem_next->vale) : ((id_ex_next->srcb) == (ex_mem_curr->destm)) ? (mem_wb_next->valm) : ((id_ex_next->srcb) == (ex_mem_curr->deste)) ? (ex_mem_curr->vale) : ((id_ex_next->srcb) == (mem_wb_curr->destm)) ? (mem_wb_curr->valm) : ((id_ex_next->srcb) == (mem_wb_curr->deste)) ? (mem_wb_curr->vale) : (d_regvalb));
}long long gen_aluA()
{return (((id_ex_curr->icode) == (I_RRMOVQ) || (id_ex_curr->icode) == (I_ALU)) ? (id_ex_curr->vala) : ((id_ex_curr->icode) == (I_IRMOVQ)|| (id_ex_curr->icode) == (I_RMMOVQ) || (id_ex_curr->icode) == (I_MRMOVQ) || (id_ex_curr->icode) == (I_IADDQ)) ? (id_ex_curr->valc) : ((id_ex_curr->icode) == (I_CALL) || (id_ex_curr->icode) == (I_PUSHQ)) ? -8 : ((id_ex_curr->icode) == (I_RET) || (id_ex_curr->icode) == (I_POPQ)) ? 8 : 0);
}long long gen_aluB()
{return (((id_ex_curr->icode) == (I_RMMOVQ) || (id_ex_curr->icode) == (I_MRMOVQ) || (id_ex_curr->icode) == (I_ALU) || (id_ex_curr->icode)== (I_CALL) || (id_ex_curr->icode) == (I_PUSHQ) || (id_ex_curr->icode) == (I_RET) || (id_ex_curr->icode) == (I_POPQ)|| (id_ex_curr->icode) == (I_IADDQ)) ? (id_ex_curr->valb) : ((id_ex_curr->icode) == (I_RRMOVQ) || (id_ex_curr->icode) == (I_IRMOVQ)) ? 0 : 0);
}long long gen_alufun()
{return (((id_ex_curr->icode) == (I_ALU)) ? (id_ex_curr->ifun) : (A_ADD));
}long long gen_set_cc()
{return (((((id_ex_curr->icode) == (I_ALU)) & !((mem_wb_next->status)== (STAT_ADR) || (mem_wb_next->status) == (STAT_INS) || (mem_wb_next->status) == (STAT_HLT))) & !((mem_wb_curr->status)== (STAT_ADR) || (mem_wb_curr->status) == (STAT_INS) || (mem_wb_curr->status) == (STAT_HLT))) | ((id_ex_curr->icode) == (I_IADDQ)));
}long long gen_e_valA()
{return (id_ex_curr->vala);
}long long gen_e_dstE()
{return ((((id_ex_curr->icode) == (I_RRMOVQ)) & !(ex_mem_next->takebranch)) ? (REG_NONE) : (id_ex_curr->deste));
}long long gen_mem_addr()
{return (((ex_mem_curr->icode) == (I_RMMOVQ) || (ex_mem_curr->icode) == (I_PUSHQ) || (ex_mem_curr->icode) == (I_CALL) || (ex_mem_curr->icode) == (I_MRMOVQ)) ? (ex_mem_curr->vale) : ((ex_mem_curr->icode) == (I_POPQ) || (ex_mem_curr->icode) == (I_RET)) ? (ex_mem_curr->vala) : 0);
}long long gen_mem_read()
{return ((ex_mem_curr->icode) == (I_MRMOVQ) || (ex_mem_curr->icode) == (I_POPQ) || (ex_mem_curr->icode) == (I_RET));
}long long gen_mem_write()
{return ((ex_mem_curr->icode) == (I_RMMOVQ) || (ex_mem_curr->icode) == (I_PUSHQ) || (ex_mem_curr->icode) == (I_CALL));
}long long gen_m_stat()
{return ((dmem_error) ? (STAT_ADR) : (ex_mem_curr->status));
}long long gen_w_dstE()
{return (mem_wb_curr->deste);
}long long gen_w_valE()
{return (mem_wb_curr->vale);
}long long gen_w_dstM()
{return (mem_wb_curr->destm);
}long long gen_w_valM()
{return (mem_wb_curr->valm);
}long long gen_Stat()
{return (((mem_wb_curr->status) == (STAT_BUB)) ? (STAT_AOK) : (mem_wb_curr->status));
}long long gen_F_bubble()
{return 0;
}long long gen_F_stall()
{return ((((id_ex_curr->icode) == (I_MRMOVQ) || (id_ex_curr->icode) == (I_POPQ)) & ((id_ex_curr->destm) == (id_ex_next->srca) || (id_ex_curr->destm) == (id_ex_next->srcb))) | ((I_RET) == (if_id_curr->icode) || (I_RET) == (id_ex_curr->icode) || (I_RET)== (ex_mem_curr->icode)));
}long long gen_D_stall()
{return (((id_ex_curr->icode) == (I_MRMOVQ) || (id_ex_curr->icode) == (I_POPQ)) & ((id_ex_curr->destm) == (id_ex_next->srca) || (id_ex_curr->destm) == (id_ex_next->srcb)));
}long long gen_D_bubble()
{return ((((id_ex_curr->icode) == (I_JMP)) & !(ex_mem_next->takebranch))| (!(((id_ex_curr->icode) == (I_MRMOVQ) || (id_ex_curr->icode) == (I_POPQ)) & ((id_ex_curr->destm) == (id_ex_next->srca) || (id_ex_curr->destm) == (id_ex_next->srcb))) & ((I_RET) == (if_id_curr->icode) || (I_RET) == (id_ex_curr->icode) || (I_RET)== (ex_mem_curr->icode))));
}long long gen_E_stall()
{return 0;
}long long gen_E_bubble()
{return ((((id_ex_curr->icode) == (I_JMP)) & !(ex_mem_next->takebranch))| (((id_ex_curr->icode) == (I_MRMOVQ) || (id_ex_curr->icode) == (I_POPQ)) & ((id_ex_curr->destm) == (id_ex_next->srca) || (id_ex_curr->destm) == (id_ex_next->srcb))));
}long long gen_M_stall()
{return 0;
}long long gen_M_bubble()
{return (((mem_wb_next->status) == (STAT_ADR) || (mem_wb_next->status)== (STAT_INS) || (mem_wb_next->status) == (STAT_HLT)) | ((mem_wb_curr->status) == (STAT_ADR) || (mem_wb_curr->status) == (STAT_INS) || (mem_wb_curr->status) == (STAT_HLT)));
}long long gen_W_stall()
{return ((mem_wb_curr->status) == (STAT_ADR) || (mem_wb_curr->status)== (STAT_INS) || (mem_wb_curr->status) == (STAT_HLT));
}long long gen_W_bubble()
{return 0;
}

改完之后,在pipe目录下:

make clean

make VERSION=full

然后测试:

./psim -t ../y86-code/asumi.yo
cd ../ptest; make SIM=../pipe/psim
cd ../ptest; make SIM=../pipe/psim TFLAGS=-i

发现都过了,那么IIADDQ指令就添加对了。接下来优化 ncopy.ys

优化 ncopy.ys

先从ptest目录回到pipe目录,测试一下基准程序:

cd ../pipe

 ./correctness.pl(测试正确性)

./benchmark.pl(给出得分)

基准程序,CEP=15.18

现在进行一些优化。

仅用第四章知识,CEP=11.55

1. 29行移到33行的位置,去掉原本的第33行。(效果:CPE降1)

2. 使用iaddq指令替换所有的addq指令

3. 把25行跳转改为传送?

        不行

        原因是,原句含义为“如果R[%r10]>0,那么R[%rax]++”。改为“%r11赋值为1,测试%r10,如果≤0,将立即数0传送给%r11,addq %r11,%rax,将r11恢复为立即数1以备下次循环使用”,测试结果是,跳转改为传送,可将CEP降低0.44,但“将r11恢复为立即数1以备下次循环使用”又将CEP提高了1.

4. 第20行,由于跳转策略,所以默认给它Loop(效果:CPE降0.14)

至此,用我们在第四章学到的知识,CEP=11.55,代码如下:

# You can modify this portionxorq %rax,%rax		# count = 0;andq %rdx,%rdx		# len <= 0?jg Loop		        # if so, goto Done:retLoop:	mrmovq (%rdi), %r10	# read val from src...rmmovq %r10, (%rsi)	# ...and store it to dstandq %r10, %r10		# val <= 0?jle NoAdd1iaddq $1, %raxNoAdd1:	iaddq $8, %rdi		# src++iaddq $8, %rsi		# dst++iaddq $-1, %rdx		# length--jg Loop			    # if so, goto Loop:

 

然后用第五章的循环展开方法继续优化。

8x1展开,CPE=9.35
# You can modify this portionxorq %rax,%rax		    # count = 0;andq %rdx, %rdxjg JudgeretJudge:	iaddq $-8, %rdxjge Loop6iaddq $8, %rdxLoop1:mrmovq (%rdi), %r10	    # read val from src...rmmovq %r10, (%rsi)	    # ...and store it to dstandq %r10, %r10		    # val <= 0?jle NoAddiaddq $1, %rax
NoAdd:iaddq $8, %rdiiaddq $8, %rsiiaddq $-1, %rdxjg Loop1		retLoop6:	mrmovq (%rdi), %r10	    # read val from src...rmmovq %r10, (%rsi)	    # ...and store it to dstandq %r10, %r10		    # val <= 0?jle NoAdd1iaddq $1, %rax
NoAdd1:	mrmovq 8(%rdi), %r10	# read val from src...rmmovq %r10, 8(%rsi)	# ...and store it to dstandq %r10, %r10 	    # val <= 0?jle NoAdd2iaddq $1, %rax
NoAdd2:	mrmovq 16(%rdi), %r10	# read val from src...rmmovq %r10, 16(%rsi)	# ...and store it to dstandq %r10, %r10		    # val <= 0?jle NoAdd3iaddq $1, %rax
NoAdd3:	mrmovq 24(%rdi), %r10	# read val from src...rmmovq %r10, 24(%rsi)	# ...and store it to dstandq %r10, %r10		    # val <= 0?jle NoAdd4iaddq $1, %rax
NoAdd4:	mrmovq 32(%rdi), %r10	# read val from src...rmmovq %r10, 32(%rsi)	# ...and store it to dstandq %r10, %r10		    # val <= 0?jle NoAdd5iaddq $1, %rax
NoAdd5:	mrmovq 40(%rdi), %r10	# read val from src...rmmovq %r10, 40(%rsi)	# ...and store it to dstandq %r10, %r10		    # val <= 0?jle NoAdd6iaddq $1, %rax
NoAdd6:	mrmovq 48(%rdi), %r10	# read val from src...rmmovq %r10, 48(%rsi)	# ...and store it to dstandq %r10, %r10		    # val <= 0?jle NoAdd7iaddq $1, %rax
NoAdd7:	mrmovq 56(%rdi), %r10	# read val from src...rmmovq %r10, 56(%rsi)	# ...and store it to dstandq %r10, %r10		    # val <= 0?jle NoAdd8iaddq $1, %rax
NoAdd8:	iaddq $64, %rdiiaddq $64, %rsiandq %rdx, %rdxjg Judge		        

8x1展开+2x1展开+消除气泡,CPE=8.10 
# You can modify this portion#xorq %rax,%rax		# count = 0;andq %rdx, %rdxjg JudgeretUnfold8:	mrmovq (%rdi), %r10	# read val from src...mrmovq 8(%rdi), %r11	# read val from src...mrmovq 16(%rdi), %r12	# read val from src...mrmovq 24(%rdi), %r13	# read val from src...rmmovq %r10, (%rsi)	# ...and store it to dstrmmovq %r11, 8(%rsi)	# ...and store it to dstrmmovq %r12, 16(%rsi)	# ...and store it to dstrmmovq %r13, 24(%rsi)	# ...and store it to dstandq %r10, %r10		# val <= 0?jle NoAdd1iaddq $1, %rax
NoAdd1:	andq %r11, %r11 	# val <= 0?jle NoAdd2iaddq $1, %rax
NoAdd2:	andq %r12, %r12		# val <= 0?jle NoAdd3iaddq $1, %rax
NoAdd3:	andq %r13, %r13		# val <= 0?jle NoAdd4iaddq $1, %rax
NoAdd4:	mrmovq 32(%rdi), %r10	# read val from src...mrmovq 40(%rdi), %r11	# read val from src...mrmovq 48(%rdi), %r12	# read val from src...mrmovq 56(%rdi), %r13	# read val from src...rmmovq %r10, 32(%rsi)	# ...and store it to dstrmmovq %r11, 40(%rsi)	# ...and store it to dstrmmovq %r12, 48(%rsi)	# ...and store it to dstrmmovq %r13, 56(%rsi)	# ...and store it to dstandq %r10, %r10		# val <= 0?jle NoAdd5iaddq $1, %rax
NoAdd5:	andq %r11, %r11 	# val <= 0?jle NoAdd6iaddq $1, %rax
NoAdd6:	andq %r12, %r12		# val <= 0?jle NoAdd7iaddq $1, %rax
NoAdd7:	andq %r13, %r13 	# val <= 0?jle NoAdd8iaddq $1, %rax
NoAdd8:	iaddq $64, %rdiiaddq $64, %rsiandq %rdx, %rdxjg JudgeretJudge:	iaddq $-8, %rdxjge Unfold8iaddq $8, %rdx
Judge2:iaddq $-2, %rdxjge Unfold2iaddq $2, %rdxSingleLoop:mrmovq (%rdi), %r10	# read val from src...rmmovq %r10, (%rsi)	# ...and store it to dstandq %r10, %r10		# val <= 0?jle Doneiaddq $1, %raxretUnfold2:mrmovq (%rdi), %r10	# read val from src...mrmovq 8(%rdi), %r11	# read val from src...rmmovq %r10, (%rsi)	# ...and store it to dstrmmovq %r11, 8(%rsi)	# ...and store it to dstandq %r10, %r10		# val <= 0?jle Noadd1iaddq $1, %rax
Noadd1:	andq %r11, %r11 	# val <= 0?jle Noadd2iaddq $1, %raxNoadd2:	iaddq $16, %rdiiaddq $16, %rsiandq %rdx, %rdxjg Judge2

参考

CSAPP | Lab4-Architecture Lab 深入解析 - 知乎 (zhihu.com)

[读书笔记]CSAPP:ArchLab - 知乎 (zhihu.com)

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

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

相关文章

算法每日一题: 使用循环数组所有元素相等的最少秒数 | 哈希

大家好&#xff0c;我是星恒&#xff0c;今天给大家带来的是一道需要感觉规律的题目&#xff0c;只要读懂题目中的规律&#xff0c;就可以做出来了 这道题用到了哈希&#xff0c;还有一个关键点比较类似循环队列 题目&#xff1a;leetcode 2808 给你一个下标从 0 开始长度为 n…

Postman发送带登录信息的请求

环境&#xff1a;win10Postman10.17.7 假设有个请求是这样的&#xff1a; RequiresPermissions("tool:add") PostMapping(value"/predict") ResponseBody /** * xxx * param seqOrderJson json格式的参数 * return */ public String predictSampleIds(Req…

svg基础(三)分组、渐变

上一篇文章简单介绍了svg常用标签及其属性,本篇主要介绍分组&#xff0c;渐变 1 分组<g> 分组容器 添加到g元素上的变换会应用到其所有的子元素上添加到g元素的属性会被其所有的子元素继承定义复杂对象&#xff0c;可通过<use>元素引用 1.1 分组 <svg>&…

EasyExcel分页上传数据

EasyExcel分页上传数据 一、实例 controller上传入口 PostMapping("/upload")ResponseBodyLog(title "导入工单", businessType BusinessType.IMPORT)public AjaxResult uploadFile(HttpServletRequest request, MultipartFile files) throws Exceptio…

Node.js+Express+Mysql服务添加环境变量

1、使用dotenv插件 1&#xff09;安装插件&#xff1a;npm install dotenv-cli --save-dev 2&#xff09;在项目根目录下添加对应的 .env 配置文件&#xff1b; // .env配置文件内容 MODEdevelopment, BASE_URLhttp://127.0.0.1:80813) 在启动命令中设置对应的加载文件&#…

springboot159基于springboot框架开发的景区民宿预约系统的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

STM32内部Flash

目录 一、内部Flash简介 二、内部Flash构成 1. 主存储器 2. 系统存储区 3. 选项字节 三、内部Flash写入过程 1. 解锁 2. 页擦除 3. 写入数据 四、工程空间分布 某工程的ROM存储器分布映像&#xff1a; 1. 程序ROM的加载与执行空间 2. ROM空间分布表 一、内部Flash…

2024.3.28-29日ICVS-AI智能汽车产业峰会(杭州)

本次安策将携手泰雷兹一起&#xff0c;参展ICVS2024第四届AI智能汽车产业峰会(杭州)&#xff0c;2024年3月28日-29日&#xff0c;欢迎新老朋友参加和莅临27号展台交流。 随着自动驾驶汽车政策密集落地。从我国四部门联合发布《关于开展智能网联汽车准入和上路通行试点工作的通知…

【头歌·计组·自己动手画CPU】一、计算机数据表示(讲解版) 【计算机硬件系统设计】

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

五、Redis之发布订阅及事务管理

5.1 发布订阅 5.1.1 Redis 发布订阅 (pub/sub) 是一种消息通信模式&#xff1a;发送者 (pub) 发送消息&#xff0c;订阅者 (sub) 接收消息。Redis 客户端可以订阅任意数量的频道。下图展示了频道 channel1 &#xff0c;以及订阅这个频道的三个客户端 —— client1 、client2 …

Spring核心基础:全面总结Spring中提供的那些基础工具类!

内容概要 Spring Framework 提供了众多实用的工具类&#xff0c;这些工具类在简化开发流程、提升代码质量和维护性方面发挥了重要作用&#xff0c;以下是部分关键工具类的总结及其使用场景&#xff1a; StringUtils&#xff1a;不仅提供了基础的字符串操作&#xff0c;如拼接…

转融通业务是什么?好处和弊端是什么?

转融通业务是指证券金融公司借入证券、筹得资金后&#xff0c;再转借给证券公司&#xff0c;为证券公司开展融资融券业务提供资金和证券来源&#xff0c;包括转融券业务和转融资业务两部分。从证券金融公司角度看&#xff0c;向证券公司提供资金和证券供其开展融资融券业务&…

Redis中的缓存穿透、雪崩、击穿的原因以及解决方案(详解)

一、概述 ① 缓存穿透&#xff1a;大量请求根本不存在的key&#xff08;下文详解&#xff09; ② 缓存雪崩&#xff1a;redis中大量key集体过期&#xff08;下文详解&#xff09; ③ 缓存击穿&#xff1a;redis中一个热点key过期&#xff08;大量用户访问该热点key&#xff0c;…

Unity类银河恶魔城学习记录3-2 Entity源代码 P48

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Entity.cs using System.Collections; using System.Collections.Generic;…

【学习笔记】树上差分总结(点差分/边差分)

一.树上差分的基本概念 1.树上差分的定义 树上差分&#xff0c;顾名思义&#xff0c;意思就是在树上做差分。 至于什么是差分呢&#xff1f;如果不会的同学&#xff0c;可以先看看我的这篇博客:一维,二维差分の详解&#xff08;简单易懂&#xff09;_一维差分-CSDN博客 2.树…

SpringBoot中使用Spring自带线程池ThreadPoolTaskExecutor与Java8CompletableFuture实现异步任务示例

场景 关于线程池的使用&#xff1a; Java中ExecutorService线程池的使用(Runnable和Callable多线程实现)&#xff1a; Java中ExecutorService线程池的使用(Runnable和Callable多线程实现)_executorservice executorservice executors.newfix-CSDN博客 Java中创建线程的方式…

React+echarts实现排名+自动滚动+X轴自定义titleTop

1、效果 2、环境准备 1、react18 2、antd 4 3、代码实现 原理&#xff1a;自动滚动通过创建定时器动态更新echar的dataZoom属性startValue、endValue&#xff0c;自定义tooltip通过监听echar的鼠标移入移出事件&#xff0c;判断tooltTip元素的显隐以及位置。 /*** 收集完成…

【Java EE】----Spring框架创建和使用

1.Spring框架创建 创建一个maven项目 添加Spring框架支持 <dependencies> 上下文<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.3.RELEASE</version></depende…

【网站项目】038汽车养护管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

PS之外的平面设计利器:7款高效软件帮你轻松搞定

平面图设计的痕迹体现在日常生活的方方面面&#xff0c;如路边传单、杂志、产品包装袋或手机开屏海报等&#xff0c;平面设计软件层出不穷。Photoshop是大多数平面图设计初学者的入门软件&#xff0c;但随着设计师需求的不断提高&#xff0c;平面图设计软件Photoshop逐渐显示出…