自己动手写CPU_step6_算术运算指令

news2024/11/14 14:37:37

接上篇,本篇开始实现算数运算指令,包括加减乘除,加减比较好实现,乘除则需要考虑指令周期与其他指令的周期长度不一致问题,可能会导致流水线效率下降,本篇先实现简单的算术运算。


指令定义

`define EXE_ADD         6'b100000   //  rs + rt -> rd(检查溢出)
`define EXE_ADDU        6'b100001   //  rs + rt -> rd(不检查溢出)
`define EXE_SUB         6'b100010   //  rs - rt -> rd
`define EXE_SUBU        6'b100011   //  rs - rt -> rd
`define EXE_SLT         6'b101010   //  (rs < rt) -> rd(比较结果为1/0)
`define EXE_SLTU        6'b101011   //  (rs < rt) -> rd(1/0)
`define EXE_CLZ         6'b100000   //  clz(rs) -> rd(从最高位开始直到遇到1,之前所有0的个数保存至rd)
`define EXE_CLO         6'b100001   //  clo(rs) -> rd(从最高位开始直到遇到0,之前所有1的个数保存至rd)
`define EXE_MUL         6'b000010   //  rs × rt -> rd(保存结果低32位)
`define EXE_MULT        6'b011000   //  rs × rt -> {HI,LO}
`define EXE_MULTU       6'b011001   //  rs × rt -> {HI,LO} 无符号

`define EXE_ADDI        6'b001000   //立即数加法             rs add imm -> rt
`define EXE_ADDIU       6'b001001   //无符号立即数加法       rs add imm -> rt
`define EXE_SLTI        6'b001010   //立即数比较指令         (rs < imm) -> rt(1/0)
`define EXE_SLTIU       6'b001011   //无符号立即数比较       (rs < imm) -> rt(1/0)

上面的是R型指令,下面的是I型指令

简单的算术运算指令和之前篇的额添加指令其实是一样的,只需要修改EX模块和ID模块即可。


ID模块

`include "defines.v"
//译码阶段  对if_id传入的指令进行译码,分离出操作数和操作码
module id(
    input                           rst,
    input [`InstAddrBus]            pc,
    input [`InstDataBus]            inst,
    //读通用寄存器        读取        
    input [`RegDataBus]             reg1_data,
    input [`RegDataBus]             reg2_data,
    output reg                      reg1_rden,
    output reg                      reg2_rden,
    output reg [`RegAddrBus]        reg1_addr,  //源操作数1的地址
    output reg [`RegAddrBus]        reg2_addr,  //源操作数2的地址
    //送到ex阶段的值
    output reg [`RegDataBus]        reg1,       //源操作数1 32b
    output reg [`RegDataBus]        reg2,       //源操作数2 32b
    output reg                      reg_wb,     //写回目的寄存器标志    
    output reg [`RegAddrBus]        reg_wb_addr,//写回目的寄存器地址
    output reg [`AluOpBus]          aluop,      //操作码    
    //相邻指令的冲突,由EX阶段给出数据旁路
    input                           ex_wr_en,   //处于执行阶段的指令是否要写目的寄存器 
    input [`RegDataBus]             ex_wr_data, 
    input [`RegAddrBus]             ex_wr_addr,  
    //相隔一条指令的冲突,由MEM阶段给出数据旁路
    input                           mem_wr_en,  //处于访存阶段指令是否要写目的寄存器
    input [`RegDataBus]             mem_wr_data,
    input [`RegAddrBus]             mem_wr_addr
    );

