[Avida-cvs] [Avida2-svn] r177 - in branches/brysonda: Avida2.xcode source/cpu

brysonda at myxo.css.msu.edu brysonda at myxo.css.msu.edu
Sat Jun 4 12:16:20 PDT 2005


Author: brysonda
Date: 2005-06-04 15:16:19 -0400 (Sat, 04 Jun 2005)
New Revision: 177

Added:
   branches/brysonda/source/cpu/hardware_smt.cc
   branches/brysonda/source/cpu/hardware_smt.h
   branches/brysonda/source/cpu/hardware_smt_thread.cc
   branches/brysonda/source/cpu/hardware_smt_thread.h
   branches/brysonda/source/cpu/tInstLib.h
Modified:
   branches/brysonda/Avida2.xcode/project.pbxproj
Log:
Begin adding new hardware classes.  Added tInstLib template.

Modified: branches/brysonda/Avida2.xcode/project.pbxproj
===================================================================
--- branches/brysonda/Avida2.xcode/project.pbxproj	2005-06-04 18:34:03 UTC (rev 176)
+++ branches/brysonda/Avida2.xcode/project.pbxproj	2005-06-04 19:16:19 UTC (rev 177)
@@ -34,6 +34,9 @@
 				70486BA50826722F009328F0,
 				70486BA60826722F009328F0,
 				70486BA70826722F009328F0,
+				706D30CD0852328F00D7DC8F,
+				706D30FD0852363400D7DC8F,
+				706D31010852366400D7DC8F,
 			);
 			isa = PBXCopyFilesBuildPhase;
 			runOnlyForDeploymentPostprocessing = 0;
@@ -92,6 +95,76 @@
 			settings = {
 			};
 		};
