目錄
4.3 验证OpenMIPS实现效果
4.3.1指令存储器ROM的实现
4.3.2 最小SOPC的实现
4.3.3 编写测试程序
4.3.4 建立Test Bench文件
4.3.5使用ModelSim检验OpenMIPS实现效果
首頁 資料庫 mysql教程 自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果

自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果

Jun 07, 2016 pm 03:20 PM
cpu 手寫 指令 自己 階段 驗證

将陆续上传本人写的新书《自己动手写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所示。

自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果

自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果

      指令存储器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所示。

自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果

      转化为十六进制即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所示。

自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果

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

自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果

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

自己动手写CPU之第四阶段(2)验证第一条指令ori的实现效果

      (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工具链。


未完待续!
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

泰拉瑞亞怎麼用指示取得物品? -泰拉瑞亞怎麼收藏物品? 泰拉瑞亞怎麼用指示取得物品? -泰拉瑞亞怎麼收藏物品? Mar 19, 2024 am 08:13 AM

泰拉瑞亞怎麼用指示取得物品?一、什麼是泰拉瑞亞給予物品指令在泰拉瑞亞遊戲中,給予物品指令是一項非常實用的功能。透過這個指令,玩家可以直接取得需要的物品,而不必費力地去打怪或傳送到某個地點。這樣可以大大節省時間,提高遊戲的效率,讓玩家更專注於探索和建立世界。總的來說,這個功能讓遊戲體驗變得更加流暢和愉快。二、如何使用泰拉瑞亞給予物品指令1.打開遊戲並進入遊戲介面。 2.按下鍵盤上的「Enter」鍵,開啟聊天視窗。 3.在聊天視窗中輸入指令的格式:「/give[玩家名稱][物品ID][物品數量]」。

如何增加電腦CPU的時脈頻率 如何增加電腦CPU的時脈頻率 Feb 20, 2024 am 09:54 AM

電腦CPU如何超頻隨著科技的不斷進步,人們對於電腦效能的需求也越來越高。而一個有效的提升電腦效能的方法就是透過超頻(overclocking)來增加CPU的工作頻率。超頻可以使CPU更快地處理數據,從而提供更高的運算能力。那麼,電腦CPU如何超頻呢?以下將為大家介紹超頻的基本原理和具體操作方法。首先,讓我們來了解一下超頻的原理。 CPU的工作頻率是由主機板上的晶振

WIN10服務主機太佔cpu的處理操作過程 WIN10服務主機太佔cpu的處理操作過程 Mar 27, 2024 pm 02:41 PM

1.首先我們右鍵點選任務列空白處,選擇【任務管理器】選項,或右鍵開始徽標,然後再選擇【任務管理器】選項。 2.在開啟的任務管理器介面,我們點選最右邊的【服務】選項卡。 3.在開啟的【服務】選項卡,點選下方的【開啟服務】選項。 4.在開啟的【服務】窗口,右鍵點選【InternetConnectionSharing(ICS)】服務,然後選擇【屬性】選項。 5.在開啟的屬性窗口,將【開啟方式】修改為【禁用】,點選【應用程式】後點選【確定】。 6.點選開始徽標,然後點選關機按鈕,選擇【重啟】,完成電腦重啟就行了。

144 核心,3D 堆疊 SRAM:富士通詳細介紹下一代資料中心處理器 MONAKA 144 核心,3D 堆疊 SRAM:富士通詳細介紹下一代資料中心處理器 MONAKA Jul 29, 2024 am 11:40 AM

本站7月28日消息,根據外媒TechRader報道,富士通詳細介紹了計劃於2027年出貨的FUJITSU-MONAKA(以下簡稱MONAKA)處理器。 MONAKACPU基於「雲端原生3D眾核」架構,採用Arm指令集,面向資料中心、邊緣與電信領域,適用於AI運算,能實現大型主機層級的RAS1。富士通表示,MONAKA將在能源效率和性能方面實現飛躍:得益於超低電壓(ULV)製程等技術,該CPU可實現2027年競品2倍的能效,冷卻無需水冷;此外該處理器的應用性能也可達對手2倍。在指令方面,MONAKA配備的向量

洩漏揭示了英特爾 Arrow Lake-U、-H、-HX 和 -S 的關鍵規格 洩漏揭示了英特爾 Arrow Lake-U、-H、-HX 和 -S 的關鍵規格 Jun 15, 2024 pm 09:49 PM

英特爾ArrowLake預計將基於與LunarLake相同的處理器架構,這意味著英特爾全新的LionCove效能核心將與經濟體的Skymont效率核心結合。

AM4 拒絕死亡,消息稱 AMD 將推出 Ryzen 9 5900XT /7 5800XT:主頻最高 4.8GHz AM4 拒絕死亡,消息稱 AMD 將推出 Ryzen 9 5900XT /7 5800XT:主頻最高 4.8GHz Jun 05, 2024 pm 09:43 PM

本站6月1日消息,消息源@CodeCommando今天發布推文,分享了AMD即將在Computex2024活動中的部分演示文檔截圖,推文內容為“AM4永不消亡”,配圖展示了兩款新的Ryzen5000XT系列處理器。根據截圖內容顯示以下兩款產品:Ryzen95900XTRyzen95900XT定位相對高端,這是一款全新的16核心AM4處理器,其時脈速度略低於A​​MD的Ryzen95950X。 Ryzen75800XT它是AMD現有Ryzen75800X處理器的更快變體,這兩款處理器的主頻最高可達4.8G

微信好友輔助驗證解封的詳細方法 微信好友輔助驗證解封的詳細方法 Mar 25, 2024 pm 01:26 PM

1.打開微信進入後,點選搜尋圖標,輸入微信團隊,點選下方的服務進入。 2、進入後,點選左下方的自助工具的選項。 3、點選後,在上方的選項內,點選解封/申訴輔助驗證的選項。

超實用!讓你成為Linux大神的Sar命令 超實用!讓你成為Linux大神的Sar命令 Mar 01, 2024 am 08:01 AM

一、概述sar命令透過從系統活動中收集的資料來展示系統的使用報告。這些報告由不同部分組成,每個部分都包含資料類型和收集資料的時間。 sar指令的預設模式顯示存取CPU的各種資源(如使用者、系統、I/O調度等)在不同時間增量下的CPU使用率。此外,它還顯示給定時間段內空閒CPU的百分比。報告底部列出了每個數據點的平均值。 sar預設每10分鐘報告一次收集的數據,但您可以使用各種選項來篩選和調整這些報告。與uptime指令類似,sar指令也可協助您監控CPU的負載狀況。透過sar,您可以了解過度負載發

See all articles