[Avida-SVN] r2778 - in branches/interrupt: Avida.xcodeproj source/cpu

beckma24 at myxo.css.msu.edu beckma24 at myxo.css.msu.edu
Fri Sep 12 20:41:20 PDT 2008


Author: beckma24
Date: 2008-09-12 23:41:19 -0400 (Fri, 12 Sep 2008)
New Revision: 2778

Modified:
   branches/interrupt/Avida.xcodeproj/project.pbxproj
   branches/interrupt/source/cpu/cHardwareCPU.cc
   branches/interrupt/source/cpu/cHardwareCPU.h
Log:
First step in creating message received and movement interrupts.  Implemented methods to perform context switching between normal thread execution and interrupt handlers.  Currently, the only limit on the interrupt queue size in the interrupted organism's received message buffer size.  Still need to hook context switching into move and receive message instruction.

Modified: branches/interrupt/Avida.xcodeproj/project.pbxproj
===================================================================
--- branches/interrupt/Avida.xcodeproj/project.pbxproj	2008-09-12 22:20:51 UTC (rev 2777)
+++ branches/interrupt/Avida.xcodeproj/project.pbxproj	2008-09-13 03:41:19 UTC (rev 2778)
@@ -205,6 +205,8 @@
 		B4FA258A0C5EB65E0086D4B5 /* cPlasticPhenotype.cc in Sources */ = {isa = PBXBuildFile; fileRef = B4FA25810C5EB6510086D4B5 /* cPlasticPhenotype.cc */; };
 		B4FA25A90C5EB7880086D4B5 /* cPhenPlastGenotype.cc in Sources */ = {isa = PBXBuildFile; fileRef = B4FA259E0C5EB7600086D4B5 /* cPhenPlastGenotype.cc */; };
 		B516AF840C91E2D400023D53 /* cDemeCellEvent.cc in Sources */ = {isa = PBXBuildFile; fileRef = B516AF790C91E24600023D53 /* cDemeCellEvent.cc */; };