+		706D30CC0852328F00D7DC8F = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.c.h;
+			path = tInstLib.h;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		706D30CD0852328F00D7DC8F = {
+			fileRef = 706D30CC0852328F00D7DC8F;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		706D30FB0852363400D7DC8F = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.c.h;
+			path = hardware_smt.h;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		706D30FC0852363400D7DC8F = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.cpp.cpp;
+			path = hardware_smt.cc;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		706D30FD0852363400D7DC8F = {
+			fileRef = 706D30FB0852363400D7DC8F;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		706D30FE0852363400D7DC8F = {
+			fileRef = 706D30FC0852363400D7DC8F;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		706D30FF0852366400D7DC8F = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.c.h;
+			path = hardware_smt_thread.h;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		706D31000852366400D7DC8F = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.cpp.cpp;
+			path = hardware_smt_thread.cc;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		706D31010852366400D7DC8F = {
+			fileRef = 706D30FF0852366400D7DC8F;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		706D31020852366400D7DC8F = {
+			fileRef = 706D31000852366400D7DC8F;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
 		70CBFCE80815E7FE0078D8CC = {
 			fileEncoding = 30;
 			isa = PBXFileReference;
@@ -2245,6 +2318,11 @@
 				DCC30FCB0762539D008F7A48,
 				DCC30FCC0762539D008F7A48,
 				DCC30FCD0762539D008F7A48,
+				706D30CC0852328F00D7DC8F,
+				706D30FB0852363400D7DC8F,
+				706D30FC0852363400D7DC8F,
+				706D30FF0852366400D7DC8F,
+				706D31000852366400D7DC8F,
 			);
 			isa = PBXGroup;
 			path = cpu;
@@ -9474,6 +9552,8 @@
 				DCC316DB0762876F008F7A48,
 				70CBFCEE0815E7FE0078D8CC,
 				70CBFCF10815E8370078D8CC,
+				706D30FE0852363400D7DC8F,
+				706D31020852366400D7DC8F,
 			);
 			isa = PBXSourcesBuildPhase;
 			runOnlyForDeploymentPostprocessing = 0;

Added: branches/brysonda/source/cpu/hardware_smt.cc
===================================================================
--- branches/brysonda/source/cpu/hardware_smt.cc	2005-06-04 18:34:03 UTC (rev 176)
+++ branches/brysonda/source/cpu/hardware_smt.cc	2005-06-04 19:16:19 UTC (rev 177)
@@ -0,0 +1,2259 @@
+/*
+ *  hardware_smt.cc
+ *  Avida2
+ *
+ *  Created by David on 6/4/05.
+ *  Copyright 2005 Michigan State University. All rights reserved.
+ *
+ */
+
+#include "hardware_smt.h"
+
+#include "config.hh"
+#include "cpu_test_info.hh"
+#include "functions.hh"
+#include "genome_util.hh"
+#include "inst_lib_base.hh"
+#include "inst_set.hh"
+#include "hardware_tracer.hh"
+#include "hardware_tracer_4stack.hh"
+#include "mutation.hh"
+#include "mutation_lib.hh"
+#include "mutation_macros.hh"
+#include "organism.hh"
+#include "phenotype.hh"
+#include "random.hh"
+#include "string_util.hh"
+#include "test_cpu.hh"
+
+#include <limits.h>
+
+using namespace std;
+
+
+
+///////////////
+//  cHardwareSMT
+///////////////
+
+const cInstruction tInstLib<cHardwareSMT::tMethod>::inst_error(255);
+const cInstruction tInstLib<cHardwareSMT::tMethod>::inst_default(0);
+cInstLibBase* cHardwareSMT::GetInstLib(){ return s_inst_slib; }
+
+tInstLib<cHardwareSMT::tMethod> *cHardwareSMT::s_inst_slib = cHardwareSMT::initInstLib();
+tInstLib<cHardwareSMT::tMethod> *cHardwareSMT::initInstLib(void){
+  struct cNOPEntry4Stack {
+    cNOPEntry4Stack(const cString &name, int nop_mod):name(name), nop_mod(nop_mod){}
+    cString name;
+    int nop_mod;
+  };
+  static const cNOPEntry4Stack s_n_array[] = {
+    cNOPEntry4Stack("Nop-A", STACK_AX),
+    cNOPEntry4Stack("Nop-B", STACK_BX),
+    cNOPEntry4Stack("Nop-C", STACK_CX),
+    cNOPEntry4Stack("Nop-D", STACK_DX),
+    cNOPEntry4Stack("Nop-E", STACK_EX),
+    cNOPEntry4Stack("Nop-F", STACK_FX)
+  };
+	
+  struct cInstEntry4Stack {
+    cInstEntry4Stack(const cString &name, tHardware4StackMethod function):name(name), function(function){}
+    cString name;
+    tHardware4StackMethod function;
+  };
+  static const cInstEntry4Stack s_f_array[] = {
+    //1 
+    cInstEntry4Stack("Nop-A",     &cHardwareSMT::Inst_Nop), 
+    //2
+    cInstEntry4Stack("Nop-B",     &cHardwareSMT::Inst_Nop), 
+    //3
+    cInstEntry4Stack("Nop-C",     &cHardwareSMT::Inst_Nop),   
+    //4 
+    cInstEntry4Stack("Nop-D",     &cHardwareSMT::Inst_Nop), 
+    //38
+    cInstEntry4Stack("Nop-E",     &cHardwareSMT::Inst_Nop),
+    //39
+    cInstEntry4Stack("Nop-F",     &cHardwareSMT::Inst_Nop),
+    //5
+    cInstEntry4Stack("Nop-X",     &cHardwareSMT::Inst_Nop),
+    //6 
+    cInstEntry4Stack("Val-Shift-R",   &cHardwareSMT::Inst_ShiftR),
+    //7
+    cInstEntry4Stack("Val-Shift-L",   &cHardwareSMT::Inst_ShiftL),
+    //8
+    cInstEntry4Stack("Val-Nand",      &cHardwareSMT::Inst_Val_Nand),
+    //9
+    cInstEntry4Stack("Val-Add",       &cHardwareSMT::Inst_Val_Add),
+    //10
+    cInstEntry4Stack("Val-Sub",       &cHardwareSMT::Inst_Val_Sub),
+    //11
+    cInstEntry4Stack("Val-Mult",      &cHardwareSMT::Inst_Val_Mult),
+    //12
+    cInstEntry4Stack("Val-Div",       &cHardwareSMT::Inst_Val_Div),
+    //13
+    cInstEntry4Stack("SetMemory",   &cHardwareSMT::Inst_SetMemory),
+    //14
+    cInstEntry4Stack("Divide",  &cHardwareSMT::Inst_Divide),
+    //15
+    cInstEntry4Stack("Inst-Read",    &cHardwareSMT::Inst_HeadRead),
+    //16
+    cInstEntry4Stack("Inst-Write",   &cHardwareSMT::Inst_HeadWrite),
+    //keeping this one for the transition period
+    //cInstEntry4Stack("Inst-Copy",    &cHardwareSMT::Inst_HeadCopy),
+    //17
+    cInstEntry4Stack("If-Equal",    &cHardwareSMT::Inst_IfEqual),
+    //18
+    cInstEntry4Stack("If-Not-Equal",  &cHardwareSMT::Inst_IfNotEqual),
+    //19
+    cInstEntry4Stack("If-Less",   &cHardwareSMT::Inst_IfLess),
+    //20
+    cInstEntry4Stack("If-Greater",    &cHardwareSMT::Inst_IfGreater),
+    //21
+    cInstEntry4Stack("Head-Push",    &cHardwareSMT::Inst_HeadPush),
+    //22
+    cInstEntry4Stack("Head-Pop",     &cHardwareSMT::Inst_HeadPop),
+    //23
+    cInstEntry4Stack("Head-Move",  &cHardwareSMT::Inst_HeadMove),
+    //24
+    cInstEntry4Stack("Search",  &cHardwareSMT::Inst_Search),
+    //25
+    cInstEntry4Stack("Push-Next",    &cHardwareSMT::Inst_PushNext),
+    //26
+    cInstEntry4Stack("Push-Prev",    &cHardwareSMT::Inst_PushPrevious),
+    //27
+    cInstEntry4Stack("Push-Comp",    &cHardwareSMT::Inst_PushComplement),
+    //28
+    cInstEntry4Stack("Val-Delete", &cHardwareSMT::Inst_ValDelete),
+    //29
+    cInstEntry4Stack("Val-Copy",  &cHardwareSMT::Inst_ValCopy),
+    //30
+    cInstEntry4Stack("ThreadFork",   &cHardwareSMT::Inst_ForkThread),
+    //31
+    //cInstEntry4Stack("if-label",  &cHardwareSMT::Inst_IfLabel),
+    //32
+    cInstEntry4Stack("Val-Inc",       &cHardwareSMT::Inst_Increment),
+    //33
+    cInstEntry4Stack("Val-Dec",       &cHardwareSMT::Inst_Decrement),
+    //34
+    cInstEntry4Stack("Val-Mod",       &cHardwareSMT::Inst_Mod),
+    //35
+    cInstEntry4Stack("ThreadKill",   &cHardwareSMT::Inst_KillThread),
+    //36
+    cInstEntry4Stack("IO", &cHardwareSMT::Inst_IO),
+    //37
+    cInstEntry4Stack("Inject", &cHardwareSMT::Inst_Inject)
+  };
+	
+  const int n_size = sizeof(s_n_array)/sizeof(cNOPEntry4Stack);
+	
+  cout << "Instruction Library has " << n_size << " instructions." << endl;
+	
+  static cString n_names[n_size];
+  static int nop_mods[n_size];
+  for (int i = 0; i < n_size; i++){
+    n_names[i] = s_n_array[i].name;
+    nop_mods[i] = s_n_array[i].nop_mod;
+  }
+	
+  const int f_size = sizeof(s_f_array)/sizeof(cInstEntry4Stack);
+  static cString f_names[f_size];
+  static tHardware4StackMethod functions[f_size];
+  for (int i = 0; i < f_size; i++){
+    f_names[i] = s_f_array[i].name;
+    functions[i] = s_f_array[i].function;
+  }
+	
+  tInstLib<cHardwareSMT::tMethod> *inst_lib = new tInstLib<cHardwareSMT::tMethod>(
+																								n_size,
+																								f_size,
+																								n_names,
+																								f_names,
+																								nop_mods,
+																								functions
+																								);
+	
+  cout <<
+		"<cHardwareSMT::initInstLib> debug: important post-init values:" <<endl<<
+		" --- GetSize(): " << inst_lib->GetSize() <<endl<<
+		" --- GetNumNops(): " << inst_lib->GetNumNops() <<endl<<
+		" --- GetName(last): " <<
+		inst_lib->GetName(inst_lib->GetSize() - 1) <<endl<<
+		endl;
+	
+  return inst_lib;
+}
+
+cHardwareSMT::cHardwareSMT(cOrganism * in_organism, cInstSet * in_inst_set)
+: cHardwareBase(in_organism, in_inst_set)
+, memory_array(NUM_MEMORY_SPACES)
+{
+  /* FIXME:  reorganize storage of m_functions.  -- kgn */
+  m_functions = s_inst_slib->GetFunctions();
+  /**/
+  inst_remainder = 0;
+	
+  for(int x=1; x<=cConfig::GetMaxCPUThreads(); x++)
+	{
+		slice_array[x] = (x-1)*cConfig::GetThreadSlicingMethod()+1;
+	}
+	
+  memory_array[0] = in_organism->GetGenome();  // Initialize memory...
+  memory_array[0].Resize(GetMemory(0).GetSize()+1);
+  memory_array[0][memory_array[0].GetSize()-1] = cInstruction();
+  Reset();                            // Setup the rest of the hardware...
+}
+
+
+cHardwareSMT::cHardwareSMT(const cHardwareSMT &hardware_4stack)
+: cHardwareBase(hardware_4stack.organism, hardware_4stack.inst_set)
+, m_functions(hardware_4stack.m_functions)
+, memory_array(hardware_4stack.memory_array)
+, threads(hardware_4stack.threads)
+, thread_id_chart(hardware_4stack.thread_id_chart)
+, cur_thread(hardware_4stack.cur_thread)
+, mal_active(hardware_4stack.mal_active)
+, inst_cost(hardware_4stack.inst_cost)
+#ifdef INSTRUCTION_COSTS
+, inst_ft_cost(hardware_4stack.inst_ft_cost)
+, inst_remainder(hardware_4stack.inst_remainder)
+#endif
+{
+  for(int i = 0; i < NUM_GLOBAL_STACKS; i++){
+    global_stacks[i] = hardware_4stack.global_stacks[i];
+  }
+  for(int i = 0; i < sizeof(slice_array)/sizeof(float); i++){
+    slice_array[i] = hardware_4stack.slice_array[i];
+  }
+}
+
+
+void cHardwareSMT::Recycle(cOrganism * new_organism, cInstSet * in_inst_set)
+{
+  cHardwareBase::Recycle(new_organism, in_inst_set);
+  memory_array[0] = new_organism->GetGenome();
+  memory_array[0].Resize(GetMemory(0).GetSize()+1);
+  memory_array[0][memory_array[0].GetSize()-1] = cInstruction();
+  Reset();
+}
+
+
+void cHardwareSMT::Reset()
+{
+  //global_stack.Clear();
+  //thread_time_used = 0;
+	
+  // Setup the memory...
+  for (int i = 1; i < NUM_MEMORY_SPACES; i++) {
+		memory_array[i].Resize(1);
+		//GetMemory(i).Replace(0, 1, cGenome(ConvertToInstruction(i)));
+		GetMemory(i)=cGenome(ConvertToInstruction(i)); 
+  }
+	
+  // We want to reset to have a single thread.
+  threads.Resize(1);
+	
+  // Reset that single thread.
+  threads[0].Reset(this, 0);
+  thread_id_chart = 1; // Mark only the first thread as taken...
+  cur_thread = 0;
+	
+  mal_active = false;
+	
+  // Reset all stacks (local and global)
+  for(int i=0; i<NUM_STACKS; i++)
+	{
+		Stack(i).Clear();
+	}
+	
+#ifdef INSTRUCTION_COSTS
+  // instruction cost arrays
+  const int num_inst_cost = GetNumInst();
+  inst_cost.Resize(num_inst_cost);
+  inst_ft_cost.Resize(num_inst_cost);
+	
+  for (int i = 0; i < num_inst_cost; i++) {
+    inst_cost[i] = GetInstSet().GetCost(cInstruction(i));
+    inst_ft_cost[i] = GetInstSet().GetFTCost(cInstruction(i));
+  }
+#endif
+	
+}
+
+// This function processes the very next command in the genome, and is made
+// to be as optimized as possible.  This is the heart of avida.
+
+void cHardwareSMT::SingleProcess()
+{
+  // Mark this organism as running...
+  organism->SetRunning(true);
+	
+  cPhenotype & phenotype = organism->GetPhenotype();
+  phenotype.IncTimeUsed();
+  //if(organism->GetCellID()==46 && IP().GetMemSpace()==2)
+  // int x=0;
+	
+  //if (GetNumThreads() > 1) thread_time_used++;
+  //assert((GetHead(HEAD_WRITE).GetPosition() == Stack(STACK_BX).Top() ||
+  // Stack(STACK_BX).Top()==GetMemory(IP().GetMemSpace()).GetSize()-1 || 
+  // GetHead(HEAD_WRITE).GetPosition() == Stack(STACK_BX).Top()+1) &&
+  // (GetHead(HEAD_WRITE).GetMemSpace() == IP().GetMemSpace() ||
+  //  GetHead(HEAD_WRITE).GetMemSpace() == IP().GetMemSpace()+1));
+  // If we have threads turned on and we executed each thread in a single
+  // timestep, adjust the number of instructions executed accordingly.
+  //const int num_inst_exec = (cConfig::GetThreadSlicingMethod() == 1) ?
+  //  GetNumThreads() : 1;
+	
+  const int num_inst_exec = int(slice_array[GetNumThreads()]+ inst_remainder);
+  inst_remainder = slice_array[GetNumThreads()] + inst_remainder - num_inst_exec;
+  
+  for (int i = 0; i < num_inst_exec; i++) {
+    // Setup the hardware for the next instruction to be executed.
+    NextThread();
+    AdvanceIP() = true;
+    IP().Adjust();
+		
+#ifdef BREAKPOINTS
+    if (IP().FlagBreakpoint() == true) {
+      organism->DoBreakpoint();
+    }
+#endif
+    
+    // Print the status of this CPU at each step...
+    if (m_tracer != NULL) {
+      if (cHardwareTracer_4Stack * tracer
+          = dynamic_cast<cHardwareTracer_4Stack *>(m_tracer)
+					){
+        tracer->TraceHardware_4Stack(*this);
+      }
+    }
+    
+    // Find the instruction to be executed
+    const cInstruction & cur_inst = IP().GetInst();
+		
+    // Test if costs have been paid and it is okay to execute this now...
+    const bool exec = SingleProcess_PayCosts(cur_inst);
+		
+    // Now execute the instruction...
+    if (exec == true) {
+      SingleProcess_ExecuteInst(cur_inst);
+			
+      // Some instruction (such as jump) may turn advance_ip off.  Ususally
+      // we now want to move to the next instruction in the memory.
+      if (AdvanceIP() == true) IP().Advance();
+    } // if exec
+    
+  } // Previous was executed once for each thread...
+	
+  // Kill creatures who have reached their max num of instructions executed
+  const int max_executed = organism->GetMaxExecuted();
+  if ((max_executed > 0 && phenotype.GetTimeUsed() >= max_executed)
+      || phenotype.GetToDie()) {
+    organism->Die();
+  }
+	
+  organism->SetRunning(false);
+}
+
+// This method will test to see if all costs have been paid associated
+// with executing an instruction and only return true when that instruction
+// should proceed.
+bool cHardwareSMT::SingleProcess_PayCosts(const cInstruction & cur_inst)
+{
+#ifdef INSTRUCTION_COSTS
+  assert(cur_inst.GetOp() < inst_cost.GetSize());
+	
+  // If first time cost hasn't been paid off...
+  if ( inst_ft_cost[cur_inst.GetOp()] > 0 ) {
+    inst_ft_cost[cur_inst.GetOp()]--;       // dec cost
+    return false;
+  }
+	
+  // Next, look at the per use cost
+  if ( GetInstSet().GetCost(cur_inst) > 0 ) {
+    if ( inst_cost[cur_inst.GetOp()] > 1 ){  // if isn't paid off (>1)
+      inst_cost[cur_inst.GetOp()]--;         // dec cost
+      return false;
+    } else {                                 // else, reset cost array
+      inst_cost[cur_inst.GetOp()] = GetInstSet().GetCost(cur_inst);
+    }
+  }
+	
+  // Prob of exec
+  if ( GetInstSet().GetProbFail(cur_inst) > 0.0 ){
+    return !( g_random.P(GetInstSet().GetProbFail(cur_inst)) );
+  }
+#endif
+  return true;
+}
+
+// This method will handle the actuall execution of an instruction
+// within single process, once that function has been finalized.
+bool cHardwareSMT::SingleProcess_ExecuteInst(const cInstruction & cur_inst) 
+{
+  // Copy Instruction locally to handle stochastic effects
+  cInstruction actual_inst = cur_inst;
+  
+#ifdef EXECUTION_ERRORS
+  // If there is an execution error, execute a random instruction.
+  if (organism->TestExeErr()) actual_inst = GetInstSet().GetRandomInst();
+#endif /* EXECUTION_ERRORS */
+	
+  // Get a pointer to the corrisponding method...
+  int inst_idx = GetInstSet().GetLibFunctionIndex(actual_inst);
+  
+  // Mark the instruction as executed
+  IP().FlagExecuted() = true;
+	
+	
+#ifdef INSTRUCTION_COUNT
+  // instruction execution count incremeneted
+  organism->GetPhenotype().IncCurInstCount(actual_inst.GetOp());
+#endif
+	
+  // And execute it.
+  const bool exec_success = (this->*(m_functions[inst_idx]))();
+	
+#ifdef INSTRUCTION_COUNT
+  // decremenet if the instruction was not executed successfully
+  if (exec_success == false) {
+    organism->GetPhenotype().DecCurInstCount(actual_inst.GetOp());
+  }
+#endif	
+	
+  return exec_success;
+}
+
+
+void cHardwareSMT::ProcessBonusInst(const cInstruction & inst)
+{
+  // Mark this organism as running...
+  bool prev_run_state = organism->GetIsRunning();
+  organism->SetRunning(true);
+	
+  // @CAO FIX PRINTING TO INDICATE THIS IS A BONUS
+  // Print the status of this CPU at each step...
+  if (m_tracer != NULL) {
+    if (cHardwareTracer_4Stack * tracer
+        = dynamic_cast<cHardwareTracer_4Stack *>(m_tracer)
+				){
+      tracer->TraceHardware_4StackBonus(*this);
+    }
+  }
+	
+  SingleProcess_ExecuteInst(inst);
+	
+  organism->SetRunning(prev_run_state);
+}
+
+
+void cHardwareSMT::LoadGenome(const cGenome & new_genome)
+{
+  GetMemory(0) = new_genome;
+}
+
+
+bool cHardwareSMT::OK()
+{
+  bool result = true;
+	
+  for(int i = 0 ; i < NUM_MEMORY_SPACES; i++) {
+    if (!memory_array[i].OK()) result = false;
+  }
+	
+  for (int i = 0; i < GetNumThreads(); i++) {
+    for(int j=0; j<NUM_LOCAL_STACKS; j++)
+			if (threads[i].local_stacks[j].OK() == false) result = false;
+    if (threads[i].next_label.OK() == false) result = false;
+  }
+	
+  return result;
+}
+
+void cHardwareSMT::PrintStatus(ostream & fp)
+{
+  fp << organism->GetPhenotype().GetTimeUsed() << " "
+	<< "IP:(" << IP().GetMemSpace() << ", " << IP().GetPosition() << ")    "
+	
+	<< "AX:" << Stack(STACK_AX).Top() << " "
+	<< setbase(16) << "[0x" << Stack(STACK_AX).Top() << "]  " << setbase(10)
+	
+	<< "BX:" << Stack(STACK_BX).Top() << " "
+	<< setbase(16) << "[0x" << Stack(STACK_BX).Top() << "]  " << setbase(10)
+	
+	<< "CX:" << Stack(STACK_CX).Top() << " "
+	<< setbase(16) << "[0x" << Stack(STACK_CX).Top() << "]  " << setbase(10)
+	
+	<< "DX:" << Stack(STACK_DX).Top() << " "
+	<< setbase(16) << "[0x" << Stack(STACK_DX).Top() << "]  " << setbase(10)
+	
+	<< endl;
+	
+  fp << "  R-Head:(" << GetHead(HEAD_READ).GetMemSpace() << ", " 
+		<< GetHead(HEAD_READ).GetPosition() << ")  " 
+		<< "W-Head:(" << GetHead(HEAD_WRITE).GetMemSpace()  << ", "
+		<< GetHead(HEAD_WRITE).GetPosition() << ")  "
+		<< "F-Head:(" << GetHead(HEAD_FLOW).GetMemSpace()   << ",  "
+		<< GetHead(HEAD_FLOW).GetPosition() << ")  "
+		<< "RL:" << GetReadLabel().AsString() << "   "
+		<< endl;
+	
+  fp << "  Mem (" << GetMemory(0).GetSize() << "):"
+		  << "  " << GetMemory(0).AsString()
+		  << endl;
+  fp << "       " << GetMemory(1).GetSize() << "):"
+		  << "  " << GetMemory(1).AsString()
+		  << endl;
+  fp << "       " << GetMemory(2).GetSize() << "):"
+		  << "  " << GetMemory(2).AsString()
+		  << endl;
+  fp << "       " << GetMemory(3).GetSize() << "):"
+		  << "  " << GetMemory(3).AsString()
+		  << endl;
+  
+  
+  fp.flush();
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// Method: cHardwareSMT::FindLabel(direction)
+//
+// Search in 'direction' (+ or - 1) from the instruction pointer for the
+// compliment of the label in 'next_label' and return a pointer to the
+// results.  If direction is 0, search from the beginning of the genome.
+//
+/////////////////////////////////////////////////////////////////////////
+
+c4StackHead cHardwareSMT::FindLabel(int direction)
+{
+  c4StackHead & inst_ptr = IP();
+	
+  // Start up a search head at the position of the instruction pointer.
+  c4StackHead search_head(inst_ptr);
+  cCodeLabel & search_label = GetLabel();
+	
+  // Make sure the label is of size  > 0.
+	
+  if (search_label.GetSize() == 0) {
+    return inst_ptr;
+  }
+	
+  // Call special functions depending on if jump is forwards or backwards.
+  int found_pos = 0;
+  if( direction < 0 ) {
+    found_pos = FindLabel_Backward(search_label, inst_ptr.GetMemory(),
+																	 inst_ptr.GetPosition() - search_label.GetSize());
+  }
+	
+  // Jump forward.
+  else if (direction > 0) {
+    found_pos = FindLabel_Forward(search_label, inst_ptr.GetMemory(),
+																	inst_ptr.GetPosition());
+  }
+	
+  // Jump forward from the very beginning.
+  else {
+    found_pos = FindLabel_Forward(search_label, inst_ptr.GetMemory(), 0);
+  }
+  
+  // Return the last line of the found label, if it was found.
+  if (found_pos > 0) search_head.Set(found_pos - 1, IP().GetMemSpace());
+  //*** I THINK THIS MIGHT HAVE BEEN WRONG...CHANGED >= to >.  -law ***//
+  
+  // Return the found position (still at start point if not found).
+  return search_head;
+}
+
+
+// Search forwards for search_label from _after_ position pos in the
+// memory.  Return the first line _after_ the the found label.  It is okay
+// to find search label's match inside another label.
+
+int cHardwareSMT::FindLabel_Forward(const cCodeLabel & search_label,
+																			 const cGenome & search_genome, int pos)
+{
+  assert (pos < search_genome.GetSize() && pos >= 0);
+	
+  int search_start = pos;
+  int label_size = search_label.GetSize();
+  bool found_label = false;
+	
+  // Move off the template we are on.
+  pos += label_size;
+	
+  // Search until we find the complement or exit the memory.
+  while (pos < search_genome.GetSize()) {
+		
+    // If we are within a label, rewind to the beginning of it and see if
+    // it has the proper sub-label that we're looking for.
+		
+    if (inst_set->IsNop(search_genome[pos])) {
+      // Find the start and end of the label we're in the middle of.
+			
+      int start_pos = pos;
+      int end_pos = pos + 1;
+      while (start_pos > search_start &&
+						 inst_set->IsNop( search_genome[start_pos - 1] )) {
+				start_pos--;
+      }
+      while (end_pos < search_genome.GetSize() &&
+						 inst_set->IsNop( search_genome[end_pos] )) {
+				end_pos++;
+      }
+      int test_size = end_pos - start_pos;
+			
+      // See if this label has the proper sub-label within it.
+      int max_offset = test_size - label_size + 1;
+      int offset = start_pos;
+      for (offset = start_pos; offset < start_pos + max_offset; offset++) {
+				
+				// Test the number of matches for this offset.
+				int matches;
+				for (matches = 0; matches < label_size; matches++) {
+					if (search_label[matches] !=
+							inst_set->GetNopMod( search_genome[offset + matches] )) {
+						break;
+					}
+				}
+				
+				// If we have found it, break out of this loop!
+				if (matches == label_size) {
+					found_label = true;
+					break;
+				}
+      }
+			
+      // If we've found the complement label, set the position to the end of
+      // the label we found it in, and break out.
+			
+      if (found_label == true) {
+				// pos = end_pos;
+				pos = label_size + offset;
+				break;
+      }
+			
+      // We haven't found it; jump pos to just after the current label being
+      // checked.
+      pos = end_pos;
+    }
+		
+    // Jump up a block to the next possible point to find a label,
+    pos += label_size;
+  }
+	
+  // If the label was not found return a -1.
+  if (found_label == false) pos = -1;
+	
+  return pos;
+}
+
+// Search backwards for search_label from _before_ position pos in the
+// memory.  Return the first line _after_ the the found label.  It is okay
+// to find search label's match inside another label.
+
+int cHardwareSMT::FindLabel_Backward(const cCodeLabel & search_label,
+																				const cGenome & search_genome, int pos)
+{
+  assert (pos < search_genome.GetSize());
+	
+  int search_start = pos;
+  int label_size = search_label.GetSize();
+  bool found_label = false;
+	
+  // Move off the template we are on.
+  pos -= label_size;
+	
+  // Search until we find the complement or exit the memory.
+  while (pos >= 0) {
+    // If we are within a label, rewind to the beginning of it and see if
+    // it has the proper sub-label that we're looking for.
+		
+    if (inst_set->IsNop( search_genome[pos] )) {
+      // Find the start and end of the label we're in the middle of.
+			
+      int start_pos = pos;
+      int end_pos = pos + 1;
+      while (start_pos > 0 && inst_set->IsNop(search_genome[start_pos - 1])) {
+				start_pos--;
+      }
+      while (end_pos < search_start &&
+						 inst_set->IsNop(search_genome[end_pos])) {
+				end_pos++;
+      }
+      int test_size = end_pos - start_pos;
+			
+      // See if this label has the proper sub-label within it.
+      int max_offset = test_size - label_size + 1;
+      for (int offset = start_pos; offset < start_pos + max_offset; offset++) {
+				
+				// Test the number of matches for this offset.
+				int matches;
+				for (matches = 0; matches < label_size; matches++) {
+					if (search_label[matches] !=
+							inst_set->GetNopMod(search_genome[offset + matches])) {
+						break;
+					}
+				}
+				
+				// If we have found it, break out of this loop!
+				if (matches == label_size) {
+					found_label = true;
+					break;
+				}
+      }
+			
+      // If we've found the complement label, set the position to the end of
+      // the label we found it in, and break out.
+			
+      if (found_label == true) {
+				pos = end_pos;
+				break;
+      }
+			
+      // We haven't found it; jump pos to just before the current label
+      // being checked.
+      pos = start_pos - 1;
+    }
+		
+    // Jump up a block to the next possible point to find a label,
+    pos -= label_size;
+  }
+	
+  // If the label was not found return a -1.
+  if (found_label == false) pos = -1;
+	
+  return pos;
+}
+
+// Search for 'in_label' anywhere in the hardware.
+c4StackHead cHardwareSMT::FindLabel(const cCodeLabel & in_label, int direction)
+{
+  assert (in_label.GetSize() > 0);
+	
+  // IDEALY:
+  // Keep making jumps (in the proper direction) equal to the label
+  // length.  If we are inside of a label, check its size, and see if
+  // any of the sub-labels match properly.
+  // FOR NOW:
+  // Get something which works, no matter how inefficient!!!
+	
+  c4StackHead temp_head(this);
+	
+  while (temp_head.InMemory()) {
+    // IDEALY: Analyze the label we are in; see if the one we are looking
+    // for could be a sub-label of it.  Skip past it if not.
+		
+    int i;
+    for (i = 0; i < in_label.GetSize(); i++) {
+      if (!inst_set->IsNop(temp_head.GetInst()) ||
+					in_label[i] != inst_set->GetNopMod(temp_head.GetInst())) {
+				break;
+      }
+    }
+    if (i == GetLabel().GetSize()) {
+      temp_head.AbsJump(i - 1);
+      return temp_head;
+    }
+		
+    temp_head.AbsJump(direction);     // IDEALY: MAKE LARGER JUMPS
+  }
+	
+  temp_head.AbsSet(-1);
+  return temp_head;
+}
+
+// @CAO: direction is not currently used; should be used to indicate the
+// direction which the heads[HEAD_IP] should progress through a creature.
+c4StackHead cHardwareSMT::FindFullLabel(const cCodeLabel & in_label)
+{
+  // cout << "Running FindFullLabel with " << in_label.AsString() <<
+  // endl;
+	
+  assert(in_label.GetSize() > 0); // Trying to find label of 0 size!
+	
+  c4StackHead temp_head(this);
+	
+  while (temp_head.InMemory()) {
+    // If we are not in a label, jump to the next checkpoint...
+    if (inst_set->IsNop(temp_head.GetInst())) {
+      temp_head.AbsJump(in_label.GetSize());
+      continue;
+    }
+		
+    // Otherwise, rewind to the begining of this label...
+		
+    while (!(temp_head.AtFront()) && inst_set->IsNop(temp_head.GetInst(-1)))
+      temp_head.AbsJump(-1);
+		
+    // Calculate the size of the label being checked, and make sure they
+    // are equal.
+		
+    int checked_size = 0;
+    while (inst_set->IsNop(temp_head.GetInst(checked_size))) {
+      checked_size++;
+    }
+    if (checked_size != in_label.GetSize()) {
+      temp_head.AbsJump(checked_size + 1);
+      continue;
+    }
+		
+    // cout << "Testing label at line " << temp_head.GetPosition() <<
+    // endl;
+		
+    // ...and do the comparison...
+		
+    int j;
+    bool label_match = true;
+    for (j = 0; j < in_label.GetSize(); j++) {
+      if (!inst_set->IsNop(temp_head.GetInst(j)) ||
+					in_label[j] != inst_set->GetNopMod(temp_head.GetInst(j))) {
+				temp_head.AbsJump(in_label.GetSize() + 1);
+				label_match = false;
+				break;
+      }
+    }
+		
+    if (label_match) {
+      // If we have found the label, return the position after it.
+      temp_head.AbsJump(j - 1);
+      return temp_head;
+    }
+		
+    // We have not found the label... increment i.
+		
+    temp_head.AbsJump(in_label.GetSize() + 1);
+  }
+	
+  // The label does not exist in this creature.
+	
+  temp_head.AbsSet(-1);
+  return temp_head;
+}
+
+// This is the code run by the INFECTED organism.  Its function is to SPREAD infection.
+bool cHardwareSMT::InjectParasite(double mut_multiplier)
+{
+  const int end_pos = GetHead(HEAD_WRITE).GetPosition();
+  const int mem_space_used = GetHead(HEAD_WRITE).GetMemSpace();
+  
+  // Make sure the creature will still be above the minimum size,
+  // TEMPORARY!  INJECTED CODE CAN 
+  if (end_pos <= 0) {
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
+    return false; // (inject fails)
+  }
+  
+  if (end_pos < MIN_INJECT_SIZE) {
+    GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
+    Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
+    return false; // (inject fails)
+  }
+	
+  GetMemory(mem_space_used).Resize(end_pos);
+	
+  cCPUMemory injected_code = GetMemory(mem_space_used);
+	
+  Inject_DoMutations(mut_multiplier, injected_code);
+	
+  int inject_signal = false;
+	
+  if(injected_code.GetSize()>0)
+    inject_signal = organism->InjectParasite(injected_code);
+  
+  //************* CALL GOES HERE ******************//
+  // spin around randomly (caution: possible organism dizziness)
+  //const int num_neighbors = organism->GetNeighborhoodSize();
+  //for(unsigned int i=0; i<g_random.GetUInt(num_neighbors); i++)
+  //  organism->Rotate(1);
+	
+  // If we don't have a host, stop here.
+  //cOrganism * host_organism = organism->GetNeighbor();
+  
+	
+  //if(host_organism!=NULL)
+  //  {
+  //    
+  //  }
+	
+  //************** CALL ENDS HERE ******************//
+	
+  //reset the memory space which was injected
+  GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
+	
+  for(int x=0; x<NUM_HEADS; x++)
+	{
+		GetHead(x).Reset(IP().GetMemSpace(), this);
+	}
+	
+  for(int x=0; x<NUM_LOCAL_STACKS; x++)
+	{
+		Stack(x).Clear();
+	}
+  
+  AdvanceIP() = false;
+  
+  return inject_signal;
+}
+
+//This is the code run by the TARGET of an injection.  This RECIEVES the infection.
+bool cHardwareSMT::InjectHost(const cCodeLabel & in_label, const cGenome & inject_code)
+{
+  // Make sure the genome will be below max size after injection.
+	
+  // xxxTEMPORARYxxx - we should have this match injection templates.  For now it simply 
+  
+	// FIND THE FIRST EMPTY MEMORY SPACE
+  int target_mem_space;
+  for (target_mem_space = 0; target_mem_space < NUM_MEMORY_SPACES; target_mem_space++)
+	{
+		if(isEmpty(target_mem_space))
+		{
+			break;
+		}
+	}
+  
+  if (target_mem_space == NUM_MEMORY_SPACES)
+	{
+		return false;
+	}
+	
+  assert(target_mem_space >=0 && target_mem_space < NUM_MEMORY_SPACES);
+  
+  if(ForkThread()) {
+    // Inject the new code
+    cCPUMemory oldcode = GetMemory(target_mem_space);
+    GetMemory(target_mem_space) = inject_code;
+    GetMemory(target_mem_space).Resize(inject_code.GetSize() + oldcode.GetSize());
+		
+    // Copies previous instructions to the end of the injected code.
+    // Is there a faster way to do this?? -law
+    for(int x=0; x<oldcode.GetSize(); x++)
+      GetMemory(target_mem_space)[inject_code.GetSize()+x] = oldcode[x];
+		
+    // Set instruction flags on the injected code
+    for (int i = 0; i < inject_code.GetSize(); i++) {
+      memory_array[target_mem_space].FlagInjected(i) = true;
+    }
+    organism->GetPhenotype().IsModified() = true;
+    
+    // Adjust all of the heads to take into account the new mem size.
+    
+    cur_thread=GetNumThreads()-1;
+    
+    for(int i=0; i<cur_thread; i++) {
+      for(int j=0; j<NUM_HEADS; j++) {
+				if(threads[i].heads[j].GetMemSpace()==target_mem_space)
+					threads[i].heads[j].Jump(inject_code.GetSize());
+      }
+    }
+    
+    for (int i=0; i < NUM_HEADS; i++) {    
+      GetHead(i).Reset(target_mem_space, this);
+    }
+    for (int i=0; i < NUM_LOCAL_STACKS; i++) {
+      Stack(i).Clear();
+    }
+  }
+	
+  return true; // (inject succeeds!)
+}
+
+void cHardwareSMT::Mutate(int mut_point)
+{
+  // Test if trying to mutate outside of genome...
+  assert(mut_point >= 0 && mut_point < GetMemory(0).GetSize());
+	
+  GetMemory(0)[mut_point] = GetRandomInst();
+  GetMemory(0).FlagMutated(mut_point) = true;
+  GetMemory(0).FlagPointMut(mut_point) = true;
+  //organism->GetPhenotype().IsMutated() = true;
+  organism->CPUStats().mut_stats.point_mut_count++;
+}
+
+int cHardwareSMT::PointMutate(const double mut_rate)
+{
+  const int num_muts =
+	g_random.GetRandBinomial(GetMemory(0).GetSize(), mut_rate);
+	
+  for (int i = 0; i < num_muts; i++) {
+    const int pos = g_random.GetUInt(GetMemory(0).GetSize());
+    Mutate(pos);
+  }
+	
+  return num_muts;
+}
+
+
+// Trigger mutations of a specific type.  Outside triggers cannot specify
+// a head since hardware types are not known.
+
+bool cHardwareSMT::TriggerMutations(int trigger)
+{
+  // Only update triggers should happen from the outside!
+  assert(trigger == MUTATION_TRIGGER_UPDATE);
+	
+  // Assume instruction pointer is the intended target (if one is even
+  // needed!
+	
+  return TriggerMutations(trigger, IP());
+}
+
+bool cHardwareSMT::TriggerMutations(int trigger, c4StackHead & cur_head)
+{
+  // Collect information about mutations from the organism.
+  cLocalMutations & mut_info = organism->GetLocalMutations();
+  const tList<cMutation> & mut_list =
+    mut_info.GetMutationLib().GetMutationList(trigger);
+	
+  // If we have no mutations for this trigger, stop here.
+  if (mut_list.GetSize() == 0) return false;
+  bool has_mutation = false;
+	
+  // Determine what memory this mutation will be affecting.
+  cCPUMemory & target_mem = (trigger == MUTATION_TRIGGER_DIVIDE) 
+    ? organism->ChildGenome() : GetMemory(0);
+	
+  // Loop through all mutations associated with this trigger and test them.
+  tConstListIterator<cMutation> mut_it(mut_list);
+	
+  while (mut_it.Next() != NULL) {
+    const cMutation * cur_mut = mut_it.Get();
+    const int mut_id = cur_mut->GetID();
+    const int scope = cur_mut->GetScope();
+    const double rate = mut_info.GetRate(mut_id);
+    switch (scope) {
+			case MUTATION_SCOPE_GENOME:
+				if (TriggerMutations_ScopeGenome(cur_mut, target_mem, cur_head, rate)) {
+					has_mutation = true;
+					mut_info.IncCount(mut_id);
+				}
+				break;
+			case MUTATION_SCOPE_LOCAL:
+			case MUTATION_SCOPE_PROP:
+				if (TriggerMutations_ScopeLocal(cur_mut, target_mem, cur_head, rate)) {
+					has_mutation = true;
+					mut_info.IncCount(mut_id);
+				}
+				break;
+			case MUTATION_SCOPE_GLOBAL:
+			case MUTATION_SCOPE_SPREAD:
+				int num_muts =
+				TriggerMutations_ScopeGlobal(cur_mut, target_mem, cur_head, rate);
+				if (num_muts > 0) {
+					has_mutation = true;
+					mut_info.IncCount(mut_id, num_muts);
+				}
+					break;
+    }
+  }
+	
+  return has_mutation;
+}
+
+bool cHardwareSMT::TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+																									 cCPUMemory & target_memory, c4StackHead & cur_head, const double rate)
+{
+  // The rate we have stored indicates the probability that a single
+  // mutation will occur anywhere in the genome.
+  
+  if (g_random.P(rate) == true) {
+    // We must create a temporary head and use it to randomly determine the
+    // position in the genome to be mutated.
+    c4StackHead tmp_head(cur_head);
+    tmp_head.AbsSet(g_random.GetUInt(target_memory.GetSize()));
+    TriggerMutations_Body(cur_mut->GetType(), target_memory, tmp_head);
+    return true;
+  }
+  return false;
+}
+
+bool cHardwareSMT::TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+																									cCPUMemory & target_memory, c4StackHead & cur_head, const double rate)
+{
+  // The rate we have stored is the probability for a mutation at this single
+  // position in the genome.
+	
+  if (g_random.P(rate) == true) {
+    TriggerMutations_Body(cur_mut->GetType(), target_memory, cur_head);
+    return true;
+  }
+  return false;
+}
+
+int cHardwareSMT::TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+																									cCPUMemory & target_memory, c4StackHead & cur_head, const double rate)
+{
+  // The probability we have stored is per-site, so we can pull a random
+  // number from a binomial distribution to determine the number of mutations
+  // that should occur.
+	
+  const int num_mut =
+	g_random.GetRandBinomial(target_memory.GetSize(), rate);
+	
+  if (num_mut > 0) {
+    for (int i = 0; i < num_mut; i++) {
+      c4StackHead tmp_head(cur_head);
+      tmp_head.AbsSet(g_random.GetUInt(target_memory.GetSize()));
+      TriggerMutations_Body(cur_mut->GetType(), target_memory, tmp_head);
+    }
+  }
+	
+  return num_mut;
+}
+
+void cHardwareSMT::TriggerMutations_Body(int type, cCPUMemory & target_memory,
+																						c4StackHead & cur_head)
+{
+  const int pos = cur_head.GetPosition();
+	
+  switch (type) {
+		case MUTATION_TYPE_POINT:
+			target_memory[pos] = GetRandomInst();
+			target_memory.FlagMutated(pos) = true;
+			break;
+		case MUTATION_TYPE_INSERT:
+		case MUTATION_TYPE_DELETE:
+		case MUTATION_TYPE_HEAD_INC:
+		case MUTATION_TYPE_HEAD_DEC:
+		case MUTATION_TYPE_TEMP:
+		case MUTATION_TYPE_KILL:
+		default:
+			cout << "Error: Mutation type not implemented!" << endl;
+			break;
+  };
+}
+
+void cHardwareSMT::ReadInst(const int in_inst)
+{
+  if (inst_set->IsNop( cInstruction(in_inst) )) {
+    GetReadLabel().AddNop(in_inst);
+  } else {
+    GetReadLabel().Clear();
+  }
+}
+
+
+void cHardwareSMT::AdjustHeads()
+{
+  for (int i = 0; i < GetNumThreads(); i++) {
+    for (int j = 0; j < NUM_HEADS; j++) {
+      threads[i].heads[j].Adjust();
+    }
+  }
+}
+
+
+
+// This function looks at the current position in the info of a creature,
+// and sets the next_label to be the sequence of nops which follows.  The
+// instruction pointer is left on the last line of the label found.
+
+void cHardwareSMT::ReadLabel(int max_size)
+{
+  int count = 0;
+  c4StackHead * inst_ptr = &( IP() );
+	
+  GetLabel().Clear();
+	
+  while (inst_set->IsNop(inst_ptr->GetNextInst()) &&
+				 (count < max_size)) {
+    count++;
+    inst_ptr->Advance();
+    GetLabel().AddNop(inst_set->GetNopMod(inst_ptr->GetInst()));
+		
+    // If this is the first line of the template, mark it executed.
+    if (GetLabel().GetSize() <=	cConfig::GetMaxLabelExeSize()) {
+      inst_ptr->FlagExecuted() = true;
+    }
+  }
+}
+
+
+bool cHardwareSMT::ForkThread()
+{
+  const int num_threads = GetNumThreads();
+  if (num_threads == cConfig::GetMaxCPUThreads()) return false;
+	
+  // Make room for the new thread.
+  threads.Resize(num_threads + 1);
+	
+  //IP().Advance();
+	
+  // Initialize the new thread to the same values as the current one.
+  threads[num_threads] = threads[cur_thread]; 
+	
+  // Find the first free bit in thread_id_chart to determine the new
+  // thread id.
+  int new_id = 0;
+  while ( (thread_id_chart >> new_id) & 1 == 1) new_id++;
+  threads[num_threads].SetID(new_id);
+  thread_id_chart |= (1 << new_id);
+	
+  return true;
+}
+
+
+int cHardwareSMT::TestParasite() const
+{
+  return IP().TestParasite();
+}
+
+
+bool cHardwareSMT::KillThread()
+{
+  // Make sure that there is always at least one thread...
+  if (GetNumThreads() == 1) return false;
+	
+  // Note the current thread and set the current back one.
+  const int kill_thread = cur_thread;
+  PrevThread();
+  
+  // Turn off this bit in the thread_id_chart...
+  thread_id_chart ^= 1 << threads[kill_thread].GetID();
+	
+  // Copy the last thread into the kill position
+  const int last_thread = GetNumThreads() - 1;
+  if (last_thread != kill_thread) {
+    threads[kill_thread] = threads[last_thread];
+  }
+	
+  // Kill the thread!
+  threads.Resize(GetNumThreads() - 1);
+	
+  if (cur_thread > kill_thread) cur_thread--;
+	
+  return true;
+}
+
+
+void cHardwareSMT::SaveState(ostream & fp)
+{
+  // note, memory & child_memory handled by cpu (@CAO Not any more!)
+  assert(fp.good());
+	
+  fp<<"cHardwareSMT"<<endl;
+	
+  // global_stack (in inverse order so load can just push)
+  for(int i=NUM_LOCAL_STACKS; i<NUM_STACKS; i++)
+    Stack(i).SaveState(fp);
+	
+  //fp << thread_time_used  << endl;
+  fp << GetNumThreads()   << endl;
+  fp << cur_thread        << endl;
+	
+  // Threads
+  for( int i = 0; i < GetNumThreads(); i++ ) {
+    threads[i].SaveState(fp);
+  }
+}
+
+
+void cHardwareSMT::LoadState(istream & fp)
+{
+  // note, memory & child_memory handled by cpu (@CAO Not any more!)
+  assert(fp.good());
+	
+  cString foo;
+  fp>>foo;
+  assert( foo == "cHardwareSMT" );
+	
+  // global_stack
+  for(int i=NUM_LOCAL_STACKS; i<NUM_STACKS; i++)
+    Stack(i).LoadState(fp);
+	
+  int num_threads;
+  //fp >> thread_time_used;
+  fp >> num_threads;
+  fp >> cur_thread;
+	
+  // Threads
+  for( int i = 0; i < num_threads; i++ ){
+    threads[i].LoadState(fp);
+  }
+}
+
+
+////////////////////////////
+//  Instruction Helpers...
+////////////////////////////
+
+inline int cHardwareSMT::FindModifiedStack(int default_stack)
+{
+  assert(default_stack < NUM_STACKS);  // Stack ID too high.
+	
+  if (GetInstSet().IsNop(IP().GetNextInst())) {
+    IP().Advance();
+    default_stack = GetInstSet().GetNopMod(IP().GetInst());
+    IP().FlagExecuted() = true;
+  }
+  return default_stack;
+}
+
+inline int cHardwareSMT::FindModifiedHead(int default_head)
+{
+  assert(default_head < NUM_HEADS); // Head ID too high.
+	
+  if (GetInstSet().IsNop(IP().GetNextInst())) {
+    IP().Advance();    
+    int nop_head = GetInstSet().GetNopMod(IP().GetInst());
+    if (nop_head < NUM_HEADS) default_head = nop_head;
+    IP().FlagExecuted() = true;
+  }
+  return default_head;
+}
+
+inline int cHardwareSMT::FindComplementStack(int base_stack)
+{
+  const int comp_stack = base_stack + 2;
+  return comp_stack%NUM_STACKS;
+}
+
+inline void cHardwareSMT::Fault(int fault_loc, int fault_type, cString fault_desc)
+{
+  organism->Fault(fault_loc, fault_type, fault_desc);
+}
+
+bool cHardwareSMT::Divide_CheckViable(const int parent_size,
+																				 const int child_size, const int mem_space)
+{
+  // Make sure the organism is okay with dividing now...
+  if (organism->Divide_CheckViable() == false) return false; // (divide fails)
+	
+  // Make sure that neither parent nor child will be below the minimum size.
+	
+  const int genome_size = organism->GetGenome().GetSize();
+  const double size_range = cConfig::GetChildSizeRange();
+  const int min_size = Max(MIN_CREATURE_SIZE, (int) (genome_size/size_range));
+  const int max_size = Min(MAX_CREATURE_SIZE, (int) (genome_size*size_range));
+  
+  if (child_size < min_size || child_size > max_size) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+					cStringUtil::Stringf("Invalid offspring length (%d)", child_size));
+    return false; // (divide fails)
+  }
+	
+  // Count the number of lines executed in the parent, and make sure the
+  // specified fraction has been reached.
+	
+  int executed_size = 0;
+  for (int i = 0; i < parent_size; i++) {
+    if (GetMemory(0).FlagExecuted(i)) executed_size++;
+  }
+	
+  const int min_exe_lines = (int) (parent_size * cConfig::GetMinExeLines());
+  if (executed_size < min_exe_lines) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+					cStringUtil::Stringf("Too few executed lines (%d < %d)",
+															 executed_size, min_exe_lines));
+    return false; // (divide fails)
+  }
+	
+  // Count the number of lines which were copied into the child, and make
+  // sure the specified fraction has been reached.
+	
+  int copied_size = 0;
+  for (int i = 0; i < GetMemory(mem_space).GetSize(); i++) {
+    if (GetMemory(mem_space).FlagCopied(i)) copied_size++;
+	}
+	
+  const int min_copied =  (int) (child_size * cConfig::GetMinCopiedLines());
+  if (copied_size < min_copied) {
+    Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+					cStringUtil::Stringf("Too few copied commands (%d < %d)",
+															 copied_size, min_copied));
+    return false; // (divide fails)
+  }
+	
+  // Save the information we collected here...
+  organism->GetPhenotype().SetLinesExecuted(executed_size);
+  organism->GetPhenotype().SetLinesCopied(copied_size);
+	
+  return true; // (divide succeeds!)
+}
+
+void cHardwareSMT::Divide_DoMutations(double mut_multiplier)
+{
+  sCPUStats & cpu_stats = organism->CPUStats();
+  cCPUMemory & child_genome = organism->ChildGenome();
+  
+  organism->GetPhenotype().SetDivType(mut_multiplier);
+	
+  // Divide Mutations
+  if (organism->TestDivideMut()) {
+    const UINT mut_line = g_random.GetUInt(child_genome.GetSize());
+    child_genome[mut_line] = GetRandomInst();
+    cpu_stats.mut_stats.divide_mut_count++;
+  }
+	
+  // Divide Insertions
+  if (organism->TestDivideIns() && child_genome.GetSize() < MAX_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(child_genome.GetSize() + 1);
+    child_genome.Insert(mut_line, GetRandomInst());
+    cpu_stats.mut_stats.divide_insert_mut_count++;
+  }
+	
+  // Divide Deletions
+  if (organism->TestDivideDel() && child_genome.GetSize() > MIN_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(child_genome.GetSize());
+    // if( child_genome.FlagCopied(mut_line) == true) copied_size_change--;
+    child_genome.Remove(mut_line);
+    cpu_stats.mut_stats.divide_delete_mut_count++;
+  }
+	
+  // Divide Mutations (per site)
+  if(organism->GetDivMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(child_genome.GetSize(), 
+																					 organism->GetDivMutProb() / mut_multiplier);
+    // If we have lines to mutate...
+    if( num_mut > 0 ){
+      for (int i = 0; i < num_mut; i++) {
+				int site = g_random.GetUInt(child_genome.GetSize());
+				child_genome[site]=GetRandomInst();
+				cpu_stats.mut_stats.div_mut_count++;
+      }
+    }
+  }
+	
+	
+  // Insert Mutations (per site)
+  if(organism->GetInsMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(child_genome.GetSize(),
+																					 organism->GetInsMutProb());
+    // If would make creature to big, insert up to MAX_CREATURE_SIZE
+    if( num_mut + child_genome.GetSize() > MAX_CREATURE_SIZE ){
+      num_mut = MAX_CREATURE_SIZE - child_genome.GetSize();
+    }
+    // If we have lines to insert...
+    if( num_mut > 0 ){
+      // Build a list of the sites where mutations occured
+      static int mut_sites[MAX_CREATURE_SIZE];
+      for (int i = 0; i < num_mut; i++) {
+				mut_sites[i] = g_random.GetUInt(child_genome.GetSize() + 1);
+      }
+      // Sort the list
+      qsort( (void*)mut_sites, num_mut, sizeof(int), &IntCompareFunction );
+      // Actually do the mutations (in reverse sort order)
+      for(int i = num_mut-1; i >= 0; i--) {
+				child_genome.Insert(mut_sites[i], GetRandomInst());
+				cpu_stats.mut_stats.insert_mut_count++;
+      }
+    }
+  }
+	
+	
+  // Delete Mutations (per site)
+  if( organism->GetDelMutProb() > 0 ){
+    int num_mut = g_random.GetRandBinomial(child_genome.GetSize(),
+																					 organism->GetDelMutProb());
+    // If would make creature too small, delete down to MIN_CREATURE_SIZE
+    if (child_genome.GetSize() - num_mut < MIN_CREATURE_SIZE) {
+      num_mut = child_genome.GetSize() - MIN_CREATURE_SIZE;
+    }
+		
+    // If we have lines to delete...
+    for (int i = 0; i < num_mut; i++) {
+      int site = g_random.GetUInt(child_genome.GetSize());
+      // if (child_genome.FlagCopied(site) == true) copied_size_change--;
+      child_genome.Remove(site);
+      cpu_stats.mut_stats.delete_mut_count++;
+    }
+  }
+	
+  // Mutations in the parent's genome
+  if (organism->GetParentMutProb() > 0) {
+    for (int i = 0; i < GetMemory(0).GetSize(); i++) {
+      if (organism->TestParentMut()) {
+				GetMemory(0)[i] = GetRandomInst();
+				cpu_stats.mut_stats.parent_mut_line_count++;
+      }
+    }
+  }
+	
+	
+  // Count up mutated lines
+  for(int i = 0; i < GetMemory(0).GetSize(); i++){
+    if (GetMemory(0).FlagPointMut(i) == true) {
+      cpu_stats.mut_stats.point_mut_line_count++;
+    }
+  }
+  for(int i = 0; i < child_genome.GetSize(); i++){
+    if( child_genome.FlagCopyMut(i) == true) {
+      cpu_stats.mut_stats.copy_mut_line_count++;
+    }
+  }
+}
+
+void cHardwareSMT::Inject_DoMutations(double mut_multiplier, cCPUMemory & injected_code)
+{
+  //sCPUStats & cpu_stats = organism->CPUStats();
+  //cCPUMemory & child_genome = organism->ChildGenome();
+  
+  organism->GetPhenotype().SetDivType(mut_multiplier);
+	
+  // Divide Mutations
+  if (organism->TestDivideMut()) {
+    const UINT mut_line = g_random.GetUInt(injected_code.GetSize());
+    injected_code[mut_line] = GetRandomInst();
+    //cpu_stats.mut_stats.divide_mut_count++;
+  }
+	
+  // Divide Insertions
+  if (organism->TestDivideIns() && injected_code.GetSize() < MAX_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(injected_code.GetSize() + 1);
+    injected_code.Insert(mut_line, GetRandomInst());
+    //cpu_stats.mut_stats.divide_insert_mut_count++;
+  }
+	
+  // Divide Deletions
+  if (organism->TestDivideDel() && injected_code.GetSize() > MIN_CREATURE_SIZE){
+    const UINT mut_line = g_random.GetUInt(injected_code.GetSize());
+    // if( injected_code.FlagCopied(mut_line) == true) copied_size_change--;
+    injected_code.Remove(mut_line);
+    //cpu_stats.mut_stats.divide_delete_mut_count++;
+  }
+	
+  // Divide Mutations (per site)
+  if(organism->GetDivMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(injected_code.GetSize(), 
+																					 organism->GetDivMutProb() / mut_multiplier);
+    // If we have lines to mutate...
+    if( num_mut > 0 ){
+      for (int i = 0; i < num_mut; i++) {
+				int site = g_random.GetUInt(injected_code.GetSize());
+				injected_code[site]=GetRandomInst();
+				//cpu_stats.mut_stats.div_mut_count++;
+      }
+    }
+  }
+	
+	
+  // Insert Mutations (per site)
+  if(organism->GetInsMutProb() > 0){
+    int num_mut = g_random.GetRandBinomial(injected_code.GetSize(),
+																					 organism->GetInsMutProb());
+    // If would make creature to big, insert up to MAX_CREATURE_SIZE
+    if( num_mut + injected_code.GetSize() > MAX_CREATURE_SIZE ){
+      num_mut = MAX_CREATURE_SIZE - injected_code.GetSize();
+    }
+    // If we have lines to insert...
+    if( num_mut > 0 ){
+      // Build a list of the sites where mutations occured
+      static int mut_sites[MAX_CREATURE_SIZE];
+      for (int i = 0; i < num_mut; i++) {
+				mut_sites[i] = g_random.GetUInt(injected_code.GetSize() + 1);
+      }
+      // Sort the list
+      qsort( (void*)mut_sites, num_mut, sizeof(int), &IntCompareFunction );
+      // Actually do the mutations (in reverse sort order)
+      for(int i = num_mut-1; i >= 0; i--) {
+				injected_code.Insert(mut_sites[i], GetRandomInst());
+				//cpu_stats.mut_stats.insert_mut_count++;
+      }
+    }
+  }
+	
+	
+  // Delete Mutations (per site)
+  if( organism->GetDelMutProb() > 0 ){
+    int num_mut = g_random.GetRandBinomial(injected_code.GetSize(),
+																					 organism->GetDelMutProb());
+    // If would make creature too small, delete down to MIN_CREATURE_SIZE
+    if (injected_code.GetSize() - num_mut < MIN_CREATURE_SIZE) {
+      num_mut = injected_code.GetSize() - MIN_CREATURE_SIZE;
+    }
+		
+    // If we have lines to delete...
+    for (int i = 0; i < num_mut; i++) {
+      int site = g_random.GetUInt(injected_code.GetSize());
+      // if (injected_code.FlagCopied(site) == true) copied_size_change--;
+      injected_code.Remove(site);
+      //cpu_stats.mut_stats.delete_mut_count++;
+    }
+  }
+	
+  // Mutations in the parent's genome
+  if (organism->GetParentMutProb() > 0) {
+    for (int i = 0; i < GetMemory(0).GetSize(); i++) {
+      if (organism->TestParentMut()) {
+				GetMemory(0)[i] = GetRandomInst();
+				//cpu_stats.mut_stats.parent_mut_line_count++;
+      }
+    }
+  }
+	
+  /*
+	 // Count up mutated lines
+	 for(int i = 0; i < GetMemory(0).GetSize(); i++){
+		 if (GetMemory(0).FlagPointMut(i) == true) {
+			 cpu_stats.mut_stats.point_mut_line_count++;
+		 }
+	 }
+	 for(int i = 0; i < injected_code.GetSize(); i++){
+		 if( injected_code.FlagCopyMut(i) == true) {
+			 cpu_stats.mut_stats.copy_mut_line_count++;
+		 }
+	 }*/
+}
+
+
+// test whether the offspring creature contains an advantageous mutation.
+void cHardwareSMT::Divide_TestFitnessMeasures()
+{
+  cPhenotype & phenotype = organism->GetPhenotype();
+  phenotype.CopyTrue() = ( organism->ChildGenome() == organism->GetGenome() );
+  phenotype.ChildFertile() = true;
+	
+  // Only continue if we're supposed to do a fitness test on divide...
+  if (organism->GetTestOnDivide() == false) return;
+	
+  // If this was a perfect copy, then we don't need to worry about any other
+  // tests...  Theoretically, we need to worry about the parent changing,
+  // but as long as the child is always compared to the original genotype,
+  // this won't be an issue.
+  if (phenotype.CopyTrue() == true) return;
+	
+  const double parent_fitness = organism->GetTestFitness();
+  const double neut_min = parent_fitness * FITNESS_NEUTRAL_MIN;
+  const double neut_max = parent_fitness * FITNESS_NEUTRAL_MAX;
+  
+  cCPUTestInfo test_info;
+  test_info.UseRandomInputs();
+  cTestCPU::TestGenome(test_info, organism->ChildGenome());
+  const double child_fitness = test_info.GetGenotypeFitness();
+  
+  bool revert = false;
+  bool sterilize = false;
+  
+  // If implicit mutations are turned off, make sure this won't spawn one.
+  if (organism->GetFailImplicit() == true) {
+    if (test_info.GetMaxDepth() > 0) sterilize = true;
+  }
+  
+  if (child_fitness == 0.0) {
+    // Fatal mutation... test for reversion.
+    if (g_random.P(organism->GetRevertFatal())) revert = true;
+    if (g_random.P(organism->GetSterilizeFatal())) sterilize = true;
+  } else if (child_fitness < neut_min) {
+    if (g_random.P(organism->GetRevertNeg())) revert = true;
+    if (g_random.P(organism->GetSterilizeNeg())) sterilize = true;
+  } else if (child_fitness <= neut_max) {
+    if (g_random.P(organism->GetRevertNeut())) revert = true;
+    if (g_random.P(organism->GetSterilizeNeut())) sterilize = true;
+  } else {
+    if (g_random.P(organism->GetRevertPos())) revert = true;
+    if (g_random.P(organism->GetSterilizePos())) sterilize = true;
+  }
+  
+  // Ideally, we won't have reversions and sterilizations turned on at the
+  // same time, but if we do, give revert the priority.
+  if (revert == true) {
+    organism->ChildGenome() = organism->GetGenome();
+  }
+	
+  if (sterilize == true) {
+    organism->GetPhenotype().ChildFertile() = false;
+  }
+}
+
+
+bool cHardwareSMT::Divide_Main(int mem_space_used, double mut_multiplier)
+{
+  int write_head_pos = GetHead(HEAD_WRITE).GetPosition();
+  
+  // We're going to disallow division calls from memory spaces other than zero 
+  // for right now -law
+  if(IP().GetMemSpace()!=0)
+    return false;
+	
+  // Make sure this divide will produce a viable offspring.
+  if(!Divide_CheckViable(GetMemory(IP().GetMemSpace()).GetSize(), 
+												 write_head_pos, mem_space_used)) 
+    return false;
+  
+  // Since the divide will now succeed, set up the information to be sent
+  // to the new organism
+  cGenome & child_genome = organism->ChildGenome();
+  GetMemory(mem_space_used).Resize(write_head_pos);
+  child_genome = GetMemory(mem_space_used);
+	
+  // Handle Divide Mutations...
+  Divide_DoMutations(mut_multiplier);
+	
+  // Many tests will require us to run the offspring through a test CPU;
+  // this is, for example, to see if mutations need to be reverted or if
+  // lineages need to be updated.
+  Divide_TestFitnessMeasures();
+	
+#ifdef INSTRUCTION_COSTS
+  // reset first time instruction costs
+  for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+    inst_ft_cost[i] = GetInstSet().GetFTCost(cInstruction(i));
+  }
+#endif
+	
+  bool parent_alive = organism->ActivateDivide();
+	
+  //reset the memory of the memory space that has been divided off
+  GetMemory(mem_space_used)=cGenome(ConvertToInstruction(mem_space_used)); 
+	
+  // 3 Division Methods:
+  // 1) DIVIDE_METHOD_OFFSPRING - Create a child, leave parent state untouched.
+  // 2) DIVIDE_METHOD_SPLIT - Create a child, completely reset state of parent.
+  // 3) DIVIDE_METHOD_BIRTH - Create a child, reset state of parent's current thread.
+  if(parent_alive && !(cConfig::GetDivideMethod() == DIVIDE_METHOD_OFFSPRING))
+	{
+		
+		if(cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT)
+		{
+			//this will wipe out all parasites on a divide.
+			Reset();
+			
+		}
+		else if(cConfig::GetDivideMethod() == DIVIDE_METHOD_BIRTH)
+		{
+			//if this isn't the only thread, get rid of it!
+			// ***this can cause a concurrency problem if we have 
+			// multiprocessor support for single organisms...don't 
+			// think that's happening anytime soon though -law ***
+			if(!organism->GetPhenotype().IsModified() && GetNumThreads()>1 || 
+				 GetNumThreads()>2)
+	    {
+	      KillThread();
+	    }
+			
+			//this will reset the current thread's heads and stacks.  It will 
+			//not touch any other threads or memory spaces (ie: parasites)
+			else
+	    {
+	      for(int x=0; x<NUM_HEADS; x++)
+				{
+					GetHead(x).Reset(0, this);
+				}
+	      for(int x=0; x<NUM_LOCAL_STACKS; x++)
+				{
+					Stack(x).Clear();
+				}	  
+	    }
+		}
+		AdvanceIP()=false;
+	}
+	
+  return true;
+}
+
+cString cHardwareSMT::ConvertToInstruction(int mem_space_used)
+{
+  char c = mem_space_used + 97;  // 97 - ASCII for 'a'
+  cString ret;
+  ret += c;
+  return ret;
+}
+
+cString cHardwareSMT::GetActiveStackID(int stackID) const
+{
+  if(stackID==STACK_AX)
+    return "AX";
+  else if(stackID==STACK_BX)
+    return "BX";
+  else if(stackID==STACK_CX)
+    return "CX";
+  else if(stackID==STACK_DX)
+    return "DX";
+  else
+    return "";
+}
+
+
+//////////////////////////
+// And the instructions...
+//////////////////////////
+
+//6
+bool cHardwareSMT::Inst_ShiftR()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  int value = Stack(stack_used).Pop();
+  value >>= 1;
+  Stack(stack_used).Push(value);
+  return true;
+}
+
+//7
+bool cHardwareSMT::Inst_ShiftL()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  int value = Stack(stack_used).Pop();
+  value <<= 1;
+  Stack(stack_used).Push(value);
+  return true;
+}
+
+//8
+bool cHardwareSMT::Inst_Val_Nand()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(~(Stack(STACK_BX).Top() & Stack(STACK_CX).Top()));
+  return true;
+}
+
+//9
+bool cHardwareSMT::Inst_Val_Add()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(Stack(STACK_BX).Top() + Stack(STACK_CX).Top());
+  return true;
+}
+
+//10
+bool cHardwareSMT::Inst_Val_Sub()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(Stack(STACK_BX).Top() - Stack(STACK_CX).Top());
+  return true;
+}
+
+//11
+bool cHardwareSMT::Inst_Val_Mult()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(Stack(STACK_BX).Top() * Stack(STACK_CX).Top());
+  return true;
+}
+
+//12
+bool cHardwareSMT::Inst_Val_Div()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  if (Stack(STACK_CX).Top() != 0) {
+    if (0-INT_MAX > Stack(STACK_BX).Top() && Stack(STACK_CX).Top() == -1)
+      Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: Float exception");
+    else
+      Stack(stack_used).Push(Stack(STACK_BX).Top() / Stack(STACK_CX).Top());
+  } else {
+    Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: dividing by 0");
+    return false;
+  }
+  return true;
+}
+
+//13 
+bool cHardwareSMT::Inst_SetMemory()   // Allocate maximal more
+{
+  int mem_space_used = FindModifiedStack(-1);
+  
+  if(mem_space_used==-1) {
+    mem_space_used = FindFirstEmpty();
+    if(mem_space_used==-1)
+      return false;
+  }
+  
+  GetHead(HEAD_FLOW).Set(0, mem_space_used);
+  return true;
+  
+  //const int cur_size = GetMemory(0).GetSize();
+  //const int alloc_size = Min((int) (cConfig::GetChildSizeRange() * cur_size),
+  //			     MAX_CREATURE_SIZE - cur_size);
+  //if( Allocate_Main(alloc_size) ) {
+  //  Stack(STACK_AX).Push(cur_size);
+  //  return true;
+  //} else return false;
+}
+
+//14
+bool cHardwareSMT::Inst_Divide()
+{
+  int mem_space_used = GetHead(HEAD_WRITE).GetMemSpace();
+  int mut_multiplier = 1;
+	
+  return Divide_Main(mem_space_used, mut_multiplier);
+}
+
+bool cHardwareSMT::Inst_HeadDivideMut(double mut_multiplier)
+{
+  // Unused for the moment...
+  return true;
+  //AdjustHeads();
+  //const int divide_pos = GetHead(HEAD_READ).GetPosition();
+  //int child_end =  GetHead(HEAD_WRITE).GetPosition();
+  //if (child_end == 0) child_end = GetMemory(0).GetSize();
+  //const int extra_lines = GetMemory(0).GetSize() - child_end;
+  //bool ret_val = Divide_Main(divide_pos, extra_lines, mut_multiplier);
+  //// Re-adjust heads.
+  //AdjustHeads();
+  //return ret_val; 
+}
+
+//15
+bool cHardwareSMT::Inst_HeadRead()
+{
+  const int head_id = FindModifiedHead(HEAD_READ);
+  GetHead(head_id).Adjust();
+  sCPUStats & cpu_stats = organism->CPUStats();
+	
+  // Mutations only occur on the read, for the moment.
+  int read_inst = 0;
+  if (organism->TestCopyMut()) {
+    read_inst = GetRandomInst().GetOp();
+    cpu_stats.mut_stats.copy_mut_count++;  // @CAO, hope this is good!
+  } else {
+    read_inst = GetHead(head_id).GetInst().GetOp();
+  }
+  Stack(STACK_AX).Push(read_inst);
+  ReadInst(read_inst);
+	
+  cpu_stats.mut_stats.copies_exec++;  // @CAO, this too..
+  GetHead(head_id).Advance();
+  return true;
+}
+
+//16
+bool cHardwareSMT::Inst_HeadWrite()
+{
+  const int head_id = FindModifiedHead(HEAD_WRITE);
+  c4StackHead & active_head = GetHead(head_id);
+  int mem_space_used = active_head.GetMemSpace();
+  
+  //commented out for right now...
+  if(active_head.GetPosition()>=GetMemory(mem_space_used).GetSize()-1)
+	{
+		GetMemory(mem_space_used).Resize(GetMemory(mem_space_used).GetSize()+1);
+		GetMemory(mem_space_used).Copy(GetMemory(mem_space_used).GetSize()-1, GetMemory(mem_space_used).GetSize()-2);
+	}
+	
+  active_head.Adjust();
+	
+  int value = Stack(STACK_AX).Pop();
+  if (value < 0 || value >= GetNumInst()) value = 0;
+	
+  active_head.SetInst(cInstruction(value));
+  active_head.FlagCopied() = true;
+	
+  // Advance the head after write...
+  active_head++;
+  return true;
+}
+
+//??
+bool cHardwareSMT::Inst_HeadCopy()
+{
+  // For the moment, this cannot be nop-modified.
+  c4StackHead & read_head = GetHead(HEAD_READ);
+  c4StackHead & write_head = GetHead(HEAD_WRITE);
+  sCPUStats & cpu_stats = organism->CPUStats();
+	
+  read_head.Adjust();
+  write_head.Adjust();
+	
+  // TriggerMutations(MUTATION_TRIGGER_READ, read_head);
+  
+  // Do mutations.
+  cInstruction read_inst = read_head.GetInst();
+  if (organism->TestCopyMut()) {
+    read_inst = GetRandomInst();
+    cpu_stats.mut_stats.copy_mut_count++; 
+    write_head.FlagMutated() = true;
+    write_head.FlagCopyMut() = true;
+    //organism->GetPhenotype().IsMutated() = true;
+  }
+  ReadInst(read_inst.GetOp());
+	
+  cpu_stats.mut_stats.copies_exec++;
+	
+  write_head.SetInst(read_inst);
+  write_head.FlagCopied() = true;  // Set the copied flag...
+	
+  // TriggerMutations(MUTATION_TRIGGER_WRITE, write_head);
+	
+  read_head.Advance();
+  write_head.Advance();
+  return true;
+}
+
+//17
+bool cHardwareSMT::Inst_IfEqual()      // Execute next if bx == ?cx?
+{
+  const int stack_used = FindModifiedStack(STACK_AX);
+  const int stack_used2 = (stack_used+1)%NUM_STACKS;
+  if (Stack(stack_used).Top() != Stack(stack_used2).Top())  IP().Advance();
+  return true;
+}
+
+//18
+bool cHardwareSMT::Inst_IfNotEqual()     // Execute next if bx != ?cx?
+{
+  const int stack_used = FindModifiedStack(STACK_AX);
+  const int stack_used2 = (stack_used+1)%NUM_STACKS;
+  if (Stack(stack_used).Top() == Stack(stack_used2).Top())  IP().Advance();
+  return true;
+}
+
+//19
+bool cHardwareSMT::Inst_IfLess()       // Execute next if ?bx? < ?cx?
+{
+  const int stack_used = FindModifiedStack(STACK_AX);
+  const int stack_used2 = (stack_used+1)%NUM_STACKS;
+  if (Stack(stack_used).Top() >=  Stack(stack_used2).Top())  IP().Advance();
+  return true;
+}
+
+//20
+bool cHardwareSMT::Inst_IfGreater()       // Execute next if bx > ?cx?
+{
+  const int stack_used = FindModifiedStack(STACK_AX);
+  const int stack_used2 = (stack_used+1)%NUM_STACKS;
+  if (Stack(stack_used).Top() <= Stack(stack_used2).Top())  IP().Advance();
+  return true;
+}
+
+//21
+bool cHardwareSMT::Inst_HeadPush()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  Stack(STACK_BX).Push(GetHead(head_used).GetPosition());
+  //if (head_used == HEAD_IP) {
+  //  GetHead(head_used).Set(GetHead(HEAD_FLOW));
+  //  AdvanceIP() = false;
+  //}
+  return true;
+}
+
+//22
+bool cHardwareSMT::Inst_HeadPop()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  GetHead(head_used).Set(Stack(STACK_BX).Pop(), 
+												 GetHead(head_used).GetMemSpace(), this);
+  return true;
+}
+
+//23 
+bool cHardwareSMT::Inst_HeadMove()
+{
+  const int head_used = FindModifiedHead(HEAD_IP);
+  if(head_used != HEAD_FLOW)
+	{
+		GetHead(head_used).Set(GetHead(HEAD_FLOW));
+		if (head_used == HEAD_IP) AdvanceIP() = false;
+	}
+  else
+	{
+		threads[cur_thread].heads[HEAD_FLOW]++;
+	}
+  return true;
+}
+
+//24
+bool cHardwareSMT::Inst_Search()
+{
+  ReadLabel();
+  GetLabel().Rotate(2, NUM_NOPS_4STACK);
+  c4StackHead found_pos = FindLabel(0);
+  if(found_pos.GetPosition()-IP().GetPosition()==0)
+	{
+		GetHead(HEAD_FLOW).Set(IP().GetPosition()+1, IP().GetMemSpace(), this);
+		// pushing zero into STACK_AX on a missed search makes it difficult to create
+		// a self-replicating organism.  -law
+		//Stack(STACK_AX).Push(0);
+		Stack(STACK_BX).Push(0);
+	}
+  else
+	{
+		int search_size = found_pos.GetPosition() - IP().GetPosition() + GetLabel().GetSize() + 1;
+		Stack(STACK_BX).Push(search_size);
+		Stack(STACK_AX).Push(GetLabel().GetSize());
+		GetHead(HEAD_FLOW).Set(found_pos);
+	}  
+  
+  return true; 
+}
+
+//25
+bool cHardwareSMT::Inst_PushNext() 
+{
+  int stack_used = FindModifiedStack(STACK_AX);
+  int successor = (stack_used+1)%NUM_STACKS;
+  Stack(successor).Push(Stack(stack_used).Pop());
+  return true;
+}
+
+//26
+bool cHardwareSMT::Inst_PushPrevious() 
+{
+  int stack_used = FindModifiedStack(STACK_BX);
+  int predecessor = (stack_used+NUM_STACKS-1)%NUM_STACKS;
+  Stack(predecessor).Push(Stack(stack_used).Pop());
+  return true;
+}
+
+//27
+bool cHardwareSMT::Inst_PushComplement() 
+{
+  int stack_used = FindModifiedStack(STACK_BX);
+  int complement = FindComplementStack(stack_used);
+  Stack(complement).Push(Stack(stack_used).Pop());
+  return true;
+}
+
+//28
+bool cHardwareSMT::Inst_ValDelete()
+{
+  int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Pop();
+  return true;
+}
+
+//29
+bool cHardwareSMT::Inst_ValCopy()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  Stack(stack_used).Push(Stack(stack_used).Top());
+  return true;
+}
+
+//30
+bool cHardwareSMT::Inst_ForkThread()
+{
+  if (!ForkThread()) 
+    Fault(FAULT_LOC_THREAD_FORK, FAULT_TYPE_FORK_TH);
+  else
+    IP().Advance();
+  return true;
+}
+
+//31
+bool cHardwareSMT::Inst_IfLabel()
+{
+  ReadLabel();
+  GetLabel().Rotate(2, NUM_NOPS_4STACK);
+  if (GetLabel() != GetReadLabel())  IP().Advance();
+  return true;
+}
+
+//32
+bool cHardwareSMT::Inst_Increment()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  int value = Stack(stack_used).Pop();
+  Stack(stack_used).Push(++value);
+  return true;
+}
+
+//33
+bool cHardwareSMT::Inst_Decrement()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  int value = Stack(stack_used).Pop();
+  Stack(stack_used).Push(--value);
+  return true;
+}
+
+//34
+bool cHardwareSMT::Inst_Mod()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+  if (Stack(STACK_CX).Top() != 0) {
+    if(Stack(STACK_CX).Top() == -1)
+      Stack(stack_used).Push(0);
+    else
+      Stack(stack_used).Push(Stack(STACK_BX).Top() % Stack(STACK_CX).Top());
+  } else {
+    Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "mod: modding by 0");
+		return false;
+  }
+  return true;
+}
+
+//35
+bool cHardwareSMT::Inst_KillThread()
+{
+  if (!KillThread()) Fault(FAULT_LOC_THREAD_KILL, FAULT_TYPE_KILL_TH);
+  else AdvanceIP() = false;
+  return true;
+}
+
+//36
+bool cHardwareSMT::Inst_IO()
+{
+  const int stack_used = FindModifiedStack(STACK_BX);
+	
+  // Do the "put" component
+  const int value_out = Stack(stack_used).Top();
+  organism->DoOutput(value_out);  // Check for tasks compleated.
+	
+  // Do the "get" component
+  const int value_in = organism->GetNextInput();
+  Stack(stack_used).Push(value_in);
+  organism->DoInput(value_in);
+  return true;
+}
+
+int cHardwareSMT::FindFirstEmpty()
+{
+  bool OK=true;
+  const int current_mem_space = IP().GetMemSpace();
+	
+  for(int x=1; x<NUM_MEMORY_SPACES; x++)
+	{
+		OK=true;
+		
+		int index = (current_mem_space+x) % NUM_MEMORY_SPACES;
+		
+		for(int y=0; y<GetMemory(index).GetSize() && OK; y++)
+		{
+			if(GetMemory(index)[y].GetOp() >= NUM_NOPS_4STACK)
+				OK=false; 
+		}
+		for(int y=0; y<GetNumThreads() && OK; y++)
+		{
+			for(int z=0; z<NUM_HEADS; z++)
+	    {
+	      if(threads[y].heads[z].GetMemSpace() == index)
+					OK=false;
+	    }
+		}
+		if(OK)
+			return index;
+	}
+  return -1;
+}
+
+bool cHardwareSMT::isEmpty(int mem_space_used)
+{
+  for(int x=0; x<GetMemory(mem_space_used).GetSize(); x++)
+	{
+		if(GetMemory(mem_space_used)[x].GetOp() >= NUM_NOPS_4STACK)
+			return false;
+	}
+  return true;
+}
+
+// The inject instruction can be used instead of a divide command, paired
+// with an allocate.  Note that for an inject to work, one needs to have a
+// broad range for sizes allowed to be allocated.
+//
+// This command will cut out from read-head to write-head.
+// It will then look at the template that follows the command and inject it
+// into the complement template found in a neighboring organism.
+
+bool cHardwareSMT::Inst_Inject()
+{
+  double mut_multiplier = 1;
+	
+  return InjectParasite(mut_multiplier);
+}
+
+
+
+/*
+ bool cHardwareSMT::Inst_InjectRand()
+ {
+	 // Rotate to a random facing and then run the normal inject instruction
+	 const int num_neighbors = organism->GetNeighborhoodSize();
+	 organism->Rotate(g_random.GetUInt(num_neighbors));
+	 Inst_Inject();
+	 return true;
+ }
+ 
+ */

