流水账(CPU设计实战)——lab3

Lab3 Rewrite V1.0

版本控制

版本描述
V0
V1.0相对V0变化: 修改了文件名,各阶段以_stage结尾(因为if是关键词,所以module名不能叫if,遂改为if_stage,为了统一命名,将所有module后缀加上_stage) 删除了imm_sign信号(默认对立即数进行有符号数扩展) 由于对sw指令进行了重新理解:无论如何都是需要将rt_data传递给EXE阶段,故将部分译码逻辑进行后移至EXE阶段,避免id_to_exe_data总线过于庞大 将ins_shmat剔除出id_to_exe_data,因为imm包括ins_shamt 对信号进行重命名(例如在ID阶段有个信号叫rf_we,最终要传递给WB阶段,那么在EXE阶段,该信号叫作exe_rf_we,同理mem_rf_we,wb_rf_we),不然都叫rf_we,Debug的时候太痛苦了。

Top顶层

接口信号

MYCPU_TOP.v(TOP

名称宽度方向描述
时钟与复位
clk1I时钟信号,来自clk_pll的输出时钟
resetn1I复位信号,低电平同步复位
取指端访存接口
inst_sram_en1O指令RAM使能信号,高电平有效
inst_sram_wen4O指令RAM字节写使能信号,高电平有效
inst_sram_addr32O指令RMA读写地址,字节寻址
inst_sram_wdata32O指令RAM写数据
inst_sram_rdata32I指令RAM读数据
数据端访存接口
data_sram_en1O数据RAM使能信号,高电平有效
data_sram_wen4O数据RAM字节写使能信号,高电平有效
data_sram_addr32O数据RAM读写地址,字节寻址
data_sram_wdata32O数据RAM写数据
data_sram_rdata32I数据RAM读数据
debug信号,供验证平台使用
debug_wb_pc32O写回级(多周期最后一级)的PC,需要myCPU里将PC一路传递到写回级
debug_wb_rf_wen4O写回级写寄存器堆(regfiles)的写使能,为字节使能,如果myCPU写regfiles为单字节写使能,则将写使能扩展成4位即可
debug_wb_rf_wnum5O写回级写regfiles的目的寄存器号
debug_wb_rf_wdata32O写回级写regfiles的写数据

接口时序

略(MIPS经典五级流水线)

代码结构

MYCPU_TOP.v

|____IF.v

|____ID.v

|____RF.v(2个读端口,1个写端口)

|____EXE.v

|____ALU.v

|____MEM.v

|____WB.v

|____MYCPU.h

DATA_RAM.v

IF.v(修改为IF_STAGE,因为会与关键词if冲突)

接口信号

名称宽度方向描述
时钟与复位
clk1I时钟信号,来自clk_pll的输出时钟
resetn1I复位信号,低电平同步复位
与TOP
inst_sram_en1ORAM使能信号,高电平有效
inst_sram_wen4ORAM字节写使能信号,高电平有效
inst_sram_addr32ORMA读写地址,字节寻址
inst_sram_wdata32ORAM写数据
inst_sram_rdata32IRAM读数据
与ID
id_to_if_allowin1Ipipe allowin
if_to_id_vld1Opipe valid
if_to_id_data64Opipe data(instruction 32-bits, pc 32-bits)
jump_bus33Ibranch instructions(enable 1bit,address 32-bits)

接口时序

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

ID.v

接口信号

名称宽度方向描述
时钟与复位
clk1I时钟信号,来自clk_pll的输出时钟
resetn1I复位信号,低电平同步复位
与IF
id_to_if_allowin1Opipe allowin
if_to_id_vld1Ipipe valid
if_to_id_data64Ipipe data(instruction 32-bits, pc 32-bits)
jump_bus33Obranch instructions(enable 1bit,address 32-bits)
与EXE
exe_to_id_allowin1Ipipe allowin
id_to_exe_vld1Opipe valid
id_to_exe_data135O{ins_R:1, ins_I:1, imm:16, alu_op:13, mem_rd:1, mem_we:1, rf_we:1, rf_dst_addr:5, data_1:32, data_2:32, pc:32}
与WB
wb_to_rf_bus38I{rf_we:1, rf_addr:5, rf_data:32}

接口信号(RF.v)

名称宽度方向描述
时钟与复位
clk1I时钟信号,来自clk_pll的输出时钟
与ID内部信号
rf_r_addr15IRF读地址1
rf_r_data132ORF读数据1
rf_r_addr25IRF读地址2
rf_r_data232ORF读数据2
rf_wen11IRF写使能1
rf_w_addr15IRF写地址1
rf_w_data132ORF写数据1

接口时序

在这里插入图片描述

电路设计

在这里插入图片描述

图3-4-1 译码电路分组(注:黄线少画了两条)

根据附录——MIPS指令。由于跳转指令不传递给EXE阶段,直接传递给IF阶段,且为纯组合逻辑输出,有可能成为关键路径,故对跳转指令单独处理。除了跳转指令外,涉及加法(减法归为加法)的指令如图3-4-1所示,即ins_addu、ins_addiu、ins_subu、ins_lw、ins_sw。

对于图3-4-1的拼接运算,可以当作移位运算执行。

EXE.v

接口信号

名称宽度方向描述
时钟与复位
clk1I时钟信号,来自clk_pll的输出时钟
resetn1I复位信号,低电平同步复位
与TOP(外接的DATA_RAM)
data_sram_en1O数据RAM使能信号,高电平有效
data_sram_wen4O数据RAM字节写使能信号,高电平有效(4个比特,应该代表32 = 4 bytes)
data_sram_addr32O数据RAM读写地址,字节寻址
data_sram_wdata32O数据RAM写数据
与ID
exe_to_id_allowin1Opipe allowin
id_to_exe_vld1Ipipe valid
id_to_exe_data135I{ins_R:1, ins_I:1, imm:16, alu_op:13, mem_rd:1, mem_we:1, rf_we:1, rf_dst_addr:5, data_1:32, data_2:32, pc:32}
与MEM
mem_to_id_allowin1Ipipe allowin
exe_to_mem_vld1Opipe valid
exe_to_mem_data71O{mem_rd:1, rf_we:1, rf_dst_addr:5, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc), exe_result:32

接口信号(ALU.v)

暂时不需要时钟和复位,纯组合逻辑

名称宽度方向描述
时钟与复位
clk1I时钟信号,来自clk_pll的输出时钟
resetn1I复位信号,低电平同步复位
与ID内部信号
alu_shamt6IALU移位(R-指令的shamt部分)
alu_op13IALU操作(加、减、乘除、位运算)
alu_din132IALU输入1
alu_din232IALU输入2
alu_out32OALU输出

接口时序

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

MEM.v

接口信号

名称宽度方向描述
时钟与复位
clk1I时钟信号,来自clk_pll的输出时钟
resetn1I复位信号,低电平同步复位
与TOP(外接的DATA_RAM)
data_sram_rdata32I数据RAM读数据
与EXE
mem_to_exe_allowin1Opipe allowin
exe_to_mem_vld1Ipipe valid
exe_to_mem_data71I{mem_rd:1, rf_we:1, rf_dst_addr:5, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc), exe_result:32}
与WB
wb_to_mem_allowin1Ipipe allowin
mem_to_wb_vld1Opipe valid
mem_to_wb_data70O{ rf_we:1, rf_dst_addr:5, mem_result:32, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc)}

