[Avida-cvs] [Avida2-svn] r300 - trunk/source/cpu
brysonda@myxo.css.msu.edu
brysonda at myxo.css.msu.edu
Mon Aug 29 12:51:42 PDT 2005
Author: brysonda
Date: 2005-08-29 15:51:42 -0400 (Mon, 29 Aug 2005)
New Revision: 300
Added:
trunk/source/cpu/cHardware4Stack.cc
trunk/source/cpu/cHardware4Stack.h
trunk/source/cpu/cHardware4Stack_Thread.cc
trunk/source/cpu/cHardware4Stack_Thread.h
trunk/source/cpu/cHardwareBase.cc
trunk/source/cpu/cHardwareBase.h
trunk/source/cpu/cHardwareCPU.cc
trunk/source/cpu/cHardwareCPU.h
trunk/source/cpu/cHardwareCPU_Thread.cc
trunk/source/cpu/cHardwareCPU_Thread.h
trunk/source/cpu/cHardwareFactory.cc
trunk/source/cpu/cHardwareFactory.h
Removed:
trunk/source/cpu/hardware_4stack.cc
trunk/source/cpu/hardware_4stack.hh
trunk/source/cpu/hardware_4stack_thread.cc
trunk/source/cpu/hardware_4stack_thread.hh
trunk/source/cpu/hardware_base.cc
trunk/source/cpu/hardware_base.hh
trunk/source/cpu/hardware_cpu.cc
trunk/source/cpu/hardware_cpu.hh
trunk/source/cpu/hardware_cpu_thread.cc
trunk/source/cpu/hardware_cpu_thread.hh
trunk/source/cpu/hardware_factory.cc
trunk/source/cpu/hardware_factory.hh
Modified:
trunk/source/cpu/CMakeLists.txt
trunk/source/cpu/cpu.pri
trunk/source/cpu/hardware_smt.h
trunk/source/cpu/hardware_status_printer.cc
trunk/source/cpu/hardware_util.cc
trunk/source/cpu/head_cpu.cc
trunk/source/cpu/head_multi_mem.cc
trunk/source/cpu/inst_lib_cpu.hh
trunk/source/cpu/test_cpu.cc
trunk/source/cpu/test_util.cc
Log:
Rename cpu/cHardwareCPU,cHardware4Stack,cHardwareBase,cHardwareFactory classes to reflect new naming conventions.
Modified: trunk/source/cpu/CMakeLists.txt
===================================================================
--- trunk/source/cpu/CMakeLists.txt 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/CMakeLists.txt 2005-08-29 19:51:42 UTC (rev 300)
@@ -3,12 +3,12 @@
cCPUMemory.cc
cCPUStack.cc
cCPUTestInfo.cc
- hardware_4stack.cc
- hardware_4stack_thread.cc
- hardware_base.cc
- hardware_cpu.cc
- hardware_cpu_thread.cc
- hardware_factory.cc
+ cHardware4Stack.cc
+ cHardware4Stack_Thread.cc
+ cHardwareBase.cc
+ cHardwareCPU.cc
+ cHardwareCPU_Thread.cc
+ cHardwareFactory.cc
hardware_smt.cc
hardware_smt_thread.cc
hardware_status_printer.cc
Copied: trunk/source/cpu/cHardware4Stack.cc (from rev 299, trunk/source/cpu/hardware_4stack.cc)
===================================================================
--- trunk/source/cpu/hardware_4stack.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/cHardware4Stack.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -0,0 +1,2306 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology //
+// //
+// Read the COPYING and README files, or contact 'avida at alife.org', //
+// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+#include "cHardware4Stack.h"
+
+#include "config.hh"
+#include "cCPUTestInfo.h"
+#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;
+
+
+
+
+///////////////
+// cInstLib4Stack
+///////////////
+
+class cInstLib4Stack : 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;
+ cHardware4Stack::tHardware4StackMethod *m_functions;
+ static const cInstruction inst_error;
+ static const cInstruction inst_default;
+public:
+ cInstLib4Stack(
+ size_t nopmod_array_size,
+ size_t function_array_size,
+ cString *nopmod_names,
+ cString *function_names,
+ const int *nopmods,
+ cHardware4Stack::tHardware4StackMethod *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)
+ {}
+ cHardware4Stack::tHardware4StackMethod *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 cInstLib4Stack::GetInstError();
+ }
+ const cInstruction & GetInstDefault(){ return inst_default; }
+ const cInstruction & GetInstError(){ return inst_error; }
+};
+
+///////////////
+// cHardware4Stack
+///////////////
+
+const cInstruction cInstLib4Stack::inst_error(255);
+const cInstruction cInstLib4Stack::inst_default(0);
+cInstLibBase *cHardware4Stack::GetInstLib(){ return s_inst_slib; }
+
+cInstLib4Stack *cHardware4Stack::s_inst_slib = cHardware4Stack::initInstLib();
+cInstLib4Stack *cHardware4Stack::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", &cHardware4Stack::Inst_Nop),
+ //2
+ cInstEntry4Stack("Nop-B", &cHardware4Stack::Inst_Nop),
+ //3
+ cInstEntry4Stack("Nop-C", &cHardware4Stack::Inst_Nop),
+ //4
+ cInstEntry4Stack("Nop-D", &cHardware4Stack::Inst_Nop),
+ //38
+ cInstEntry4Stack("Nop-E", &cHardware4Stack::Inst_Nop),
+ //39
+ cInstEntry4Stack("Nop-F", &cHardware4Stack::Inst_Nop),
+ //5
+ cInstEntry4Stack("Nop-X", &cHardware4Stack::Inst_Nop),
+ //6
+ cInstEntry4Stack("Val-Shift-R", &cHardware4Stack::Inst_ShiftR),
+ //7
+ cInstEntry4Stack("Val-Shift-L", &cHardware4Stack::Inst_ShiftL),
+ //8
+ cInstEntry4Stack("Val-Nand", &cHardware4Stack::Inst_Val_Nand),
+ //9
+ cInstEntry4Stack("Val-Add", &cHardware4Stack::Inst_Val_Add),
+ //10
+ cInstEntry4Stack("Val-Sub", &cHardware4Stack::Inst_Val_Sub),
+ //11
+ cInstEntry4Stack("Val-Mult", &cHardware4Stack::Inst_Val_Mult),
+ //12
+ cInstEntry4Stack("Val-Div", &cHardware4Stack::Inst_Val_Div),
+ //13
+ cInstEntry4Stack("SetMemory", &cHardware4Stack::Inst_SetMemory),
+ //14
+ cInstEntry4Stack("Divide", &cHardware4Stack::Inst_Divide),
+ //15
+ cInstEntry4Stack("Inst-Read", &cHardware4Stack::Inst_HeadRead),
+ //16
+ cInstEntry4Stack("Inst-Write", &cHardware4Stack::Inst_HeadWrite),
+ //keeping this one for the transition period
+ //cInstEntry4Stack("Inst-Copy", &cHardware4Stack::Inst_HeadCopy),
+ //17
+ cInstEntry4Stack("If-Equal", &cHardware4Stack::Inst_IfEqual),
+ //18
+ cInstEntry4Stack("If-Not-Equal", &cHardware4Stack::Inst_IfNotEqual),
+ //19
+ cInstEntry4Stack("If-Less", &cHardware4Stack::Inst_IfLess),
+ //20
+ cInstEntry4Stack("If-Greater", &cHardware4Stack::Inst_IfGreater),
+ //21
+ cInstEntry4Stack("Head-Push", &cHardware4Stack::Inst_HeadPush),
+ //22
+ cInstEntry4Stack("Head-Pop", &cHardware4Stack::Inst_HeadPop),
+ //23
+ cInstEntry4Stack("Head-Move", &cHardware4Stack::Inst_HeadMove),
+ //24
+ cInstEntry4Stack("Search", &cHardware4Stack::Inst_Search),
+ //25
+ cInstEntry4Stack("Push-Next", &cHardware4Stack::Inst_PushNext),
+ //26
+ cInstEntry4Stack("Push-Prev", &cHardware4Stack::Inst_PushPrevious),
+ //27
+ cInstEntry4Stack("Push-Comp", &cHardware4Stack::Inst_PushComplement),
+ //28
+ cInstEntry4Stack("Val-Delete", &cHardware4Stack::Inst_ValDelete),
+ //29
+ cInstEntry4Stack("Val-Copy", &cHardware4Stack::Inst_ValCopy),
+ //30
+ cInstEntry4Stack("ThreadFork", &cHardware4Stack::Inst_ForkThread),
+ //31
+ //cInstEntry4Stack("if-label", &cHardware4Stack::Inst_IfLabel),
+ //32
+ cInstEntry4Stack("Val-Inc", &cHardware4Stack::Inst_Increment),
+ //33
+ cInstEntry4Stack("Val-Dec", &cHardware4Stack::Inst_Decrement),
+ //34
+ cInstEntry4Stack("Val-Mod", &cHardware4Stack::Inst_Mod),
+ //35
+ cInstEntry4Stack("ThreadKill", &cHardware4Stack::Inst_KillThread),
+ //36
+ cInstEntry4Stack("IO", &cHardware4Stack::Inst_IO),
+ //37
+ cInstEntry4Stack("Inject", &cHardware4Stack::Inst_Inject)
+ };
+
+ const int n_size = sizeof(s_n_array)/sizeof(cNOPEntry4Stack);
+
+ 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;
+ }
+
+ cInstLib4Stack *inst_lib = new cInstLib4Stack(
+ n_size,
+ f_size,
+ n_names,
+ f_names,
+ nop_mods,
+ functions
+ );
+
+ return inst_lib;
+}
+
+cHardware4Stack::cHardware4Stack(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...
+}
+
+
+cHardware4Stack::cHardware4Stack(const cHardware4Stack &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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::LoadGenome(const cGenome & new_genome)
+{
+ GetMemory(0) = new_genome;
+}
+
+
+bool cHardware4Stack::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 cHardware4Stack::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: cHardware4Stack::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.
+//
+/////////////////////////////////////////////////////////////////////////
+
+cHeadMultiMem cHardware4Stack::FindLabel(int direction)
+{
+ cHeadMultiMem & inst_ptr = IP();
+
+ // Start up a search head at the position of the instruction pointer.
+ cHeadMultiMem 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 cHardware4Stack::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 cHardware4Stack::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.
+cHeadMultiMem cHardware4Stack::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!!!
+
+ cHeadMultiMem 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.
+cHeadMultiMem cHardware4Stack::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!
+
+ cHeadMultiMem 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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::TriggerMutations(int trigger, cHeadMultiMem & 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 cHardware4Stack::TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadMultiMem & 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.
+ cHeadMultiMem 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 cHardware4Stack::TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadMultiMem & 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 cHardware4Stack::TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadMultiMem & 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++) {
+ cHeadMultiMem 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 cHardware4Stack::TriggerMutations_Body(int type, cCPUMemory & target_memory,
+ cHeadMultiMem & 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 cHardware4Stack::ReadInst(const int in_inst)
+{
+ if (inst_set->IsNop( cInstruction(in_inst) )) {
+ GetReadLabel().AddNop(in_inst);
+ } else {
+ GetReadLabel().Clear();
+ }
+}
+
+
+void cHardware4Stack::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 cHardware4Stack::ReadLabel(int max_size)
+{
+ int count = 0;
+ cHeadMultiMem * 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 cHardware4Stack::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 cHardware4Stack::TestParasite() const
+{
+ return IP().TestParasite();
+}
+
+
+bool cHardware4Stack::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 cHardware4Stack::SaveState(ostream & fp)
+{
+ // note, memory & child_memory handled by cpu (@CAO Not any more!)
+ assert(fp.good());
+
+ fp<<"cHardware4Stack"<<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 cHardware4Stack::LoadState(istream & fp)
+{
+ // note, memory & child_memory handled by cpu (@CAO Not any more!)
+ assert(fp.good());
+
+ cString foo;
+ fp>>foo;
+ assert( foo == "cHardware4Stack" );
+
+ // 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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::FindComplementStack(int base_stack)
+{
+ const int comp_stack = base_stack + 2;
+ return comp_stack%NUM_STACKS;
+}
+
+inline void cHardware4Stack::Fault(int fault_loc, int fault_type, cString fault_desc)
+{
+ organism->Fault(fault_loc, fault_type, fault_desc);
+}
+
+bool cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::ConvertToInstruction(int mem_space_used)
+{
+ char c = mem_space_used + 97; // 97 - ASCII for 'a'
+ cString ret;
+ ret += c;
+ return ret;
+}
+
+cString cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_Divide()
+{
+ int mem_space_used = GetHead(HEAD_WRITE).GetMemSpace();
+ int mut_multiplier = 1;
+
+ return Divide_Main(mem_space_used, mut_multiplier);
+}
+
+bool cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_HeadWrite()
+{
+ const int head_id = FindModifiedHead(HEAD_WRITE);
+ cHeadMultiMem & 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 cHardware4Stack::Inst_HeadCopy()
+{
+ // For the moment, this cannot be nop-modified.
+ cHeadMultiMem & read_head = GetHead(HEAD_READ);
+ cHeadMultiMem & 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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_Search()
+{
+ ReadLabel();
+ GetLabel().Rotate(2, NUM_NOPS_4STACK);
+ cHeadMultiMem 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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_PushComplement()
+{
+ int stack_used = FindModifiedStack(STACK_BX);
+ int complement = FindComplementStack(stack_used);
+ Stack(complement).Push(Stack(stack_used).Pop());
+ return true;
+}
+
+//28
+bool cHardware4Stack::Inst_ValDelete()
+{
+ int stack_used = FindModifiedStack(STACK_BX);
+ Stack(stack_used).Pop();
+ return true;
+}
+
+//29
+bool cHardware4Stack::Inst_ValCopy()
+{
+ const int stack_used = FindModifiedStack(STACK_BX);
+ Stack(stack_used).Push(Stack(stack_used).Top());
+ return true;
+}
+
+//30
+bool cHardware4Stack::Inst_ForkThread()
+{
+ if (!ForkThread())
+ Fault(FAULT_LOC_THREAD_FORK, FAULT_TYPE_FORK_TH);
+ else
+ IP().Advance();
+ return true;
+}
+
+//31
+bool cHardware4Stack::Inst_IfLabel()
+{
+ ReadLabel();
+ GetLabel().Rotate(2, NUM_NOPS_4STACK);
+ if (GetLabel() != GetReadLabel()) IP().Advance();
+ return true;
+}
+
+//32
+bool cHardware4Stack::Inst_Increment()
+{
+ const int stack_used = FindModifiedStack(STACK_BX);
+ int value = Stack(stack_used).Pop();
+ Stack(stack_used).Push(++value);
+ return true;
+}
+
+//33
+bool cHardware4Stack::Inst_Decrement()
+{
+ const int stack_used = FindModifiedStack(STACK_BX);
+ int value = Stack(stack_used).Pop();
+ Stack(stack_used).Push(--value);
+ return true;
+}
+
+//34
+bool cHardware4Stack::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 cHardware4Stack::Inst_KillThread()
+{
+ if (!KillThread()) Fault(FAULT_LOC_THREAD_KILL, FAULT_TYPE_KILL_TH);
+ else AdvanceIP() = false;
+ return true;
+}
+
+//36
+bool cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_Inject()
+{
+ double mut_multiplier = 1;
+
+ return InjectParasite(mut_multiplier);
+}
+
+
+
+/*
+bool cHardware4Stack::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;
+}
+
+*/
Copied: trunk/source/cpu/cHardware4Stack.h (from rev 299, trunk/source/cpu/hardware_4stack.hh)
===================================================================
--- trunk/source/cpu/hardware_4stack.hh 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/cHardware4Stack.h 2005-08-29 19:51:42 UTC (rev 300)
@@ -0,0 +1,515 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology //
+// //
+// Read the COPYING and README files, or contact 'avida at alife.org', //
+// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_4STACK_HH
+#define HARDWARE_4STACK_HH
+
+#include <iomanip>
+
+#ifndef CPU_MEMORY_HH
+#include "cCPUMemory.h"
+#endif
+#ifndef CPU_STACK_HH
+#include "cCPUStack.h"
+#endif
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef HEAD_MULTI_MEM_HH
+#include "head_multi_mem.hh"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "cHardwareBase.h"
+#endif
+#ifndef HARDWARE_4STACK_CONSTANTS_HH
+#include "hardware_4stack_constants.hh"
+#endif
+#ifndef HARDWARE_4STACK_THREAD_HH
+#include "cHardware4Stack_Thread.h"
+#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 cHardware4Stack structure which keeps track of the
+ * current status of all the components of the simulated hardware.
+ *
+ * @see cHardware4Stack_Thread, cCPUStack, cCPUMemory, cInstSet
+ **/
+
+class cCodeLabel;
+class cCPUMemory;
+class cCPUStack; // aggregate
+class cHeadMultiMem; // access
+class cGenome;
+class cHardware4Stack_Thread; // access
+class cInjectGenotype;
+class cInstLib4Stack; // access
+class cInstruction;
+class cInstSet;
+class cOrganism;
+class cString; // aggregate
+template <class T> class tArray; // aggregate
+
+class cHardware4Stack : public cHardwareBase {
+public:
+ typedef bool (cHardware4Stack::*tHardware4StackMethod)();
+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<cHardware4Stack_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:
+ cHardware4Stack(cOrganism * in_organism, cInstSet * in_inst_set);
+ explicit cHardware4Stack(const cHardware4Stack &);
+ ~cHardware4Stack() { ; }
+ 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 cHeadMultiMem & GetHead(int head_id) const
+ { return threads[cur_thread].heads[head_id]; }
+ cHeadMultiMem & GetHead(int head_id)
+ { return threads[cur_thread].heads[head_id];}
+
+ const cHeadMultiMem & GetHead(int head_id, int thread) const
+ { return threads[thread].heads[head_id]; }
+ cHeadMultiMem & GetHead(int head_id, int thread)
+ { return threads[thread].heads[head_id];}
+
+ const cHeadMultiMem & GetActiveHead() const { return GetHead(GetCurHead()); }
+ cHeadMultiMem & GetActiveHead() { return GetHead(GetCurHead()); }
+
+ void AdjustHeads();
+
+ inline const cHeadMultiMem & IP() const
+ { return threads[cur_thread].heads[HEAD_IP]; }
+ inline cHeadMultiMem & IP() { return threads[cur_thread].heads[HEAD_IP]; }
+
+ inline const cHeadMultiMem & IP(int thread) const
+ { return threads[thread].heads[HEAD_IP]; }
+ inline cHeadMultiMem & 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...
+ cHeadMultiMem 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);
+ cHeadMultiMem FindLabel(const cCodeLabel & in_label, int direction);
+ cHeadMultiMem 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, cHeadMultiMem & cur_head);
+ bool TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadMultiMem & cur_head, const double rate);
+ bool TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadMultiMem & cur_head, const double rate);
+ int TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadMultiMem & cur_head, const double rate);
+ void TriggerMutations_Body(int type, cCPUMemory & target_memory,
+ cHeadMultiMem & 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();
+ */
+
+};
+
+
+//////////////////
+// cHardware4Stack
+//////////////////
+
+//Not used, but here to satisfy the requirements of HardwareBase
+inline const cCPUMemory & cHardware4Stack::GetMemory() const
+{
+ return memory_array[0];
+}
+
+//Not used, but here to satisfy the requirements of HardwareBase
+inline cCPUMemory & cHardware4Stack::GetMemory()
+{
+ return memory_array[0];
+}
+
+inline const cCPUMemory & cHardware4Stack::GetMemory(int mem_space) const
+{
+ if(mem_space >= NUM_MEMORY_SPACES)
+ mem_space %= NUM_MEMORY_SPACES;
+ return memory_array[mem_space];
+}
+
+inline cCPUMemory & cHardware4Stack::GetMemory(int mem_space)
+{
+ if(mem_space >= NUM_MEMORY_SPACES)
+ mem_space %= NUM_MEMORY_SPACES;
+ return memory_array[mem_space];
+}
+
+inline void cHardware4Stack::NextThread()
+{
+ cur_thread++;
+ if (cur_thread >= GetNumThreads()) cur_thread = 0;
+}
+
+inline void cHardware4Stack::PrevThread()
+{
+ if (cur_thread == 0) cur_thread = GetNumThreads() - 1;
+ else cur_thread--;
+}
+
+inline void cHardware4Stack::SetThread(int value)
+{
+ if (value>=0 && value < GetNumThreads())
+ cur_thread=value;
+}
+
+inline cInjectGenotype * cHardware4Stack::GetCurThreadOwner()
+{
+ return threads[cur_thread].owner;
+}
+
+inline cInjectGenotype * cHardware4Stack::GetThreadOwner(int thread)
+{
+ return threads[thread].owner;
+}
+
+inline void cHardware4Stack::SetThreadOwner(cInjectGenotype * in_genotype)
+{
+ threads[cur_thread].owner = in_genotype;
+}
+
+/*inline void cHardware4Stack::StackFlip()
+{
+ if (threads[cur_thread].cur_stack == 0) {
+ threads[cur_thread].stack.Flip();
+ } else {
+ global_stack.Flip();
+ }
+}*/
+
+inline int cHardware4Stack::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 cHardware4Stack::StackClear()
+//{
+
+ //if (threads[cur_thread].cur_stack == 0) {
+ // threads[cur_thread].stack.Clear();
+ //} else {
+ // global_stack.Clear();
+ //}
+//}
+
+//inline void cHardware4Stack::SwitchStack()
+//{
+// threads[cur_thread].cur_stack++;
+// if (threads[cur_thread].cur_stack > 1) threads[cur_thread].cur_stack = 0;
+//}
+
+inline cCPUStack& cHardware4Stack::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& cHardware4Stack::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& cHardware4Stack::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& cHardware4Stack::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
Copied: trunk/source/cpu/cHardware4Stack_Thread.cc (from rev 298, trunk/source/cpu/hardware_4stack_thread.cc)
===================================================================
--- trunk/source/cpu/hardware_4stack_thread.cc 2005-08-29 18:54:25 UTC (rev 298)
+++ trunk/source/cpu/cHardware4Stack_Thread.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -0,0 +1,110 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology //
+// //
+// Read the COPYING and README files, or contact 'avida at alife.org', //
+// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_4STACK_THREAD_HH
+#include "cHardware4Stack_Thread.h"
+#endif
+
+using namespace std;
+
+/////////////////////////
+// cHardware4Stack_Thread
+/////////////////////////
+
+cHardware4Stack_Thread::cHardware4Stack_Thread(cHardwareBase * in_hardware, int _id)
+{
+ Reset(in_hardware, _id);
+}
+
+cHardware4Stack_Thread::cHardware4Stack_Thread(const cHardware4Stack_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;
+}
+
+cHardware4Stack_Thread::~cHardware4Stack_Thread() {}
+
+void cHardware4Stack_Thread::operator=(const cHardware4Stack_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 cHardware4Stack_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 cHardware4Stack_Thread::SaveState(ostream & fp){
+ assert(fp.good());
+ fp << "cHardware4Stack_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 cHardware4Stack_Thread::LoadState(istream & fp){
+ assert(fp.good());
+ cString foo;
+ fp >> foo;
+ assert( foo == "cHardware4Stack_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: */
+
+ // Code labels
+ read_label.LoadState(fp);
+ next_label.LoadState(fp);
+}
Copied: trunk/source/cpu/cHardware4Stack_Thread.h (from rev 299, trunk/source/cpu/hardware_4stack_thread.hh)
Copied: trunk/source/cpu/cHardwareBase.cc (from rev 298, trunk/source/cpu/hardware_base.cc)
===================================================================
--- trunk/source/cpu/hardware_base.cc 2005-08-29 18:54:25 UTC (rev 298)
+++ trunk/source/cpu/cHardwareBase.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -0,0 +1,61 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology //
+// //
+// Read the COPYING and README files, or contact 'avida at alife.org', //
+// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "cHardwareBase.h"
+
+#include "inst_set.hh"
+
+using namespace std;
+
+int cHardwareBase::instance_count(0);
+
+cHardwareBase::cHardwareBase(cOrganism * in_organism, cInstSet * in_inst_set)
+ : organism(in_organism)
+ , inst_set(in_inst_set)
+ , viewer_lock(-1)
+ , m_tracer(NULL)
+{
+ assert(inst_set->OK());
+ assert(organism != NULL);
+
+ instance_count++;
+}
+
+cHardwareBase::~cHardwareBase()
+{
+ instance_count--;
+}
+
+void cHardwareBase::Recycle(cOrganism * new_organism, cInstSet * in_inst_set)
+{
+ assert(inst_set->OK());
+ assert(new_organism != NULL);
+
+ organism = new_organism;
+ inst_set = in_inst_set;
+ viewer_lock = -1;
+}
+
+bool cHardwareBase::Inst_Nop() // Do Nothing.
+{
+ return true;
+}
+
+
+int cHardwareBase::GetNumInst()
+{
+ assert(inst_set != NULL);
+ return inst_set->GetSize();
+}
+
+
+cInstruction cHardwareBase::GetRandomInst()
+{
+ assert(inst_set != NULL);
+ return inst_set->GetRandomInst();
+}
+
Copied: trunk/source/cpu/cHardwareBase.h (from rev 298, trunk/source/cpu/hardware_base.hh)
Copied: trunk/source/cpu/cHardwareCPU.cc (from rev 299, trunk/source/cpu/hardware_cpu.cc)
===================================================================
--- trunk/source/cpu/hardware_cpu.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/cHardwareCPU.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -0,0 +1,3463 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2004 California Institute of Technology //
+// //
+// Read the COPYING and README files, or contact 'avida at alife.org', //
+// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "cHardwareCPU.h"
+
+#include "config.hh"
+#include "cCPUTestInfo.h"
+#include "functions.hh"
+#include "genome_util.hh"
+#include "genotype.hh"
+#include "hardware_tracer.hh"
+#include "hardware_tracer_cpu.hh"
+#include "inst_lib_cpu.hh"
+#include "inst_set.hh"
+#include "mutation.hh"
+#include "mutation_lib.hh"
+#include "mutation_macros.hh"
+#include "organism.hh"
+#include "phenotype.hh"
+#include "string_util.hh"
+#include "test_cpu.hh"
+
+#include <limits.h>
+#include <fstream>
+
+using namespace std;
+
+
+///////////////
+// cHardwareCPU
+///////////////
+
+const cInstruction cInstLibCPU::inst_error(255);
+const cInstruction cInstLibCPU::inst_default(0);
+cInstLibCPU *cHardwareCPU::GetInstLib(){ return s_inst_slib; }
+
+cInstLibCPU *cHardwareCPU::s_inst_slib = cHardwareCPU::initInstLib();
+cInstLibCPU *cHardwareCPU::initInstLib(void){
+ struct cNOPEntryCPU {
+ cString name;
+ int nop_mod;
+ cNOPEntryCPU(const cString &name, int nop_mod)
+ : name(name), nop_mod(nop_mod) {}
+ };
+ static const cNOPEntryCPU s_n_array[] = {
+ cNOPEntryCPU("nop-A", REG_AX),
+ cNOPEntryCPU("nop-B", REG_BX),
+ cNOPEntryCPU("nop-C", REG_CX),
+ cNOPEntryCPU("nop-D", REG_DX)
+ };
+
+ struct cInstEntryCPU {
+ const cString name;
+ const tHardwareCPUMethod function;
+ const bool is_default;
+ const cString desc;
+
+ cInstEntryCPU(const cString & _name, tHardwareCPUMethod _fun,
+ bool _def=false, const cString & _desc="")
+ : name(_name), function(_fun), is_default(_def), desc(_desc) {}
+ };
+ static const cInstEntryCPU s_f_array[] = {
+ /*
+ Note: all entries of cNOPEntryCPU s_n_array must have corresponding
+ in the same order in cInstEntryCPU s_f_array, and these entries must
+ be the first elements of s_f_array.
+ */
+ cInstEntryCPU("nop-A", &cHardwareCPU::Inst_Nop, true,
+ "No-operation instruction; modifies other instructions"),
+ cInstEntryCPU("nop-B", &cHardwareCPU::Inst_Nop, true,
+ "No-operation instruction; modifies other instructions"),
+ cInstEntryCPU("nop-C", &cHardwareCPU::Inst_Nop, true,
+ "No-operation instruction; modifies other instructions"),
+ cInstEntryCPU("nop-D", &cHardwareCPU::Inst_Nop, true,
+ "No-operation instruction; modifies other instructions"),
+
+ cInstEntryCPU("NULL", &cHardwareCPU::Inst_Nop, false,
+ "True no-operation instruction: does nothing"),
+ cInstEntryCPU("nop-X", &cHardwareCPU::Inst_Nop, false,
+ "True no-operation instruction: does nothing"),
+ cInstEntryCPU("if-equ-0", &cHardwareCPU::Inst_If0, false,
+ "Execute next instruction if ?BX?==0, else skip it"),
+ cInstEntryCPU("if-not-0", &cHardwareCPU::Inst_IfNot0, false,
+ "Execute next instruction if ?BX?!=0, else skip it"),
+ cInstEntryCPU("if-n-equ", &cHardwareCPU::Inst_IfNEqu, true,
+ "Execute next instruction if ?BX?!=?CX?, else skip it"),
+ cInstEntryCPU("if-equ", &cHardwareCPU::Inst_IfEqu, false,
+ "Execute next instruction if ?BX?==?CX?, else skip it"),
+ cInstEntryCPU("if-grt-0", &cHardwareCPU::Inst_IfGr0),
+ cInstEntryCPU("if-grt", &cHardwareCPU::Inst_IfGr),
+ cInstEntryCPU("if->=-0", &cHardwareCPU::Inst_IfGrEqu0),
+ cInstEntryCPU("if->=", &cHardwareCPU::Inst_IfGrEqu),
+ cInstEntryCPU("if-les-0", &cHardwareCPU::Inst_IfLess0),
+ cInstEntryCPU("if-less", &cHardwareCPU::Inst_IfLess, true,
+ "Execute next instruction if ?BX? < ?CX?, else skip it"),
+ cInstEntryCPU("if-<=-0", &cHardwareCPU::Inst_IfLsEqu0),
+ cInstEntryCPU("if-<=", &cHardwareCPU::Inst_IfLsEqu),
+ cInstEntryCPU("if-A!=B", &cHardwareCPU::Inst_IfANotEqB),
+ cInstEntryCPU("if-B!=C", &cHardwareCPU::Inst_IfBNotEqC),
+ cInstEntryCPU("if-A!=C", &cHardwareCPU::Inst_IfANotEqC),
+ cInstEntryCPU("if-bit-1", &cHardwareCPU::Inst_IfBit1),
+
+ cInstEntryCPU("jump-f", &cHardwareCPU::Inst_JumpF),
+ cInstEntryCPU("jump-b", &cHardwareCPU::Inst_JumpB),
+ cInstEntryCPU("jump-p", &cHardwareCPU::Inst_JumpP),
+ cInstEntryCPU("jump-slf", &cHardwareCPU::Inst_JumpSelf),
+ cInstEntryCPU("call", &cHardwareCPU::Inst_Call),
+ cInstEntryCPU("return", &cHardwareCPU::Inst_Return),
+
+ cInstEntryCPU("pop", &cHardwareCPU::Inst_Pop, true,
+ "Remove top number from stack and place into ?BX?"),
+ cInstEntryCPU("push", &cHardwareCPU::Inst_Push, true,
+ "Copy number from ?BX? and place it into the stack"),
+ cInstEntryCPU("swap-stk", &cHardwareCPU::Inst_SwitchStack, true,
+ "Toggle which stack is currently being used"),
+ cInstEntryCPU("flip-stk", &cHardwareCPU::Inst_FlipStack),
+ cInstEntryCPU("swap", &cHardwareCPU::Inst_Swap, true,
+ "Swap the contents of ?BX? with ?CX?"),
+ cInstEntryCPU("swap-AB", &cHardwareCPU::Inst_SwapAB),
+ cInstEntryCPU("swap-BC", &cHardwareCPU::Inst_SwapBC),
+ cInstEntryCPU("swap-AC", &cHardwareCPU::Inst_SwapAC),
+ cInstEntryCPU("copy-reg", &cHardwareCPU::Inst_CopyReg),
+ cInstEntryCPU("set_A=B", &cHardwareCPU::Inst_CopyRegAB),
+ cInstEntryCPU("set_A=C", &cHardwareCPU::Inst_CopyRegAC),
+ cInstEntryCPU("set_B=A", &cHardwareCPU::Inst_CopyRegBA),
+ cInstEntryCPU("set_B=C", &cHardwareCPU::Inst_CopyRegBC),
+ cInstEntryCPU("set_C=A", &cHardwareCPU::Inst_CopyRegCA),
+ cInstEntryCPU("set_C=B", &cHardwareCPU::Inst_CopyRegCB),
+ cInstEntryCPU("reset", &cHardwareCPU::Inst_Reset),
+
+ cInstEntryCPU("pop-A", &cHardwareCPU::Inst_PopA),
+ cInstEntryCPU("pop-B", &cHardwareCPU::Inst_PopB),
+ cInstEntryCPU("pop-C", &cHardwareCPU::Inst_PopC),
+ cInstEntryCPU("push-A", &cHardwareCPU::Inst_PushA),
+ cInstEntryCPU("push-B", &cHardwareCPU::Inst_PushB),
+ cInstEntryCPU("push-C", &cHardwareCPU::Inst_PushC),
+
+ cInstEntryCPU("shift-r", &cHardwareCPU::Inst_ShiftR, true,
+ "Shift bits in ?BX? right by one (divide by two)"),
+ cInstEntryCPU("shift-l", &cHardwareCPU::Inst_ShiftL, true,
+ "Shift bits in ?BX? left by one (multiply by two)"),
+ cInstEntryCPU("bit-1", &cHardwareCPU::Inst_Bit1),
+ cInstEntryCPU("set-num", &cHardwareCPU::Inst_SetNum),
+ cInstEntryCPU("val-grey", &cHardwareCPU::Inst_ValGrey),
+ cInstEntryCPU("val-dir", &cHardwareCPU::Inst_ValDir),
+ cInstEntryCPU("val-add-p", &cHardwareCPU::Inst_ValAddP),
+ cInstEntryCPU("val-fib", &cHardwareCPU::Inst_ValFib),
+ cInstEntryCPU("val-poly-c",&cHardwareCPU::Inst_ValPolyC),
+ cInstEntryCPU("inc", &cHardwareCPU::Inst_Inc, true,
+ "Increment ?BX? by one"),
+ cInstEntryCPU("dec", &cHardwareCPU::Inst_Dec, true,
+ "Decrement ?BX? by one"),
+ cInstEntryCPU("zero", &cHardwareCPU::Inst_Zero, false,
+ "Set ?BX? to zero"),
+ cInstEntryCPU("neg", &cHardwareCPU::Inst_Neg),
+ cInstEntryCPU("square", &cHardwareCPU::Inst_Square),
+ cInstEntryCPU("sqrt", &cHardwareCPU::Inst_Sqrt),
+ cInstEntryCPU("not", &cHardwareCPU::Inst_Not),
+ cInstEntryCPU("minus-17", &cHardwareCPU::Inst_Minus17),
+
+ cInstEntryCPU("add", &cHardwareCPU::Inst_Add, true,
+ "Add BX to CX and place the result in ?BX?"),
+ cInstEntryCPU("sub", &cHardwareCPU::Inst_Sub, true,
+ "Subtract CX from BX and place the result in ?BX?"),
+ cInstEntryCPU("mult", &cHardwareCPU::Inst_Mult, false,
+ "Multiple BX by CX and place the result in ?BX?"),
+ cInstEntryCPU("div", &cHardwareCPU::Inst_Div, false,
+ "Divide BX by CX and place the result in ?BX?"),
+ cInstEntryCPU("mod", &cHardwareCPU::Inst_Mod),
+ cInstEntryCPU("nand", &cHardwareCPU::Inst_Nand, true,
+ "Nand BX by CX and place the result in ?BX?"),
+ cInstEntryCPU("nor", &cHardwareCPU::Inst_Nor),
+ cInstEntryCPU("and", &cHardwareCPU::Inst_And),
+ cInstEntryCPU("order", &cHardwareCPU::Inst_Order),
+ cInstEntryCPU("xor", &cHardwareCPU::Inst_Xor),
+
+ cInstEntryCPU("copy", &cHardwareCPU::Inst_Copy),
+ cInstEntryCPU("read", &cHardwareCPU::Inst_ReadInst),
+ cInstEntryCPU("write", &cHardwareCPU::Inst_WriteInst),
+ cInstEntryCPU("stk-read", &cHardwareCPU::Inst_StackReadInst),
+ cInstEntryCPU("stk-writ", &cHardwareCPU::Inst_StackWriteInst),
+
+ cInstEntryCPU("compare", &cHardwareCPU::Inst_Compare),
+ cInstEntryCPU("if-n-cpy", &cHardwareCPU::Inst_IfNCpy),
+ cInstEntryCPU("allocate", &cHardwareCPU::Inst_Allocate),
+ cInstEntryCPU("divide", &cHardwareCPU::Inst_Divide),
+ cInstEntryCPU("c-alloc", &cHardwareCPU::Inst_CAlloc),
+ cInstEntryCPU("c-divide", &cHardwareCPU::Inst_CDivide),
+ cInstEntryCPU("inject", &cHardwareCPU::Inst_Inject),
+ cInstEntryCPU("inject-r", &cHardwareCPU::Inst_InjectRand),
+ cInstEntryCPU("search-f", &cHardwareCPU::Inst_SearchF),
+ cInstEntryCPU("search-b", &cHardwareCPU::Inst_SearchB),
+ cInstEntryCPU("mem-size", &cHardwareCPU::Inst_MemSize),
+
+ cInstEntryCPU("get", &cHardwareCPU::Inst_TaskGet),
+ cInstEntryCPU("stk-get", &cHardwareCPU::Inst_TaskStackGet),
+ cInstEntryCPU("stk-load", &cHardwareCPU::Inst_TaskStackLoad),
+ cInstEntryCPU("put", &cHardwareCPU::Inst_TaskPut),
+ cInstEntryCPU("IO", &cHardwareCPU::Inst_TaskIO, true,
+ "Output ?BX?, and input new number back into ?BX?"),
+
+ cInstEntryCPU("send", &cHardwareCPU::Inst_Send),
+ cInstEntryCPU("receive", &cHardwareCPU::Inst_Receive),
+ cInstEntryCPU("sense", &cHardwareCPU::Inst_Sense),
+
+ cInstEntryCPU("donate-rnd", &cHardwareCPU::Inst_DonateRandom),
+ cInstEntryCPU("donate-kin", &cHardwareCPU::Inst_DonateKin),
+ cInstEntryCPU("donate-edt", &cHardwareCPU::Inst_DonateEditDist),
+ cInstEntryCPU("donate-NUL", &cHardwareCPU::Inst_DonateNULL),
+
+ cInstEntryCPU("rotate-l", &cHardwareCPU::Inst_RotateL),
+ cInstEntryCPU("rotate-r", &cHardwareCPU::Inst_RotateR),
+
+ cInstEntryCPU("set-cmut", &cHardwareCPU::Inst_SetCopyMut),
+ cInstEntryCPU("mod-cmut", &cHardwareCPU::Inst_ModCopyMut),
+
+ // Threading instructions
+ cInstEntryCPU("fork-th", &cHardwareCPU::Inst_ForkThread),
+ cInstEntryCPU("kill-th", &cHardwareCPU::Inst_KillThread),
+ cInstEntryCPU("id-th", &cHardwareCPU::Inst_ThreadID),
+
+ // Head-based instructions
+ cInstEntryCPU("h-alloc", &cHardwareCPU::Inst_MaxAlloc, true,
+ "Allocate maximum allowed space"),
+ cInstEntryCPU("h-divide", &cHardwareCPU::Inst_HeadDivide, true,
+ "Divide code between read and write heads."),
+ cInstEntryCPU("h-read", &cHardwareCPU::Inst_HeadRead),
+ cInstEntryCPU("h-write", &cHardwareCPU::Inst_HeadWrite),
+ cInstEntryCPU("h-copy", &cHardwareCPU::Inst_HeadCopy, true,
+ "Copy from read-head to write-head; advance both"),
+ cInstEntryCPU("h-search", &cHardwareCPU::Inst_HeadSearch, true,
+ "Find complement template and make with flow head"),
+ cInstEntryCPU("h-push", &cHardwareCPU::Inst_HeadPush),
+ cInstEntryCPU("h-pop", &cHardwareCPU::Inst_HeadPop),
+ cInstEntryCPU("set-head", &cHardwareCPU::Inst_SetHead),
+ cInstEntryCPU("adv-head", &cHardwareCPU::Inst_AdvanceHead),
+ cInstEntryCPU("mov-head", &cHardwareCPU::Inst_MoveHead, true,
+ "Move head ?IP? to the flow head"),
+ cInstEntryCPU("jmp-head", &cHardwareCPU::Inst_JumpHead, true,
+ "Move head ?IP? by amount in CX register; CX = old pos."),
+ cInstEntryCPU("get-head", &cHardwareCPU::Inst_GetHead, true,
+ "Copy the position of the ?IP? head into CX"),
+ cInstEntryCPU("if-label", &cHardwareCPU::Inst_IfLabel, true,
+ "Execute next if we copied complement of attached label"),
+ cInstEntryCPU("if-label2", &cHardwareCPU::Inst_IfLabel2, true,
+ "If copied label compl., exec next inst; else SKIP W/NOPS"),
+ cInstEntryCPU("set-flow", &cHardwareCPU::Inst_SetFlow, true,
+ "Set flow-head to position in ?CX?"),
+
+ cInstEntryCPU("h-copy2", &cHardwareCPU::Inst_HeadCopy2),
+ cInstEntryCPU("h-copy3", &cHardwareCPU::Inst_HeadCopy3),
+ cInstEntryCPU("h-copy4", &cHardwareCPU::Inst_HeadCopy4),
+ cInstEntryCPU("h-copy5", &cHardwareCPU::Inst_HeadCopy5),
+ cInstEntryCPU("h-copy6", &cHardwareCPU::Inst_HeadCopy6),
+ cInstEntryCPU("h-copy7", &cHardwareCPU::Inst_HeadCopy7),
+ cInstEntryCPU("h-copy8", &cHardwareCPU::Inst_HeadCopy8),
+ cInstEntryCPU("h-copy9", &cHardwareCPU::Inst_HeadCopy9),
+ cInstEntryCPU("h-copy10", &cHardwareCPU::Inst_HeadCopy10),
+
+ cInstEntryCPU("divide-sex", &cHardwareCPU::Inst_HeadDivideSex),
+ cInstEntryCPU("divide-asex", &cHardwareCPU::Inst_HeadDivideAsex),
+
+ cInstEntryCPU("div-sex", &cHardwareCPU::Inst_HeadDivideSex),
+ cInstEntryCPU("div-asex", &cHardwareCPU::Inst_HeadDivideAsex),
+ cInstEntryCPU("div-asex-w", &cHardwareCPU::Inst_HeadDivideAsexWait),
+ cInstEntryCPU("div-sex-MS", &cHardwareCPU::Inst_HeadDivideMateSelect),
+
+ cInstEntryCPU("h-divide1", &cHardwareCPU::Inst_HeadDivide1),
+ cInstEntryCPU("h-divide2", &cHardwareCPU::Inst_HeadDivide2),
+ cInstEntryCPU("h-divide3", &cHardwareCPU::Inst_HeadDivide3),
+ cInstEntryCPU("h-divide4", &cHardwareCPU::Inst_HeadDivide4),
+ cInstEntryCPU("h-divide5", &cHardwareCPU::Inst_HeadDivide5),
+ cInstEntryCPU("h-divide6", &cHardwareCPU::Inst_HeadDivide6),
+ cInstEntryCPU("h-divide7", &cHardwareCPU::Inst_HeadDivide7),
+ cInstEntryCPU("h-divide8", &cHardwareCPU::Inst_HeadDivide8),
+ cInstEntryCPU("h-divide9", &cHardwareCPU::Inst_HeadDivide9),
+ cInstEntryCPU("h-divide10", &cHardwareCPU::Inst_HeadDivide10),
+ cInstEntryCPU("h-divide16", &cHardwareCPU::Inst_HeadDivide16),
+ cInstEntryCPU("h-divide32", &cHardwareCPU::Inst_HeadDivide32),
+ cInstEntryCPU("h-divide50", &cHardwareCPU::Inst_HeadDivide50),
+ cInstEntryCPU("h-divide100", &cHardwareCPU::Inst_HeadDivide100),
+ cInstEntryCPU("h-divide500", &cHardwareCPU::Inst_HeadDivide500),
+ cInstEntryCPU("h-divide1000", &cHardwareCPU::Inst_HeadDivide1000),
+ cInstEntryCPU("h-divide5000", &cHardwareCPU::Inst_HeadDivide5000),
+ cInstEntryCPU("h-divide10000", &cHardwareCPU::Inst_HeadDivide10000),
+ cInstEntryCPU("h-divide50000", &cHardwareCPU::Inst_HeadDivide50000),
+ cInstEntryCPU("h-divide0.5", &cHardwareCPU::Inst_HeadDivide0_5),
+ cInstEntryCPU("h-divide0.1", &cHardwareCPU::Inst_HeadDivide0_1),
+ cInstEntryCPU("h-divide0.05", &cHardwareCPU::Inst_HeadDivide0_05),
+ cInstEntryCPU("h-divide0.01", &cHardwareCPU::Inst_HeadDivide0_01),
+ cInstEntryCPU("h-divide0.001", &cHardwareCPU::Inst_HeadDivide0_001),
+
+ // High-level instructions
+ cInstEntryCPU("repro", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-A", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-B", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-C", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-D", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-E", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-F", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-G", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-H", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-I", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-J", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-K", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-L", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-M", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-N", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-O", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-P", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-Q", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-R", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-S", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-T", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-U", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-V", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-W", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-X", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-Y", &cHardwareCPU::Inst_Repro),
+ cInstEntryCPU("repro-Z", &cHardwareCPU::Inst_Repro),
+
+ // Suicide
+ cInstEntryCPU("kazi", &cHardwareCPU::Inst_Kazi),
+ cInstEntryCPU("die", &cHardwareCPU::Inst_Die),
+
+
+
+ // Placebo instructions
+ // nop-x (included with nops)
+ cInstEntryCPU("skip", &cHardwareCPU::Inst_Skip)
+ };
+
+ const int n_size = sizeof(s_n_array)/sizeof(cNOPEntryCPU);
+
+ 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(cInstEntryCPU);
+ static cString f_names[f_size];
+ static tHardwareCPUMethod 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;
+ }
+
+ cInstLibCPU *inst_lib = new cInstLibCPU(
+ n_size,
+ f_size,
+ n_names,
+ f_names,
+ nop_mods,
+ functions
+ );
+
+ return inst_lib;
+}
+
+cHardwareCPU::cHardwareCPU(cOrganism * in_organism, cInstSet * in_inst_set)
+ : cHardwareBase(in_organism, in_inst_set)
+{
+ /* FIXME: reorganize storage of m_functions. -- kgn */
+ m_functions = s_inst_slib->GetFunctions();
+ /**/
+ memory = in_organism->GetGenome(); // Initialize memory...
+ Reset(); // Setup the rest of the hardware...
+}
+
+
+cHardwareCPU::cHardwareCPU(const cHardwareCPU &hardware_cpu)
+: cHardwareBase(hardware_cpu.organism, hardware_cpu.inst_set)
+, m_functions(hardware_cpu.m_functions)
+, memory(hardware_cpu.memory)
+, global_stack(hardware_cpu.global_stack)
+, thread_time_used(hardware_cpu.thread_time_used)
+, threads(hardware_cpu.threads)
+, thread_id_chart(hardware_cpu.thread_id_chart)
+, cur_thread(hardware_cpu.cur_thread)
+, mal_active(hardware_cpu.mal_active)
+, advance_ip(hardware_cpu.advance_ip)
+#ifdef INSTRUCTION_COSTS
+, inst_cost(hardware_cpu.inst_cost)
+, inst_ft_cost(hardware_cpu.inst_ft_cost)
+#endif
+{
+}
+
+
+cHardwareCPU::~cHardwareCPU()
+{
+}
+
+
+void cHardwareCPU::Recycle(cOrganism * new_organism, cInstSet * in_inst_set)
+{
+ cHardwareBase::Recycle(new_organism, in_inst_set);
+ memory = new_organism->GetGenome();
+ Reset();
+}
+
+
+void cHardwareCPU::Reset()
+{
+ global_stack.Clear();
+ thread_time_used = 0;
+
+ // 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;
+
+#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 cHardwareCPU::SingleProcess()
+{
+ // Mark this organism as running...
+ organism->SetRunning(true);
+
+ cPhenotype & phenotype = organism->GetPhenotype();
+ phenotype.IncTimeUsed();
+ const int num_threads = GetNumThreads();
+ if (num_threads > 1) thread_time_used++;
+
+ // 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) ?
+ num_threads : 1;
+
+ for (int i = 0; i < num_inst_exec; i++) {
+ // Setup the hardware for the next instruction to be executed.
+ NextThread();
+ advance_ip = 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_CPU * tracer
+ = dynamic_cast<cHardwareTracer_CPU *>(m_tracer)
+ ){
+ tracer->TraceHardware_CPU(*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 (advance_ip == 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() == true) {
+ 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 cHardwareCPU::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 cHardwareCPU::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 cHardwareCPU::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_CPU * tracer
+ = dynamic_cast<cHardwareTracer_CPU *>(m_tracer)
+ ){
+ tracer->TraceHardware_CPUBonus(*this);
+ }
+ }
+
+ SingleProcess_ExecuteInst(inst);
+
+ organism->SetRunning(prev_run_state);
+}
+
+
+void cHardwareCPU::LoadGenome(const cGenome & new_genome)
+{
+ GetMemory() = new_genome;
+}
+
+
+bool cHardwareCPU::OK()
+{
+ bool result = true;
+
+ if (!memory.OK()) result = false;
+
+ for (int i = 0; i < GetNumThreads(); i++) {
+ if (threads[i].stack.OK() == false) result = false;
+ if (threads[i].next_label.OK() == false) result = false;
+ }
+
+ return result;
+}
+
+void cHardwareCPU::PrintStatus(ostream & fp)
+{
+ fp << organism->GetPhenotype().GetTimeUsed() << " "
+ << "IP:" << IP().GetPosition() << " "
+
+ << "AX:" << Register(REG_AX) << " "
+ << setbase(16) << "[0x" << Register(REG_AX) << "] " << setbase(10)
+
+ << "BX:" << Register(REG_BX) << " "
+ << setbase(16) << "[0x" << Register(REG_BX) << "] " << setbase(10)
+
+ << "CX:" << Register(REG_CX) << " "
+ << setbase(16) << "[0x" << Register(REG_CX) << "]" << setbase(10)
+
+ << endl;
+
+ fp << " R-Head:" << GetHead(HEAD_READ).GetPosition() << " "
+ << "W-Head:" << GetHead(HEAD_WRITE).GetPosition() << " "
+ << "F-Head:" << GetHead(HEAD_FLOW).GetPosition() << " "
+ << "RL:" << GetReadLabel().AsString() << " "
+ << endl;
+
+ fp << " Mem (" << GetMemory().GetSize() << "):"
+ << " " << GetMemory().AsString()
+ << endl;
+ fp.flush();
+}
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// Method: cHardwareCPU::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.
+//
+/////////////////////////////////////////////////////////////////////////
+
+cHeadCPU cHardwareCPU::FindLabel(int direction)
+{
+ cHeadCPU & inst_ptr = IP();
+
+ // Start up a search head at the position of the instruction pointer.
+ cHeadCPU 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);
+
+ // 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 cHardwareCPU::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 cHardwareCPU::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.
+cHeadCPU cHardwareCPU::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!!!
+
+ cHeadCPU 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.
+cHeadCPU cHardwareCPU::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!
+
+ cHeadCPU 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;
+}
+
+
+bool cHardwareCPU::InjectHost(const cCodeLabel & in_label, const cGenome & injection)
+{
+ // Make sure the genome will be below max size after injection.
+
+ const int new_size = injection.GetSize() + GetMemory().GetSize();
+ if (new_size > MAX_CREATURE_SIZE) return false; // (inject fails)
+
+ const int inject_line = FindFullLabel(in_label).GetPosition();
+
+ // Abort if no compliment is found.
+ if (inject_line == -1) return false; // (inject fails)
+
+ // Inject the code!
+ InjectCode(injection, inject_line+1);
+
+ return true; // (inject succeeds!)
+}
+
+int cHardwareCPU::InjectThread(const cCodeLabel & in_label, const cGenome & injection)
+{
+ // Make sure the genome will be below max size after injection.
+
+ const int new_size = injection.GetSize() + GetMemory().GetSize();
+ if (new_size > MAX_CREATURE_SIZE) return 1; // (inject fails)
+
+ const int inject_line = FindFullLabel(in_label).GetPosition();
+
+ // Abort if no compliment is found.
+ if (inject_line == -1) return 2; // (inject fails)
+
+ // Inject the code!
+ InjectCodeThread(injection, inject_line+1);
+
+ return 0; // (inject succeeds!)
+}
+
+void cHardwareCPU::InjectCode(const cGenome & inject_code, const int line_num)
+{
+ assert(line_num >= 0);
+ assert(line_num <= memory.GetSize());
+ assert(memory.GetSize() + inject_code.GetSize() < MAX_CREATURE_SIZE);
+
+ // Inject the new code.
+ const int inject_size = inject_code.GetSize();
+ memory.Insert(line_num, inject_code);
+
+ // Set instruction flags on the injected code
+ for (int i = line_num; i < line_num + inject_size; i++) {
+ memory.FlagInjected(i) = true;
+ }
+ organism->GetPhenotype().IsModified() = true;
+
+ // Adjust all of the heads to take into account the new mem size.
+
+ for (int i=0; i < NUM_HEADS; i++) {
+ if (!GetHead(i).TestParasite() &&
+ GetHead(i).GetPosition() > line_num)
+ GetHead(i).Jump(inject_size);
+ }
+}
+
+void cHardwareCPU::InjectCodeThread(const cGenome & inject_code, const int line_num)
+{
+ assert(line_num >= 0);
+ assert(line_num <= memory.GetSize());
+ assert(memory.GetSize() + inject_code.GetSize() < MAX_CREATURE_SIZE);
+
+ if(ForkThread())
+ {
+ // Inject the new code.
+ const int inject_size = inject_code.GetSize();
+ memory.Insert(line_num, inject_code);
+
+ // Set instruction flags on the injected code
+ for (int i = line_num; i < line_num + inject_size; i++) {
+ memory.FlagInjected(i) = true;
+ }
+ organism->GetPhenotype().IsModified() = true;
+ organism->GetPhenotype().IsMultiThread() = true;
+
+ // Adjust all of the heads to take into account the new mem size.
+
+ int currthread = GetCurThread();
+ SetThread(0);
+ for (int i=0; i<GetNumThreads()-2; i++)
+ {
+ for (int j=0; j < NUM_HEADS; j++)
+ {
+ if (!GetHead(i).TestParasite() && GetHead(i).GetPosition() > line_num)
+ GetHead(i).Jump(inject_size);
+ }
+ NextThread();
+ }
+ SetThread(currthread);
+
+ }
+ else
+ {
+ //Some kind of error message should go here...but what?
+ }
+
+}
+
+void cHardwareCPU::Mutate(int mut_point)
+{
+ // Test if trying to mutate outside of genome...
+ assert(mut_point >= 0 && mut_point < GetMemory().GetSize());
+
+ GetMemory()[mut_point] = GetRandomInst();
+ GetMemory().FlagMutated(mut_point) = true;
+ GetMemory().FlagPointMut(mut_point) = true;
+ //organism->GetPhenotype().IsMutated() = true;
+ organism->CPUStats().mut_stats.point_mut_count++;
+}
+
+int cHardwareCPU::PointMutate(const double mut_rate)
+{
+ const int num_muts =
+ g_random.GetRandBinomial(GetMemory().GetSize(), mut_rate);
+
+ for (int i = 0; i < num_muts; i++) {
+ const int pos = g_random.GetUInt(GetMemory().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 cHardwareCPU::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 cHardwareCPU::TriggerMutations(int trigger, cHeadCPU & 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();
+
+ // 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 cHardwareCPU::TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadCPU & 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.
+ cHeadCPU 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 cHardwareCPU::TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadCPU & 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 cHardwareCPU::TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadCPU & 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++) {
+ cHeadCPU 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 cHardwareCPU::TriggerMutations_Body(int type, cCPUMemory & target_memory,
+ cHeadCPU & 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 cHardwareCPU::ReadInst(const int in_inst)
+{
+ if (inst_set->IsNop( cInstruction(in_inst) )) {
+ GetReadLabel().AddNop(in_inst);
+ } else {
+ GetReadLabel().Clear();
+ }
+}
+
+
+void cHardwareCPU::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 cHardwareCPU::ReadLabel(int max_size)
+{
+ int count = 0;
+ cHeadCPU * 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 cHardwareCPU::ForkThread()
+{
+ const int num_threads = GetNumThreads();
+ if (num_threads == cConfig::GetMaxCPUThreads()) return false;
+
+ // Make room for the new thread.
+ threads.Resize(num_threads + 1);
+
+ // 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 cHardwareCPU::TestParasite() const
+{
+ return IP().TestParasite();
+}
+
+
+bool cHardwareCPU::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 cHardwareCPU::SaveState(ostream & fp)
+{
+ // note, memory & child_memory handled by cpu (@CAO Not any more!)
+ assert(fp.good());
+
+ fp<<"cHardwareCPU"<<endl;
+
+ // global_stack (in inverse order so load can just push)
+ global_stack.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 cHardwareCPU::LoadState(istream & fp)
+{
+ // note, memory & child_memory handled by cpu (@CAO Not any more!)
+ assert(fp.good());
+
+ cString foo;
+ fp>>foo;
+ assert( foo == "cHardwareCPU" );
+
+ // global_stack
+ global_stack.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 cHardwareCPU::FindModifiedRegister(int default_register)
+{
+ assert(default_register < NUM_REGISTERS); // Reg ID too high.
+
+ if (GetInstSet().IsNop(IP().GetNextInst())) {
+ IP().Advance();
+ default_register = GetInstSet().GetNopMod(IP().GetInst());
+ IP().FlagExecuted() = true;
+ }
+ return default_register;
+}
+
+
+inline int cHardwareCPU::FindModifiedHead(int default_head)
+{
+ assert(default_head < NUM_HEADS); // Head ID too high.
+
+ if (GetInstSet().IsNop(IP().GetNextInst())) {
+ IP().Advance();
+ default_head = GetInstSet().GetNopMod(IP().GetInst());
+ IP().FlagExecuted() = true;
+ }
+ return default_head;
+}
+
+
+inline int cHardwareCPU::FindComplementRegister(int base_reg)
+{
+ const int comp_reg = base_reg + 1;
+ return (comp_reg == NUM_REGISTERS) ? 0 : comp_reg;
+}
+
+
+inline void cHardwareCPU::Fault(int fault_loc, int fault_type, cString fault_desc)
+{
+ organism->Fault(fault_loc, fault_type, fault_desc);
+}
+
+
+bool cHardwareCPU::Allocate_Necro(const int new_size)
+{
+ GetMemory().ResizeOld(new_size);
+ return true;
+}
+
+bool cHardwareCPU::Allocate_Random(const int old_size, const int new_size)
+{
+ GetMemory().Resize(new_size);
+
+ for (int i = old_size; i < new_size; i++) {
+ GetMemory()[i] = GetInstSet().GetRandomInst();
+ }
+ return true;
+}
+
+bool cHardwareCPU::Allocate_Default(const int new_size)
+{
+ GetMemory().Resize(new_size);
+
+ // New space already defaults to default instruction...
+
+ return true;
+}
+
+bool cHardwareCPU::Allocate_Main(const int allocated_size)
+{
+ // must do divide before second allocate & must allocate positive amount...
+ if (cConfig::GetRequireAllocate() && mal_active == true) {
+ Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR, "Allocate already active");
+ return false;
+ }
+ if (allocated_size < 1) {
+ Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+ cStringUtil::Stringf("Allocate of %d too small", allocated_size));
+ return false;
+ }
+
+ const int old_size = GetMemory().GetSize();
+ const int new_size = old_size + allocated_size;
+
+ // Make sure that the new size is in range.
+ if (new_size > MAX_CREATURE_SIZE || new_size < MIN_CREATURE_SIZE) {
+ Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+ cStringUtil::Stringf("Invalid post-allocate size (%d)",
+ new_size));
+ return false;
+ }
+
+ const int max_alloc_size = (int) (old_size * cConfig::GetChildSizeRange());
+ if (allocated_size > max_alloc_size) {
+ Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+ cStringUtil::Stringf("Allocate too large (%d > %d)",
+ allocated_size, max_alloc_size));
+ return false;
+ }
+
+ const int max_old_size =
+ (int) (allocated_size * cConfig::GetChildSizeRange());
+ if (old_size > max_old_size) {
+ Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+ cStringUtil::Stringf("Allocate too small (%d > %d)",
+ old_size, max_old_size));
+ return false;
+ }
+
+ switch (cConfig::GetAllocMethod()) {
+ case ALLOC_METHOD_NECRO:
+ // Only break if this succeeds -- otherwise just do random.
+ if (Allocate_Necro(new_size) == true) break;
+ case ALLOC_METHOD_RANDOM:
+ Allocate_Random(old_size, new_size);
+ break;
+ case ALLOC_METHOD_DEFAULT:
+ Allocate_Default(new_size);
+ break;
+ }
+
+ mal_active = true;
+
+ return true;
+}
+
+
+bool cHardwareCPU::Divide_CheckViable(const int child_size,
+ const int parent_size)
+{
+ // Make sure the organism is okay with dividing now...
+ if (organism->Divide_CheckViable() == false) return false; // (divide fails)
+
+ // If required, make sure an allocate has occured.
+ if (cConfig::GetRequireAllocate() && mal_active == false) {
+ Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR, "Must allocate before divide");
+ 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)
+ }
+ if (parent_size < min_size || parent_size > max_size) {
+ Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
+ cStringUtil::Stringf("Invalid post-divide length (%d)",parent_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().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 = parent_size; i < parent_size + child_size; i++) {
+ if (GetMemory().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...
+ cPhenotype & phenotype = organism->GetPhenotype();
+ phenotype.SetLinesExecuted(executed_size);
+ phenotype.SetLinesCopied(copied_size);
+
+ // Determine the fitness of this organism as compared to its parent...
+ if (cConfig::GetTestSterilize() == true &&
+ phenotype.IsInjected() == false) {
+ const int merit_base =
+ cPhenotype::CalcSizeMerit(genome_size, copied_size, executed_size);
+ const double cur_fitness =
+ merit_base * phenotype.GetCurBonus() / phenotype.GetTimeUsed();
+ const double fitness_ratio = cur_fitness / phenotype.GetLastFitness();
+
+
+ // const double neut_min = parent_fitness * FITNESS_NEUTRAL_MIN;
+ // const double neut_max = parent_fitness * FITNESS_NEUTRAL_MAX;
+
+ bool sterilize = false;
+
+ if (fitness_ratio < FITNESS_NEUTRAL_MIN) {
+ if (g_random.P(organism->GetSterilizeNeg())) sterilize = true;
+ } else if (fitness_ratio <= FITNESS_NEUTRAL_MAX) {
+ if (g_random.P(organism->GetSterilizeNeut())) sterilize = true;
+ } else {
+ if (g_random.P(organism->GetSterilizePos())) sterilize = true;
+ }
+
+// cout << "[ min(" << genome_size
+// << "," << copied_size
+// << "," << executed_size
+// << ") * " << phenotype.GetCurBonus()
+// << " / " << phenotype.GetTimeUsed()
+// << "] / " << phenotype.GetLastFitness()
+// << " == " << fitness_ratio;
+
+ if (sterilize == true) {
+ //Don't let this organism have this or any more children!
+ phenotype.IsFertile() = false;
+ return false;
+ }
+ }
+
+ return true; // (divide succeeds!)
+}
+
+
+void cHardwareCPU::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().GetSize(); i++) {
+ if (organism->TestParentMut()) {
+ GetMemory()[i] = GetRandomInst();
+ cpu_stats.mut_stats.parent_mut_line_count++;
+ }
+ }
+ }
+
+
+ // Count up mutated lines
+ for(int i = 0; i < GetMemory().GetSize(); i++){
+ if (GetMemory().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++;
+ }
+ }
+}
+
+
+// test whether the offspring creature contains an advantageous mutation.
+void cHardwareCPU::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 cHardwareCPU::Divide_Main(const int div_point, const int extra_lines, double mut_multiplier)
+{
+ const int child_size = GetMemory().GetSize() - div_point - extra_lines;
+
+ // Make sure this divide will produce a viable offspring.
+ const bool viable = Divide_CheckViable(child_size, div_point);
+ if (viable == false) return false;
+
+ // Since the divide will now succeed, set up the information to be sent
+ // to the new organism
+ cGenome & child_genome = organism->ChildGenome();
+ child_genome = cGenomeUtil::Crop(memory, div_point, div_point+child_size);
+
+ // Cut off everything in this memory past the divide point.
+ GetMemory().Resize(div_point);
+
+ // 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
+
+ mal_active = false;
+ if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) {
+ advance_ip = false;
+ }
+
+ // Activate the child, and do more work if the parent lives through the
+ // birth.
+ bool parent_alive = organism->ActivateDivide();
+ if (parent_alive) {
+ if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) Reset();
+ }
+
+ return true;
+}
+
+
+//////////////////////////
+// And the instructions...
+//////////////////////////
+
+bool cHardwareCPU::Inst_If0() // Execute next if ?bx? ==0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (Register(reg_used) != 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfNot0() // Execute next if ?bx? != 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (Register(reg_used) == 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfEqu() // Execute next if bx == ?cx?
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int reg_used2 = FindComplementRegister(reg_used);
+ if (Register(reg_used) != Register(reg_used2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfNEqu() // Execute next if bx != ?cx?
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int reg_used2 = FindComplementRegister(reg_used);
+ if (Register(reg_used) == Register(reg_used2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfGr0() // Execute next if ?bx? ! < 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (Register(reg_used) <= 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfGr() // Execute next if bx > ?cx?
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int reg_used2 = FindComplementRegister(reg_used);
+ if (Register(reg_used) <= Register(reg_used2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfGrEqu0() // Execute next if ?bx? != 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (Register(reg_used) < 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfGrEqu() // Execute next if bx > ?cx?
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int reg_used2 = FindComplementRegister(reg_used);
+ if (Register(reg_used) < Register(reg_used2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfLess0() // Execute next if ?bx? != 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (Register(reg_used) >= 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfLess() // Execute next if ?bx? < ?cx?
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int reg_used2 = FindComplementRegister(reg_used);
+ if (Register(reg_used) >= Register(reg_used2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfLsEqu0() // Execute next if ?bx? != 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (Register(reg_used) > 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfLsEqu() // Execute next if bx > ?cx?
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int reg_used2 = FindComplementRegister(reg_used);
+ if (Register(reg_used) > Register(reg_used2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfBit1()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if ((Register(reg_used) & 1) == 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfANotEqB() // Execute next if AX != BX
+{
+ if (Register(REG_AX) == Register(REG_BX) ) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfBNotEqC() // Execute next if BX != CX
+{
+ if (Register(REG_BX) == Register(REG_CX) ) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfANotEqC() // Execute next if AX != BX
+{
+ if (Register(REG_AX) == Register(REG_CX) ) IP().Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_JumpF()
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+
+ // If there is no label, jump BX steps.
+ if (GetLabel().GetSize() == 0) {
+ GetActiveHead().Jump(Register(REG_BX));
+ return true;
+ }
+
+ // Otherwise, try to jump to the complement label.
+ const cHeadCPU jump_location(FindLabel(1));
+ if ( jump_location.GetPosition() != -1 ) {
+ GetActiveHead().Set(jump_location);
+ return true;
+ }
+
+ // If complement label was not found; record an error.
+ organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+ "jump-f: No complement label");
+ return false;
+}
+
+
+bool cHardwareCPU::Inst_JumpB()
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+
+ // If there is no label, jump BX steps.
+ if (GetLabel().GetSize() == 0) {
+ GetActiveHead().Jump(-Register(REG_BX));
+ return true;
+ }
+
+ // otherwise jump to the complement label.
+ const cHeadCPU jump_location(FindLabel(-1));
+ if ( jump_location.GetPosition() != -1 ) {
+ GetActiveHead().Set(jump_location);
+ return true;
+ }
+
+ // If complement label was not found; record an error.
+ organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+ "jump-b: No complement label");
+ return false;
+}
+
+bool cHardwareCPU::Inst_JumpP()
+{
+ cOrganism * other_organism = organism->GetNeighbor();
+
+ // Make sure the other organism was found and that its hardware is of the
+ // same type, or else we won't be able to be parasitic on it.
+ if (other_organism == NULL ||
+ other_organism->GetHardware().GetType() != GetType()) {
+ // Without another organism, its hard to determine if we're dealing
+ // with a parasite. For the moment, we'll assume it is and move on.
+ // @CAO Do better!
+ organism->GetPhenotype().IsParasite() = true;
+ return true;
+ }
+
+ // Otherwise, grab the hardware from the neighbor, and use it!
+ cHardwareCPU & other_hardware = (cHardwareCPU &) other_organism->GetHardware();
+
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+
+ // If there is no label, jump to line BX in creature.
+ if (GetLabel().GetSize() == 0) {
+ const int new_pos = Register(REG_BX);
+ IP().Set(new_pos, &other_hardware);
+ organism->GetPhenotype().IsParasite() = true;
+ return true;
+ }
+
+ // otherwise jump to the complement label.
+ const cHeadCPU jump_location(other_hardware.FindFullLabel(GetLabel()));
+ if (jump_location.GetPosition() != -1) {
+ IP().Set(jump_location);
+ organism->GetPhenotype().IsParasite() = true;
+ return true;
+ }
+
+ // If complement label was not found; record a warning (since the
+ // actual neighbors are not under the organisms control, this is not
+ // a full-scale error).
+ organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_WARNING,
+ "jump-p: No complement label");
+ return false;
+}
+
+bool cHardwareCPU::Inst_JumpSelf()
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+
+ // If there is no label, jump to line BX in creature.
+ if (GetLabel().GetSize() == 0) {
+ IP().Set(Register(REG_BX), this);
+ return true;
+ }
+
+ // otherwise jump to the complement label.
+ const cHeadCPU jump_location( FindFullLabel(GetLabel()) );
+ if ( jump_location.GetPosition() != -1 ) {
+ IP().Set(jump_location);
+ return true;
+ }
+
+ // If complement label was not found; record an error.
+ organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+ "jump-slf: no complement label");
+ return false;
+}
+
+bool cHardwareCPU::Inst_Call()
+{
+ // Put the starting location onto the stack
+ const int location = IP().GetPosition();
+ StackPush(location);
+
+ // Jump to the compliment label (or by the ammount in the bx register)
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+
+ if (GetLabel().GetSize() == 0) {
+ IP().Jump(Register(REG_BX));
+ return true;
+ }
+
+ const cHeadCPU jump_location(FindLabel(1));
+ if (jump_location.GetPosition() != -1) {
+ IP().Set(jump_location);
+ return true;
+ }
+
+ // If complement label was not found; record an error.
+ organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+ "call: no complement label");
+ return false;
+}
+
+bool cHardwareCPU::Inst_Return()
+{
+ IP().Set(StackPop());
+ return true;
+}
+
+bool cHardwareCPU::Inst_Pop()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = StackPop();
+ return true;
+}
+
+bool cHardwareCPU::Inst_Push()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ StackPush(Register(reg_used));
+ return true;
+}
+
+bool cHardwareCPU::Inst_HeadPop()
+{
+ const int head_used = FindModifiedHead(HEAD_IP);
+ GetHead(head_used).Set(StackPop(), this);
+ return true;
+}
+
+bool cHardwareCPU::Inst_HeadPush()
+{
+ const int head_used = FindModifiedHead(HEAD_IP);
+ StackPush(GetHead(head_used).GetPosition());
+ if (head_used == HEAD_IP) {
+ GetHead(head_used).Set(GetHead(HEAD_FLOW));
+ advance_ip = false;
+ }
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_PopA() { Register(REG_AX) = StackPop(); return true;}
+bool cHardwareCPU::Inst_PopB() { Register(REG_BX) = StackPop(); return true;}
+bool cHardwareCPU::Inst_PopC() { Register(REG_CX) = StackPop(); return true;}
+
+bool cHardwareCPU::Inst_PushA() { StackPush(Register(REG_AX)); return true;}
+bool cHardwareCPU::Inst_PushB() { StackPush(Register(REG_BX)); return true;}
+bool cHardwareCPU::Inst_PushC() { StackPush(Register(REG_CX)); return true;}
+
+bool cHardwareCPU::Inst_SwitchStack() { SwitchStack(); return true;}
+bool cHardwareCPU::Inst_FlipStack() { StackFlip(); return true;}
+
+bool cHardwareCPU::Inst_Swap()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int other_reg = FindComplementRegister(reg_used);
+// cout << endl;
+// cout << "Regs 1, 2, 3 are: " << Register(1) << " " << Register(2) << " " << Register(3) << endl;
+// cout << "Modified reg = " << reg_used << ", Complement reg = " << other_reg << endl;
+// cout << "Calling Swap with " << Register(reg_used) << " and " << Register(other_reg) << endl;
+ nFunctions::Swap(Register(reg_used), Register(other_reg));
+// cout << "Current State is " << Register(reg_used) << " and " << Register(other_reg) << endl;
+// cout << "Regs 1, 2, 3 are: " << Register(1) << " " << Register(2) << " " << Register(3) << endl;
+ return true;
+}
+
+bool cHardwareCPU::Inst_SwapAB() { nFunctions::Swap(Register(REG_AX), Register(REG_BX)); return true; }
+bool cHardwareCPU::Inst_SwapBC() { nFunctions::Swap(Register(REG_BX), Register(REG_CX)); return true; }
+bool cHardwareCPU::Inst_SwapAC() { nFunctions::Swap(Register(REG_AX), Register(REG_CX)); return true; }
+
+bool cHardwareCPU::Inst_CopyReg()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int other_reg = FindComplementRegister(reg_used);
+ Register(other_reg) = Register(reg_used);
+ return true;
+}
+
+bool cHardwareCPU::Inst_CopyRegAB() { Register(REG_AX) = Register(REG_BX); return true;
+}
+bool cHardwareCPU::Inst_CopyRegAC() { Register(REG_AX) = Register(REG_CX); return true;
+}
+bool cHardwareCPU::Inst_CopyRegBA() { Register(REG_BX) = Register(REG_AX); return true;
+}
+bool cHardwareCPU::Inst_CopyRegBC() { Register(REG_BX) = Register(REG_CX); return true;
+}
+bool cHardwareCPU::Inst_CopyRegCA() { Register(REG_CX) = Register(REG_AX); return true;
+}
+bool cHardwareCPU::Inst_CopyRegCB() { Register(REG_CX) = Register(REG_BX); return true;
+}
+
+bool cHardwareCPU::Inst_Reset()
+{
+ Register(REG_AX) = 0;
+ Register(REG_BX) = 0;
+ Register(REG_CX) = 0;
+ StackClear();
+ return true;
+}
+
+bool cHardwareCPU::Inst_ShiftR()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) >>= 1;
+ return true;
+}
+
+bool cHardwareCPU::Inst_ShiftL()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) <<= 1;
+ return true;
+}
+
+bool cHardwareCPU::Inst_Bit1()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) |= 1;
+ return true;
+}
+
+bool cHardwareCPU::Inst_SetNum()
+{
+ ReadLabel();
+ Register(REG_BX) = GetLabel().AsInt(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareCPU::Inst_ValGrey(void) {
+ ReadLabel();
+ Register(REG_BX) = GetLabel().AsIntGreyCode(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareCPU::Inst_ValDir(void) {
+ ReadLabel();
+ Register(REG_BX) = GetLabel().AsIntDirect(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareCPU::Inst_ValAddP(void) {
+ ReadLabel();
+ Register(REG_BX) = GetLabel().AsIntAdditivePolynomial(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareCPU::Inst_ValFib(void) {
+ ReadLabel();
+ Register(REG_BX) = GetLabel().AsIntFib(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareCPU::Inst_ValPolyC(void) {
+ ReadLabel();
+ Register(REG_BX) = GetLabel().AsIntPolynomialCoefficent(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareCPU::Inst_Inc()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) += 1;
+ return true;
+}
+
+bool cHardwareCPU::Inst_Dec()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) -= 1;
+ return true;
+}
+
+bool cHardwareCPU::Inst_Zero()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = 0;
+ return true;
+}
+
+bool cHardwareCPU::Inst_Neg()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = 0-Register(reg_used);
+ return true;
+}
+
+bool cHardwareCPU::Inst_Square()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = Register(reg_used) * Register(reg_used);
+ return true;
+}
+
+bool cHardwareCPU::Inst_Sqrt()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int value = Register(reg_used);
+ if (value > 1) Register(reg_used) = (int) sqrt((double) value);
+ else if (value < 0) {
+ Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "sqrt: value is negative");
+ return false;
+ }
+ return true;
+}
+
+bool cHardwareCPU::Inst_Log()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int value = Register(reg_used);
+ if (value >= 1) Register(reg_used) = (int) log((double) value);
+ else if (value < 0) {
+ Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "log: value is negative");
+ return false;
+ }
+ return true;
+}
+
+bool cHardwareCPU::Inst_Log10()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int value = Register(reg_used);
+ if (value >= 1) Register(reg_used) = (int) log10((double) value);
+ else if (value < 0) {
+ Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "log10: value is negative");
+ return false;
+ }
+ return true;
+}
+
+bool cHardwareCPU::Inst_Minus17()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) -= 17;
+ return true;
+}
+
+bool cHardwareCPU::Inst_Add()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = Register(REG_BX) + Register(REG_CX);
+ return true;
+}
+
+bool cHardwareCPU::Inst_Sub()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = Register(REG_BX) - Register(REG_CX);
+ return true;
+}
+
+bool cHardwareCPU::Inst_Mult()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = Register(REG_BX) * Register(REG_CX);
+ return true;
+}
+
+bool cHardwareCPU::Inst_Div()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (Register(REG_CX) != 0) {
+ if (0-INT_MAX > Register(REG_BX) && Register(REG_CX) == -1)
+ Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: Float exception");
+ else
+ Register(reg_used) = Register(REG_BX) / Register(REG_CX);
+ } else {
+ Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: dividing by 0");
+ return false;
+ }
+ return true;
+}
+
+bool cHardwareCPU::Inst_Mod()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (Register(REG_CX) != 0) {
+ Register(reg_used) = Register(REG_BX) % Register(REG_CX);
+ } else {
+ Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "mod: modding by 0");
+ return false;
+ }
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_Nand()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = ~(Register(REG_BX) & Register(REG_CX));
+ return true;
+}
+
+bool cHardwareCPU::Inst_Nor()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = ~(Register(REG_BX) | Register(REG_CX));
+ return true;
+}
+
+bool cHardwareCPU::Inst_And()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = (Register(REG_BX) & Register(REG_CX));
+ return true;
+}
+
+bool cHardwareCPU::Inst_Not()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = ~(Register(reg_used));
+ return true;
+}
+
+bool cHardwareCPU::Inst_Order()
+{
+ if (Register(REG_BX) > Register(REG_CX)) {
+ nFunctions::Swap(Register(REG_BX), Register(REG_CX));
+ }
+ return true;
+}
+
+bool cHardwareCPU::Inst_Xor()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = Register(REG_BX) ^ Register(REG_CX);
+ return true;
+}
+
+bool cHardwareCPU::Inst_Copy()
+{
+ const cHeadCPU from(this, Register(REG_BX));
+ cHeadCPU to(this, Register(REG_AX) + Register(REG_BX));
+ sCPUStats & cpu_stats = organism->CPUStats();
+
+ if (organism->TestCopyMut()) {
+ to.SetInst(GetRandomInst());
+ to.FlagMutated() = true; // Mark this instruction as mutated...
+ to.FlagCopyMut() = true; // Mark this instruction as copy mut...
+ //organism->GetPhenotype().IsMutated() = true;
+ cpu_stats.mut_stats.copy_mut_count++;
+ } else {
+ to.SetInst(from.GetInst());
+ to.FlagMutated() = false; // UnMark
+ to.FlagCopyMut() = false; // UnMark
+ }
+
+ to.FlagCopied() = true; // Set the copied flag.
+ cpu_stats.mut_stats.copies_exec++;
+ return true;
+}
+
+bool cHardwareCPU::Inst_ReadInst()
+{
+ const int reg_used = FindModifiedRegister(REG_CX);
+ const cHeadCPU from(this, Register(REG_BX));
+
+ // Dis-allowing mutations on read, for the moment (write only...)
+ // @CAO This allows perfect error-correction...
+ Register(reg_used) = from.GetInst().GetOp();
+ return true;
+}
+
+bool cHardwareCPU::Inst_WriteInst()
+{
+ cHeadCPU to(this, Register(REG_AX) + Register(REG_BX));
+ const int reg_used = FindModifiedRegister(REG_CX);
+ const int value = Mod(Register(reg_used), GetNumInst());
+ sCPUStats & cpu_stats = organism->CPUStats();
+
+ // Change value on a mutation...
+ if (organism->TestCopyMut()) {
+ to.SetInst(GetRandomInst());
+ to.FlagMutated() = true; // Mark this instruction as mutated...
+ to.FlagCopyMut() = true; // Mark this instruction as copy mut...
+ //organism->GetPhenotype().IsMutated() = true;
+ cpu_stats.mut_stats.copy_mut_count++;
+ } else {
+ to.SetInst(cInstruction(value));
+ to.FlagMutated() = false; // UnMark
+ to.FlagCopyMut() = false; // UnMark
+ }
+
+ to.FlagCopied() = true; // Set the copied flag.
+ cpu_stats.mut_stats.copies_exec++;
+ return true;
+}
+
+bool cHardwareCPU::Inst_StackReadInst()
+{
+ const int reg_used = FindModifiedRegister(REG_CX);
+ cHeadCPU from(this, Register(reg_used));
+ StackPush(from.GetInst().GetOp());
+ return true;
+}
+
+bool cHardwareCPU::Inst_StackWriteInst()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ cHeadCPU to(this, Register(REG_AX) + Register(reg_used));
+ const int value = Mod(StackPop(), GetNumInst());
+ sCPUStats & cpu_stats = organism->CPUStats();
+
+ // Change value on a mutation...
+ if (organism->TestCopyMut()) {
+ to.SetInst(GetRandomInst());
+ to.FlagMutated() = true; // Mark this instruction as mutated...
+ to.FlagCopyMut() = true; // Mark this instruction as copy mut...
+ //organism->GetPhenotype().IsMutated() = true;
+ cpu_stats.mut_stats.copy_mut_count++;
+ } else {
+ to.SetInst(cInstruction(value));
+ to.FlagMutated() = false; // UnMark
+ to.FlagCopyMut() = false; // UnMark
+ }
+
+ to.FlagCopied() = true; // Set the copied flag.
+ cpu_stats.mut_stats.copies_exec++;
+ return true;
+}
+
+bool cHardwareCPU::Inst_Compare()
+{
+ const int reg_used = FindModifiedRegister(REG_CX);
+ cHeadCPU from(this, Register(REG_BX));
+ cHeadCPU to(this, Register(REG_AX) + Register(REG_BX));
+
+ // Compare is dangerous -- it can cause mutations!
+ if (organism->TestCopyMut()) {
+ to.SetInst(GetRandomInst());
+ to.FlagMutated() = true; // Mark this instruction as mutated...
+ to.FlagCopyMut() = true; // Mark this instruction as copy mut...
+ //organism->GetPhenotype().IsMutated() = true;
+ }
+
+ Register(reg_used) = from.GetInst().GetOp() - to.GetInst().GetOp();
+
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfNCpy()
+{
+ const cHeadCPU from(this, Register(REG_BX));
+ const cHeadCPU to(this, Register(REG_AX) + Register(REG_BX));
+
+ // Allow for errors in this test...
+ if (organism->TestCopyMut()) {
+ if (from.GetInst() != to.GetInst()) IP().Advance();
+ } else {
+ if (from.GetInst() == to.GetInst()) IP().Advance();
+ }
+ return true;
+}
+
+bool cHardwareCPU::Inst_Allocate() // Allocate bx more space...
+{
+ const int size = GetMemory().GetSize();
+ if( Allocate_Main(Register(REG_BX)) ) {
+ Register(REG_AX) = size;
+ return true;
+ } else return false;
+}
+
+bool cHardwareCPU::Inst_Divide()
+{
+ return Divide_Main(Register(REG_AX));
+}
+
+bool cHardwareCPU::Inst_CDivide()
+{
+ return Divide_Main(GetMemory().GetSize() / 2);
+}
+
+bool cHardwareCPU::Inst_CAlloc()
+{
+ return Allocate_Main(GetMemory().GetSize());
+}
+
+bool cHardwareCPU::Inst_MaxAlloc() // Allocate maximal more
+{
+ const int cur_size = GetMemory().GetSize();
+ const int alloc_size = Min((int) (cConfig::GetChildSizeRange() * cur_size),
+ MAX_CREATURE_SIZE - cur_size);
+ if( Allocate_Main(alloc_size) ) {
+ Register(REG_AX) = cur_size;
+ return true;
+ } else return false;
+}
+
+
+bool cHardwareCPU::Inst_Repro()
+{
+ // Setup child
+ cCPUMemory & child_genome = organism->ChildGenome();
+ child_genome = GetMemory();
+ organism->GetPhenotype().SetLinesCopied(GetMemory().GetSize());
+
+ int lines_executed = 0;
+ for ( int i = 0; i < GetMemory().GetSize(); i++ ) {
+ if ( GetMemory().FlagExecuted(i) == true ) lines_executed++;
+ }
+ organism->GetPhenotype().SetLinesExecuted(lines_executed);
+
+ // Perform Copy Mutations...
+ if (organism->GetCopyMutProb() > 0) { // Skip this if no mutations....
+ for (int i = 0; i < GetMemory().GetSize(); i++) {
+ if (organism->TestCopyMut()) {
+ child_genome[i]=GetRandomInst();
+ //organism->GetPhenotype().IsMutated() = true;
+ }
+ }
+ }
+ Divide_DoMutations();
+
+ // 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
+
+ if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) advance_ip = false;
+
+ organism->ActivateDivide();
+
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_Kazi()
+{
+ const int reg_used = FindModifiedRegister(REG_AX);
+ int percentProb = Register(reg_used) % 100;
+ int random = abs(rand()) % 100;
+ if (random >= percentProb)
+ {
+ return true;
+ }
+ else
+ {
+ organism->Kaboom();
+ return true;
+ }
+}
+
+bool cHardwareCPU::Inst_Die()
+{
+ const double die_prob = cConfig::GetDieProb();
+ if(g_random.GetDouble() < die_prob) { organism->Die(); }
+ 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 cHardwareCPU::Inst_Inject()
+{
+ AdjustHeads();
+ const int start_pos = GetHead(HEAD_READ).GetPosition();
+ const int end_pos = GetHead(HEAD_WRITE).GetPosition();
+ const int inject_size = end_pos - start_pos;
+
+ // Make sure the creature will still be above the minimum size,
+ if (inject_size <= 0) {
+ Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
+ return false; // (inject fails)
+ }
+ if (start_pos < MIN_CREATURE_SIZE) {
+ Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
+ return false; // (inject fails)
+ }
+
+ // Since its legal to cut out the injected piece, do so.
+ cGenome inject_code( cGenomeUtil::Crop(GetMemory(), start_pos, end_pos) );
+ GetMemory().Remove(start_pos, inject_size);
+
+ // If we don't have a host, stop here.
+ cOrganism * host_organism = organism->GetNeighbor();
+ if (host_organism == NULL) return false;
+
+ // Scan for the label to match...
+ ReadLabel();
+
+ // If there is no label, abort.
+ if (GetLabel().GetSize() == 0) {
+ Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: label required");
+ return false; // (inject fails)
+ }
+
+ // Search for the label in the host...
+ GetLabel().Rotate(1, NUM_NOPS);
+
+ const bool inject_signal = host_organism->GetHardware().InjectHost(GetLabel(), inject_code);
+ if (inject_signal) {
+ Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: host too large.");
+ return false; // Inject failed.
+ }
+
+ // Set the relevent flags.
+ organism->GetPhenotype().IsModifier() = true;
+
+ return inject_signal;
+}
+
+
+bool cHardwareCPU::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;
+}
+
+// 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 cHardwareCPU::Inst_InjectThread()
+{
+ AdjustHeads();
+ const int start_pos = GetHead(HEAD_READ).GetPosition();
+ const int end_pos = GetHead(HEAD_WRITE).GetPosition();
+ const int inject_size = end_pos - start_pos;
+
+ // Make sure the creature will still be above the minimum size,
+ if (inject_size <= 0) {
+ Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
+ return false; // (inject fails)
+ }
+ if (start_pos < MIN_CREATURE_SIZE) {
+ Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
+ return false; // (inject fails)
+ }
+
+ // Since its legal to cut out the injected piece, do so.
+ cGenome inject_code( cGenomeUtil::Crop(GetMemory(), start_pos, end_pos) );
+ GetMemory().Remove(start_pos, inject_size);
+
+ // If we don't have a host, stop here.
+ cOrganism * host_organism = organism->GetNeighbor();
+ if (host_organism == NULL) return false;
+
+ // Scan for the label to match...
+ ReadLabel();
+
+ // If there is no label, abort.
+ if (GetLabel().GetSize() == 0) {
+ Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: label required");
+ return false; // (inject fails)
+ }
+
+ // Search for the label in the host...
+ GetLabel().Rotate(1, NUM_NOPS);
+
+ const int inject_signal =
+ host_organism->GetHardware().InjectThread(GetLabel(), inject_code);
+ if (inject_signal == 1) {
+ Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: host too large.");
+ return false; // Inject failed.
+ }
+ if (inject_signal == 2) {
+ Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: target not in host.");
+ return false; // Inject failed.
+ }
+
+ // Set the relevent flags.
+ organism->GetPhenotype().IsModifier() = true;
+
+ return true;
+}
+
+bool cHardwareCPU::Inst_TaskGet()
+{
+ const int reg_used = FindModifiedRegister(REG_CX);
+ const int value = organism->GetNextInput();
+ Register(reg_used) = value;
+ organism->DoInput(value);
+ return true;
+}
+
+bool cHardwareCPU::Inst_TaskStackGet()
+{
+ const int value = organism->GetNextInput();
+ StackPush(value);
+ organism->DoInput(value);
+ return true;
+}
+
+bool cHardwareCPU::Inst_TaskStackLoad()
+{
+ for (int i = 0; i < IO_SIZE; i++)
+ StackPush( organism->GetNextInput() );
+ return true;
+}
+
+bool cHardwareCPU::Inst_TaskPut()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int value = Register(reg_used);
+ Register(reg_used) = 0;
+ organism->DoOutput(value);
+ return true;
+}
+
+bool cHardwareCPU::Inst_TaskIO()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+
+ // Do the "put" component
+ const int value_out = Register(reg_used);
+ organism->DoOutput(value_out); // Check for tasks compleated.
+
+ // Do the "get" component
+ const int value_in = organism->GetNextInput();
+ Register(reg_used) = value_in;
+ organism->DoInput(value_in);
+ return true;
+}
+
+bool cHardwareCPU::Inst_Send()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ organism->SendValue(Register(reg_used));
+ Register(reg_used) = 0;
+ return true;
+}
+
+bool cHardwareCPU::Inst_Receive()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = organism->ReceiveValue();
+ return true;
+}
+
+bool cHardwareCPU::Inst_Sense()
+{
+ const tArray<double> & res_count = organism->PopInterface().GetResources();
+ const int reg_used = FindModifiedRegister(REG_BX);
+
+ // If there are no resources to measure, this instruction fails.
+ if (res_count.GetSize() == 0) return false;
+
+ // Always get the first resource, and convert it to and int.
+ Register(reg_used) = (int) res_count[0];
+
+ // @CAO Since resources are sometimes less than one, perhaps we should
+ // multiply it by some constant? Or perhaps taking the log would be more
+ // useful so they can easily scan across orders of magnitude?
+
+ return true;
+}
+
+void cHardwareCPU::DoDonate(cOrganism * to_org)
+{
+ assert(to_org != NULL);
+
+ const double merit_given = cConfig::GetMeritGiven();
+ const double merit_received = cConfig::GetMeritReceived();
+
+ double cur_merit = organism->GetPhenotype().GetMerit().GetDouble();
+ cur_merit -= merit_given;
+
+ // Plug the current merit back into this organism and notify the scheduler.
+ organism->UpdateMerit(cur_merit);
+
+ // Update the merit of the organism being donated to...
+ double other_merit = to_org->GetPhenotype().GetMerit().GetDouble();
+ other_merit += merit_received;
+ to_org->UpdateMerit(other_merit);
+}
+
+bool cHardwareCPU::Inst_DonateRandom()
+{
+ organism->GetPhenotype().IncDonates();
+ if (organism->GetPhenotype().GetCurNumDonates() > cConfig::GetMaxDonates()) {
+ return false;
+ }
+
+ // Turn to a random neighbor, get it, and turn back...
+ int neighbor_id = g_random.GetInt(organism->GetNeighborhoodSize());
+ for (int i = 0; i < neighbor_id; i++) organism->Rotate(1);
+ cOrganism * neighbor = organism->GetNeighbor();
+ for (int i = 0; i < neighbor_id; i++) organism->Rotate(-1);
+
+ // Donate only if we have found a neighbor.
+ if (neighbor != NULL) DoDonate(neighbor);
+
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_DonateKin()
+{
+ organism->GetPhenotype().IncDonates();
+ if (organism->GetPhenotype().GetCurNumDonates() > cConfig::GetMaxDonates()) {
+ return false;
+ }
+
+ // Find the target as the first Kin found in the neighborhood.
+ const int num_neighbors = organism->GetNeighborhoodSize();
+
+ // Turn to face a random neighbor
+ int neighbor_id = g_random.GetInt(num_neighbors);
+ for (int i = 0; i < neighbor_id; i++) organism->Rotate(1);
+ cOrganism * neighbor = organism->GetNeighbor();
+
+ // If there is no max distance, just take the random neighbor we're facing.
+ const int max_dist = cConfig::GetMaxDonateKinDistance();
+ if (max_dist != -1) {
+ int max_id = neighbor_id + num_neighbors;
+ bool found = false;
+ cGenotype * genotype = organism->GetGenotype();
+ while (neighbor_id < max_id) {
+ neighbor = organism->GetNeighbor();
+ if (neighbor != NULL &&
+ genotype->GetPhyloDistance(neighbor->GetGenotype()) <= max_dist) {
+ found = true;
+ break;
+ }
+ organism->Rotate(1);
+ neighbor_id++;
+ }
+ if (found == false) neighbor = NULL;
+ }
+
+ // Put the facing back where it was.
+ for (int i = 0; i < neighbor_id; i++) organism->Rotate(-1);
+
+ // Donate only if we have found a close enough relative...
+ if (neighbor != NULL) DoDonate(neighbor);
+
+ return true;
+}
+
+bool cHardwareCPU::Inst_DonateEditDist()
+{
+ organism->GetPhenotype().IncDonates();
+ if (organism->GetPhenotype().GetCurNumDonates() > cConfig::GetMaxDonates()) {
+ return false;
+ }
+
+ // Find the target as the first Kin found in the neighborhood.
+ const int num_neighbors = organism->GetNeighborhoodSize();
+
+ // Turn to face a random neighbor
+ int neighbor_id = g_random.GetInt(num_neighbors);
+ for (int i = 0; i < neighbor_id; i++) organism->Rotate(1);
+ cOrganism * neighbor = organism->GetNeighbor();
+
+ // If there is no max edit distance, take the random neighbor we're facing.
+ const int max_dist = cConfig::GetMaxDonateEditDistance();
+ if (max_dist != -1) {
+ int max_id = neighbor_id + num_neighbors;
+ bool found = false;
+ while (neighbor_id < max_id) {
+ neighbor = organism->GetNeighbor();
+ int edit_dist = max_dist + 1;
+ if (neighbor != NULL) {
+ edit_dist = cGenomeUtil::FindEditDistance(organism->GetGenome(),
+ neighbor->GetGenome());
+ }
+ if (edit_dist <= max_dist) {
+ found = true;
+ break;
+ }
+ organism->Rotate(1);
+ neighbor_id++;
+ }
+ if (found == false) neighbor = NULL;
+ }
+
+ // Put the facing back where it was.
+ for (int i = 0; i < neighbor_id; i++) organism->Rotate(-1);
+
+ // Donate only if we have found a close enough relative...
+ if (neighbor != NULL) DoDonate(neighbor);
+
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_DonateNULL()
+{
+ organism->GetPhenotype().IncDonates();
+ if (organism->GetPhenotype().GetCurNumDonates() > cConfig::GetMaxDonates()) {
+ return false;
+ }
+
+ // This is a fake donate command that causes the organism to lose merit,
+ // but no one else to gain any.
+
+ const double merit_given = cConfig::GetMeritGiven();
+ double cur_merit = organism->GetPhenotype().GetMerit().GetDouble();
+ cur_merit -= merit_given;
+
+ // Plug the current merit back into this organism and notify the scheduler.
+ organism->UpdateMerit(cur_merit);
+
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_SearchF()
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+ const int search_size = FindLabel(1).GetPosition() - IP().GetPosition();
+ Register(REG_BX) = search_size;
+ Register(REG_CX) = GetLabel().GetSize();
+ return true;
+}
+
+bool cHardwareCPU::Inst_SearchB()
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+ const int search_size = IP().GetPosition() - FindLabel(-1).GetPosition();
+ Register(REG_BX) = search_size;
+ Register(REG_CX) = GetLabel().GetSize();
+ return true;
+}
+
+bool cHardwareCPU::Inst_MemSize()
+{
+ Register(FindModifiedRegister(REG_BX)) = GetMemory().GetSize();
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_RotateL()
+{
+ const int num_neighbors = organism->GetNeighborhoodSize();
+
+ // If this organism has no neighbors, ignore rotate.
+ if (num_neighbors == 0) return false;
+
+ ReadLabel();
+
+ // Always rotate at least once.
+ organism->Rotate(-1);
+
+ // If there is no label, then the one rotation was all we want.
+ if (!GetLabel().GetSize()) return true;
+
+ // Rotate until a complement label is found (or all have been checked).
+ GetLabel().Rotate(1, NUM_NOPS);
+ for (int i = 1; i < num_neighbors; i++) {
+ cOrganism * neighbor = organism->GetNeighbor();
+
+ // Assuming we have a neighbor and it is of the same hardware type,
+ // search for the label in it.
+ if (neighbor != NULL &&
+ neighbor->GetHardware().GetType() == GetType()) {
+
+ // If this facing has the full label, stop here.
+ cHardwareCPU & cur_hardware = (cHardwareCPU &) neighbor->GetHardware();
+ if (cur_hardware.FindFullLabel( GetLabel() ).InMemory()) return true;
+ }
+
+ // Otherwise keep rotating...
+ organism->Rotate(-1);
+ }
+ return true;
+}
+
+bool cHardwareCPU::Inst_RotateR()
+{
+ const int num_neighbors = organism->GetNeighborhoodSize();
+
+ // If this organism has no neighbors, ignore rotate.
+ if (num_neighbors == 0) return false;
+
+ ReadLabel();
+
+ // Always rotate at least once.
+ organism->Rotate(-1);
+
+ // If there is no label, then the one rotation was all we want.
+ if (!GetLabel().GetSize()) return true;
+
+ // Rotate until a complement label is found (or all have been checked).
+ GetLabel().Rotate(1, NUM_NOPS);
+ for (int i = 1; i < num_neighbors; i++) {
+ cOrganism * neighbor = organism->GetNeighbor();
+
+ // Assuming we have a neighbor and it is of the same hardware type,
+ // search for the label in it.
+ if (neighbor != NULL &&
+ neighbor->GetHardware().GetType() == GetType()) {
+
+ // If this facing has the full label, stop here.
+ cHardwareCPU & cur_hardware = (cHardwareCPU &) neighbor->GetHardware();
+ if (cur_hardware.FindFullLabel( GetLabel() ).InMemory()) return true;
+ }
+
+ // Otherwise keep rotating...
+ organism->Rotate(1);
+ }
+ return true;
+}
+
+bool cHardwareCPU::Inst_SetCopyMut()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int new_mut_rate = Max( Register(reg_used), 1 );
+ organism->SetCopyMutProb(((double) new_mut_rate) / 10000.0);
+ return true;
+}
+
+bool cHardwareCPU::Inst_ModCopyMut()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const double new_mut_rate = organism->GetCopyMutProb() +
+ ((double) Register(reg_used)) / 10000.0;
+ if (new_mut_rate > 0.0) organism->SetCopyMutProb(new_mut_rate);
+ return true;
+}
+
+
+// Multi-threading.
+
+bool cHardwareCPU::Inst_ForkThread()
+{
+ IP().Advance();
+ if (!ForkThread()) Fault(FAULT_LOC_THREAD_FORK, FAULT_TYPE_FORK_TH);
+ return true;
+}
+
+bool cHardwareCPU::Inst_KillThread()
+{
+ if (!KillThread()) Fault(FAULT_LOC_THREAD_KILL, FAULT_TYPE_KILL_TH);
+ else advance_ip = false;
+ return true;
+}
+
+bool cHardwareCPU::Inst_ThreadID()
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ Register(reg_used) = GetCurThreadID();
+ return true;
+}
+
+
+// Head-based instructions
+
+bool cHardwareCPU::Inst_SetHead()
+{
+ const int head_used = FindModifiedHead(HEAD_IP);
+ SetActiveHead(head_used);
+ return true;
+}
+
+bool cHardwareCPU::Inst_AdvanceHead()
+{
+ const int head_used = FindModifiedHead(HEAD_WRITE);
+ GetHead(head_used).Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_MoveHead()
+{
+ const int head_used = FindModifiedHead(HEAD_IP);
+ GetHead(head_used).Set(GetHead(HEAD_FLOW));
+ if (head_used == HEAD_IP) advance_ip = false;
+ return true;
+}
+
+bool cHardwareCPU::Inst_JumpHead()
+{
+ const int head_used = FindModifiedHead(HEAD_IP);
+ GetHead(head_used).Jump( Register(REG_CX) );
+ return true;
+}
+
+bool cHardwareCPU::Inst_GetHead()
+{
+ const int head_used = FindModifiedHead(HEAD_IP);
+ Register(REG_CX) = GetHead(head_used).GetPosition();
+ return true;
+}
+
+bool cHardwareCPU::Inst_IfLabel()
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+ if (GetLabel() != GetReadLabel()) IP().Advance();
+ return true;
+}
+
+// This is a variation on IfLabel that will skip the next command if the "if"
+// is false, but it will also skip all nops following that command.
+bool cHardwareCPU::Inst_IfLabel2()
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+ if (GetLabel() != GetReadLabel()) {
+ IP().Advance();
+ if (inst_set->IsNop( IP().GetNextInst() )) IP().Advance();
+ }
+ return true;
+}
+
+bool cHardwareCPU::Inst_HeadDivideMut(double mut_multiplier)
+{
+ AdjustHeads();
+ const int divide_pos = GetHead(HEAD_READ).GetPosition();
+ int child_end = GetHead(HEAD_WRITE).GetPosition();
+ if (child_end == 0) child_end = GetMemory().GetSize();
+ const int extra_lines = GetMemory().GetSize() - child_end;
+ bool ret_val = Divide_Main(divide_pos, extra_lines, mut_multiplier);
+ // Re-adjust heads.
+ AdjustHeads();
+ return ret_val;
+}
+
+bool cHardwareCPU::Inst_HeadDivide()
+{
+ return Inst_HeadDivideMut(1);
+}
+
+bool cHardwareCPU::Inst_HeadDivideSex()
+{
+ organism->GetPhenotype().SetDivideSex(true);
+ organism->GetPhenotype().SetCrossNum(1);
+ return Inst_HeadDivide();
+}
+
+bool cHardwareCPU::Inst_HeadDivideAsex()
+{
+ organism->GetPhenotype().SetDivideSex(false);
+ organism->GetPhenotype().SetCrossNum(0);
+ return Inst_HeadDivide();
+}
+
+bool cHardwareCPU::Inst_HeadDivideAsexWait()
+{
+ organism->GetPhenotype().SetDivideSex(true);
+ organism->GetPhenotype().SetCrossNum(0);
+ return Inst_HeadDivide();
+}
+
+bool cHardwareCPU::Inst_HeadDivideMateSelect()
+{
+ // Take the label that follows this divide and use it as the ID for which
+ // other organisms this one is willing to mate with.
+ ReadLabel();
+ organism->GetPhenotype().SetMateSelectID( GetLabel().AsInt(NUM_NOPS) );
+
+// int mate_id = GetLabel().AsInt(NUM_NOPS);
+// if (mate_id > 0) cout << mate_id << " "
+// << GetLabel().AsString() << endl;
+
+ // Proceed as normal with the rest of mate selection.
+ organism->GetPhenotype().SetDivideSex(true);
+ organism->GetPhenotype().SetCrossNum(1);
+ return Inst_HeadDivide();
+}
+
+bool cHardwareCPU::Inst_HeadDivide1() { return Inst_HeadDivideMut(1); }
+bool cHardwareCPU::Inst_HeadDivide2() { return Inst_HeadDivideMut(2); }
+bool cHardwareCPU::Inst_HeadDivide3() { return Inst_HeadDivideMut(3); }
+bool cHardwareCPU::Inst_HeadDivide4() { return Inst_HeadDivideMut(4); }
+bool cHardwareCPU::Inst_HeadDivide5() { return Inst_HeadDivideMut(5); }
+bool cHardwareCPU::Inst_HeadDivide6() { return Inst_HeadDivideMut(6); }
+bool cHardwareCPU::Inst_HeadDivide7() { return Inst_HeadDivideMut(7); }
+bool cHardwareCPU::Inst_HeadDivide8() { return Inst_HeadDivideMut(8); }
+bool cHardwareCPU::Inst_HeadDivide9() { return Inst_HeadDivideMut(9); }
+bool cHardwareCPU::Inst_HeadDivide10() { return Inst_HeadDivideMut(10); }
+bool cHardwareCPU::Inst_HeadDivide16() { return Inst_HeadDivideMut(16); }
+bool cHardwareCPU::Inst_HeadDivide32() { return Inst_HeadDivideMut(32); }
+bool cHardwareCPU::Inst_HeadDivide50() { return Inst_HeadDivideMut(50); }
+bool cHardwareCPU::Inst_HeadDivide100() { return Inst_HeadDivideMut(100); }
+bool cHardwareCPU::Inst_HeadDivide500() { return Inst_HeadDivideMut(500); }
+bool cHardwareCPU::Inst_HeadDivide1000() { return Inst_HeadDivideMut(1000); }
+bool cHardwareCPU::Inst_HeadDivide5000() { return Inst_HeadDivideMut(5000); }
+bool cHardwareCPU::Inst_HeadDivide10000() { return Inst_HeadDivideMut(10000); }
+bool cHardwareCPU::Inst_HeadDivide50000() { return Inst_HeadDivideMut(50000); }
+bool cHardwareCPU::Inst_HeadDivide0_5() { return Inst_HeadDivideMut(0.5); }
+bool cHardwareCPU::Inst_HeadDivide0_1() { return Inst_HeadDivideMut(0.1); }
+bool cHardwareCPU::Inst_HeadDivide0_05() { return Inst_HeadDivideMut(0.05); }
+bool cHardwareCPU::Inst_HeadDivide0_01() { return Inst_HeadDivideMut(0.01); }
+bool cHardwareCPU::Inst_HeadDivide0_001() { return Inst_HeadDivideMut(0.001); }
+
+bool cHardwareCPU::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();
+ }
+ Register(REG_BX) = read_inst;
+ ReadInst(read_inst);
+
+ cpu_stats.mut_stats.copies_exec++; // @CAO, this too..
+ GetHead(head_id).Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_HeadWrite()
+{
+ const int head_id = FindModifiedHead(HEAD_WRITE);
+ cHeadCPU & active_head = GetHead(head_id);
+
+ active_head.Adjust();
+
+ int value = Register(REG_BX);
+ 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 cHardwareCPU::Inst_HeadCopy()
+{
+ // For the moment, this cannot be nop-modified.
+ cHeadCPU & read_head = GetHead(HEAD_READ);
+ cHeadCPU & 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();
+ ReadInst(read_inst.GetOp());
+ 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;
+ }
+
+ 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;
+}
+
+bool cHardwareCPU::HeadCopy_ErrorCorrect(double reduction)
+{
+ // For the moment, this cannot be nop-modified.
+ cHeadCPU & read_head = GetHead(HEAD_READ);
+ cHeadCPU & write_head = GetHead(HEAD_WRITE);
+ sCPUStats & cpu_stats = organism->CPUStats();
+
+ read_head.Adjust();
+ write_head.Adjust();
+
+ // Do mutations.
+ cInstruction read_inst = read_head.GetInst();
+ ReadInst(read_inst.GetOp());
+ if ( g_random.P(organism->GetCopyMutProb() / reduction) ) {
+ read_inst = GetRandomInst();
+ cpu_stats.mut_stats.copy_mut_count++;
+ write_head.FlagMutated() = true;
+ write_head.FlagCopyMut() = true;
+ //organism->GetPhenotype().IsMutated() = true;
+ }
+
+ cpu_stats.mut_stats.copies_exec++;
+
+ write_head.SetInst(read_inst);
+ write_head.FlagCopied() = true; // Set the copied flag...
+
+ read_head.Advance();
+ write_head.Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_HeadCopy2() { return HeadCopy_ErrorCorrect(2); }
+bool cHardwareCPU::Inst_HeadCopy3() { return HeadCopy_ErrorCorrect(3); }
+bool cHardwareCPU::Inst_HeadCopy4() { return HeadCopy_ErrorCorrect(4); }
+bool cHardwareCPU::Inst_HeadCopy5() { return HeadCopy_ErrorCorrect(5); }
+bool cHardwareCPU::Inst_HeadCopy6() { return HeadCopy_ErrorCorrect(6); }
+bool cHardwareCPU::Inst_HeadCopy7() { return HeadCopy_ErrorCorrect(7); }
+bool cHardwareCPU::Inst_HeadCopy8() { return HeadCopy_ErrorCorrect(8); }
+bool cHardwareCPU::Inst_HeadCopy9() { return HeadCopy_ErrorCorrect(9); }
+bool cHardwareCPU::Inst_HeadCopy10() { return HeadCopy_ErrorCorrect(10); }
+
+bool cHardwareCPU::Inst_HeadSearch()
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+ cHeadCPU found_pos = FindLabel(0);
+ const int search_size = found_pos.GetPosition() - IP().GetPosition();
+ Register(REG_BX) = search_size;
+ Register(REG_CX) = GetLabel().GetSize();
+ GetHead(HEAD_FLOW).Set(found_pos);
+ GetHead(HEAD_FLOW).Advance();
+ return true;
+}
+
+bool cHardwareCPU::Inst_SetFlow()
+{
+ const int reg_used = FindModifiedRegister(REG_CX);
+ GetHead(HEAD_FLOW).Set(Register(reg_used), this);
+ return true;
+}
+
+// Direct Matching Templates
+
+bool cHardwareCPU::Inst_DMJumpF()
+{
+ ReadLabel();
+
+ // If there is no label, jump BX steps.
+ if (GetLabel().GetSize() == 0) {
+ IP().Jump(Register(REG_BX));
+ return true;
+ }
+
+ // Otherwise, jump to the label.
+ cHeadCPU jump_location(FindLabel(1));
+ if (jump_location.GetPosition() != -1) {
+ IP().Set(jump_location);
+ return true;
+ }
+
+ // If complement label was not found; record an error.
+ organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
+ "dm-jump-f: no complement label");
+ return false;
+}
+
+
+//// Placebo insts ////
+bool cHardwareCPU::Inst_Skip()
+{
+ IP().Advance();
+ return true;
+}
+
+
Copied: trunk/source/cpu/cHardwareCPU.h (from rev 299, trunk/source/cpu/hardware_cpu.hh)
===================================================================
--- trunk/source/cpu/hardware_cpu.hh 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/cHardwareCPU.h 2005-08-29 19:51:42 UTC (rev 300)
@@ -0,0 +1,588 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2004 California Institute of Technology //
+// //
+// Read the COPYING and README files, or contact 'avida at alife.org', //
+// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_CPU_HH
+#define HARDWARE_CPU_HH
+
+#include <iomanip>
+#include <vector>
+
+#ifndef DEFS_HH
+#include "defs.hh"
+#endif
+#ifndef CODE_LABEL_HH
+#include "cCodeLabel.h"
+#endif
+#ifndef CPU_DEFS_HH
+#include "cpu_defs.hh"
+#endif
+#ifndef HEAD_CPU_HH
+#include "head_cpu.hh"
+#endif
+#ifndef CPU_MEMORY_HH
+#include "cCPUMemory.h"
+#endif
+#ifndef CPU_STACK_HH
+#include "cCPUStack.h"
+#endif
+#ifndef HARDWARE_BASE_HH
+#include "cHardwareBase.h"
+#endif
+#ifndef HARDWARE_CPU_THREAD_HH
+#include "cHardwareCPU_Thread.h"
+#endif
+#ifndef STRING_HH
+#include "string.hh"
+#endif
+#ifndef TARRAY_HH
+#include "tArray.hh"
+#endif
+
+class cInstSet;
+class cInstLibBase;
+class cOrganism;
+class cMutation;
+class cHardwareCPU_Thread;
+
+#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 cHardwareCPU structure which keeps track of the
+ * current status of all the components of the simulated hardware.
+ *
+ * @see cHardwareCPU_Thread, cCPUStack, cCPUMemory, cInstSet
+ **/
+
+class cCodeLabel; // access
+class cHeadCPU; // access
+class cCPUMemory; // aggregate
+class cCPUStack; // aggregate
+class cGenome;
+class cHardwareCPU_Thread; // access
+class cInstLibBase;
+class cInstLibCPU;
+class cInstruction;
+class cInstSet;
+class cMutation;
+class cOrganism;
+class cString; // aggregate
+template <class T> class tBuffer;
+template <class T> class tArray; // aggregate
+
+class cHardwareCPU : public cHardwareBase {
+public:
+ typedef bool (cHardwareCPU::*tHardwareCPUMethod)();
+private:
+ static cInstLibCPU *s_inst_slib;
+ static cInstLibCPU *initInstLib(void);
+ tHardwareCPUMethod *m_functions;
+private:
+ cCPUMemory memory; // Memory...
+ cCPUStack global_stack; // A stack that all threads share.
+ int thread_time_used;
+
+ tArray<cHardwareCPU_Thread> threads;
+ int thread_id_chart;
+ int cur_thread;
+
+ // Flags...
+ bool mal_active; // Has an allocate occured since last divide?
+ 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
+
+public:
+ cHardwareCPU(cOrganism * in_organism, cInstSet * in_inst_set);
+ explicit cHardwareCPU(const cHardwareCPU &);
+ ~cHardwareCPU();
+ void Recycle(cOrganism * new_organism, cInstSet * in_inst_set);
+ static cInstLibCPU *GetInstLib();
+ static cString GetDefaultInstFilename() { return "inst_lib.default"; }
+ 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... --------
+ inline void StackPush(int value);
+ inline int StackPop();
+ inline void StackFlip();
+ inline int GetStack(int depth=0, int stack_id=-1) const;
+ inline void StackClear();
+ inline void SwitchStack();
+ int GetActiveStackID() const { return threads[cur_thread].cur_stack; }
+
+
+ // -------- 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 cHeadCPU & GetHead(int head_id) const
+ { return threads[cur_thread].heads[head_id]; }
+ cHeadCPU & GetHead(int head_id) { return threads[cur_thread].heads[head_id];}
+
+ const cHeadCPU & GetActiveHead() const { return GetHead(GetCurHead()); }
+ cHeadCPU & GetActiveHead() { return GetHead(GetCurHead()); }
+
+ void AdjustHeads();
+
+ inline const cHeadCPU & IP() const
+ { return threads[cur_thread].heads[HEAD_IP]; }
+ inline cHeadCPU & IP() { return threads[cur_thread].heads[HEAD_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 --------
+ const 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 const cCPUMemory & Memory() const { return memory; }
+ inline cCPUMemory & Memory() { return memory; }
+
+ // -------- 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);
+
+ // -------- Tests --------
+
+ int TestParasite() const;
+
+ // -------- Accessors --------
+ const cCPUMemory & GetMemory() const { return memory; }
+ cCPUMemory & GetMemory() { return memory; }
+ const cCPUMemory & GetMemory(int value) const { return memory;}
+ cCPUMemory & GetMemory(int value) { return memory; }
+
+ 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...
+ cHeadCPU 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);
+ cHeadCPU FindLabel(const cCodeLabel & in_label, int direction);
+ cHeadCPU FindFullLabel(const cCodeLabel & in_label);
+
+ int GetType() const { return HARDWARE_TYPE_CPU_ORIGINAL; }
+ bool InjectHost(const cCodeLabel & in_label, const cGenome & injection);
+ int InjectThread(const cCodeLabel & in_label, const cGenome & injection);
+ void InjectCode(const cGenome & injection, const int line_num);
+ void InjectCodeThread(const cGenome & injection, const int line_num);
+ void Mutate(const int mut_point);
+ int PointMutate(const double mut_rate);
+
+ bool TriggerMutations(int trigger);
+ bool TriggerMutations(int trigger, cHeadCPU & cur_head);
+ bool TriggerMutations_ScopeGenome(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadCPU & cur_head, const double rate);
+ bool TriggerMutations_ScopeLocal(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadCPU & cur_head, const double rate);
+ int TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
+ cCPUMemory & target_memory, cHeadCPU & cur_head, const double rate);
+ void TriggerMutations_Body(int type, cCPUMemory & target_memory,
+ cHeadCPU & 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);
+
+
+private:
+
+ /////////---------- Instruction Helpers ------------//////////
+
+ int FindModifiedRegister(int default_register);
+ int FindModifiedHead(int default_head);
+ int FindComplementRegister(int base_reg);
+
+ 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 divide_point, const int extra_lines=0, double mut_multiplier=1);
+
+ bool Divide_CheckViable(const int child_size, const int parent_size);
+ void Divide_DoMutations(double mut_multiplier=1);
+ void Divide_TestFitnessMeasures();
+
+ bool HeadCopy_ErrorCorrect(double reduction);
+ bool Inst_HeadDivideMut(double mut_multiplier=1);
+
+public:
+ /////////---------- Instruction Library ------------//////////
+
+ // Flow Control
+ bool Inst_If0();
+ bool Inst_IfEqu();
+ bool Inst_IfNot0();
+ bool Inst_IfNEqu();
+ bool Inst_IfGr0();
+ bool Inst_IfGr();
+ bool Inst_IfGrEqu0();
+ bool Inst_IfGrEqu();
+ bool Inst_IfLess0();
+ bool Inst_IfLess();
+ bool Inst_IfLsEqu0();
+ bool Inst_IfLsEqu();
+ bool Inst_IfBit1();
+ bool Inst_IfANotEqB();
+ bool Inst_IfBNotEqC();
+ bool Inst_IfANotEqC();
+
+ bool Inst_JumpF();
+ bool Inst_JumpB();
+ bool Inst_JumpP();
+ bool Inst_JumpSelf();
+ bool Inst_Call();
+ bool Inst_Return();
+
+ // Stack and Register Operations
+ bool Inst_Pop();
+ bool Inst_Push();
+ bool Inst_HeadPop();
+ bool Inst_HeadPush();
+
+ bool Inst_PopA();
+ bool Inst_PopB();
+ bool Inst_PopC();
+ bool Inst_PushA();
+ bool Inst_PushB();
+ bool Inst_PushC();
+
+ bool Inst_SwitchStack();
+ bool Inst_FlipStack();
+ bool Inst_Swap();
+ bool Inst_SwapAB();
+ bool Inst_SwapBC();
+ bool Inst_SwapAC();
+ bool Inst_CopyReg();
+ bool Inst_CopyRegAB();
+ bool Inst_CopyRegAC();
+ bool Inst_CopyRegBA();
+ bool Inst_CopyRegBC();
+ bool Inst_CopyRegCA();
+ bool Inst_CopyRegCB();
+ bool Inst_Reset();
+
+ // Single-Argument Math
+ bool Inst_ShiftR();
+ bool Inst_ShiftL();
+ bool Inst_Bit1();
+ bool Inst_SetNum();
+ bool Inst_ValGrey();
+ bool Inst_ValDir();
+ bool Inst_ValAddP();
+ bool Inst_ValFib();
+ bool Inst_ValPolyC();
+ bool Inst_Inc();
+ bool Inst_Dec();
+ bool Inst_Zero();
+ bool Inst_Not();
+ bool Inst_Neg();
+ bool Inst_Square();
+ bool Inst_Sqrt();
+ bool Inst_Log();
+ bool Inst_Log10();
+ bool Inst_Minus17();
+
+ // Double Argument Math
+ bool Inst_Add();
+ bool Inst_Sub();
+ bool Inst_Mult();
+ bool Inst_Div();
+ bool Inst_Mod();
+ bool Inst_Nand();
+ bool Inst_Nor();
+ bool Inst_And();
+ bool Inst_Order();
+ bool Inst_Xor();
+
+ // Biological
+ bool Inst_Copy();
+ bool Inst_ReadInst();
+ bool Inst_WriteInst();
+ bool Inst_StackReadInst();
+ bool Inst_StackWriteInst();
+ bool Inst_Compare();
+ bool Inst_IfNCpy();
+ bool Inst_Allocate();
+ bool Inst_Divide();
+ bool Inst_CAlloc();
+ bool Inst_CDivide();
+ bool Inst_MaxAlloc();
+ bool Inst_Inject();
+ bool Inst_InjectRand();
+ bool Inst_InjectThread();
+ bool Inst_Repro();
+ bool Inst_Kazi();
+ bool Inst_Die();
+
+ // I/O and Sensory
+ bool Inst_TaskGet();
+ bool Inst_TaskStackGet();
+ bool Inst_TaskStackLoad();
+ bool Inst_TaskPut();
+ bool Inst_TaskIO();
+ bool Inst_Send();
+ bool Inst_Receive();
+ bool Inst_Sense();
+
+ void DoDonate(cOrganism * to_org);
+ bool Inst_DonateRandom();
+ bool Inst_DonateKin();
+ bool Inst_DonateEditDist();
+ bool Inst_DonateNULL();
+
+ bool Inst_SearchF();
+ bool Inst_SearchB();
+ bool Inst_MemSize();
+
+ // Environment
+
+ bool Inst_RotateL();
+ bool Inst_RotateR();
+ bool Inst_SetCopyMut();
+ bool Inst_ModCopyMut();
+
+ // Multi-threading...
+
+ bool Inst_ForkThread();
+ bool Inst_KillThread();
+ bool Inst_ThreadID();
+
+ // Head-based instructions...
+
+ bool Inst_SetHead();
+ bool Inst_AdvanceHead();
+ bool Inst_MoveHead();
+ bool Inst_JumpHead();
+ bool Inst_GetHead();
+ bool Inst_IfLabel();
+ bool Inst_IfLabel2();
+ bool Inst_HeadDivide();
+ bool Inst_HeadRead();
+ bool Inst_HeadWrite();
+ bool Inst_HeadCopy();
+ bool Inst_HeadSearch();
+ bool Inst_SetFlow();
+
+ bool Inst_HeadCopy2();
+ bool Inst_HeadCopy3();
+ bool Inst_HeadCopy4();
+ bool Inst_HeadCopy5();
+ bool Inst_HeadCopy6();
+ bool Inst_HeadCopy7();
+ bool Inst_HeadCopy8();
+ bool Inst_HeadCopy9();
+ bool Inst_HeadCopy10();
+
+ bool Inst_HeadDivideSex();
+ bool Inst_HeadDivideAsex();
+ bool Inst_HeadDivideAsexWait();
+ bool Inst_HeadDivideMateSelect();
+
+ bool Inst_HeadDivide1();
+ bool Inst_HeadDivide2();
+ bool Inst_HeadDivide3();
+ bool Inst_HeadDivide4();
+ bool Inst_HeadDivide5();
+ bool Inst_HeadDivide6();
+ bool Inst_HeadDivide7();
+ bool Inst_HeadDivide8();
+ bool Inst_HeadDivide9();
+ bool Inst_HeadDivide10();
+ bool Inst_HeadDivide16();
+ bool Inst_HeadDivide32();
+ bool Inst_HeadDivide50();
+ bool Inst_HeadDivide100();
+ bool Inst_HeadDivide500();
+ bool Inst_HeadDivide1000();
+ bool Inst_HeadDivide5000();
+ bool Inst_HeadDivide10000();
+ bool Inst_HeadDivide50000();
+ bool Inst_HeadDivide0_5();
+ bool Inst_HeadDivide0_1();
+ bool Inst_HeadDivide0_05();
+ bool Inst_HeadDivide0_01();
+ bool Inst_HeadDivide0_001();
+
+
+ // Direct Matching Templates
+
+ bool Inst_DMJumpF();
+ //bool Inst_DMJumpB();
+ //bool Inst_DMCall();
+ //bool Inst_DMSearchF();
+ //bool Inst_DMSearchB();
+
+ // Relative Addressed Jumps
+
+ //bool Inst_REJumpF();
+ //bool Inst_REJumpB();
+
+ // Absoulte Addressed Jumps
+
+ //bool Inst_ABSJump();
+
+ // Biologically inspired reproduction
+ //bool Inst_BCAlloc();
+ //bool Inst_BCopy();
+ //bool Inst_BDivide();
+private:
+ bool Inst_BCopy_Main(double mut_prob); // Internal called by all BCopy's
+public:
+ // Bio Error Correction
+ //bool Inst_BCopyDiv2();
+ //bool Inst_BCopyDiv3();
+ //bool Inst_BCopyDiv4();
+ //bool Inst_BCopyDiv5();
+ //bool Inst_BCopyDiv6();
+ //bool Inst_BCopyDiv7();
+ //bool Inst_BCopyDiv8();
+ //bool Inst_BCopyDiv9();
+ //bool Inst_BCopyDiv10();
+ //bool Inst_BCopyPow2();
+ //bool Inst_BIfNotCopy();
+ //bool Inst_BIfCopy();
+
+
+ //// Placebo ////
+ bool Inst_Skip();
+};
+
+
+//////////////////
+// cHardwareCPU
+//////////////////
+
+inline void cHardwareCPU::NextThread()
+{
+ cur_thread++;
+ if (cur_thread >= GetNumThreads()) cur_thread = 0;
+}
+
+inline void cHardwareCPU::PrevThread()
+{
+ if (cur_thread == 0) cur_thread = GetNumThreads() - 1;
+ else cur_thread--;
+}
+
+inline void cHardwareCPU::SetThread(int value)
+{
+ if (value>=0 && value < GetNumThreads())
+ cur_thread=value;
+}
+
+inline void cHardwareCPU::StackPush(int value)
+{
+ if (threads[cur_thread].cur_stack == 0) {
+ threads[cur_thread].stack.Push(value);
+ } else {
+ global_stack.Push(value);
+ }
+}
+
+inline int cHardwareCPU::StackPop()
+{
+ int pop_value;
+
+ if (threads[cur_thread].cur_stack == 0) {
+ pop_value = threads[cur_thread].stack.Pop();
+ } else {
+ pop_value = global_stack.Pop();
+ }
+
+ return pop_value;
+}
+
+inline void cHardwareCPU::StackFlip()
+{
+ if (threads[cur_thread].cur_stack == 0) {
+ threads[cur_thread].stack.Flip();
+ } else {
+ global_stack.Flip();
+ }
+}
+
+inline int cHardwareCPU::GetStack(int depth, int stack_id) const
+{
+ int value = 0;
+
+ if (stack_id == -1) stack_id = threads[cur_thread].cur_stack;
+
+ if (stack_id == 0) value = threads[cur_thread].stack.Get(depth);
+ else if (stack_id == 1) value = global_stack.Get(depth);
+
+ return value;
+}
+
+inline void cHardwareCPU::StackClear()
+{
+ if (threads[cur_thread].cur_stack == 0) {
+ threads[cur_thread].stack.Clear();
+ } else {
+ global_stack.Clear();
+ }
+}
+
+inline void cHardwareCPU::SwitchStack()
+{
+ threads[cur_thread].cur_stack++;
+ if (threads[cur_thread].cur_stack > 1) threads[cur_thread].cur_stack = 0;
+}
+
+#endif
Copied: trunk/source/cpu/cHardwareCPU_Thread.cc (from rev 298, trunk/source/cpu/hardware_cpu_thread.cc)
===================================================================
--- trunk/source/cpu/hardware_cpu_thread.cc 2005-08-29 18:54:25 UTC (rev 298)
+++ trunk/source/cpu/cHardwareCPU_Thread.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -0,0 +1,126 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology //
+// //
+// Read the COPYING and README files, or contact 'avida at alife.org', //
+// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef HARDWARE_CPU_THREAD_HH
+#include "cHardwareCPU_Thread.h"
+#endif
+
+using namespace std;
+
+/////////////////////////
+// cHardwareCPU_Thread
+/////////////////////////
+
+cHardwareCPU_Thread::cHardwareCPU_Thread(cHardwareBase * in_hardware, int _id)
+{
+ Reset(in_hardware, _id);
+}
+
+cHardwareCPU_Thread::cHardwareCPU_Thread(const cHardwareCPU_Thread & in_thread, int _id)
+{
+ id = _id;
+ if (id == -1) id = in_thread.id;
+ for (int i = 0; i < NUM_REGISTERS; i++) {
+ reg[i] = in_thread.reg[i];
+ }
+ for (int i = 0; i < NUM_HEADS; i++) {
+ heads[i] = in_thread.heads[i];
+ }
+ stack = in_thread.stack;
+}
+
+cHardwareCPU_Thread::~cHardwareCPU_Thread() {}
+
+void cHardwareCPU_Thread::operator=(const cHardwareCPU_Thread & in_thread)
+{
+ id = in_thread.id;
+ for (int i = 0; i < NUM_REGISTERS; i++) {
+ reg[i] = in_thread.reg[i];
+ }
+ for (int i = 0; i < NUM_HEADS; i++) {
+ heads[i] = in_thread.heads[i];
+ }
+ stack = in_thread.stack;
+}
+
+void cHardwareCPU_Thread::Reset(cHardwareBase * in_hardware, int _id)
+{
+ id = _id;
+
+ for (int i = 0; i < NUM_REGISTERS; i++) reg[i] = 0;
+ for (int i = 0; i < NUM_HEADS; i++) heads[i].Reset(in_hardware);
+
+ stack.Clear();
+ cur_stack = 0;
+ cur_head = HEAD_IP;
+ read_label.Clear();
+ next_label.Clear();
+}
+
+
+
+
+void cHardwareCPU_Thread::SaveState(ostream & fp){
+ assert(fp.good());
+ fp << "cHardwareCPU_Thread" << endl;
+
+ // registers
+ for( int i=0; i<NUM_REGISTERS; ++i ){
+ fp<<reg[i]<<endl;
+ }
+
+ // heads (@TCC does not handle parasites!!!)
+ for( int i=0; i<NUM_HEADS; ++i ){
+ fp<<heads[i].GetPosition()<<endl;
+ }
+
+ stack.SaveState(fp);
+
+ fp<<"|"; // marker
+ fp<<cur_stack;
+ fp<<cur_head;
+ fp<<endl;
+
+ // Code labels
+ read_label.SaveState(fp);
+ next_label.SaveState(fp);
+}
+
+
+
+void cHardwareCPU_Thread::LoadState(istream & fp){
+ assert(fp.good());
+ cString foo;
+ fp >> foo;
+ assert( foo == "cHardwareCPU_Thread");
+
+ // registers
+ for( int i=0; i<NUM_REGISTERS; ++i ){
+ fp>>reg[i];
+ }
+
+ // heads (@TCC does not handle parasites!!!)
+ for( int i=0; i<NUM_HEADS; ++i ){
+ int pos;
+ fp>>pos;
+ heads[i].AbsSet(pos);
+ }
+
+ // stack
+ stack.LoadState(fp);
+
+ char marker; fp>>marker; assert( marker == '|' );
+ /* YIKES! data loss below: */
+ char the_cur_stack = cur_stack;
+ char the_cur_head = cur_head;
+ fp.get(the_cur_stack);
+ fp.get(the_cur_head);
+
+ // Code labels
+ read_label.LoadState(fp);
+ next_label.LoadState(fp);
+}
Copied: trunk/source/cpu/cHardwareCPU_Thread.h (from rev 299, trunk/source/cpu/hardware_cpu_thread.hh)
Copied: trunk/source/cpu/cHardwareFactory.cc (from rev 298, trunk/source/cpu/hardware_factory.cc)
===================================================================
--- trunk/source/cpu/hardware_factory.cc 2005-08-29 18:54:25 UTC (rev 298)
+++ trunk/source/cpu/cHardwareFactory.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -0,0 +1,82 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1993 - 2003 California Institute of Technology //
+// //
+// Read the COPYING and README files, or contact 'avida at alife.org', //
+// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
+//////////////////////////////////////////////////////////////////////////////
+
+#include "cHardwareFactory.h"
+
+#include "cHardwareBase.h"
+#include "cHardwareCPU.h"
+#include "cHardware4Stack.h"
+#include "hardware_smt.h"
+#include "inst_set.hh"
+#include "organism.hh"
+
+using namespace std;
+
+// Static private variables...
+tList<cHardwareBase> cHardwareFactory::hardware_cpu_list;
+int cHardwareFactory::new_count(0);
+int cHardwareFactory::recycle_count(0);
+
+cHardwareBase * cHardwareFactory::Create(cOrganism * in_org,
+ cInstSet * inst_set, int type)
+{
+ assert(in_org != NULL);
+ assert(inst_set != NULL && inst_set->OK());
+
+ cHardwareBase * new_hardware = NULL;
+
+ // If there is nothing to recycle, just create a new one.
+ if (hardware_cpu_list.GetSize() == 0)
+ {
+ new_count++;
+ switch (type)
+ {
+ case HARDWARE_TYPE_CPU_ORIGINAL:
+ new_hardware = new cHardwareCPU(in_org, inst_set);
+ break;
+ case HARDWARE_TYPE_CPU_4STACK:
+ new_hardware = new cHardware4Stack(in_org, inst_set);
+ break;
+ case HARDWARE_TYPE_CPU_SMT:
+ new_hardware = new cHardwareSMT(in_org, inst_set);
+ }
+ }
+
+ // If we do have hardware to recycle, do so!
+ else {
+ new_hardware = hardware_cpu_list.PopRear();
+ new_hardware->Recycle(in_org, inst_set);
+ recycle_count++;
+ }
+
+ return new_hardware;
+}
+
+// Recycled hardware may be *briefly* in use, so don't delete immediately.
+void cHardwareFactory::Recycle(cHardwareBase * out_hardware)
+{
+ hardware_cpu_list.Push(out_hardware);
+}
+
+// Delete any hardware that needs it, save the rest for re-use.
+void cHardwareFactory::Update()
+{
+ int delete_count = 0;
+ while (hardware_cpu_list.GetSize() > 100) {
+ delete hardware_cpu_list.Pop();
+ delete_count++;
+ }
+
+// cerr << " NewHardware: " << new_count
+// << " Recycled: " << recycle_count
+// << " Deleted: " << delete_count
+// << " Stored: " << hardware_cpu_list.GetSize()
+// << " Existing: " << cHardwareBase::GetInstanceCount()
+// << endl;
+
+ new_count = recycle_count = 0;
+}
Copied: trunk/source/cpu/cHardwareFactory.h (from rev 298, trunk/source/cpu/hardware_factory.hh)
Modified: trunk/source/cpu/cpu.pri
===================================================================
--- trunk/source/cpu/cpu.pri 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/cpu.pri 2005-08-29 19:51:42 UTC (rev 300)
@@ -6,10 +6,10 @@
$$CPU_HH/cCPUMemory.h \
$$CPU_HH/cCPUStack.h \
$$CPU_HH/sCPUStats.h \
- $$CPU_HH/hardware_4stack.hh \
- $$CPU_HH/hardware_base.hh \
- $$CPU_HH/hardware_cpu.hh \
- $$CPU_HH/hardware_factory.hh \
+ $$CPU_HH/cHardware4Stack.h \
+ $$CPU_HH/cHardwareBase.h \
+ $$CPU_HH/cHardwareCPU.h \
+ $$CPU_HH/cHardwareFactory.h \
$$CPU_HH/hardware_util.hh \
$$CPU_HH/test_cpu.hh \
$$CPU_HH/test_util.hh
@@ -21,12 +21,12 @@
$$CPU_CC/cCPUMemory.cc \
$$CPU_CC/cCPUStack.cc \
$$CPU_CC/cCPUTestInfo.cc \
- $$CPU_CC/hardware_4stack.cc \
- $$CPU_CC/hardware_4stack_thread.cc \
- $$CPU_CC/hardware_base.cc \
- $$CPU_CC/hardware_cpu.cc \
- $$CPU_CC/hardware_cpu_thread.cc \
- $$CPU_CC/hardware_factory.cc \
+ $$CPU_CC/cHardware4Stack.cc \
+ $$CPU_CC/cHardware4Stack_Thread.cc \
+ $$CPU_CC/cHardwareBase.cc \
+ $$CPU_CC/cHardwareCPU.cc \
+ $$CPU_CC/cHardwareCPU_Thread.cc \
+ $$CPU_CC/cHardwareFactory.cc \
$$CPU_CC/hardware_util.cc \
$$CPU_CC/memory_flags.cc \
$$CPU_CC/test_cpu.cc \
Deleted: trunk/source/cpu/hardware_4stack.cc
===================================================================
--- trunk/source/cpu/hardware_4stack.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_4stack.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,2306 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2003 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-
-
-#include "hardware_4stack.hh"
-
-#include "config.hh"
-#include "cCPUTestInfo.h"
-#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;
-
-
-
-
-///////////////
-// cInstLib4Stack
-///////////////
-
-class cInstLib4Stack : 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;
- cHardware4Stack::tHardware4StackMethod *m_functions;
- static const cInstruction inst_error;
- static const cInstruction inst_default;
-public:
- cInstLib4Stack(
- size_t nopmod_array_size,
- size_t function_array_size,
- cString *nopmod_names,
- cString *function_names,
- const int *nopmods,
- cHardware4Stack::tHardware4StackMethod *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)
- {}
- cHardware4Stack::tHardware4StackMethod *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 cInstLib4Stack::GetInstError();
- }
- const cInstruction & GetInstDefault(){ return inst_default; }
- const cInstruction & GetInstError(){ return inst_error; }
-};
-
-///////////////
-// cHardware4Stack
-///////////////
-
-const cInstruction cInstLib4Stack::inst_error(255);
-const cInstruction cInstLib4Stack::inst_default(0);
-cInstLibBase *cHardware4Stack::GetInstLib(){ return s_inst_slib; }
-
-cInstLib4Stack *cHardware4Stack::s_inst_slib = cHardware4Stack::initInstLib();
-cInstLib4Stack *cHardware4Stack::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", &cHardware4Stack::Inst_Nop),
- //2
- cInstEntry4Stack("Nop-B", &cHardware4Stack::Inst_Nop),
- //3
- cInstEntry4Stack("Nop-C", &cHardware4Stack::Inst_Nop),
- //4
- cInstEntry4Stack("Nop-D", &cHardware4Stack::Inst_Nop),
- //38
- cInstEntry4Stack("Nop-E", &cHardware4Stack::Inst_Nop),
- //39
- cInstEntry4Stack("Nop-F", &cHardware4Stack::Inst_Nop),
- //5
- cInstEntry4Stack("Nop-X", &cHardware4Stack::Inst_Nop),
- //6
- cInstEntry4Stack("Val-Shift-R", &cHardware4Stack::Inst_ShiftR),
- //7
- cInstEntry4Stack("Val-Shift-L", &cHardware4Stack::Inst_ShiftL),
- //8
- cInstEntry4Stack("Val-Nand", &cHardware4Stack::Inst_Val_Nand),
- //9
- cInstEntry4Stack("Val-Add", &cHardware4Stack::Inst_Val_Add),
- //10
- cInstEntry4Stack("Val-Sub", &cHardware4Stack::Inst_Val_Sub),
- //11
- cInstEntry4Stack("Val-Mult", &cHardware4Stack::Inst_Val_Mult),
- //12
- cInstEntry4Stack("Val-Div", &cHardware4Stack::Inst_Val_Div),
- //13
- cInstEntry4Stack("SetMemory", &cHardware4Stack::Inst_SetMemory),
- //14
- cInstEntry4Stack("Divide", &cHardware4Stack::Inst_Divide),
- //15
- cInstEntry4Stack("Inst-Read", &cHardware4Stack::Inst_HeadRead),
- //16
- cInstEntry4Stack("Inst-Write", &cHardware4Stack::Inst_HeadWrite),
- //keeping this one for the transition period
- //cInstEntry4Stack("Inst-Copy", &cHardware4Stack::Inst_HeadCopy),
- //17
- cInstEntry4Stack("If-Equal", &cHardware4Stack::Inst_IfEqual),
- //18
- cInstEntry4Stack("If-Not-Equal", &cHardware4Stack::Inst_IfNotEqual),
- //19
- cInstEntry4Stack("If-Less", &cHardware4Stack::Inst_IfLess),
- //20
- cInstEntry4Stack("If-Greater", &cHardware4Stack::Inst_IfGreater),
- //21
- cInstEntry4Stack("Head-Push", &cHardware4Stack::Inst_HeadPush),
- //22
- cInstEntry4Stack("Head-Pop", &cHardware4Stack::Inst_HeadPop),
- //23
- cInstEntry4Stack("Head-Move", &cHardware4Stack::Inst_HeadMove),
- //24
- cInstEntry4Stack("Search", &cHardware4Stack::Inst_Search),
- //25
- cInstEntry4Stack("Push-Next", &cHardware4Stack::Inst_PushNext),
- //26
- cInstEntry4Stack("Push-Prev", &cHardware4Stack::Inst_PushPrevious),
- //27
- cInstEntry4Stack("Push-Comp", &cHardware4Stack::Inst_PushComplement),
- //28
- cInstEntry4Stack("Val-Delete", &cHardware4Stack::Inst_ValDelete),
- //29
- cInstEntry4Stack("Val-Copy", &cHardware4Stack::Inst_ValCopy),
- //30
- cInstEntry4Stack("ThreadFork", &cHardware4Stack::Inst_ForkThread),
- //31
- //cInstEntry4Stack("if-label", &cHardware4Stack::Inst_IfLabel),
- //32
- cInstEntry4Stack("Val-Inc", &cHardware4Stack::Inst_Increment),
- //33
- cInstEntry4Stack("Val-Dec", &cHardware4Stack::Inst_Decrement),
- //34
- cInstEntry4Stack("Val-Mod", &cHardware4Stack::Inst_Mod),
- //35
- cInstEntry4Stack("ThreadKill", &cHardware4Stack::Inst_KillThread),
- //36
- cInstEntry4Stack("IO", &cHardware4Stack::Inst_IO),
- //37
- cInstEntry4Stack("Inject", &cHardware4Stack::Inst_Inject)
- };
-
- const int n_size = sizeof(s_n_array)/sizeof(cNOPEntry4Stack);
-
- 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;
- }
-
- cInstLib4Stack *inst_lib = new cInstLib4Stack(
- n_size,
- f_size,
- n_names,
- f_names,
- nop_mods,
- functions
- );
-
- return inst_lib;
-}
-
-cHardware4Stack::cHardware4Stack(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...
-}
-
-
-cHardware4Stack::cHardware4Stack(const cHardware4Stack &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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::LoadGenome(const cGenome & new_genome)
-{
- GetMemory(0) = new_genome;
-}
-
-
-bool cHardware4Stack::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 cHardware4Stack::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: cHardware4Stack::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.
-//
-/////////////////////////////////////////////////////////////////////////
-
-cHeadMultiMem cHardware4Stack::FindLabel(int direction)
-{
- cHeadMultiMem & inst_ptr = IP();
-
- // Start up a search head at the position of the instruction pointer.
- cHeadMultiMem 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 cHardware4Stack::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 cHardware4Stack::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.
-cHeadMultiMem cHardware4Stack::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!!!
-
- cHeadMultiMem 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.
-cHeadMultiMem cHardware4Stack::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!
-
- cHeadMultiMem 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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::TriggerMutations(int trigger, cHeadMultiMem & 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 cHardware4Stack::TriggerMutations_ScopeGenome(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadMultiMem & 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.
- cHeadMultiMem 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 cHardware4Stack::TriggerMutations_ScopeLocal(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadMultiMem & 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 cHardware4Stack::TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadMultiMem & 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++) {
- cHeadMultiMem 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 cHardware4Stack::TriggerMutations_Body(int type, cCPUMemory & target_memory,
- cHeadMultiMem & 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 cHardware4Stack::ReadInst(const int in_inst)
-{
- if (inst_set->IsNop( cInstruction(in_inst) )) {
- GetReadLabel().AddNop(in_inst);
- } else {
- GetReadLabel().Clear();
- }
-}
-
-
-void cHardware4Stack::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 cHardware4Stack::ReadLabel(int max_size)
-{
- int count = 0;
- cHeadMultiMem * 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 cHardware4Stack::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 cHardware4Stack::TestParasite() const
-{
- return IP().TestParasite();
-}
-
-
-bool cHardware4Stack::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 cHardware4Stack::SaveState(ostream & fp)
-{
- // note, memory & child_memory handled by cpu (@CAO Not any more!)
- assert(fp.good());
-
- fp<<"cHardware4Stack"<<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 cHardware4Stack::LoadState(istream & fp)
-{
- // note, memory & child_memory handled by cpu (@CAO Not any more!)
- assert(fp.good());
-
- cString foo;
- fp>>foo;
- assert( foo == "cHardware4Stack" );
-
- // 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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::FindComplementStack(int base_stack)
-{
- const int comp_stack = base_stack + 2;
- return comp_stack%NUM_STACKS;
-}
-
-inline void cHardware4Stack::Fault(int fault_loc, int fault_type, cString fault_desc)
-{
- organism->Fault(fault_loc, fault_type, fault_desc);
-}
-
-bool cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::ConvertToInstruction(int mem_space_used)
-{
- char c = mem_space_used + 97; // 97 - ASCII for 'a'
- cString ret;
- ret += c;
- return ret;
-}
-
-cString cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_Divide()
-{
- int mem_space_used = GetHead(HEAD_WRITE).GetMemSpace();
- int mut_multiplier = 1;
-
- return Divide_Main(mem_space_used, mut_multiplier);
-}
-
-bool cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_HeadWrite()
-{
- const int head_id = FindModifiedHead(HEAD_WRITE);
- cHeadMultiMem & 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 cHardware4Stack::Inst_HeadCopy()
-{
- // For the moment, this cannot be nop-modified.
- cHeadMultiMem & read_head = GetHead(HEAD_READ);
- cHeadMultiMem & 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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_Search()
-{
- ReadLabel();
- GetLabel().Rotate(2, NUM_NOPS_4STACK);
- cHeadMultiMem 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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_PushComplement()
-{
- int stack_used = FindModifiedStack(STACK_BX);
- int complement = FindComplementStack(stack_used);
- Stack(complement).Push(Stack(stack_used).Pop());
- return true;
-}
-
-//28
-bool cHardware4Stack::Inst_ValDelete()
-{
- int stack_used = FindModifiedStack(STACK_BX);
- Stack(stack_used).Pop();
- return true;
-}
-
-//29
-bool cHardware4Stack::Inst_ValCopy()
-{
- const int stack_used = FindModifiedStack(STACK_BX);
- Stack(stack_used).Push(Stack(stack_used).Top());
- return true;
-}
-
-//30
-bool cHardware4Stack::Inst_ForkThread()
-{
- if (!ForkThread())
- Fault(FAULT_LOC_THREAD_FORK, FAULT_TYPE_FORK_TH);
- else
- IP().Advance();
- return true;
-}
-
-//31
-bool cHardware4Stack::Inst_IfLabel()
-{
- ReadLabel();
- GetLabel().Rotate(2, NUM_NOPS_4STACK);
- if (GetLabel() != GetReadLabel()) IP().Advance();
- return true;
-}
-
-//32
-bool cHardware4Stack::Inst_Increment()
-{
- const int stack_used = FindModifiedStack(STACK_BX);
- int value = Stack(stack_used).Pop();
- Stack(stack_used).Push(++value);
- return true;
-}
-
-//33
-bool cHardware4Stack::Inst_Decrement()
-{
- const int stack_used = FindModifiedStack(STACK_BX);
- int value = Stack(stack_used).Pop();
- Stack(stack_used).Push(--value);
- return true;
-}
-
-//34
-bool cHardware4Stack::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 cHardware4Stack::Inst_KillThread()
-{
- if (!KillThread()) Fault(FAULT_LOC_THREAD_KILL, FAULT_TYPE_KILL_TH);
- else AdvanceIP() = false;
- return true;
-}
-
-//36
-bool cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::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 cHardware4Stack::Inst_Inject()
-{
- double mut_multiplier = 1;
-
- return InjectParasite(mut_multiplier);
-}
-
-
-
-/*
-bool cHardware4Stack::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;
-}
-
-*/
Deleted: trunk/source/cpu/hardware_4stack.hh
===================================================================
--- trunk/source/cpu/hardware_4stack.hh 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_4stack.hh 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,515 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2003 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef HARDWARE_4STACK_HH
-#define HARDWARE_4STACK_HH
-
-#include <iomanip>
-
-#ifndef CPU_MEMORY_HH
-#include "cCPUMemory.h"
-#endif
-#ifndef CPU_STACK_HH
-#include "cCPUStack.h"
-#endif
-#ifndef DEFS_HH
-#include "defs.hh"
-#endif
-#ifndef HEAD_MULTI_MEM_HH
-#include "head_multi_mem.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 cHardware4Stack structure which keeps track of the
- * current status of all the components of the simulated hardware.
- *
- * @see cHardware4Stack_Thread, cCPUStack, cCPUMemory, cInstSet
- **/
-
-class cCodeLabel;
-class cCPUMemory;
-class cCPUStack; // aggregate
-class cHeadMultiMem; // access
-class cGenome;
-class cHardware4Stack_Thread; // access
-class cInjectGenotype;
-class cInstLib4Stack; // access
-class cInstruction;
-class cInstSet;
-class cOrganism;
-class cString; // aggregate
-template <class T> class tArray; // aggregate
-
-class cHardware4Stack : public cHardwareBase {
-public:
- typedef bool (cHardware4Stack::*tHardware4StackMethod)();
-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<cHardware4Stack_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:
- cHardware4Stack(cOrganism * in_organism, cInstSet * in_inst_set);
- explicit cHardware4Stack(const cHardware4Stack &);
- ~cHardware4Stack() { ; }
- 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 cHeadMultiMem & GetHead(int head_id) const
- { return threads[cur_thread].heads[head_id]; }
- cHeadMultiMem & GetHead(int head_id)
- { return threads[cur_thread].heads[head_id];}
-
- const cHeadMultiMem & GetHead(int head_id, int thread) const
- { return threads[thread].heads[head_id]; }
- cHeadMultiMem & GetHead(int head_id, int thread)
- { return threads[thread].heads[head_id];}
-
- const cHeadMultiMem & GetActiveHead() const { return GetHead(GetCurHead()); }
- cHeadMultiMem & GetActiveHead() { return GetHead(GetCurHead()); }
-
- void AdjustHeads();
-
- inline const cHeadMultiMem & IP() const
- { return threads[cur_thread].heads[HEAD_IP]; }
- inline cHeadMultiMem & IP() { return threads[cur_thread].heads[HEAD_IP]; }
-
- inline const cHeadMultiMem & IP(int thread) const
- { return threads[thread].heads[HEAD_IP]; }
- inline cHeadMultiMem & 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...
- cHeadMultiMem 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);
- cHeadMultiMem FindLabel(const cCodeLabel & in_label, int direction);
- cHeadMultiMem 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, cHeadMultiMem & cur_head);
- bool TriggerMutations_ScopeGenome(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadMultiMem & cur_head, const double rate);
- bool TriggerMutations_ScopeLocal(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadMultiMem & cur_head, const double rate);
- int TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadMultiMem & cur_head, const double rate);
- void TriggerMutations_Body(int type, cCPUMemory & target_memory,
- cHeadMultiMem & 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();
- */
-
-};
-
-
-//////////////////
-// cHardware4Stack
-//////////////////
-
-//Not used, but here to satisfy the requirements of HardwareBase
-inline const cCPUMemory & cHardware4Stack::GetMemory() const
-{
- return memory_array[0];
-}
-
-//Not used, but here to satisfy the requirements of HardwareBase
-inline cCPUMemory & cHardware4Stack::GetMemory()
-{
- return memory_array[0];
-}
-
-inline const cCPUMemory & cHardware4Stack::GetMemory(int mem_space) const
-{
- if(mem_space >= NUM_MEMORY_SPACES)
- mem_space %= NUM_MEMORY_SPACES;
- return memory_array[mem_space];
-}
-
-inline cCPUMemory & cHardware4Stack::GetMemory(int mem_space)
-{
- if(mem_space >= NUM_MEMORY_SPACES)
- mem_space %= NUM_MEMORY_SPACES;
- return memory_array[mem_space];
-}
-
-inline void cHardware4Stack::NextThread()
-{
- cur_thread++;
- if (cur_thread >= GetNumThreads()) cur_thread = 0;
-}
-
-inline void cHardware4Stack::PrevThread()
-{
- if (cur_thread == 0) cur_thread = GetNumThreads() - 1;
- else cur_thread--;
-}
-
-inline void cHardware4Stack::SetThread(int value)
-{
- if (value>=0 && value < GetNumThreads())
- cur_thread=value;
-}
-
-inline cInjectGenotype * cHardware4Stack::GetCurThreadOwner()
-{
- return threads[cur_thread].owner;
-}
-
-inline cInjectGenotype * cHardware4Stack::GetThreadOwner(int thread)
-{
- return threads[thread].owner;
-}
-
-inline void cHardware4Stack::SetThreadOwner(cInjectGenotype * in_genotype)
-{
- threads[cur_thread].owner = in_genotype;
-}
-
-/*inline void cHardware4Stack::StackFlip()
-{
- if (threads[cur_thread].cur_stack == 0) {
- threads[cur_thread].stack.Flip();
- } else {
- global_stack.Flip();
- }
-}*/
-
-inline int cHardware4Stack::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 cHardware4Stack::StackClear()
-//{
-
- //if (threads[cur_thread].cur_stack == 0) {
- // threads[cur_thread].stack.Clear();
- //} else {
- // global_stack.Clear();
- //}
-//}
-
-//inline void cHardware4Stack::SwitchStack()
-//{
-// threads[cur_thread].cur_stack++;
-// if (threads[cur_thread].cur_stack > 1) threads[cur_thread].cur_stack = 0;
-//}
-
-inline cCPUStack& cHardware4Stack::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& cHardware4Stack::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& cHardware4Stack::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& cHardware4Stack::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
Deleted: trunk/source/cpu/hardware_4stack_thread.cc
===================================================================
--- trunk/source/cpu/hardware_4stack_thread.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_4stack_thread.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,110 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2003 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef HARDWARE_4STACK_THREAD_HH
-#include "hardware_4stack_thread.hh"
-#endif
-
-using namespace std;
-
-/////////////////////////
-// cHardware4Stack_Thread
-/////////////////////////
-
-cHardware4Stack_Thread::cHardware4Stack_Thread(cHardwareBase * in_hardware, int _id)
-{
- Reset(in_hardware, _id);
-}
-
-cHardware4Stack_Thread::cHardware4Stack_Thread(const cHardware4Stack_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;
-}
-
-cHardware4Stack_Thread::~cHardware4Stack_Thread() {}
-
-void cHardware4Stack_Thread::operator=(const cHardware4Stack_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 cHardware4Stack_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 cHardware4Stack_Thread::SaveState(ostream & fp){
- assert(fp.good());
- fp << "cHardware4Stack_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 cHardware4Stack_Thread::LoadState(istream & fp){
- assert(fp.good());
- cString foo;
- fp >> foo;
- assert( foo == "cHardware4Stack_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: */
-
- // Code labels
- read_label.LoadState(fp);
- next_label.LoadState(fp);
-}
Deleted: trunk/source/cpu/hardware_4stack_thread.hh
===================================================================
--- trunk/source/cpu/hardware_4stack_thread.hh 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_4stack_thread.hh 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,71 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2003 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef HARDWARE_4STACK_THREAD_HH
-#define HARDWARE_4STACK_THREAD_HH
-
-#include <iostream>
-
-#ifndef CODE_LABEL_HH
-#include "cCodeLabel.h"
-#endif
-#ifndef CPU_STACK_HH
-#include "cCPUStack.h"
-#endif
-#ifndef HEAD_MULTI_MEM_HH
-#include "head_multi_mem.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, cHeadMultiMem, cHardware4Stack
- **/
-
-class cHeadMultiMem; // aggregate
-class cCodeLabel; // aggregate
-class cCPUStack; // aggregate
-class cHardwareBase;
-class cInjectGenotype;
-template <class T> class tBuffer; // aggregate
-
-struct cHardware4Stack_Thread {
-private:
- int id;
-public:
- cHeadMultiMem 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:
- cHardware4Stack_Thread(cHardwareBase * in_hardware=NULL, int _id=-1);
- cHardware4Stack_Thread(const cHardware4Stack_Thread & in_thread, int _id=-1);
- ~cHardware4Stack_Thread();
-
- void operator=(const cHardware4Stack_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
Deleted: trunk/source/cpu/hardware_base.cc
===================================================================
--- trunk/source/cpu/hardware_base.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_base.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,61 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2003 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#include "hardware_base.hh"
-
-#include "inst_set.hh"
-
-using namespace std;
-
-int cHardwareBase::instance_count(0);
-
-cHardwareBase::cHardwareBase(cOrganism * in_organism, cInstSet * in_inst_set)
- : organism(in_organism)
- , inst_set(in_inst_set)
- , viewer_lock(-1)
- , m_tracer(NULL)
-{
- assert(inst_set->OK());
- assert(organism != NULL);
-
- instance_count++;
-}
-
-cHardwareBase::~cHardwareBase()
-{
- instance_count--;
-}
-
-void cHardwareBase::Recycle(cOrganism * new_organism, cInstSet * in_inst_set)
-{
- assert(inst_set->OK());
- assert(new_organism != NULL);
-
- organism = new_organism;
- inst_set = in_inst_set;
- viewer_lock = -1;
-}
-
-bool cHardwareBase::Inst_Nop() // Do Nothing.
-{
- return true;
-}
-
-
-int cHardwareBase::GetNumInst()
-{
- assert(inst_set != NULL);
- return inst_set->GetSize();
-}
-
-
-cInstruction cHardwareBase::GetRandomInst()
-{
- assert(inst_set != NULL);
- return inst_set->GetRandomInst();
-}
-
Deleted: trunk/source/cpu/hardware_base.hh
===================================================================
--- trunk/source/cpu/hardware_base.hh 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_base.hh 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,91 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2003 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef HARDWARE_BASE_HH
-#define HARDWARE_BASE_HH
-
-#include <iostream>
-
-#ifndef INSTRUCTION_HH
-#include "instruction.hh"
-#endif
-
-using namespace std;
-
-class cCodeLabel;
-class cCPUMemory;
-class cGenome;
-class cHardwareTracer;
-class cInstruction; // aggregate
-class cInstSet;
-class cOrganism;
-
-class cHardwareBase {
-protected:
- cOrganism * organism; // Organism using this hardware.
- cInstSet * inst_set; // Instruction set being used.
- int viewer_lock; // Used if the viewer should only lock onto
- // one aspect of the hardware.
-
- cHardwareTracer * m_tracer; // Set this if you want execution traced.
-
- static int instance_count;
-public:
- cHardwareBase(cOrganism * in_organism, cInstSet * in_inst_set);
- virtual ~cHardwareBase();
- virtual void Recycle(cOrganism * new_organism, cInstSet * in_inst_set);
-
- // -------- Organism ---------
- cOrganism * GetOrganism() { return organism; }
-
- // -------- Instruction Library --------
- const cInstSet & GetInstSet() { return *inst_set; }
- int GetNumInst();
- cInstruction GetRandomInst();
- virtual void SetInstSet(cInstSet & in_inst_set) { inst_set = &in_inst_set; }
-
- // -------- No-Operation Instruction --------
- bool Inst_Nop(); // A no-operation instruction that does nothing!
-
- // -------- Interaction with Viewer --------
- int & ViewerLock() { return viewer_lock; }
-
- // -------- Core Functionality --------
- virtual void Reset() = 0;
- virtual void SingleProcess() = 0;
- virtual void ProcessBonusInst(const cInstruction & inst) = 0;
- virtual void LoadGenome(const cGenome & new_genome) = 0;
- virtual bool OK() = 0;
-
- // -------- Other Virtual Tools --------
- virtual int GetType() const = 0;
- virtual bool InjectHost(const cCodeLabel & in_label,
- const cGenome & injection) = 0;
- virtual int InjectThread(const cCodeLabel & in_label,
- const cGenome & injection) = 0;
-
- // -------- Input and Output --------
- virtual void PrintStatus(std::ostream & fp) = 0;
- virtual void SaveState(std::ostream & fp) = 0;
- virtual void LoadState(std::istream & fp) = 0;
-
- void SetTrace(cHardwareTracer * tracer) { m_tracer = tracer; }
-
-
- // -------- Mutations (Must be Virtual) --------
- virtual int PointMutate(const double mut_rate) = 0;
- virtual bool TriggerMutations(int trigger) = 0;
-
- // -------- @CAO Should be rethought? --------
- virtual cCPUMemory & GetMemory() = 0;
- virtual cCPUMemory & GetMemory(int) = 0;
-
- // -------- DEBUG ---------
- static int GetInstanceCount() { return instance_count; }
-};
-
-#endif
Deleted: trunk/source/cpu/hardware_cpu.cc
===================================================================
--- trunk/source/cpu/hardware_cpu.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_cpu.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,3463 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2004 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#include "hardware_cpu.hh"
-
-#include "config.hh"
-#include "cCPUTestInfo.h"
-#include "functions.hh"
-#include "genome_util.hh"
-#include "genotype.hh"
-#include "hardware_tracer.hh"
-#include "hardware_tracer_cpu.hh"
-#include "inst_lib_cpu.hh"
-#include "inst_set.hh"
-#include "mutation.hh"
-#include "mutation_lib.hh"
-#include "mutation_macros.hh"
-#include "organism.hh"
-#include "phenotype.hh"
-#include "string_util.hh"
-#include "test_cpu.hh"
-
-#include <limits.h>
-#include <fstream>
-
-using namespace std;
-
-
-///////////////
-// cHardwareCPU
-///////////////
-
-const cInstruction cInstLibCPU::inst_error(255);
-const cInstruction cInstLibCPU::inst_default(0);
-cInstLibCPU *cHardwareCPU::GetInstLib(){ return s_inst_slib; }
-
-cInstLibCPU *cHardwareCPU::s_inst_slib = cHardwareCPU::initInstLib();
-cInstLibCPU *cHardwareCPU::initInstLib(void){
- struct cNOPEntryCPU {
- cString name;
- int nop_mod;
- cNOPEntryCPU(const cString &name, int nop_mod)
- : name(name), nop_mod(nop_mod) {}
- };
- static const cNOPEntryCPU s_n_array[] = {
- cNOPEntryCPU("nop-A", REG_AX),
- cNOPEntryCPU("nop-B", REG_BX),
- cNOPEntryCPU("nop-C", REG_CX),
- cNOPEntryCPU("nop-D", REG_DX)
- };
-
- struct cInstEntryCPU {
- const cString name;
- const tHardwareCPUMethod function;
- const bool is_default;
- const cString desc;
-
- cInstEntryCPU(const cString & _name, tHardwareCPUMethod _fun,
- bool _def=false, const cString & _desc="")
- : name(_name), function(_fun), is_default(_def), desc(_desc) {}
- };
- static const cInstEntryCPU s_f_array[] = {
- /*
- Note: all entries of cNOPEntryCPU s_n_array must have corresponding
- in the same order in cInstEntryCPU s_f_array, and these entries must
- be the first elements of s_f_array.
- */
- cInstEntryCPU("nop-A", &cHardwareCPU::Inst_Nop, true,
- "No-operation instruction; modifies other instructions"),
- cInstEntryCPU("nop-B", &cHardwareCPU::Inst_Nop, true,
- "No-operation instruction; modifies other instructions"),
- cInstEntryCPU("nop-C", &cHardwareCPU::Inst_Nop, true,
- "No-operation instruction; modifies other instructions"),
- cInstEntryCPU("nop-D", &cHardwareCPU::Inst_Nop, true,
- "No-operation instruction; modifies other instructions"),
-
- cInstEntryCPU("NULL", &cHardwareCPU::Inst_Nop, false,
- "True no-operation instruction: does nothing"),
- cInstEntryCPU("nop-X", &cHardwareCPU::Inst_Nop, false,
- "True no-operation instruction: does nothing"),
- cInstEntryCPU("if-equ-0", &cHardwareCPU::Inst_If0, false,
- "Execute next instruction if ?BX?==0, else skip it"),
- cInstEntryCPU("if-not-0", &cHardwareCPU::Inst_IfNot0, false,
- "Execute next instruction if ?BX?!=0, else skip it"),
- cInstEntryCPU("if-n-equ", &cHardwareCPU::Inst_IfNEqu, true,
- "Execute next instruction if ?BX?!=?CX?, else skip it"),
- cInstEntryCPU("if-equ", &cHardwareCPU::Inst_IfEqu, false,
- "Execute next instruction if ?BX?==?CX?, else skip it"),
- cInstEntryCPU("if-grt-0", &cHardwareCPU::Inst_IfGr0),
- cInstEntryCPU("if-grt", &cHardwareCPU::Inst_IfGr),
- cInstEntryCPU("if->=-0", &cHardwareCPU::Inst_IfGrEqu0),
- cInstEntryCPU("if->=", &cHardwareCPU::Inst_IfGrEqu),
- cInstEntryCPU("if-les-0", &cHardwareCPU::Inst_IfLess0),
- cInstEntryCPU("if-less", &cHardwareCPU::Inst_IfLess, true,
- "Execute next instruction if ?BX? < ?CX?, else skip it"),
- cInstEntryCPU("if-<=-0", &cHardwareCPU::Inst_IfLsEqu0),
- cInstEntryCPU("if-<=", &cHardwareCPU::Inst_IfLsEqu),
- cInstEntryCPU("if-A!=B", &cHardwareCPU::Inst_IfANotEqB),
- cInstEntryCPU("if-B!=C", &cHardwareCPU::Inst_IfBNotEqC),
- cInstEntryCPU("if-A!=C", &cHardwareCPU::Inst_IfANotEqC),
- cInstEntryCPU("if-bit-1", &cHardwareCPU::Inst_IfBit1),
-
- cInstEntryCPU("jump-f", &cHardwareCPU::Inst_JumpF),
- cInstEntryCPU("jump-b", &cHardwareCPU::Inst_JumpB),
- cInstEntryCPU("jump-p", &cHardwareCPU::Inst_JumpP),
- cInstEntryCPU("jump-slf", &cHardwareCPU::Inst_JumpSelf),
- cInstEntryCPU("call", &cHardwareCPU::Inst_Call),
- cInstEntryCPU("return", &cHardwareCPU::Inst_Return),
-
- cInstEntryCPU("pop", &cHardwareCPU::Inst_Pop, true,
- "Remove top number from stack and place into ?BX?"),
- cInstEntryCPU("push", &cHardwareCPU::Inst_Push, true,
- "Copy number from ?BX? and place it into the stack"),
- cInstEntryCPU("swap-stk", &cHardwareCPU::Inst_SwitchStack, true,
- "Toggle which stack is currently being used"),
- cInstEntryCPU("flip-stk", &cHardwareCPU::Inst_FlipStack),
- cInstEntryCPU("swap", &cHardwareCPU::Inst_Swap, true,
- "Swap the contents of ?BX? with ?CX?"),
- cInstEntryCPU("swap-AB", &cHardwareCPU::Inst_SwapAB),
- cInstEntryCPU("swap-BC", &cHardwareCPU::Inst_SwapBC),
- cInstEntryCPU("swap-AC", &cHardwareCPU::Inst_SwapAC),
- cInstEntryCPU("copy-reg", &cHardwareCPU::Inst_CopyReg),
- cInstEntryCPU("set_A=B", &cHardwareCPU::Inst_CopyRegAB),
- cInstEntryCPU("set_A=C", &cHardwareCPU::Inst_CopyRegAC),
- cInstEntryCPU("set_B=A", &cHardwareCPU::Inst_CopyRegBA),
- cInstEntryCPU("set_B=C", &cHardwareCPU::Inst_CopyRegBC),
- cInstEntryCPU("set_C=A", &cHardwareCPU::Inst_CopyRegCA),
- cInstEntryCPU("set_C=B", &cHardwareCPU::Inst_CopyRegCB),
- cInstEntryCPU("reset", &cHardwareCPU::Inst_Reset),
-
- cInstEntryCPU("pop-A", &cHardwareCPU::Inst_PopA),
- cInstEntryCPU("pop-B", &cHardwareCPU::Inst_PopB),
- cInstEntryCPU("pop-C", &cHardwareCPU::Inst_PopC),
- cInstEntryCPU("push-A", &cHardwareCPU::Inst_PushA),
- cInstEntryCPU("push-B", &cHardwareCPU::Inst_PushB),
- cInstEntryCPU("push-C", &cHardwareCPU::Inst_PushC),
-
- cInstEntryCPU("shift-r", &cHardwareCPU::Inst_ShiftR, true,
- "Shift bits in ?BX? right by one (divide by two)"),
- cInstEntryCPU("shift-l", &cHardwareCPU::Inst_ShiftL, true,
- "Shift bits in ?BX? left by one (multiply by two)"),
- cInstEntryCPU("bit-1", &cHardwareCPU::Inst_Bit1),
- cInstEntryCPU("set-num", &cHardwareCPU::Inst_SetNum),
- cInstEntryCPU("val-grey", &cHardwareCPU::Inst_ValGrey),
- cInstEntryCPU("val-dir", &cHardwareCPU::Inst_ValDir),
- cInstEntryCPU("val-add-p", &cHardwareCPU::Inst_ValAddP),
- cInstEntryCPU("val-fib", &cHardwareCPU::Inst_ValFib),
- cInstEntryCPU("val-poly-c",&cHardwareCPU::Inst_ValPolyC),
- cInstEntryCPU("inc", &cHardwareCPU::Inst_Inc, true,
- "Increment ?BX? by one"),
- cInstEntryCPU("dec", &cHardwareCPU::Inst_Dec, true,
- "Decrement ?BX? by one"),
- cInstEntryCPU("zero", &cHardwareCPU::Inst_Zero, false,
- "Set ?BX? to zero"),
- cInstEntryCPU("neg", &cHardwareCPU::Inst_Neg),
- cInstEntryCPU("square", &cHardwareCPU::Inst_Square),
- cInstEntryCPU("sqrt", &cHardwareCPU::Inst_Sqrt),
- cInstEntryCPU("not", &cHardwareCPU::Inst_Not),
- cInstEntryCPU("minus-17", &cHardwareCPU::Inst_Minus17),
-
- cInstEntryCPU("add", &cHardwareCPU::Inst_Add, true,
- "Add BX to CX and place the result in ?BX?"),
- cInstEntryCPU("sub", &cHardwareCPU::Inst_Sub, true,
- "Subtract CX from BX and place the result in ?BX?"),
- cInstEntryCPU("mult", &cHardwareCPU::Inst_Mult, false,
- "Multiple BX by CX and place the result in ?BX?"),
- cInstEntryCPU("div", &cHardwareCPU::Inst_Div, false,
- "Divide BX by CX and place the result in ?BX?"),
- cInstEntryCPU("mod", &cHardwareCPU::Inst_Mod),
- cInstEntryCPU("nand", &cHardwareCPU::Inst_Nand, true,
- "Nand BX by CX and place the result in ?BX?"),
- cInstEntryCPU("nor", &cHardwareCPU::Inst_Nor),
- cInstEntryCPU("and", &cHardwareCPU::Inst_And),
- cInstEntryCPU("order", &cHardwareCPU::Inst_Order),
- cInstEntryCPU("xor", &cHardwareCPU::Inst_Xor),
-
- cInstEntryCPU("copy", &cHardwareCPU::Inst_Copy),
- cInstEntryCPU("read", &cHardwareCPU::Inst_ReadInst),
- cInstEntryCPU("write", &cHardwareCPU::Inst_WriteInst),
- cInstEntryCPU("stk-read", &cHardwareCPU::Inst_StackReadInst),
- cInstEntryCPU("stk-writ", &cHardwareCPU::Inst_StackWriteInst),
-
- cInstEntryCPU("compare", &cHardwareCPU::Inst_Compare),
- cInstEntryCPU("if-n-cpy", &cHardwareCPU::Inst_IfNCpy),
- cInstEntryCPU("allocate", &cHardwareCPU::Inst_Allocate),
- cInstEntryCPU("divide", &cHardwareCPU::Inst_Divide),
- cInstEntryCPU("c-alloc", &cHardwareCPU::Inst_CAlloc),
- cInstEntryCPU("c-divide", &cHardwareCPU::Inst_CDivide),
- cInstEntryCPU("inject", &cHardwareCPU::Inst_Inject),
- cInstEntryCPU("inject-r", &cHardwareCPU::Inst_InjectRand),
- cInstEntryCPU("search-f", &cHardwareCPU::Inst_SearchF),
- cInstEntryCPU("search-b", &cHardwareCPU::Inst_SearchB),
- cInstEntryCPU("mem-size", &cHardwareCPU::Inst_MemSize),
-
- cInstEntryCPU("get", &cHardwareCPU::Inst_TaskGet),
- cInstEntryCPU("stk-get", &cHardwareCPU::Inst_TaskStackGet),
- cInstEntryCPU("stk-load", &cHardwareCPU::Inst_TaskStackLoad),
- cInstEntryCPU("put", &cHardwareCPU::Inst_TaskPut),
- cInstEntryCPU("IO", &cHardwareCPU::Inst_TaskIO, true,
- "Output ?BX?, and input new number back into ?BX?"),
-
- cInstEntryCPU("send", &cHardwareCPU::Inst_Send),
- cInstEntryCPU("receive", &cHardwareCPU::Inst_Receive),
- cInstEntryCPU("sense", &cHardwareCPU::Inst_Sense),
-
- cInstEntryCPU("donate-rnd", &cHardwareCPU::Inst_DonateRandom),
- cInstEntryCPU("donate-kin", &cHardwareCPU::Inst_DonateKin),
- cInstEntryCPU("donate-edt", &cHardwareCPU::Inst_DonateEditDist),
- cInstEntryCPU("donate-NUL", &cHardwareCPU::Inst_DonateNULL),
-
- cInstEntryCPU("rotate-l", &cHardwareCPU::Inst_RotateL),
- cInstEntryCPU("rotate-r", &cHardwareCPU::Inst_RotateR),
-
- cInstEntryCPU("set-cmut", &cHardwareCPU::Inst_SetCopyMut),
- cInstEntryCPU("mod-cmut", &cHardwareCPU::Inst_ModCopyMut),
-
- // Threading instructions
- cInstEntryCPU("fork-th", &cHardwareCPU::Inst_ForkThread),
- cInstEntryCPU("kill-th", &cHardwareCPU::Inst_KillThread),
- cInstEntryCPU("id-th", &cHardwareCPU::Inst_ThreadID),
-
- // Head-based instructions
- cInstEntryCPU("h-alloc", &cHardwareCPU::Inst_MaxAlloc, true,
- "Allocate maximum allowed space"),
- cInstEntryCPU("h-divide", &cHardwareCPU::Inst_HeadDivide, true,
- "Divide code between read and write heads."),
- cInstEntryCPU("h-read", &cHardwareCPU::Inst_HeadRead),
- cInstEntryCPU("h-write", &cHardwareCPU::Inst_HeadWrite),
- cInstEntryCPU("h-copy", &cHardwareCPU::Inst_HeadCopy, true,
- "Copy from read-head to write-head; advance both"),
- cInstEntryCPU("h-search", &cHardwareCPU::Inst_HeadSearch, true,
- "Find complement template and make with flow head"),
- cInstEntryCPU("h-push", &cHardwareCPU::Inst_HeadPush),
- cInstEntryCPU("h-pop", &cHardwareCPU::Inst_HeadPop),
- cInstEntryCPU("set-head", &cHardwareCPU::Inst_SetHead),
- cInstEntryCPU("adv-head", &cHardwareCPU::Inst_AdvanceHead),
- cInstEntryCPU("mov-head", &cHardwareCPU::Inst_MoveHead, true,
- "Move head ?IP? to the flow head"),
- cInstEntryCPU("jmp-head", &cHardwareCPU::Inst_JumpHead, true,
- "Move head ?IP? by amount in CX register; CX = old pos."),
- cInstEntryCPU("get-head", &cHardwareCPU::Inst_GetHead, true,
- "Copy the position of the ?IP? head into CX"),
- cInstEntryCPU("if-label", &cHardwareCPU::Inst_IfLabel, true,
- "Execute next if we copied complement of attached label"),
- cInstEntryCPU("if-label2", &cHardwareCPU::Inst_IfLabel2, true,
- "If copied label compl., exec next inst; else SKIP W/NOPS"),
- cInstEntryCPU("set-flow", &cHardwareCPU::Inst_SetFlow, true,
- "Set flow-head to position in ?CX?"),
-
- cInstEntryCPU("h-copy2", &cHardwareCPU::Inst_HeadCopy2),
- cInstEntryCPU("h-copy3", &cHardwareCPU::Inst_HeadCopy3),
- cInstEntryCPU("h-copy4", &cHardwareCPU::Inst_HeadCopy4),
- cInstEntryCPU("h-copy5", &cHardwareCPU::Inst_HeadCopy5),
- cInstEntryCPU("h-copy6", &cHardwareCPU::Inst_HeadCopy6),
- cInstEntryCPU("h-copy7", &cHardwareCPU::Inst_HeadCopy7),
- cInstEntryCPU("h-copy8", &cHardwareCPU::Inst_HeadCopy8),
- cInstEntryCPU("h-copy9", &cHardwareCPU::Inst_HeadCopy9),
- cInstEntryCPU("h-copy10", &cHardwareCPU::Inst_HeadCopy10),
-
- cInstEntryCPU("divide-sex", &cHardwareCPU::Inst_HeadDivideSex),
- cInstEntryCPU("divide-asex", &cHardwareCPU::Inst_HeadDivideAsex),
-
- cInstEntryCPU("div-sex", &cHardwareCPU::Inst_HeadDivideSex),
- cInstEntryCPU("div-asex", &cHardwareCPU::Inst_HeadDivideAsex),
- cInstEntryCPU("div-asex-w", &cHardwareCPU::Inst_HeadDivideAsexWait),
- cInstEntryCPU("div-sex-MS", &cHardwareCPU::Inst_HeadDivideMateSelect),
-
- cInstEntryCPU("h-divide1", &cHardwareCPU::Inst_HeadDivide1),
- cInstEntryCPU("h-divide2", &cHardwareCPU::Inst_HeadDivide2),
- cInstEntryCPU("h-divide3", &cHardwareCPU::Inst_HeadDivide3),
- cInstEntryCPU("h-divide4", &cHardwareCPU::Inst_HeadDivide4),
- cInstEntryCPU("h-divide5", &cHardwareCPU::Inst_HeadDivide5),
- cInstEntryCPU("h-divide6", &cHardwareCPU::Inst_HeadDivide6),
- cInstEntryCPU("h-divide7", &cHardwareCPU::Inst_HeadDivide7),
- cInstEntryCPU("h-divide8", &cHardwareCPU::Inst_HeadDivide8),
- cInstEntryCPU("h-divide9", &cHardwareCPU::Inst_HeadDivide9),
- cInstEntryCPU("h-divide10", &cHardwareCPU::Inst_HeadDivide10),
- cInstEntryCPU("h-divide16", &cHardwareCPU::Inst_HeadDivide16),
- cInstEntryCPU("h-divide32", &cHardwareCPU::Inst_HeadDivide32),
- cInstEntryCPU("h-divide50", &cHardwareCPU::Inst_HeadDivide50),
- cInstEntryCPU("h-divide100", &cHardwareCPU::Inst_HeadDivide100),
- cInstEntryCPU("h-divide500", &cHardwareCPU::Inst_HeadDivide500),
- cInstEntryCPU("h-divide1000", &cHardwareCPU::Inst_HeadDivide1000),
- cInstEntryCPU("h-divide5000", &cHardwareCPU::Inst_HeadDivide5000),
- cInstEntryCPU("h-divide10000", &cHardwareCPU::Inst_HeadDivide10000),
- cInstEntryCPU("h-divide50000", &cHardwareCPU::Inst_HeadDivide50000),
- cInstEntryCPU("h-divide0.5", &cHardwareCPU::Inst_HeadDivide0_5),
- cInstEntryCPU("h-divide0.1", &cHardwareCPU::Inst_HeadDivide0_1),
- cInstEntryCPU("h-divide0.05", &cHardwareCPU::Inst_HeadDivide0_05),
- cInstEntryCPU("h-divide0.01", &cHardwareCPU::Inst_HeadDivide0_01),
- cInstEntryCPU("h-divide0.001", &cHardwareCPU::Inst_HeadDivide0_001),
-
- // High-level instructions
- cInstEntryCPU("repro", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-A", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-B", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-C", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-D", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-E", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-F", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-G", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-H", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-I", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-J", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-K", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-L", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-M", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-N", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-O", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-P", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-Q", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-R", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-S", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-T", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-U", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-V", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-W", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-X", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-Y", &cHardwareCPU::Inst_Repro),
- cInstEntryCPU("repro-Z", &cHardwareCPU::Inst_Repro),
-
- // Suicide
- cInstEntryCPU("kazi", &cHardwareCPU::Inst_Kazi),
- cInstEntryCPU("die", &cHardwareCPU::Inst_Die),
-
-
-
- // Placebo instructions
- // nop-x (included with nops)
- cInstEntryCPU("skip", &cHardwareCPU::Inst_Skip)
- };
-
- const int n_size = sizeof(s_n_array)/sizeof(cNOPEntryCPU);
-
- 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(cInstEntryCPU);
- static cString f_names[f_size];
- static tHardwareCPUMethod 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;
- }
-
- cInstLibCPU *inst_lib = new cInstLibCPU(
- n_size,
- f_size,
- n_names,
- f_names,
- nop_mods,
- functions
- );
-
- return inst_lib;
-}
-
-cHardwareCPU::cHardwareCPU(cOrganism * in_organism, cInstSet * in_inst_set)
- : cHardwareBase(in_organism, in_inst_set)
-{
- /* FIXME: reorganize storage of m_functions. -- kgn */
- m_functions = s_inst_slib->GetFunctions();
- /**/
- memory = in_organism->GetGenome(); // Initialize memory...
- Reset(); // Setup the rest of the hardware...
-}
-
-
-cHardwareCPU::cHardwareCPU(const cHardwareCPU &hardware_cpu)
-: cHardwareBase(hardware_cpu.organism, hardware_cpu.inst_set)
-, m_functions(hardware_cpu.m_functions)
-, memory(hardware_cpu.memory)
-, global_stack(hardware_cpu.global_stack)
-, thread_time_used(hardware_cpu.thread_time_used)
-, threads(hardware_cpu.threads)
-, thread_id_chart(hardware_cpu.thread_id_chart)
-, cur_thread(hardware_cpu.cur_thread)
-, mal_active(hardware_cpu.mal_active)
-, advance_ip(hardware_cpu.advance_ip)
-#ifdef INSTRUCTION_COSTS
-, inst_cost(hardware_cpu.inst_cost)
-, inst_ft_cost(hardware_cpu.inst_ft_cost)
-#endif
-{
-}
-
-
-cHardwareCPU::~cHardwareCPU()
-{
-}
-
-
-void cHardwareCPU::Recycle(cOrganism * new_organism, cInstSet * in_inst_set)
-{
- cHardwareBase::Recycle(new_organism, in_inst_set);
- memory = new_organism->GetGenome();
- Reset();
-}
-
-
-void cHardwareCPU::Reset()
-{
- global_stack.Clear();
- thread_time_used = 0;
-
- // 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;
-
-#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 cHardwareCPU::SingleProcess()
-{
- // Mark this organism as running...
- organism->SetRunning(true);
-
- cPhenotype & phenotype = organism->GetPhenotype();
- phenotype.IncTimeUsed();
- const int num_threads = GetNumThreads();
- if (num_threads > 1) thread_time_used++;
-
- // 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) ?
- num_threads : 1;
-
- for (int i = 0; i < num_inst_exec; i++) {
- // Setup the hardware for the next instruction to be executed.
- NextThread();
- advance_ip = 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_CPU * tracer
- = dynamic_cast<cHardwareTracer_CPU *>(m_tracer)
- ){
- tracer->TraceHardware_CPU(*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 (advance_ip == 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() == true) {
- 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 cHardwareCPU::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 cHardwareCPU::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 cHardwareCPU::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_CPU * tracer
- = dynamic_cast<cHardwareTracer_CPU *>(m_tracer)
- ){
- tracer->TraceHardware_CPUBonus(*this);
- }
- }
-
- SingleProcess_ExecuteInst(inst);
-
- organism->SetRunning(prev_run_state);
-}
-
-
-void cHardwareCPU::LoadGenome(const cGenome & new_genome)
-{
- GetMemory() = new_genome;
-}
-
-
-bool cHardwareCPU::OK()
-{
- bool result = true;
-
- if (!memory.OK()) result = false;
-
- for (int i = 0; i < GetNumThreads(); i++) {
- if (threads[i].stack.OK() == false) result = false;
- if (threads[i].next_label.OK() == false) result = false;
- }
-
- return result;
-}
-
-void cHardwareCPU::PrintStatus(ostream & fp)
-{
- fp << organism->GetPhenotype().GetTimeUsed() << " "
- << "IP:" << IP().GetPosition() << " "
-
- << "AX:" << Register(REG_AX) << " "
- << setbase(16) << "[0x" << Register(REG_AX) << "] " << setbase(10)
-
- << "BX:" << Register(REG_BX) << " "
- << setbase(16) << "[0x" << Register(REG_BX) << "] " << setbase(10)
-
- << "CX:" << Register(REG_CX) << " "
- << setbase(16) << "[0x" << Register(REG_CX) << "]" << setbase(10)
-
- << endl;
-
- fp << " R-Head:" << GetHead(HEAD_READ).GetPosition() << " "
- << "W-Head:" << GetHead(HEAD_WRITE).GetPosition() << " "
- << "F-Head:" << GetHead(HEAD_FLOW).GetPosition() << " "
- << "RL:" << GetReadLabel().AsString() << " "
- << endl;
-
- fp << " Mem (" << GetMemory().GetSize() << "):"
- << " " << GetMemory().AsString()
- << endl;
- fp.flush();
-}
-
-
-
-
-
-/////////////////////////////////////////////////////////////////////////
-// Method: cHardwareCPU::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.
-//
-/////////////////////////////////////////////////////////////////////////
-
-cHeadCPU cHardwareCPU::FindLabel(int direction)
-{
- cHeadCPU & inst_ptr = IP();
-
- // Start up a search head at the position of the instruction pointer.
- cHeadCPU 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);
-
- // 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 cHardwareCPU::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 cHardwareCPU::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.
-cHeadCPU cHardwareCPU::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!!!
-
- cHeadCPU 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.
-cHeadCPU cHardwareCPU::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!
-
- cHeadCPU 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;
-}
-
-
-bool cHardwareCPU::InjectHost(const cCodeLabel & in_label, const cGenome & injection)
-{
- // Make sure the genome will be below max size after injection.
-
- const int new_size = injection.GetSize() + GetMemory().GetSize();
- if (new_size > MAX_CREATURE_SIZE) return false; // (inject fails)
-
- const int inject_line = FindFullLabel(in_label).GetPosition();
-
- // Abort if no compliment is found.
- if (inject_line == -1) return false; // (inject fails)
-
- // Inject the code!
- InjectCode(injection, inject_line+1);
-
- return true; // (inject succeeds!)
-}
-
-int cHardwareCPU::InjectThread(const cCodeLabel & in_label, const cGenome & injection)
-{
- // Make sure the genome will be below max size after injection.
-
- const int new_size = injection.GetSize() + GetMemory().GetSize();
- if (new_size > MAX_CREATURE_SIZE) return 1; // (inject fails)
-
- const int inject_line = FindFullLabel(in_label).GetPosition();
-
- // Abort if no compliment is found.
- if (inject_line == -1) return 2; // (inject fails)
-
- // Inject the code!
- InjectCodeThread(injection, inject_line+1);
-
- return 0; // (inject succeeds!)
-}
-
-void cHardwareCPU::InjectCode(const cGenome & inject_code, const int line_num)
-{
- assert(line_num >= 0);
- assert(line_num <= memory.GetSize());
- assert(memory.GetSize() + inject_code.GetSize() < MAX_CREATURE_SIZE);
-
- // Inject the new code.
- const int inject_size = inject_code.GetSize();
- memory.Insert(line_num, inject_code);
-
- // Set instruction flags on the injected code
- for (int i = line_num; i < line_num + inject_size; i++) {
- memory.FlagInjected(i) = true;
- }
- organism->GetPhenotype().IsModified() = true;
-
- // Adjust all of the heads to take into account the new mem size.
-
- for (int i=0; i < NUM_HEADS; i++) {
- if (!GetHead(i).TestParasite() &&
- GetHead(i).GetPosition() > line_num)
- GetHead(i).Jump(inject_size);
- }
-}
-
-void cHardwareCPU::InjectCodeThread(const cGenome & inject_code, const int line_num)
-{
- assert(line_num >= 0);
- assert(line_num <= memory.GetSize());
- assert(memory.GetSize() + inject_code.GetSize() < MAX_CREATURE_SIZE);
-
- if(ForkThread())
- {
- // Inject the new code.
- const int inject_size = inject_code.GetSize();
- memory.Insert(line_num, inject_code);
-
- // Set instruction flags on the injected code
- for (int i = line_num; i < line_num + inject_size; i++) {
- memory.FlagInjected(i) = true;
- }
- organism->GetPhenotype().IsModified() = true;
- organism->GetPhenotype().IsMultiThread() = true;
-
- // Adjust all of the heads to take into account the new mem size.
-
- int currthread = GetCurThread();
- SetThread(0);
- for (int i=0; i<GetNumThreads()-2; i++)
- {
- for (int j=0; j < NUM_HEADS; j++)
- {
- if (!GetHead(i).TestParasite() && GetHead(i).GetPosition() > line_num)
- GetHead(i).Jump(inject_size);
- }
- NextThread();
- }
- SetThread(currthread);
-
- }
- else
- {
- //Some kind of error message should go here...but what?
- }
-
-}
-
-void cHardwareCPU::Mutate(int mut_point)
-{
- // Test if trying to mutate outside of genome...
- assert(mut_point >= 0 && mut_point < GetMemory().GetSize());
-
- GetMemory()[mut_point] = GetRandomInst();
- GetMemory().FlagMutated(mut_point) = true;
- GetMemory().FlagPointMut(mut_point) = true;
- //organism->GetPhenotype().IsMutated() = true;
- organism->CPUStats().mut_stats.point_mut_count++;
-}
-
-int cHardwareCPU::PointMutate(const double mut_rate)
-{
- const int num_muts =
- g_random.GetRandBinomial(GetMemory().GetSize(), mut_rate);
-
- for (int i = 0; i < num_muts; i++) {
- const int pos = g_random.GetUInt(GetMemory().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 cHardwareCPU::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 cHardwareCPU::TriggerMutations(int trigger, cHeadCPU & 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();
-
- // 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 cHardwareCPU::TriggerMutations_ScopeGenome(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadCPU & 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.
- cHeadCPU 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 cHardwareCPU::TriggerMutations_ScopeLocal(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadCPU & 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 cHardwareCPU::TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadCPU & 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++) {
- cHeadCPU 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 cHardwareCPU::TriggerMutations_Body(int type, cCPUMemory & target_memory,
- cHeadCPU & 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 cHardwareCPU::ReadInst(const int in_inst)
-{
- if (inst_set->IsNop( cInstruction(in_inst) )) {
- GetReadLabel().AddNop(in_inst);
- } else {
- GetReadLabel().Clear();
- }
-}
-
-
-void cHardwareCPU::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 cHardwareCPU::ReadLabel(int max_size)
-{
- int count = 0;
- cHeadCPU * 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 cHardwareCPU::ForkThread()
-{
- const int num_threads = GetNumThreads();
- if (num_threads == cConfig::GetMaxCPUThreads()) return false;
-
- // Make room for the new thread.
- threads.Resize(num_threads + 1);
-
- // 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 cHardwareCPU::TestParasite() const
-{
- return IP().TestParasite();
-}
-
-
-bool cHardwareCPU::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 cHardwareCPU::SaveState(ostream & fp)
-{
- // note, memory & child_memory handled by cpu (@CAO Not any more!)
- assert(fp.good());
-
- fp<<"cHardwareCPU"<<endl;
-
- // global_stack (in inverse order so load can just push)
- global_stack.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 cHardwareCPU::LoadState(istream & fp)
-{
- // note, memory & child_memory handled by cpu (@CAO Not any more!)
- assert(fp.good());
-
- cString foo;
- fp>>foo;
- assert( foo == "cHardwareCPU" );
-
- // global_stack
- global_stack.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 cHardwareCPU::FindModifiedRegister(int default_register)
-{
- assert(default_register < NUM_REGISTERS); // Reg ID too high.
-
- if (GetInstSet().IsNop(IP().GetNextInst())) {
- IP().Advance();
- default_register = GetInstSet().GetNopMod(IP().GetInst());
- IP().FlagExecuted() = true;
- }
- return default_register;
-}
-
-
-inline int cHardwareCPU::FindModifiedHead(int default_head)
-{
- assert(default_head < NUM_HEADS); // Head ID too high.
-
- if (GetInstSet().IsNop(IP().GetNextInst())) {
- IP().Advance();
- default_head = GetInstSet().GetNopMod(IP().GetInst());
- IP().FlagExecuted() = true;
- }
- return default_head;
-}
-
-
-inline int cHardwareCPU::FindComplementRegister(int base_reg)
-{
- const int comp_reg = base_reg + 1;
- return (comp_reg == NUM_REGISTERS) ? 0 : comp_reg;
-}
-
-
-inline void cHardwareCPU::Fault(int fault_loc, int fault_type, cString fault_desc)
-{
- organism->Fault(fault_loc, fault_type, fault_desc);
-}
-
-
-bool cHardwareCPU::Allocate_Necro(const int new_size)
-{
- GetMemory().ResizeOld(new_size);
- return true;
-}
-
-bool cHardwareCPU::Allocate_Random(const int old_size, const int new_size)
-{
- GetMemory().Resize(new_size);
-
- for (int i = old_size; i < new_size; i++) {
- GetMemory()[i] = GetInstSet().GetRandomInst();
- }
- return true;
-}
-
-bool cHardwareCPU::Allocate_Default(const int new_size)
-{
- GetMemory().Resize(new_size);
-
- // New space already defaults to default instruction...
-
- return true;
-}
-
-bool cHardwareCPU::Allocate_Main(const int allocated_size)
-{
- // must do divide before second allocate & must allocate positive amount...
- if (cConfig::GetRequireAllocate() && mal_active == true) {
- Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR, "Allocate already active");
- return false;
- }
- if (allocated_size < 1) {
- Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
- cStringUtil::Stringf("Allocate of %d too small", allocated_size));
- return false;
- }
-
- const int old_size = GetMemory().GetSize();
- const int new_size = old_size + allocated_size;
-
- // Make sure that the new size is in range.
- if (new_size > MAX_CREATURE_SIZE || new_size < MIN_CREATURE_SIZE) {
- Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
- cStringUtil::Stringf("Invalid post-allocate size (%d)",
- new_size));
- return false;
- }
-
- const int max_alloc_size = (int) (old_size * cConfig::GetChildSizeRange());
- if (allocated_size > max_alloc_size) {
- Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
- cStringUtil::Stringf("Allocate too large (%d > %d)",
- allocated_size, max_alloc_size));
- return false;
- }
-
- const int max_old_size =
- (int) (allocated_size * cConfig::GetChildSizeRange());
- if (old_size > max_old_size) {
- Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
- cStringUtil::Stringf("Allocate too small (%d > %d)",
- old_size, max_old_size));
- return false;
- }
-
- switch (cConfig::GetAllocMethod()) {
- case ALLOC_METHOD_NECRO:
- // Only break if this succeeds -- otherwise just do random.
- if (Allocate_Necro(new_size) == true) break;
- case ALLOC_METHOD_RANDOM:
- Allocate_Random(old_size, new_size);
- break;
- case ALLOC_METHOD_DEFAULT:
- Allocate_Default(new_size);
- break;
- }
-
- mal_active = true;
-
- return true;
-}
-
-
-bool cHardwareCPU::Divide_CheckViable(const int child_size,
- const int parent_size)
-{
- // Make sure the organism is okay with dividing now...
- if (organism->Divide_CheckViable() == false) return false; // (divide fails)
-
- // If required, make sure an allocate has occured.
- if (cConfig::GetRequireAllocate() && mal_active == false) {
- Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR, "Must allocate before divide");
- 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)
- }
- if (parent_size < min_size || parent_size > max_size) {
- Fault(FAULT_LOC_DIVIDE, FAULT_TYPE_ERROR,
- cStringUtil::Stringf("Invalid post-divide length (%d)",parent_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().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 = parent_size; i < parent_size + child_size; i++) {
- if (GetMemory().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...
- cPhenotype & phenotype = organism->GetPhenotype();
- phenotype.SetLinesExecuted(executed_size);
- phenotype.SetLinesCopied(copied_size);
-
- // Determine the fitness of this organism as compared to its parent...
- if (cConfig::GetTestSterilize() == true &&
- phenotype.IsInjected() == false) {
- const int merit_base =
- cPhenotype::CalcSizeMerit(genome_size, copied_size, executed_size);
- const double cur_fitness =
- merit_base * phenotype.GetCurBonus() / phenotype.GetTimeUsed();
- const double fitness_ratio = cur_fitness / phenotype.GetLastFitness();
-
-
- // const double neut_min = parent_fitness * FITNESS_NEUTRAL_MIN;
- // const double neut_max = parent_fitness * FITNESS_NEUTRAL_MAX;
-
- bool sterilize = false;
-
- if (fitness_ratio < FITNESS_NEUTRAL_MIN) {
- if (g_random.P(organism->GetSterilizeNeg())) sterilize = true;
- } else if (fitness_ratio <= FITNESS_NEUTRAL_MAX) {
- if (g_random.P(organism->GetSterilizeNeut())) sterilize = true;
- } else {
- if (g_random.P(organism->GetSterilizePos())) sterilize = true;
- }
-
-// cout << "[ min(" << genome_size
-// << "," << copied_size
-// << "," << executed_size
-// << ") * " << phenotype.GetCurBonus()
-// << " / " << phenotype.GetTimeUsed()
-// << "] / " << phenotype.GetLastFitness()
-// << " == " << fitness_ratio;
-
- if (sterilize == true) {
- //Don't let this organism have this or any more children!
- phenotype.IsFertile() = false;
- return false;
- }
- }
-
- return true; // (divide succeeds!)
-}
-
-
-void cHardwareCPU::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().GetSize(); i++) {
- if (organism->TestParentMut()) {
- GetMemory()[i] = GetRandomInst();
- cpu_stats.mut_stats.parent_mut_line_count++;
- }
- }
- }
-
-
- // Count up mutated lines
- for(int i = 0; i < GetMemory().GetSize(); i++){
- if (GetMemory().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++;
- }
- }
-}
-
-
-// test whether the offspring creature contains an advantageous mutation.
-void cHardwareCPU::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 cHardwareCPU::Divide_Main(const int div_point, const int extra_lines, double mut_multiplier)
-{
- const int child_size = GetMemory().GetSize() - div_point - extra_lines;
-
- // Make sure this divide will produce a viable offspring.
- const bool viable = Divide_CheckViable(child_size, div_point);
- if (viable == false) return false;
-
- // Since the divide will now succeed, set up the information to be sent
- // to the new organism
- cGenome & child_genome = organism->ChildGenome();
- child_genome = cGenomeUtil::Crop(memory, div_point, div_point+child_size);
-
- // Cut off everything in this memory past the divide point.
- GetMemory().Resize(div_point);
-
- // 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
-
- mal_active = false;
- if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) {
- advance_ip = false;
- }
-
- // Activate the child, and do more work if the parent lives through the
- // birth.
- bool parent_alive = organism->ActivateDivide();
- if (parent_alive) {
- if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) Reset();
- }
-
- return true;
-}
-
-
-//////////////////////////
-// And the instructions...
-//////////////////////////
-
-bool cHardwareCPU::Inst_If0() // Execute next if ?bx? ==0.
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- if (Register(reg_used) != 0) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfNot0() // Execute next if ?bx? != 0.
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- if (Register(reg_used) == 0) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfEqu() // Execute next if bx == ?cx?
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int reg_used2 = FindComplementRegister(reg_used);
- if (Register(reg_used) != Register(reg_used2)) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfNEqu() // Execute next if bx != ?cx?
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int reg_used2 = FindComplementRegister(reg_used);
- if (Register(reg_used) == Register(reg_used2)) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfGr0() // Execute next if ?bx? ! < 0.
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- if (Register(reg_used) <= 0) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfGr() // Execute next if bx > ?cx?
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int reg_used2 = FindComplementRegister(reg_used);
- if (Register(reg_used) <= Register(reg_used2)) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfGrEqu0() // Execute next if ?bx? != 0.
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- if (Register(reg_used) < 0) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfGrEqu() // Execute next if bx > ?cx?
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int reg_used2 = FindComplementRegister(reg_used);
- if (Register(reg_used) < Register(reg_used2)) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfLess0() // Execute next if ?bx? != 0.
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- if (Register(reg_used) >= 0) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfLess() // Execute next if ?bx? < ?cx?
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int reg_used2 = FindComplementRegister(reg_used);
- if (Register(reg_used) >= Register(reg_used2)) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfLsEqu0() // Execute next if ?bx? != 0.
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- if (Register(reg_used) > 0) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfLsEqu() // Execute next if bx > ?cx?
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int reg_used2 = FindComplementRegister(reg_used);
- if (Register(reg_used) > Register(reg_used2)) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfBit1()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- if ((Register(reg_used) & 1) == 0) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfANotEqB() // Execute next if AX != BX
-{
- if (Register(REG_AX) == Register(REG_BX) ) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfBNotEqC() // Execute next if BX != CX
-{
- if (Register(REG_BX) == Register(REG_CX) ) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfANotEqC() // Execute next if AX != BX
-{
- if (Register(REG_AX) == Register(REG_CX) ) IP().Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_JumpF()
-{
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
-
- // If there is no label, jump BX steps.
- if (GetLabel().GetSize() == 0) {
- GetActiveHead().Jump(Register(REG_BX));
- return true;
- }
-
- // Otherwise, try to jump to the complement label.
- const cHeadCPU jump_location(FindLabel(1));
- if ( jump_location.GetPosition() != -1 ) {
- GetActiveHead().Set(jump_location);
- return true;
- }
-
- // If complement label was not found; record an error.
- organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
- "jump-f: No complement label");
- return false;
-}
-
-
-bool cHardwareCPU::Inst_JumpB()
-{
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
-
- // If there is no label, jump BX steps.
- if (GetLabel().GetSize() == 0) {
- GetActiveHead().Jump(-Register(REG_BX));
- return true;
- }
-
- // otherwise jump to the complement label.
- const cHeadCPU jump_location(FindLabel(-1));
- if ( jump_location.GetPosition() != -1 ) {
- GetActiveHead().Set(jump_location);
- return true;
- }
-
- // If complement label was not found; record an error.
- organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
- "jump-b: No complement label");
- return false;
-}
-
-bool cHardwareCPU::Inst_JumpP()
-{
- cOrganism * other_organism = organism->GetNeighbor();
-
- // Make sure the other organism was found and that its hardware is of the
- // same type, or else we won't be able to be parasitic on it.
- if (other_organism == NULL ||
- other_organism->GetHardware().GetType() != GetType()) {
- // Without another organism, its hard to determine if we're dealing
- // with a parasite. For the moment, we'll assume it is and move on.
- // @CAO Do better!
- organism->GetPhenotype().IsParasite() = true;
- return true;
- }
-
- // Otherwise, grab the hardware from the neighbor, and use it!
- cHardwareCPU & other_hardware = (cHardwareCPU &) other_organism->GetHardware();
-
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
-
- // If there is no label, jump to line BX in creature.
- if (GetLabel().GetSize() == 0) {
- const int new_pos = Register(REG_BX);
- IP().Set(new_pos, &other_hardware);
- organism->GetPhenotype().IsParasite() = true;
- return true;
- }
-
- // otherwise jump to the complement label.
- const cHeadCPU jump_location(other_hardware.FindFullLabel(GetLabel()));
- if (jump_location.GetPosition() != -1) {
- IP().Set(jump_location);
- organism->GetPhenotype().IsParasite() = true;
- return true;
- }
-
- // If complement label was not found; record a warning (since the
- // actual neighbors are not under the organisms control, this is not
- // a full-scale error).
- organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_WARNING,
- "jump-p: No complement label");
- return false;
-}
-
-bool cHardwareCPU::Inst_JumpSelf()
-{
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
-
- // If there is no label, jump to line BX in creature.
- if (GetLabel().GetSize() == 0) {
- IP().Set(Register(REG_BX), this);
- return true;
- }
-
- // otherwise jump to the complement label.
- const cHeadCPU jump_location( FindFullLabel(GetLabel()) );
- if ( jump_location.GetPosition() != -1 ) {
- IP().Set(jump_location);
- return true;
- }
-
- // If complement label was not found; record an error.
- organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
- "jump-slf: no complement label");
- return false;
-}
-
-bool cHardwareCPU::Inst_Call()
-{
- // Put the starting location onto the stack
- const int location = IP().GetPosition();
- StackPush(location);
-
- // Jump to the compliment label (or by the ammount in the bx register)
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
-
- if (GetLabel().GetSize() == 0) {
- IP().Jump(Register(REG_BX));
- return true;
- }
-
- const cHeadCPU jump_location(FindLabel(1));
- if (jump_location.GetPosition() != -1) {
- IP().Set(jump_location);
- return true;
- }
-
- // If complement label was not found; record an error.
- organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
- "call: no complement label");
- return false;
-}
-
-bool cHardwareCPU::Inst_Return()
-{
- IP().Set(StackPop());
- return true;
-}
-
-bool cHardwareCPU::Inst_Pop()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = StackPop();
- return true;
-}
-
-bool cHardwareCPU::Inst_Push()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- StackPush(Register(reg_used));
- return true;
-}
-
-bool cHardwareCPU::Inst_HeadPop()
-{
- const int head_used = FindModifiedHead(HEAD_IP);
- GetHead(head_used).Set(StackPop(), this);
- return true;
-}
-
-bool cHardwareCPU::Inst_HeadPush()
-{
- const int head_used = FindModifiedHead(HEAD_IP);
- StackPush(GetHead(head_used).GetPosition());
- if (head_used == HEAD_IP) {
- GetHead(head_used).Set(GetHead(HEAD_FLOW));
- advance_ip = false;
- }
- return true;
-}
-
-
-bool cHardwareCPU::Inst_PopA() { Register(REG_AX) = StackPop(); return true;}
-bool cHardwareCPU::Inst_PopB() { Register(REG_BX) = StackPop(); return true;}
-bool cHardwareCPU::Inst_PopC() { Register(REG_CX) = StackPop(); return true;}
-
-bool cHardwareCPU::Inst_PushA() { StackPush(Register(REG_AX)); return true;}
-bool cHardwareCPU::Inst_PushB() { StackPush(Register(REG_BX)); return true;}
-bool cHardwareCPU::Inst_PushC() { StackPush(Register(REG_CX)); return true;}
-
-bool cHardwareCPU::Inst_SwitchStack() { SwitchStack(); return true;}
-bool cHardwareCPU::Inst_FlipStack() { StackFlip(); return true;}
-
-bool cHardwareCPU::Inst_Swap()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int other_reg = FindComplementRegister(reg_used);
-// cout << endl;
-// cout << "Regs 1, 2, 3 are: " << Register(1) << " " << Register(2) << " " << Register(3) << endl;
-// cout << "Modified reg = " << reg_used << ", Complement reg = " << other_reg << endl;
-// cout << "Calling Swap with " << Register(reg_used) << " and " << Register(other_reg) << endl;
- nFunctions::Swap(Register(reg_used), Register(other_reg));
-// cout << "Current State is " << Register(reg_used) << " and " << Register(other_reg) << endl;
-// cout << "Regs 1, 2, 3 are: " << Register(1) << " " << Register(2) << " " << Register(3) << endl;
- return true;
-}
-
-bool cHardwareCPU::Inst_SwapAB() { nFunctions::Swap(Register(REG_AX), Register(REG_BX)); return true; }
-bool cHardwareCPU::Inst_SwapBC() { nFunctions::Swap(Register(REG_BX), Register(REG_CX)); return true; }
-bool cHardwareCPU::Inst_SwapAC() { nFunctions::Swap(Register(REG_AX), Register(REG_CX)); return true; }
-
-bool cHardwareCPU::Inst_CopyReg()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int other_reg = FindComplementRegister(reg_used);
- Register(other_reg) = Register(reg_used);
- return true;
-}
-
-bool cHardwareCPU::Inst_CopyRegAB() { Register(REG_AX) = Register(REG_BX); return true;
-}
-bool cHardwareCPU::Inst_CopyRegAC() { Register(REG_AX) = Register(REG_CX); return true;
-}
-bool cHardwareCPU::Inst_CopyRegBA() { Register(REG_BX) = Register(REG_AX); return true;
-}
-bool cHardwareCPU::Inst_CopyRegBC() { Register(REG_BX) = Register(REG_CX); return true;
-}
-bool cHardwareCPU::Inst_CopyRegCA() { Register(REG_CX) = Register(REG_AX); return true;
-}
-bool cHardwareCPU::Inst_CopyRegCB() { Register(REG_CX) = Register(REG_BX); return true;
-}
-
-bool cHardwareCPU::Inst_Reset()
-{
- Register(REG_AX) = 0;
- Register(REG_BX) = 0;
- Register(REG_CX) = 0;
- StackClear();
- return true;
-}
-
-bool cHardwareCPU::Inst_ShiftR()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) >>= 1;
- return true;
-}
-
-bool cHardwareCPU::Inst_ShiftL()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) <<= 1;
- return true;
-}
-
-bool cHardwareCPU::Inst_Bit1()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) |= 1;
- return true;
-}
-
-bool cHardwareCPU::Inst_SetNum()
-{
- ReadLabel();
- Register(REG_BX) = GetLabel().AsInt(NUM_NOPS);
- return true;
-}
-
-bool cHardwareCPU::Inst_ValGrey(void) {
- ReadLabel();
- Register(REG_BX) = GetLabel().AsIntGreyCode(NUM_NOPS);
- return true;
-}
-
-bool cHardwareCPU::Inst_ValDir(void) {
- ReadLabel();
- Register(REG_BX) = GetLabel().AsIntDirect(NUM_NOPS);
- return true;
-}
-
-bool cHardwareCPU::Inst_ValAddP(void) {
- ReadLabel();
- Register(REG_BX) = GetLabel().AsIntAdditivePolynomial(NUM_NOPS);
- return true;
-}
-
-bool cHardwareCPU::Inst_ValFib(void) {
- ReadLabel();
- Register(REG_BX) = GetLabel().AsIntFib(NUM_NOPS);
- return true;
-}
-
-bool cHardwareCPU::Inst_ValPolyC(void) {
- ReadLabel();
- Register(REG_BX) = GetLabel().AsIntPolynomialCoefficent(NUM_NOPS);
- return true;
-}
-
-bool cHardwareCPU::Inst_Inc()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) += 1;
- return true;
-}
-
-bool cHardwareCPU::Inst_Dec()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) -= 1;
- return true;
-}
-
-bool cHardwareCPU::Inst_Zero()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = 0;
- return true;
-}
-
-bool cHardwareCPU::Inst_Neg()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = 0-Register(reg_used);
- return true;
-}
-
-bool cHardwareCPU::Inst_Square()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = Register(reg_used) * Register(reg_used);
- return true;
-}
-
-bool cHardwareCPU::Inst_Sqrt()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int value = Register(reg_used);
- if (value > 1) Register(reg_used) = (int) sqrt((double) value);
- else if (value < 0) {
- Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "sqrt: value is negative");
- return false;
- }
- return true;
-}
-
-bool cHardwareCPU::Inst_Log()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int value = Register(reg_used);
- if (value >= 1) Register(reg_used) = (int) log((double) value);
- else if (value < 0) {
- Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "log: value is negative");
- return false;
- }
- return true;
-}
-
-bool cHardwareCPU::Inst_Log10()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int value = Register(reg_used);
- if (value >= 1) Register(reg_used) = (int) log10((double) value);
- else if (value < 0) {
- Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "log10: value is negative");
- return false;
- }
- return true;
-}
-
-bool cHardwareCPU::Inst_Minus17()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) -= 17;
- return true;
-}
-
-bool cHardwareCPU::Inst_Add()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = Register(REG_BX) + Register(REG_CX);
- return true;
-}
-
-bool cHardwareCPU::Inst_Sub()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = Register(REG_BX) - Register(REG_CX);
- return true;
-}
-
-bool cHardwareCPU::Inst_Mult()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = Register(REG_BX) * Register(REG_CX);
- return true;
-}
-
-bool cHardwareCPU::Inst_Div()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- if (Register(REG_CX) != 0) {
- if (0-INT_MAX > Register(REG_BX) && Register(REG_CX) == -1)
- Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: Float exception");
- else
- Register(reg_used) = Register(REG_BX) / Register(REG_CX);
- } else {
- Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: dividing by 0");
- return false;
- }
- return true;
-}
-
-bool cHardwareCPU::Inst_Mod()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- if (Register(REG_CX) != 0) {
- Register(reg_used) = Register(REG_BX) % Register(REG_CX);
- } else {
- Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "mod: modding by 0");
- return false;
- }
- return true;
-}
-
-
-bool cHardwareCPU::Inst_Nand()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = ~(Register(REG_BX) & Register(REG_CX));
- return true;
-}
-
-bool cHardwareCPU::Inst_Nor()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = ~(Register(REG_BX) | Register(REG_CX));
- return true;
-}
-
-bool cHardwareCPU::Inst_And()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = (Register(REG_BX) & Register(REG_CX));
- return true;
-}
-
-bool cHardwareCPU::Inst_Not()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = ~(Register(reg_used));
- return true;
-}
-
-bool cHardwareCPU::Inst_Order()
-{
- if (Register(REG_BX) > Register(REG_CX)) {
- nFunctions::Swap(Register(REG_BX), Register(REG_CX));
- }
- return true;
-}
-
-bool cHardwareCPU::Inst_Xor()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = Register(REG_BX) ^ Register(REG_CX);
- return true;
-}
-
-bool cHardwareCPU::Inst_Copy()
-{
- const cHeadCPU from(this, Register(REG_BX));
- cHeadCPU to(this, Register(REG_AX) + Register(REG_BX));
- sCPUStats & cpu_stats = organism->CPUStats();
-
- if (organism->TestCopyMut()) {
- to.SetInst(GetRandomInst());
- to.FlagMutated() = true; // Mark this instruction as mutated...
- to.FlagCopyMut() = true; // Mark this instruction as copy mut...
- //organism->GetPhenotype().IsMutated() = true;
- cpu_stats.mut_stats.copy_mut_count++;
- } else {
- to.SetInst(from.GetInst());
- to.FlagMutated() = false; // UnMark
- to.FlagCopyMut() = false; // UnMark
- }
-
- to.FlagCopied() = true; // Set the copied flag.
- cpu_stats.mut_stats.copies_exec++;
- return true;
-}
-
-bool cHardwareCPU::Inst_ReadInst()
-{
- const int reg_used = FindModifiedRegister(REG_CX);
- const cHeadCPU from(this, Register(REG_BX));
-
- // Dis-allowing mutations on read, for the moment (write only...)
- // @CAO This allows perfect error-correction...
- Register(reg_used) = from.GetInst().GetOp();
- return true;
-}
-
-bool cHardwareCPU::Inst_WriteInst()
-{
- cHeadCPU to(this, Register(REG_AX) + Register(REG_BX));
- const int reg_used = FindModifiedRegister(REG_CX);
- const int value = Mod(Register(reg_used), GetNumInst());
- sCPUStats & cpu_stats = organism->CPUStats();
-
- // Change value on a mutation...
- if (organism->TestCopyMut()) {
- to.SetInst(GetRandomInst());
- to.FlagMutated() = true; // Mark this instruction as mutated...
- to.FlagCopyMut() = true; // Mark this instruction as copy mut...
- //organism->GetPhenotype().IsMutated() = true;
- cpu_stats.mut_stats.copy_mut_count++;
- } else {
- to.SetInst(cInstruction(value));
- to.FlagMutated() = false; // UnMark
- to.FlagCopyMut() = false; // UnMark
- }
-
- to.FlagCopied() = true; // Set the copied flag.
- cpu_stats.mut_stats.copies_exec++;
- return true;
-}
-
-bool cHardwareCPU::Inst_StackReadInst()
-{
- const int reg_used = FindModifiedRegister(REG_CX);
- cHeadCPU from(this, Register(reg_used));
- StackPush(from.GetInst().GetOp());
- return true;
-}
-
-bool cHardwareCPU::Inst_StackWriteInst()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- cHeadCPU to(this, Register(REG_AX) + Register(reg_used));
- const int value = Mod(StackPop(), GetNumInst());
- sCPUStats & cpu_stats = organism->CPUStats();
-
- // Change value on a mutation...
- if (organism->TestCopyMut()) {
- to.SetInst(GetRandomInst());
- to.FlagMutated() = true; // Mark this instruction as mutated...
- to.FlagCopyMut() = true; // Mark this instruction as copy mut...
- //organism->GetPhenotype().IsMutated() = true;
- cpu_stats.mut_stats.copy_mut_count++;
- } else {
- to.SetInst(cInstruction(value));
- to.FlagMutated() = false; // UnMark
- to.FlagCopyMut() = false; // UnMark
- }
-
- to.FlagCopied() = true; // Set the copied flag.
- cpu_stats.mut_stats.copies_exec++;
- return true;
-}
-
-bool cHardwareCPU::Inst_Compare()
-{
- const int reg_used = FindModifiedRegister(REG_CX);
- cHeadCPU from(this, Register(REG_BX));
- cHeadCPU to(this, Register(REG_AX) + Register(REG_BX));
-
- // Compare is dangerous -- it can cause mutations!
- if (organism->TestCopyMut()) {
- to.SetInst(GetRandomInst());
- to.FlagMutated() = true; // Mark this instruction as mutated...
- to.FlagCopyMut() = true; // Mark this instruction as copy mut...
- //organism->GetPhenotype().IsMutated() = true;
- }
-
- Register(reg_used) = from.GetInst().GetOp() - to.GetInst().GetOp();
-
- return true;
-}
-
-bool cHardwareCPU::Inst_IfNCpy()
-{
- const cHeadCPU from(this, Register(REG_BX));
- const cHeadCPU to(this, Register(REG_AX) + Register(REG_BX));
-
- // Allow for errors in this test...
- if (organism->TestCopyMut()) {
- if (from.GetInst() != to.GetInst()) IP().Advance();
- } else {
- if (from.GetInst() == to.GetInst()) IP().Advance();
- }
- return true;
-}
-
-bool cHardwareCPU::Inst_Allocate() // Allocate bx more space...
-{
- const int size = GetMemory().GetSize();
- if( Allocate_Main(Register(REG_BX)) ) {
- Register(REG_AX) = size;
- return true;
- } else return false;
-}
-
-bool cHardwareCPU::Inst_Divide()
-{
- return Divide_Main(Register(REG_AX));
-}
-
-bool cHardwareCPU::Inst_CDivide()
-{
- return Divide_Main(GetMemory().GetSize() / 2);
-}
-
-bool cHardwareCPU::Inst_CAlloc()
-{
- return Allocate_Main(GetMemory().GetSize());
-}
-
-bool cHardwareCPU::Inst_MaxAlloc() // Allocate maximal more
-{
- const int cur_size = GetMemory().GetSize();
- const int alloc_size = Min((int) (cConfig::GetChildSizeRange() * cur_size),
- MAX_CREATURE_SIZE - cur_size);
- if( Allocate_Main(alloc_size) ) {
- Register(REG_AX) = cur_size;
- return true;
- } else return false;
-}
-
-
-bool cHardwareCPU::Inst_Repro()
-{
- // Setup child
- cCPUMemory & child_genome = organism->ChildGenome();
- child_genome = GetMemory();
- organism->GetPhenotype().SetLinesCopied(GetMemory().GetSize());
-
- int lines_executed = 0;
- for ( int i = 0; i < GetMemory().GetSize(); i++ ) {
- if ( GetMemory().FlagExecuted(i) == true ) lines_executed++;
- }
- organism->GetPhenotype().SetLinesExecuted(lines_executed);
-
- // Perform Copy Mutations...
- if (organism->GetCopyMutProb() > 0) { // Skip this if no mutations....
- for (int i = 0; i < GetMemory().GetSize(); i++) {
- if (organism->TestCopyMut()) {
- child_genome[i]=GetRandomInst();
- //organism->GetPhenotype().IsMutated() = true;
- }
- }
- }
- Divide_DoMutations();
-
- // 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
-
- if (cConfig::GetDivideMethod() == DIVIDE_METHOD_SPLIT) advance_ip = false;
-
- organism->ActivateDivide();
-
- return true;
-}
-
-
-bool cHardwareCPU::Inst_Kazi()
-{
- const int reg_used = FindModifiedRegister(REG_AX);
- int percentProb = Register(reg_used) % 100;
- int random = abs(rand()) % 100;
- if (random >= percentProb)
- {
- return true;
- }
- else
- {
- organism->Kaboom();
- return true;
- }
-}
-
-bool cHardwareCPU::Inst_Die()
-{
- const double die_prob = cConfig::GetDieProb();
- if(g_random.GetDouble() < die_prob) { organism->Die(); }
- 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 cHardwareCPU::Inst_Inject()
-{
- AdjustHeads();
- const int start_pos = GetHead(HEAD_READ).GetPosition();
- const int end_pos = GetHead(HEAD_WRITE).GetPosition();
- const int inject_size = end_pos - start_pos;
-
- // Make sure the creature will still be above the minimum size,
- if (inject_size <= 0) {
- Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
- return false; // (inject fails)
- }
- if (start_pos < MIN_CREATURE_SIZE) {
- Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
- return false; // (inject fails)
- }
-
- // Since its legal to cut out the injected piece, do so.
- cGenome inject_code( cGenomeUtil::Crop(GetMemory(), start_pos, end_pos) );
- GetMemory().Remove(start_pos, inject_size);
-
- // If we don't have a host, stop here.
- cOrganism * host_organism = organism->GetNeighbor();
- if (host_organism == NULL) return false;
-
- // Scan for the label to match...
- ReadLabel();
-
- // If there is no label, abort.
- if (GetLabel().GetSize() == 0) {
- Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: label required");
- return false; // (inject fails)
- }
-
- // Search for the label in the host...
- GetLabel().Rotate(1, NUM_NOPS);
-
- const bool inject_signal = host_organism->GetHardware().InjectHost(GetLabel(), inject_code);
- if (inject_signal) {
- Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: host too large.");
- return false; // Inject failed.
- }
-
- // Set the relevent flags.
- organism->GetPhenotype().IsModifier() = true;
-
- return inject_signal;
-}
-
-
-bool cHardwareCPU::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;
-}
-
-// 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 cHardwareCPU::Inst_InjectThread()
-{
- AdjustHeads();
- const int start_pos = GetHead(HEAD_READ).GetPosition();
- const int end_pos = GetHead(HEAD_WRITE).GetPosition();
- const int inject_size = end_pos - start_pos;
-
- // Make sure the creature will still be above the minimum size,
- if (inject_size <= 0) {
- Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
- return false; // (inject fails)
- }
- if (start_pos < MIN_CREATURE_SIZE) {
- Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: new size too small");
- return false; // (inject fails)
- }
-
- // Since its legal to cut out the injected piece, do so.
- cGenome inject_code( cGenomeUtil::Crop(GetMemory(), start_pos, end_pos) );
- GetMemory().Remove(start_pos, inject_size);
-
- // If we don't have a host, stop here.
- cOrganism * host_organism = organism->GetNeighbor();
- if (host_organism == NULL) return false;
-
- // Scan for the label to match...
- ReadLabel();
-
- // If there is no label, abort.
- if (GetLabel().GetSize() == 0) {
- Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: label required");
- return false; // (inject fails)
- }
-
- // Search for the label in the host...
- GetLabel().Rotate(1, NUM_NOPS);
-
- const int inject_signal =
- host_organism->GetHardware().InjectThread(GetLabel(), inject_code);
- if (inject_signal == 1) {
- Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: host too large.");
- return false; // Inject failed.
- }
- if (inject_signal == 2) {
- Fault(FAULT_LOC_INJECT, FAULT_TYPE_WARNING, "inject: target not in host.");
- return false; // Inject failed.
- }
-
- // Set the relevent flags.
- organism->GetPhenotype().IsModifier() = true;
-
- return true;
-}
-
-bool cHardwareCPU::Inst_TaskGet()
-{
- const int reg_used = FindModifiedRegister(REG_CX);
- const int value = organism->GetNextInput();
- Register(reg_used) = value;
- organism->DoInput(value);
- return true;
-}
-
-bool cHardwareCPU::Inst_TaskStackGet()
-{
- const int value = organism->GetNextInput();
- StackPush(value);
- organism->DoInput(value);
- return true;
-}
-
-bool cHardwareCPU::Inst_TaskStackLoad()
-{
- for (int i = 0; i < IO_SIZE; i++)
- StackPush( organism->GetNextInput() );
- return true;
-}
-
-bool cHardwareCPU::Inst_TaskPut()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int value = Register(reg_used);
- Register(reg_used) = 0;
- organism->DoOutput(value);
- return true;
-}
-
-bool cHardwareCPU::Inst_TaskIO()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
-
- // Do the "put" component
- const int value_out = Register(reg_used);
- organism->DoOutput(value_out); // Check for tasks compleated.
-
- // Do the "get" component
- const int value_in = organism->GetNextInput();
- Register(reg_used) = value_in;
- organism->DoInput(value_in);
- return true;
-}
-
-bool cHardwareCPU::Inst_Send()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- organism->SendValue(Register(reg_used));
- Register(reg_used) = 0;
- return true;
-}
-
-bool cHardwareCPU::Inst_Receive()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = organism->ReceiveValue();
- return true;
-}
-
-bool cHardwareCPU::Inst_Sense()
-{
- const tArray<double> & res_count = organism->PopInterface().GetResources();
- const int reg_used = FindModifiedRegister(REG_BX);
-
- // If there are no resources to measure, this instruction fails.
- if (res_count.GetSize() == 0) return false;
-
- // Always get the first resource, and convert it to and int.
- Register(reg_used) = (int) res_count[0];
-
- // @CAO Since resources are sometimes less than one, perhaps we should
- // multiply it by some constant? Or perhaps taking the log would be more
- // useful so they can easily scan across orders of magnitude?
-
- return true;
-}
-
-void cHardwareCPU::DoDonate(cOrganism * to_org)
-{
- assert(to_org != NULL);
-
- const double merit_given = cConfig::GetMeritGiven();
- const double merit_received = cConfig::GetMeritReceived();
-
- double cur_merit = organism->GetPhenotype().GetMerit().GetDouble();
- cur_merit -= merit_given;
-
- // Plug the current merit back into this organism and notify the scheduler.
- organism->UpdateMerit(cur_merit);
-
- // Update the merit of the organism being donated to...
- double other_merit = to_org->GetPhenotype().GetMerit().GetDouble();
- other_merit += merit_received;
- to_org->UpdateMerit(other_merit);
-}
-
-bool cHardwareCPU::Inst_DonateRandom()
-{
- organism->GetPhenotype().IncDonates();
- if (organism->GetPhenotype().GetCurNumDonates() > cConfig::GetMaxDonates()) {
- return false;
- }
-
- // Turn to a random neighbor, get it, and turn back...
- int neighbor_id = g_random.GetInt(organism->GetNeighborhoodSize());
- for (int i = 0; i < neighbor_id; i++) organism->Rotate(1);
- cOrganism * neighbor = organism->GetNeighbor();
- for (int i = 0; i < neighbor_id; i++) organism->Rotate(-1);
-
- // Donate only if we have found a neighbor.
- if (neighbor != NULL) DoDonate(neighbor);
-
- return true;
-}
-
-
-bool cHardwareCPU::Inst_DonateKin()
-{
- organism->GetPhenotype().IncDonates();
- if (organism->GetPhenotype().GetCurNumDonates() > cConfig::GetMaxDonates()) {
- return false;
- }
-
- // Find the target as the first Kin found in the neighborhood.
- const int num_neighbors = organism->GetNeighborhoodSize();
-
- // Turn to face a random neighbor
- int neighbor_id = g_random.GetInt(num_neighbors);
- for (int i = 0; i < neighbor_id; i++) organism->Rotate(1);
- cOrganism * neighbor = organism->GetNeighbor();
-
- // If there is no max distance, just take the random neighbor we're facing.
- const int max_dist = cConfig::GetMaxDonateKinDistance();
- if (max_dist != -1) {
- int max_id = neighbor_id + num_neighbors;
- bool found = false;
- cGenotype * genotype = organism->GetGenotype();
- while (neighbor_id < max_id) {
- neighbor = organism->GetNeighbor();
- if (neighbor != NULL &&
- genotype->GetPhyloDistance(neighbor->GetGenotype()) <= max_dist) {
- found = true;
- break;
- }
- organism->Rotate(1);
- neighbor_id++;
- }
- if (found == false) neighbor = NULL;
- }
-
- // Put the facing back where it was.
- for (int i = 0; i < neighbor_id; i++) organism->Rotate(-1);
-
- // Donate only if we have found a close enough relative...
- if (neighbor != NULL) DoDonate(neighbor);
-
- return true;
-}
-
-bool cHardwareCPU::Inst_DonateEditDist()
-{
- organism->GetPhenotype().IncDonates();
- if (organism->GetPhenotype().GetCurNumDonates() > cConfig::GetMaxDonates()) {
- return false;
- }
-
- // Find the target as the first Kin found in the neighborhood.
- const int num_neighbors = organism->GetNeighborhoodSize();
-
- // Turn to face a random neighbor
- int neighbor_id = g_random.GetInt(num_neighbors);
- for (int i = 0; i < neighbor_id; i++) organism->Rotate(1);
- cOrganism * neighbor = organism->GetNeighbor();
-
- // If there is no max edit distance, take the random neighbor we're facing.
- const int max_dist = cConfig::GetMaxDonateEditDistance();
- if (max_dist != -1) {
- int max_id = neighbor_id + num_neighbors;
- bool found = false;
- while (neighbor_id < max_id) {
- neighbor = organism->GetNeighbor();
- int edit_dist = max_dist + 1;
- if (neighbor != NULL) {
- edit_dist = cGenomeUtil::FindEditDistance(organism->GetGenome(),
- neighbor->GetGenome());
- }
- if (edit_dist <= max_dist) {
- found = true;
- break;
- }
- organism->Rotate(1);
- neighbor_id++;
- }
- if (found == false) neighbor = NULL;
- }
-
- // Put the facing back where it was.
- for (int i = 0; i < neighbor_id; i++) organism->Rotate(-1);
-
- // Donate only if we have found a close enough relative...
- if (neighbor != NULL) DoDonate(neighbor);
-
- return true;
-}
-
-
-bool cHardwareCPU::Inst_DonateNULL()
-{
- organism->GetPhenotype().IncDonates();
- if (organism->GetPhenotype().GetCurNumDonates() > cConfig::GetMaxDonates()) {
- return false;
- }
-
- // This is a fake donate command that causes the organism to lose merit,
- // but no one else to gain any.
-
- const double merit_given = cConfig::GetMeritGiven();
- double cur_merit = organism->GetPhenotype().GetMerit().GetDouble();
- cur_merit -= merit_given;
-
- // Plug the current merit back into this organism and notify the scheduler.
- organism->UpdateMerit(cur_merit);
-
- return true;
-}
-
-
-bool cHardwareCPU::Inst_SearchF()
-{
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
- const int search_size = FindLabel(1).GetPosition() - IP().GetPosition();
- Register(REG_BX) = search_size;
- Register(REG_CX) = GetLabel().GetSize();
- return true;
-}
-
-bool cHardwareCPU::Inst_SearchB()
-{
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
- const int search_size = IP().GetPosition() - FindLabel(-1).GetPosition();
- Register(REG_BX) = search_size;
- Register(REG_CX) = GetLabel().GetSize();
- return true;
-}
-
-bool cHardwareCPU::Inst_MemSize()
-{
- Register(FindModifiedRegister(REG_BX)) = GetMemory().GetSize();
- return true;
-}
-
-
-bool cHardwareCPU::Inst_RotateL()
-{
- const int num_neighbors = organism->GetNeighborhoodSize();
-
- // If this organism has no neighbors, ignore rotate.
- if (num_neighbors == 0) return false;
-
- ReadLabel();
-
- // Always rotate at least once.
- organism->Rotate(-1);
-
- // If there is no label, then the one rotation was all we want.
- if (!GetLabel().GetSize()) return true;
-
- // Rotate until a complement label is found (or all have been checked).
- GetLabel().Rotate(1, NUM_NOPS);
- for (int i = 1; i < num_neighbors; i++) {
- cOrganism * neighbor = organism->GetNeighbor();
-
- // Assuming we have a neighbor and it is of the same hardware type,
- // search for the label in it.
- if (neighbor != NULL &&
- neighbor->GetHardware().GetType() == GetType()) {
-
- // If this facing has the full label, stop here.
- cHardwareCPU & cur_hardware = (cHardwareCPU &) neighbor->GetHardware();
- if (cur_hardware.FindFullLabel( GetLabel() ).InMemory()) return true;
- }
-
- // Otherwise keep rotating...
- organism->Rotate(-1);
- }
- return true;
-}
-
-bool cHardwareCPU::Inst_RotateR()
-{
- const int num_neighbors = organism->GetNeighborhoodSize();
-
- // If this organism has no neighbors, ignore rotate.
- if (num_neighbors == 0) return false;
-
- ReadLabel();
-
- // Always rotate at least once.
- organism->Rotate(-1);
-
- // If there is no label, then the one rotation was all we want.
- if (!GetLabel().GetSize()) return true;
-
- // Rotate until a complement label is found (or all have been checked).
- GetLabel().Rotate(1, NUM_NOPS);
- for (int i = 1; i < num_neighbors; i++) {
- cOrganism * neighbor = organism->GetNeighbor();
-
- // Assuming we have a neighbor and it is of the same hardware type,
- // search for the label in it.
- if (neighbor != NULL &&
- neighbor->GetHardware().GetType() == GetType()) {
-
- // If this facing has the full label, stop here.
- cHardwareCPU & cur_hardware = (cHardwareCPU &) neighbor->GetHardware();
- if (cur_hardware.FindFullLabel( GetLabel() ).InMemory()) return true;
- }
-
- // Otherwise keep rotating...
- organism->Rotate(1);
- }
- return true;
-}
-
-bool cHardwareCPU::Inst_SetCopyMut()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const int new_mut_rate = Max( Register(reg_used), 1 );
- organism->SetCopyMutProb(((double) new_mut_rate) / 10000.0);
- return true;
-}
-
-bool cHardwareCPU::Inst_ModCopyMut()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- const double new_mut_rate = organism->GetCopyMutProb() +
- ((double) Register(reg_used)) / 10000.0;
- if (new_mut_rate > 0.0) organism->SetCopyMutProb(new_mut_rate);
- return true;
-}
-
-
-// Multi-threading.
-
-bool cHardwareCPU::Inst_ForkThread()
-{
- IP().Advance();
- if (!ForkThread()) Fault(FAULT_LOC_THREAD_FORK, FAULT_TYPE_FORK_TH);
- return true;
-}
-
-bool cHardwareCPU::Inst_KillThread()
-{
- if (!KillThread()) Fault(FAULT_LOC_THREAD_KILL, FAULT_TYPE_KILL_TH);
- else advance_ip = false;
- return true;
-}
-
-bool cHardwareCPU::Inst_ThreadID()
-{
- const int reg_used = FindModifiedRegister(REG_BX);
- Register(reg_used) = GetCurThreadID();
- return true;
-}
-
-
-// Head-based instructions
-
-bool cHardwareCPU::Inst_SetHead()
-{
- const int head_used = FindModifiedHead(HEAD_IP);
- SetActiveHead(head_used);
- return true;
-}
-
-bool cHardwareCPU::Inst_AdvanceHead()
-{
- const int head_used = FindModifiedHead(HEAD_WRITE);
- GetHead(head_used).Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_MoveHead()
-{
- const int head_used = FindModifiedHead(HEAD_IP);
- GetHead(head_used).Set(GetHead(HEAD_FLOW));
- if (head_used == HEAD_IP) advance_ip = false;
- return true;
-}
-
-bool cHardwareCPU::Inst_JumpHead()
-{
- const int head_used = FindModifiedHead(HEAD_IP);
- GetHead(head_used).Jump( Register(REG_CX) );
- return true;
-}
-
-bool cHardwareCPU::Inst_GetHead()
-{
- const int head_used = FindModifiedHead(HEAD_IP);
- Register(REG_CX) = GetHead(head_used).GetPosition();
- return true;
-}
-
-bool cHardwareCPU::Inst_IfLabel()
-{
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
- if (GetLabel() != GetReadLabel()) IP().Advance();
- return true;
-}
-
-// This is a variation on IfLabel that will skip the next command if the "if"
-// is false, but it will also skip all nops following that command.
-bool cHardwareCPU::Inst_IfLabel2()
-{
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
- if (GetLabel() != GetReadLabel()) {
- IP().Advance();
- if (inst_set->IsNop( IP().GetNextInst() )) IP().Advance();
- }
- return true;
-}
-
-bool cHardwareCPU::Inst_HeadDivideMut(double mut_multiplier)
-{
- AdjustHeads();
- const int divide_pos = GetHead(HEAD_READ).GetPosition();
- int child_end = GetHead(HEAD_WRITE).GetPosition();
- if (child_end == 0) child_end = GetMemory().GetSize();
- const int extra_lines = GetMemory().GetSize() - child_end;
- bool ret_val = Divide_Main(divide_pos, extra_lines, mut_multiplier);
- // Re-adjust heads.
- AdjustHeads();
- return ret_val;
-}
-
-bool cHardwareCPU::Inst_HeadDivide()
-{
- return Inst_HeadDivideMut(1);
-}
-
-bool cHardwareCPU::Inst_HeadDivideSex()
-{
- organism->GetPhenotype().SetDivideSex(true);
- organism->GetPhenotype().SetCrossNum(1);
- return Inst_HeadDivide();
-}
-
-bool cHardwareCPU::Inst_HeadDivideAsex()
-{
- organism->GetPhenotype().SetDivideSex(false);
- organism->GetPhenotype().SetCrossNum(0);
- return Inst_HeadDivide();
-}
-
-bool cHardwareCPU::Inst_HeadDivideAsexWait()
-{
- organism->GetPhenotype().SetDivideSex(true);
- organism->GetPhenotype().SetCrossNum(0);
- return Inst_HeadDivide();
-}
-
-bool cHardwareCPU::Inst_HeadDivideMateSelect()
-{
- // Take the label that follows this divide and use it as the ID for which
- // other organisms this one is willing to mate with.
- ReadLabel();
- organism->GetPhenotype().SetMateSelectID( GetLabel().AsInt(NUM_NOPS) );
-
-// int mate_id = GetLabel().AsInt(NUM_NOPS);
-// if (mate_id > 0) cout << mate_id << " "
-// << GetLabel().AsString() << endl;
-
- // Proceed as normal with the rest of mate selection.
- organism->GetPhenotype().SetDivideSex(true);
- organism->GetPhenotype().SetCrossNum(1);
- return Inst_HeadDivide();
-}
-
-bool cHardwareCPU::Inst_HeadDivide1() { return Inst_HeadDivideMut(1); }
-bool cHardwareCPU::Inst_HeadDivide2() { return Inst_HeadDivideMut(2); }
-bool cHardwareCPU::Inst_HeadDivide3() { return Inst_HeadDivideMut(3); }
-bool cHardwareCPU::Inst_HeadDivide4() { return Inst_HeadDivideMut(4); }
-bool cHardwareCPU::Inst_HeadDivide5() { return Inst_HeadDivideMut(5); }
-bool cHardwareCPU::Inst_HeadDivide6() { return Inst_HeadDivideMut(6); }
-bool cHardwareCPU::Inst_HeadDivide7() { return Inst_HeadDivideMut(7); }
-bool cHardwareCPU::Inst_HeadDivide8() { return Inst_HeadDivideMut(8); }
-bool cHardwareCPU::Inst_HeadDivide9() { return Inst_HeadDivideMut(9); }
-bool cHardwareCPU::Inst_HeadDivide10() { return Inst_HeadDivideMut(10); }
-bool cHardwareCPU::Inst_HeadDivide16() { return Inst_HeadDivideMut(16); }
-bool cHardwareCPU::Inst_HeadDivide32() { return Inst_HeadDivideMut(32); }
-bool cHardwareCPU::Inst_HeadDivide50() { return Inst_HeadDivideMut(50); }
-bool cHardwareCPU::Inst_HeadDivide100() { return Inst_HeadDivideMut(100); }
-bool cHardwareCPU::Inst_HeadDivide500() { return Inst_HeadDivideMut(500); }
-bool cHardwareCPU::Inst_HeadDivide1000() { return Inst_HeadDivideMut(1000); }
-bool cHardwareCPU::Inst_HeadDivide5000() { return Inst_HeadDivideMut(5000); }
-bool cHardwareCPU::Inst_HeadDivide10000() { return Inst_HeadDivideMut(10000); }
-bool cHardwareCPU::Inst_HeadDivide50000() { return Inst_HeadDivideMut(50000); }
-bool cHardwareCPU::Inst_HeadDivide0_5() { return Inst_HeadDivideMut(0.5); }
-bool cHardwareCPU::Inst_HeadDivide0_1() { return Inst_HeadDivideMut(0.1); }
-bool cHardwareCPU::Inst_HeadDivide0_05() { return Inst_HeadDivideMut(0.05); }
-bool cHardwareCPU::Inst_HeadDivide0_01() { return Inst_HeadDivideMut(0.01); }
-bool cHardwareCPU::Inst_HeadDivide0_001() { return Inst_HeadDivideMut(0.001); }
-
-bool cHardwareCPU::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();
- }
- Register(REG_BX) = read_inst;
- ReadInst(read_inst);
-
- cpu_stats.mut_stats.copies_exec++; // @CAO, this too..
- GetHead(head_id).Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_HeadWrite()
-{
- const int head_id = FindModifiedHead(HEAD_WRITE);
- cHeadCPU & active_head = GetHead(head_id);
-
- active_head.Adjust();
-
- int value = Register(REG_BX);
- 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 cHardwareCPU::Inst_HeadCopy()
-{
- // For the moment, this cannot be nop-modified.
- cHeadCPU & read_head = GetHead(HEAD_READ);
- cHeadCPU & 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();
- ReadInst(read_inst.GetOp());
- 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;
- }
-
- 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;
-}
-
-bool cHardwareCPU::HeadCopy_ErrorCorrect(double reduction)
-{
- // For the moment, this cannot be nop-modified.
- cHeadCPU & read_head = GetHead(HEAD_READ);
- cHeadCPU & write_head = GetHead(HEAD_WRITE);
- sCPUStats & cpu_stats = organism->CPUStats();
-
- read_head.Adjust();
- write_head.Adjust();
-
- // Do mutations.
- cInstruction read_inst = read_head.GetInst();
- ReadInst(read_inst.GetOp());
- if ( g_random.P(organism->GetCopyMutProb() / reduction) ) {
- read_inst = GetRandomInst();
- cpu_stats.mut_stats.copy_mut_count++;
- write_head.FlagMutated() = true;
- write_head.FlagCopyMut() = true;
- //organism->GetPhenotype().IsMutated() = true;
- }
-
- cpu_stats.mut_stats.copies_exec++;
-
- write_head.SetInst(read_inst);
- write_head.FlagCopied() = true; // Set the copied flag...
-
- read_head.Advance();
- write_head.Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_HeadCopy2() { return HeadCopy_ErrorCorrect(2); }
-bool cHardwareCPU::Inst_HeadCopy3() { return HeadCopy_ErrorCorrect(3); }
-bool cHardwareCPU::Inst_HeadCopy4() { return HeadCopy_ErrorCorrect(4); }
-bool cHardwareCPU::Inst_HeadCopy5() { return HeadCopy_ErrorCorrect(5); }
-bool cHardwareCPU::Inst_HeadCopy6() { return HeadCopy_ErrorCorrect(6); }
-bool cHardwareCPU::Inst_HeadCopy7() { return HeadCopy_ErrorCorrect(7); }
-bool cHardwareCPU::Inst_HeadCopy8() { return HeadCopy_ErrorCorrect(8); }
-bool cHardwareCPU::Inst_HeadCopy9() { return HeadCopy_ErrorCorrect(9); }
-bool cHardwareCPU::Inst_HeadCopy10() { return HeadCopy_ErrorCorrect(10); }
-
-bool cHardwareCPU::Inst_HeadSearch()
-{
- ReadLabel();
- GetLabel().Rotate(1, NUM_NOPS);
- cHeadCPU found_pos = FindLabel(0);
- const int search_size = found_pos.GetPosition() - IP().GetPosition();
- Register(REG_BX) = search_size;
- Register(REG_CX) = GetLabel().GetSize();
- GetHead(HEAD_FLOW).Set(found_pos);
- GetHead(HEAD_FLOW).Advance();
- return true;
-}
-
-bool cHardwareCPU::Inst_SetFlow()
-{
- const int reg_used = FindModifiedRegister(REG_CX);
- GetHead(HEAD_FLOW).Set(Register(reg_used), this);
- return true;
-}
-
-// Direct Matching Templates
-
-bool cHardwareCPU::Inst_DMJumpF()
-{
- ReadLabel();
-
- // If there is no label, jump BX steps.
- if (GetLabel().GetSize() == 0) {
- IP().Jump(Register(REG_BX));
- return true;
- }
-
- // Otherwise, jump to the label.
- cHeadCPU jump_location(FindLabel(1));
- if (jump_location.GetPosition() != -1) {
- IP().Set(jump_location);
- return true;
- }
-
- // If complement label was not found; record an error.
- organism->Fault(FAULT_LOC_JUMP, FAULT_TYPE_ERROR,
- "dm-jump-f: no complement label");
- return false;
-}
-
-
-//// Placebo insts ////
-bool cHardwareCPU::Inst_Skip()
-{
- IP().Advance();
- return true;
-}
-
-
Deleted: trunk/source/cpu/hardware_cpu.hh
===================================================================
--- trunk/source/cpu/hardware_cpu.hh 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_cpu.hh 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,588 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2004 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef HARDWARE_CPU_HH
-#define HARDWARE_CPU_HH
-
-#include <iomanip>
-#include <vector>
-
-#ifndef DEFS_HH
-#include "defs.hh"
-#endif
-#ifndef CODE_LABEL_HH
-#include "cCodeLabel.h"
-#endif
-#ifndef CPU_DEFS_HH
-#include "cpu_defs.hh"
-#endif
-#ifndef HEAD_CPU_HH
-#include "head_cpu.hh"
-#endif
-#ifndef CPU_MEMORY_HH
-#include "cCPUMemory.h"
-#endif
-#ifndef CPU_STACK_HH
-#include "cCPUStack.h"
-#endif
-#ifndef HARDWARE_BASE_HH
-#include "hardware_base.hh"
-#endif
-#ifndef HARDWARE_CPU_THREAD_HH
-#include "hardware_cpu_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 cHardwareCPU_Thread;
-
-#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 cHardwareCPU structure which keeps track of the
- * current status of all the components of the simulated hardware.
- *
- * @see cHardwareCPU_Thread, cCPUStack, cCPUMemory, cInstSet
- **/
-
-class cCodeLabel; // access
-class cHeadCPU; // access
-class cCPUMemory; // aggregate
-class cCPUStack; // aggregate
-class cGenome;
-class cHardwareCPU_Thread; // access
-class cInstLibBase;
-class cInstLibCPU;
-class cInstruction;
-class cInstSet;
-class cMutation;
-class cOrganism;
-class cString; // aggregate
-template <class T> class tBuffer;
-template <class T> class tArray; // aggregate
-
-class cHardwareCPU : public cHardwareBase {
-public:
- typedef bool (cHardwareCPU::*tHardwareCPUMethod)();
-private:
- static cInstLibCPU *s_inst_slib;
- static cInstLibCPU *initInstLib(void);
- tHardwareCPUMethod *m_functions;
-private:
- cCPUMemory memory; // Memory...
- cCPUStack global_stack; // A stack that all threads share.
- int thread_time_used;
-
- tArray<cHardwareCPU_Thread> threads;
- int thread_id_chart;
- int cur_thread;
-
- // Flags...
- bool mal_active; // Has an allocate occured since last divide?
- 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
-
-public:
- cHardwareCPU(cOrganism * in_organism, cInstSet * in_inst_set);
- explicit cHardwareCPU(const cHardwareCPU &);
- ~cHardwareCPU();
- void Recycle(cOrganism * new_organism, cInstSet * in_inst_set);
- static cInstLibCPU *GetInstLib();
- static cString GetDefaultInstFilename() { return "inst_lib.default"; }
- 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... --------
- inline void StackPush(int value);
- inline int StackPop();
- inline void StackFlip();
- inline int GetStack(int depth=0, int stack_id=-1) const;
- inline void StackClear();
- inline void SwitchStack();
- int GetActiveStackID() const { return threads[cur_thread].cur_stack; }
-
-
- // -------- 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 cHeadCPU & GetHead(int head_id) const
- { return threads[cur_thread].heads[head_id]; }
- cHeadCPU & GetHead(int head_id) { return threads[cur_thread].heads[head_id];}
-
- const cHeadCPU & GetActiveHead() const { return GetHead(GetCurHead()); }
- cHeadCPU & GetActiveHead() { return GetHead(GetCurHead()); }
-
- void AdjustHeads();
-
- inline const cHeadCPU & IP() const
- { return threads[cur_thread].heads[HEAD_IP]; }
- inline cHeadCPU & IP() { return threads[cur_thread].heads[HEAD_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 --------
- const 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 const cCPUMemory & Memory() const { return memory; }
- inline cCPUMemory & Memory() { return memory; }
-
- // -------- 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);
-
- // -------- Tests --------
-
- int TestParasite() const;
-
- // -------- Accessors --------
- const cCPUMemory & GetMemory() const { return memory; }
- cCPUMemory & GetMemory() { return memory; }
- const cCPUMemory & GetMemory(int value) const { return memory;}
- cCPUMemory & GetMemory(int value) { return memory; }
-
- 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...
- cHeadCPU 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);
- cHeadCPU FindLabel(const cCodeLabel & in_label, int direction);
- cHeadCPU FindFullLabel(const cCodeLabel & in_label);
-
- int GetType() const { return HARDWARE_TYPE_CPU_ORIGINAL; }
- bool InjectHost(const cCodeLabel & in_label, const cGenome & injection);
- int InjectThread(const cCodeLabel & in_label, const cGenome & injection);
- void InjectCode(const cGenome & injection, const int line_num);
- void InjectCodeThread(const cGenome & injection, const int line_num);
- void Mutate(const int mut_point);
- int PointMutate(const double mut_rate);
-
- bool TriggerMutations(int trigger);
- bool TriggerMutations(int trigger, cHeadCPU & cur_head);
- bool TriggerMutations_ScopeGenome(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadCPU & cur_head, const double rate);
- bool TriggerMutations_ScopeLocal(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadCPU & cur_head, const double rate);
- int TriggerMutations_ScopeGlobal(const cMutation * cur_mut,
- cCPUMemory & target_memory, cHeadCPU & cur_head, const double rate);
- void TriggerMutations_Body(int type, cCPUMemory & target_memory,
- cHeadCPU & 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);
-
-
-private:
-
- /////////---------- Instruction Helpers ------------//////////
-
- int FindModifiedRegister(int default_register);
- int FindModifiedHead(int default_head);
- int FindComplementRegister(int base_reg);
-
- 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 divide_point, const int extra_lines=0, double mut_multiplier=1);
-
- bool Divide_CheckViable(const int child_size, const int parent_size);
- void Divide_DoMutations(double mut_multiplier=1);
- void Divide_TestFitnessMeasures();
-
- bool HeadCopy_ErrorCorrect(double reduction);
- bool Inst_HeadDivideMut(double mut_multiplier=1);
-
-public:
- /////////---------- Instruction Library ------------//////////
-
- // Flow Control
- bool Inst_If0();
- bool Inst_IfEqu();
- bool Inst_IfNot0();
- bool Inst_IfNEqu();
- bool Inst_IfGr0();
- bool Inst_IfGr();
- bool Inst_IfGrEqu0();
- bool Inst_IfGrEqu();
- bool Inst_IfLess0();
- bool Inst_IfLess();
- bool Inst_IfLsEqu0();
- bool Inst_IfLsEqu();
- bool Inst_IfBit1();
- bool Inst_IfANotEqB();
- bool Inst_IfBNotEqC();
- bool Inst_IfANotEqC();
-
- bool Inst_JumpF();
- bool Inst_JumpB();
- bool Inst_JumpP();
- bool Inst_JumpSelf();
- bool Inst_Call();
- bool Inst_Return();
-
- // Stack and Register Operations
- bool Inst_Pop();
- bool Inst_Push();
- bool Inst_HeadPop();
- bool Inst_HeadPush();
-
- bool Inst_PopA();
- bool Inst_PopB();
- bool Inst_PopC();
- bool Inst_PushA();
- bool Inst_PushB();
- bool Inst_PushC();
-
- bool Inst_SwitchStack();
- bool Inst_FlipStack();
- bool Inst_Swap();
- bool Inst_SwapAB();
- bool Inst_SwapBC();
- bool Inst_SwapAC();
- bool Inst_CopyReg();
- bool Inst_CopyRegAB();
- bool Inst_CopyRegAC();
- bool Inst_CopyRegBA();
- bool Inst_CopyRegBC();
- bool Inst_CopyRegCA();
- bool Inst_CopyRegCB();
- bool Inst_Reset();
-
- // Single-Argument Math
- bool Inst_ShiftR();
- bool Inst_ShiftL();
- bool Inst_Bit1();
- bool Inst_SetNum();
- bool Inst_ValGrey();
- bool Inst_ValDir();
- bool Inst_ValAddP();
- bool Inst_ValFib();
- bool Inst_ValPolyC();
- bool Inst_Inc();
- bool Inst_Dec();
- bool Inst_Zero();
- bool Inst_Not();
- bool Inst_Neg();
- bool Inst_Square();
- bool Inst_Sqrt();
- bool Inst_Log();
- bool Inst_Log10();
- bool Inst_Minus17();
-
- // Double Argument Math
- bool Inst_Add();
- bool Inst_Sub();
- bool Inst_Mult();
- bool Inst_Div();
- bool Inst_Mod();
- bool Inst_Nand();
- bool Inst_Nor();
- bool Inst_And();
- bool Inst_Order();
- bool Inst_Xor();
-
- // Biological
- bool Inst_Copy();
- bool Inst_ReadInst();
- bool Inst_WriteInst();
- bool Inst_StackReadInst();
- bool Inst_StackWriteInst();
- bool Inst_Compare();
- bool Inst_IfNCpy();
- bool Inst_Allocate();
- bool Inst_Divide();
- bool Inst_CAlloc();
- bool Inst_CDivide();
- bool Inst_MaxAlloc();
- bool Inst_Inject();
- bool Inst_InjectRand();
- bool Inst_InjectThread();
- bool Inst_Repro();
- bool Inst_Kazi();
- bool Inst_Die();
-
- // I/O and Sensory
- bool Inst_TaskGet();
- bool Inst_TaskStackGet();
- bool Inst_TaskStackLoad();
- bool Inst_TaskPut();
- bool Inst_TaskIO();
- bool Inst_Send();
- bool Inst_Receive();
- bool Inst_Sense();
-
- void DoDonate(cOrganism * to_org);
- bool Inst_DonateRandom();
- bool Inst_DonateKin();
- bool Inst_DonateEditDist();
- bool Inst_DonateNULL();
-
- bool Inst_SearchF();
- bool Inst_SearchB();
- bool Inst_MemSize();
-
- // Environment
-
- bool Inst_RotateL();
- bool Inst_RotateR();
- bool Inst_SetCopyMut();
- bool Inst_ModCopyMut();
-
- // Multi-threading...
-
- bool Inst_ForkThread();
- bool Inst_KillThread();
- bool Inst_ThreadID();
-
- // Head-based instructions...
-
- bool Inst_SetHead();
- bool Inst_AdvanceHead();
- bool Inst_MoveHead();
- bool Inst_JumpHead();
- bool Inst_GetHead();
- bool Inst_IfLabel();
- bool Inst_IfLabel2();
- bool Inst_HeadDivide();
- bool Inst_HeadRead();
- bool Inst_HeadWrite();
- bool Inst_HeadCopy();
- bool Inst_HeadSearch();
- bool Inst_SetFlow();
-
- bool Inst_HeadCopy2();
- bool Inst_HeadCopy3();
- bool Inst_HeadCopy4();
- bool Inst_HeadCopy5();
- bool Inst_HeadCopy6();
- bool Inst_HeadCopy7();
- bool Inst_HeadCopy8();
- bool Inst_HeadCopy9();
- bool Inst_HeadCopy10();
-
- bool Inst_HeadDivideSex();
- bool Inst_HeadDivideAsex();
- bool Inst_HeadDivideAsexWait();
- bool Inst_HeadDivideMateSelect();
-
- bool Inst_HeadDivide1();
- bool Inst_HeadDivide2();
- bool Inst_HeadDivide3();
- bool Inst_HeadDivide4();
- bool Inst_HeadDivide5();
- bool Inst_HeadDivide6();
- bool Inst_HeadDivide7();
- bool Inst_HeadDivide8();
- bool Inst_HeadDivide9();
- bool Inst_HeadDivide10();
- bool Inst_HeadDivide16();
- bool Inst_HeadDivide32();
- bool Inst_HeadDivide50();
- bool Inst_HeadDivide100();
- bool Inst_HeadDivide500();
- bool Inst_HeadDivide1000();
- bool Inst_HeadDivide5000();
- bool Inst_HeadDivide10000();
- bool Inst_HeadDivide50000();
- bool Inst_HeadDivide0_5();
- bool Inst_HeadDivide0_1();
- bool Inst_HeadDivide0_05();
- bool Inst_HeadDivide0_01();
- bool Inst_HeadDivide0_001();
-
-
- // Direct Matching Templates
-
- bool Inst_DMJumpF();
- //bool Inst_DMJumpB();
- //bool Inst_DMCall();
- //bool Inst_DMSearchF();
- //bool Inst_DMSearchB();
-
- // Relative Addressed Jumps
-
- //bool Inst_REJumpF();
- //bool Inst_REJumpB();
-
- // Absoulte Addressed Jumps
-
- //bool Inst_ABSJump();
-
- // Biologically inspired reproduction
- //bool Inst_BCAlloc();
- //bool Inst_BCopy();
- //bool Inst_BDivide();
-private:
- bool Inst_BCopy_Main(double mut_prob); // Internal called by all BCopy's
-public:
- // Bio Error Correction
- //bool Inst_BCopyDiv2();
- //bool Inst_BCopyDiv3();
- //bool Inst_BCopyDiv4();
- //bool Inst_BCopyDiv5();
- //bool Inst_BCopyDiv6();
- //bool Inst_BCopyDiv7();
- //bool Inst_BCopyDiv8();
- //bool Inst_BCopyDiv9();
- //bool Inst_BCopyDiv10();
- //bool Inst_BCopyPow2();
- //bool Inst_BIfNotCopy();
- //bool Inst_BIfCopy();
-
-
- //// Placebo ////
- bool Inst_Skip();
-};
-
-
-//////////////////
-// cHardwareCPU
-//////////////////
-
-inline void cHardwareCPU::NextThread()
-{
- cur_thread++;
- if (cur_thread >= GetNumThreads()) cur_thread = 0;
-}
-
-inline void cHardwareCPU::PrevThread()
-{
- if (cur_thread == 0) cur_thread = GetNumThreads() - 1;
- else cur_thread--;
-}
-
-inline void cHardwareCPU::SetThread(int value)
-{
- if (value>=0 && value < GetNumThreads())
- cur_thread=value;
-}
-
-inline void cHardwareCPU::StackPush(int value)
-{
- if (threads[cur_thread].cur_stack == 0) {
- threads[cur_thread].stack.Push(value);
- } else {
- global_stack.Push(value);
- }
-}
-
-inline int cHardwareCPU::StackPop()
-{
- int pop_value;
-
- if (threads[cur_thread].cur_stack == 0) {
- pop_value = threads[cur_thread].stack.Pop();
- } else {
- pop_value = global_stack.Pop();
- }
-
- return pop_value;
-}
-
-inline void cHardwareCPU::StackFlip()
-{
- if (threads[cur_thread].cur_stack == 0) {
- threads[cur_thread].stack.Flip();
- } else {
- global_stack.Flip();
- }
-}
-
-inline int cHardwareCPU::GetStack(int depth, int stack_id) const
-{
- int value = 0;
-
- if (stack_id == -1) stack_id = threads[cur_thread].cur_stack;
-
- if (stack_id == 0) value = threads[cur_thread].stack.Get(depth);
- else if (stack_id == 1) value = global_stack.Get(depth);
-
- return value;
-}
-
-inline void cHardwareCPU::StackClear()
-{
- if (threads[cur_thread].cur_stack == 0) {
- threads[cur_thread].stack.Clear();
- } else {
- global_stack.Clear();
- }
-}
-
-inline void cHardwareCPU::SwitchStack()
-{
- threads[cur_thread].cur_stack++;
- if (threads[cur_thread].cur_stack > 1) threads[cur_thread].cur_stack = 0;
-}
-
-#endif
Deleted: trunk/source/cpu/hardware_cpu_thread.cc
===================================================================
--- trunk/source/cpu/hardware_cpu_thread.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_cpu_thread.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,126 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2003 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef HARDWARE_CPU_THREAD_HH
-#include "hardware_cpu_thread.hh"
-#endif
-
-using namespace std;
-
-/////////////////////////
-// cHardwareCPU_Thread
-/////////////////////////
-
-cHardwareCPU_Thread::cHardwareCPU_Thread(cHardwareBase * in_hardware, int _id)
-{
- Reset(in_hardware, _id);
-}
-
-cHardwareCPU_Thread::cHardwareCPU_Thread(const cHardwareCPU_Thread & in_thread, int _id)
-{
- id = _id;
- if (id == -1) id = in_thread.id;
- for (int i = 0; i < NUM_REGISTERS; i++) {
- reg[i] = in_thread.reg[i];
- }
- for (int i = 0; i < NUM_HEADS; i++) {
- heads[i] = in_thread.heads[i];
- }
- stack = in_thread.stack;
-}
-
-cHardwareCPU_Thread::~cHardwareCPU_Thread() {}
-
-void cHardwareCPU_Thread::operator=(const cHardwareCPU_Thread & in_thread)
-{
- id = in_thread.id;
- for (int i = 0; i < NUM_REGISTERS; i++) {
- reg[i] = in_thread.reg[i];
- }
- for (int i = 0; i < NUM_HEADS; i++) {
- heads[i] = in_thread.heads[i];
- }
- stack = in_thread.stack;
-}
-
-void cHardwareCPU_Thread::Reset(cHardwareBase * in_hardware, int _id)
-{
- id = _id;
-
- for (int i = 0; i < NUM_REGISTERS; i++) reg[i] = 0;
- for (int i = 0; i < NUM_HEADS; i++) heads[i].Reset(in_hardware);
-
- stack.Clear();
- cur_stack = 0;
- cur_head = HEAD_IP;
- read_label.Clear();
- next_label.Clear();
-}
-
-
-
-
-void cHardwareCPU_Thread::SaveState(ostream & fp){
- assert(fp.good());
- fp << "cHardwareCPU_Thread" << endl;
-
- // registers
- for( int i=0; i<NUM_REGISTERS; ++i ){
- fp<<reg[i]<<endl;
- }
-
- // heads (@TCC does not handle parasites!!!)
- for( int i=0; i<NUM_HEADS; ++i ){
- fp<<heads[i].GetPosition()<<endl;
- }
-
- stack.SaveState(fp);
-
- fp<<"|"; // marker
- fp<<cur_stack;
- fp<<cur_head;
- fp<<endl;
-
- // Code labels
- read_label.SaveState(fp);
- next_label.SaveState(fp);
-}
-
-
-
-void cHardwareCPU_Thread::LoadState(istream & fp){
- assert(fp.good());
- cString foo;
- fp >> foo;
- assert( foo == "cHardwareCPU_Thread");
-
- // registers
- for( int i=0; i<NUM_REGISTERS; ++i ){
- fp>>reg[i];
- }
-
- // heads (@TCC does not handle parasites!!!)
- for( int i=0; i<NUM_HEADS; ++i ){
- int pos;
- fp>>pos;
- heads[i].AbsSet(pos);
- }
-
- // stack
- stack.LoadState(fp);
-
- char marker; fp>>marker; assert( marker == '|' );
- /* YIKES! data loss below: */
- char the_cur_stack = cur_stack;
- char the_cur_head = cur_head;
- fp.get(the_cur_stack);
- fp.get(the_cur_head);
-
- // Code labels
- read_label.LoadState(fp);
- next_label.LoadState(fp);
-}
Deleted: trunk/source/cpu/hardware_cpu_thread.hh
===================================================================
--- trunk/source/cpu/hardware_cpu_thread.hh 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_cpu_thread.hh 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,68 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2003 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef HARDWARE_CPU_THREAD_HH
-#define HARDWARE_CPU_THREAD_HH
-
-#include <iostream>
-
-#ifndef CODE_LABEL_HH
-#include "cCodeLabel.h"
-#endif
-#ifndef CPU_DEFS_HH
-#include "cpu_defs.hh"
-#endif
-#ifndef HEAD_CPU_HH
-#include "head_cpu.hh"
-#endif
-#ifndef CPU_STACK_HH
-#include "cCPUStack.h"
-#endif
-#ifndef TBUFFER_HH
-#include "tBuffer.hh"
-#endif
-
-/**
- * This class is needed to run several threads on a single genome.
- *
- * @see cCPUStack, cHeadCPU, cHardwareCPU
- **/
-
-class cCodeLabel; // aggregate;
-class cHeadCPU; // aggregate
-class cCPUStack; // aggregate
-class cHardwareBase;
-template <class T> class tBuffer; // aggregate
-
-struct cHardwareCPU_Thread {
-private:
- int id;
-public:
- int reg[NUM_REGISTERS];
- cHeadCPU heads[NUM_HEADS];
- cCPUStack stack;
- UCHAR cur_stack; // 0 = local stack, 1 = global stack.
- UCHAR cur_head;
-
- cCodeLabel read_label;
- cCodeLabel next_label;
-public:
- cHardwareCPU_Thread(cHardwareBase * in_hardware=NULL, int _id=-1);
- cHardwareCPU_Thread(const cHardwareCPU_Thread & in_thread, int _id=-1);
- ~cHardwareCPU_Thread();
-
- void operator=(const cHardwareCPU_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
Deleted: trunk/source/cpu/hardware_factory.cc
===================================================================
--- trunk/source/cpu/hardware_factory.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_factory.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,82 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2003 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#include "hardware_factory.hh"
-
-#include "hardware_base.hh"
-#include "hardware_cpu.hh"
-#include "hardware_4stack.hh"
-#include "hardware_smt.h"
-#include "inst_set.hh"
-#include "organism.hh"
-
-using namespace std;
-
-// Static private variables...
-tList<cHardwareBase> cHardwareFactory::hardware_cpu_list;
-int cHardwareFactory::new_count(0);
-int cHardwareFactory::recycle_count(0);
-
-cHardwareBase * cHardwareFactory::Create(cOrganism * in_org,
- cInstSet * inst_set, int type)
-{
- assert(in_org != NULL);
- assert(inst_set != NULL && inst_set->OK());
-
- cHardwareBase * new_hardware = NULL;
-
- // If there is nothing to recycle, just create a new one.
- if (hardware_cpu_list.GetSize() == 0)
- {
- new_count++;
- switch (type)
- {
- case HARDWARE_TYPE_CPU_ORIGINAL:
- new_hardware = new cHardwareCPU(in_org, inst_set);
- break;
- case HARDWARE_TYPE_CPU_4STACK:
- new_hardware = new cHardware4Stack(in_org, inst_set);
- break;
- case HARDWARE_TYPE_CPU_SMT:
- new_hardware = new cHardwareSMT(in_org, inst_set);
- }
- }
-
- // If we do have hardware to recycle, do so!
- else {
- new_hardware = hardware_cpu_list.PopRear();
- new_hardware->Recycle(in_org, inst_set);
- recycle_count++;
- }
-
- return new_hardware;
-}
-
-// Recycled hardware may be *briefly* in use, so don't delete immediately.
-void cHardwareFactory::Recycle(cHardwareBase * out_hardware)
-{
- hardware_cpu_list.Push(out_hardware);
-}
-
-// Delete any hardware that needs it, save the rest for re-use.
-void cHardwareFactory::Update()
-{
- int delete_count = 0;
- while (hardware_cpu_list.GetSize() > 100) {
- delete hardware_cpu_list.Pop();
- delete_count++;
- }
-
-// cerr << " NewHardware: " << new_count
-// << " Recycled: " << recycle_count
-// << " Deleted: " << delete_count
-// << " Stored: " << hardware_cpu_list.GetSize()
-// << " Existing: " << cHardwareBase::GetInstanceCount()
-// << endl;
-
- new_count = recycle_count = 0;
-}
Deleted: trunk/source/cpu/hardware_factory.hh
===================================================================
--- trunk/source/cpu/hardware_factory.hh 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_factory.hh 2005-08-29 19:51:42 UTC (rev 300)
@@ -1,32 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1993 - 2001 California Institute of Technology //
-// //
-// Read the COPYING and README files, or contact 'avida at alife.org', //
-// before continuing. SOME RESTRICTIONS MAY APPLY TO USE OF THIS FILE. //
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef HARDWARE_FACTORY_HH
-#define HARDWARE_FACTORY_HH
-
-#ifndef TLIST_HH
-#include "tList.hh"
-#endif
-
-class cHardwareBase;
-class cOrganism;
-class cInstSet;
-
-class cHardwareFactory {
-private:
- // A static list for each hardware type.
- static tList<cHardwareBase> hardware_cpu_list;
- static int new_count;
- static int recycle_count;
-public:
- static cHardwareBase * Create(cOrganism * in_org, cInstSet * inst_set,
- int type=0);
- static void Recycle(cHardwareBase * out_hardware);
- static void Update();
-};
-
-#endif
Modified: trunk/source/cpu/hardware_smt.h
===================================================================
--- trunk/source/cpu/hardware_smt.h 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_smt.h 2005-08-29 19:51:42 UTC (rev 300)
@@ -25,7 +25,7 @@
#include "head_multi_mem.hh"
#endif
#ifndef HARDWARE_BASE_HH
-#include "hardware_base.hh"
+#include "cHardwareBase.h"
#endif
#ifndef HARDWARE_SMT_CONSTANTS_H
#include "hardware_smt_constants.h"
Modified: trunk/source/cpu/hardware_status_printer.cc
===================================================================
--- trunk/source/cpu/hardware_status_printer.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_status_printer.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -6,9 +6,9 @@
//////////////////////////////////////////////////////////////////////////////
#include "head_cpu.hh"
-#include "hardware_4stack.hh"
-#include "hardware_base.hh"
-#include "hardware_cpu.hh"
+#include "cHardware4Stack.h"
+#include "cHardwareBase.h"
+#include "cHardwareCPU.h"
#include "hardware_status_printer.hh"
#include "inst_set.hh"
#include "organism.hh"
Modified: trunk/source/cpu/hardware_util.cc
===================================================================
--- trunk/source/cpu/hardware_util.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/hardware_util.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -13,13 +13,13 @@
#include "config.hh"
#endif
#ifndef HARDWARE_UTIL_HH
-#include "hardware_base.hh"
+#include "cHardwareBase.h"
#endif
#ifndef HARDWARE_CPU_HH
-#include "hardware_cpu.hh"
+#include "cHardwareCPU.h"
#endif
#ifndef HARDWARE_4STACK_HH
-#include "hardware_4stack.hh"
+#include "cHardware4Stack.h"
#endif
#ifndef HARDWARE_SMT_H
#include "hardware_smt.h"
Modified: trunk/source/cpu/head_cpu.cc
===================================================================
--- trunk/source/cpu/head_cpu.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/head_cpu.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -19,7 +19,7 @@
#include "genome.hh"
#endif
#ifndef HARDWARE_BASE_HH
-#include "hardware_base.hh"
+#include "cHardwareBase.h"
#endif
#ifndef INST_SET_HH
#include "inst_set.hh"
Modified: trunk/source/cpu/head_multi_mem.cc
===================================================================
--- trunk/source/cpu/head_multi_mem.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/head_multi_mem.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -13,7 +13,7 @@
#include "cCPUMemory.h"
#endif
#ifndef HARDWARE_BASE_HH
-#include "hardware_base.hh"
+#include "cHardwareBase.h"
#endif
#ifndef INST_SET_HH
#include "inst_set.hh"
Modified: trunk/source/cpu/inst_lib_cpu.hh
===================================================================
--- trunk/source/cpu/inst_lib_cpu.hh 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/inst_lib_cpu.hh 2005-08-29 19:51:42 UTC (rev 300)
@@ -7,7 +7,7 @@
#endif
#ifndef HARDWARE_CPU_HH
-#include "hardware_cpu.hh"
+#include "cHardwareCPU.h"
#endif
#ifndef INSTRUCTION_HH
#include "instruction.hh"
Modified: trunk/source/cpu/test_cpu.cc
===================================================================
--- trunk/source/cpu/test_cpu.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/test_cpu.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -11,7 +11,7 @@
#include "config.hh"
#include "environment.hh"
#include "functions.hh"
-#include "hardware_base.hh"
+#include "cHardwareBase.h"
#include "hardware_status_printer.hh"
#include "inst_set.hh"
#include "inst_util.hh"
Modified: trunk/source/cpu/test_util.cc
===================================================================
--- trunk/source/cpu/test_util.cc 2005-08-29 19:15:32 UTC (rev 299)
+++ trunk/source/cpu/test_util.cc 2005-08-29 19:51:42 UTC (rev 300)
@@ -11,7 +11,7 @@
#include "environment.hh"
#include "genome.hh"
#include "genotype.hh"
-#include "hardware_base.hh"
+#include "cHardwareBase.h"
#include "inject_genotype.hh"
#include "inst_util.hh"
#include "organism.hh"
More information about the Avida-cvs
mailing list