将陆续上传本人写的新书《自己动手写CPU》(尚未出版),今天是第12篇,我尽量每周四篇 书名又之前的《自己动手写处理器》改为《自己动手写CPU》 4.3 验证OpenMIPS实现效果 4.3.1指令存储器ROM的实现 本节将验证我们的OpenMIPS是否实现正确,包含:流水线是
将陆续上传本人写的新书《自己动手写CPU》(尚未出版),今天是第12篇,我尽量每周四篇
书名又之前的《自己动手写处理器》改为《自己动手写CPU》
4.3 验证OpenMIPS实现效果
4.3.1指令存储器ROM的实现
本节将验证我们的OpenMIPS是否实现正确,包含:流水线是否正确、ori指令是否实现正确。在验证之前,需要首先实现指令存储器,以便OpenMIPS从中读取指令。
指令存储器模块是只读的,其接口如图4-7所示,还是采用左边是输入接口,右边是输出接口的方式绘制,这样便于理解。接口含义如表4-12所示。

指令存储器ROM模块在文件inst_rom.v中实现,代码如下,可以在本书附带光盘的Code\Chapter4\目录下找到源文件。
module inst_rom( input wire ce, input wire[`InstAddrBus] addr, output reg[`InstBus] inst ); // 定义一个数组,大小是InstMemNum,元素宽度是InstBus reg[`InstBus] inst_mem[0:`InstMemNum-1]; // 使用文件inst_rom.data初始化指令存储器 initial $readmemh ( "inst_rom.data", inst_mem ); // 当复位信号无效时,依据输入的地址,给出指令存储器ROM中对应的元素 always @ (*) begin if (ce == `ChipDisable) begin inst <p> 代码很好理解,有以下几点说明。</p> <p> (1)在初始化指令存储器时,使用了initial过程语句。initial过程语句只执行一次,通常用于仿真模块中对激励向量的描述,或用于给变量赋初值,是面向模拟仿真的过程语句,通常不能被综合工具支持。所以如果要将本章实现的OpenMIPS处理器使用综合工具进行综合,那么需要修改这里初始化指令存储器的方法。</p> <p> (2)在初始化指令存储器时,使用了系统函数$readmemh,表示从inst_rom.data文件中读取数据以初始化inst_mem,而inst_mem正是之前定义的数组。inst_rom.data是一个文本文件,里面存储的是指令,其每行存储一条32位宽度的指令(使用十六进制表示),系统函数$readmemh会将inst_rom.data中的数据依次填写到inst_mem数组中。</p> <p> (3)OpenMIPS是按照字节寻址的,而此处定义的指令存储器的每个地址是一个32bit的字,所以要将OpenMIPS给出的指令地址除以4再使用,比如:要读取地址0xC处的指令,那么实际就是对应ROM的inst_mem[3],如图4-8所示。</p> <p><img src="/static/imghwm/default1.png" data-src="/inc/test.jsp?url=http%3A%2F%2Fimg.blog.csdn.net%2F20140725125057562%3Fwatermark%2F2%2Ftext%2FaHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVpc2hhbmd3ZW4%3D%2Ffont%2F5a6L5L2T%2Ffontsize%2F400%2Ffill%2FI0JBQkFCMA%3D%3D%2Fdissolve%2F70%2Fgravity%2FSouthEast&refer=http%3A%2F%2Fblog.csdn.net%2Fleishangwen%2Farticle%2Fdetails%2F38113933" class="lazy" alt="自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果" ><br> </p> <p> 除以4也就是将指令地址右移2位,所以在读取的时候给出的地址是addr[`InstMemNumLog2+1:2],其中InstMemNumLog2是指令存储器的实际地址宽度,比如:如果inst_mem有1024个元素,那么InstMemNum等于1024,InstMemNumLog2等于10,表示实际地址宽度为10。</p> <h3 id="最小SOPC的实现">4.3.2 最小SOPC的实现 </h3> <p> 为了验证,需要建立一个SOPC,其中仅包含OpenMIPS、指令存储器ROM,所以是一个最小SOPC。OpenMIPS从指令存储器中读取指令,指令进入OpenMIPS开始执行。最小SOPC的结构如图4-9所示。</p> <img src="/static/imghwm/default1.png" data-src="/inc/test.jsp?url=http%3A%2F%2Fimg.blog.csdn.net%2F20140725125417380%3Fwatermark%2F2%2Ftext%2FaHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVpc2hhbmd3ZW4%3D%2Ffont%2F5a6L5L2T%2Ffontsize%2F400%2Ffill%2FI0JBQkFCMA%3D%3D%2Fdissolve%2F70%2Fgravity%2FSouthEast&refer=http%3A%2F%2Fblog.csdn.net%2Fleishangwen%2Farticle%2Fdetails%2F38113933" class="lazy" alt="自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果" ><br> <p> 最小SOPC对应的模块是openmips_min_sopc,位于文件openmips_min_sopc.v中,读者可以在本书附带光盘的Code\Chapter4\目录下找到该文件,主要内容如下。在其中例化了处理器OpenMIPS、指令存储器ROM,并将两者按照图4-9的方式连接。</p> <pre class="brush:php;toolbar:false">module openmips_min_sopc( input wire clk, input wire rst ); // 连接指令存储器 wire[`InstAddrBus] inst_addr; wire[`InstBus] inst; wire rom_ce; // 例化处理器OpenMIPS openmips openmips0( .clk(clk), .rst(rst), .rom_addr_o(inst_addr), .rom_data_i(inst), .rom_ce(rom_ce) ); // 例化指令存储器ROM inst_rom inst_rom0( .ce(rom_ce), .addr(inst_addr), .inst(inst) ); endmodule
4.3.3 编写测试程序
我们需要写一段测试程序,并将其存储到指令存储器ROM,这样当上一节建立的最小SOPC开始运行的时候,就会从ROM中取出我们的程序,送入OpenMIPS处理器执行。由于目前的OpenMIPS只实现了一条ori指令,所以测试程序很简单,如下,对应本书附带光盘Code\Chapter4\TestAsm目录下的inst_rom.S文件。
ori $1,$0,0x1100 # $1 = $0 | 0x1100 = 0x1100 ori $2,$0,0x0020 # $2 = $0 | 0x0020 = 0x0020 ori $3,$0,0xff00 # $3 = $0 | 0xff00 = 0xff00 ori $4,$0,0xffff # $4 = $0 | 0xffff = 0xffff
共有4条指令,都是ori指令。
第1条指令将0x1100进行零扩展后与寄存器$0进行逻辑“或”运算,结果保存在寄存器$1中。
第2条指令将0x0020进行零扩展后与寄存器$0进行逻辑“或”运算,结果保存在寄存器$2中。
第3条指令将0xff00进行零扩展后与寄存器$0进行逻辑“或”运算,结果保存在寄存器$3中。
第4条指令将0xffff进行零扩展后与寄存器$0进行逻辑“或”运算,结果保存在寄存器$4中。
指令的注释说明了指令的执行结果。接下来,按照正常的顺序应该是使用编译器编译我们的测试程序,但由于GCC编译器的安装、使用、Makefile文件的制作等内容还需要不少篇幅讲解,而想必各位读者和笔者一样,急切地想知道OpenMIPS是否实现正确,所以本节采用手工编译的方式编译测试程序,4.4节将专题介绍GCC编译器的使用。
手工编译只需按照指令内容填充进图4-1所示的ori指令格式中,即可得到对应的二进制字,比如:对于指令ori $1,$0,0x1100,对应的二进制字如图4-10所示。

