自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果
将陆续上传本人写的新书《自己动手写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/imghw/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/imghw/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工具链。
未完待续!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Terraria에서 명령을 사용하여 아이템을 얻는 방법은 무엇입니까? 1. 테라리아에서 아이템을 주는 명령은 무엇인가요? 테라리아 게임에서 아이템에 명령을 내리는 것은 매우 실용적인 기능입니다. 이 명령을 통해 플레이어는 몬스터와 싸우거나 특정 위치로 순간이동할 필요 없이 필요한 아이템을 직접 얻을 수 있습니다. 이를 통해 시간을 크게 절약하고, 게임 효율성을 향상시키며, 플레이어가 세계를 탐험하고 건설하는 데 더 집중할 수 있습니다. 전반적으로 이 기능은 게임 경험을 더 부드럽고 즐겁게 만듭니다. 2. Terraria를 사용하여 아이템 명령을 내리는 방법 1. 게임을 열고 게임 인터페이스로 들어갑니다. 2. 키보드의 "Enter" 키를 눌러 채팅창을 엽니다. 3. 채팅창에 "/give[플레이어 이름][아이템 ID][아이템 수량]" 명령 형식을 입력하세요.

컴퓨터 CPU를 오버클럭하는 방법 기술이 지속적으로 발전함에 따라 컴퓨터 성능에 대한 사람들의 요구도 점점 더 높아지고 있습니다. 컴퓨터 성능을 향상시키는 효과적인 방법은 오버클럭을 통해 CPU의 작동 주파수를 높이는 것입니다. 오버클러킹을 사용하면 CPU가 데이터를 더 빠르게 처리하여 더 높은 컴퓨팅 성능을 제공할 수 있습니다. 그렇다면 컴퓨터 CPU를 오버클럭하는 방법은 무엇입니까? 다음은 오버클러킹의 기본 원리와 구체적인 작동 방법을 소개합니다. 먼저 오버클러킹이 어떻게 작동하는지 이해해 보겠습니다. CPU의 작동 주파수는 마더보드의 수정 발진기에 의해 결정됩니다.

28일 본 홈페이지 소식에 따르면 외신 테크레이더(TechRader)는 후지쯔가 2027년 출하 예정인 FUJITSU-MONAKA(이하 MONAKA) 프로세서를 자세하게 소개했다고 보도했다. MONAKACPU는 "클라우드 네이티브 3D 매니코어" 아키텍처를 기반으로 하며 Arm 명령어 세트를 채택합니다. 이는 데이터 센터, 엣지 및 통신 분야를 지향하며 메인프레임 수준의 RAS1을 구현할 수 있습니다. Fujitsu는 MONAKA가 에너지 효율성과 성능의 도약을 이룰 것이라고 밝혔습니다. 초저전압(ULV) 기술 등의 기술 덕분에 CPU는 2027년에 경쟁 제품보다 2배의 에너지 효율성을 달성할 수 있으며 냉각에는 수냉이 필요하지 않습니다. ; 게다가 프로세서의 애플리케이션 성능도 상대보다 두 배나 뛰어납니다. 지침 측면에서 MONAKA에는 벡터가 장착되어 있습니다.

1. 먼저 작업 표시줄의 빈 공간을 마우스 오른쪽 버튼으로 클릭하고 [작업 관리자] 옵션을 선택하거나, 시작 로고를 마우스 오른쪽 버튼으로 클릭한 후 [작업 관리자] 옵션을 선택합니다. 2. 열린 작업 관리자 인터페이스에서 맨 오른쪽에 있는 [서비스] 탭을 클릭합니다. 3. 열린 [서비스] 탭에서 아래의 [서비스 열기] 옵션을 클릭하세요. 4. 열리는 [서비스] 창에서 [InternetConnectionSharing(ICS)] 서비스를 마우스 오른쪽 버튼으로 클릭한 후 [속성] 옵션을 선택하세요. 5. 열리는 속성 창에서 [연결 프로그램]을 [사용 안 함]으로 변경하고 [적용]을 클릭한 후 [확인]을 클릭하세요. 6. 시작 로고를 클릭한 후 종료 버튼을 클릭하고 [다시 시작]을 선택한 후 컴퓨터를 다시 시작합니다.

6월 1일 이 웹사이트의 뉴스에 따르면, @CodeCommando 소스는 오늘 Computex2024 이벤트에서 AMD의 다가오는 프레젠테이션 문서의 일부 스크린샷을 공유하면서 트윗의 내용은 "AM4는 결코 죽지 않을 것입니다"였으며 첨부된 사진에는 두 가지 새로운 내용이 나와 있었습니다. Ryzen5000XT 시리즈 프로세서. 스크린샷에 따르면 다음 두 가지 제품이 표시됩니다. Ryzen95900XTR Ryzen95900XT는 AMD의 Ryzen95950X보다 클럭 속도가 약간 낮은 새로운 16코어 AM4 프로세서입니다. Ryzen75800XT AMD의 기존 Ryzen75800X 프로세서보다 더 빠른 변형입니다. 두 프로세서 모두 최대 4.8G까지 클럭됩니다.

Intel Arrow Lake는 Lunar Lake와 동일한 프로세서 아키텍처를 기반으로 할 것으로 예상됩니다. 즉, Intel의 새로운 LionCove 성능 코어가 경제적인 Skymont 효율성 코어와 결합될 것입니다. Lunar Lake는 Ava에서만 사용할 수 있습니다.

1. WeChat을 연 후 검색 아이콘을 클릭하고 WeChat 팀을 입력한 후 아래 서비스를 클릭하여 들어갑니다. 2. 입력 후 좌측 하단의 셀프 서비스 도구 옵션을 클릭하세요. 3. 클릭 후, 위 옵션 중 보조검증 차단해제/이의제기 옵션을 클릭해 주세요.

1. 개요 sar 명령은 시스템 활동에서 수집된 데이터를 통해 시스템 사용 보고서를 표시합니다. 이러한 보고서는 다양한 섹션으로 구성되어 있으며 각 섹션에는 데이터 유형과 데이터 수집 시기가 포함되어 있습니다. sar 명령의 기본 모드는 CPU에 액세스하는 다양한 리소스(예: 사용자, 시스템, I/O 스케줄러 등)에 대해 다양한 시간 증분으로 CPU 사용량을 표시합니다. 또한 특정 기간 동안 유휴 CPU의 비율을 표시합니다. 각 데이터 포인트의 평균값은 보고서 하단에 나열됩니다. sar 보고서는 기본적으로 10분마다 데이터를 수집하지만 다양한 옵션을 사용하여 이러한 보고서를 필터링하고 조정할 수 있습니다. uptime 명령과 마찬가지로 sar 명령도 CPU 로드를 모니터링하는 데 도움이 될 수 있습니다. sar를 통해 과도한 부하 발생을 이해할 수 있다.