WB.v

接口信号

名称宽度方向描述
时钟与复位
clk1I时钟信号,来自clk_pll的输出时钟
resetn1I复位信号,低电平同步复位
与TOP
debug_wb_pc32O写回级(多周期最后一级)的PC,需要myCPU里将PC一路传递到写回级(与原书保持一致)
debug_wb_rf_wen4O写回级写寄存器堆(regfiles)的写使能,为字节使能,如果myCPU写regfiles为单字节写使能,则将写使能扩展成4位即可(与原书保持一致)
debug_wb_rf_wnum5O写回级写regfiles的目的寄存器号(与原书保持一致)
debug_wb_rf_wdata32O写回级写regfiles的写数据(与原书保持一致)
与MEM
wb_to_mem_allowin1Opipe allowin
mem_to_wb_vld1Ipipe valid
mem_to_wb_data70I{ rf_we:1, rf_dst_addr:5, mem_result:32, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc)}
与ID
wb_to_rf_bus38O{rf_we:1, rf_addr:5, rf_data:32}

接口时序

在这里插入图片描述

附录——参考

  1. 参考:处理机流水线------经典五段流水线-CSDN博客

附录——原书指令

指令sel_nextpcinst_ram_weninst_ram_wensel_alu_src1sel_alu_src2alu_opdata_ram_endata_ram_wenrf_wesel_rf_dstsel_rf_res
ADDU0001100010010000000000010010010
ADDIU0001100010100000000000010010100
SUBU0001100010010000000000100010010
LW0001100010100000000000011010101
SW0001100010100000000000011100000
BEQ0010100000000000000000000000000
BNE0010100000000000000000000000000
JAL0100100101000000000000010011000
JR1000100000000000000000000000000
SLT0001100010010000000001000010010
SLTU0001100010010000000010000010010
SLL0001101000010001000000000010010
SRL0001101000010010000000000010010
SRA0001101000010100000000000010010
LUI0001100000101000000000000010100
AND0001100010010000000100000010010
OR0001100010010000010000000010010
XOR0001100010010000100000000010010
NOR0001100010010000001000000010010