转化为十六进制即0x34011100,其余3条指令按照同样的方式可以得到对应的二进制字,按照$readmemh函数的要求,一行放一条指令,得到测试程序对应的isnt_rom.data文件如下,可在本书附带光盘的Code\Chapter4\TestAsm目录下找到同名文件。
34011100 34020020 3403ff00 3404ffff
4.3.4 建立Test Bench文件
本小节将建立Test Bench文件,其中给出最小SOPC运行所需的时钟信号、复位信号。代码如下,对应本书附带光盘Code\Chapter4\目录下的openmips_min_sopc_tb.v文件。
// 时间单位是1ns,精度是1ps `timescale 1ns/1ps module openmips_min_sopc_tb(); reg CLOCK_50; reg rst; // 每隔10ns,CLOCK_50信号翻转一次,所以一个周期是20ns,对应50MHz initial begin CLOCK_50 = 1'b0; forever #10 CLOCK_50 = ~CLOCK_50; end // 最初时刻,复位信号有效,在第195ns,复位信号无效,最小SOPC开始运行 // 运行1000ns后,暂停仿真 initial begin rst = `RstEnable; #195 rst= `RstDisable; #1000 $stop; end // 例化最小SOPC openmips_min_sopc openmips_min_sopc0( .clk(CLOCK_50), .rst(rst) ); endmodule
4.3.5使用ModelSim检验OpenMIPS实现效果
万事俱备,只欠东风了,本节是验证前的最后一步——建立ModelSim工程,进行仿真。参考第2章的介绍,新建一个ModelSim工程,工程名可以为openmips_min_sopc,将上文创建的OpenMIPS所有源文件、Test Bench文件、指令存储器的源文件等(也就是本书附带光盘Code\Chapter4目录下所有.v文件)添加到工程中,然后编译。
注意:还需要将上一小节制作的inst_rom.data文件复制到工程目录下。
编译通过后,将workspace切换到Library选项卡,打开work这个library,选中openmips_min_sopc_tb,右键点击,选择Simulate,如图4-11所示。

