/** * @file arm9_isa.cpp * @author Rodrigo Padilha Thaiane Lima Lopes * * The ArchC Team * http://www.archc.org/ * * Computer Systems Laboratory (LSC) * IC-UNICAMP * http://www.lsc.ic.unicamp.br * * @version 1.0 * @date fri, 02 nov 2007 15:33:28 -0300 * * @brief The ArchC arm9 cycle-accurate model. * * @attention Copyright (C) 2002-2006 --- The ArchC Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "archc.H" #include "ac_types.H" #include "ac_parms.H" #include "arm9.H" #include "ac_isa_init.cpp" //!User defined macros to reference registers. #define Ra 31 #define Hi 32 #define Lo 33 // Forwarded values ac_Uword ex_value1, ex_value2; ac_Uword id_value1, id_value2; /************************************************************************/ //!Common pos execution function for all I Type instructions // Copy the pipeline registers contents from the EX_MEM to the MEM_WB #define TYPE_I_MEM_WB_REG_COPY \ MEM_WB.regwrite = EX_MEM.regwrite;\ MEM_WB.rdest = EX_MEM.rdest;\ MEM_WB.wbdata = EX_MEM.alures /************************************************************************/ /************************************************************************/ //!Generic instruction behavior method. void ac_behavior( instruction ){ switch( stage ) { case IF: ac_pc += 4; IF_ID.npc = ac_pc; break; case ID: break; case EX: break; case MEM: break; case WB: /* Execute write back when allowed */ if (MEM_WB.regwrite == 1) { // Register 0 is never written if (MEM_WB.rdest != 0) ){ RB.write(MEM_WB.rdest, MEM_WB.wbdata); } break; default: break; } }; /************************************************************************/ /************************************************************************/ //! Common behaviour for all R Type instructions void ac_behavior( Type_DPI ){ switch( stage ) { case IF: break; case ID: /* Assuming that all R type instructions execute write back. When it is not necessary, the instruction BY ITSELF must clear the regwrite bit on its ID stage */ ID_EX.regwrite = 1; ID_EX.memread = 0; ID_EX.memwrite = 0; ID_EX.npc = IF_ID.npc; ID_EX.rs = rs; ID_EX.rt = rt; ID_EX.rd = rd; /* Checking forwarding for the rs register */ if ( (EX_MEM.regwrite == 1) && (EX_MEM.rdest != 0) && (EX_MEM.rdest == ID_EX.rs) ) id_value1 = EX_MEM.alures.read(); else if ( (MEM_WB.regwrite == 1) && (MEM_WB.rdest != 0) && (MEM_WB.rdest == ID_EX.rs) ) id_value1 = MEM_WB.wbdata.read(); else id_value1 = RB.read(rs); /* Checking forwarding for the rt register */ if ( (EX_MEM.regwrite == 1) && (EX_MEM.rdest != 0) && (EX_MEM.rdest == ID_EX.rt) ) id_value2 = EX_MEM.alures.read(); else if ( (MEM_WB.regwrite == 1) && (MEM_WB.rdest != 0) && (MEM_WB.rdest == ID_EX.rt) ) id_value2 = MEM_WB.wbdata.read(); else id_value2 = RB.read(rt); ID_EX.data1 = id_value1; ID_EX.data2 = id_value2; break; case EX: /* Checking forwarding for the rs register */ if ( (EX_MEM.regwrite == 1) && (EX_MEM.rdest != 0) && (EX_MEM.rdest == ID_EX.rs) ) ex_value1 = EX_MEM.alures; else if ( (MEM_WB.regwrite == 1) && (MEM_WB.rdest != 0) && (MEM_WB.rdest == ID_EX.rs) ) ex_value1 = MEM_WB.wbdata; else ex_value1 = ID_EX.data1; /* Checking forwarding for the rt register */ if ( (EX_MEM.regwrite == 1) && (EX_MEM.rdest != 0) && (EX_MEM.rdest == ID_EX.rt) ) ex_value2 = EX_MEM.alures; else if ( (MEM_WB.regwrite == 1) && (MEM_WB.rdest != 0) && (MEM_WB.rdest == ID_EX.rt) ) ex_value2 = MEM_WB.wbdata; else ex_value2 = ID_EX.data2; break; case MEM: /* Just copies the values from EX_MEM to MEM_WB */ MEM_WB.regwrite = EX_MEM.regwrite; MEM_WB.wbdata = EX_MEM.alures; MEM_WB.rdest = EX_MEM.rdest; break; case WB: break; default: break; } } /!Instruction add behavior method. void ac_behavior( ADD ){ switch( stage ) { case IF: /* It was implemented for all instructions on ac_behaviour( instruction ) */ break; case ID: break; case EX: printf("%d"EX_MEM.alures); if(EX_MEM.alures ==0) EX_MEM.alures = ex_value1 + ex_value2; EX_MEM.alures = ex_value1 + imm; // Overflow test if ( ((ex_value1 & 0x80000000) == (EX_MEM.alures & 0x80000000)) && ((EX_MEM.alures & 0x80000000) != (ex_value2 & 0x80000000)) ) { fprintf(stderr, "EXCEPTION(add): integer overflow.\n"); exit(EXIT_FAILURE); } EX_MEM.regwrite = ID_EX.regwrite; EX_MEM.memread = ID_EX.memread; EX_MEM.memwrite = ID_EX.memwrite; EX_MEM.rdest = ID_EX.rd; break; case MEM: break; case WB: break; default: break; } };//!Instruction sub behavior method. void ac_behavior( SUB ){ switch( stage ) { case IF: break; case ID: break; case EX: printf("%d"EX_MEM.alures); if(EX_MEM.alures ==0) EX_MEM.alures = ex_value1 - ex_value2; EX_MEM.regwrite = ID_EX.regwrite; EX_MEM.memread = ID_EX.memread; EX_MEM.memwrite = ID_EX.memwrite; EX_MEM.rdest = ID_EX.rd; break; case MEM: break; case WB: break; default: break; } }; void ac_behavior( AND ){ switch( stage ) { case IF: /* It was implemented for all instructions on ac_behaviour( instruction ) */ break; case ID: break; case EX: printf("%d"EX_MEM.alures); if(EX_MEM.alures ==0) EX_MEM.alures = ex_value1 & ex_value2; EX_MEM.alures = ex_value1 + imm; // Overflow test if ( ((ex_value1 & 0x80000000) == (EX_MEM.alures & 0x80000000)) && ((EX_MEM.alures & 0x80000000) != (ex_value2 & 0x80000000)) ) { fprintf(stderr, "EXCEPTION(and): integer overflow.\n"); exit(EXIT_FAILURE); } EX_MEM.regwrite = ID_EX.regwrite; EX_MEM.memread = ID_EX.memread; EX_MEM.memwrite = ID_EX.memwrite; EX_MEM.rdest = ID_EX.rd; break; case MEM: break; case WB: break; default: break; } }; void ac_behavior( ORR ){ switch( stage ) { case IF: /* It was implemented for all instructions on ac_behaviour( instruction ) */ break; case ID: break; case EX: printf("%d"EX_MEM.alures); if(EX_MEM.alures ==0) EX_MEM.alures = ex_value1 | ex_value2; EX_MEM.alures = ex_value1 + imm; // Overflow test if ( ((ex_value1 & 0x80000000) == (EX_MEM.alures & 0x80000000)) && ((EX_MEM.alures & 0x80000000) != (ex_value2 & 0x80000000)) ) { fprintf(stderr, "EXCEPTION(orr): integer overflow.\n"); exit(EXIT_FAILURE); } EX_MEM.regwrite = ID_EX.regwrite; EX_MEM.memread = ID_EX.memread; EX_MEM.memwrite = ID_EX.memwrite; EX_MEM.rdest = ID_EX.rd; break; case MEM: break; case WB: break; default: break; } }; void ac_behavior( BIC ){ switch( stage ) { case IF: /* It was implemented for all instructions on ac_behaviour( instruction ) */ break; case ID: break; case EX: printf("%d"EX_MEM.alures); if(EX_MEM.alures ==0) EX_MEM.alures = ex_value1 &~ ex_value2; EX_MEM.alures = ex_value1 + imm; // Overflow test if ( ((ex_value1 & 0x80000000) == (EX_MEM.alures & 0x80000000)) && ((EX_MEM.alures & 0x80000000) != (ex_value2 & 0x80000000)) ) { fprintf(stderr, "EXCEPTION(bic): integer overflow.\n"); exit(EXIT_FAILURE); } EX_MEM.regwrite = ID_EX.regwrite; EX_MEM.memread = ID_EX.memread; EX_MEM.memwrite = ID_EX.memwrite; EX_MEM.rdest = ID_EX.rd; break; case MEM: break; case WB: break; default: break; } }; void ac_behavior( XOR ){ switch( stage ) { case IF: /* It was implemented for all instructions on ac_behaviour( instruction ) */ break; case ID: break; case EX: printf("%d"EX_MEM.alures); if(EX_MEM.alures ==0) EX_MEM.alures = ex_value1 xor ex_value2; EX_MEM.alures = ex_value1 + imm; // Overflow test if ( ((ex_value1 & 0x80000000) == (EX_MEM.alures & 0x80000000)) && ((EX_MEM.alures & 0x80000000) != (ex_value2 & 0x80000000)) ) { fprintf(stderr, "EXCEPTION(xor): integer overflow.\n"); exit(EXIT_FAILURE); } EX_MEM.regwrite = ID_EX.regwrite; EX_MEM.memread = ID_EX.memread; EX_MEM.memwrite = ID_EX.memwrite; EX_MEM.rdest = ID_EX.rd; break; case MEM: break; case WB: break; default: break; } };