附录——Debug

PC复位问题

在这里插入图片描述

PC的跳转有误,直接看IF_STAGE.v

修改代码为:

在这里插入图片描述

RegFile的零寄存器问题

在这里插入图片描述

修改如下:

在这里插入图片描述

RF数据高阻

在这里插入图片描述

发现数据有错,应当为63:32

在这里插入图片描述

跳转指令的PC值

跳转指令的PC,本人使用的都是ID阶段的pc,经过vivado调试,发现有误,隧改为如下,即使用IF阶段的pc:

在这里插入图片描述

lui译码错误

在ID阶段,lui指令译码错误,具体如下:

assign ins_lui = op_ext[6’h15] & rs_ext[5’h00];//错误

改为如下:

assign ins_lui = op_ext[6’h0f] & rs_ext[5’h00];

addiu执行错误

经排查,发现在ID阶段,忘了声明rs_data和rt_data这两个变量,导致被默认为1 bit(实际都是32 bit的变量)

addiu执行错误

(影响Debug了)

经排查,发现rs数据读取为高阻,向前追溯,发现是写寄存器的时候,写入的是高阻,最终发现在WB阶段的,rf_we始终为高,更改如下:

assign rf_we = wb_data[69] ;

assign debug_wb_rf_wen = {4{rf_we}} ;

assign wb_to_rf_bus[37] = rf_we & wb_vld;

改为:

assign rf_we = wb_data[69] & wb_vld;

assign debug_wb_rf_wen = {4{rf_we}} ;

assign wb_to_rf_bus[37] = rf_we ;

然而还是有错,遂向前回溯,发现RF.v中的rf_group声明有误:

reg [31:0] rf_group [4:0];

改为:

reg [31:0] rf_group [31:0];

lw错误

发现电路设计本身就有问题,原因为:从CSDN上的一个MIPS指令集设计的电路,但是该CSDN上的内容是错的!!!

电路设计错误:发现rf_we漏掉了ins_lw

在这里插入图片描述

更改如下:

assign rf_we = ins_addu

|ins_addiu

|ins_subu

|ins_lw

|ins_jal

|ins_slt xxxxxx ;

subu错误

在这里插入图片描述

assign alu_din2_two_cmpl[31] = 1’b1;

