CPU设计实战—异常处理指令

异常类型以及精确异常的处理

异常有点像中断,处理完还要回到原来的状态,所以需要对之前的状态进行保存。本CPU主要实现对以下异常的处理:

1.外部硬件中断

2.复位异常

3.系统调用异常(发生在译码阶段)

4.溢出异常(发生在执行阶段)

5.自陷指令异常(发生在执行阶段因为需要进行条件判断)

6.无效指令异常(发生在译码阶段)

为了不破坏原程序的执行,异常指令之前的指令都要确保执行完成,而异常指令和其之后的指令需要取消。这要求异常发生的循序和指令发生的顺序相同。可会有例外吗?

由于流水线的特性,不同指令的异常可能发生在不同阶段。例如:加载指令在访存阶段发生未对齐异常,而下一个指令是无效指令在译码阶段发生异常。无效指令先发生异常,顺序错误。如何解决?

先发生的异常不立即处理,先进行标记,所有的异常统一留到访存阶段进行处理

一、异常处理过程

 异常发生之后进行的处理:

如果发生,先看当前是否处于异常处理阶段(根据状态寄存器的EXL字段);

如果正在异常处理,接着判断是否处于中断阶段,是的话则不处理此中断(异常处理过程会禁止中断);

不是处于中断异常则保存异常原因,进入异常处理例程即可。

如果没有正在进行异常处理:

1.先保存异常原因(Cause寄存器的Execode字段)

2.将保存异常返回地址到EPC(这时候需要判断是否为延迟槽指令?PC-4,BD=1:PC,BD=0)

4.转移到异常处理例程(最后就是根据异常类型确定PC的值是哪一个入口地址)

 EXL表示当前是否在异常状态EPC保存异常返回地址BD是当发生异常的指令在分支延迟槽时被置位

 如果异常指令是延迟槽指令,那么也必须执行上一条转移指令(PC-4)

二、实现思路

我们先在译码(系统调用,无效,异常返回)执行阶段(自陷,溢出)判断是否有相关异常发生并传递给访存阶段对不同异常结合CP0寄存器进行具体判断。如果需要处理,就转移到异常处理入口地址(在异常向量表中有定义),同时需要清除回写阶段前的所有寄存器

自陷异常

通过条件判断是否发生异常,如果发生就进入异常处理例程

 系统调用异常

当我们想要切换工作模式(比如获得更高权限进入内核模式),通过调用系统异常指令来实现修改工作模式状态位:即CP0中Status的UM字段。但是本CPU没有实现其他模式。

系统异常返回

作用是返回异常出现之前的指令,异常结束,具体操作为:

1.EPC寄存器(存储异常指令地址)的值给到PC

2.清除异常状态(EXL字段清零)

三 具体实现思路

1.在各个阶段(译码阶段需要判断延迟槽)收集异常状态将信号(异常判断信号与异常地址)传送到访存阶段

2.访存阶段判断异常是否处理(需要根据CP0中的一些寄存器):

需要处理:进入异常地址(如果是异常返回指令则进入EPC的地址);清除之前阶段;修改CP0(进入异常状态等)

四 各个阶段具体实现

1.PC阶段