+		BB723EEE0E7B4DE9004461EB /* cOrganismThread.h in Headers */ = {isa = PBXBuildFile; fileRef = BB723EEC0E7B4DE9004461EB /* cOrganismThread.h */; };
+		BB723EEF0E7B4DE9004461EB /* cOrganismThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB723EED0E7B4DE9004461EB /* cOrganismThread.cpp */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXBuildRule section */
@@ -845,6 +847,8 @@
 		B4FA259E0C5EB7600086D4B5 /* cPhenPlastGenotype.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cPhenPlastGenotype.cc; sourceTree = "<group>"; };
 		B516AF790C91E24600023D53 /* cDemeCellEvent.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = cDemeCellEvent.cc; path = source/main/cDemeCellEvent.cc; sourceTree = SOURCE_ROOT; };
 		B516AF7A0C91E24600023D53 /* cDemeCellEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = cDemeCellEvent.h; path = source/main/cDemeCellEvent.h; sourceTree = SOURCE_ROOT; };
+		BB723EEC0E7B4DE9004461EB /* cOrganismThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cOrganismThread.h; sourceTree = "<group>"; };
+		BB723EED0E7B4DE9004461EB /* cOrganismThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cOrganismThread.cpp; sourceTree = "<group>"; };
 		DCC30FCF0762539D008F7A48 /* Doxyfile */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Doxyfile; sourceTree = "<group>"; };
 		DCC3109C0762539E008F7A48 /* avida.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = avida.cc; sourceTree = "<group>"; };
 		DCC31547076253A4008F7A48 /* cCycleCheck.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cCycleCheck.cc; sourceTree = "<group>"; };
@@ -1352,6 +1356,8 @@
 		DCC30F7C0762539D008F7A48 /* cpu */ = {
 			isa = PBXGroup;
 			children = (
+				BB723EEC0E7B4DE9004461EB /* cOrganismThread.h */,
+				BB723EED0E7B4DE9004461EB /* cOrganismThread.cpp */,
 				70B1A64F0B7E237F00067486 /* cHardwareExperimental.cc */,
 				705261050B87AF5C0007426F /* cInstLib.h */,
 				706C703E0B83FB95003174C1 /* tInstLibEntry.h */,
@@ -1669,6 +1675,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				2A57A4000D6B954D00FC54C7 /* cProbDemeProbSchedule.h in Headers */,
+				BB723EEE0E7B4DE9004461EB /* cOrganismThread.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2020,6 +2027,7 @@
 				70A778390D69D5CA00735F1E /* cDemeProbSchedule.cc in Sources */,
 				2A57A3FF0D6B954D00FC54C7 /* cProbDemeProbSchedule.cc in Sources */,
 				70EFD6600D975B6E00FAD32A /* cConstBurstSchedule.cc in Sources */,
+				BB723EEF0E7B4DE9004461EB /* cOrganismThread.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: branches/interrupt/source/cpu/cHardwareCPU.cc
===================================================================
--- branches/interrupt/source/cpu/cHardwareCPU.cc	2008-09-12 22:20:51 UTC (rev 2777)
+++ branches/interrupt/source/cpu/cHardwareCPU.cc	2008-09-13 03:41:19 UTC (rev 2778)
@@ -416,7 +416,11 @@
     tInstLibEntry<tMethod>("alarm-label-high", &cHardwareCPU::Inst_Alarm_Label),
     tInstLibEntry<tMethod>("alarm-label-low", &cHardwareCPU::Inst_Alarm_Label),
 
-
+		// Interrupt
+    tInstLibEntry<tMethod>("MSG_received_handler_START", &cHardwareCPU::Inst_MSG_received_handler_START),
+    tInstLibEntry<tMethod>("Moved_handler_START", &cHardwareCPU::Inst_Moved_handler_START),
+    tInstLibEntry<tMethod>("interrupt_handler_END", &cHardwareCPU::Inst_interrupt_handler_END),
+		
     // Placebo instructions
     tInstLibEntry<tMethod>("skip", &cHardwareCPU::Inst_Skip),
 
@@ -528,7 +532,7 @@
   m_threads.Resize(1);
   
   // Reset that single thread.
-  m_threads[0].Reset(this, 0);
+  m_threads[0].Reset(m_world, this, 0);
   m_thread_id_chart = 1; // Mark only the first thread as taken...
   m_cur_thread = 0;
   
@@ -566,7 +570,7 @@
   }
 }
 
-void cHardwareCPU::cLocalThread::operator=(const cLocalThread& in_thread)
+void cLocalThread::operator=(const cLocalThread& in_thread)
 {
   m_id = in_thread.m_id;
   for (int i = 0; i < NUM_REGISTERS; i++) reg[i] = in_thread.reg[i];
@@ -574,8 +578,9 @@
   stack = in_thread.stack;
 }
 
-void cHardwareCPU::cLocalThread::Reset(cHardwareBase* in_hardware, int in_id)
+void cLocalThread::Reset(cWorld* world, cHardwareCPU* in_hardware, int in_id)
 {
+	m_world = world;
   m_id = in_id;
   
   for (int i = 0; i < NUM_REGISTERS; i++) reg[i] = 0;
@@ -587,6 +592,8 @@
   read_label.Clear();
   next_label.Clear();
   
+	interrupted = false;
+	
   // Promoter model
   m_promoter_inst_executed = 0;
 }
@@ -4763,7 +4770,7 @@
   {
     //const int write_head_pos = GetHead(nHardware::HEAD_WRITE).GetPosition();
     //const int read_head_pos = GetHead(nHardware::HEAD_READ).GetPosition();
-    m_threads[m_cur_thread].Reset(this, m_threads[m_cur_thread].GetID());
+    m_threads[m_cur_thread].Reset(m_world, this, m_threads[m_cur_thread].GetID());
     //GetHead(nHardware::HEAD_WRITE).Set(write_head_pos);
     //GetHead(nHardware::HEAD_READ).Set(read_head_pos);
     
@@ -5155,6 +5162,162 @@
 }
 
 
+
+// Interrupt Handler code
+
+/* interrupt handling - MSG arrives, add to waiting pool, and process interrupts until all have been processed
+   
+ ***an interrupts cannot be preempted***
+ 
+ 
+Processing interrupt
+ Save current state
+ Push interrupt arguments into registers, i.e. MSG contents are placed in BX & CX
+ Jump 1 instruction passed MSG_received_handler_START
+ Process instructions until MSG_received_handler_END
+ On MSG_received_handler_END, process next interrupt or restore previous state
+ */
+
+void cLocalThread::saveState() {
+	assert(!interrupted);
+	// save registers
+	// save heads
+	// save thread stack
+	
+	for(int i = 0; i < NUM_REGISTERS; i++) {
+		pushedState.reg[i] = reg[i];
+	}
+	
+	for(int i = 0; i < NUM_HEADS; i++) {
+		pushedState.heads[i] = heads[i];
+	}
+	
+	pushedState.stack = stack;
+	pushedState.cur_stack = cur_stack;
+	pushedState.cur_head = cur_head;
+	pushedState.read_label = read_label;
+	pushedState.next_label = next_label;
+}
+
+void cLocalThread::restoreState() {
+	assert(interrupted);
+	// restore registers
+	// restore heads
+	// save thread stack
+
+	for(int i = 0; i < NUM_REGISTERS; i++) {
+		reg[i] = pushedState.reg[i];
+	}
+	
+	for(int i = 0; i < NUM_HEADS; i++) {
+		heads[i] = pushedState.heads[i];
+	}
+	
+	stack = pushedState.stack;
+	cur_stack = pushedState.cur_stack;
+	cur_head = pushedState.cur_head;
+	read_label = pushedState.read_label;
+	next_label = pushedState.next_label;
+}
+
+// push interrupt arguments into registers, i.e. MSG contents are placed in BX & CX, nothing for movement
+void cLocalThread::setInterruptState() {
+  for (int i = 0; i < NUM_REGISTERS; i++) hardware->GetRegister(i) = 0;
+  for (int i = 0; i < NUM_HEADS; i++) hardware->GetHead(i).Reset(hardware);///  TODO:????  // what do we do with the heads?
+  
+  stack.Clear();
+  cur_stack = 0;
+  cur_head = nHardware::HEAD_IP;
+  read_label.Clear();
+  next_label.Clear();
+}
+
+void cLocalThread::moveInstructionHeadToMSGHandler() {
+	//Jump 1 instruction passed MSG_received_handler_START
+	cInstruction label_inst = hardware->GetInstSet().GetInst("MSG_received_handler_START");  //cStringUtil::Stringf("MSG_received_handler_END"));
+	
+	cHeadCPU search_head(hardware->IP());
+	int start_pos = search_head.GetPosition();
+	search_head++;
+	
+	while (start_pos != search_head.GetPosition()) {
+		if (search_head.GetInst() == label_inst) {
+			// move IP to here
+			search_head++;
+			hardware->IP().Set(search_head.GetPosition());
+		}
+		search_head++;
+	}	
+}
+
+void cLocalThread::interruptContextSwitch() {
+	if(!interrupted) { //normal -> interrupt
+		interrupted = true;
+		//Save current state
+		saveState();
+		
+		setInterruptState();
+		hardware->Inst_RetrieveMessage(m_world->GetDefaultContext());  // if movement interrupt then registers remain zero
+
+		moveInstructionHeadToMSGHandler();
+		
+	} else { // currently interrupted
+		setInterruptState();  // this line only affect else clause
+		// note: movement interrupts cannot be blocked (just message interrupts), so following if statement is OK
+		if(hardware->Inst_RetrieveMessage(m_world->GetDefaultContext())) {  // interrupt -> normal
+			interrupted = false;
+			//restore state
+			restoreState();
+		} else {  // more messages interrupts to process
+			// thread state is set
+			// move IP to MSG_received_handler_START
+			moveInstructionHeadToMSGHandler();
+		}
+	}
+	
+}
+
+bool cHardwareCPU::moveInstructionHeadToInterruptEnd() {
+	//Jump 1 instruction passed MSG_received_handler_START
+	cInstruction label_inst = GetInstSet().GetInst("interrupt_handler_END");  //cStringUtil::Stringf("MSG_received_handler_END"));
+	
+	cHeadCPU search_head(IP());
+	int start_pos = search_head.GetPosition();
+	search_head++;
+	
+	while (start_pos != search_head.GetPosition()) {
+		if (search_head.GetInst() == label_inst) {
+			// move IP to here
+			search_head++;
+			IP().Set(search_head.GetPosition());
+			return true;
+		}
+		search_head++;
+	}
+	return false;
+}
+
+// jumps one instruction passed MSG_received_handler_END
+bool cHardwareCPU::Inst_MSG_received_handler_START(cAvidaContext& ctx) {
+	return moveInstructionHeadToInterruptEnd();
+}
+
+bool cHardwareCPU::Inst_Moved_handler_START(cAvidaContext& ctx) {
+	return moveInstructionHeadToInterruptEnd();
+}
+
+bool cHardwareCPU::Inst_interrupt_handler_END(cAvidaContext& ctx) {
+
+	/*
+	 Process instructions in interrupt handler until MSG_received_handler_END instruction
+	 On MSG_received_handler_END, process next interrupt or restore previous state
+	 */
+	const int threadID = GetCurThread();
+	m_threads[threadID].interruptContextSwitch();
+	return true;
+}
+
+
 //// Placebo insts ////
 bool cHardwareCPU::Inst_Skip(cAvidaContext& ctx)
 {

Modified: branches/interrupt/source/cpu/cHardwareCPU.h
===================================================================
--- branches/interrupt/source/cpu/cHardwareCPU.h	2008-09-12 22:20:51 UTC (rev 2777)
+++ branches/interrupt/source/cpu/cHardwareCPU.h	2008-09-13 03:41:19 UTC (rev 2778)
@@ -44,6 +44,9 @@
 #ifndef cHardwareBase_h
 #include "cHardwareBase.h"
 #endif
+#ifndef cOrganismThread_h
+#include "cOrganismThread.h"
+#endif
 #ifndef cString_h
 #include "cString.h"
 #endif
@@ -64,6 +67,7 @@
 #include "nHardware.h"
 #endif
 
+
 /**
  * Each organism may have a cHardwareCPU structure which keeps track of the
  * current status of all the components of the simulated hardware.
@@ -76,8 +80,68 @@
 class cInstSet;
 class cMutation;
 class cOrganism;
+class cHardwareCPU;
 
+// --------  Data Structures  --------
+class cLocalThread : public cOrganismThread
+{
+private:
+	cWorld* m_world;
+	int m_promoter_inst_executed;
+public:
+	static const int NUM_REGISTERS = 3;
+  static const int NUM_HEADS = nHardware::NUM_HEADS >= NUM_REGISTERS ? nHardware::NUM_HEADS : NUM_REGISTERS;
+	
+	int reg[NUM_REGISTERS];
+	cHeadCPU heads[NUM_HEADS];
+	cCPUStack stack;
+	unsigned char cur_stack;              // 0 = local stack, 1 = global stack.
+	unsigned char cur_head;
+	
+	cCodeLabel read_label;
+	cCodeLabel next_label;
+	
+	struct savedState {
+		int reg[NUM_REGISTERS];
+		cHeadCPU heads[NUM_HEADS];
+		cCPUStack stack;
+		unsigned char cur_stack;              // 0 = local stack, 1 = global stack.
+		unsigned char cur_head;
+		
+		cCodeLabel read_label;
+		cCodeLabel next_label;
+	};
+	
+	savedState pushedState;  //<! state of thread before interrupt
+	bool interrupted;        //<! is thread interrupted
+	cHardwareCPU* hardware;  //<! hardware that this thread is running on
+	
+	cLocalThread(cWorld* world = NULL, cHardwareCPU* in_hardware = NULL, int in_id = -1) : m_world(world), hardware(in_hardware) { Reset(world, in_hardware, in_id); }
+	~cLocalThread() { ; }
+	
+	void operator=(const cLocalThread& in_thread);
+	
+	void Reset(cWorld* world, cHardwareCPU* in_hardware, int in_id);
+	int GetPromoterInstExecuted() { return m_promoter_inst_executed; }
+	void IncPromoterInstExecuted() { m_promoter_inst_executed++; }
+	void ResetPromoterInstExecuted() { m_promoter_inst_executed = 0; }
+	
+	// save registers
+	// save heads
+	// save thread stack		
+	void saveState();
+	
+	// restore registers
+	// restore heads
+	// save thread stack		
+	void restoreState();
+	void setInterruptState();
+	void interruptContextSwitch();  //!< performs context switch between normal thread execution and interrupt handler
+	void moveInstructionHeadToMSGHandler();
+	void moveInstructionHeadToInterruptEnd();
+};
 
+
 class cHardwareCPU : public cHardwareBase
 {
 public:
@@ -89,44 +153,11 @@
   static const int NUM_HEADS = nHardware::NUM_HEADS >= NUM_REGISTERS ? nHardware::NUM_HEADS : NUM_REGISTERS;
   enum tRegisters { REG_AX = 0, REG_BX, REG_CX, REG_DX, REG_EX, REG_FX };
   static const int NUM_NOPS = 3;
-  
-  // --------  Data Structures  --------
-  struct cLocalThread
-  {
-  private:
-    int m_id;
-    int m_promoter_inst_executed;
-  public:
-    int reg[NUM_REGISTERS];
-    cHeadCPU heads[NUM_HEADS];
-    cCPUStack stack;
-    unsigned char cur_stack;              // 0 = local stack, 1 = global stack.
-    unsigned char cur_head;
     
-    cCodeLabel read_label;
-    cCodeLabel next_label;
-    
-    
-    cLocalThread(cHardwareBase* in_hardware = NULL, int in_id = -1) { Reset(in_hardware, in_id); }
-    ~cLocalThread() { ; }
-    
-    void operator=(const cLocalThread& in_thread);
-    
-    void Reset(cHardwareBase* in_hardware, int in_id);
-    int GetID() const { return m_id; }
-    void SetID(int in_id) { m_id = in_id; }
-    int GetPromoterInstExecuted() { return m_promoter_inst_executed; }
-    void IncPromoterInstExecuted() { m_promoter_inst_executed++; }
-    void ResetPromoterInstExecuted() { m_promoter_inst_executed = 0; }
-    
-  };
-
-    
   // --------  Static Variables  --------
   static tInstLib<tMethod>* s_inst_slib;
   static tInstLib<tMethod>* initInstLib(void);
 
-
   // --------  Member Variables  --------
   const tMethod* m_functions;
 
@@ -612,8 +643,10 @@
   
   //// Messaging ////
   bool Inst_SendMessage(cAvidaContext& ctx);
+public:
   bool Inst_RetrieveMessage(cAvidaContext& ctx);
-  
+private:
+	
   //// Alarm ////
   bool Inst_Alarm_MSG_local(cAvidaContext& ctx);
   bool Inst_Alarm_MSG_multihop(cAvidaContext& ctx);
@@ -622,7 +655,12 @@
   bool Inst_Alarm_Label(cAvidaContext& ctx);
   bool Jump_To_Alarm_Label(int jump_label);
 
-  
+  // interrupt		
+	bool Inst_MSG_received_handler_START(cAvidaContext& ctx);
+	bool Inst_Moved_handler_START(cAvidaContext& ctx);
+	bool Inst_interrupt_handler_END(cAvidaContext& ctx);
+	bool moveInstructionHeadToInterruptEnd();
+	
   //// Placebo ////
   bool Inst_Skip(cAvidaContext& ctx);
 




More information about the Avida-cvs mailing list