cpu设计和实现(协处理器cp0)

news2024/11/29 22:45:00

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        除了通用计算器负责控制和计算之外,cpu如果需要正常有序地运行,还需要一定地协处理器来帮助完成对应地工作。在mips下面,这样地协处理器称之为cp0。协处理器的工作一般包括这几个方面,

        1)处理中断和异常;

        2)处理mmu和tlb;

        3)处理cache;

        4)处理其他cpu的相关属性。

        之前我们在谈到乘法和除法的时候,涉及到hi和lo这两个寄存器。其实,cp0的处理方法和他们是差不多的。如果是mf读操作,那么这个动作是在exe阶段完成的;如果是写操作,那么这个动作也是在wb阶段完成的。

1、准备cp0_reg.v

`include "defines.v"

module cp0_reg(

	input	wire										clk,
	input wire										rst,
	
	
	input wire                    we_i,
	input wire[4:0]               waddr_i,
	input wire[4:0]               raddr_i,
	input wire[`RegBus]           data_i,
	
//	input wire[31:0]              excepttype_i,
	input wire[5:0]               int_i,
//	input wire[`RegBus]           current_inst_addr_i,
//	input wire                    is_in_delayslot_i,
	
	output reg[`RegBus]           data_o,
	output reg[`RegBus]           count_o,
	output reg[`RegBus]           compare_o,
	output reg[`RegBus]           status_o,
	output reg[`RegBus]           cause_o,
	output reg[`RegBus]           epc_o,
	output reg[`RegBus]           config_o,
	output reg[`RegBus]           prid_o,
	
	output reg                   timer_int_o    
	
);

	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			count_o <= `ZeroWord;
			compare_o <= `ZeroWord;
			//status寄存器的CU为0001,表示协处理器CP0存在
			status_o <= 32'b00010000000000000000000000000000;
			cause_o <= `ZeroWord;
			epc_o <= `ZeroWord;
			//config寄存器的BE为1,表示Big-Endian;MT为00,表示没有MMU
			config_o <= 32'b00000000000000001000000000000000;
			//制作者是L,对应的是0x48,类型是0x1,基本类型,版本号是1.0
			prid_o <= 32'b00000000010011000000000100000010;
      timer_int_o <= `InterruptNotAssert;
		end else begin
		  count_o <= count_o + 1 ;
		  cause_o[15:10] <= int_i;
		
			if(compare_o != `ZeroWord && count_o == compare_o) begin
				timer_int_o <= `InterruptAssert;
			end
					
			if(we_i == `WriteEnable) begin
				case (waddr_i) 
					`CP0_REG_COUNT:		begin
						count_o <= data_i;
					end
					`CP0_REG_COMPARE:	begin
						compare_o <= data_i;
						//count_o <= `ZeroWord;
            timer_int_o <= `InterruptNotAssert;
					end
					`CP0_REG_STATUS:	begin
						status_o <= data_i;
					end
					`CP0_REG_EPC:	begin
						epc_o <= data_i;
					end
					`CP0_REG_CAUSE:	begin
					  //cause寄存器只有IP[1:0]、IV、WP字段是可写的
						cause_o[9:8] <= data_i[9:8];
						cause_o[23] <= data_i[23];
						cause_o[22] <= data_i[22];
					end					
				endcase  //case addr_i
			end
			
			
		end    //if
	end      //always
			
	always @ (*) begin
		if(rst == `RstEnable) begin
			data_o <= `ZeroWord;
		end else begin
				case (raddr_i) 
					`CP0_REG_COUNT:		begin
						data_o <= count_o ;
					end
					`CP0_REG_COMPARE:	begin
						data_o <= compare_o ;
					end
					`CP0_REG_STATUS:	begin
						data_o <= status_o ;
					end
					`CP0_REG_CAUSE:	begin
						data_o <= cause_o ;
					end
					`CP0_REG_EPC:	begin
						data_o <= epc_o ;
					end
					`CP0_REG_PrId:	begin
						data_o <= prid_o ;
					end
					`CP0_REG_CONFIG:	begin
						data_o <= config_o ;
					end	
					default: 	begin
					end			
				endcase  //case addr_i			
		end    //if
	end      //always

endmodule

2、id添加译码

     if(inst_i[31:21] == 11'b01000000000 && 
										inst_i[10:0] == 11'b00000000000) begin
				aluop_o <= `EXE_MFC0_OP;
				alusel_o <= `EXE_RES_MOVE;
				wd_o <= inst_i[20:16];
				wreg_o <= `WriteEnable;
				instvalid <= `InstValid;	   
				reg1_read_o <= 1'b0;
				reg2_read_o <= 1'b0;		
			end else if(inst_i[31:21] == 11'b01000000100 && 
										inst_i[10:0] == 11'b00000000000) begin
				aluop_o <= `EXE_MTC0_OP;
				alusel_o <= `EXE_RES_NOP;
				wreg_o <= `WriteDisable;
				instvalid <= `InstValid;	   
				reg1_read_o <= 1'b1;
				reg1_addr_o <= inst_i[20:16];
				reg2_read_o <= 1'b0;					
			end

3、ex阶段

1)增加数据读取操作

	   	`EXE_MFC0_OP:		begin
	   	  cp0_reg_read_addr_o <= inst_i[15:11];
	   		moveres <= cp0_reg_data_i;
	   		if( mem_cp0_reg_we == `WriteEnable &&
	   				  mem_cp0_reg_write_addr == inst_i[15:11] ) begin
	   				moveres <= mem_cp0_reg_data;
	   		end else if( wb_cp0_reg_we == `WriteEnable &&
	   				 							 wb_cp0_reg_write_addr == inst_i[15:11] ) begin
	   				moveres <= wb_cp0_reg_data;
	   		end
	   	end	 

        看到这里,大家应该对这个代码不陌生了。之前谈到过,所有的寄存器都是在wb之后,才会真正写到寄存器里面的。但是,mfc0的动作是在exe阶段进行的,那么这个时候势必会出现数据读取错误的情况的。所以,解决这个问题最好的办法就是数据预取。id中寄存器预取、ex阶段hi&lo以及mfc预取、mem阶段llbit预取,本质上都是一回事。

2)增加写操作


	always @ (*) begin
		if(rst == `RstEnable) begin
			cp0_reg_write_addr_o <= 5'b00000;
			cp0_reg_we_o <= `WriteDisable;
			cp0_reg_data_o <= `ZeroWord;
		end else if(aluop_i == `EXE_MTC0_OP) begin
			cp0_reg_write_addr_o <= inst_i[15:11];
			cp0_reg_we_o <= `WriteEnable;
			cp0_reg_data_o <= reg1_i;
	  end else begin
			cp0_reg_write_addr_o <= 5'b00000;
			cp0_reg_we_o <= `WriteDisable;
			cp0_reg_data_o <= `ZeroWord;
		end				
	end	

        cp0寄存器的写操作是和通用寄存器分开来的。所以这部分代码需要单独用逻辑快来表达。

4、mem阶段

        mem阶段对cp0没有什么影响,主要工作就是把之前ex阶段的数据透传下去即可。

		  cp0_reg_we_o <= cp0_reg_we_i;
		  cp0_reg_write_addr_o <= cp0_reg_write_addr_i;
		  cp0_reg_data_o <= cp0_reg_data_i;	

5、准备汇编代码测试

   .org 0x0
   .set noat
   .set noreorder
   .set nomacro
   .global _start
_start:
   ori $1,$0,0xf
   mtc0 $1,$11,0x0  #写compare寄存器,开始计时
   lui $1,0x1000
   ori $1,$1,0x401
   mtc0 $1,$12,0x0  #将0x401写如status寄存器
   mfc0 $2,$12,0x0  #读status寄存器,$2=0x401

_loop:
   j _loop
   nop
   
   

6、将对应的汇编代码翻译成二进制文件

3401000f
40815800
3c011000
34210401
40816000
40026000
08000006
00000000

7、利用iverilog和gtkwave进行波形分析

         除了通用的pc、inst这些寄存器、wire之外,还可以把cp0_reg0里面的寄存器拉出来看看。重点看看we_i什么时候为高、写入的waddr_i对不对、和之前给出来的汇编代码能不能对的上。最后就是死循环了,因为mips延迟槽的原因,循环肯定是两个pc地址交替进行的。

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

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

相关文章

Vue实现流程图,借鉴vue-tree-color 实现流程框架技术

Vue实现流程图&#xff0c;借鉴vue-tree-color 实现流程框架技术 文章目录Vue实现流程图&#xff0c;借鉴vue-tree-color 实现流程框架技术借鉴鸣谢演示效果引入依赖添加全局组件的二次封装步骤1 创建组件目录Vuenode.jstree.less使用组件引入使用数据结构案例借鉴鸣谢 实现组…

[附源码]Python计算机毕业设计Django的桌游信息管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

元宇宙产业委调研行杭州站 | 联合西溪谷管委会共商元宇宙赋能实体经济

11月29日下午&#xff0c;由杭州西溪谷建设发展管理委员会和中国移动通信联合会元宇宙产业工作委员会共同举办的“元宇宙赋能实体经济企业家沙龙暨元宇宙产业委调研行杭州站”在西溪谷杭州蚂蚁链产业创新中心召开。20余家元宇宙和区块链企业到场&#xff0c;西溪谷管委会党委书…

pytorch复习笔记--loss.backward()、optimizer.step()和optimizer.zero_grad()的用法

目录 1--loss.backward()的用法 2--optimizer.step()的用法 3--optimizer.zero_grad()的用法 4--举例说明 5--参考 1--loss.backward()的用法 作用&#xff1a;将损失loss向输入测进行反向传播&#xff1b;这一步会计算所有变量x的梯度值 &#xff0c;并将其累积为 进行备…

迎合国家新政策,共享购联合共享经济,三方互利,消费增值

共享单车打通出行“最后一公里”&#xff0c;共享充电宝让人们出门在外免于“电量烦恼”&#xff0c;共享办公降低办公成本……共享经济已深入到人们日常生活。近日&#xff0c;国家信息中心发布的《中国共享经济发展报告&#xff08;2022&#xff09;》显示&#xff0c;2021年…

EMR-Jindo Spark 核心引擎优化

Jindo-Spark 是阿里云智能E-MapReduce 团队在开源的Apache Spark 基础上自主研发的分布式云原生 OLAP 引擎&#xff0c;已经在近千E-MapReduce 客户中大规模部署使用。Jindo Spark 在开源版本基础上做了大量优化和扩展&#xff0c;深度集成和连接了众多阿里云基础服务。凭借该引…

工作流-流程实例【ProcessInstance】与执行实例【Execution】

一、ProcessInstance与Execution的区别 这是一个Activiti的难点&#xff0c;能够懂得这个&#xff0c;工作流也就入门大半了。 下面&#xff0c;我就细致的讲解一下他们的区别。 &#xff08;1&#xff09;首先&#xff0c;我们来看一张我总结的图片&#xff08;这个图片中两条…

Flink-处理函数以及TopN运用案例

7 处理函数 7.1 概述 更底层的操作&#xff0c;直接对流进行操作&#xff0c;直接调用处理函数 7.2 基本处理函数ProcessFunction 分析 ProcessFunction的来源 处理函数继承了AbstractRichFunction富函数抽象类&#xff0c;因此就具有访问状态(state)和其他运行时环境 例…

Day39——Dp专题

文章目录01背包二维数组一维数组6.整数拆分7.不同的二叉搜索01背包 01背包&#xff1a;每一个物品只能选一次&#xff0c;选或者不选 状态标识&#xff1a;f[i][j]&#xff1a;所有只考虑前i个物品&#xff0c;且总体积不超j的所有选法的集合 属性&#xff1a;Max 状态计算&a…

链表之反转链表

文章目录链表之反转链表题目描述解题思路代码实现链表之反转链表 力扣链接 题目描述 定义一个函数&#xff0c;输入一个链表的头节点&#xff0c;反转该链表并输出反转后链表的头节点。 示例&#xff1a; ​ 输入: 1->2->3->4->5->NULL ​ 输出: 5->4-&…

如何设计高性能架构

高性能复杂度模型 高性能复杂度分析和设计 单机 集群 任务分配 将任务分配给多个服务器执行 复杂度分析 增加“任务分配器”节点&#xff0c;可以是独立的服务器&#xff0c;也可以是SDK任务分配器需要管理所有的服务器&#xff0c;可以通过配置文件&#xff0c;也可以通过…

RK3588移植-opencv交叉编译aarch64

文章参考&#xff1a;https://blog.csdn.net/KayChanGEEK/article/details/80365320 文章目录概括准备资源交叉编译OPENCV修改CMakelist文件将lib库复制到/lib目录注意&#xff1a;本文中的所有配置相关路径都与当前安装的路径有关&#xff0c;需要根据自己的环境进行自行修改&…

『Java课设』JavaSwing+MySQL实现学生成绩管理系统

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位喜欢写作&#xff0c;计科专业大三菜鸟 &#x1f3e1;个人主页&#xff1a;starry陆离 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 『Java课设』JavaSwingMySQL实现学生成绩管理系统前言1.开…

SparkMlib 之随机森林及其案例

文章目录什么是随机森林&#xff1f;随机森林的优缺点随机森林示例——鸢尾花分类什么是随机森林&#xff1f; 随机森林算法是机器学习、计算机视觉等领域内应用极为广泛的一个算法&#xff0c;它不仅可以用来做分类&#xff0c;也可用来做回归即预测&#xff0c;随机森林机由…

RabbitMQ之可靠性分析

在使用任何消息中间件的过程中&#xff0c;难免会出现消息丢失等异常情况&#xff0c;这个时候就需要有一个良好的机制来跟踪记录消息的过程&#xff08;轨迹溯源&#xff09;&#xff0c;帮助我们排查问题。在RabbitMQ 中可以使用Firehose 功能来实现消息追踪&#xff0c;Fire…

艾美捷MTT细胞增殖检测试剂盒结果示例引用文献

艾美捷MTT细胞增殖检测试剂盒测定原理&#xff1a; 该试剂盒提供了比色形式测量和监测细胞增殖&#xff0c;含有足够的试剂用于评估在96孔板中进行960次测定或在24孔板中进行192次测定。细胞可以被镀&#xff0c;然后用影响增殖的化合物或药剂。然后用增殖试剂检测细胞&#x…

3.矩阵计算及导数基础

1. 梯度 将导数拓展到向量。 1. 标量对向量求导 x是列向量&#xff0c;y是标量&#xff0c;求导之后变成了行向量 ps&#xff1a; x1^2 2x2^2 这个函数可以画成等高线,对于&#xff08;x1&#xff0c;x2&#xff09;这个点&#xff0c;可以做等高线的切线&#xff0c;再做出…

Spark Streaming(二)

声明&#xff1a; 文章中代码及相关语句为自己根据相应理解编写&#xff0c;文章中出现的相关图片为自己实践中的截图和相关技术对应的图片&#xff0c;若有相关异议&#xff0c;请联系删除。感谢。转载请注明出处&#xff0c;感谢。 By luoyepiaoxue2014 B站&#xff…

动态规划算法(2)最长回文子串详解

文章目录最长回文字串动态规划代码示例前篇&#xff1a; &#xff08;1&#xff09;初识动态规划 最长回文字串 传送门&#xff1a; https://leetcode.cn/problems/longest-palindromic-substring/description/ 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 s &qu…

大数据学习:使用Java API操作HDFS

文章目录一、创建Maven项目二、添加依赖三、创建日志属性文件四、在HDFS上创建文件五、写入HDFS文件1、将数据直接写入HDFS文件2、将本地文件写入HDFS文件六、读取HDFS文件1、读取HDFS文件直接在控制台显示2、读取HDFS文件&#xff0c;保存为本地文件一、创建Maven项目 二、添加…