在出现的波形显示界面中,添加要观察的信号,即可开始仿真。此处我们选择寄存器$1-$4作为观察对象,如图4-12所示,通过观察寄存器$1-$4的最终值,可知OpenMIPS正确执行了测试程序,也就是正确实现了ori指令。

添加更多要观察的信号,可以了解流水线执行情况,如图4-13所示。为了使流水线情况显示的更加直观,此处以第一条指令在流水线中的执行过程为例,并且图中去掉了其它指令执行时引起的信号变化。

(1)在复位结束后的第一个时钟周期上升沿,rom_ce_o变为ChipEnable,表示指令存储器使能,开始取指,进入取指阶段,从指令存储器中取出第一条指令0x34011100,赋给IF/ID模块的输入端口if_inst。下一个时钟周期,第一条指令进入译码阶段。
(2)观察译码阶段。
- 此时译码阶段的指令id_inst正是第一条指令0x34011100
- 指令地址id_pc是0x00000000
- 在ID模块对指令进行译码,得到指令运算类型alusel_o是3'b001,查询defines.h文件中的宏定义可知,对应宏EXE_RES_LOGIC,表示是逻辑运算
- 得到运算子类型aluop_o是8'b00100101,查询defines.h文件中的宏定义可知,对应宏EXE_OR_OP,表示逻辑“或”运算
- 译码得到参与运算的源操作数1是0x00000000,正是$0寄存器的值
- 译码得到参与运算的源操作数2是0x00001100,正是指令中立即数零扩展后的值
- 译码得到wreg_o的值为1,表示要写目的寄存器
- 译码得到要写入的目的寄存器wd_o是5'b00001,正是$1寄存器
(3)观察执行阶段。
- 进行指定的运算,得到wdata_o为0x00001100,就是要写到目的寄存器的数据
- 传递译码阶段wreg_o的值,为1,表示要写目的寄存器
- 传递译码阶段wd_o的值,为5'b00001,表示要写入的目的寄存器是$1寄存器
(4)观察访存阶段
- 传递执行阶段wdata_o的值,为0x00001100,表示要写到目的寄存器的数据
- 传递执行阶段wreg_o的值,为1,表示要写目的寄存器
- 传递执行阶段wd_o的值,为5'b00001,表示要写入的目的寄存器是$1寄存器
(5)观察回写阶段
- 得到访存阶段wdata_o的值,为0x00001100,表示要写到目的寄存器的数据
- 得到访存阶段wreg_o的值,为1,表示要写目的寄存器
- 得到访存阶段wd_o的值,为5'b00001,表示要写入的目的寄存器是$1寄存器
在回写阶段的最后,将按照要求写目的寄存器$1,使得$1的值为0x00001100。通过上面的观察,可知原始的OpenMIPS五级流水线实现正确。接下来,我们就可以以此为基础,不断充实,添加实现更多的MIPS指令,不过,在此之前,我们要先学习使用GNU工具链,本节的例子只有4条指令,可以手工编译,以后会遇到比较复杂,拥有较多指令的程序,届时,手工编译就显得效率低下了,所以要使用GNU工具链。
未完待续!