assign alu_din2_two_cmpl[30:0] = (~alu_din2) + 1’b1;

上面两句,修改为下:

assign alu_din2_two_cmpl[31:0] = (~alu_din2) + 1’b1;

在MIPS指令中有subu和sub两种指令,(lab3只要求实现subu,不要求实现sub指令)而在代码中本人将subu简写为sub是不合适的,已全部修改为subu

slt报错

在这里插入图片描述

原始代码:

assign result_slt = ($signed(alu_din1) < $signed(alu_din2)) ? 32’h1: 32’h0;

学习了下原书上的源码,发现可以将比较运算合并至减法运算,于是修改了slt(同时也修改了sltu)如下:

assign add_din2 = (alu_subu | alu_slt | alu_sltu) ? alu_din2_two_cmpl
alu_din2;

另外,我发现单独进行求补码运算,可能会浪费加法器,不利于vivado优化,遂修改

在这里插入图片描述

修改为:

在这里插入图片描述

nor报错

assign result_nor = ~result_xor ;

更改为:

assign result_nor = ~ result_or ;

srl报错

在这里插入图片描述

发现ID阶段的译码错误:

assign ins_srl = op_ext[6’h00] & sa_ext[5’h00] & fun_ext[6’h06];

更改为:

assign ins_srl = op_ext[6’h00] & rs_ext[5’h00] & fun_ext[6’h02];

sra报错

在这里插入图片描述

assign result_sra = alu_din2 >>> alu_shamt ;

更改为:

assign result_sra = $signed(alu_din2) >>> alu_shamt ;

sw/lw报错

lw报错,经排查是因为sw命令有误

本人设计的时候没有认真分析sw指令,导致EXE阶段的sram_wdata数据有误。

具体地讲,由于本人设计阶段欠缺,误认为加法结果给到sram_wdata(实际上加法结果是给sram_addr),导致出错。

由于欠思考导致总线也需要更改,需要将rt_data从ID阶段传递给exe阶段,因为sw指令执行中需要将rt_data赋给sram_wdata。

bne出错

在这里插入图片描述

又是码错了

assign jump_bne = (rt_equ_rs == 1’b0) & ins_beq ;

更改为:

assign jump_bne = (rt_equ_rs == 1’b0) & ins_bne ;

完结

还有一些小bug没有记录,终于pass了,完结。

在这里插入图片描述

