和你一起从零开始写RISC-V处理器(2)

2023-11-16

RISC-V加法指令的实现(Ⅱ)

上期回顾

本文首发于公众号:FPGA学习者,关注公众号,获取更多资料与内容。
上期说到,要实现加法指令,需要编写以下八个模块:
在这里插入图片描述
先总体看一下,该部分的模块连接的框图如下:
在这里插入图片描述Yx_risc-v(名称根据自身喜好命名)内核内部模块连接框图为:
在这里插入图片描述


一、正片开始——编写各个模块

①pc_reg模块

在这里插入图片描述
pc_reg模块主要用来根据时钟信号产生指令地址,因为ROM中一般每个存储空间有8位,所以四个存储空间才能完全存放一个指令信号,故,该模块的指令地址信号每时钟下进行加4操作。代码如下:


//该模块主要产生指令地址信号
module pc_reg(
  input    wire       clk    ,
  input   wire       rst_n    ,
  output   reg [31:0]   pc_o      //输出的指令地址
);

  always@(posedge clk or negedge rst_n)begin
    if(~rst_n)begin
      pc_o <= 32'b0;
    end
    else begin
      pc_o <= pc_o + 3'd4;
    end
  end
endmodule
//复位的时候,指令地址指向第0个指令寄存器,ROM的最开始
//其余时刻,不断加4,因为每个指令占用4个空间

②if模块

在这里插入图片描述
if(instruction fetch)取指模块,将输入的指令地址,送至ROM中,ROM根据指令地址产生相应的指令信号送入if取指模块,if再将指令信号和指令地址信号输出至下一个模块。代码如下:


//取指模块,从ROM中取出指令信号,组合逻辑
module ifeth(    //由于if为verilog关键字,所以使用ifetch
  //from pc_reg
  input   wire [31:0]   pc_addr_i    ,
  //from rom
  input   wire [31:0]   rom_inst_i    ,      //取出的命令,rom返回的指令
  //to rom
  output   wire [31:0]   if2rom_addr_o  ,      //将指令地址给rom,rom返回指令
  //to if_id
  output   wire [31:0]   inst_addr_o    ,      //将指令地址送入下一个模块打拍
  output   wire [31:0]   inst_o            //将指令送入下一个模块打拍

);
  assign if2rom_addr_o = pc_addr_i;
  assign inst_addr_o = pc_addr_i;
  assign inst_o = rom_inst_i;
endmodule

③rom模块

在这里插入图片描述 rom模块根据取指模块给出的地址,将相应的指令返回给取指模块,代码如下:

//存放指令的ROM
module rom(
  input   wire   [31:0]   inst_addr_i,
  output   reg  [31:0]   inst_o
);
  reg [31:0] rom_mem [0 : 4095];      //4096个32bit空间
  //这里一次性实现命令的32位了,和原本想法略有不符
  //所以下面要一次进行加一的操作,所以才右移4位。
  always@(*)begin
    inst_o = rom_mem[inst_addr_i >> 2];  //右移两位,缩小四倍,实现每次加一操作
  end
endmodule

对于rom模块,可以使用8位的rom,然后再进行逻辑处理;此处使用的比较简单,直接为32位rom,将本来步进加4的地址信号,右移两位(除以4)实现步进加1操作。

④if_id模块

在这里插入图片描述
对于if_id模块,实现简单的打一拍操作,防止出现时序违例。代码如下:

//时序逻辑,进行打拍
`include  "defines.v"
module if_id(
  input   wire         clk      ,
  input   wire         rst_n      ,
  input   wire [31:0]   inst_i      ,
  input   wire [31:0]   inst_addr_i  ,
  output   wire [31:0]   inst_addr_o,        //打一拍之后的地址输出
  output   wire [31:0]   inst_o            //打一拍之后的指令输出
);
  //例化D触发器,实现打一拍的逻辑
  dff_set #(32) dff1(clk,rst_n,`INST_NOP,inst_i,inst_o);
  dff_set #(32) dff2(clk,rst_n,32'b0,inst_addr_i,inst_addr_o);

