專注做一家男生最愛的網(wǎng)站百度代發(fā)排名
異常類型以及精確異常的處理
異常有點(diǎn)像中斷,處理完還要回到原來的狀態(tài),所以需要對(duì)之前的狀態(tài)進(jìn)行保存。本CPU主要實(shí)現(xiàn)對(duì)以下異常的處理:
1.外部硬件中斷
2.復(fù)位異常
3.系統(tǒng)調(diào)用異常(發(fā)生在譯碼階段)
4.溢出異常(發(fā)生在執(zhí)行階段)
5.自陷指令異常(發(fā)生在執(zhí)行階段因?yàn)樾枰M(jìn)行條件判斷)
6.無效指令異常(發(fā)生在譯碼階段)
為了不破壞原程序的執(zhí)行,異常指令之前的指令都要確保執(zhí)行完成,而異常指令和其之后的指令需要取消。這要求異常發(fā)生的循序和指令發(fā)生的順序相同??蓵?huì)有例外嗎?
由于流水線的特性,不同指令的異??赡馨l(fā)生在不同階段。例如:加載指令在訪存階段發(fā)生未對(duì)齊異常,而下一個(gè)指令是無效指令在譯碼階段發(fā)生異常。無效指令先發(fā)生異常,順序錯(cuò)誤。如何解決?
先發(fā)生的異常不立即處理,先進(jìn)行標(biāo)記,所有的異常統(tǒng)一留到訪存階段進(jìn)行處理。
一、異常處理過程
?異常發(fā)生之后進(jìn)行的處理:
如果發(fā)生,先看當(dāng)前是否處于異常處理階段(根據(jù)狀態(tài)寄存器的EXL字段);
如果正在異常處理,接著判斷是否處于中斷階段,是的話則不處理此中斷(異常處理過程會(huì)禁止中斷);
不是處于中斷異常則保存異常原因,進(jìn)入異常處理例程即可。
如果沒有正在進(jìn)行異常處理:
1.先保存異常原因(Cause寄存器的Execode字段)
2.將保存異常返回地址到EPC(這時(shí)候需要判斷是否為延遲槽指令?PC-4,BD=1:PC,BD=0)
4.轉(zhuǎn)移到異常處理例程(最后就是根據(jù)異常類型確定PC的值是哪一個(gè)入口地址)
?EXL表示當(dāng)前是否在異常狀態(tài),EPC保存異常返回地址,BD是當(dāng)發(fā)生異常的指令在分支延遲槽時(shí)被置位
?如果異常指令是延遲槽指令,那么也必須執(zhí)行上一條轉(zhuǎn)移指令(PC-4)
二、實(shí)現(xiàn)思路
我們先在譯碼(系統(tǒng)調(diào)用,無效,異常返回)執(zhí)行階段(自陷,溢出)判斷是否有相關(guān)異常發(fā)生并傳遞給訪存階段對(duì)不同異常結(jié)合CP0寄存器進(jìn)行具體判斷。如果需要處理,就轉(zhuǎn)移到異常處理入口地址(在異常向量表中有定義),同時(shí)需要清除回寫階段前的所有寄存器。
自陷異常
通過條件判斷是否發(fā)生異常,如果發(fā)生就進(jìn)入異常處理例程
?系統(tǒng)調(diào)用異常
當(dāng)我們想要切換工作模式(比如獲得更高權(quán)限進(jìn)入內(nèi)核模式),通過調(diào)用系統(tǒng)異常指令來實(shí)現(xiàn)修改工作模式狀態(tài)位:即CP0中Status的UM字段。但是本CPU沒有實(shí)現(xiàn)其他模式。
系統(tǒng)異常返回
作用是返回異常出現(xiàn)之前的指令,異常結(jié)束,具體操作為:
1.EPC寄存器(存儲(chǔ)異常指令地址)的值給到PC
2.清除異常狀態(tài)(EXL字段清零)
三 具體實(shí)現(xiàn)思路
1.在各個(gè)階段(譯碼階段需要判斷延遲槽)收集異常狀態(tài)將信號(hào)(異常判斷信號(hào)與異常地址)傳送到訪存階段
2.訪存階段判斷異常是否處理(需要根據(jù)CP0中的一些寄存器):
需要處理:進(jìn)入異常地址(如果是異常返回指令則進(jìn)入EPC的地址);清除之前階段;修改CP0(進(jìn)入異常狀態(tài)等)
四 各個(gè)階段具體實(shí)現(xiàn)
1.PC階段
如果異常到來就使用新的PC值
end else if(stall[1] == `NoStop) beginid_pc <= if_pc;id_inst <= if_inst;
2.各個(gè)寄存器階段
如果異常來臨把所有輸出信號(hào)賦初始值
end else if(flush == 1'b1 ) beginex_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.譯碼階段
對(duì)指令進(jìn)行譯碼,如果是異常指令保存狀態(tài):如系統(tǒng)調(diào)用,異常返回,自陷指令在執(zhí)行階段還要進(jìn)行條件判斷所以這里不記錄
然后把異常狀態(tài)都保存到一個(gè)信號(hào)中
//exceptiontype的低8bit留給外部中斷,第9bit表示是否是syscall指令//第10bit表示是否是無效指令,第11bit表示是否是trap指令assign excepttype_o = {19'b0,excepttype_is_eret,2'b0,instvalid, excepttype_is_syscall,8'b0};
4.執(zhí)行階段
判斷執(zhí)行階段里的異常狀態(tài):如溢出,自陷指令條件判斷并把相關(guān)信號(hào)輸出:
assign excepttype_o = {excepttype_i[31:12],ovassert,trapassert,excepttype_i[9:8],8'h00};
5.訪存階段
主要目的是進(jìn)一步判斷是否要發(fā)生異常類型(結(jié)合CP0中的信號(hào)判斷)以及具體哪個(gè)異常
什么時(shí)候發(fā)生異常:復(fù)位,異常和暫停情況不處理異常,所以取指地址不為0才發(fā)生異常
區(qū)分是哪個(gè)異常類型(不能只根據(jù)傳過來的異常類型,因?yàn)橛行┻€需要CP0中的額外條件):
中斷異常:當(dāng)處于中斷或者異常情況下不處理中斷:
發(fā)生中斷的依據(jù)是: Cause 寄存器的IP字段不為0,且Status寄存器中相應(yīng)的中斷掩碼字段IM也不為0,另外,Status 寄存器的EXL字段為0,表示不處于異常處理過程中,Status 寄存器的IE字段為1,表示中斷使能。
其他異常類型沒有額外條件,只要之前異常觸發(fā)了就可以。
if(current_inst_address_i != `ZeroWord) beginif(((cp0_cause[15:8] & (cp0_status[15:8])) != 8'h00) &&
(cp0_status[1] == 1'b0) && (cp0_status[0] == 1'b1)) beginexcepttype_o <= 32'h00000001; //interruptend else if(excepttype_i[8] == 1'b1) beginexcepttype_o <= 32'h00000008; //syscallend else if(excepttype_i[9] == 1'b1) beginexcepttype_o <= 32'h0000000a; //inst_invalidend else if(excepttype_i[10] ==1'b1) beginexcepttype_o <= 32'h0000000d; //trapend else if(excepttype_i[11] == 1'b1) begin //ovexcepttype_o <= 32'h0000000c;end else if(excepttype_i[12] == 1'b1) begin //返回指令excepttype_o <= 32'h0000000e;endend
?具體每個(gè)異常類型對(duì)應(yīng)的輸出回顧譯碼和執(zhí)行階段做的定義:
?到這一步才算完成對(duì)異常類型的判斷!!!
下面是根據(jù)不同的異常類型做不同的操作,主要是給修改PC以及寄存器
6.根據(jù)不同的異常類型修改CP0的值(主要記載返回地址和返回原因)
CP0中重要寄存器作用:
1.EPC是異常程序計(jì)數(shù)器(Exception Program Counter),用來存儲(chǔ)異常返回地址,一般情況下,存儲(chǔ)發(fā)生異常的指令的地址,但是,如果發(fā)生異常的指令位于延遲槽中,那么EPC存儲(chǔ)的是前一條轉(zhuǎn)移指令的地址。該寄存器可讀、可寫。
2.cause寄存器的BD字段
當(dāng)發(fā)生異常的指令處于分支延遲槽(Branch DelaySlot)時(shí),該字段被置為1。ExeCode是表示異常原因
3.Status寄存器的EXL字段
表示是否處于異常級(jí)( Exception Level), 當(dāng)異常發(fā)生時(shí),會(huì)設(shè)置本字段為1,表示處理器處于異常級(jí),此時(shí),處理器會(huì)進(jìn)入內(nèi)核模式下工作,并且禁止中斷。
中斷指令:
依據(jù)發(fā)生異常的指令是否位于延遲槽中,保存返回地址設(shè)置EPC寄存器的值,以及Status 寄存器的BD字段,如果位于延遲槽中,那么設(shè)置EPC寄存器為上一條指令的地址,Status 寄存器的BD字段為1,反之,設(shè)置EPC寄存器為發(fā)生異常指令的地址,Status寄存器的BD字段為0。另外,設(shè)置異常狀態(tài)設(shè)置Status 寄存器的EXL字段為I,表示處于異常級(jí),中斷禁止。最后,保存返回原因設(shè)置Cause寄存器的ExcCode字段5'b00000,表示異常原因是中斷。
系統(tǒng)調(diào)用異常:
分兩種情況。
(1)如果Status寄存器的EXL字段為0,那么依據(jù)發(fā)生異常的指令是否位于延遲槽中,設(shè)置EPC寄存器的值,以及Status寄存器的BD字段。如果位于延遲槽中,那么設(shè)置EPC寄存器為上一條指令的地址,Status 寄存器的BD字段為1,反之,設(shè)置EPC寄存器為發(fā)生異常指令的地址,Status 寄存器的BD字段為0。然后,設(shè)置Status寄存器的EXL字段為1,表示處于異常級(jí),中斷禁止。最后,設(shè)置Cause寄存器的ExcCode字段為5"b01000,表示異常原因是系統(tǒng)調(diào)用指令syscall,參考第10章的表10-7。
(2)如果Status寄存器的EXL字段為1,表示當(dāng)前已經(jīng)處于異常級(jí)了,又發(fā)生了新的異常,那么只需要將異常原因保存到Cause寄存器的ExcCode字段,此處設(shè)置為5'b01000,表示異常原因是系統(tǒng)調(diào)用指令syscall。
3.無效指令異常
與系統(tǒng)調(diào)用異常的處理過程類似,只是設(shè)置Status寄存器的ExcCode字段為5"b01010,表示異常原因是無效指令。
4.自陷異常
與系統(tǒng)調(diào)用異常的處理過程類似,只是設(shè)置Status寄存器的ExcCode字段為5'b01101,表示異常原因是自陷.?
5.溢出異常
與系統(tǒng)調(diào)用異常的處理過程類似,只是設(shè)置Status寄存器的ExcCode字段為5'b01100,表示異常原因是溢出。
6.異常返回指令eret
清除Status寄存器的IE字段,表示中斷允許。
6.控制模塊
根據(jù)異常類型給出下一個(gè)PC應(yīng)有的值,這個(gè)值根據(jù)異常處理入口例程;
如果是異常返回地址,則跳轉(zhuǎn)到異常返回地址
always @ (*) beginif(rst == `RstEnable) beginstall <= 6'b000000;flush <= 1'b0;new_pc <= `ZeroWord;end else if(excepttype_i != `ZeroWord) beginflush <= 1'b1;stall <= 6'b000000;case (excepttype_i)32'h00000001: begin //interruptnew_pc <= 32'h00000020;end32'h00000008: begin //syscallnew_pc <= 32'h00000040;end32'h0000000a: begin //inst_invalidnew_pc <= 32'h00000040;end32'h0000000d: begin //trapnew_pc <= 32'h00000040;end32'h0000000c: begin //ovnew_pc <= 32'h00000040;end32'h0000000e: begin //eretnew_pc <= cp0_epc_i;enddefault : beginendendcase end else if(stallreq_from_ex == `Stop) beginstall <= 6'b001111;flush <= 1'b0; end else if(stallreq_from_id == `Stop) beginstall <= 6'b000111; flush <= 1'b0; end else beginstall <= 6'b000000;flush <= 1'b0;new_pc <= `ZeroWord; end //ifend //always
7.定時(shí)中斷的結(jié)構(gòu)實(shí)現(xiàn)
將時(shí)鐘中斷輸出作為一個(gè)中斷信號(hào)輸入,這樣就可以處理時(shí)鐘中斷了,從而驗(yàn)證異常相關(guān)指令是否實(shí)現(xiàn)正確。
?
8、測(cè)試程序
系統(tǒng)調(diào)用異常測(cè)試程序
?當(dāng)指令根據(jù)系統(tǒng)調(diào)用異常的指示入口地址跳轉(zhuǎn)到這里后,需要自己寫代碼去進(jìn)行在EPC內(nèi)進(jìn)行PC+4的操作,不然等異常返回指令后PC按照EPC內(nèi)的值跳轉(zhuǎn)后還是在系統(tǒng)調(diào)用指令處繼續(xù)異常。