wire [5:0] op = inst[31:26];         //从指令中获取操作码   高6位
wire [5:0] func = inst[5:0];        //从指令中获取功能号确定指令类型   低6位
wire [4:0] shmat = inst[10:6];      //部分移位位数不从寄存器取值,直接由shmat给出
reg [`RegDataBus] imm;              //立即数

always @ (*) begin
    if (rst) begin
        reg1_rden       <= 1'd0;
        reg2_rden       <= 1'd0;
        reg1_addr       <= 5'd0;
        reg2_addr       <= 5'd0;
        imm             <= 32'd0;
        reg_wb          <= 1'd0;
        reg_wb_addr     <= 5'd0;
        aluop           <= 7'd0;
    end else begin
        reg1_rden       <= 1'd0;
        reg2_rden       <= 1'd0;
        reg1_addr       <= inst[25:21];         //默认从指令中读取操作数1地址
        reg2_addr       <= inst[20:16];         //默认从指令中读取操作数2地址
        imm             <= 32'd0; 
        reg_wb          <= 1'd0;
        reg_wb_addr     <= inst[15:11];         //默认结果地址寄存器rd        
        aluop           <= 7'd0;                
        //操作类型
        if (op == `EXE_SPECIAL) begin
            reg1_rden   <= 1'd1;
            reg2_rden   <= 1'd1;
            reg_wb      <= 1'd1;
            case (func) 
                `EXE_AND:   begin
                        aluop   <=  `EXE_AND_FUNC;
                end            
                `EXE_OR:    begin
                        aluop   <=  `EXE_OR_FUNC;
                end
                `EXE_XOR:   begin
                        aluop   <=  `EXE_XOR_FUNC;
                end
                `EXE_NOR:   begin
                        aluop   <=  `EXE_NOR_FUNC;
                end
                `EXE_SLLV:  begin
                        aluop   <=  `EXE_SLL_FUNC;
                end
                `EXE_SRLV:  begin
                        aluop   <=  `EXE_SRLV_FUNC;
                end
                `EXE_SRAV:  begin
                        aluop   <=  `EXE_SRAV_FUNC;
                end
                `EXE_SLL:   begin
                        reg1_rden   <=  1'd0;
                        imm[4:0]    <=  shmat;
                        aluop       <=  `EXE_SLL_FUNC;
                end
                `EXE_SRL:   begin
                        reg1_rden   <=  1'd0;
                        imm[4:0]    <=  shmat;
                        aluop       <=  `EXE_SRL_FUNC;
                end
                `EXE_SRA:   begin
                        reg1_rden   <=  1'd0;
                        imm[4:0]    <=  shmat;
                        aluop       <=  `EXE_SRA_FUNC;
                end
                `EXE_MOVN:  begin
                        if (reg2 == 32'd0)  begin
                            reg_wb  <=  1'b0;
                        end else begin
                            reg_wb  <=  1'b1;
                            aluop   <=  `EXE_MOVN_FUNC;
                        end
                end
                `EXE_MOVZ:  begin
                        if (reg2 == 32'd0)  begin
                            reg_wb  <=  1'b1;
                            aluop   <=  `EXE_MOVZ_FUNC;
                        end else begin
                            reg_wb  <=  1'b0;
                        end
                end
                `EXE_MFHI:  begin
                        reg1_rden   <=  1'b0;
                        reg2_rden   <=  1'b0;
                        aluop       <=  `EXE_MFHI_FUNC;
                end
                `EXE_MFLO:  begin
                        reg1_rden   <=  1'b0;
                        reg2_rden   <=  1'b0;
                        aluop       <=  `EXE_MFLO_FUNC; 
                end
                `EXE_MTHI:  begin
                        reg2_rden   <=  1'b0;
                        reg_wb      <=  1'b0;
                        aluop       <=  `EXE_MTHI_FUNC;
                end
                `EXE_MTLO:  begin
                        reg2_rden   <=  1'b0;
                        reg_wb      <=  1'b0;
                        aluop       <=  `EXE_MTLO_FUNC;
                end
                `EXE_ADD:   begin
                        aluop   <=  `EXE_ADD_FUNC;
                end
                `EXE_ADDU:  begin
                        aluop   <=  `EXE_ADDU_FUNC;
                end
                `EXE_SUB:   begin
                        aluop   <=  `EXE_SUB_FUNC;
                end
                `EXE_SUBU:  begin
                        aluop   <=  `EXE_SUBU_FUNC;
                end
                default:    
                        aluop       <=  7'd0;
            endcase
        end else if (op == `EXE_SPECIAL2) begin     //由FUNC字段决定,操作码为011100的指令
            reg1_rden   <=  1'd1;
            reg2_rden   <=  1'd1;
            reg_wb      <=  1'd1;
            case (op)
                
                default:    begin
                        reg1_rden   <=  1'd0;
                        reg2_rden   <=  1'd0;
                        reg_wb      <=  1'd0;
                end
            endcase
        end else begin
            reg1_rden   <= 1'd1;  //需要读取操作数1 rs寄存器的值
            reg2_rden   <= 1'd0;  //不需要读取操作数2 rt寄存器值,
            imm         <= {16'h0, inst[15:0]};   
            reg_wb      <= 1'd1;
            reg_wb_addr <= inst[20:16];
            case (op)
                `EXE_ORI:   begin           //或指令  rs寄存器值是操作数1,imm是操作数2,结果放到rt寄存器
                        aluop   <=  `EXE_ORI_OP;           
                end
                `EXE_ANDI:  begin
                        aluop   <=  `EXE_ANDI_OP;
                end 
                `EXE_XORI:  begin
                        aluop   <=  `EXE_XORI_OP;
                end
                `EXE_LUI:   begin
                        reg1_rden   <= 1'b0;
                        aluop   <=  `EXE_LUI_OP;
                end
                `EXE_ADDI:  begin
                        aluop   <=  `EXE_ADDI_OP;
                end
                `EXE_ADDIU: begin
                        aluop   <=  `EXE_ADDIU_OP;
                end
                default:
                        aluop   <=  7'd0;    
            endcase
        end
    end
end

always @ (*) begin
    if (rst) begin
        reg1 <= 32'd0;
    end else if (reg1_rden == 1'd1 && ex_wr_en == 1'd1 && ex_wr_addr == reg1_addr) begin    //执行阶段旁路
        reg1 <= ex_wr_data;
    end else if (reg1_rden == 1'd1 && mem_wr_en == 1'd1 && mem_wr_addr == reg1_addr) begin   //访存阶段旁路
        reg1 <= mem_wr_data;
    end else if (reg1_rden == 1'd1) begin   //从通用寄存器获取操作数
        reg1 <= reg1_data;
    end else if (reg1_rden == 1'd0) begin   //从指令中获取操作数
        reg1 <= imm;
    end else begin
        reg1 <= 32'd0;
    end
end
    
always @ (*) begin
    if (rst) begin
        reg2 <= 32'd0;
    end else if (reg2_rden == 1'd1 && ex_wr_en == 1'd1 && ex_wr_addr == reg2_addr) begin    //执行阶段旁路
        reg2 <= ex_wr_data;
    end else if (reg2_rden == 1'd1 && mem_wr_en == 1'd1 && mem_wr_addr == reg2_addr) begin   //访存阶段旁路
        reg2 <= mem_wr_data;
    end else if (reg2_rden == 1'd1) begin   //从通用寄存器获取操作数
        reg2 <= reg2_data;
    end else if (reg2_rden == 1'd0) begin   //从指令中获取操作数
        reg2 <= imm;
    end else begin
        reg2 <= 32'd0;
    end
end
    
endmodule

本篇,我们只添加实现6条指令代码,分别是有符号加减、无符号加减、立即数有符号加和立即数无符号加法运算。鉴于之前给的主要是代码和结果,不太好理解,本篇开始一步一步的进行仿真,尽量把步骤详细写出来。


EX模块

`include "defines.v"
//执行阶段,根据译码阶段得到的操作码和操作数进行运算,得到结果
module ex(
    input                       rst,
    input [`AluOpBus]           aluop,
    input [`RegDataBus]         reg1,
    input [`RegDataBus]         reg2,
    input                       reg_wb_i,
    input [`RegAddrBus]         reg_wb_addr_i,
    output reg                  reg_wb_o,
    output reg [`RegAddrBus]    reg_wb_addr_o,
    output reg [`RegDataBus]    reg_wb_data,    //写回数据到目的寄存器
    //HILO寄存器
    input [`RegDataBus]         hi_reg_i,       //读取HI寄存器数据
    input [`RegDataBus]         lo_reg_i,       //读取LO寄存器数据
    output reg [`RegDataBus]    hi_reg_o,       //写入HI寄存器数据
    output reg [`RegDataBus]    lo_reg_o,       //写入LO寄存器数据
    output reg                  hi_wren,        //HI寄存器写使能        
    output reg                  lo_wren,        //LO寄存器写使能        
    //  HILO寄存器旁路                          
    input [`RegDataBus]         wb_hi_i,
    input [`RegDataBus]         wb_lo_i,
    input                       wb_hi_wren_i,  //有指令写HI,从写回阶段给出旁路(隔一条指令)
    input                       wb_lo_wren_i,  //有指令写LO,从写回阶段给出旁路(隔一条指令)
    input [`RegDataBus]         mem_hi_i,
    input [`RegDataBus]         mem_lo_i,
    input                       mem_hi_wren_i,  //有指令写HI,从访存阶段给出旁路(上一条指令)
    input                       mem_lo_wren_i  //有指令写LO,从访存阶段给出旁路(上一条指令)
    );

//需要转换成补码的指令
wire        reg2_mux   =   ((aluop==`EXE_SUB_FUNC)||(aluop==`EXE_SUBU_FUNC)||(aluop==`EXE_SLT_FUNC)) ? (~reg2+1) : reg2;
wire [31:0] res        =   reg1 + reg2_mux;    //判断加减的结果是否溢出,减法转换成加法
//overflow flag 两个正数相加得负或两个负数相加得正则溢出
wire        of         =   ((!reg1[31]&&!reg2[31]&&res[31])||(reg1[31]&&reg2[31]&&!res[31])); 
    
    always @ (*) begin
        if (rst) begin
            reg_wb_o        <= 1'd0;
            reg_wb_addr_o   <= 5'd0;
            reg_wb_data     <= 32'd0;
            hi_reg_o        <= 32'd0;
            lo_reg_o        <= 32'd0;
            hi_wren         <= 1'b0;
            lo_wren         <= 1'b0;
        end else begin
            reg_wb_o        <= reg_wb_i;
            reg_wb_addr_o   <= reg_wb_addr_i;
            reg_wb_data     <= 32'd0;
            hi_wren         <= 1'b0;
            lo_wren         <= 1'b0;
            hi_reg_o        <= 32'd0;
            lo_reg_o        <= 32'd0;
            case (aluop) 
                `EXE_ORI_OP,`EXE_OR_FUNC:       begin
                       reg_wb_data      <=  reg1 | reg2;
                end
                `EXE_ANDI_OP,`EXE_AND_FUNC:     begin
                        reg_wb_data     <=  reg1 & reg2;
                end
                `EXE_XORI_OP,`EXE_XOR_FUNC:     begin
                        reg_wb_data     <=  reg1 ^ reg2;
                end
                `EXE_LUI_OP:                    begin
                        reg_wb_data     <=  {reg2[15:0],reg2[31:16]};
                end
                `EXE_NOR_FUNC:                  begin
                        reg_wb_data     <=  ~(reg1 | reg2);
                end
                `EXE_SLL_FUNC,`EXE_SLLV_FUNC:   begin
                        reg_wb_data     <=  reg2 << reg1[4:0];
                end
                `EXE_SRL_FUNC,`EXE_SRLV_FUNC:   begin
                        reg_wb_data     <=  reg2 >> reg1[4:0];
                end
                `EXE_SRA_FUNC,`EXE_SRAV_FUNC:   begin       //算术移位也可以直接使用>>>
                        reg_wb_data     <=  ({32{reg2[31]}} << (6'd32 - {1'b0,reg1[4:0]})) | reg2 >> reg1[4:0];
                end
                `EXE_MOVN_FUNC,`EXE_MOVZ_FUNC:  begin
                        reg_wb_data     <=  reg1;
                end
                `EXE_MFHI_FUNC:                 begin
                        if (mem_hi_wren_i) begin            //访存阶段数据旁路
                            reg_wb_data     <=  mem_hi_i;
                        end else if (wb_hi_wren_i) begin    //写回阶段数据旁路
                            reg_wb_data     <=  wb_hi_i;
                        end else begin
                            reg_wb_data     <=  hi_reg_i;   //正常读取HI寄存器
                        end
                end
                `EXE_MFLO_FUNC:                 begin
                        if (mem_lo_wren_i) begin            //旁路
                            reg_wb_data     <=  mem_lo_i;
                        end else if (wb_lo_wren_i) begin    //旁路
                            reg_wb_data     <=  wb_lo_i;
                        end else begin                      //正常读取LO寄存器
                            reg_wb_data     <=  lo_reg_i;
                        end
                end
                `EXE_MTHI_FUNC:                 begin
                        hi_wren         <=  1'b1;
                        hi_reg_o        <=  reg1;
                        lo_reg_o        <=  lo_reg_i;
                end
                `EXE_MTLO_FUNC:                 begin
                        lo_wren         <=  1'b1;
                        lo_reg_o        <=  reg1;
                        hi_reg_o        <=  hi_reg_i;
                end
                `EXE_ADD_FUNC,`EXE_SUB_FUNC,
                `EXE_ADDI_OP:                   begin       //加法减法都是加法实现
                        reg_wb_data     <=  res;
                        if (of) begin
                            reg_wb_o    <=  1'd0;
                        end else begin  
                            reg_wb_o    <=  1'd1;
                        end
                end
                `EXE_ADDU_FUNC,`EXE_SUBU_FUNC,
                `EXE_ADDIU_OP:                  begin       //无符号数无需判断溢出,直接截断保存
                        reg_wb_data     <=  res;
                end
                default:                        begin
                        reg_wb_o        <= 1'd0;
                        reg_wb_addr_o   <= 5'd0;
                        reg_wb_data     <= 32'd0;
                        hi_reg_o        <= 32'd0;
                        lo_reg_o        <= 32'd0;
                        hi_wren         <= 1'b0;
                        lo_wren         <= 1'b0;
                end
            endcase
        end
    end

endmodule

有符号加减时需要判断溢出,如果溢出的话,就不讲结果写回目的寄存器;无符号加减则不需要考虑溢出问题,直接高位截断即可。


仿真测试1

3c018000:        LUI        reg1=>8000,0000
3c028000:        LUI        reg2=>8000,0000
34210001:        ORI       reg1=>8000,0001
34420002:        ORI       reg2=>8000,0002
00221820:        ADD      reg3=>溢出,无结果
00222021:        ADDU    reg4=>0000,0003 截断

有测试结果可知,ADD指令的有符号和无符号指令正确执行,在第五个时钟周期得到结果。


仿真测试2

00242822:        SUB        reg1 - reg3 => reg4 溢出无结果
00243023:        SUBU      reg1 - reg3 => reg5 无符号截断 8000,0001+(3)补码        

有测试结果可知,这两条减法指令也是正确无误。


加减指令都测试无误,下一篇将介绍其他指令的设计与测试!

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

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

相关文章

java epoll网络编程

java epoll网络编程 从通信开始 人类社会的发展离不开相互协作&#xff0c;一起围猎、抵御野兽&#xff0c;一起扛起锄头夯地、夯人&#xff0c;再到你与好兄弟之间征战峡谷。在这一切互相协作的背后&#xff0c;都离不开信息的传递&#xff0c;也就是通信。一群人聚在一起&am…

Android学习笔记(一) Android Studio 安装配置

大家好&#xff0c;我是半虹&#xff0c;这篇文章来讲 Android Studio 的安装配置 1、基本介绍 Android Studio 是 Google 推出的 Android 集成开发环境&#xff0c;可以用于创建、开发和调试 Android 项目 Android Studio 是基于 IntelliJ IDEA 开发的 &#xff0c;提供了专…

typora的一些配置方法

1.设置图片的保存路径 选择 文件 --> 偏好设置 --> 图像 --> 设置图片要保存的位置 将网络的图片保存到本地&#xff0c;例如&#xff0c;从csdn复制文章时&#xff0c;将文章中的图片自动保存到本地 在图像设置的插入图片时一栏&#xff0c;勾选对网络位置的图片应…

vmware中克隆过来的linux节点无system eth0

问题现象 使用vmware虚拟机的克隆功能后&#xff0c;找不到system eth0 解决办法 编辑/etc/udev/rules.d/70-persistent-net.rules文件 可以看到&#xff0c;eth0&#xff0c;是克隆前机器的网卡&#xff0c;eth1是克隆后机器生成的网卡&#xff0c;所以把NAME"eth0&q…

解决方案:在autodl环境下安装torch被killed掉

文章目录 一、现象二、解决方案 一、现象 平台&#xff1a;autodl 镜像&#xff1a;PyTorch 2.0.0 Python 3.8(ubuntu20.04) Cuda 11.8 GPU&#xff1a;A40(48GB) * 1 CPU&#xff1a;15 vCPU AMD EPYC 7543 32-Core Processor 内存&#xff1a;80GB 安装torch:1.13.0环境&a…

基于CloudflareSpeedTest项目实现git clone加速

1.网络测速 「自选优选 IP」测试 Cloudflare CDN 延迟和速度&#xff0c;获取最快 IP 更多内容参考项目&#xff1a;https://github.com/XIU2/CloudflareSpeedTest 国外很多网站都在使用 Cloudflare CDN&#xff0c;但分配给中国内地访客的 IP 并不友好&#xff08;延迟高、丢…

串口助手使用和插入usb转TTL的COM口识别问题

问题出现原因 由于串口调试中经常需要通过断电对单片机烧录程序&#xff0c;所以制作了一个转接带开关的USB 转接口&#xff0c;如下图所示&#xff0c;其中按键控制的是OUT口的电源通断。但为了能够数据传输&#xff0c;有两根传输数据的线是一直连接的。在使用usb进行程序烧…

【Threejs学习】创建Threejs页面

学习文档地址&#xff1a; threejs官网&#xff1a;https://threejs.org/ Threejs官网中文文档&#xff1a;https://threejs.org/docs/index.html#manual/zh/ threejs中文网&#xff1a;http://www.webgl3d.cn/ threejs基础教程&#xff1a;http://www.webgl3d.cn/pages/aac9ab…

《软件工程导论》(第6版)第6章 详细设计 复习笔记

第6章 详细设计 一、详细设计概述 1&#xff0e;目标 &#xff08;1&#xff09;详细设计阶段的根本目标是确定应该怎样具体地实现所要求的系统&#xff0c;即经过这个阶段的设计工作&#xff0c;应该得出对目标系统的精确描述&#xff0c;从而在编码阶段可以把这个描述直接…

四足机器人控制算法——建模、控制与实践(unitree_guide配置)

目录 官方文档 unitree_guide 1. 快捷指令 2. ROS安装 3. LCM库安装 3.1. 安装步骤 4. pthread库 5. 工程文件下载 6. 编译 报错&#xff1a; 报错1 报错2&#xff1a; 报错3 其他报错 7. 运行 7.1. 运行 Gazebo 仿真环境 7.2. 启动控制器 8. 简单使用 官方文…

贪心(临项交换)

前言&#xff1a;对待这个问题&#xff0c;我想到就是一定是贪心&#xff0c;但是我不知道怎么排序 对待这种问题&#xff0c;肯定是要先假设只有两个&#xff0c;我们要怎么排序呢 class Solution { public:long long minDamage(int power, vector<int>& damage, v…

分布式主键

目录 1.分布式主键的基本需求 2.常见的分布式主键生成策略 2.1UUID&#xff08;128位&#xff09; 2.2MySQL 2.2.1自增主键 2.2.2区间号段 2.3Redis 2.4SnowFlake雪花算法&#xff08;64位&#xff09; 1.分布式主键的基本需求 全局唯一&#xff1a;不管什么主键&…

Linux驱动(二):模块化编程的基本操作

目录 前言一、模块化编程1.模块化驱动代码框架2.printk详解3.应用操作 二、多模块编程三、多文件编程四、函数传参 前言 没多少东西&#xff0c;就是最基础的一些Linux驱动编写操作。 一、模块化编程 驱动加载到内核中的两种方法&#xff1a; 1.静态编译&#xff1a;就是将模…

【Python百日进阶-Web开发-Feffery】Day500 - dash使用秘籍

文章目录 前言:fac是什么?“人生苦短,我用Python;Web开发,首选Feffery!”↓↓↓ 今日笔记 ↓↓↓1 dash应用使用cdn加载静态资源1.1 页面效果1.2 项目源码2 suppress_callback_exceptions=True3 阻止首次回调3.1 阻止所有回调函数的首次回调3.2 阻止单个回调函数的首次回…

《JavaEE进阶》----5.<SpringMVC②剩余基本操作(CookieSessionHeader响应)>

Cookie和Session简介。 Spring MVC的 2.请求 Cookie的设置和两种获取方式 Session的设置和三种获取方式。 3.响应 1.返回静态页面 2.返回数据 3.返回HTML片段 4.返回JSON 5.设置状态码 6.设置header 三、&#xff08;接上文&#xff09;SpringMVC剩余基本操作 3.2postman请求 …

CSAPP Data Lab

CSAPP 的第一个 Lab&#xff0c;对应知识点为书中的第 2 章&#xff08;信息的表示与处理&#xff09;&#xff0c;要求使用受限制的运算符和表达式实现一些位操作。主要分为两个部分&#xff1a;整数部分和浮点数部分。其中整数部分限制较多&#xff0c;比较偏重技巧性&#x…

Red Hat Enterprise Linux 9—Red Hat 9.4Linux系统 Mac电脑虚拟机安装【保姆级教程】

Mac分享吧 文章目录 效果一、下载软件二、安装软件与配置1、安装2、配置 三、查看基本信息安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件 地址&#xff1a;www.macfxb.cn 二、安装软件与配置 1、安装 2、配置 三、查看基本信息 安装完成&#xf…

【国考】特值法

特值法 题干中存在乘除关系&#xff0c;且对应量未知。 例3&#xff1a;甲、乙、丙三个工程队的效率比为6&#xff1a;5&#xff1a;4,现将A、B两项工作量相同的工程交给这三个工程队,甲队负责A工程,乙队负责B工程,丙队参与A工程若干天后转而参与B工程.两项工程同时开工,耗时16…

【PyQt6 应用程序】视频百叶窗效果一键生成模块

在现代的多媒体创作中,音频和视频的结合是提升作品感染力的关键因素之一。尤其是短视频的制作,往往需要根据音频的节奏进行精细的剪辑和特效添加。PyQt6 作为一个功能强大的 Python GUI 库,为我们提供了极大的便利,使得我们可以轻松地创建功能丰富的应用程序。 本教程将一…

J.U.C并发工具集实战及原理分析

​在J.U.C里提供了很多的并发控制工具类&#xff0c;这些工具类可以使得线程按照业务的某种约束来执行。本节包含CountDownLatch、Semaphore、CyclicBarrier等工具类。目的是了解他们基本使用、原理及实际应用。 1. CountDownLatch主题 1.1 CountDownLatch简介 CountDownLat…