后记

  1. 原书是将regfile.v当作ID_stage的一个子模块,WB_stage写回时,也是通过ID_stage的顶层将信号传递到regfile模块。本设计将regfile.v置于与ID、WB的同一hierarchy

  2. 原书将跳转指令(如JAL)的译码放在ID_stage模块中(没有问题,因为译码就是在ID_stage阶段),并以组合逻辑的形式传递给IF_stage(必须用组合逻辑,否则会影响流水)。本设计将跳转指令放在IF模块中,避免组合逻辑穿越模块边界。(还是不要合并,因为R、I、J型指令均含有跳转指令,合并至IF模块,会增加大量的额外译码逻辑。)

  3. 原书的译码方式值得学习:

    在这里插入图片描述

    在这里插入图片描述

    若是按我之前的写法,大概率会写成如下形式:

    always@(*)begin

    case(xxxx)

    endcase

    end

    always-case的形式容易写错,而且不够清晰。使用原书的写法,避免写成:

    inst_addu = (op == 6’h0 ) & (func == 6’h21) & (sa == 5’h00);

  • 小括号太多,看着就乱
  • 等号也影响纠错
  • 原书将0写成00,格式上是对齐的,更舒服
  • 另外我猜测将判断逻辑写成generate—endgenerate的形式,也更容易让编译器进行优化
  1. 在自己设计译码的时候,本人遇到一个问题,译码到什么程度才算“译码”。是译码出R\I\J型指令(每种类型用1bit标志位表示),还是译码至具体的加减乘除?

    我的思想:EXE除了负责寄存一些必要数据外(比如WB需要的数据),其核心执行内容应当只有:加、减、乘、除、移位、与、或、非、异或。也就是说,ID阶段负责输入的数据给准备好级EXE。然后我就在想Regfile怎么搞,因为Regfile读是不需要周期的(即本周期给出地址,本周就可以得到数据),但是WB写Regfile的时候,如果同时读Regfile的同一地址,怎么办呢?这个读写冲突应当放在Regfile中处理吗?

    另一方面,EXE的执行时,输入可以是寄存器(比如and指令),也可以是pc(比如跳转指令)。当输入是寄存器时,需要读Regfile,当输入是pc时,不需要读Regfile,将Regfile置于与ID、EXE同一hierarchy,意味着需要在EXE阶段判断输入是pc还是来自Regfile,这样增加了复杂性。(我现在理解了原书为什么要把Regfile当作ID的子模块,还是有道理的)

  2. 原lab3中的ID_stage.v中的ds_to_es_bus是136bits,但是在EXE阶段还存在少量的译码,我认为译码这种东西应当在ID阶段全部完成,不应当在EXE阶段还进行译码。

  3. 译码逻辑我写的是:assign {ins_op, ins_rs, ins_rt, ins_rd, ins_sa, ins_fun} = ins;

    原书代码给的是:

    assign ins_op = ins[31:26];

    assign ins_rs = ins[25:21];

    assign ins_rt = ins[20:16];

    assign ins_rd = ins[15:11];

    assign ins_sa = ins[10:6] ;

    assign ins_fun = ins[5:0] ;

    assign ins_index = ins[25:0] ;

    assign ins_imm = ins[15:0] ;

感觉还是书上写的比较易读,隧写成书上的这种形式

  1. 实例化,我写的是:

decoder_6_64 U_decoder_6_64(

.din ( ins ),

.dout( ins_ext )

);

原书上写的是:

decoder_6_64 U_decoder_6_64(.din ( ins ),.dout( ins_ext ) );

感觉还是差不多,我还是按我自己的写

  1. 在译码过程中对于5bits转32bits,和6bits转64bits。本人可以理解opcode和function需要转换成64bits、32bits,但是不明白rs、rt、rd、sa为何还需要转换。我现在是怀疑,后续指令会扩展,然后译码的时候将rt、rd、sa也加进去,可以确保指令译码的唯一性。

  2. 我原本想将ID阶段中的译码中的rf_dst_addr按下图进行Coding:

    在这里插入图片描述

    但是看了原书的代码后,认为,没默认ins_R选项即可,只需要判断其他写寄存器地址,遂改为如下:

    assign rf_dst_addr = ins_jal ? 5’d31 : ins_I ? ins_rt : ins_rd ;

同理,也对data_2的生成进行了类似的修改。

  1. 原书源码中每个阶段的pc值叫作fs_pc、ds_pc等,而我写的代码中都叫作pc,导致使用vivado调试时,都叫作pc不好定位
  2. 在跑通了全程后(共两周,包括Debug两天),感觉自己的Coding水平还是不如原书,而且控制信号和数据通路结构层次不好,级与级之间的bus编码(信号的放置位置等)也不够完美,数据的命名相同不利于debug(比如都叫pc,分不清是if的pc,还是exe的pc)。数据的耦合严重,尤其是ID与EXE阶段,两个阶段的信号耦合过于严重。除此之外还有资源上的复用也有所欠缺。还有一点就是出现了许多Coding的问题,比如wire信号忘记声明就使用,bne却使用了beq的信号。最后一点就是9.14节的sw/lw报错问题,这个bug,本人解决了一个晚上加一个上午,因为在设计阶段,是按照CSDN上的一篇博客上给出的MIPS指令设计的,所以一直没意识到博客本身就有问题,这种先入为主的指令加上本人设计的代码结构在sw/lw指令上耦合严重,导致后来阅读龙芯给的PDF时也没意识的问题,最后阅读了lab3原书上的源码才发现问题。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