Added: branches/brysonda/source/cpu/hardware_smt.h
===================================================================
--- branches/brysonda/source/cpu/hardware_smt.h	2005-06-04 18:34:03 UTC (rev 176)
+++ branches/brysonda/source/cpu/hardware_smt.h	2005-06-04 19:16:19 UTC (rev 177)
@@ -0,0 +1,517 @@
+/*
+ *  hardware_smt.h
+ *  Avida2
+ *
+ *  Created by David on 6/4/05.
+ *  Copyright 2005 Michigan State University. All rights reserved.
+ *
+ */
+
+#ifndef HARDWARE_SMT_HH
+#define HARDWARE_SMT_HH
+
+#include <iomanip>
+
+#ifndef CPU_MEMORY_HH
+#include "cpu_memory.hh"
+#endif
+#ifndef CPU_STACK_HH
+#include "cpu_stack.hh"
+#endif
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef FOURSTACK_HEAD_HH
+#include "4stack_head.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "hardware_base.hh"
+#endif
+#ifndef HARDWARE_4STACK_CONSTANTS_HH
+#include "hardware_4stack_constants.hh"
+#endif
+#ifndef HARDWARE_4STACK_THREAD_HH
+#include "hardware_4stack_thread.hh"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+class cInstSet;
+class cInstLibBase;
+class cOrganism;
+class cMutation;
+class cInjectGenotype;
+
+#ifdef SINGLE_IO_BUFFER   // For Single IOBuffer vs IOBuffer for each Thread
+# define IO_THREAD 0
+#else
+# define IO_THREAD cur_thread
+#endif
+
+/**
+* Each organism may have a cHardwareSMT structure which keeps track of the
+ * current status of all the components of the simulated hardware.
+ *
+ * @see cHardwareSMT_Thread, cCPUStack, cCPUMemory, cInstSet
+ **/
+
+class cCodeLabel;
+class cCPUMemory;
+class cCPUStack; // aggregate
+class c4StackHead; // access
+class cGenome;
+class cHardwareSMT_Thread; // access
+class cInjectGenotype;
+class cInstLib4Stack; // access
+class cInstruction;
+class cInstSet;
+class cOrganism;
+class cString; // aggregate
+template <class T> class tArray; // aggregate
+
+class cHardwareSMT : public cHardwareBase {
+public:
+  typedef bool (cHardwareSMT::*tMethod)();
+private:
+  static cInstLib4Stack *s_inst_slib;
+  static cInstLib4Stack *initInstLib(void);
+  tHardware4StackMethod *m_functions;
+private:
+		tArray<cCPUMemory> memory_array;          // Memory...
+																							//cCPUStack global_stack;     // A stack that all threads share.
+  cCPUStack global_stacks[NUM_GLOBAL_STACKS];
+  //int thread_time_used;
+	
+  tArray<cHardwareSMT_Thread> threads;
+  int thread_id_chart;
+  int cur_thread;
+	
+  // Flags...
+  bool mal_active;         // Has an allocate occured since last dividehe?
+													 //bool advance_ip;         // Should the IP advance after this instruction?
+	
+  // Instruction costs...
+#ifdef INSTRUCTION_COSTS
+  tArray<int> inst_cost;
+  tArray<int> inst_ft_cost;
+#endif
+	
+  // Thread slicing...
+	
+	// Keeps track of the base thread slicing number for each possible number of threads
+  float slice_array[10]; //***HACK!  How do I do this right? -law
+                         //this wouldn't compile -> [cConfig::GetMaxCPUThreads()+1]***; 
+	
+  // Keeps track of fractional instructions that carry over into next update
+  float inst_remainder; 
+	
+public:
+		cHardwareSMT(cOrganism * in_organism, cInstSet * in_inst_set);
+  explicit cHardwareSMT(const cHardwareSMT &);
+  ~cHardwareSMT() { ; }
+  void Recycle(cOrganism * new_organism, cInstSet * in_inst_set);
+  static cInstLibBase *GetInstLib();
+  static cString GetDefaultInstFilename() { return "inst_lib.4stack"; }
+  static void WriteDefaultInstSet() { ; }
+	
+  void Reset();
+  void SingleProcess();
+  bool SingleProcess_PayCosts(const cInstruction & cur_inst);
+  bool SingleProcess_ExecuteInst(const cInstruction & cur_inst);
+  void ProcessBonusInst(const cInstruction & inst);
+  void LoadGenome(const cGenome & new_genome);
+	
+  // --------  Helper methods  --------
+  bool OK();
+  void PrintStatus(std::ostream & fp);
+	
+	
+  // --------  Flag Accessors --------
+  bool GetMalActive() const   { return mal_active; }
+	
+  // --------  Stack Manipulation...  --------
+  //void StackFlip();
+  inline int GetStack(int depth=0, int stack_id=-1, int in_thread=-1) const;
+  //inline void StackClear();
+  //inline void SwitchStack();
+  cString GetActiveStackID(int stackID) const;
+  //retrieves appropriate stack
+  inline cCPUStack & Stack(int stack_id); 
+  inline const cCPUStack & Stack(int stack_id) const;
+  inline cCPUStack & Stack(int stack_id, int in_thread);
+  inline const cCPUStack & Stack(int stack_id, int in_thread) const;
+	
+  // --------  Head Manipulation (including IP)  --------
+  inline void SetActiveHead(const int new_head)
+  { threads[cur_thread].cur_head = (UCHAR) new_head; }
+	
+  int GetCurHead() const { return threads[cur_thread].cur_head; }
+  
+  const c4StackHead & GetHead(int head_id) const
+  { return threads[cur_thread].heads[head_id]; }
+  c4StackHead & GetHead(int head_id) 
+  { return threads[cur_thread].heads[head_id];}
+  
+  const c4StackHead & GetHead(int head_id, int thread) const
+  { return threads[thread].heads[head_id]; }
+  c4StackHead & GetHead(int head_id, int thread) 
+  { return threads[thread].heads[head_id];}
+	
+  const c4StackHead & GetActiveHead() const { return GetHead(GetCurHead()); }
+  c4StackHead & GetActiveHead() { return GetHead(GetCurHead()); }
+	
+  void AdjustHeads();
+	
+  inline const c4StackHead & IP() const
+	{ return threads[cur_thread].heads[HEAD_IP]; }
+  inline c4StackHead & IP() { return threads[cur_thread].heads[HEAD_IP]; }
+	
+  inline const c4StackHead & IP(int thread) const
+  { return threads[thread].heads[HEAD_IP]; }
+  inline c4StackHead & IP(int thread) 
+  { return threads[thread].heads[HEAD_IP]; }
+	
+	
+  inline const bool & AdvanceIP() const
+	{ return threads[cur_thread].advance_ip; }
+  inline bool & AdvanceIP() { return threads[cur_thread].advance_ip; }
+	
+  // --------  Label Manipulation  -------
+  void ReadLabel(int max_size=MAX_LABEL_SIZE);
+  const cCodeLabel & GetLabel() const 
+	{ return threads[cur_thread].next_label; }
+  cCodeLabel & GetLabel() { return threads[cur_thread].next_label; }
+  const cCodeLabel & GetReadLabel() const
+	{ return threads[cur_thread].read_label; }
+  cCodeLabel & GetReadLabel() { return threads[cur_thread].read_label; }
+	
+	
+  // --------  Register Manipulation  --------
+  //int Register(int reg_id) const { return threads[cur_thread].reg[reg_id]; }
+  //int & Register(int reg_id) { return threads[cur_thread].reg[reg_id]; }
+	
+  // --------  Memory Manipulation  --------}
+  inline cCPUMemory & GetMemory();
+  inline cCPUMemory & GetMemory(int mem_space);
+  inline const cCPUMemory & GetMemory(int mem_space) const;
+  inline const cCPUMemory & GetMemory() const;
+	
+  // --------  Thread Manipulation  --------
+  bool ForkThread(); // Adds a new thread based off of cur_thread.
+  bool KillThread(); // Kill the current thread!
+  inline void PrevThread(); // Shift the current thread in use.
+  inline void NextThread();
+  inline void SetThread(int value);
+  inline cInjectGenotype * GetCurThreadOwner(); 
+  inline cInjectGenotype * GetThreadOwner(int in_thread);
+  inline void SetThreadOwner(cInjectGenotype * in_genotype);
+	
+  // --------  Tests  --------
+	
+  int TestParasite() const;
+	
+  // --------  Accessors  --------
+  //int GetThreadTimeUsed() const { return thread_time_used; }
+  int GetNumThreads() const     { return threads.GetSize(); }
+  int GetCurThread() const      { return cur_thread; }
+  int GetCurThreadID() const    { return threads[cur_thread].GetID(); }
+	
+  int GetThreadDist() const {
+    if (GetNumThreads() == 1) return 0;
+    return threads[0].heads[HEAD_IP].GetPosition() -
+      threads[1].heads[HEAD_IP].GetPosition();
+  }
+	
+  // Complex label manipulation...
+  c4StackHead FindLabel(int direction);
+  int FindLabel_Forward(const cCodeLabel & search_label,
+												const cGenome & search_genome, int pos);
+  int FindLabel_Backward(const cCodeLabel & search_label,
+												 const cGenome & search_genome, int pos);
+  c4StackHead FindLabel(const cCodeLabel & in_label, int direction);
+  c4StackHead FindFullLabel(const cCodeLabel & in_label);
+	
+  int GetType() const { return HARDWARE_TYPE_CPU_4STACK; }
+  bool InjectParasite(double mut_multiplier);
+  bool InjectHost(const cCodeLabel & in_label, const cGenome & injection);
+  int InjectThread(const cCodeLabel &, const cGenome &) { return -1; }
+  void Mutate(const int mut_point);
+  int PointMutate(const double mut_rate);
+  int FindFirstEmpty();
+  bool isEmpty(int mem_space_used);
+	
+  bool TriggerMutations(int trigger);
+  bool TriggerMutations(int trigger, c4StackHead & cur_head);
+  bool TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+																		cCPUMemory & target_memory, c4StackHead & cur_head, const double rate);
+  bool TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+																	 cCPUMemory & target_memory, c4StackHead & cur_head, const double rate);
+  int TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+																	 cCPUMemory & target_memory, c4StackHead & cur_head, const double rate);
+  void TriggerMutations_Body(int type, cCPUMemory & target_memory,
+														 c4StackHead & cur_head);
+	
+  void ReadInst(const int in_inst);
+	
+  void SaveState(std::ostream & fp);
+  void LoadState(std::istream & fp);
+	
+  //void InitInstSet(const cString & filename, cInstSet & inst_set);
+  cString ConvertToInstruction(int mem_space_used);
+	
+	
+private:
+		
+		/////////---------- Instruction Helpers ------------//////////
+		
+		int FindModifiedStack(int default_stack);
+  int FindModifiedHead(int default_head);
+  int FindComplementStack(int base_stack);
+	
+  void Fault(int fault_loc, int fault_type, cString fault_desc=""); 
+  bool Allocate_Necro(const int new_size);
+  bool Allocate_Random(const int old_size, const int new_size);
+  bool Allocate_Default(const int new_size);
+  bool Allocate_Main(const int allocated_size);
+	
+  bool Divide_Main(const int mem_space_used, double mut_multiplier=1);
+  bool Divide_CheckViable(const int parent_size, const int child_size, const int mem_space);
+  void Divide_DoMutations(double mut_multiplier=1);
+  void Inject_DoMutations(double mut_multiplier, cCPUMemory & injected_code);
+  void Divide_TestFitnessMeasures();
+	
+  bool HeadCopy_ErrorCorrect(double reduction);
+  bool Inst_HeadDivideMut(double mut_multiplier=1);
+	
+public:
+		/////////---------- Instruction Library ------------//////////
+		
+		//6
+		bool Inst_ShiftR();
+  //7
+  bool Inst_ShiftL();
+  //8
+  bool Inst_Val_Nand();
+  //9
+  bool Inst_Val_Add();
+  //10
+  bool Inst_Val_Sub();
+  //11
+  bool Inst_Val_Mult();
+  //12
+  bool Inst_Val_Div();
+  //13
+  bool Inst_SetMemory();
+  //14
+  bool Inst_Divide();
+  //15
+  bool Inst_HeadRead();
+  //16
+  bool Inst_HeadWrite();
+  //??
+  bool Inst_HeadCopy();
+  //17
+  bool Inst_IfEqual();
+  //18
+  bool Inst_IfNotEqual();
+  //19
+  bool Inst_IfLess();
+  //20
+  bool Inst_IfGreater();
+  //21
+  bool Inst_HeadPush();
+  //22
+  bool Inst_HeadPop();
+  //23
+  bool Inst_HeadMove();
+  //24
+  bool Inst_Search();
+  //25
+  bool Inst_PushNext();
+  //26
+  bool Inst_PushPrevious();
+  //27
+  bool Inst_PushComplement();
+  //28
+  bool Inst_ValDelete();
+  //29
+  bool Inst_ValCopy();
+  //30
+  bool Inst_ForkThread();
+  //31
+  bool Inst_IfLabel();
+  //32
+  bool Inst_Increment();
+  //33
+  bool Inst_Decrement();
+  //34
+  bool Inst_Mod();
+  //35 
+  bool Inst_KillThread();
+  //36
+  bool Inst_IO();
+  //37
+  bool Inst_Inject();
+  
+  /*
+	 bool Inst_InjectRand();
+	 bool Inst_InjectThread();
+	 bool Inst_Repro();
+	 */
+	
+};
+
+
+//////////////////
+//  cHardwareSMT
+//////////////////
+
+//Not used, but here to satisfy the requirements of HardwareBase
+inline const cCPUMemory & cHardwareSMT::GetMemory() const
+{
+  return memory_array[0];
+}
+
+//Not used, but here to satisfy the requirements of HardwareBase 
+inline cCPUMemory & cHardwareSMT::GetMemory()
+{
+  return memory_array[0];
+}
+
+inline const cCPUMemory & cHardwareSMT::GetMemory(int mem_space) const
+{
+  if(mem_space >= NUM_MEMORY_SPACES)
+    mem_space %= NUM_MEMORY_SPACES;
+  return memory_array[mem_space];
+}
+
+inline cCPUMemory & cHardwareSMT::GetMemory(int mem_space)
+{
+	if(mem_space >= NUM_MEMORY_SPACES)
+    mem_space %= NUM_MEMORY_SPACES;
+  return memory_array[mem_space];
+}
+
+inline void cHardwareSMT::NextThread()
+{
+  cur_thread++;
+  if (cur_thread >= GetNumThreads()) cur_thread = 0;
+}
+
+inline void cHardwareSMT::PrevThread()
+{
+  if (cur_thread == 0) cur_thread = GetNumThreads() - 1;
+  else cur_thread--;
+}
+
+inline void cHardwareSMT::SetThread(int value)
+{
+  if (value>=0 && value < GetNumThreads())
+    cur_thread=value;
+}
+
+inline cInjectGenotype * cHardwareSMT::GetCurThreadOwner() 
+{ 
+  return threads[cur_thread].owner; 
+}
+
+inline cInjectGenotype * cHardwareSMT::GetThreadOwner(int thread) 
+{ 
+  return threads[thread].owner; 
+}
+
+inline void cHardwareSMT::SetThreadOwner(cInjectGenotype * in_genotype)
+{ 
+  threads[cur_thread].owner = in_genotype; 
+}
+
+/*inline void cHardwareSMT::StackFlip()
+{
+  if (threads[cur_thread].cur_stack == 0) {
+    threads[cur_thread].stack.Flip();
+  } else {
+    global_stack.Flip();
+  }
+}*/
+
+inline int cHardwareSMT::GetStack(int depth, int stack_id, int in_thread) const
+{
+  if(stack_id<0 || stack_id>NUM_STACKS) stack_id=0;
+  
+  if(in_thread==-1)
+    in_thread=cur_thread;
+  
+  return Stack(stack_id, in_thread).Get(depth);
+}
+
+//inline void cHardwareSMT::StackClear()
+//{
+
+//if (threads[cur_thread].cur_stack == 0) {
+//  threads[cur_thread].stack.Clear();
+//} else {
+//  global_stack.Clear();
+//}
+//}
+
+//inline void cHardwareSMT::SwitchStack()
+//{
+//  threads[cur_thread].cur_stack++;
+//  if (threads[cur_thread].cur_stack > 1) threads[cur_thread].cur_stack = 0;
+//}
+	
+inline cCPUStack& cHardwareSMT::Stack(int stack_id)
+{
+  if(stack_id >= NUM_STACKS)
+	{
+		stack_id=0;
+	}
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[cur_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
+inline const cCPUStack& cHardwareSMT::Stack(int stack_id) const 
+{
+  if(stack_id >= NUM_STACKS)
+	{
+		stack_id=0;
+	}
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[cur_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
+inline cCPUStack& cHardwareSMT::Stack(int stack_id, int in_thread) 
+{
+  if(stack_id >= NUM_STACKS)
+		stack_id=0;
+  if(in_thread >= threads.GetSize())
+		in_thread=cur_thread;
+	
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[in_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
+inline const cCPUStack& cHardwareSMT::Stack(int stack_id, int in_thread) const 
+{
+  if(stack_id >= NUM_STACKS)
+		stack_id=0;
+  if(in_thread >= threads.GetSize())
+		in_thread=cur_thread;
+	
+  if(stack_id < NUM_LOCAL_STACKS)
+    return threads[in_thread].local_stacks[stack_id];
+  else
+    return global_stacks[stack_id % NUM_LOCAL_STACKS];
+}
+
+#endif

Added: branches/brysonda/source/cpu/hardware_smt_thread.cc
===================================================================
--- branches/brysonda/source/cpu/hardware_smt_thread.cc	2005-06-04 18:34:03 UTC (rev 176)
+++ branches/brysonda/source/cpu/hardware_smt_thread.cc	2005-06-04 19:16:19 UTC (rev 177)
@@ -0,0 +1,111 @@
+/*
+ *  hardware_smt_thread.cc
+ *  Avida2
+ *
+ *  Created by David on 6/4/05.
+ *  Copyright 2005 Michigan State University. All rights reserved.
+ *
+ */
+
+#include "hardware_smt_thread.h"
+
+using namespace std;
+
+/////////////////////////
+//  cHardwareSMT_Thread
+/////////////////////////
+
+cHardwareSMT_Thread::cHardwareSMT_Thread(cHardwareBase * in_hardware, int _id)
+{
+  Reset(in_hardware, _id);
+}
+
+cHardwareSMT_Thread::cHardwareSMT_Thread(const cHardwareSMT_Thread & in_thread, int _id)
+{
+	id = _id;
+	if (id == -1) id = in_thread.id;
+	for (int i = 0; i < NUM_LOCAL_STACKS; i++) {
+		local_stacks[i] = in_thread.local_stacks[i];
+	}
+	for (int i = 0; i < NUM_HEADS; i++) {
+		heads[i] = in_thread.heads[i];
+	}
+	owner = in_thread.owner;
+}
+
+cHardwareSMT_Thread::~cHardwareSMT_Thread() {}
+
+void cHardwareSMT_Thread::operator=(const cHardwareSMT_Thread & in_thread)
+{
+  id = in_thread.id;
+  for (int i = 0; i < NUM_LOCAL_STACKS; i++) {
+    local_stacks[i] = in_thread.local_stacks[i];
+  }
+  for (int i = 0; i < NUM_HEADS; i++) {
+    heads[i] = in_thread.heads[i];
+  }
+  owner = in_thread.owner;
+}
+
+void cHardwareSMT_Thread::Reset(cHardwareBase * in_hardware, int _id)
+{
+  id = _id;
+	
+  for (int i = 0; i < NUM_LOCAL_STACKS; i++) local_stacks[i].Clear();
+  for (int i = 0; i < NUM_HEADS; i++) heads[i].Reset(0, in_hardware);
+	
+  cur_head = HEAD_IP;
+  read_label.Clear();
+  next_label.Clear();
+  owner = NULL;
+}
+
+void cHardwareSMT_Thread::SaveState(ostream & fp){
+  assert(fp.good());
+  fp << "cHardwareSMT_Thread" << endl;
+	
+  // stacks (NOT WORKING! -law)
+  for( int i=0; i<NUM_STACKS; ++i ){
+    local_stacks[i].SaveState(fp);
+  }
+	
+  // heads (@TCC does not handle parasites!!!)
+  for( int i=0; i<NUM_HEADS; ++i ){
+    fp<<heads[i].GetPosition()<<endl;
+  }
+	
+  fp<<"|"; // marker
+  fp<<cur_head;
+  fp<<endl;
+	
+  // Code labels
+  read_label.SaveState(fp);
+  next_label.SaveState(fp);
+}
+
+void cHardwareSMT_Thread::LoadState(istream & fp){
+  assert(fp.good());
+  cString foo;
+  fp >> foo;
+  assert( foo == "cHardwareSMT_Thread");
+	
+  // stacks (NOT WORKING!  -law)
+  for( int i=0; i<NUM_STACKS; ++i ){
+    local_stacks[i].LoadState(fp);
+  }
+	
+  // heads (@TCC does not handle parasites!!!)
+  for( int i=0; i<NUM_HEADS; ++i ){
+    int pos;
+    fp>>pos;
+    heads[i].AbsSet(pos);
+  }
+	
+  char marker; fp>>marker; assert( marker == '|' );
+  /* YIKES!  data loss below: */ 
+  char the_cur_head = cur_head;
+	
+  // Code labels
+  read_label.LoadState(fp);
+  next_label.LoadState(fp);
+}

Added: branches/brysonda/source/cpu/hardware_smt_thread.h
===================================================================
--- branches/brysonda/source/cpu/hardware_smt_thread.h	2005-06-04 18:34:03 UTC (rev 176)
+++ branches/brysonda/source/cpu/hardware_smt_thread.h	2005-06-04 19:16:19 UTC (rev 177)
@@ -0,0 +1,73 @@
+/*
+ *  hardware_smt_thread.h
+ *  Avida2
+ *
+ *  Created by David on 6/4/05.
+ *  Copyright 2005 Michigan State University. All rights reserved.
+ *
+ */
+
+#ifndef HARDWARE_SMT_THREAD_HH
+#define HARDWARE_SMT_THREAD_HH
+
+#include <iostream>
+
+#ifndef CODE_LABEL_HH
+#include "code_label.hh"
+#endif
+#ifndef CPU_STACK_HH
+#include "cpu_stack.hh"
+#endif
+#ifndef FOURSTACK_HEAD_HH
+#include "4stack_head.hh"
+#endif
+#ifndef HARDWARE_4STACK_CONSTANTS_HH
+#include "hardware_4stack_constants.hh"
+#endif
+#ifndef TBUFFER_HH
+#include "tBuffer.hh"
+#endif
+
+/**
+* This class is needed to run several threads on a single genome.
+ *
+ * @see cCPUStack, c4StackHead, cHardwareSMT
+ **/
+
+class c4StackHead; // aggregate
+class cCodeLabel; // aggregate
+class cCPUStack; // aggregate
+class cHardwareBase;
+class cInjectGenotype;
+template <class T> class tBuffer; // aggregate
+
+struct cHardwareSMT_Thread {
+private:
+  int id;
+public:
+  c4StackHead heads[NUM_HEADS];
+  UCHAR cur_head;
+  cCPUStack local_stacks[NUM_LOCAL_STACKS];
+	
+  bool advance_ip;         // Should the IP advance after this instruction?
+  cCodeLabel read_label;
+  cCodeLabel next_label;
+  // If this thread was spawned by Inject, this will point to the genotype 
+  // of the parasite running the thread.  Otherwise, it will be NULL.
+  cInjectGenotype* owner;
+public:
+		cHardwareSMT_Thread(cHardwareBase * in_hardware=NULL, int _id=-1);
+  cHardwareSMT_Thread(const cHardwareSMT_Thread & in_thread, int _id=-1);
+  ~cHardwareSMT_Thread();
+	
+  void operator=(const cHardwareSMT_Thread & in_thread);
+	
+  void Reset(cHardwareBase * in_hardware, int _id);
+  int GetID() const { return id; }
+  void SetID(int _id) { id = _id; }
+	
+  void SaveState(std::ostream & fp);
+  void LoadState(std::istream & fp);
+};
+
+#endif

Added: branches/brysonda/source/cpu/tInstLib.h
===================================================================
--- branches/brysonda/source/cpu/tInstLib.h	2005-06-04 18:34:03 UTC (rev 176)
+++ branches/brysonda/source/cpu/tInstLib.h	2005-06-04 19:16:19 UTC (rev 177)
@@ -0,0 +1,70 @@
+/*
+ *  tInstLib.h
+ *  Avida2
+ *
+ *  Created by David on 6/4/05.
+ *  Copyright 2005 Michigan State University. All rights reserved.
+ *
+ */
+
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef INST_LIB_BASE_HH
+#include "inst_lib_base.hh"
+#endif
+
+class cInstruction;
+
+template <class MethodType> class tInstLib : public cInstLibBase {
+  const size_t m_nopmods_array_size;
+  const size_t m_function_array_size;
+  cString *m_nopmod_names;
+  cString *m_function_names;
+  const int *m_nopmods;
+  MethodType *m_functions;
+  static const cInstruction inst_error;
+  static const cInstruction inst_default;
+public:
+		tInstLib(
+									 size_t nopmod_array_size,
+									 size_t function_array_size,
+									 cString *nopmod_names,
+									 cString *function_names,
+									 const int *nopmods,
+									 MethodType *functions
+									 ):m_nopmods_array_size(nopmod_array_size),
+    m_function_array_size(function_array_size),
+    m_nopmod_names(nopmod_names),
+    m_function_names(function_names),
+    m_nopmods(nopmods),
+    m_functions(functions)
+  {}
+  MethodType *GetFunctions(void){ return m_functions; } 
+  const cString &GetName(const unsigned int id) {
+    assert(id < m_function_array_size);
+    return m_function_names[id];
+  }
+  const cString &GetNopName(const unsigned int id) {
+    assert(id < m_nopmods_array_size);
+    return m_nopmod_names[id];
+  }
+  int GetNopMod(const unsigned int id){
+    assert(id < m_nopmods_array_size);
+    return m_nopmods[id];
+  }
+  int GetNopMod(const cInstruction & inst){
+    return GetNopMod(inst.GetOp());
+  }
+  int GetSize(){ return m_function_array_size; }
+  int GetNumNops(){ return m_nopmods_array_size; }
+  cInstruction GetInst(const cString & in_name){
+    for (unsigned int i = 0; i < m_function_array_size; i++) {
+      if (m_function_names[i] == in_name) return cInstruction(i);
+    }
+    return tInstLib::GetInstError();
+  }
+  const cInstruction & GetInstDefault(){ return inst_default; }
+  const cInstruction & GetInstError(){ return inst_error; }
+};
+




More information about the Avida-cvs mailing list