核心数指的是CPU内核数量,表示一个CPU由多少个核心组成;cpu核心是CPU的重要组成部件,在内核频率、缓存大小等条件相同的情况下,CPU核心数量越多,CPU的整体性能越强。线程数是一种逻辑的概念,简单地说,就是模拟出的CPU核心数。CPU之所以要增加线程数,是源于多任务处理的需要;线程数越多,越有利于同时运行多个程序,因为线程数等同于在某个瞬间CPU能同时并行处理的任务数。

区别:1、单核就是CPU集成了一个运算核心,多核就是CPU集成了两个或多个运算核心;2、单核能同时运行的线程数较多核更少,不利于同时运行多个程序,而多核有利于同时运行多个程序;3、单核的执行速度较多核更慢,容易造成卡顿;4、多核的多任务处理效率比单核高;5、多核的性能比单核高,散热量、耗电量也比单核大;6、单核多用于部分要求轻薄、待机时间长、而对性能要求不高的笔记本电脑上。

cpu温度高的原因:1、散热不良;2、机器内灰尘过多也会引起死机故障;3、内存条故障;4、CPU超频;5、 硬盘故障;6、软硬件不兼容;7、驱动程序安装有误;8、应用软件的缺陷;9、病毒感染;10、启动的程序太多;11、用非法格式或参数非法打开或释放有关程序;12、误删除了系统文件;13、CMOS设置不当。

12核16线程指的是CPU中有12个内核,CPU的线程是16个,最多可以模拟16个核心;CPU的核心是运算器和控制器,多核可以增强并行处理能力,线程是进程中某个单一顺序的控制流,在单个程序中同时运行多个线程完成不同的工作,称为多线程。

能直接存取。内存储器又称内存,是外存与CPU进行沟通的桥梁,计算机中所有程序的运行都是在内存中进行。内存的作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机运行,操作系统就会把需要运算的数据从内存调到CPU中进行运算;当运算完成后,CPU再将结果传送出来,内存的运行也决定了计算机的稳定运行。

cpu温度过高导致的影响:1、CPU有自我保护功能,CPU过高会自动开启保护系统,降低电脑运行速率,系统越来越慢,直至死机,反复重启;2、长时间高温(长时间85度以上),CPU的自我保护功能可能失效,会烧坏CPU;3、自动关机,且关机之后,温度未降低之前无法开机。

cpu封装温度指的是表面CPU温度,就是说从表面CPU层的温度,一般还有内核温度,相差的度数不大;中央处理器温度是指CPU外壳温度,核心温度就是CPU内核的温度;一般核心温度和封装温度是接近的,cpu表面温度比后面者低不少。

四大主流cpu架构:1、X86架构,采用CISC指令集(复杂指令集计算机),程序的各条指令是按顺序串行执行的,每条指令中的各个操作也是按顺序串行执行的。2、ARM架构,是一个32位的精简指令集(RISC)架构。3、RISC-V架构,是基于精简指令集计算(RISC)原理建立的开放指令集架构。4、MIPS架构,是一种采取精简指令集(RISC)的处理器架构,可支持高级语言的优化执行。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

Dreamweaver Mac版
ビジュアル Web 開発ツール