设计模式 22 访问者模式 Visitor Pattern

设计模式 22 访问者模式 Visitor Pattern 1.定义 访问者模式是一种行为型设计模式&#xff0c;它允许你在不改变已有类结构的情况下&#xff0c;为一组对象添加新的操作。它将算法与对象结构分离&#xff0c;使你能够在不修改现有类的情况下&#xff0c;为这些类添加新的操作。…

Autosar Dcm配置-特定NRC实现方式-基于ETAS软件

文章目录 前言工具配置代码编写总结 前言 项目开发过程中&#xff0c;诊断服务一般客户需求或系统需求都会有特定NRC(一般为NRC22-条件不满足)&#xff0c;也就会有特定的条件&#xff0c;需要手动加代码实现。本文介绍ETAS工具中配置的接口及简单实现。 工具配置 对于每一个…

【高阶数据结构】 B树 -- 详解

一、常见的搜索结构 适合做内查找&#xff1a; 以上结构适合用于数据量相对不是很大&#xff0c;能够一次性存放在内存中&#xff0c;进行数据查找的场景。如果数据量很大&#xff0c;比如有 100G 数据&#xff0c;无法一次放进内存中&#xff0c;那就只能放在磁盘上了。 如果…

坦克飞机大战项目详解:从包结构到测试发布

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、项目初始化与包结构构建 代码案例&#xff1a; 二、资源文件与配置文件管理 代码案例…

关于NLTK

一、NLTK简介 下图来自NLTK官网&#xff1a;https://www.nltk.org/index.html NLTK&#xff0c;全称为Natural Language Toolkit&#xff0c;是一个用于处理和分析自然语言文本的Python库。它提供了一系列丰富的工具和资源&#xff0c;包括词汇资源&#xff08;如WordNet&am…

【接口自动化_05课_Pytest接口自动化简单封装与Logging应用】

一、关键字驱动--设计框架的常用的思路 封装的作用&#xff1a;在编程中&#xff0c;封装一个方法&#xff08;函数&#xff09;主要有以下几个作用&#xff1a;1. **代码重用**&#xff1a;通过封装重复使用的代码到一个方法中&#xff0c;你可以在多个地方调用这个方法而不是…

【进程空间】通过页表寻址的过程

文章目录 前言介绍页表、页框、页目录的概念页框页表页目录页表和页目录的分配 一级页表和二级页表一级页表寻址过程 二级页表寻址过程 一级页表和二级页表的对比 前言 我们知道每个进程都有属于自己的虚拟地址空间&#xff0c;且每个进程的虚拟地址都是统一的。要想通过虚拟地…

JS逆向之企名科技

文章目录 初步分析定位js编写完整代码参考文献初步分析 目标网址:企名科技 抓包分析,发现是post请求 请求代码如下: #!/usr/bin/env python3 # -*- coding: utf-8 -*- import requestsheaders = {Connection:

【主流分布式算法总结】

文章目录 分布式常见的问题常见的分布式算法Raft算法概念Raft的实现 ZAB算法Paxos算法 分布式常见的问题 分布式场景下困扰我们的3个核心问题&#xff08;CAP&#xff09;&#xff1a;一致性、可用性、分区容错性。 1、一致性&#xff08;Consistency&#xff09;&#xff1a;…

玄机平台应急响应—webshell查杀

1、前言 这篇文章说一下应急响应的内容&#xff0c;webshell查杀呢是应急响应的一部分。那么什么是应急响应呢&#xff0c;所谓的应急响应指的是&#xff0c;当网站突然出现异常情况或者漏洞时&#xff0c;能够马上根据实际问题进行分析&#xff0c;然后及时解决问题。 2、应…

内网安全-隧道搭建穿透上线内网穿透-nps自定义上线内网渗透-Linux上线-cs上线Linux主机