endmodule

上述代码中包含头文件defines.v,该文件中主要是相关命令的宏定义,该文件获取方式在文末给出。

因为后续还有模块会用到寄存器打拍的操作,所以将D触发器打拍单独写为一个模块,上述if_id模块对其进行了例化。D触发器模块代码如下:

//D触发器模块,将输入的数据打一拍
module dff_set #(
  parameter DW = 32
)
(
  input   wire           clk    ,
  input   wire           rst    ,
  input   wire   [DW-1 : 0] set_data  ,  //复位时的信号
  input   wire   [DW-1 : 0] data_i  ,
  output   reg    [DW-1 : 0] data_o
);
  always@(posedge clk or negedge rst)begin
    if(~rst)begin
      data_o <= set_data;        //置位信号
    end
    else begin
      data_o <= data_i;
    end
  end
endmodule

⑤id模块

在这里插入图片描述
id模块对前级输入的指令信号进行译码,通过译码得出寄存器的地址信号,将该地址信号送至寄存器组,寄存器组返回相应的数据,然后向后级输出操作数1、操作数2、需要回写的目的寄存器地址和写寄存器使能信号。代码相对较长,此处仅放端口定义,完整代码获取方式文末给出。

该模块主要根据操作码和funct3功能码进行命令的判断。

module id(
  //from if_id
  input   wire   [31:0]   inst_i        ,        //前级输入的指令
  input   wire  [31:0]   inst_addr_i    ,        //前级输入的指令地址
  //to regs
  output   reg   [4:0]    rs1_addr_o  ,          //给寄存器组的地址
  output   reg   [4:0]   rs2_addr_o  ,          //给寄存器组的地址
  //from regs
  input   wire  [31:0]   rs1_data_i    ,        //从寄存器中取出的数据
  input   wire  [31:0]   rs2_data_i    ,        //从寄存器中取出的数据
  //to id_ex
  output   reg   [31:0]   inst_o      ,        //输出到后边的指令
  output   reg   [31:0]   inst_addr_o    ,        //输出到后边的指令地址
  output   reg   [31:0]   op1_o      ,        //操作数1
  output   reg   [31:0]   op2_o      ,        //操作数2
  output   reg   [4:0]     rd_addr_o    ,        //目的寄存器的地址,回写的时候用
  output   reg            reg_wen_o            //寄存器使能,写寄存器的时候用
);

⑥regs模块

在这里插入图片描述
寄存器组,一方面接收来自译码模块的地址信号并返回相应的数据信号,另一方面接收来自执行模块的地址信号、数据信号和使能信号。代码如下:


//寄存器组