如果异常到来就使用新的PC值

	  end else if(stall[1] == `NoStop) begin
		  id_pc <= if_pc;
		  id_inst <= if_inst;

2.各个寄存器阶段

如果异常来临把所有输出信号赋初始值

		end else if(flush == 1'b1 ) begin
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;
			ex_excepttype <= `ZeroWord;
			ex_link_address <= `ZeroWord;
			ex_inst <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;
	    ex_current_inst_address <= `ZeroWord;	
	    is_in_delayslot_o <= `NotInDelaySlot;	

3.译码阶段

对指令进行译码,如果是异常指令保存状态:如系统调用异常返回,自陷指令在执行阶段还要进行条件判断所以这里不记录

然后把异常状态都保存到一个信号中

//exceptiontype的低8bit留给外部中断,第9bit表示是否是syscall指令
  //第10bit表示是否是无效指令,第11bit表示是否是trap指令
  assign excepttype_o = {19'b0,excepttype_is_eret,2'b0,
  						instvalid, excepttype_is_syscall,8'b0};

4.执行阶段

判断执行阶段里的异常状态:如溢出自陷指令条件判断并把相关信号输出:

assign excepttype_o = {excepttype_i[31:12],ovassert,trapassert,excepttype_i[9:8],8'h00};

5.访存阶段

主要目的是进一步判断是否要发生异常类型(结合CP0中的信号判断)以及具体哪个异常

什么时候发生异常:复位,异常和暂停情况不处理异常,所以取指地址不为0才发生异常

区分是哪个异常类型(不能只根据传过来的异常类型,因为有些还需要CP0中的额外条件):

中断异常:当处于中断或者异常情况下不处理中断

发生中断的依据是: Cause 寄存器的IP字段不为0,且Status寄存器中相应的中断掩码字段IM也不为0,另外,Status 寄存器的EXL字段为0,表示不处于异常处理过程中,Status 寄存器的IE字段为1,表示中断使能。

其他异常类型没有额外条件,只要之前异常触发了就可以。

			
			if(current_inst_address_i != `ZeroWord) begin
				if(((cp0_cause[15:8] & (cp0_status[15:8])) != 8'h00) && 
(cp0_status[1] == 1'b0) && (cp0_status[0] == 1'b1)) begin
					excepttype_o <= 32'h00000001;        //interrupt
				end else if(excepttype_i[8] == 1'b1) begin
			  	excepttype_o <= 32'h00000008;        //syscall
				end else if(excepttype_i[9] == 1'b1) begin
					excepttype_o <= 32'h0000000a;        //inst_invalid
				end else if(excepttype_i[10] ==1'b1) begin
					excepttype_o <= 32'h0000000d;        //trap
				end else if(excepttype_i[11] == 1'b1) begin  //ov
					excepttype_o <= 32'h0000000c;
				end else if(excepttype_i[12] == 1'b1) begin  //返回指令
					excepttype_o <= 32'h0000000e;
				end
			end

 具体每个异常类型对应的输出回顾译码和执行阶段做的定义:

 到这一步才算完成对异常类型的判断!!!

下面是根据不同的异常类型做不同的操作,主要是给修改PC以及寄存器

6.根据不同的异常类型修改CP0的值(主要记载返回地址和返回原因)

CP0中重要寄存器作用:

1.EPC是异常程序计数器(Exception Program Counter),用来存储异常返回地址,一般情况下,存储发生异常的指令的地址,但是,如果发生异常的指令位于延迟槽中,那么EPC存储的是前一条转移指令的地址。该寄存器可读、可写。

2.cause寄存器的BD字段
当发生异常的指令处于分支延迟槽(Branch DelaySlot)时,该字段被置为1。ExeCode是表示异常原因

3.Status寄存器的EXL字段

表示是否处于异常级( Exception Level), 当异常发生时,会设置本字段为1,表示处理器处于异常级,此时,处理器会进入内核模式下工作,并且禁止中断。

中断指令:

依据发生异常的指令是否位于延迟槽中,保存返回地址设置EPC寄存器的值,以及Status 寄存器的BD字段,如果位于延迟槽中,那么设置EPC寄存器为上一条指令的地址,Status 寄存器的BD字段为1,反之,设置EPC寄存器为发生异常指令的地址,Status寄存器的BD字段为0。另外,设置异常状态设置Status 寄存器的EXL字段为I,表示处于异常级,中断禁止。最后,保存返回原因设置Cause寄存器的ExcCode字段5'b00000,表示异常原因是中断。

系统调用异常:

分两种情况。
(1)如果Status寄存器的EXL字段为0,那么依据发生异常的指令是否位于延迟槽中,设置EPC寄存器的值,以及Status寄存器的BD字段。如果位于延迟槽中,那么设置EPC寄存器为上一条指令的地址,Status 寄存器的BD字段为1,反之,设置EPC寄存器为发生异常指令的地址,Status 寄存器的BD字段为0。然后,设置Status寄存器的EXL字段为1,表示处于异常级,中断禁止。最后,设置Cause寄存器的ExcCode字段为5"b01000,表示异常原因是系统调用指令syscall,参考第10章的表10-7。
(2)如果Status寄存器的EXL字段为1,表示当前已经处于异常级了,又发生了新的异常,那么只需要将异常原因保存到Cause寄存器的ExcCode字段,此处设置为5'b01000,表示异常原因是系统调用指令syscall。

3.无效指令异常
与系统调用异常的处理过程类似,只是设置Status寄存器的ExcCode字段为5"b01010,表示异常原因是无效指令。
4.自陷异常
与系统调用异常的处理过程类似,只是设置Status寄存器的ExcCode字段为5'b01101,表示异常原因是自陷. 
5.溢出异常
与系统调用异常的处理过程类似,只是设置Status寄存器的ExcCode字段为5'b01100,表示异常原因是溢出。
6.异常返回指令eret
清除Status寄存器的IE字段,表示中断允许。

6.控制模块

根据异常类型给出下一个PC应有的值,这个值根据异常处理入口例程;

如果是异常返回地址,则跳转到异常返回地址

	always @ (*) begin
		if(rst == `RstEnable) begin
			stall <= 6'b000000;
			flush <= 1'b0;
			new_pc <= `ZeroWord;
		end else if(excepttype_i != `ZeroWord) begin
		  flush <= 1'b1;
		  stall <= 6'b000000;
			case (excepttype_i)
				32'h00000001:		begin   //interrupt
					new_pc <= 32'h00000020;
				end
				32'h00000008:		begin   //syscall
					new_pc <= 32'h00000040;
				end
				32'h0000000a:		begin   //inst_invalid
					new_pc <= 32'h00000040;
				end
				32'h0000000d:		begin   //trap
					new_pc <= 32'h00000040;
				end
				32'h0000000c:		begin   //ov
					new_pc <= 32'h00000040;
				end
				32'h0000000e:		begin   //eret
					new_pc <= cp0_epc_i;
				end
				default	: begin
				end
			endcase 						
		end else if(stallreq_from_ex == `Stop) begin
			stall <= 6'b001111;
			flush <= 1'b0;		
		end else if(stallreq_from_id == `Stop) begin
			stall <= 6'b000111;	
			flush <= 1'b0;		
		end else begin
			stall <= 6'b000000;
			flush <= 1'b0;
			new_pc <= `ZeroWord;		
		end    //if
	end      //always

7.定时中断的结构实现

将时钟中断输出作为一个中断信号输入,这样就可以处理时钟中断了,从而验证异常相关指令是否实现正确。
 

8、测试程序

系统调用异常测试程序

 当指令根据系统调用异常的指示入口地址跳转到这里后,需要自己写代码去进行在EPC内进行PC+4的操作,不然等异常返回指令后PC按照EPC内的值跳转后还是在系统调用指令处继续异常。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring6--基于注解管理Bean / 手写IOC

1. 基于注入管理Bean概念 Java 5 引入了注解&#xff08;Annotation&#xff09;这一特性&#xff0c;它允许程序员在源代码中插入元数据&#xff0c;这些元数据以标签形式存在&#xff0c;可以被编译器、类加载器或运行时环境所识别和处理。注解可以帮助开发者在不修改业务逻…

flex属性详解

flex布局&#xff0c;父元素属性可参考&#xff1a;flex布局 &#xff0c;本文主要介绍flex添加到子元素的属性。 <div class"father"><div class"left"></div><div class"middle"></div><div class"midd…

【01】htmlcssgit网络基础知识

一、html&css 防脱发神器 一图胜千言 使用border-box控制尺寸更加直观,因此,很多网站都会加入下面的代码 * {margin: 0;padding: 0;box-sizing: border-box; }颜色的 alpha 通道 颜色的 alpha 通道标识了色彩的透明度,它是一个 0~1 之间的取值,0 标识完全透明,1…

香港科技大学(广州)先进材料学域智能制造学域可持续能源与环境学域博士招生宣讲会——北京航空航天大学专场(暨全额奖学金政策)

香港科技大学&#xff08;广州&#xff09;先进材料学域&智能制造学域&可持续能源与环境学域博士招生宣讲会——北京航空航天大学专场&#xff08;暨全额奖学金政策&#xff09; 三个学域代表教授亲临现场&#xff0c;面对面答疑解惑助攻申请&#xff01;可带简历现场…

恒驰喜讯 | 亮相华为中国合作伙伴大会2024,荣膺最佳服务一致性奖等3大奖项

3月14日至15日&#xff0c;华为中国合作伙伴大会2024在深圳隆重召开。大会以“因聚而生&#xff0c;数智有为”为主题&#xff0c;面向数智化转型的浪潮&#xff0c;华为携手伙伴共同探讨如何通过强化“伙伴华为”体系&#xff0c;帮助客户抓住数智化转型的巨大机遇&#xff0c…

python-pandas基础学习

可参考&#xff1a; pandas&#xff1a;http://pandas.pydata.org/docs/user_guide/10min.html 一、基础知识 DataFrame 方法&#xff0c;可以将一组数据&#xff08;ndarray、series, map, list, dict 等类型&#xff09;转化为表格型数据 import pandas as pd data {name: …

第十五届蓝桥杯模拟考试III_物联网设计与开发官方代码分析

目录 前言&#xff1a;显示界面部分&#xff1a;页面切换:数值的轮回调整&#xff1a;传递数据&#xff1a; 前言&#xff1a; 这次模拟的效果很不好。85分&#xff0c;4h的限时我花了两天完成&#xff0c;这个时间是远远超出要求的&#xff0c;而且最后还只拿到56分&#xff0…

Java使用Selenium实现自动化测试以及全功能爬虫

前言 工作中需要抓取一下某音频网站的音频&#xff0c;我就用了两个小时学习弄了一下&#xff0c;竟然弄出来&#xff0c;这里分享记录一下。 springboot项目 Selenium Java使用Selenium实现自动化测试以及全功能爬虫 前言1 自动化测试2 java中集成Selenium3 添加浏览器驱动4…

什么是大型语言模型(LLM)?

大型语言模型 (LLM) 是一种能够理解和生成人类语言文本的机器学习模型。它们通过分析大量语言数据集来工作。 一、什么是大型语言模型 (LLM)&#xff1f; 大型语言模型 (LLM) 是一种人工智能 (AI) 程序&#xff0c;它可以识别和生成文本以及完成其他任务。LLM 经过了庞大的数据…

Xilinx LVDS ISERDESE2

ISERDESE2 7 系列 FPGA 是一款专用的串行到并行转换器,具有特定的时钟和逻辑功能,旨在促进高速源同步应用的实现。该ISERDESE2避免了在FPGA架构中设计解串器时遇到的额外时序复杂性. ISERDESE2功能包括: 1,专用解串器/串行转换器 ISERDESE2解串器可实现高速数据传输,而无需…

ssh免密登陆更换目标主机后无法连接

在进行hadoop分布式环境搭建时&#xff08;三台机&#xff0c;master&#xff0c;slave1&#xff0c;slave2&#xff09;&#xff0c;后期slave2系统出现问题&#xff0c;更换新机后&#xff0c;master与slave2文件传输失败&#xff1a; 以为是秘钥过期的问题&#xff0c;更换…

【好书推荐2】AI提示工程实战:从零开始利用提示工程学习应用大语言模型

【好书推荐2】AI提示工程实战&#xff1a;从零开始利用提示工程学习应用大语言模型 写在最前面AI辅助研发方向一&#xff1a;AI辅助研发的技术进展方向二&#xff1a;行业应用案例方向三&#xff1a;面临的挑战与机遇方向四&#xff1a;未来趋势预测方向五&#xff1a;与法规的…

动态规划(算法竞赛、蓝桥杯)--单调队列优化修建草坪

1、B站视频链接&#xff1a;E44 单调队列优化DP 修剪草坪_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; typedef long long LL; const int N1e510; int n,k,q[N]; LL w[N],f[N],sum;int main(){cin>>n>>k; k; //for(int i1;i<n;i){ci…

爬虫技术实战案例解析

目录 前言 案例背景 案例实现 案例总结 结语 前言 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊爬虫技术实战案例解析&#xff0c;希望大家能觉得实用&#xff01; 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1…

【FPGA】摄像头模块OV5640

本篇文章包含的内容 一、OV5640简介1.1 基本概述1.2 工作时序1.2.1 DVP Timing&#xff08;数据传输时序&#xff09;1.2.2 帧曝光工作模式 1.3 OV5640 闪光灯工作模式1.3.1 Xenon Flash&#xff08;氙灯闪烁&#xff09;模式1.3.2 LED 1&2 模式1.3.3 LED 3模式1.3.4 手动开…

milvus安装

milvus安装 sudo curl -L “https://github.com/docker/compose/releases/download/1.29.2/docker-compose- $ (uname -s)- $ (uname -m)” -o /usr/local/bin/docker-compose sudo chmod x /usr/local/bin/docker-compose sudo ln -s /usr/local/bin/docker-compose /usr/bin/…

Leetcode992-K个不同整数的子数组[两种方法] 关键词 滑窗

文章目录 题目方法一&#xff1a;滑窗右端每次1&#xff0c;左端来回滑动方法二&#xff1a;&#xff08;最多K种的子串数&#xff09; - &#xff08;最多K-1种的子串数&#xff09; 恰好K种 题目 1 < nums.length < 20000 1 < nums[i], k < nums.length 方法一…

Pytest 教程:从 0 到 1 搭建 Pytest 接口自动化测试项目

从 0 到 1 搭建 Pytest 接口自动化测试项目 1.创建项目目录 mkdir Pytest-API-Testing-Demo 2.项目初始化 // 进入项目文件夹下cd Pytest-API-Testing-Demo// 创建项目 python 项目虚拟环境python -m venv .env// 启用项目 python 项目虚拟环境source .env/bin/activate 3…

【InternLM 笔记】OpenXLAB浦源的基本操作

OpenXLab网址 网址&#xff1a;OpenXLab浦源 模型 创建模型 页面右上角选择【创建】然后选择【创建模型】 创建模型的页面如下 感觉页面中的提示信息填写相应的内容&#xff0c;全部填完后点页面下方的【立即创建】完成模型的创建 模型上传 安装所需的工具 apt install …

最全参赛指南!2024 年(第 17 届)中国大学生计算机设计大赛大数据主题赛现已开赛

2024 年&#xff08;第 17 届&#xff09;中国大学生计算机设计大赛大数据主题赛“数据解读乡村发展”赛题已于和鲸平台正式开赛&#xff0c;一个月来&#xff0c;全国已有超百所高校近千位优秀本科生积极响应大赛号召完成报名。 为进一步助力广大师生顺利参赛&#xff0c;和鲸…