目录 内网安全-隧道搭建&穿透上线内网穿透-nps-自定义-上线NPS工具介绍搭建过程 nps原理介绍MSF上线CS上线 内网渗透-Linux上线-cs上线Linux主机1.下载插件2.导入插件模块3.配置监听器4.服务端配置5.配置C2监听器并生成木马6.执行木马 内网安全-隧道搭建&穿透上线 内网…

做抖店如何避免被同行内卷?这5点建议,可以解决这个问题

我是王路飞。 都说2024年的抖店不赚钱了&#xff0c;商家太多了&#xff0c;太内卷了&#xff0c;一点都不好做~ 那为什么依然有很多商家在坚持做呢&#xff1f;为什么依然有很多新手入局呢&#xff1f; 无非是抖店确实能带来可观的利润回报罢了。 那如何避免被同行内卷呢&…

idea中git检出失败

之前clone好好的&#xff0c;今天突然就拉取不下来了。很多时候是用户凭证的信息没更新的问题。由于window对同一个地址都存储了会话。如果是新的会话&#xff0c;必须要更新window下的凭证。 然后根据你的仓库找到你对应的账户&#xff0c;更新信息即可。

【前端】从手动部署到自动部署:前端项目进化之路

从手动部署到自动部署&#xff1a;前端项目进化之路 在前端开发的领域内&#xff0c;部署是一个不可忽视的环节。随着项目复杂度的增加和线上更新频率的提升&#xff0c;手动部署逐渐暴露出它的弊端。本文将带你从手动部署过渡到自动部署&#xff0c;完成前端项目进化的重要一…

Round-Robin 调度逻辑算法

Round-Robin 调度逻辑算法 1 Intro1.1 固定优先级1.2 Round-Robin算法 之前上学还是工作&#xff0c;都接触过调度算法&#xff1a;Round-Robin和weight-Round Robin算法&#xff0c;但只知道它的功能和目的是什么&#xff0c;没有具体了解如何实现的&#xff1b; 现在是工作上…

移动云服务器选购指南(图文教程详解)

目录 一、前言 二、基本概念 2.1 定义 2.2 部署形式 2.3 用处 三、主流平台 四、主流产品推荐 4.1 云电脑 4.2 云主机ECS 4.3 弹性公网 IP 五、选购指南 5.1 明确场景 5.2 明确需求 5.3 明确身份 新用户 老用户 5.4 明确时间 5.5 明确教程 六、总结 一、前言…

【多态】(超级详细!)

【多态】&#xff08;超级详细&#xff01;&#xff09; 前言一、 多态的概念二、重写1. 方法重写的规则2. 重写和重载的区别 三、多态实现的条件四、 向上转型五、动态绑定 前言 面向对象的三大特征&#xff1a;封装性、继承性、多态性。 extends继承或者implements实现&…

短视频商城全套源码:开启电商新纪元

随着数字媒体的快速发展&#xff0c;短视频平台已经成为人们获取信息、娱乐和社交的重要渠道。在这样一个大背景下&#xff0c;短视频商城的兴起&#xff0c;无疑为电商行业带来了新的机遇和挑战。本文将探讨短视频商城全套源码的重要性&#xff0c;以及它如何助力商家和开发者…

详解Spring MVC

目录 1.什么是Spring Web MVC MVC定义 2.学习Spring MVC 建立连接 RequestMapping 注解介绍及使用 获取单个参数 获取多个参数 获取普通对象 获取JSON对象 获取基础URL参数 获取上传文件 获取Header 获取Cookie 获取Session 总结 1.什么是Spring Web MVC 官⽅对于…

生成式AI模型大PK——GPT-4、Claude 2.1和Claude 3.0 Opus

RAG(检索增强生成)系统的新评估似乎每天都在发布&#xff0c;其中许多都集中在有关框架的检索阶段。然而&#xff0c;生成方面——模型如何合成和表达这些检索到的信息&#xff0c;在实践中可能具有同等甚至更大的意义。许多实际应用中的案例证明&#xff0c;系统不仅仅要求从上…