module regs(
  input   wire       clk        ,
  input   wire      rst_n        ,
  //from id
  input   wire [4:0]   reg1_raddr_i  ,
  input   wire [4:0]   reg2_raddr_i  ,
  //to id
  output   reg [31:0]   reg1_rdata_o  ,
  output   reg [31:0]   reg2_rdata_o  ,
  //from ex                                  //从ex回来的地址和数据和使能信号
  input   wire [4:0]  reg_waddr_i  ,
  input   wire [31:0]  reg_wdata_i  ,
  input           reg_wen_i
);

  integer i;
  reg [31:0] regs [0 : 31];

  always@(*)begin
    if(~rst_n)begin
      reg1_rdata_o = 32'b0;
    end
    else if(reg1_raddr_i == 5'b0)
      reg1_rdata_o = 32'b0;
    else if(reg_wen_i && reg1_raddr_i == reg_waddr_i)    //这个地方主要是在指令冲突的时候
      reg1_rdata_o = reg_wdata_i;                //不需要通过读取回写之后的数据,直接进行判断后由该寄存器内部数据传递即可
    else
      reg1_rdata_o = regs[reg1_raddr_i];
  end
  always@(*)begin
    if(~rst_n)begin
      reg2_rdata_o = 32'b0;
    end
    else if(reg2_raddr_i == 5'b0)
      reg2_rdata_o = 32'b0;
    else if(reg_wen_i && reg2_raddr_i == reg_waddr_i)
      reg2_rdata_o = reg_wdata_i;
    else
      reg2_rdata_o = regs[reg2_raddr_i];
  end
  always@(posedge clk or negedge rst_n)begin
    if(~rst_n)begin                            //复位的时候,对寄存器组进行初始化
      for(i =  0 ; i < 31; i = i + 1)begin
        regs[i] <= 32'd0;    
      end
    end
    else if(reg_wen_i && reg_waddr_i != 5'b0) begin      //不能写入零寄存器
      regs[reg_waddr_i] <= reg_wdata_i;
    end
  end
endmodule

在上述代码的注释处描述的是指令冲突时的操作:如果第二条指令的源寄存器刚好是第一条指令的目的寄存器,(即:第二条指令的源寄存器地址等于第一条指令的目的寄存器地址),那就直接将执行模块得到的数据通过组合逻辑赋值给当前需要读出的源寄存器的数据,同时按照时序逻辑写入regs中去(每次回写都是必须要写的)。可参照下图以及上述程序进行理解上面那段话的含义。
在这里插入图片描述

⑦id_ex模块

在这里插入图片描述
对数据实现打一拍输出。

//进行打一拍输出
`include  "defines.v"
module id_ex(
  input   wire         clk      ,
  input   wire         rst_n      ,
  //from id
  input   wire [31:0]   inst_i      ,
  input   wire [31:0]   inst_addr_i  ,  
  input   wire [31:0]   op1_i      ,
  input   wire [31:0]   op2_i      ,
  input   wire [4:0]     rd_addr_i  ,
  input   wire          reg_wen_i  ,
  //to ex
  output   wire [31:0]   inst_o    ,          //输出到后边的指令
  output   wire [31:0]   inst_addr_o  ,          //输出到后边的指令地址
  output   wire [31:0]   op1_o    ,          //操作数1
  output   wire [31:0]   op2_o    ,          //操作数2
  output   wire [4:0]     rd_addr_o  ,          //目的寄存器的地址,回写的时候用
  output   wire          reg_wen_o            //寄存器使能,写寄存器的时候用

);
  dff_set #(32) dff1(clk,rst_n,`INST_NOP,inst_i,inst_o);
  dff_set #(32) dff2(clk,rst_n,32'd0,inst_addr_i,inst_addr_o);
  dff_set #(32) dff3(clk,rst_n,32'd0,op1_i,op1_o);
  dff_set #(32) dff4(clk,rst_n,32'd0,op2_i,op2_o);
  dff_set #(5) dff5(clk,rst_n,5'd0,rd_addr_i,rd_addr_o);
  dff_set #(1) dff6(clk,rst_n,1'b0,reg_wen_i,reg_wen_o);

endmodule

⑧ex模块

在这里插入图片描述
ex模块,实现执行和回写两个部分的内容,主要根据操作码、功能码funct3和功能码funct7来判断命令具体是哪一条,然后再执行相应的操作。

将操作后的数据根据地址信号和使能信号,回写到regs寄存器数组中。由于该部分代码较长,仅放端口定义,完整代码获取方式文末给出。


`include  "defines.v"
//执行模块
module ex(
  //from id_ex
  input   wire [31:0]   inst_i      ,
  input   wire [31:0]   inst_addr_i  ,  
  input   wire [31:0]   op1_i      ,
  input   wire [31:0]   op2_i      ,
  input   wire [4:0]     rd_addr_i  ,
  input   wire          reg_wen_i  ,
  //to regs
  output   reg [4:0]     rd_addr_o  ,
  output   reg [31:0]     rd_data_o  ,
  output   reg        rd_wen_o
);

好了,至此,所有的模块都绿了,这样就行了嘛?当然不行,要全绿才可以!下面要编写顶层模块将上述除ROM外的所有模块进行例化。

二、顶层模块搭建

在这里插入图片描述
好了,这下全绿了,该部分就是将上述除ROM外的七个模块进行例化,注意之间的连线,一步一步来,尽量不要出错,代码过长,此处仅放置端口定义,完整代码获取方式在文末给出:

//顶层文件
//将除了ROM之外的模块连接起来,ROM为外设,不是内核
`include  "defines.v"
`timescale 1ns/1ns
module Yx_risc_v(
  input   wire       clk      ,
  input   wire       rst_n      ,
  input   wire [31:0] inst_i      ,
  output   wire [31:0] inst_addr_o
);

除此之外,还要编写一个soc顶层文件,例化该内核模块和rom模块,代码如下:

//顶层文件
//`include  "defines.v"
module Yx_risc_v_soc(
  input   wire       clk  ,
  input   wire       rst_n
);
  //Yx_risc_v to rom
  wire [31:0] Yx_risc_v_inst_addr_o;
  //rom to Yx_risc_v
  wire [31:0] rom_inst_o;
  Yx_risc_v Yx_risc_v_inst(
    .clk          (clk                ),
    .rst_n        (rst_n              ),
    .inst_i        (rom_inst_o          ),
    .inst_addr_o    (Yx_risc_v_inst_addr_o  )
);
  rom rom_inst(
    .inst_addr_i      (Yx_risc_v_inst_addr_o  ),
    .inst_o        (rom_inst_o          )
);
endmodule

如此便可形成如下结构:

在这里插入图片描述

三、测试文件编写

或许你正看上面的文章看的津津有味,有没有突然想到,哎?光说从rom中读取指令,那rom中的指令从哪里来呢?

这里使用了一个系统函数:$readmemb,通过该函数将外部.txt文件中的指令读取到rom中即可。
testbench文件编写如下:


`timescale 1ns/1ns
module tb;
  reg clk;
  reg rst_n;
Yx_risc_v_soc Yx_risc_v_soc_inst(
  .clk(clk),
  .rst_n(rst_n)
);
  always #10 clk = ~clk;
  initial begin
    clk = 0;
    rst_n = 0;
    #30;
    rst_n = 1'b1;
  end
  //rom 初始值
  initial begin  //第一个参数为文件名,第二个参数为需要写入的寄存器
    $readmemb("inst_data_ADD.txt",tb.Yx_risc_v_soc_inst.rom_inst.rom_mem);
  end
  initial begin
    while(1)begin
      @(posedge clk)
      $display("x27 register value is %d",tb.Yx_risc_v_soc_inst.Yx_risc_v_inst.regs_inst.regs[27]);
      $display("x28 register value is %d",tb.Yx_risc_v_soc_inst.Yx_risc_v_inst.regs_inst.regs[28]);
      $display("x29 register value is %d",tb.Yx_risc_v_soc_inst.Yx_risc_v_inst.regs_inst.regs[29]);
      $display("---------------------------");
      $display("---------------------------");
    end
  end
endmodule

编写的.txt文件如下:


00000000111100000000110110010011
00000001100100000000111000010011
00000001110011011000111010110011

对应的指令为:
在这里插入图片描述这样运算得到的结果应该为40;ModelSim中仿真结果如下:
在这里插入图片描述
结果是正确的,编写的代码应该也问题不大。看看波形吧,如下:
在这里插入图片描述
确实也是分三个时钟周期执行完一条指令。
好,先测到这里,其他详细测试暂时不写了;今天内容有些超量了哈哈。

总结

上述代码,关注公众号:FPGA学习者,后台回复【指令添加】即可获取全部工程文件。

往期精彩

和你一起从零开始写RISC-V处理器(1)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

和你一起从零开始写RISC-V处理器(2) 的相关文章

  • SD卡读写实验(SPI模式)

    对于 SD 卡的 SPI 模式而言 采用的 SPI 的通信模式为模式 3 即 CPOL 1 CPHA 1 在 SD 卡 2 0 版 本协议中 SPI CLK 时钟频率可达 50Mhz SD 卡的 SPI 模式 只用到了 SDIO D3 SP
  • 手把手教你Modelsim仿真【2020.4版本】

    首先新建一个文件夹 test5 打开Modelsim 依次选择 File gt Change Directory 把目录选择到创建的 test5 文件夹 创建库 依次选择 File gt New gt Library 一般我们选择第三个 库
  • 跨时钟域处理方法(一)——打拍

    一 说明 处理跨时钟域的数据可以分为单bit数据和多bit数据 而打拍的方法主要常见于处理单bit数据的跨时钟域问题 打拍的本质是通过添加寄存器 对输入的数据进行延拍 其主要目标是消除亚稳态的影响 常见的是打2拍 也就是添加2级寄存器 二
  • 数码管电子时钟

    文章目录 前言 一 回顾数码管 二 任务描述 三 系统框图 四 模块调用 五 模块原理图 六 工程源码 6 2 时钟计数模块代码 6 2 数码管驱动模块代码 6 3 顶层模块代码 七 仿真测试 7 1 测试代码 7 2 仿真结果 八 管脚信
  • FIFO读写控制

    如果在两个模块之间传输数据 两个模块之间的处理速率不同 会导致采集数据的遗漏或错误 在他们之间加一个数据缓存器 所有数据先经过缓存器缓存 再输入数据接送模块 创建两个模块 一个 作为发送模块 一个作为接受模块 发送模块检测到 fifo为空开
  • 【Xilinx DDR3 MIG】Xilinx FPGA DDR3读写实验相关用户接口引脚解释

    目录 DDR3读写实验 实验框图 时钟模块 DDR3读写及LED指示模块 MIG IP核 用户接口解释
  • FPGA提示产生latch的报错

    在fpga的设计中有时会遇到 latch 的报错 1 latch是什么 Latch 就是锁存器 是一种在异步电路系统中 对输入信号电平敏感的单元 用来存储信息 锁存器在数据锁存使能时 数据被锁存 输入信号不起作用 这违背了组合逻辑中输出随输
  • 蓝桥杯真题:迷宫

    目录 题目描述 运行限制 dfs bfs 结果 题目描述 本题为填空题 只需要算出结果后 在代码中使用输出语句将所填结果输出即可 下图给出了一个迷宫的平面图 其中标记为 11 的为障碍 标记为 00 的为可以通行的地方 010000 000
  • 【FPGA】通俗理解从VGA显示到HDMI显示

    注 大部分参考内容来自 征途Pro FPGA Verilog开发实战指南 基于Altera EP4CE10 2021 7 10 上 贴个下载地址 野火FPGA Altera EP4CE10征途开发板 核心板 野火产品资料下载中心 文档 hd
  • 【电子技术】什么是LFSR?

    目录 0 前言 1 数学基础 1 1 逻辑异或 1 2 模2乘法 和 模2除法 2 线性反馈移位寄存器LFSR 3 抽头和特征多项式 4 阶线性反馈移位寄存器实例 0 前言 线性反馈移位寄存器 Linear Feedback Shift R
  • 如何用GDB调试交叉编译的QEMU程序?

    我在使用 GDB 调试 QEMU 中运行的简单程序时遇到问题 GDB似乎无法找到我在程序中的位置 因为它总是显示 作为我当前的位置 并且它永远不会达到我设置的任何断点 在一个终端中 我运行 QEMU cat add c int main i
  • 为什么 $ra 被调用者保存在 RISC-V 中

    我发现在 RISC V 中 ra调用者是否已保存 以 MIPS 为单位 ra是被调用者 这意味着在 RISC V 中被调用者可以直接更改ra没有保存 但自从ra已经改变了 被调用者如何返回调用者 无论名称如何 RISC V ra 和 MIP
  • 硬核 | 从零制作一个激光雷达需要多久?

    编辑 ADS智库 点击下方 卡片 关注 自动驾驶之心 公众号 ADAS巨卷干货 即可获取 点击进入 自动驾驶之心 硬件交流 技术交流群 本文只做学术分享 如有侵权 联系删文 激光雷达 LiDAR 是激光探测及测距系统的简称 目前广泛应用在无
  • [Verilog] Verilog 基本格式和语法

    主页 元存储博客 全文 3000 字 文章目录 1 声明格式 1 1 模块声明 1 2 输入输出声明 1 3 内部信号声明 1 4 内部逻辑声明
  • 凿子3.功能模块Mux4

    我正在按照文档学习 Chisel在 Github 上 https github com ucb bar chisel3 wiki Short 20Users 20Guide 20to 20Chisel 到目前为止 一切都完美无缺 但我还是卡
  • TRICONEX MA2211-100 芯片上相互连接

    TRICONEX MA2211 100 芯片上相互连接 TRICONEX MA2211 100 所有相同的组件 io的电源 处理器 和内存将需要 但是 你可以看到所有这些带存储器和处理器的OO板 针不能嵌入到一个小的单片机上 现在是 普拉克
  • 裸机 RISC-V CPU - 处理器如何知道从哪个地址开始获取指令?

    我正在设计自己的 RISC V CPU 并且已经能够实现一些指令代码 我已经安装了 RV32I 版本的 GCC 编译器 所以我现在有了汇编器riscv32 unknown elf as可用的 我正在尝试仅用一条指令来汇编一个程序 simpl
  • DSCA190V 57310001-PK

    DSCA190V 57310001 PK DSCA190V 57310001 PK 具有两个可编程继电器功能 并安装在坚固的 XP 外壳中 DSCA190V 57310001 PK 即可使用 只需最少的最终用户校准 DSCA190V 573
  • 数组和结构体可以以不同的方式初始化吗?

    我的问题可能看起来很奇怪 事实上 这是上下文 我目前在切换时遇到一个奇怪的问题 关于我正在从事的项目 核心从pullinino到CV32 也发生了一些其他变化 例如关于crt0 如一些数据内存重置 这是一个 真实的 例子 说明了一个非常简单
  • RISC-V 规范引用了“hart”一词 - “hart”是什么意思?

    我找到了参考文献hart在第 35 页RISC V 2 1 规范 https content riscv org wp content uploads 2016 06 riscv spec v2 1 pdf 但是 我找不到它的定义hart在

随机推荐

  • umijs----路由(修改路由的某一个path )

    1 在src下创建app js ts tsx 2 修改路由 export function patchRoutes routes routes为 umirc ts中设置的routes数组 可以使用数组的方法插入删除 运行时在最前面插入一个路
  • Webpack配置Vue热更新

    Webpack配置Vue热更新 需要的包 cnpm i vue webpack webpack cli webpack dev server html webpack plugin clean webpack plugin style lo
  • 【正点原子MP157连载】第七章 认识HAL库-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南

    1 实验平台 正点原子STM32MP157开发板 2 购买链接 https item taobao com item htm id 629270721801 3 全套实验源码 手册 视频下载地址 http www openedv com t
  • selenium4

    1 单选框和复选框 单选框 type radio 定位 gt 点击 判断是否被选中 元素 is selected 复选框 type checkbox 只选择一个 gt 同单选框一样 全选 定位所有复选框 遍历 判断是否被选中 点击 选择部分
  • java入门六:java基础终章

    1 static关键字 静态变量和类一起加载 final修饰后的类无法被继承 2 抽象类 abstract修饰符可以用来修饰方法也可以修饰类 如果修饰方法 那么该方法就是抽象方法 如果修饰类 那么该类就是抽象类 抽象类中可以没有抽象方法 但
  • Linux Shell程序设计(2)

    实验十一 Shell程序设计 2 一 实验要求 综合运用shell编程知识进行设计性编程 二 实验内容和实验步骤 1 实验内容 假设你作为某工厂生产管理员 需要负责统计各车间每天生产的产品数据 你的计算机安装了双硬盘 为了保证数据安全 你在
  • 【定位问题】Mybatis-plus的selectPage()分页查询不生效问题

    背景 项目需要从mybits切换到mubits plus 但是我在进行分页查询的时候 发现一直不生效 问题原因 添加监听器 配置如下 Configuration MapperScan com baomidou mybatisplus sam
  • parted创建硬盘分区并创建LVM

    目的 将两个三T的硬盘做成LVM sdc sdd 一 parted将硬盘进行分区 1 parted的命令方式 Parted 命令分为两种模式 命令行模式和交互模式 1 命令行模式 parted option device command 该
  • 【原创】第一个iOS应用程序

    摘要 第一个iOS应用程序 包括获取控件 绑定事件 设置属性等内容 iOS Objective C 目录 第一章 窗口与应用程序 第二章 添加视图 2 1 从nib文件初始化视图 2 2 使用脚本添加视图 第三章 添加子视图 3 1 通过x
  • 制作自己的 Kindle 电子书

    想象以下场景 你刚收到一台新的 Kindle Paperwhite 心中已然响起了轰轰烈烈的 我今年 或这个冬天 一定要阅读 100 本书 结果发现 想看的书 Amazon 上找不到 或者排版很糟糕 如何解决 自己动手做呗 准备工作 我使用
  • UE4 UI实现改键功能

    主要内容 本文主要讲解如何在UI中实现自定义按键的功能类似于游戏中的改键操作 用到的是UE4自带的第三人称案例 因为第三人称自带了小白人和几个按键绑定就不用再手动去设置 实现步骤 1 创建两个UMG用来展示UI效果 1 创建WBP Key
  • C++链表合并

    有l1和l2两个链表 这两个链表降序排列 把l2合并到l1中 并按降序排列 同时清空l2链表 例如l1 9 8 7 6 l2 12 11 10 5 4 3 2 1 合并后l1 12 11 10 9 8 7 6 5 4 3 2 1 l2 in
  • 【Android】利用intent启动浏览器

    文章目录 一 默认浏览器 二 指定浏览器 三 选择浏览器 一 默认浏览器 需要设置Action和Date属性 构造 Uri uri Uri parse https www baidu com Intent intent new Intent
  • SCADE Suite 状态机之变量隐式赋值

    SCADE Suite 状态机之变量隐式赋值 1 变量的隐式赋值 目的 简化模型设计 Last 只要没有显示赋值 便取上一周期的数值 Default 只要没有显示赋值 便取默认设置的数值 优先级更高 设置方法 2 定义变量的Last值 1
  • LeetCode 817:链表组件(计数)

    解法一 常规解法 建图 DFS 时间复杂度O n O n 空间复杂度因为需要存储图 所以是O n 这种方法是通解 对于所有图都适用 Definition for singly linked list struct ListNode int
  • lua元表以及元方法

    知微出凡 lua元表以及元方法 lua中的变量是没有数据类型的 值有类型 类型有八种nil number boolean string function thread userdata以及table Lua 中的每个值都可以有一个 元表 这
  • 62.[GIS基础]笛卡尔坐标系

    文章目录 笛卡尔坐标系 多坐标系 坐标系的嵌套 坐标变换 坐标系转换 转载请注明原始链接 http blog csdn net a464057216 article details 54578069 后续此博客不再更新 欢迎大家搜索关注微信
  • 基于粒子群算法(PSO)优化径向基神经网络(PSO-RBF)的分类预测。matlab代码,优化参数为扩散速度,采用交叉验证。多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就

    清空环境变量 warning off 关闭报警信息 close all 关闭开启的图窗 clear 清空变量 clc 清空命令行 读取数据 res xlsread 数据集 xlsx 分析数据 num class length unique
  • 抛去容抗角度,从电容充放电角度理解RC低通滤波器

  • 和你一起从零开始写RISC-V处理器(2)

    RISC V加法指令的实现 文章目录 RISC V加法指令的实现 上期回顾 一 正片开始 编写各个模块 pc reg模块 if模块 rom模块 if id模块 id模块 regs模块 id ex模块 ex模块 二 顶层模块搭建 三 测试文件