[Avida-SVN] r1443 - in development: Avida.xcodeproj source source/cpu
dknoester at myxo.css.msu.edu
dknoester at myxo.css.msu.edu
Sun Apr 1 15:37:35 PDT 2007
Author: dknoester
Date: 2007-04-01 18:37:34 -0400 (Sun, 01 Apr 2007)
New Revision: 1443
Added:
development/source/cpu/cHardwareGX.cc
development/source/cpu/cHardwareGX.h
Modified:
development/Avida.xcodeproj/project.pbxproj
development/source/cpu/cHardwareManager.cc
development/source/defs.h
Log:
Added new cpu type for gene expression work.
Modified: development/Avida.xcodeproj/project.pbxproj
===================================================================
--- development/Avida.xcodeproj/project.pbxproj 2007-03-30 15:03:40 UTC (rev 1442)
+++ development/Avida.xcodeproj/project.pbxproj 2007-04-01 22:37:34 UTC (rev 1443)
@@ -10,6 +10,8 @@
1097463F0AE9606E00929ED6 /* cDeme.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1097463D0AE9606E00929ED6 /* cDeme.cc */; };
109746410AE9606E00929ED6 /* cDeme.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1097463D0AE9606E00929ED6 /* cDeme.cc */; };
109746430AE9606E00929ED6 /* cDeme.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1097463D0AE9606E00929ED6 /* cDeme.cc */; };
+ 4233358A0BC067E3000DF681 /* cHardwareGX.cc in Sources */ = {isa = PBXBuildFile; fileRef = 423335880BC067E3000DF681 /* cHardwareGX.cc */; };
+ 4233358B0BC067E3000DF681 /* cHardwareGX.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 423335890BC067E3000DF681 /* cHardwareGX.h */; };
7005A70409BA0FA90007E16E /* cTestCPUInterface.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7005A70209BA0FA90007E16E /* cTestCPUInterface.cc */; };
7005A70609BA0FA90007E16E /* cTestCPUInterface.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7005A70209BA0FA90007E16E /* cTestCPUInterface.cc */; };
7005A70809BA0FA90007E16E /* cTestCPUInterface.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7005A70209BA0FA90007E16E /* cTestCPUInterface.cc */; };
@@ -422,6 +424,7 @@
7049F3730A66AD7E00640512 /* default-transsmt.org in CopyFiles */,
70B1A7430B7E3FFD00067486 /* instset-experimental.cfg in CopyFiles */,
70B1A75A0B7E431F00067486 /* experimental.org in CopyFiles */,
+ 4233358B0BC067E3000DF681 /* cHardwareGX.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -440,6 +443,8 @@
/* Begin PBXFileReference section */
1097463D0AE9606E00929ED6 /* cDeme.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cDeme.cc; sourceTree = "<group>"; };
1097463E0AE9606E00929ED6 /* cDeme.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cDeme.h; sourceTree = "<group>"; };
+ 423335880BC067E3000DF681 /* cHardwareGX.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cHardwareGX.cc; sourceTree = "<group>"; };
+ 423335890BC067E3000DF681 /* cHardwareGX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cHardwareGX.h; sourceTree = "<group>"; };
7005A70109BA0FA90007E16E /* cTestCPUInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cTestCPUInterface.h; sourceTree = "<group>"; };
7005A70209BA0FA90007E16E /* cTestCPUInterface.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cTestCPUInterface.cc; sourceTree = "<group>"; };
7005A70909BA0FBE0007E16E /* cOrgInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cOrgInterface.h; sourceTree = "<group>"; };
@@ -452,7 +457,7 @@
700E12610A097A0800B604CD /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
700E12630A097A1700B604CD /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
700E28CF0859FFD700CF158A /* tObjectFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tObjectFactory.h; sourceTree = "<group>"; };
- 700E2B83085DE50C00CF158A /* avida-viewer */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = "avida-viewer"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 700E2B83085DE50C00CF158A /* avida-viewer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "avida-viewer"; sourceTree = BUILT_PRODUCTS_DIR; };
7013845F09028B3E0087ED2E /* cAvidaConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cAvidaConfig.h; sourceTree = "<group>"; };
7013846009028B3E0087ED2E /* cAvidaConfig.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cAvidaConfig.cc; sourceTree = "<group>"; };
701384A10902A16F0087ED2E /* defs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = defs.h; sourceTree = "<group>"; };
@@ -923,7 +928,7 @@
DCC315CF076253A5008F7A48 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
DCC315D0076253A5008F7A48 /* task_event_gen.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = task_event_gen.cc; sourceTree = "<group>"; };
DCC315D1076253A5008F7A48 /* task_event_gen.old.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = task_event_gen.old.cc; sourceTree = "<group>"; };
- DCC3164D07626CF3008F7A48 /* avida */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = avida; sourceTree = BUILT_PRODUCTS_DIR; };
+ DCC3164D07626CF3008F7A48 /* avida */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = avida; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -1366,6 +1371,8 @@
70C1EF9E08C39F0E00F50912 /* cHardwareBase.h */,
70C1EFA508C39F2100F50912 /* cHardwareCPU.cc */,
70C1EFA008C39F0E00F50912 /* cHardwareCPU.h */,
+ 423335880BC067E3000DF681 /* cHardwareGX.cc */,
+ 423335890BC067E3000DF681 /* cHardwareGX.h */,
70C5BD690905CE5F0028A785 /* cHardwareManager.cc */,
70C5BD6A0905CE5F0028A785 /* cHardwareManager.h */,
70C1F02308C3C71300F50912 /* cHardwareSMT.cc */,
@@ -2176,6 +2183,7 @@
1097463F0AE9606E00929ED6 /* cDeme.cc in Sources */,
70B1A6500B7E237F00067486 /* cHardwareExperimental.cc in Sources */,
706C6FFF0B83F265003174C1 /* cInstSet.cc in Sources */,
+ 4233358A0BC067E3000DF681 /* cHardwareGX.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Added: development/source/cpu/cHardwareGX.cc
===================================================================
--- development/source/cpu/cHardwareGX.cc 2007-03-30 15:03:40 UTC (rev 1442)
+++ development/source/cpu/cHardwareGX.cc 2007-04-01 22:37:34 UTC (rev 1443)
@@ -0,0 +1,3556 @@
+/*
+ * cHardwareGX.cc
+ * Avida
+ *
+ * Copyright 1999-2007 Michigan State University. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#include <climits>
+#include <fstream>
+#include "cHardwareGX.h"
+#include "cAvidaContext.h"
+#include "cCPUTestInfo.h"
+#include "functions.h"
+#include "cGenomeUtil.h"
+#include "cGenotype.h"
+#include "cHardwareManager.h"
+#include "cHardwareTracer.h"
+#include "cInstSet.h"
+#include "cMutation.h"
+#include "cMutationLib.h"
+#include "nMutation.h"
+#include "cOrganism.h"
+#include "cPhenotype.h"
+#include "cStringUtil.h"
+#include "cTestCPU.h"
+#include "cWorldDriver.h"
+#include "cWorld.h"
+#include "tInstLibEntry.h"
+
+
+using namespace std;
+
+
+tInstLib<cHardwareGX::tMethod>* cHardwareGX::s_inst_slib = cHardwareGX::initInstLib();
+
+tInstLib<cHardwareGX::tMethod>* cHardwareGX::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)
+ };
+
+ static const tInstLibEntry<tMethod> s_f_array[] = {
+ /*
+ Note: all entries of cNOPEntryCPU s_n_array must have corresponding
+ in the same order in tInstLibEntry<tMethod> s_f_array, and these entries must
+ be the first elements of s_f_array.
+ */
+ tInstLibEntry<tMethod>("nop-A", &cHardwareGX::Inst_Nop, (nInstFlag::DEFAULT | nInstFlag::NOP), "No-operation instruction; modifies other instructions"),
+ tInstLibEntry<tMethod>("nop-B", &cHardwareGX::Inst_Nop, (nInstFlag::DEFAULT | nInstFlag::NOP), "No-operation instruction; modifies other instructions"),
+ tInstLibEntry<tMethod>("nop-C", &cHardwareGX::Inst_Nop, (nInstFlag::DEFAULT | nInstFlag::NOP), "No-operation instruction; modifies other instructions"),
+
+ tInstLibEntry<tMethod>("NULL", &cHardwareGX::Inst_Nop, 0, "True no-operation instruction: does nothing"),
+ tInstLibEntry<tMethod>("nop-X", &cHardwareGX::Inst_Nop, 0, "True no-operation instruction: does nothing"),
+ tInstLibEntry<tMethod>("if-equ-0", &cHardwareGX::Inst_If0, 0, "Execute next instruction if ?BX?==0, else skip it"),
+ tInstLibEntry<tMethod>("if-not-0", &cHardwareGX::Inst_IfNot0, 0, "Execute next instruction if ?BX?!=0, else skip it"),
+ tInstLibEntry<tMethod>("if-n-equ", &cHardwareGX::Inst_IfNEqu, nInstFlag::DEFAULT, "Execute next instruction if ?BX?!=?CX?, else skip it"),
+ tInstLibEntry<tMethod>("if-equ", &cHardwareGX::Inst_IfEqu, 0, "Execute next instruction if ?BX?==?CX?, else skip it"),
+ tInstLibEntry<tMethod>("if-grt-0", &cHardwareGX::Inst_IfGr0),
+ tInstLibEntry<tMethod>("if-grt", &cHardwareGX::Inst_IfGr),
+ tInstLibEntry<tMethod>("if->=-0", &cHardwareGX::Inst_IfGrEqu0),
+ tInstLibEntry<tMethod>("if->=", &cHardwareGX::Inst_IfGrEqu),
+ tInstLibEntry<tMethod>("if-les-0", &cHardwareGX::Inst_IfLess0),
+ tInstLibEntry<tMethod>("if-less", &cHardwareGX::Inst_IfLess, nInstFlag::DEFAULT, "Execute next instruction if ?BX? < ?CX?, else skip it"),
+ tInstLibEntry<tMethod>("if-<=-0", &cHardwareGX::Inst_IfLsEqu0),
+ tInstLibEntry<tMethod>("if-<=", &cHardwareGX::Inst_IfLsEqu),
+ tInstLibEntry<tMethod>("if-A!=B", &cHardwareGX::Inst_IfANotEqB),
+ tInstLibEntry<tMethod>("if-B!=C", &cHardwareGX::Inst_IfBNotEqC),
+ tInstLibEntry<tMethod>("if-A!=C", &cHardwareGX::Inst_IfANotEqC),
+ tInstLibEntry<tMethod>("if-bit-1", &cHardwareGX::Inst_IfBit1),
+
+ tInstLibEntry<tMethod>("jump-f", &cHardwareGX::Inst_JumpF),
+ tInstLibEntry<tMethod>("jump-b", &cHardwareGX::Inst_JumpB),
+ tInstLibEntry<tMethod>("call", &cHardwareGX::Inst_Call),
+ tInstLibEntry<tMethod>("return", &cHardwareGX::Inst_Return),
+
+ tInstLibEntry<tMethod>("throw", &cHardwareGX::Inst_Throw),
+ tInstLibEntry<tMethod>("throwif=0", &cHardwareGX::Inst_ThrowIf0),
+ tInstLibEntry<tMethod>("throwif!=0", &cHardwareGX::Inst_ThrowIfNot0),
+ tInstLibEntry<tMethod>("catch", &cHardwareGX::Inst_Catch),
+
+ tInstLibEntry<tMethod>("goto", &cHardwareGX::Inst_Goto),
+ tInstLibEntry<tMethod>("goto-if=0", &cHardwareGX::Inst_GotoIf0),
+ tInstLibEntry<tMethod>("goto-if!=0", &cHardwareGX::Inst_GotoIfNot0),
+ tInstLibEntry<tMethod>("label", &cHardwareGX::Inst_Label),
+
+ tInstLibEntry<tMethod>("pop", &cHardwareGX::Inst_Pop, nInstFlag::DEFAULT, "Remove top number from stack and place into ?BX?"),
+ tInstLibEntry<tMethod>("push", &cHardwareGX::Inst_Push, nInstFlag::DEFAULT, "Copy number from ?BX? and place it into the stack"),
+ tInstLibEntry<tMethod>("swap-stk", &cHardwareGX::Inst_SwitchStack, nInstFlag::DEFAULT, "Toggle which stack is currently being used"),
+ tInstLibEntry<tMethod>("flip-stk", &cHardwareGX::Inst_FlipStack),
+ tInstLibEntry<tMethod>("swap", &cHardwareGX::Inst_Swap, nInstFlag::DEFAULT, "Swap the contents of ?BX? with ?CX?"),
+ tInstLibEntry<tMethod>("swap-AB", &cHardwareGX::Inst_SwapAB),
+ tInstLibEntry<tMethod>("swap-BC", &cHardwareGX::Inst_SwapBC),
+ tInstLibEntry<tMethod>("swap-AC", &cHardwareGX::Inst_SwapAC),
+ tInstLibEntry<tMethod>("copy-reg", &cHardwareGX::Inst_CopyReg),
+ tInstLibEntry<tMethod>("set_A=B", &cHardwareGX::Inst_CopyRegAB),
+ tInstLibEntry<tMethod>("set_A=C", &cHardwareGX::Inst_CopyRegAC),
+ tInstLibEntry<tMethod>("set_B=A", &cHardwareGX::Inst_CopyRegBA),
+ tInstLibEntry<tMethod>("set_B=C", &cHardwareGX::Inst_CopyRegBC),
+ tInstLibEntry<tMethod>("set_C=A", &cHardwareGX::Inst_CopyRegCA),
+ tInstLibEntry<tMethod>("set_C=B", &cHardwareGX::Inst_CopyRegCB),
+ tInstLibEntry<tMethod>("reset", &cHardwareGX::Inst_Reset),
+
+ tInstLibEntry<tMethod>("pop-A", &cHardwareGX::Inst_PopA),
+ tInstLibEntry<tMethod>("pop-B", &cHardwareGX::Inst_PopB),
+ tInstLibEntry<tMethod>("pop-C", &cHardwareGX::Inst_PopC),
+ tInstLibEntry<tMethod>("push-A", &cHardwareGX::Inst_PushA),
+ tInstLibEntry<tMethod>("push-B", &cHardwareGX::Inst_PushB),
+ tInstLibEntry<tMethod>("push-C", &cHardwareGX::Inst_PushC),
+
+ tInstLibEntry<tMethod>("shift-r", &cHardwareGX::Inst_ShiftR, nInstFlag::DEFAULT, "Shift bits in ?BX? right by one (divide by two)"),
+ tInstLibEntry<tMethod>("shift-l", &cHardwareGX::Inst_ShiftL, nInstFlag::DEFAULT, "Shift bits in ?BX? left by one (multiply by two)"),
+ tInstLibEntry<tMethod>("bit-1", &cHardwareGX::Inst_Bit1),
+ tInstLibEntry<tMethod>("set-num", &cHardwareGX::Inst_SetNum),
+ tInstLibEntry<tMethod>("val-grey", &cHardwareGX::Inst_ValGrey),
+ tInstLibEntry<tMethod>("val-dir", &cHardwareGX::Inst_ValDir),
+ tInstLibEntry<tMethod>("val-add-p", &cHardwareGX::Inst_ValAddP),
+ tInstLibEntry<tMethod>("val-fib", &cHardwareGX::Inst_ValFib),
+ tInstLibEntry<tMethod>("val-poly-c", &cHardwareGX::Inst_ValPolyC),
+ tInstLibEntry<tMethod>("inc", &cHardwareGX::Inst_Inc, nInstFlag::DEFAULT, "Increment ?BX? by one"),
+ tInstLibEntry<tMethod>("dec", &cHardwareGX::Inst_Dec, nInstFlag::DEFAULT, "Decrement ?BX? by one"),
+ tInstLibEntry<tMethod>("zero", &cHardwareGX::Inst_Zero, 0, "Set ?BX? to zero"),
+ tInstLibEntry<tMethod>("neg", &cHardwareGX::Inst_Neg),
+ tInstLibEntry<tMethod>("square", &cHardwareGX::Inst_Square),
+ tInstLibEntry<tMethod>("sqrt", &cHardwareGX::Inst_Sqrt),
+ tInstLibEntry<tMethod>("not", &cHardwareGX::Inst_Not),
+
+ tInstLibEntry<tMethod>("add", &cHardwareGX::Inst_Add, nInstFlag::DEFAULT, "Add BX to CX and place the result in ?BX?"),
+ tInstLibEntry<tMethod>("sub", &cHardwareGX::Inst_Sub, nInstFlag::DEFAULT, "Subtract CX from BX and place the result in ?BX?"),
+ tInstLibEntry<tMethod>("mult", &cHardwareGX::Inst_Mult, 0, "Multiple BX by CX and place the result in ?BX?"),
+ tInstLibEntry<tMethod>("div", &cHardwareGX::Inst_Div, 0, "Divide BX by CX and place the result in ?BX?"),
+ tInstLibEntry<tMethod>("mod", &cHardwareGX::Inst_Mod),
+ tInstLibEntry<tMethod>("nand", &cHardwareGX::Inst_Nand, nInstFlag::DEFAULT, "Nand BX by CX and place the result in ?BX?"),
+ tInstLibEntry<tMethod>("nor", &cHardwareGX::Inst_Nor),
+ tInstLibEntry<tMethod>("and", &cHardwareGX::Inst_And),
+ tInstLibEntry<tMethod>("order", &cHardwareGX::Inst_Order),
+ tInstLibEntry<tMethod>("xor", &cHardwareGX::Inst_Xor),
+
+ tInstLibEntry<tMethod>("copy", &cHardwareGX::Inst_Copy),
+ tInstLibEntry<tMethod>("read", &cHardwareGX::Inst_ReadInst),
+ tInstLibEntry<tMethod>("write", &cHardwareGX::Inst_WriteInst),
+ tInstLibEntry<tMethod>("stk-read", &cHardwareGX::Inst_StackReadInst),
+ tInstLibEntry<tMethod>("stk-writ", &cHardwareGX::Inst_StackWriteInst),
+
+ tInstLibEntry<tMethod>("compare", &cHardwareGX::Inst_Compare),
+ tInstLibEntry<tMethod>("if-n-cpy", &cHardwareGX::Inst_IfNCpy),
+ tInstLibEntry<tMethod>("allocate", &cHardwareGX::Inst_Allocate),
+ tInstLibEntry<tMethod>("divide", &cHardwareGX::Inst_Divide),
+ tInstLibEntry<tMethod>("divideRS", &cHardwareGX::Inst_DivideRS),
+ tInstLibEntry<tMethod>("c-alloc", &cHardwareGX::Inst_CAlloc),
+ tInstLibEntry<tMethod>("c-divide", &cHardwareGX::Inst_CDivide),
+ tInstLibEntry<tMethod>("inject", &cHardwareGX::Inst_Inject),
+ tInstLibEntry<tMethod>("inject-r", &cHardwareGX::Inst_InjectRand),
+ tInstLibEntry<tMethod>("transposon", &cHardwareGX::Inst_Transposon),
+ tInstLibEntry<tMethod>("search-f", &cHardwareGX::Inst_SearchF),
+ tInstLibEntry<tMethod>("search-b", &cHardwareGX::Inst_SearchB),
+ tInstLibEntry<tMethod>("mem-size", &cHardwareGX::Inst_MemSize),
+
+ tInstLibEntry<tMethod>("get", &cHardwareGX::Inst_TaskGet),
+ tInstLibEntry<tMethod>("get-2", &cHardwareGX::Inst_TaskGet2),
+ tInstLibEntry<tMethod>("stk-get", &cHardwareGX::Inst_TaskStackGet),
+ tInstLibEntry<tMethod>("stk-load", &cHardwareGX::Inst_TaskStackLoad),
+ tInstLibEntry<tMethod>("put", &cHardwareGX::Inst_TaskPut),
+ tInstLibEntry<tMethod>("put-reset", &cHardwareGX::Inst_TaskPutResetInputs),
+ tInstLibEntry<tMethod>("IO", &cHardwareGX::Inst_TaskIO, nInstFlag::DEFAULT, "Output ?BX?, and input new number back into ?BX?"),
+ tInstLibEntry<tMethod>("IO-Feedback", &cHardwareGX::Inst_TaskIO_Feedback, 0, "Output ?BX?, and input new number back into ?BX?, and push 1,0, or -1 onto stack1 if merit increased, stayed the same, or decreased"),
+ tInstLibEntry<tMethod>("match-strings", &cHardwareGX::Inst_MatchStrings),
+ tInstLibEntry<tMethod>("sell", &cHardwareGX::Inst_Sell),
+ tInstLibEntry<tMethod>("buy", &cHardwareGX::Inst_Buy),
+ tInstLibEntry<tMethod>("send", &cHardwareGX::Inst_Send),
+ tInstLibEntry<tMethod>("receive", &cHardwareGX::Inst_Receive),
+ tInstLibEntry<tMethod>("sense", &cHardwareGX::Inst_SenseLog2),
+ tInstLibEntry<tMethod>("sense-unit", &cHardwareGX::Inst_SenseUnit),
+ tInstLibEntry<tMethod>("sense-m100", &cHardwareGX::Inst_SenseMult100),
+
+ tInstLibEntry<tMethod>("donate-rnd", &cHardwareGX::Inst_DonateRandom),
+ tInstLibEntry<tMethod>("donate-kin", &cHardwareGX::Inst_DonateKin),
+ tInstLibEntry<tMethod>("donate-edt", &cHardwareGX::Inst_DonateEditDist),
+ tInstLibEntry<tMethod>("donate-NUL", &cHardwareGX::Inst_DonateNULL),
+
+ tInstLibEntry<tMethod>("rotate-l", &cHardwareGX::Inst_RotateL),
+ tInstLibEntry<tMethod>("rotate-r", &cHardwareGX::Inst_RotateR),
+
+ tInstLibEntry<tMethod>("set-cmut", &cHardwareGX::Inst_SetCopyMut),
+ tInstLibEntry<tMethod>("mod-cmut", &cHardwareGX::Inst_ModCopyMut),
+
+ // Energy instruction
+ tInstLibEntry<tMethod>("recover", &cHardwareGX::Inst_ZeroEnergyUsed),
+
+ // Threading instructions
+ tInstLibEntry<tMethod>("fork-th", &cHardwareGX::Inst_ForkThread),
+ tInstLibEntry<tMethod>("kill-th", &cHardwareGX::Inst_KillThread),
+ tInstLibEntry<tMethod>("id-th", &cHardwareGX::Inst_ThreadID),
+
+ // Head-based instructions
+ tInstLibEntry<tMethod>("h-alloc", &cHardwareGX::Inst_MaxAlloc, nInstFlag::DEFAULT, "Allocate maximum allowed space"),
+ tInstLibEntry<tMethod>("h-divide", &cHardwareGX::Inst_HeadDivide, nInstFlag::DEFAULT, "Divide code between read and write heads."),
+ tInstLibEntry<tMethod>("h-divide1RS", &cHardwareGX::Inst_HeadDivide1RS, 0, "Divide code between read and write heads, at most one mutation on divide, resample if reverted."),
+ tInstLibEntry<tMethod>("h-divide2RS", &cHardwareGX::Inst_HeadDivide2RS, 0, "Divide code between read and write heads, at most two mutations on divide, resample if reverted."),
+ tInstLibEntry<tMethod>("h-divideRS", &cHardwareGX::Inst_HeadDivideRS, 0, "Divide code between read and write heads, resample if reverted."),
+ tInstLibEntry<tMethod>("h-read", &cHardwareGX::Inst_HeadRead),
+ tInstLibEntry<tMethod>("h-write", &cHardwareGX::Inst_HeadWrite),
+ tInstLibEntry<tMethod>("h-copy", &cHardwareGX::Inst_HeadCopy, nInstFlag::DEFAULT, "Copy from read-head to write-head; advance both"),
+ tInstLibEntry<tMethod>("h-search", &cHardwareGX::Inst_HeadSearch, nInstFlag::DEFAULT, "Find complement template and make with flow head"),
+ tInstLibEntry<tMethod>("h-push", &cHardwareGX::Inst_HeadPush),
+ tInstLibEntry<tMethod>("h-pop", &cHardwareGX::Inst_HeadPop),
+ tInstLibEntry<tMethod>("set-head", &cHardwareGX::Inst_SetHead),
+ tInstLibEntry<tMethod>("adv-head", &cHardwareGX::Inst_AdvanceHead),
+ tInstLibEntry<tMethod>("mov-head", &cHardwareGX::Inst_MoveHead, nInstFlag::DEFAULT, "Move head ?IP? to the flow head"),
+ tInstLibEntry<tMethod>("jmp-head", &cHardwareGX::Inst_JumpHead, nInstFlag::DEFAULT, "Move head ?IP? by amount in CX register; CX = old pos."),
+ tInstLibEntry<tMethod>("get-head", &cHardwareGX::Inst_GetHead, nInstFlag::DEFAULT, "Copy the position of the ?IP? head into CX"),
+ tInstLibEntry<tMethod>("if-label", &cHardwareGX::Inst_IfLabel, nInstFlag::DEFAULT, "Execute next if we copied complement of attached label"),
+ tInstLibEntry<tMethod>("if-label2", &cHardwareGX::Inst_IfLabel2, 0, "If copied label compl., exec next inst; else SKIP W/NOPS"),
+ tInstLibEntry<tMethod>("set-flow", &cHardwareGX::Inst_SetFlow, nInstFlag::DEFAULT, "Set flow-head to position in ?CX?"),
+
+ tInstLibEntry<tMethod>("h-copy2", &cHardwareGX::Inst_HeadCopy2),
+ tInstLibEntry<tMethod>("h-copy3", &cHardwareGX::Inst_HeadCopy3),
+ tInstLibEntry<tMethod>("h-copy4", &cHardwareGX::Inst_HeadCopy4),
+ tInstLibEntry<tMethod>("h-copy5", &cHardwareGX::Inst_HeadCopy5),
+ tInstLibEntry<tMethod>("h-copy6", &cHardwareGX::Inst_HeadCopy6),
+ tInstLibEntry<tMethod>("h-copy7", &cHardwareGX::Inst_HeadCopy7),
+ tInstLibEntry<tMethod>("h-copy8", &cHardwareGX::Inst_HeadCopy8),
+ tInstLibEntry<tMethod>("h-copy9", &cHardwareGX::Inst_HeadCopy9),
+ tInstLibEntry<tMethod>("h-copy10", &cHardwareGX::Inst_HeadCopy10),
+
+ tInstLibEntry<tMethod>("divide-sex", &cHardwareGX::Inst_HeadDivideSex),
+ tInstLibEntry<tMethod>("divide-asex", &cHardwareGX::Inst_HeadDivideAsex),
+
+ tInstLibEntry<tMethod>("div-sex", &cHardwareGX::Inst_HeadDivideSex),
+ tInstLibEntry<tMethod>("div-asex", &cHardwareGX::Inst_HeadDivideAsex),
+ tInstLibEntry<tMethod>("div-asex-w", &cHardwareGX::Inst_HeadDivideAsexWait),
+ tInstLibEntry<tMethod>("div-sex-MS", &cHardwareGX::Inst_HeadDivideMateSelect),
+
+ tInstLibEntry<tMethod>("h-divide1", &cHardwareGX::Inst_HeadDivide1),
+ tInstLibEntry<tMethod>("h-divide2", &cHardwareGX::Inst_HeadDivide2),
+ tInstLibEntry<tMethod>("h-divide3", &cHardwareGX::Inst_HeadDivide3),
+ tInstLibEntry<tMethod>("h-divide4", &cHardwareGX::Inst_HeadDivide4),
+ tInstLibEntry<tMethod>("h-divide5", &cHardwareGX::Inst_HeadDivide5),
+ tInstLibEntry<tMethod>("h-divide6", &cHardwareGX::Inst_HeadDivide6),
+ tInstLibEntry<tMethod>("h-divide7", &cHardwareGX::Inst_HeadDivide7),
+ tInstLibEntry<tMethod>("h-divide8", &cHardwareGX::Inst_HeadDivide8),
+ tInstLibEntry<tMethod>("h-divide9", &cHardwareGX::Inst_HeadDivide9),
+ tInstLibEntry<tMethod>("h-divide10", &cHardwareGX::Inst_HeadDivide10),
+ tInstLibEntry<tMethod>("h-divide16", &cHardwareGX::Inst_HeadDivide16),
+ tInstLibEntry<tMethod>("h-divide32", &cHardwareGX::Inst_HeadDivide32),
+ tInstLibEntry<tMethod>("h-divide50", &cHardwareGX::Inst_HeadDivide50),
+ tInstLibEntry<tMethod>("h-divide100", &cHardwareGX::Inst_HeadDivide100),
+ tInstLibEntry<tMethod>("h-divide500", &cHardwareGX::Inst_HeadDivide500),
+ tInstLibEntry<tMethod>("h-divide1000", &cHardwareGX::Inst_HeadDivide1000),
+ tInstLibEntry<tMethod>("h-divide5000", &cHardwareGX::Inst_HeadDivide5000),
+ tInstLibEntry<tMethod>("h-divide10000", &cHardwareGX::Inst_HeadDivide10000),
+ tInstLibEntry<tMethod>("h-divide50000", &cHardwareGX::Inst_HeadDivide50000),
+ tInstLibEntry<tMethod>("h-divide0.5", &cHardwareGX::Inst_HeadDivide0_5),
+ tInstLibEntry<tMethod>("h-divide0.1", &cHardwareGX::Inst_HeadDivide0_1),
+ tInstLibEntry<tMethod>("h-divide0.05", &cHardwareGX::Inst_HeadDivide0_05),
+ tInstLibEntry<tMethod>("h-divide0.01", &cHardwareGX::Inst_HeadDivide0_01),
+ tInstLibEntry<tMethod>("h-divide0.001", &cHardwareGX::Inst_HeadDivide0_001),
+
+ // High-level instructions
+ tInstLibEntry<tMethod>("repro", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-A", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-B", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-C", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-D", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-E", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-F", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-G", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-H", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-I", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-J", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-K", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-L", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-M", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-N", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-O", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-P", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-Q", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-R", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-S", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-T", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-U", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-V", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-W", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-X", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-Y", &cHardwareGX::Inst_Repro),
+ tInstLibEntry<tMethod>("repro-Z", &cHardwareGX::Inst_Repro),
+
+ tInstLibEntry<tMethod>("put-repro", &cHardwareGX::Inst_TaskPutRepro),
+ tInstLibEntry<tMethod>("metabolize", &cHardwareGX::Inst_TaskPutResetInputsRepro),
+
+ tInstLibEntry<tMethod>("spawn-deme", &cHardwareGX::Inst_SpawnDeme),
+
+ // Suicide
+ tInstLibEntry<tMethod>("kazi", &cHardwareGX::Inst_Kazi),
+ tInstLibEntry<tMethod>("kazi5", &cHardwareGX::Inst_Kazi5),
+ tInstLibEntry<tMethod>("die", &cHardwareGX::Inst_Die),
+
+ // Placebo instructions
+ tInstLibEntry<tMethod>("skip", &cHardwareGX::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 < NUM_REGISTERS; 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(tInstLibEntry<tMethod>);
+ static tMethod functions[f_size];
+ for (int i = 0; i < f_size; i++) functions[i] = s_f_array[i].GetFunction();
+
+ const cInstruction error(255);
+ const cInstruction def(0);
+
+ return new tInstLib<tMethod>(f_size, s_f_array, n_names, nop_mods, functions, error, def);
+}
+
+cHardwareGX::cHardwareGX(cWorld* world, cOrganism* in_organism, cInstSet* in_m_inst_set)
+: cHardwareBase(world, in_organism, in_m_inst_set)
+{
+ /* FIXME: reorganize storage of m_functions. -- kgn */
+ m_functions = s_inst_slib->GetFunctions();
+ /**/
+ m_memory = in_organism->GetGenome(); // Initialize memory...
+ Reset(); // Setup the rest of the hardware...
+}
+
+
+cHardwareGX::cHardwareGX(const cHardwareGX &hardware_cpu)
+: cHardwareBase(hardware_cpu.m_world, hardware_cpu.organism, hardware_cpu.m_inst_set)
+, m_functions(hardware_cpu.m_functions)
+, m_memory(hardware_cpu.m_memory)
+, m_global_stack(hardware_cpu.m_global_stack)
+, m_threads(hardware_cpu.m_threads)
+, m_thread_id_chart(hardware_cpu.m_thread_id_chart)
+, m_cur_thread(hardware_cpu.m_cur_thread)
+, m_mal_active(hardware_cpu.m_mal_active)
+, m_advance_ip(hardware_cpu.m_advance_ip)
+, m_executedmatchstrings(hardware_cpu.m_executedmatchstrings)
+#if INSTRUCTION_COSTS
+, inst_cost(hardware_cpu.inst_cost)
+, inst_ft_cost(hardware_cpu.inst_ft_cost)
+#endif
+{
+}
+
+
+void cHardwareGX::Reset()
+{
+ m_global_stack.Clear();
+
+ // We want to reset to have a single thread.
+ m_threads.Resize(1);
+
+ // Reset that single thread.
+ m_threads[0].Reset(this, 0);
+ m_thread_id_chart = 1; // Mark only the first thread as taken...
+ m_cur_thread = 0;
+
+ m_mal_active = false;
+ m_executedmatchstrings = false;
+
+#if INSTRUCTION_COSTS
+ // instruction cost arrays
+ const int num_inst_cost = m_inst_set->GetSize();
+ 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] = m_inst_set->GetCost(cInstruction(i));
+ inst_ft_cost[i] = m_inst_set->GetFTCost(cInstruction(i));
+ }
+#endif
+
+}
+
+void cHardwareGX::cLocalThread::operator=(const cLocalThread& in_thread)
+{
+ m_id = in_thread.m_id;
+ for (int i = 0; i < NUM_REGISTERS; i++) reg[i] = in_thread.reg[i];
+ for (int i = 0; i < NUM_HEADS; i++) heads[i] = in_thread.heads[i];
+ stack = in_thread.stack;
+}
+
+void cHardwareGX::cLocalThread::Reset(cHardwareBase* in_hardware, int in_id)
+{
+ m_id = in_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 = nHardware::HEAD_IP;
+ read_label.Clear();
+ next_label.Clear();
+}
+
+
+
+// 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 cHardwareGX::SingleProcess(cAvidaContext& ctx)
+{
+ // Mark this organism as running...
+ organism->SetRunning(true);
+
+ cPhenotype & phenotype = organism->GetPhenotype();
+ phenotype.IncTimeUsed();
+ phenotype.IncCPUCyclesUsed();
+
+ const int num_threads = GetNumThreads();
+
+ // 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 = (m_world->GetConfig().THREAD_SLICING_METHOD.Get() == 1) ?
+num_threads : 1;
+
+ for (int i = 0; i < num_inst_exec; i++) {
+ // Setup the hardware for the next instruction to be executed.
+ ThreadNext();
+ m_advance_ip = true;
+ IP().Adjust();
+
+#if BREAKPOINTS
+ if (IP().FlagBreakpoint()) {
+ organism->DoBreakpoint();
+ }
+#endif
+
+ // Print the status of this CPU at each step...
+ if (m_tracer != NULL) m_tracer->TraceHardware(*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...
+ bool exec = SingleProcess_PayCosts(ctx, cur_inst);
+
+ // Now execute the instruction...
+ if (exec == true) {
+ // NOTE: This call based on the cur_inst must occur prior to instruction
+ // execution, because this instruction reference may be invalid after
+ // certain classes of instructions (namely divide instructions) @DMB
+ const int addl_time_cost = m_inst_set->GetAddlTimeCost(cur_inst);
+
+ // Prob of exec (moved from SingleProcess_PayCosts so that we advance IP after a fail)
+ if ( m_inst_set->GetProbFail(cur_inst) > 0.0 )
+ {
+ exec = !( ctx.GetRandom().P(m_inst_set->GetProbFail(cur_inst)) );
+ }
+
+ if (exec == true) SingleProcess_ExecuteInst(ctx, cur_inst);
+
+ // Some instruction (such as jump) may turn m_advance_ip off. Usually
+ // we now want to move to the next instruction in the memory.
+ if (m_advance_ip == true) IP().Advance();
+
+ // Pay the additional death_cost of the instruction now
+ phenotype.IncTimeUsed(addl_time_cost);
+ } // 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 cHardwareGX::SingleProcess_PayCosts(cAvidaContext& ctx, const cInstruction& cur_inst)
+{
+#if 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 ( m_inst_set->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()] = m_inst_set->GetCost(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 cHardwareGX::SingleProcess_ExecuteInst(cAvidaContext& ctx, 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 = m_inst_set->GetRandomInst(ctx);
+#endif /* EXECUTION_ERRORS */
+
+ // Get a pointer to the corrisponding method...
+ int inst_idx = m_inst_set->GetLibFunctionIndex(actual_inst);
+
+ // Mark the instruction as executed
+ IP().SetFlagExecuted();
+
+
+#if 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]))(ctx);
+
+#if 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 cHardwareGX::ProcessBonusInst(cAvidaContext& ctx, const cInstruction& inst)
+{
+ // Mark this organism as running...
+ bool prev_run_state = organism->IsRunning();
+ organism->SetRunning(true);
+
+ if (m_tracer != NULL) m_tracer->TraceHardware(*this, true);
+
+ SingleProcess_ExecuteInst(ctx, inst);
+
+ organism->SetRunning(prev_run_state);
+}
+
+
+bool cHardwareGX::OK()
+{
+ bool result = true;
+
+ if (!m_memory.OK()) result = false;
+
+ for (int i = 0; i < GetNumThreads(); i++) {
+ if (m_threads[i].stack.OK() == false) result = false;
+ if (m_threads[i].next_label.OK() == false) result = false;
+ }
+
+ return result;
+}
+
+void cHardwareGX::PrintStatus(ostream& fp)
+{
+ fp << organism->GetPhenotype().GetCPUCyclesUsed() << " ";
+ fp << "IP:" << IP().GetPosition() << " ";
+
+ for (int i = 0; i < NUM_REGISTERS; i++) {
+ fp << static_cast<char>('A' + i) << "X:" << GetRegister(i) << " ";
+ fp << setbase(16) << "[0x" << GetRegister(i) << "] " << setbase(10);
+ }
+
+ // Add some extra information if additional time costs are used for instructions,
+ // leave this out if there are no differences to keep it cleaner
+ if ( organism->GetPhenotype().GetTimeUsed() != organism->GetPhenotype().GetCPUCyclesUsed() )
+ {
+ fp << " EnergyUsed:" << organism->GetPhenotype().GetTimeUsed();
+ }
+ fp << endl;
+
+ fp << " R-Head:" << GetHead(nHardware::HEAD_READ).GetPosition() << " "
+ << "W-Head:" << GetHead(nHardware::HEAD_WRITE).GetPosition() << " "
+ << "F-Head:" << GetHead(nHardware::HEAD_FLOW).GetPosition() << " "
+ << "RL:" << GetReadLabel().AsString() << " "
+ << endl;
+
+ int number_of_stacks = GetNumStacks();
+ for (int stack_id = 0; stack_id < number_of_stacks; stack_id++) {
+ fp << ((m_threads[m_cur_thread].cur_stack == stack_id) ? '*' : ' ') << " Stack " << stack_id << ":" << setbase(16) << setfill('0');
+ for (int i = 0; i < nHardware::STACK_SIZE; i++) fp << " Ox" << setw(8) << GetStack(i, stack_id, 0);
+ fp << setfill(' ') << setbase(10) << endl;
+ }
+
+ fp << " Mem (" << GetMemory().GetSize() << "):"
+ << " " << GetMemory().AsString()
+ << endl;
+ fp.flush();
+}
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// Method: cHardwareGX::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 cHardwareGX::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 cHardwareGX::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 (m_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 &&
+ m_inst_set->IsNop( search_genome[start_pos - 1] )) {
+ start_pos--;
+ }
+ while (end_pos < search_genome.GetSize() &&
+ m_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] !=
+ m_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 cHardwareGX::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 (m_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 && m_inst_set->IsNop(search_genome[start_pos - 1])) {
+ start_pos--;
+ }
+ while (end_pos < search_start &&
+ m_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] !=
+ m_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 cHardwareGX::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 (!m_inst_set->IsNop(temp_head.GetInst()) ||
+ in_label[i] != m_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;
+}
+
+
+bool cHardwareGX::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 = FindLabelFull(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!)
+}
+
+void cHardwareGX::InjectCode(const cGenome & inject_code, const int line_num)
+{
+ assert(line_num >= 0);
+ assert(line_num <= m_memory.GetSize());
+ assert(m_memory.GetSize() + inject_code.GetSize() < MAX_CREATURE_SIZE);
+
+ // Inject the new code.
+ const int inject_size = inject_code.GetSize();
+ m_memory.Insert(line_num, inject_code);
+
+ // Set instruction flags on the injected code
+ for (int i = line_num; i < line_num + inject_size; i++) {
+ m_memory.SetFlagInjected(i);
+ }
+ 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).GetPosition() > line_num) GetHead(i).Jump(inject_size);
+ }
+}
+
+
+void cHardwareGX::ReadInst(const int in_inst)
+{
+ if (m_inst_set->IsNop( cInstruction(in_inst) )) {
+ GetReadLabel().AddNop(in_inst);
+ } else {
+ GetReadLabel().Clear();
+ }
+}
+
+
+void cHardwareGX::AdjustHeads()
+{
+ for (int i = 0; i < GetNumThreads(); i++) {
+ for (int j = 0; j < NUM_HEADS; j++) {
+ m_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 cHardwareGX::ReadLabel(int max_size)
+{
+ int count = 0;
+ cHeadCPU * inst_ptr = &( IP() );
+
+ GetLabel().Clear();
+
+ while (m_inst_set->IsNop(inst_ptr->GetNextInst()) &&
+ (count < max_size)) {
+ count++;
+ inst_ptr->Advance();
+ GetLabel().AddNop(m_inst_set->GetNopMod(inst_ptr->GetInst()));
+
+ // If this is the first line of the template, mark it executed.
+ if (GetLabel().GetSize() <= m_world->GetConfig().MAX_LABEL_EXE_SIZE.Get()) {
+ inst_ptr->SetFlagExecuted();
+ }
+ }
+}
+
+
+bool cHardwareGX::ForkThread()
+{
+ const int num_threads = GetNumThreads();
+ if (num_threads == m_world->GetConfig().MAX_CPU_THREADS.Get()) return false;
+
+ // Make room for the new thread.
+ m_threads.Resize(num_threads + 1);
+
+ // Initialize the new thread to the same values as the current one.
+ m_threads[num_threads] = m_threads[m_cur_thread];
+
+ // Find the first free bit in m_thread_id_chart to determine the new
+ // thread id.
+ int new_id = 0;
+ while ( (m_thread_id_chart >> new_id) & 1 == 1) new_id++;
+ m_threads[num_threads].SetID(new_id);
+ m_thread_id_chart |= (1 << new_id);
+
+ return true;
+}
+
+
+bool cHardwareGX::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 = m_cur_thread;
+ ThreadPrev();
+
+ // Turn off this bit in the m_thread_id_chart...
+ m_thread_id_chart ^= 1 << m_threads[kill_thread].GetID();
+
+ // Copy the last thread into the kill position
+ const int last_thread = GetNumThreads() - 1;
+ if (last_thread != kill_thread) {
+ m_threads[kill_thread] = m_threads[last_thread];
+ }
+
+ // Kill the thread!
+ m_threads.Resize(GetNumThreads() - 1);
+
+ if (m_cur_thread > kill_thread) m_cur_thread--;
+
+ return true;
+}
+
+////////////////////////////
+// Instruction Helpers...
+////////////////////////////
+
+inline int cHardwareGX::FindModifiedRegister(int default_register)
+{
+ assert(default_register < NUM_REGISTERS); // Reg ID too high.
+
+ if (m_inst_set->IsNop(IP().GetNextInst())) {
+ IP().Advance();
+ default_register = m_inst_set->GetNopMod(IP().GetInst());
+ IP().SetFlagExecuted();
+ }
+ return default_register;
+}
+
+inline int cHardwareGX::FindModifiedNextRegister(int default_register)
+{
+ assert(default_register < NUM_REGISTERS); // Reg ID too high.
+
+ if (m_inst_set->IsNop(IP().GetNextInst())) {
+ IP().Advance();
+ default_register = m_inst_set->GetNopMod(IP().GetInst());
+ IP().SetFlagExecuted();
+ } else {
+ default_register = (default_register + 1) % NUM_REGISTERS;
+ }
+ return default_register;
+}
+
+inline int cHardwareGX::FindModifiedPreviousRegister(int default_register)
+{
+ assert(default_register < NUM_REGISTERS); // Reg ID too high.
+
+ if (m_inst_set->IsNop(IP().GetNextInst())) {
+ IP().Advance();
+ default_register = m_inst_set->GetNopMod(IP().GetInst());
+ IP().SetFlagExecuted();
+ } else {
+ default_register = (default_register + NUM_REGISTERS - 1) % NUM_REGISTERS;
+ }
+ return default_register;
+}
+
+
+inline int cHardwareGX::FindModifiedHead(int default_head)
+{
+ assert(default_head < NUM_HEADS); // Head ID too high.
+
+ if (m_inst_set->IsNop(IP().GetNextInst())) {
+ IP().Advance();
+ default_head = m_inst_set->GetNopMod(IP().GetInst());
+ IP().SetFlagExecuted();
+ }
+ return default_head;
+}
+
+
+inline int cHardwareGX::FindNextRegister(int base_reg)
+{
+ return (base_reg + 1) % NUM_REGISTERS;
+}
+
+
+bool cHardwareGX::Allocate_Necro(const int new_size)
+{
+ GetMemory().ResizeOld(new_size);
+ return true;
+}
+
+bool cHardwareGX::Allocate_Random(cAvidaContext& ctx, const int old_size, const int new_size)
+{
+ GetMemory().Resize(new_size);
+
+ for (int i = old_size; i < new_size; i++) {
+ GetMemory()[i] = m_inst_set->GetRandomInst(ctx);
+ }
+ return true;
+}
+
+bool cHardwareGX::Allocate_Default(const int new_size)
+{
+ GetMemory().Resize(new_size);
+
+ // New space already defaults to default instruction...
+
+ return true;
+}
+
+bool cHardwareGX::Allocate_Main(cAvidaContext& ctx, const int allocated_size)
+{
+ // must do divide before second allocate & must allocate positive amount...
+ if (m_world->GetConfig().REQUIRE_ALLOCATE.Get() && m_mal_active == true) {
+ organism->Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR, "Allocate already active");
+ return false;
+ }
+ if (allocated_size < 1) {
+ organism->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) {
+ organism->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 * m_world->GetConfig().CHILD_SIZE_RANGE.Get());
+ if (allocated_size > max_alloc_size) {
+ organism->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 * m_world->GetConfig().CHILD_SIZE_RANGE.Get());
+ if (old_size > max_old_size) {
+ organism->Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+ cStringUtil::Stringf("Allocate too small (%d > %d)",
+ old_size, max_old_size));
+ return false;
+ }
+
+ switch (m_world->GetConfig().ALLOC_METHOD.Get()) {
+ 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(ctx, old_size, new_size);
+ break;
+ case ALLOC_METHOD_DEFAULT:
+ Allocate_Default(new_size);
+ break;
+ }
+
+ m_mal_active = true;
+
+ return true;
+}
+
+int cHardwareGX::GetCopiedSize(const int parent_size, const int child_size)
+{
+ int copied_size = 0;
+ const cCPUMemory& memory = GetMemory();
+ for (int i = parent_size; i < parent_size + child_size; i++) {
+ if (memory.FlagCopied(i)) copied_size++;
+ }
+ return copied_size;
+}
+
+
+bool cHardwareGX::Divide_Main(cAvidaContext& ctx, 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(ctx, div_point, child_size);
+ 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(m_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(ctx, 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(ctx);
+
+#if INSTRUCTION_COSTS
+ // reset first time instruction costs
+ for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+ inst_ft_cost[i] = m_inst_set->GetFTCost(cInstruction(i));
+ }
+#endif
+
+ m_mal_active = false;
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
+ m_advance_ip = false;
+ }
+
+ // Activate the child
+ bool parent_alive = organism->ActivateDivide(ctx);
+
+ // Do more work if the parent lives through the birth of the offspring
+ if (parent_alive) {
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) Reset();
+ }
+
+ return true;
+}
+
+/*
+ Almost the same as Divide_Main, but resamples reverted offspring.
+
+ RESAMPLING ONLY WORKS CORRECTLY WHEN ALL MUTIONS OCCUR ON DIVIDE!!
+
+ AWC - 06/29/06
+*/
+bool cHardwareGX::Divide_MainRS(cAvidaContext& ctx, const int div_point,
+ const int extra_lines, double mut_multiplier)
+{
+
+ //cStats stats = m_world->GetStats();
+ const int child_size = GetMemory().GetSize() - div_point - extra_lines;
+
+ // Make sure this divide will produce a viable offspring.
+ const bool viable = Divide_CheckViable(ctx, div_point, child_size);
+ 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(m_memory, div_point, div_point+child_size);
+
+ // Cut off everything in this memory past the divide point.
+ GetMemory().Resize(div_point);
+
+ unsigned
+ totalMutations = 0,
+ mutations = 0;
+ //RScount = 0;
+
+
+ bool
+ fitTest = false;
+
+ // Handle Divide Mutations...
+ /*
+ Do mutations until one of these conditions are satisified:
+ we have resampled X times
+ we have an offspring with the same number of muations as the first offspring
+ that is not reverted
+ the parent is steralized (usually means an implicit mutation)
+ */
+ for(unsigned i = 0; i <= 100; i++){
+ if(i == 0){
+ mutations = totalMutations = Divide_DoMutations(ctx, mut_multiplier);
+ }
+ else{
+ mutations = Divide_DoMutations(ctx, mut_multiplier);
+ m_world->GetStats().IncResamplings();
+ }
+
+ fitTest = Divide_TestFitnessMeasures(ctx);
+
+ if(!fitTest && mutations >= totalMutations) break;
+
+ }
+ // think about making this mutations == totalMuations - though this may be too hard...
+ /*
+ if(RScount > 2)
+ cerr << "Resampled " << RScount << endl;
+ */
+ //org could not be resampled beneath the hard cap -- it is then steraalized
+ if(fitTest/*RScount == 11*/) {
+ organism->GetPhenotype().ChildFertile() = false;
+ m_world->GetStats().IncFailedResamplings();
+ }
+
+#if INSTRUCTION_COSTS
+ // reset first time instruction costs
+ for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+ inst_ft_cost[i] = m_inst_set->GetFTCost(cInstruction(i));
+ }
+#endif
+
+ m_mal_active = false;
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
+ m_advance_ip = false;
+ }
+
+ // Activate the child, and do more work if the parent lives through the
+ // birth.
+ bool parent_alive = organism->ActivateDivide(ctx);
+ if (parent_alive) {
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) Reset();
+ }
+
+ return true;
+}
+
+/*
+ Almost the same as Divide_Main, but only allows for one mutation
+ on divde and resamples reverted offspring.
+
+ RESAMPLING ONLY WORKS CORRECTLY WHEN ALL MUTIONS OCCUR ON DIVIDE!!
+
+ AWC - 07/28/06
+*/
+bool cHardwareGX::Divide_Main1RS(cAvidaContext& ctx, const int div_point,
+ const int extra_lines, double mut_multiplier)
+{
+
+ //cStats stats = m_world->GetStats();
+ const int child_size = GetMemory().GetSize() - div_point - extra_lines;
+
+ // Make sure this divide will produce a viable offspring.
+ const bool viable = Divide_CheckViable(ctx, div_point, child_size);
+ 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(m_memory, div_point, div_point+child_size);
+
+ // Cut off everything in this memory past the divide point.
+ GetMemory().Resize(div_point);
+
+ unsigned
+ totalMutations = 0,
+ mutations = 0;
+ // RScount = 0;
+
+ bool
+ fitTest = false;
+
+
+ // Handle Divide Mutations...
+ /*
+ Do mutations until one of these conditions are satisified:
+ we have resampled X times
+ we have an offspring with the same number of muations as the first offspring
+ that is not reverted
+ the parent is steralized (usually means an implicit mutation)
+ */
+ for(unsigned i = 0; i < 100; i++){
+ if(!i){
+ mutations = totalMutations = Divide_DoMutations(ctx, mut_multiplier,1);
+ }
+ else{
+ mutations = Divide_DoExactMutations(ctx, mut_multiplier,1);
+ m_world->GetStats().IncResamplings();
+ }
+
+ fitTest = Divide_TestFitnessMeasures(ctx);
+ //if(mutations > 1 ) cerr << "Too Many mutations!!!!!!!!!!!!!!!" << endl;
+ if(!fitTest && mutations >= totalMutations) break;
+
+ }
+ // think about making this mutations == totalMuations - though this may be too hard...
+ /*
+ if(RScount > 2)
+ cerr << "Resampled " << RScount << endl;
+ */
+ //org could not be resampled beneath the hard cap -- it is then steraalized
+ if(fitTest/*RScount == 11*/) {
+ organism->GetPhenotype().ChildFertile() = false;
+ m_world->GetStats().IncFailedResamplings();
+ }
+
+#if INSTRUCTION_COSTS
+ // reset first time instruction costs
+ for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+ inst_ft_cost[i] = m_inst_set->GetFTCost(cInstruction(i));
+ }
+#endif
+
+ m_mal_active = false;
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
+ m_advance_ip = false;
+ }
+
+ // Activate the child, and do more work if the parent lives through the
+ // birth.
+ bool parent_alive = organism->ActivateDivide(ctx);
+ if (parent_alive) {
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) Reset();
+ }
+
+ return true;
+}
+
+/*
+ Almost the same as Divide_Main, but only allows for one mutation
+ on divde and resamples reverted offspring.
+
+ RESAMPLING ONLY WORKS CORRECTLY WHEN ALL MUTIONS OCCUR ON DIVIDE!!
+
+ AWC - 07/28/06
+*/
+bool cHardwareGX::Divide_Main2RS(cAvidaContext& ctx, const int div_point,
+ const int extra_lines, double mut_multiplier)
+{
+
+ //cStats stats = m_world->GetStats();
+ const int child_size = GetMemory().GetSize() - div_point - extra_lines;
+
+ // Make sure this divide will produce a viable offspring.
+ const bool viable = Divide_CheckViable(ctx, div_point, child_size);
+ 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(m_memory, div_point, div_point+child_size);
+
+ // Cut off everything in this memory past the divide point.
+ GetMemory().Resize(div_point);
+
+ unsigned
+ totalMutations = 0,
+ mutations = 0;
+ // RScount = 0;
+
+ bool
+ fitTest = false;
+
+
+ // Handle Divide Mutations...
+ /*
+ Do mutations until one of these conditions are satisified:
+ we have resampled X times
+ we have an offspring with the same number of muations as the first offspring
+ that is not reverted
+ the parent is steralized (usually means an implicit mutation)
+ */
+ for(unsigned i = 0; i < 100; i++){
+ if(!i){
+ mutations = totalMutations = Divide_DoMutations(ctx, mut_multiplier,2);
+ }
+ else{
+ Divide_DoExactMutations(ctx, mut_multiplier,mutations);
+ m_world->GetStats().IncResamplings();
+ }
+
+ fitTest = Divide_TestFitnessMeasures(ctx);
+ //if(mutations > 1 ) cerr << "Too Many mutations!!!!!!!!!!!!!!!" << endl;
+ if(!fitTest && mutations >= totalMutations) break;
+
+ }
+ // think about making this mutations == totalMuations - though this may be too hard...
+ /*
+ if(RScount > 2)
+ cerr << "Resampled " << RScount << endl;
+ */
+ //org could not be resampled beneath the hard cap -- it is then steraalized
+ if(fitTest/*RScount == 11*/) {
+ organism->GetPhenotype().ChildFertile() = false;
+ m_world->GetStats().IncFailedResamplings();
+ }
+
+#if INSTRUCTION_COSTS
+ // reset first time instruction costs
+ for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+ inst_ft_cost[i] = m_inst_set->GetFTCost(cInstruction(i));
+ }
+#endif
+
+ m_mal_active = false;
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
+ m_advance_ip = false;
+ }
+
+ // Activate the child, and do more work if the parent lives through the
+ // birth.
+ bool parent_alive = organism->ActivateDivide(ctx);
+ if (parent_alive) {
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) Reset();
+ }
+
+ return true;
+}
+
+
+//////////////////////////
+// And the instructions...
+//////////////////////////
+
+bool cHardwareGX::Inst_If0(cAvidaContext& ctx) // Execute next if ?bx? ==0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (GetRegister(reg_used) != 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfNot0(cAvidaContext& ctx) // Execute next if ?bx? != 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (GetRegister(reg_used) == 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfEqu(cAvidaContext& ctx) // Execute next if bx == ?cx?
+{
+ const int op1 = FindModifiedRegister(REG_BX);
+ const int op2 = FindNextRegister(op1);
+ if (GetRegister(op1) != GetRegister(op2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfNEqu(cAvidaContext& ctx) // Execute next if bx != ?cx?
+{
+ const int op1 = FindModifiedRegister(REG_BX);
+ const int op2 = FindNextRegister(op1);
+ if (GetRegister(op1) == GetRegister(op2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfGr0(cAvidaContext& ctx) // Execute next if ?bx? ! < 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (GetRegister(reg_used) <= 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfGr(cAvidaContext& ctx) // Execute next if bx > ?cx?
+{
+ const int op1 = FindModifiedRegister(REG_BX);
+ const int op2 = FindNextRegister(op1);
+ if (GetRegister(op1) <= GetRegister(op2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfGrEqu0(cAvidaContext& ctx) // Execute next if ?bx? != 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (GetRegister(reg_used) < 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfGrEqu(cAvidaContext& ctx) // Execute next if bx > ?cx?
+{
+ const int op1 = FindModifiedRegister(REG_BX);
+ const int op2 = FindNextRegister(op1);
+ if (GetRegister(op1) < GetRegister(op2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfLess0(cAvidaContext& ctx) // Execute next if ?bx? != 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (GetRegister(reg_used) >= 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfLess(cAvidaContext& ctx) // Execute next if ?bx? < ?cx?
+{
+ const int op1 = FindModifiedRegister(REG_BX);
+ const int op2 = FindNextRegister(op1);
+ if (GetRegister(op1) >= GetRegister(op2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfLsEqu0(cAvidaContext& ctx) // Execute next if ?bx? != 0.
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if (GetRegister(reg_used) > 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfLsEqu(cAvidaContext& ctx) // Execute next if bx > ?cx?
+{
+ const int op1 = FindModifiedRegister(REG_BX);
+ const int op2 = FindNextRegister(op1);
+ if (GetRegister(op1) > GetRegister(op2)) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfBit1(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ if ((GetRegister(reg_used) & 1) == 0) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfANotEqB(cAvidaContext& ctx) // Execute next if AX != BX
+{
+ if (GetRegister(REG_AX) == GetRegister(REG_BX) ) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfBNotEqC(cAvidaContext& ctx) // Execute next if BX != CX
+{
+ if (GetRegister(REG_BX) == GetRegister(REG_CX) ) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfANotEqC(cAvidaContext& ctx) // Execute next if AX != BX
+{
+ if (GetRegister(REG_AX) == GetRegister(REG_CX) ) IP().Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_JumpF(cAvidaContext& ctx)
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+
+ // If there is no label, jump BX steps.
+ if (GetLabel().GetSize() == 0) {
+ GetActiveHead().Jump(GetRegister(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 cHardwareGX::Inst_JumpB(cAvidaContext& ctx)
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+
+ // If there is no label, jump BX steps.
+ if (GetLabel().GetSize() == 0) {
+ GetActiveHead().Jump(GetRegister(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 cHardwareGX::Inst_Call(cAvidaContext& ctx)
+{
+ // 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(GetRegister(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 cHardwareGX::Inst_Return(cAvidaContext& ctx)
+{
+ IP().Set(StackPop());
+ return true;
+}
+
+bool cHardwareGX::Inst_Throw(cAvidaContext& ctx)
+{
+ // Only initialize this once to save some time...
+ static cInstruction catch_inst = GetInstSet().GetInst(cStringUtil::Stringf("catch"));
+
+ //Look for the label directly (no complement)
+ ReadLabel();
+
+ cHeadCPU search_head(IP());
+ int start_pos = search_head.GetPosition();
+ search_head++;
+
+ while (start_pos != search_head.GetPosition())
+ {
+ // If we find a catch instruction, compare the NOPs following it
+ if (search_head.GetInst() == catch_inst)
+ {
+ int catch_pos = search_head.GetPosition();
+ search_head++;
+
+ // Continue to examine the label after the catch
+ // (1) It ends (=> use the catch!)
+ // (2) It becomes longer than the throw label (=> use the catch!)
+ // (3) We find a NOP that doesnt match the throw (=> DON'T use the catch...)
+
+ bool match = true;
+ int size_matched = 0;
+ while ( match && m_inst_set->IsNop(search_head.GetInst()) && (size_matched < GetLabel().GetSize()) )
+ {
+ if ( GetLabel()[size_matched] != m_inst_set->GetNopMod( search_head.GetInst()) ) match = false;
+ search_head++;
+ size_matched++;
+ }
+
+ // We found a matching catch instruction
+ if (match)
+ {
+ IP().Set(catch_pos);
+ m_advance_ip = false; // Don't automatically move the IP
+ // so we mark the catch as executed.
+ return true;
+ }
+
+ //If we advanced past NOPs during testing, retreat
+ if ( !m_inst_set->IsNop(search_head.GetInst()) ) search_head--;
+ }
+ search_head.Advance();
+ }
+
+ return false;
+}
+
+
+bool cHardwareGX::Inst_ThrowIfNot0(cAvidaContext& ctx)
+{
+ if (GetRegister(REG_BX) == 0) return false;
+ return Inst_Throw(ctx);
+}
+
+bool cHardwareGX::Inst_ThrowIf0(cAvidaContext& ctx)
+{
+ if (GetRegister(REG_BX) != 0) return false;
+ return Inst_Throw(ctx);
+}
+
+bool cHardwareGX::Inst_Goto(cAvidaContext& ctx)
+{
+ // Only initialize this once to save some time...
+ static cInstruction label_inst = GetInstSet().GetInst(cStringUtil::Stringf("label"));
+
+ //Look for an EXACT label match after a 'label' instruction
+ ReadLabel();
+
+ cHeadCPU search_head(IP());
+ int start_pos = search_head.GetPosition();
+ search_head++;
+
+ while (start_pos != search_head.GetPosition())
+ {
+ if (search_head.GetInst() == label_inst)
+ {
+ int label_pos = search_head.GetPosition();
+ search_head++;
+ int size_matched = 0;
+ while ( size_matched < GetLabel().GetSize() )
+ {
+ if ( !m_inst_set->IsNop(search_head.GetInst()) ) break;
+ if ( GetLabel()[size_matched] != m_inst_set->GetNopMod( search_head.GetInst()) ) break;
+ if ( !m_inst_set->IsNop(search_head.GetInst()) ) break;
+
+ size_matched++;
+ search_head++;
+ }
+
+ // We found a matching 'label' instruction only if the next
+ // instruction (at the search head now) is also not a NOP
+ if ( (size_matched == GetLabel().GetSize()) && !m_inst_set->IsNop(search_head.GetInst()) )
+ {
+ IP().Set(label_pos);
+ m_advance_ip = false; // Don't automatically move the IP
+ // so we mark the catch as executed.
+ return true;
+ }
+
+ //If we advanced past NOPs during testing, retreat
+ if ( !m_inst_set->IsNop(search_head.GetInst()) ) search_head--;
+ }
+ search_head++;
+ }
+
+ return false;
+}
+
+
+bool cHardwareGX::Inst_GotoIfNot0(cAvidaContext& ctx)
+{
+ if (GetRegister(REG_BX) == 0) return false;
+ return Inst_Goto(ctx);
+}
+
+bool cHardwareGX::Inst_GotoIf0(cAvidaContext& ctx)
+{
+ if (GetRegister(REG_BX) != 0) return false;
+ return Inst_Goto(ctx);
+}
+
+
+bool cHardwareGX::Inst_Pop(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ GetRegister(reg_used) = StackPop();
+ return true;
+}
+
+bool cHardwareGX::Inst_Push(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ StackPush(GetRegister(reg_used));
+ return true;
+}
+
+bool cHardwareGX::Inst_HeadPop(cAvidaContext& ctx)
+{
+ const int head_used = FindModifiedHead(nHardware::HEAD_IP);
+ GetHead(head_used).Set(StackPop());
+ return true;
+}
+
+bool cHardwareGX::Inst_HeadPush(cAvidaContext& ctx)
+{
+ const int head_used = FindModifiedHead(nHardware::HEAD_IP);
+ StackPush(GetHead(head_used).GetPosition());
+ if (head_used == nHardware::HEAD_IP) {
+ GetHead(head_used).Set(GetHead(nHardware::HEAD_FLOW));
+ m_advance_ip = false;
+ }
+ return true;
+}
+
+
+bool cHardwareGX::Inst_PopA(cAvidaContext& ctx) { GetRegister(REG_AX) = StackPop(); return true;}
+bool cHardwareGX::Inst_PopB(cAvidaContext& ctx) { GetRegister(REG_BX) = StackPop(); return true;}
+bool cHardwareGX::Inst_PopC(cAvidaContext& ctx) { GetRegister(REG_CX) = StackPop(); return true;}
+
+bool cHardwareGX::Inst_PushA(cAvidaContext& ctx) { StackPush(GetRegister(REG_AX)); return true;}
+bool cHardwareGX::Inst_PushB(cAvidaContext& ctx) { StackPush(GetRegister(REG_BX)); return true;}
+bool cHardwareGX::Inst_PushC(cAvidaContext& ctx) { StackPush(GetRegister(REG_CX)); return true;}
+
+bool cHardwareGX::Inst_SwitchStack(cAvidaContext& ctx) { SwitchStack(); return true;}
+bool cHardwareGX::Inst_FlipStack(cAvidaContext& ctx) { StackFlip(); return true;}
+
+bool cHardwareGX::Inst_Swap(cAvidaContext& ctx)
+{
+ const int op1 = FindModifiedRegister(REG_BX);
+ const int op2 = FindNextRegister(op1);
+ nFunctions::Swap(GetRegister(op1), GetRegister(op2));
+ return true;
+}
+
+bool cHardwareGX::Inst_SwapAB(cAvidaContext& ctx)\
+{
+ nFunctions::Swap(GetRegister(REG_AX), GetRegister(REG_BX)); return true;
+}
+bool cHardwareGX::Inst_SwapBC(cAvidaContext& ctx)
+{
+ nFunctions::Swap(GetRegister(REG_BX), GetRegister(REG_CX)); return true;
+}
+bool cHardwareGX::Inst_SwapAC(cAvidaContext& ctx)
+{
+ nFunctions::Swap(GetRegister(REG_AX), GetRegister(REG_CX)); return true;
+}
+
+bool cHardwareGX::Inst_CopyReg(cAvidaContext& ctx)
+{
+ const int src = FindModifiedRegister(REG_BX);
+ const int dst = FindNextRegister(src);
+ GetRegister(dst) = GetRegister(src);
+ return true;
+}
+
+bool cHardwareGX::Inst_CopyRegAB(cAvidaContext& ctx)
+{
+ GetRegister(REG_AX) = GetRegister(REG_BX); return true;
+}
+bool cHardwareGX::Inst_CopyRegAC(cAvidaContext& ctx)
+{
+ GetRegister(REG_AX) = GetRegister(REG_CX); return true;
+}
+bool cHardwareGX::Inst_CopyRegBA(cAvidaContext& ctx)
+{
+ GetRegister(REG_BX) = GetRegister(REG_AX); return true;
+}
+bool cHardwareGX::Inst_CopyRegBC(cAvidaContext& ctx)
+{
+ GetRegister(REG_BX) = GetRegister(REG_CX); return true;
+}
+bool cHardwareGX::Inst_CopyRegCA(cAvidaContext& ctx)
+{
+ GetRegister(REG_CX) = GetRegister(REG_AX); return true;
+}
+bool cHardwareGX::Inst_CopyRegCB(cAvidaContext& ctx)
+{
+ GetRegister(REG_CX) = GetRegister(REG_BX); return true;
+}
+
+bool cHardwareGX::Inst_Reset(cAvidaContext& ctx)
+{
+ GetRegister(REG_AX) = 0;
+ GetRegister(REG_BX) = 0;
+ GetRegister(REG_CX) = 0;
+ StackClear();
+ return true;
+}
+
+bool cHardwareGX::Inst_ShiftR(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ GetRegister(reg_used) >>= 1;
+ return true;
+}
+
+bool cHardwareGX::Inst_ShiftL(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ GetRegister(reg_used) <<= 1;
+ return true;
+}
+
+bool cHardwareGX::Inst_Bit1(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ GetRegister(reg_used) |= 1;
+ return true;
+}
+
+bool cHardwareGX::Inst_SetNum(cAvidaContext& ctx)
+{
+ ReadLabel();
+ GetRegister(REG_BX) = GetLabel().AsInt(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareGX::Inst_ValGrey(cAvidaContext& ctx) {
+ ReadLabel();
+ GetRegister(REG_BX) = GetLabel().AsIntGreyCode(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareGX::Inst_ValDir(cAvidaContext& ctx) {
+ ReadLabel();
+ GetRegister(REG_BX) = GetLabel().AsIntDirect(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareGX::Inst_ValAddP(cAvidaContext& ctx) {
+ ReadLabel();
+ GetRegister(REG_BX) = GetLabel().AsIntAdditivePolynomial(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareGX::Inst_ValFib(cAvidaContext& ctx) {
+ ReadLabel();
+ GetRegister(REG_BX) = GetLabel().AsIntFib(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareGX::Inst_ValPolyC(cAvidaContext& ctx) {
+ ReadLabel();
+ GetRegister(REG_BX) = GetLabel().AsIntPolynomialCoefficent(NUM_NOPS);
+ return true;
+}
+
+bool cHardwareGX::Inst_Inc(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ GetRegister(reg_used) += 1;
+ return true;
+}
+
+bool cHardwareGX::Inst_Dec(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ GetRegister(reg_used) -= 1;
+ return true;
+}
+
+bool cHardwareGX::Inst_Zero(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ GetRegister(reg_used) = 0;
+ return true;
+}
+
+bool cHardwareGX::Inst_Neg(cAvidaContext& ctx)
+{
+ const int src = FindModifiedRegister(REG_BX);
+ const int dst = src;
+ GetRegister(dst) = -GetRegister(src);
+ return true;
+}
+
+bool cHardwareGX::Inst_Square(cAvidaContext& ctx)
+{
+ const int src = FindModifiedRegister(REG_BX);
+ const int dst = src;
+ GetRegister(dst) = GetRegister(src) * GetRegister(src);
+ return true;
+}
+
+bool cHardwareGX::Inst_Sqrt(cAvidaContext& ctx)
+{
+ const int src = FindModifiedRegister(REG_BX);
+ const int dst = src;
+ const int value = GetRegister(src);
+ if (value > 1) GetRegister(dst) = static_cast<int>(sqrt(static_cast<double>(value)));
+ else if (value < 0) {
+ organism->Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "sqrt: value is negative");
+ return false;
+ }
+ return true;
+}
+
+bool cHardwareGX::Inst_Log(cAvidaContext& ctx)
+{
+ const int src = FindModifiedRegister(REG_BX);
+ const int dst = src;
+ const int value = GetRegister(src);
+ if (value >= 1) GetRegister(dst) = static_cast<int>(log(static_cast<double>(value)));
+ else if (value < 0) {
+ organism->Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "log: value is negative");
+ return false;
+ }
+ return true;
+}
+
+bool cHardwareGX::Inst_Log10(cAvidaContext& ctx)
+{
+ const int src = FindModifiedRegister(REG_BX);
+ const int dst = src;
+ const int value = GetRegister(src);
+ if (value >= 1) GetRegister(dst) = static_cast<int>(log10(static_cast<double>(value)));
+ else if (value < 0) {
+ organism->Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "log10: value is negative");
+ return false;
+ }
+ return true;
+}
+
+bool cHardwareGX::Inst_Add(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ GetRegister(dst) = GetRegister(op1) + GetRegister(op2);
+ return true;
+}
+
+bool cHardwareGX::Inst_Sub(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ GetRegister(dst) = GetRegister(op1) - GetRegister(op2);
+ return true;
+}
+
+bool cHardwareGX::Inst_Mult(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ GetRegister(dst) = GetRegister(op1) * GetRegister(op2);
+ return true;
+}
+
+bool cHardwareGX::Inst_Div(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ if (GetRegister(op2) != 0) {
+ if (0-INT_MAX > GetRegister(op1) && GetRegister(op2) == -1)
+ organism->Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: Float exception");
+ else
+ GetRegister(dst) = GetRegister(op1) / GetRegister(op2);
+ } else {
+ organism->Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "div: dividing by 0");
+ return false;
+ }
+ return true;
+}
+
+bool cHardwareGX::Inst_Mod(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ if (GetRegister(op2) != 0) {
+ GetRegister(dst) = GetRegister(op1) % GetRegister(op2);
+ } else {
+ organism->Fault(FAULT_LOC_MATH, FAULT_TYPE_ERROR, "mod: modding by 0");
+ return false;
+ }
+ return true;
+}
+
+
+bool cHardwareGX::Inst_Nand(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ GetRegister(dst) = ~(GetRegister(op1) & GetRegister(op2));
+ return true;
+}
+
+bool cHardwareGX::Inst_Nor(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ GetRegister(dst) = ~(GetRegister(op1) | GetRegister(op2));
+ return true;
+}
+
+bool cHardwareGX::Inst_And(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ GetRegister(dst) = (GetRegister(op1) & GetRegister(op2));
+ return true;
+}
+
+bool cHardwareGX::Inst_Not(cAvidaContext& ctx)
+{
+ const int src = FindModifiedRegister(REG_BX);
+ const int dst = src;
+ GetRegister(dst) = ~(GetRegister(src));
+ return true;
+}
+
+bool cHardwareGX::Inst_Order(cAvidaContext& ctx)
+{
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ if (GetRegister(op1) > GetRegister(op2)) {
+ nFunctions::Swap(GetRegister(op1), GetRegister(op2));
+ }
+ return true;
+}
+
+bool cHardwareGX::Inst_Xor(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_BX;
+ const int op2 = REG_CX;
+ GetRegister(dst) = GetRegister(op1) ^ GetRegister(op2);
+ return true;
+}
+
+bool cHardwareGX::Inst_Copy(cAvidaContext& ctx)
+{
+ const int op1 = REG_BX;
+ const int op2 = REG_AX;
+
+ const cHeadCPU from(this, GetRegister(op1));
+ cHeadCPU to(this, GetRegister(op2) + GetRegister(op1));
+ sCPUStats& cpu_stats = organism->CPUStats();
+
+ if (organism->TestCopyMut(ctx)) {
+ to.SetInst(m_inst_set->GetRandomInst(ctx));
+ to.SetFlagMutated(); // Mark this instruction as mutated...
+ to.SetFlagCopyMut(); // Mark this instruction as copy mut...
+ //organism->GetPhenotype().IsMutated() = true;
+ cpu_stats.mut_stats.copy_mut_count++;
+ } else {
+ to.SetInst(from.GetInst());
+ to.ClearFlagMutated(); // UnMark
+ to.ClearFlagCopyMut(); // UnMark
+ }
+
+ to.SetFlagCopied(); // Set the copied flag.
+ cpu_stats.mut_stats.copies_exec++;
+ return true;
+}
+
+bool cHardwareGX::Inst_ReadInst(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_CX);
+ const int src = REG_BX;
+
+ const cHeadCPU from(this, GetRegister(src));
+
+ // Dis-allowing mutations on read, for the moment (write only...)
+ // @CAO This allows perfect error-correction...
+ GetRegister(dst) = from.GetInst().GetOp();
+ return true;
+}
+
+bool cHardwareGX::Inst_WriteInst(cAvidaContext& ctx)
+{
+ const int src = FindModifiedRegister(REG_CX);
+ const int op1 = REG_BX;
+ const int op2 = REG_AX;
+
+ cHeadCPU to(this, GetRegister(op2) + GetRegister(op1));
+ const int value = Mod(GetRegister(src), m_inst_set->GetSize());
+ sCPUStats& cpu_stats = organism->CPUStats();
+
+ // Change value on a mutation...
+ if (organism->TestCopyMut(ctx)) {
+ to.SetInst(m_inst_set->GetRandomInst(ctx));
+ to.SetFlagMutated(); // Mark this instruction as mutated...
+ to.SetFlagCopyMut(); // Mark this instruction as copy mut...
+ //organism->GetPhenotype().IsMutated() = true;
+ cpu_stats.mut_stats.copy_mut_count++;
+ } else {
+ to.SetInst(cInstruction(value));
+ to.ClearFlagMutated(); // UnMark
+ to.ClearFlagCopyMut(); // UnMark
+ }
+
+ to.SetFlagCopied(); // Set the copied flag.
+ cpu_stats.mut_stats.copies_exec++;
+ return true;
+}
+
+bool cHardwareGX::Inst_StackReadInst(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_CX);
+ cHeadCPU from(this, GetRegister(reg_used));
+ StackPush(from.GetInst().GetOp());
+ return true;
+}
+
+bool cHardwareGX::Inst_StackWriteInst(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_BX);
+ const int op1 = REG_AX;
+ cHeadCPU to(this, GetRegister(op1) + GetRegister(dst));
+ const int value = Mod(StackPop(), m_inst_set->GetSize());
+ sCPUStats& cpu_stats = organism->CPUStats();
+
+ // Change value on a mutation...
+ if (organism->TestCopyMut(ctx)) {
+ to.SetInst(m_inst_set->GetRandomInst(ctx));
+ to.SetFlagMutated(); // Mark this instruction as mutated...
+ to.SetFlagCopyMut(); // Mark this instruction as copy mut...
+ //organism->GetPhenotype().IsMutated() = true;
+ cpu_stats.mut_stats.copy_mut_count++;
+ } else {
+ to.SetInst(cInstruction(value));
+ to.ClearFlagMutated(); // UnMark
+ to.ClearFlagCopyMut(); // UnMark
+ }
+
+ to.SetFlagCopied(); // Set the copied flag.
+ cpu_stats.mut_stats.copies_exec++;
+ return true;
+}
+
+bool cHardwareGX::Inst_Compare(cAvidaContext& ctx)
+{
+ const int dst = FindModifiedRegister(REG_CX);
+ const int op1 = REG_BX;
+ const int op2 = REG_AX;
+
+ cHeadCPU from(this, GetRegister(op1));
+ cHeadCPU to(this, GetRegister(op2) + GetRegister(op1));
+
+ // Compare is dangerous -- it can cause mutations!
+ if (organism->TestCopyMut(ctx)) {
+ to.SetInst(m_inst_set->GetRandomInst(ctx));
+ to.SetFlagMutated(); // Mark this instruction as mutated...
+ to.SetFlagCopyMut(); // Mark this instruction as copy mut...
+ //organism->GetPhenotype().IsMutated() = true;
+ }
+
+ GetRegister(dst) = from.GetInst().GetOp() - to.GetInst().GetOp();
+
+ return true;
+}
+
+bool cHardwareGX::Inst_IfNCpy(cAvidaContext& ctx)
+{
+ const int op1 = REG_BX;
+ const int op2 = REG_AX;
+
+ const cHeadCPU from(this, GetRegister(op1));
+ const cHeadCPU to(this, GetRegister(op2) + GetRegister(op1));
+
+ // Allow for errors in this test...
+ if (organism->TestCopyMut(ctx)) {
+ if (from.GetInst() != to.GetInst()) IP().Advance();
+ } else {
+ if (from.GetInst() == to.GetInst()) IP().Advance();
+ }
+ return true;
+}
+
+bool cHardwareGX::Inst_Allocate(cAvidaContext& ctx) // Allocate bx more space...
+{
+ const int src = REG_BX;
+ const int dst = REG_AX;
+ const int size = GetMemory().GetSize();
+ if (Allocate_Main(ctx, GetRegister(src))) {
+ GetRegister(dst) = size;
+ return true;
+ } else return false;
+}
+
+bool cHardwareGX::Inst_Divide(cAvidaContext& ctx)
+{
+ const int src = REG_AX;
+ return Divide_Main(ctx, GetRegister(src));
+}
+
+/*
+ Divide with resampling -- Same as regular divide but on reversions will be
+ resampled after they are reverted.
+
+ AWC 06/29/06
+
+ */
+
+bool cHardwareGX::Inst_DivideRS(cAvidaContext& ctx)
+{
+ const int src = REG_AX;
+ return Divide_MainRS(ctx, GetRegister(src));
+}
+
+
+bool cHardwareGX::Inst_CDivide(cAvidaContext& ctx)
+{
+ return Divide_Main(ctx, GetMemory().GetSize() / 2);
+}
+
+bool cHardwareGX::Inst_CAlloc(cAvidaContext& ctx)
+{
+ return Allocate_Main(ctx, GetMemory().GetSize());
+}
+
+bool cHardwareGX::Inst_MaxAlloc(cAvidaContext& ctx) // Allocate maximal more
+{
+ const int dst = REG_AX;
+ const int cur_size = GetMemory().GetSize();
+ const int alloc_size = Min((int) (m_world->GetConfig().CHILD_SIZE_RANGE.Get() * cur_size),
+ MAX_CREATURE_SIZE - cur_size);
+ if (Allocate_Main(ctx, alloc_size)) {
+ GetRegister(dst) = cur_size;
+ return true;
+ } else return false;
+}
+
+bool cHardwareGX::Inst_Transposon(cAvidaContext& ctx)
+{
+ ReadLabel();
+ //organism->GetPhenotype().ActivateTransposon(GetLabel());
+ return true;
+}
+
+void cHardwareGX::Divide_DoTransposons(cAvidaContext& ctx)
+{
+ // This only works if 'transposon' is in the current instruction set
+ static bool transposon_in_use = GetInstSet().InstInSet(cStringUtil::Stringf("transposon"));
+ if (!transposon_in_use) return;
+
+ static cInstruction transposon_inst = GetInstSet().GetInst(cStringUtil::Stringf("transposon"));
+ cCPUMemory& child_genome = organism->ChildGenome();
+
+ // Count the number of transposons that are marked as executed
+ int tr_count = 0;
+ for (int i=0; i < child_genome.GetSize(); i++)
+ {
+ if (child_genome.FlagExecuted(i) && (child_genome[i] == transposon_inst)) tr_count++;
+ }
+
+ for (int i=0; i < tr_count; i++)
+ {
+ if (ctx.GetRandom().P(0.01))
+ {
+ const unsigned int mut_line = ctx.GetRandom().GetUInt(child_genome.GetSize() + 1);
+ child_genome.Insert(mut_line, transposon_inst);
+ }
+ }
+
+
+/*
+ const tArray<cCodeLabel> tr = organism->GetPhenotype().GetActiveTransposons();
+ cCPUMemory& child_genome = organism->ChildGenome();
+
+ for (int i=0; i < tr.GetSize(); i++)
+ {
+ if (ctx.GetRandom().P(0.1))
+ {
+ const unsigned int mut_line = ctx.GetRandom().GetUInt(child_genome.GetSize() + 1);
+ child_genome.Insert(mut_line, transposon_inst);
+ }
+ }
+*/
+}
+
+bool cHardwareGX::Inst_Repro(cAvidaContext& ctx)
+{
+ // const bool viable = Divide_CheckViable(ctx, div_point, child_size);
+ // these checks should be done, but currently they make some assumptions
+ // that crash when evaluating this kind of organism -- JEB
+
+ // Setup child
+ cCPUMemory& child_genome = organism->ChildGenome();
+ child_genome = GetMemory();
+ organism->GetPhenotype().SetLinesCopied(GetMemory().GetSize());
+
+ // @JEB - Make sure that an organism has accumulated any required bonus
+ const int bonus_required = m_world->GetConfig().REQUIRED_BONUS.Get();
+ if (organism->GetPhenotype().GetCurBonus() < bonus_required) {
+ return false; // (divide fails)
+ }
+
+ int lines_executed = 0;
+ for ( int i = 0; i < GetMemory().GetSize(); i++ ) {
+ if ( GetMemory().FlagExecuted(i)) lines_executed++;
+ }
+ organism->GetPhenotype().SetLinesExecuted(lines_executed);
+
+ // Do transposon movement and copying before other mutations
+ Divide_DoTransposons(ctx);
+
+ // Perform Copy Mutations...
+ if (organism->GetCopyMutProb() > 0) { // Skip this if no mutations....
+ for (int i = 0; i < GetMemory().GetSize(); i++) {
+ if (organism->TestCopyMut(ctx)) {
+ child_genome[i] = m_inst_set->GetRandomInst(ctx);
+ //organism->GetPhenotype().IsMutated() = true;
+ }
+ }
+ }
+ Divide_DoMutations(ctx);
+
+ // 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(ctx);
+
+#if INSTRUCTION_COSTS
+ // reset first time instruction costs
+ for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+ inst_ft_cost[i] = m_inst_set->GetFTCost(cInstruction(i));
+ }
+#endif
+
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) m_advance_ip = false;
+
+ organism->ActivateDivide(ctx);
+
+ //Reset the parent
+ if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) Reset();
+
+ return true;
+}
+
+bool cHardwareGX::Inst_TaskPutRepro(cAvidaContext& ctx)
+{
+ // Do normal IO, but don't zero register
+ //Inst_TaskPut(ctx);
+
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int value = GetRegister(reg_used);
+ // GetRegister(reg_used) = 0;
+ organism->DoOutput(ctx, value);
+
+ // Immediately attempt a repro
+ return Inst_Repro(ctx);
+}
+
+bool cHardwareGX::Inst_TaskPutResetInputsRepro(cAvidaContext& ctx)
+{
+ // Do normal IO
+ bool return_value = Inst_TaskPutResetInputs(ctx);
+
+ // Immediately attempt a repro
+ Inst_Repro(ctx);
+
+ // return value of put since successful repro would wipe state anyway
+ return return_value;
+}
+
+bool cHardwareGX::Inst_SpawnDeme(cAvidaContext& ctx)
+{
+ organism->SpawnDeme();
+ return true;
+}
+
+bool cHardwareGX::Inst_Kazi(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_AX);
+ double percentProb = ((double) (GetRegister(reg_used) % 100)) / 100.0;
+ if ( ctx.GetRandom().P(percentProb) ) organism->Kaboom(0);
+ return true;
+}
+
+bool cHardwareGX::Inst_Kazi5(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_AX);
+ double percentProb = ((double) (GetRegister(reg_used) % 100)) / 100.0;
+ if ( ctx.GetRandom().P(percentProb) ) organism->Kaboom(5);
+ return true;
+}
+
+bool cHardwareGX::Inst_Die(cAvidaContext& ctx)
+{
+ 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 cHardwareGX::Inst_Inject(cAvidaContext& ctx)
+{
+ AdjustHeads();
+ const int start_pos = GetHead(nHardware::HEAD_READ).GetPosition();
+ const int end_pos = GetHead(nHardware::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) {
+ organism->Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
+ return false; // (inject fails)
+ }
+ if (start_pos < MIN_CREATURE_SIZE) {
+ organism->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) {
+ organism->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) {
+ organism->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 cHardwareGX::Inst_InjectRand(cAvidaContext& ctx)
+{
+ // Rotate to a random facing and then run the normal inject instruction
+ const int num_neighbors = organism->GetNeighborhoodSize();
+ organism->Rotate(ctx.GetRandom().GetUInt(num_neighbors));
+ Inst_Inject(ctx);
+ 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 cHardwareGX::Inst_InjectThread(cAvidaContext& ctx)
+{
+ AdjustHeads();
+ const int start_pos = GetHead(nHardware::HEAD_READ).GetPosition();
+ const int end_pos = GetHead(nHardware::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) {
+ organism->Fault(FAULT_LOC_INJECT, FAULT_TYPE_ERROR, "inject: no code to inject");
+ return false; // (inject fails)
+ }
+ if (start_pos < MIN_CREATURE_SIZE) {
+ organism->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) {
+ organism->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);
+
+ if (host_organism->GetHardware().InjectHost(GetLabel(), inject_code)) {
+ if (ForkThread()) organism->GetPhenotype().IsMultiThread() = true;
+ }
+
+ // Set the relevent flags.
+ organism->GetPhenotype().IsModifier() = true;
+
+ return true;
+}
+
+bool cHardwareGX::Inst_TaskGet(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_CX);
+ const int value = organism->GetNextInput();
+ GetRegister(reg_used) = value;
+ organism->DoInput(value);
+ return true;
+}
+
+
+// @JEB - this instruction does more than two "gets" together
+// it also (1) resets the inputs and (2) resets an organisms task counts
+bool cHardwareGX::Inst_TaskGet2(cAvidaContext& ctx)
+{
+ // Randomize the inputs so they can't save numbers
+ organism->GetOrgInterface().ResetInputs(ctx); // Now re-randomize the inputs this organism sees
+ organism->ClearInput(); // Also clear their input buffers, or they can still claim
+ // rewards for numbers no longer in their environment!
+
+ const int reg_used_1 = FindModifiedRegister(REG_BX);
+ const int reg_used_2 = FindNextRegister(reg_used_1);
+
+ const int value1 = organism->GetNextInput();
+ GetRegister(reg_used_1) = value1;
+ organism->DoInput(value1);
+
+ const int value2 = organism->GetNextInput();
+ GetRegister(reg_used_2) = value2;
+ organism->DoInput(value2);
+
+ // Clear the task number
+ organism->GetPhenotype().ClearEffTaskCount();
+
+ return true;
+}
+
+bool cHardwareGX::Inst_TaskStackGet(cAvidaContext& ctx)
+{
+ const int value = organism->GetNextInput();
+ StackPush(value);
+ organism->DoInput(value);
+ return true;
+}
+
+bool cHardwareGX::Inst_TaskStackLoad(cAvidaContext& ctx)
+{
+ // @DMB - TODO: this should look at the input_size...
+ for (int i = 0; i < 3; i++)
+ StackPush( organism->GetNextInput() );
+ return true;
+}
+
+bool cHardwareGX::Inst_TaskPut(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int value = GetRegister(reg_used);
+ GetRegister(reg_used) = 0;
+ organism->DoOutput(ctx, value);
+ return true;
+}
+
+bool cHardwareGX::Inst_TaskPutResetInputs(cAvidaContext& ctx)
+{
+ bool return_value = Inst_TaskPut(ctx); // Do a normal put
+ organism->GetOrgInterface().ResetInputs(ctx); // Now re-randomize the inputs this organism sees
+ organism->ClearInput(); // Also clear their input buffers, or they can still claim
+ // rewards for numbers no longer in their environment!
+ return return_value;
+}
+
+bool cHardwareGX::Inst_TaskIO(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+
+ // Do the "put" component
+ const int value_out = GetRegister(reg_used);
+ organism->DoOutput(ctx, value_out); // Check for tasks completed.
+
+ // Do the "get" component
+ const int value_in = organism->GetNextInput();
+ GetRegister(reg_used) = value_in;
+ organism->DoInput(value_in);
+ return true;
+}
+
+bool cHardwareGX::Inst_TaskIO_Feedback(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+
+ //check cur_bonus before the output
+ double preOutputBonus = organism->GetPhenotype().GetCurBonus();
+
+ // Do the "put" component
+ const int value_out = GetRegister(reg_used);
+ organism->DoOutput(ctx, value_out); // Check for tasks completed.
+
+ //check cur_merit after the output
+ double postOutputBonus = organism->GetPhenotype().GetCurBonus();
+
+
+ //push the effect of the IO on merit (+,0,-) to the active stack
+
+ if (preOutputBonus > postOutputBonus){
+ StackPush(-1);
+ }
+ else if (preOutputBonus == postOutputBonus){
+ StackPush(0);
+ }
+ else if (preOutputBonus < postOutputBonus){
+ StackPush(1);
+ }
+ else {
+ assert(0);
+ //Bollocks. There was an error.
+ }
+
+
+
+
+
+
+ // Do the "get" component
+ const int value_in = organism->GetNextInput();
+ GetRegister(reg_used) = value_in;
+ organism->DoInput(value_in);
+ return true;
+}
+
+bool cHardwareGX::Inst_MatchStrings(cAvidaContext& ctx)
+{
+ if (m_executedmatchstrings)
+ return false;
+ organism->DoOutput(ctx, 357913941);
+ m_executedmatchstrings = true;
+ return true;
+}
+
+bool cHardwareGX::Inst_Sell(cAvidaContext& ctx)
+{
+ int search_label = GetLabel().AsInt(3) % MARKET_SIZE;
+ int send_value = GetRegister(REG_BX);
+ int sell_price = m_world->GetConfig().SELL_PRICE.Get();
+ organism->SellValue(send_value, search_label, sell_price);
+ return true;
+}
+
+bool cHardwareGX::Inst_Buy(cAvidaContext& ctx)
+{
+ int search_label = GetLabel().AsInt(3) % MARKET_SIZE;
+ int buy_price = m_world->GetConfig().BUY_PRICE.Get();
+ GetRegister(REG_BX) = organism->BuyValue(search_label, buy_price);
+ return true;
+}
+
+bool cHardwareGX::Inst_Send(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ organism->SendValue(GetRegister(reg_used));
+ GetRegister(reg_used) = 0;
+ return true;
+}
+
+bool cHardwareGX::Inst_Receive(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ GetRegister(reg_used) = organism->ReceiveValue();
+ return true;
+}
+
+bool cHardwareGX::Inst_SenseLog2(cAvidaContext& ctx)
+{
+ return DoSense(ctx, 0, 2);
+}
+
+bool cHardwareGX::Inst_SenseUnit(cAvidaContext& ctx)
+{
+ return DoSense(ctx, 1, 1);
+}
+
+bool cHardwareGX::Inst_SenseMult100(cAvidaContext& ctx)
+{
+ return DoSense(ctx, 1, 100);
+}
+
+bool cHardwareGX::DoSense(cAvidaContext& ctx, int conversion_method, double base)
+{
+ // Returns the log2 amount of a resource or resources
+ // specified by modifying NOPs into register BX
+ const tArray<double> & res_count = organism->GetOrgInterface().GetResources();
+
+ // Arbitrarily set to BX since the conditionals use this directly.
+ int reg_to_set = REG_BX;
+
+ // There are no resources, return
+ if (res_count.GetSize() == 0) return false;
+
+ // Only recalculate logs if these values have changed
+ static int last_num_resources = 0;
+ static int max_label_length = 0;
+ int num_nops = GetInstSet().GetNumNops();
+
+ if ((last_num_resources != res_count.GetSize()))
+ {
+ max_label_length = (int) ceil(log((double)res_count.GetSize())/log((double)num_nops));
+ last_num_resources = res_count.GetSize();
+ }
+
+ // Convert modifying NOPs to the index of the resource.
+ // If there are fewer than the number of NOPs required
+ // to uniquely specify a resource, then add together
+ // a subset of resources (motivation: regulation can evolve
+ // to be more specific if there is an advantage)
+
+ // Find the maximum number of NOPs needed to specify this number of resources
+ // Note: It's a bit wasteful to recalculate this every time and organisms will
+ // definitely be confused if the number of resources changes during a run
+ // because their mapping to resources will be disrupted
+
+ // Attempt to read a label with this maximum length
+ cHardwareGX::ReadLabel(max_label_length);
+
+ // Find the length of the label that we actually obtained (max is max_reg_needed)
+ int real_label_length = GetLabel().GetSize();
+
+ // Start and end labels to define the start and end indices of
+ // resources that we need to add together
+ cCodeLabel start_label = cCodeLabel(GetLabel());
+ cCodeLabel end_label = cCodeLabel(GetLabel());
+
+ for (int i = 0; i < max_label_length - real_label_length; i++)
+ {
+ start_label.AddNop(0);
+ end_label.AddNop(num_nops-1);
+ }
+
+ int start_index = start_label.AsInt(num_nops);
+ int end_index = end_label.AsInt(num_nops);
+
+ // If the label refers to ONLY resources that
+ // do not exist, then the operation fails
+ if (start_index >= res_count.GetSize()) return false;
+
+ // Otherwise sum all valid resources that it might refer to
+ // (this will only be ONE if the label was of the maximum length).
+ int resource_result = 0;
+ for (int i = start_index; i <= end_index; i++)
+ {
+ // if it's a valid resource
+ if (i < res_count.GetSize())
+ {
+ if (conversion_method == 0) // Log2
+ {
+ // (alternately you could assign min_int for zero resources, but
+ // that would cause wierdness when adding sense values together)
+ if (res_count[i] > 0) resource_result += (int)(log(res_count[i])/log(base));
+ }
+ else if (conversion_method == 1) // Addition of multiplied resource amount
+ {
+ int add_amount = (int) (res_count[i] * base);
+ // Do some range checking to make sure we don't overflow
+ resource_result = (INT_MAX - resource_result <= add_amount) ? INT_MAX : resource_result + add_amount;
+ }
+ }
+ }
+
+ //Dump this value into an arbitrary register: BX
+ GetRegister(reg_to_set) = resource_result;
+
+ //We have to convert this to a different index that includes all degenerate labels possible: shortest to longest
+ int sensed_index = 0;
+ int on = 1;
+ for (int i = 0; i < real_label_length; i++)
+ {
+ sensed_index += on;
+ on *= num_nops;
+ }
+ sensed_index+= GetLabel().AsInt(num_nops);
+ organism->GetPhenotype().IncSenseCount(sensed_index);
+
+ return true;
+
+ // Note that we are converting <double> resources to <int> register values
+}
+
+void cHardwareGX::DoDonate(cOrganism* to_org)
+{
+ assert(to_org != NULL);
+
+ const double merit_given = m_world->GetConfig().DONATE_SIZE.Get();
+ const double merit_received =
+ merit_given * m_world->GetConfig().DONATE_MULT.Get();
+
+ 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 cHardwareGX::Inst_DonateRandom(cAvidaContext& ctx)
+{
+ organism->GetPhenotype().IncDonates();
+ if (organism->GetPhenotype().GetCurNumDonates() > m_world->GetConfig().MAX_DONATES.Get()) {
+ return false;
+ }
+
+ // Turn to a random neighbor, get it, and turn back...
+ int neighbor_id = ctx.GetRandom().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 cHardwareGX::Inst_DonateKin(cAvidaContext& ctx)
+{
+ organism->GetPhenotype().IncDonates();
+ if (organism->GetPhenotype().GetCurNumDonates() > m_world->GetConfig().MAX_DONATES.Get()) {
+ 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 = ctx.GetRandom().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 = m_world->GetConfig().MAX_DONATE_KIN_DIST.Get();
+ 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 cHardwareGX::Inst_DonateEditDist(cAvidaContext& ctx)
+{
+ organism->GetPhenotype().IncDonates();
+ if (organism->GetPhenotype().GetCurNumDonates() > m_world->GetConfig().MAX_DONATES.Get()) {
+ 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 = ctx.GetRandom().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 = m_world->GetConfig().MAX_DONATE_EDIT_DIST.Get();
+ 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 cHardwareGX::Inst_DonateNULL(cAvidaContext& ctx)
+{
+ organism->GetPhenotype().IncDonates();
+ if (organism->GetPhenotype().GetCurNumDonates() > m_world->GetConfig().MAX_DONATES.Get()) {
+ 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 = m_world->GetConfig().DONATE_SIZE.Get();
+ 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 cHardwareGX::Inst_SearchF(cAvidaContext& ctx)
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+ const int search_size = FindLabel(1).GetPosition() - IP().GetPosition();
+ GetRegister(REG_BX) = search_size;
+ GetRegister(REG_CX) = GetLabel().GetSize();
+ return true;
+}
+
+bool cHardwareGX::Inst_SearchB(cAvidaContext& ctx)
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+ const int search_size = IP().GetPosition() - FindLabel(-1).GetPosition();
+ GetRegister(REG_BX) = search_size;
+ GetRegister(REG_CX) = GetLabel().GetSize();
+ return true;
+}
+
+bool cHardwareGX::Inst_MemSize(cAvidaContext& ctx)
+{
+ GetRegister(FindModifiedRegister(REG_BX)) = GetMemory().GetSize();
+ return true;
+}
+
+
+bool cHardwareGX::Inst_RotateL(cAvidaContext& ctx)
+{
+ 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();
+
+ if (neighbor != NULL && neighbor->GetHardware().FindLabelFull(GetLabel()).InMemory()) return true;
+
+ // Otherwise keep rotating...
+ organism->Rotate(-1);
+ }
+ return true;
+}
+
+bool cHardwareGX::Inst_RotateR(cAvidaContext& ctx)
+{
+ 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();
+
+ if (neighbor != NULL && neighbor->GetHardware().FindLabelFull(GetLabel()).InMemory()) return true;
+
+ // Otherwise keep rotating...
+ organism->Rotate(1);
+ }
+ return true;
+}
+
+bool cHardwareGX::Inst_SetCopyMut(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const int new_mut_rate = Max(GetRegister(reg_used), 1 );
+ organism->SetCopyMutProb(static_cast<double>(new_mut_rate) / 10000.0);
+ return true;
+}
+
+bool cHardwareGX::Inst_ModCopyMut(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ const double new_mut_rate = organism->GetCopyMutProb() + static_cast<double>(GetRegister(reg_used)) / 10000.0;
+ if (new_mut_rate > 0.0) organism->SetCopyMutProb(new_mut_rate);
+ return true;
+}
+
+// Energy use
+
+bool cHardwareGX::Inst_ZeroEnergyUsed(cAvidaContext& ctx)
+{
+ // Typically, this instruction should be triggered by a REACTION
+ organism->GetPhenotype().SetTimeUsed(0);
+ return true;
+}
+
+// Multi-threading.
+
+bool cHardwareGX::Inst_ForkThread(cAvidaContext& ctx)
+{
+ IP().Advance();
+ if (!ForkThread()) organism->Fault(FAULT_LOC_THREAD_FORK, FAULT_TYPE_FORK_TH);
+ return true;
+}
+
+bool cHardwareGX::Inst_KillThread(cAvidaContext& ctx)
+{
+ if (!KillThread()) organism->Fault(FAULT_LOC_THREAD_KILL, FAULT_TYPE_KILL_TH);
+ else m_advance_ip = false;
+ return true;
+}
+
+bool cHardwareGX::Inst_ThreadID(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_BX);
+ GetRegister(reg_used) = GetCurThreadID();
+ return true;
+}
+
+
+// Head-based instructions
+
+bool cHardwareGX::Inst_SetHead(cAvidaContext& ctx)
+{
+ const int head_used = FindModifiedHead(nHardware::HEAD_IP);
+ m_threads[m_cur_thread].cur_head = static_cast<unsigned char>(head_used);
+ return true;
+}
+
+bool cHardwareGX::Inst_AdvanceHead(cAvidaContext& ctx)
+{
+ const int head_used = FindModifiedHead(nHardware::HEAD_WRITE);
+ GetHead(head_used).Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_MoveHead(cAvidaContext& ctx)
+{
+ const int head_used = FindModifiedHead(nHardware::HEAD_IP);
+ const int target = nHardware::HEAD_FLOW;
+ GetHead(head_used).Set(GetHead(target));
+ if (head_used == nHardware::HEAD_IP) m_advance_ip = false;
+ return true;
+}
+
+bool cHardwareGX::Inst_JumpHead(cAvidaContext& ctx)
+{
+ const int head_used = FindModifiedHead(nHardware::HEAD_IP);
+ GetHead(head_used).Jump(GetRegister(REG_CX) );
+ // JEB - probably shouldn't advance inst ptr after jumping here?
+ // Any negative number jumps to the beginning of the genome (pos 0)
+ // and then we immediately advance past that first instruction.
+ return true;
+}
+
+bool cHardwareGX::Inst_GetHead(cAvidaContext& ctx)
+{
+ const int head_used = FindModifiedHead(nHardware::HEAD_IP);
+ GetRegister(REG_CX) = GetHead(head_used).GetPosition();
+ return true;
+}
+
+bool cHardwareGX::Inst_IfLabel(cAvidaContext& ctx)
+{
+ 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 cHardwareGX::Inst_IfLabel2(cAvidaContext& ctx)
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+ if (GetLabel() != GetReadLabel()) {
+ IP().Advance();
+ if (m_inst_set->IsNop( IP().GetNextInst() )) IP().Advance();
+ }
+ return true;
+}
+
+bool cHardwareGX::Inst_HeadDivideMut(cAvidaContext& ctx, double mut_multiplier)
+{
+ AdjustHeads();
+ const int divide_pos = GetHead(nHardware::HEAD_READ).GetPosition();
+ int child_end = GetHead(nHardware::HEAD_WRITE).GetPosition();
+ if (child_end == 0) child_end = GetMemory().GetSize();
+ const int extra_lines = GetMemory().GetSize() - child_end;
+ bool ret_val = Divide_Main(ctx, divide_pos, extra_lines, mut_multiplier);
+ // Re-adjust heads.
+ AdjustHeads();
+ return ret_val;
+}
+
+bool cHardwareGX::Inst_HeadDivide(cAvidaContext& ctx)
+{
+ return Inst_HeadDivideMut(ctx, 1);
+
+}
+
+/*
+ Resample Divide -- AWC 06/29/06
+*/
+
+bool cHardwareGX::Inst_HeadDivideRS(cAvidaContext& ctx)
+{
+ AdjustHeads();
+ const int divide_pos = GetHead(nHardware::HEAD_READ).GetPosition();
+ int child_end = GetHead(nHardware::HEAD_WRITE).GetPosition();
+ if (child_end == 0) child_end = GetMemory().GetSize();
+ const int extra_lines = GetMemory().GetSize() - child_end;
+ bool ret_val = Divide_MainRS(ctx, divide_pos, extra_lines, 1);
+ // Re-adjust heads.
+ AdjustHeads();
+ return ret_val;
+}
+
+/*
+ Resample Divide -- single mut on divide-- AWC 07/28/06
+*/
+
+bool cHardwareGX::Inst_HeadDivide1RS(cAvidaContext& ctx)
+{
+ AdjustHeads();
+ const int divide_pos = GetHead(nHardware::HEAD_READ).GetPosition();
+ int child_end = GetHead(nHardware::HEAD_WRITE).GetPosition();
+ if (child_end == 0) child_end = GetMemory().GetSize();
+ const int extra_lines = GetMemory().GetSize() - child_end;
+ bool ret_val = Divide_Main1RS(ctx, divide_pos, extra_lines, 1);
+ // Re-adjust heads.
+ AdjustHeads();
+ return ret_val;
+}
+
+/*
+ Resample Divide -- double mut on divide-- AWC 08/29/06
+*/
+
+bool cHardwareGX::Inst_HeadDivide2RS(cAvidaContext& ctx)
+{
+ AdjustHeads();
+ const int divide_pos = GetHead(nHardware::HEAD_READ).GetPosition();
+ int child_end = GetHead(nHardware::HEAD_WRITE).GetPosition();
+ if (child_end == 0) child_end = GetMemory().GetSize();
+ const int extra_lines = GetMemory().GetSize() - child_end;
+ bool ret_val = Divide_Main2RS(ctx, divide_pos, extra_lines, 1);
+ // Re-adjust heads.
+ AdjustHeads();
+ return ret_val;
+}
+
+
+bool cHardwareGX::Inst_HeadDivideSex(cAvidaContext& ctx)
+{
+ organism->GetPhenotype().SetDivideSex(true);
+ organism->GetPhenotype().SetCrossNum(1);
+ return Inst_HeadDivide(ctx);
+}
+
+bool cHardwareGX::Inst_HeadDivideAsex(cAvidaContext& ctx)
+{
+ organism->GetPhenotype().SetDivideSex(false);
+ organism->GetPhenotype().SetCrossNum(0);
+ return Inst_HeadDivide(ctx);
+}
+
+bool cHardwareGX::Inst_HeadDivideAsexWait(cAvidaContext& ctx)
+{
+ organism->GetPhenotype().SetDivideSex(true);
+ organism->GetPhenotype().SetCrossNum(0);
+ return Inst_HeadDivide(ctx);
+}
+
+bool cHardwareGX::Inst_HeadDivideMateSelect(cAvidaContext& ctx)
+{
+ // 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) );
+
+ // Proceed as normal with the rest of mate selection.
+ organism->GetPhenotype().SetDivideSex(true);
+ organism->GetPhenotype().SetCrossNum(1);
+ return Inst_HeadDivide(ctx);
+}
+
+bool cHardwareGX::Inst_HeadDivide1(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 1); }
+bool cHardwareGX::Inst_HeadDivide2(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 2); }
+bool cHardwareGX::Inst_HeadDivide3(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 3); }
+bool cHardwareGX::Inst_HeadDivide4(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 4); }
+bool cHardwareGX::Inst_HeadDivide5(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 5); }
+bool cHardwareGX::Inst_HeadDivide6(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 6); }
+bool cHardwareGX::Inst_HeadDivide7(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 7); }
+bool cHardwareGX::Inst_HeadDivide8(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 8); }
+bool cHardwareGX::Inst_HeadDivide9(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 9); }
+bool cHardwareGX::Inst_HeadDivide10(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 10); }
+bool cHardwareGX::Inst_HeadDivide16(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 16); }
+bool cHardwareGX::Inst_HeadDivide32(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 32); }
+bool cHardwareGX::Inst_HeadDivide50(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 50); }
+bool cHardwareGX::Inst_HeadDivide100(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 100); }
+bool cHardwareGX::Inst_HeadDivide500(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 500); }
+bool cHardwareGX::Inst_HeadDivide1000(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 1000); }
+bool cHardwareGX::Inst_HeadDivide5000(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 5000); }
+bool cHardwareGX::Inst_HeadDivide10000(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 10000); }
+bool cHardwareGX::Inst_HeadDivide50000(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 50000); }
+bool cHardwareGX::Inst_HeadDivide0_5(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 0.5); }
+bool cHardwareGX::Inst_HeadDivide0_1(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 0.1); }
+bool cHardwareGX::Inst_HeadDivide0_05(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 0.05); }
+bool cHardwareGX::Inst_HeadDivide0_01(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 0.01); }
+bool cHardwareGX::Inst_HeadDivide0_001(cAvidaContext& ctx) { return Inst_HeadDivideMut(ctx, 0.001); }
+
+bool cHardwareGX::Inst_HeadRead(cAvidaContext& ctx)
+{
+ const int dst = REG_BX;
+
+ const int head_id = FindModifiedHead(nHardware::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(ctx)) {
+ read_inst = m_inst_set->GetRandomInst(ctx).GetOp();
+ cpu_stats.mut_stats.copy_mut_count++; // @CAO, hope this is good!
+ } else {
+ read_inst = GetHead(head_id).GetInst().GetOp();
+ }
+ GetRegister(dst) = read_inst;
+ ReadInst(read_inst);
+
+ cpu_stats.mut_stats.copies_exec++; // @CAO, this too..
+ GetHead(head_id).Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_HeadWrite(cAvidaContext& ctx)
+{
+ const int src = REG_BX;
+ const int head_id = FindModifiedHead(nHardware::HEAD_WRITE);
+ cHeadCPU& active_head = GetHead(head_id);
+
+ active_head.Adjust();
+
+ int value = GetRegister(src);
+ if (value < 0 || value >= m_inst_set->GetSize()) value = 0;
+
+ active_head.SetInst(cInstruction(value));
+ active_head.SetFlagCopied();
+
+ // Advance the head after write...
+ active_head++;
+ return true;
+}
+
+bool cHardwareGX::Inst_HeadCopy(cAvidaContext& ctx)
+{
+ // For the moment, this cannot be nop-modified.
+ cHeadCPU& read_head = GetHead(nHardware::HEAD_READ);
+ cHeadCPU& write_head = GetHead(nHardware::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 (organism->TestCopyMut(ctx)) {
+ read_inst = m_inst_set->GetRandomInst(ctx);
+ cpu_stats.mut_stats.copy_mut_count++;
+ write_head.SetFlagMutated();
+ write_head.SetFlagCopyMut();
+ }
+
+ cpu_stats.mut_stats.copies_exec++;
+
+ write_head.SetInst(read_inst);
+ write_head.SetFlagCopied(); // Set the copied flag...
+
+ read_head.Advance();
+ write_head.Advance();
+ return true;
+}
+
+bool cHardwareGX::HeadCopy_ErrorCorrect(cAvidaContext& ctx, double reduction)
+{
+ // For the moment, this cannot be nop-modified.
+ cHeadCPU & read_head = GetHead(nHardware::HEAD_READ);
+ cHeadCPU & write_head = GetHead(nHardware::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 ( ctx.GetRandom().P(organism->GetCopyMutProb() / reduction) ) {
+ read_inst = m_inst_set->GetRandomInst(ctx);
+ cpu_stats.mut_stats.copy_mut_count++;
+ write_head.SetFlagMutated();
+ write_head.SetFlagCopyMut();
+ //organism->GetPhenotype().IsMutated() = true;
+ }
+
+ cpu_stats.mut_stats.copies_exec++;
+
+ write_head.SetInst(read_inst);
+ write_head.SetFlagCopied(); // Set the copied flag...
+
+ read_head.Advance();
+ write_head.Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_HeadCopy2(cAvidaContext& ctx) { return HeadCopy_ErrorCorrect(ctx, 2); }
+bool cHardwareGX::Inst_HeadCopy3(cAvidaContext& ctx) { return HeadCopy_ErrorCorrect(ctx, 3); }
+bool cHardwareGX::Inst_HeadCopy4(cAvidaContext& ctx) { return HeadCopy_ErrorCorrect(ctx, 4); }
+bool cHardwareGX::Inst_HeadCopy5(cAvidaContext& ctx) { return HeadCopy_ErrorCorrect(ctx, 5); }
+bool cHardwareGX::Inst_HeadCopy6(cAvidaContext& ctx) { return HeadCopy_ErrorCorrect(ctx, 6); }
+bool cHardwareGX::Inst_HeadCopy7(cAvidaContext& ctx) { return HeadCopy_ErrorCorrect(ctx, 7); }
+bool cHardwareGX::Inst_HeadCopy8(cAvidaContext& ctx) { return HeadCopy_ErrorCorrect(ctx, 8); }
+bool cHardwareGX::Inst_HeadCopy9(cAvidaContext& ctx) { return HeadCopy_ErrorCorrect(ctx, 9); }
+bool cHardwareGX::Inst_HeadCopy10(cAvidaContext& ctx) { return HeadCopy_ErrorCorrect(ctx, 10); }
+
+bool cHardwareGX::Inst_HeadSearch(cAvidaContext& ctx)
+{
+ ReadLabel();
+ GetLabel().Rotate(1, NUM_NOPS);
+ cHeadCPU found_pos = FindLabel(0);
+ const int search_size = found_pos.GetPosition() - IP().GetPosition();
+ GetRegister(REG_BX) = search_size;
+ GetRegister(REG_CX) = GetLabel().GetSize();
+ GetHead(nHardware::HEAD_FLOW).Set(found_pos);
+ GetHead(nHardware::HEAD_FLOW).Advance();
+ return true;
+}
+
+bool cHardwareGX::Inst_SetFlow(cAvidaContext& ctx)
+{
+ const int reg_used = FindModifiedRegister(REG_CX);
+ GetHead(nHardware::HEAD_FLOW).Set(GetRegister(reg_used));
+return true;
+}
+
+//// Placebo insts ////
+bool cHardwareGX::Inst_Skip(cAvidaContext& ctx)
+{
+ IP().Advance();
+ return true;
+}
+
Added: development/source/cpu/cHardwareGX.h
===================================================================
--- development/source/cpu/cHardwareGX.h 2007-03-30 15:03:40 UTC (rev 1442)
+++ development/source/cpu/cHardwareGX.h 2007-04-01 22:37:34 UTC (rev 1443)
@@ -0,0 +1,582 @@
+/*
+ * cHardwareGX.h
+ * Avida
+ *
+ * Copyright 1999-2007 Michigan State University. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef cHardwareGX_h
+#define cHardwareGX_h
+
+#include <iomanip>
+#include <vector>
+#include "cCodeLabel.h"
+#include "cHeadCPU.h"
+#include "cCPUMemory.h"
+#include "cCPUStack.h"
+#include "cHardwareBase.h"
+#include "cString.h"
+#include "cStats.h"
+#include "tArray.h"
+#include "tInstLib.h"
+#include "defs.h"
+#include "nHardware.h"
+
+
+class cInjectGenotype;
+class cInstLib;
+class cInstSet;
+class cMutation;
+class cOrganism;
+
+
+/*! Each organism may have a cHardwareGX structure that keeps track of the
+* current status of simulated hardware. This particular CPU architecture is
+* designed to explore the evolution of gene expression.
+*/
+class cHardwareGX : public cHardwareBase
+{
+public:
+ typedef bool (cHardwareGX::*tMethod)(cAvidaContext& ctx);
+
+protected:
+ // -------- Structure Constants --------
+ static const int NUM_REGISTERS = 3;
+ static const int NUM_HEADS = nHardware::NUM_HEADS >= NUM_REGISTERS ? nHardware::NUM_HEADS : NUM_REGISTERS;
+ enum tRegisters { REG_AX = 0, REG_BX, REG_CX, REG_DX, REG_EX, REG_FX };
+ static const int NUM_NOPS = 3;
+
+ // -------- Data Structures --------
+ struct cLocalThread
+ {
+ private:
+ int m_id;
+
+ public:
+ int reg[NUM_REGISTERS];
+ cHeadCPU heads[NUM_HEADS];
+ cCPUStack stack;
+ unsigned char cur_stack; // 0 = local stack, 1 = global stack.
+ unsigned char cur_head;
+
+ cCodeLabel read_label;
+ cCodeLabel next_label;
+
+
+ cLocalThread(cHardwareBase* in_hardware = NULL, int in_id = -1) { Reset(in_hardware, in_id); }
+ ~cLocalThread() { ; }
+
+ void operator=(const cLocalThread& in_thread);
+
+ void Reset(cHardwareBase* in_hardware, int in_id);
+ int GetID() const { return m_id; }
+ void SetID(int in_id) { m_id = in_id; }
+ };
+
+
+ // -------- Static Variables --------
+ static tInstLib<tMethod>* s_inst_slib;
+ static tInstLib<tMethod>* initInstLib(void);
+
+
+ // -------- Member Variables --------
+ const tMethod* m_functions;
+
+ cCPUMemory m_memory; // Memory...
+ cCPUStack m_global_stack; // A stack that all threads share.
+
+ tArray<cLocalThread> m_threads;
+ int m_thread_id_chart;
+ int m_cur_thread;
+
+ // Flags...
+ bool m_mal_active; // Has an allocate occured since last divide?
+ bool m_advance_ip; // Should the IP advance after this instruction?
+ bool m_executedmatchstrings; // Have we already executed the match strings instruction?
+
+ // Instruction costs...
+#if INSTRUCTION_COSTS
+ tArray<int> inst_cost;
+ tArray<int> inst_ft_cost;
+#endif
+
+
+ bool SingleProcess_PayCosts(cAvidaContext& ctx, const cInstruction& cur_inst);
+ bool SingleProcess_ExecuteInst(cAvidaContext& ctx, const cInstruction& cur_inst);
+
+ // -------- Stack Manipulation... --------
+ inline void StackPush(int value);
+ inline int StackPop();
+ inline void StackFlip();
+ inline void StackClear();
+ inline void SwitchStack();
+
+
+ // -------- Head Manipulation (including IP) --------
+ cHeadCPU& GetActiveHead() { return m_threads[m_cur_thread].heads[m_threads[m_cur_thread].cur_head]; }
+ void AdjustHeads();
+
+
+ // -------- Label Manipulation -------
+ const cCodeLabel& GetLabel() const { return m_threads[m_cur_thread].next_label; }
+ cCodeLabel& GetLabel() { return m_threads[m_cur_thread].next_label; }
+ void ReadLabel(int max_size=nHardware::MAX_LABEL_SIZE);
+ 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);
+ const cCodeLabel& GetReadLabel() const { return m_threads[m_cur_thread].read_label; }
+ cCodeLabel& GetReadLabel() { return m_threads[m_cur_thread].read_label; }
+
+
+ // -------- Thread Manipulation -------
+ bool ForkThread(); // Adds a new thread based off of m_cur_thread.
+ bool KillThread(); // Kill the current thread!
+
+
+ // ---------- Instruction Helpers -----------
+ int FindModifiedRegister(int default_register);
+ int FindModifiedNextRegister(int default_register);
+ int FindModifiedPreviousRegister(int default_register);
+ int FindModifiedHead(int default_head);
+ int FindNextRegister(int base_reg);
+
+ bool Allocate_Necro(const int new_size);
+ bool Allocate_Random(cAvidaContext& ctx, const int old_size, const int new_size);
+ bool Allocate_Default(const int new_size);
+ bool Allocate_Main(cAvidaContext& ctx, const int allocated_size);
+
+ int GetCopiedSize(const int parent_size, const int child_size);
+
+ bool Divide_Main(cAvidaContext& ctx, const int divide_point, const int extra_lines=0, double mut_multiplier=1);
+ bool Divide_MainRS(cAvidaContext& ctx, const int divide_point, const int extra_lines=0, double mut_multiplier=1); //AWC 06/29/06
+ bool Divide_Main1RS(cAvidaContext& ctx, const int divide_point, const int extra_lines=0, double mut_multiplier=1); //AWC 07/28/06
+ bool Divide_Main2RS(cAvidaContext& ctx, const int divide_point, const int extra_lines=0, double mut_multiplier=1); //AWC 07/28/06
+
+ void Divide_DoTransposons(cAvidaContext& ctx);
+
+ void InjectCode(const cGenome& injection, const int line_num);
+
+ bool HeadCopy_ErrorCorrect(cAvidaContext& ctx, double reduction);
+ bool Inst_HeadDivideMut(cAvidaContext& ctx, double mut_multiplier = 1);
+
+ void ReadInst(const int in_inst);
+
+
+ cHardwareGX& operator=(const cHardwareGX&); // @not_implemented
+
+public:
+ cHardwareGX(cWorld* world, cOrganism* in_organism, cInstSet* in_inst_set);
+ explicit cHardwareGX(const cHardwareGX&);
+ ~cHardwareGX() { ; }
+ static tInstLib<tMethod>* GetInstLib() { return s_inst_slib; }
+ static cString GetDefaultInstFilename() { return "instset-gx.cfg"; }
+
+ void Reset();
+ void SingleProcess(cAvidaContext& ctx);
+ void ProcessBonusInst(cAvidaContext& ctx, const cInstruction& inst);
+
+
+ // -------- Helper methods --------
+ int GetType() const { return HARDWARE_TYPE_CPU_GX; }
+ bool OK();
+ void PrintStatus(std::ostream& fp);
+
+
+ // -------- Stack Manipulation... --------
+ inline int GetStack(int depth=0, int stack_id=-1, int in_thread=-1) const;
+ inline int GetNumStacks() const { return 2; }
+
+
+ // -------- Head Manipulation (including IP) --------
+ const cHeadCPU& GetHead(int head_id) const { return m_threads[m_cur_thread].heads[head_id]; }
+ cHeadCPU& GetHead(int head_id) { return m_threads[m_cur_thread].heads[head_id];}
+ const cHeadCPU& GetHead(int head_id, int thread) const { return m_threads[thread].heads[head_id]; }
+ cHeadCPU& GetHead(int head_id, int thread) { return m_threads[thread].heads[head_id];}
+ int GetNumHeads() const { return NUM_HEADS; }
+
+ const cHeadCPU& IP() const { return m_threads[m_cur_thread].heads[nHardware::HEAD_IP]; }
+ cHeadCPU& IP() { return m_threads[m_cur_thread].heads[nHardware::HEAD_IP]; }
+ const cHeadCPU& IP(int thread) const { return m_threads[thread].heads[nHardware::HEAD_IP]; }
+ cHeadCPU& IP(int thread) { return m_threads[thread].heads[nHardware::HEAD_IP]; }
+
+
+ // -------- Memory Manipulation --------
+ const cCPUMemory& GetMemory() const { return m_memory; }
+ cCPUMemory& GetMemory() { return m_memory; }
+ const cCPUMemory& GetMemory(int value) const { return m_memory; }
+ cCPUMemory& GetMemory(int value) { return m_memory; }
+ int GetNumMemSpaces() const { return 1; }
+
+
+ // -------- Register Manipulation --------
+ const int GetRegister(int reg_id) const { return m_threads[m_cur_thread].reg[reg_id]; }
+ int& GetRegister(int reg_id) { return m_threads[m_cur_thread].reg[reg_id]; }
+ int GetNumRegisters() const { return NUM_REGISTERS; }
+
+
+ // -------- Thread Manipulation --------
+ bool ThreadSelect(const int thread_num);
+ bool ThreadSelect(const cCodeLabel& in_label) { return false; } // Labeled threads not supported
+ inline void ThreadPrev(); // Shift the current thread in use.
+ inline void ThreadNext();
+ cInjectGenotype* ThreadGetOwner() { return NULL; } // @DMB - cHardwareGX does not really implement cInjectGenotype yet
+ void ThreadSetOwner(cInjectGenotype* in_genotype) { return; }
+
+ int GetNumThreads() const { return m_threads.GetSize(); }
+ int GetCurThread() const { return m_cur_thread; }
+ int GetCurThreadID() const { return m_threads[m_cur_thread].GetID(); }
+
+
+ // -------- Parasite Stuff --------
+ bool InjectHost(const cCodeLabel& in_label, const cGenome& injection);
+
+
+ // Non-Standard Methods
+
+ int GetActiveStack() const { return m_threads[m_cur_thread].cur_stack; }
+ bool GetMalActive() const { return m_mal_active; }
+
+private:
+ // ---------- Instruction Library -----------
+
+ // Flow Control
+ bool Inst_If0(cAvidaContext& ctx);
+ bool Inst_IfEqu(cAvidaContext& ctx);
+ bool Inst_IfNot0(cAvidaContext& ctx);
+ bool Inst_IfNEqu(cAvidaContext& ctx);
+ bool Inst_IfGr0(cAvidaContext& ctx);
+ bool Inst_IfGr(cAvidaContext& ctx);
+ bool Inst_IfGrEqu0(cAvidaContext& ctx);
+ bool Inst_IfGrEqu(cAvidaContext& ctx);
+ bool Inst_IfLess0(cAvidaContext& ctx);
+ bool Inst_IfLess(cAvidaContext& ctx);
+ bool Inst_IfLsEqu0(cAvidaContext& ctx);
+ bool Inst_IfLsEqu(cAvidaContext& ctx);
+ bool Inst_IfBit1(cAvidaContext& ctx);
+ bool Inst_IfANotEqB(cAvidaContext& ctx);
+ bool Inst_IfBNotEqC(cAvidaContext& ctx);
+ bool Inst_IfANotEqC(cAvidaContext& ctx);
+
+ bool Inst_JumpF(cAvidaContext& ctx);
+ bool Inst_JumpB(cAvidaContext& ctx);
+ bool Inst_Call(cAvidaContext& ctx);
+ bool Inst_Return(cAvidaContext& ctx);
+
+ bool Inst_Throw(cAvidaContext& ctx);
+ bool Inst_ThrowIf0(cAvidaContext& ctx);
+ bool Inst_ThrowIfNot0(cAvidaContext& ctx);
+ bool Inst_Catch(cAvidaContext& ctx) { ReadLabel(); return true; };
+
+ bool Inst_Goto(cAvidaContext& ctx);
+ bool Inst_GotoIf0(cAvidaContext& ctx);
+ bool Inst_GotoIfNot0(cAvidaContext& ctx);
+ bool Inst_Label(cAvidaContext& ctx) { ReadLabel(); return true; };
+
+ // Stack and Register Operations
+ bool Inst_Pop(cAvidaContext& ctx);
+ bool Inst_Push(cAvidaContext& ctx);
+ bool Inst_HeadPop(cAvidaContext& ctx);
+ bool Inst_HeadPush(cAvidaContext& ctx);
+
+ bool Inst_PopA(cAvidaContext& ctx);
+ bool Inst_PopB(cAvidaContext& ctx);
+ bool Inst_PopC(cAvidaContext& ctx);
+ bool Inst_PushA(cAvidaContext& ctx);
+ bool Inst_PushB(cAvidaContext& ctx);
+ bool Inst_PushC(cAvidaContext& ctx);
+
+ bool Inst_SwitchStack(cAvidaContext& ctx);
+ bool Inst_FlipStack(cAvidaContext& ctx);
+ bool Inst_Swap(cAvidaContext& ctx);
+ bool Inst_SwapAB(cAvidaContext& ctx);
+ bool Inst_SwapBC(cAvidaContext& ctx);
+ bool Inst_SwapAC(cAvidaContext& ctx);
+ bool Inst_CopyReg(cAvidaContext& ctx);
+ bool Inst_CopyRegAB(cAvidaContext& ctx);
+ bool Inst_CopyRegAC(cAvidaContext& ctx);
+ bool Inst_CopyRegBA(cAvidaContext& ctx);
+ bool Inst_CopyRegBC(cAvidaContext& ctx);
+ bool Inst_CopyRegCA(cAvidaContext& ctx);
+ bool Inst_CopyRegCB(cAvidaContext& ctx);
+ bool Inst_Reset(cAvidaContext& ctx);
+
+ // Single-Argument Math
+ bool Inst_ShiftR(cAvidaContext& ctx);
+ bool Inst_ShiftL(cAvidaContext& ctx);
+ bool Inst_Bit1(cAvidaContext& ctx);
+ bool Inst_SetNum(cAvidaContext& ctx);
+ bool Inst_ValGrey(cAvidaContext& ctx);
+ bool Inst_ValDir(cAvidaContext& ctx);
+ bool Inst_ValAddP(cAvidaContext& ctx);
+ bool Inst_ValFib(cAvidaContext& ctx);
+ bool Inst_ValPolyC(cAvidaContext& ctx);
+ bool Inst_Inc(cAvidaContext& ctx);
+ bool Inst_Dec(cAvidaContext& ctx);
+ bool Inst_Zero(cAvidaContext& ctx);
+ bool Inst_Not(cAvidaContext& ctx);
+ bool Inst_Neg(cAvidaContext& ctx);
+ bool Inst_Square(cAvidaContext& ctx);
+ bool Inst_Sqrt(cAvidaContext& ctx);
+ bool Inst_Log(cAvidaContext& ctx);
+ bool Inst_Log10(cAvidaContext& ctx);
+ bool Inst_Minus17(cAvidaContext& ctx);
+
+ // Double Argument Math
+ bool Inst_Add(cAvidaContext& ctx);
+ bool Inst_Sub(cAvidaContext& ctx);
+ bool Inst_Mult(cAvidaContext& ctx);
+ bool Inst_Div(cAvidaContext& ctx);
+ bool Inst_Mod(cAvidaContext& ctx);
+ bool Inst_Nand(cAvidaContext& ctx);
+ bool Inst_Nor(cAvidaContext& ctx);
+ bool Inst_And(cAvidaContext& ctx);
+ bool Inst_Order(cAvidaContext& ctx);
+ bool Inst_Xor(cAvidaContext& ctx);
+
+ // Biological
+ bool Inst_Copy(cAvidaContext& ctx);
+ bool Inst_ReadInst(cAvidaContext& ctx);
+ bool Inst_WriteInst(cAvidaContext& ctx);
+ bool Inst_StackReadInst(cAvidaContext& ctx);
+ bool Inst_StackWriteInst(cAvidaContext& ctx);
+ bool Inst_Compare(cAvidaContext& ctx);
+ bool Inst_IfNCpy(cAvidaContext& ctx);
+ bool Inst_Allocate(cAvidaContext& ctx);
+ bool Inst_Divide(cAvidaContext& ctx);
+ bool Inst_DivideRS(cAvidaContext& ctx); // AWC 06/29/06
+ bool Inst_CAlloc(cAvidaContext& ctx);
+ bool Inst_CDivide(cAvidaContext& ctx);
+ bool Inst_MaxAlloc(cAvidaContext& ctx);
+ bool Inst_Inject(cAvidaContext& ctx);
+ bool Inst_InjectRand(cAvidaContext& ctx);
+ bool Inst_InjectThread(cAvidaContext& ctx);
+ bool Inst_Transposon(cAvidaContext& ctx);
+ bool Inst_Repro(cAvidaContext& ctx);
+ bool Inst_TaskPutRepro(cAvidaContext& ctx);
+ bool Inst_TaskPutResetInputsRepro(cAvidaContext& ctx);
+
+ bool Inst_SpawnDeme(cAvidaContext& ctx);
+ bool Inst_Kazi(cAvidaContext& ctx);
+ bool Inst_Kazi5(cAvidaContext& ctx);
+ bool Inst_Die(cAvidaContext& ctx);
+
+ // I/O and Sensory
+ bool Inst_TaskGet(cAvidaContext& ctx);
+ bool Inst_TaskGet2(cAvidaContext& ctx);
+ bool Inst_TaskStackGet(cAvidaContext& ctx);
+ bool Inst_TaskStackLoad(cAvidaContext& ctx);
+ bool Inst_TaskPut(cAvidaContext& ctx);
+ bool Inst_TaskPutResetInputs(cAvidaContext& ctx);
+ bool Inst_TaskIO(cAvidaContext& ctx);
+ bool Inst_TaskIO_Feedback(cAvidaContext& ctx);
+ bool Inst_MatchStrings(cAvidaContext& ctx);
+ bool Inst_Sell(cAvidaContext& ctx);
+ bool Inst_Buy(cAvidaContext& ctx);
+ bool Inst_Send(cAvidaContext& ctx);
+ bool Inst_Receive(cAvidaContext& ctx);
+ bool Inst_SenseLog2(cAvidaContext& ctx);
+ bool Inst_SenseUnit(cAvidaContext& ctx);
+ bool Inst_SenseMult100(cAvidaContext& ctx);
+ bool DoSense(cAvidaContext& ctx, int conversion_method, double base);
+
+ void DoDonate(cOrganism * to_org);
+ bool Inst_DonateRandom(cAvidaContext& ctx);
+ bool Inst_DonateKin(cAvidaContext& ctx);
+ bool Inst_DonateEditDist(cAvidaContext& ctx);
+ bool Inst_DonateNULL(cAvidaContext& ctx);
+
+ bool Inst_SearchF(cAvidaContext& ctx);
+ bool Inst_SearchB(cAvidaContext& ctx);
+ bool Inst_MemSize(cAvidaContext& ctx);
+
+ // Environment
+
+ bool Inst_RotateL(cAvidaContext& ctx);
+ bool Inst_RotateR(cAvidaContext& ctx);
+ bool Inst_SetCopyMut(cAvidaContext& ctx);
+ bool Inst_ModCopyMut(cAvidaContext& ctx);
+
+ // Energy use
+
+ bool Inst_ZeroEnergyUsed(cAvidaContext& ctx);
+
+ // Multi-threading...
+
+ bool Inst_ForkThread(cAvidaContext& ctx);
+ bool Inst_KillThread(cAvidaContext& ctx);
+ bool Inst_ThreadID(cAvidaContext& ctx);
+
+ // Head-based instructions...
+
+ bool Inst_SetHead(cAvidaContext& ctx);
+ bool Inst_AdvanceHead(cAvidaContext& ctx);
+ bool Inst_MoveHead(cAvidaContext& ctx);
+ bool Inst_JumpHead(cAvidaContext& ctx);
+ bool Inst_GetHead(cAvidaContext& ctx);
+ bool Inst_IfLabel(cAvidaContext& ctx);
+ bool Inst_IfLabel2(cAvidaContext& ctx);
+ bool Inst_HeadDivide(cAvidaContext& ctx);
+ bool Inst_HeadDivideRS(cAvidaContext& ctx); //AWC 06/29/06
+ bool Inst_HeadDivide1RS(cAvidaContext& ctx); //AWC 07/28/06
+ bool Inst_HeadDivide2RS(cAvidaContext& ctx); //AWC 08/29/06
+ bool Inst_HeadRead(cAvidaContext& ctx);
+ bool Inst_HeadWrite(cAvidaContext& ctx);
+ bool Inst_HeadCopy(cAvidaContext& ctx);
+ bool Inst_HeadSearch(cAvidaContext& ctx);
+ bool Inst_SetFlow(cAvidaContext& ctx);
+
+ bool Inst_HeadCopy2(cAvidaContext& ctx);
+ bool Inst_HeadCopy3(cAvidaContext& ctx);
+ bool Inst_HeadCopy4(cAvidaContext& ctx);
+ bool Inst_HeadCopy5(cAvidaContext& ctx);
+ bool Inst_HeadCopy6(cAvidaContext& ctx);
+ bool Inst_HeadCopy7(cAvidaContext& ctx);
+ bool Inst_HeadCopy8(cAvidaContext& ctx);
+ bool Inst_HeadCopy9(cAvidaContext& ctx);
+ bool Inst_HeadCopy10(cAvidaContext& ctx);
+
+ bool Inst_HeadDivideSex(cAvidaContext& ctx);
+ bool Inst_HeadDivideAsex(cAvidaContext& ctx);
+ bool Inst_HeadDivideAsexWait(cAvidaContext& ctx);
+ bool Inst_HeadDivideMateSelect(cAvidaContext& ctx);
+
+ bool Inst_HeadDivide1(cAvidaContext& ctx);
+ bool Inst_HeadDivide2(cAvidaContext& ctx);
+ bool Inst_HeadDivide3(cAvidaContext& ctx);
+ bool Inst_HeadDivide4(cAvidaContext& ctx);
+ bool Inst_HeadDivide5(cAvidaContext& ctx);
+ bool Inst_HeadDivide6(cAvidaContext& ctx);
+ bool Inst_HeadDivide7(cAvidaContext& ctx);
+ bool Inst_HeadDivide8(cAvidaContext& ctx);
+ bool Inst_HeadDivide9(cAvidaContext& ctx);
+ bool Inst_HeadDivide10(cAvidaContext& ctx);
+ bool Inst_HeadDivide16(cAvidaContext& ctx);
+ bool Inst_HeadDivide32(cAvidaContext& ctx);
+ bool Inst_HeadDivide50(cAvidaContext& ctx);
+ bool Inst_HeadDivide100(cAvidaContext& ctx);
+ bool Inst_HeadDivide500(cAvidaContext& ctx);
+ bool Inst_HeadDivide1000(cAvidaContext& ctx);
+ bool Inst_HeadDivide5000(cAvidaContext& ctx);
+ bool Inst_HeadDivide10000(cAvidaContext& ctx);
+ bool Inst_HeadDivide50000(cAvidaContext& ctx);
+ bool Inst_HeadDivide0_5(cAvidaContext& ctx);
+ bool Inst_HeadDivide0_1(cAvidaContext& ctx);
+ bool Inst_HeadDivide0_05(cAvidaContext& ctx);
+ bool Inst_HeadDivide0_01(cAvidaContext& ctx);
+ bool Inst_HeadDivide0_001(cAvidaContext& ctx);
+
+ //// Placebo ////
+ bool Inst_Skip(cAvidaContext& ctx);
+};
+
+
+#ifdef ENABLE_UNIT_TESTS
+namespace nHardwareCPU {
+ /**
+ * Run unit tests
+ *
+ * @param full Run full test suite; if false, just the fast tests.
+ **/
+ void UnitTests(bool full = false);
+}
+#endif
+
+
+inline bool cHardwareGX::ThreadSelect(const int thread_num)
+{
+ if (thread_num >= 0 && thread_num < m_threads.GetSize()) {
+ m_cur_thread = thread_num;
+ return true;
+ }
+
+ return false;
+}
+
+inline void cHardwareGX::ThreadNext()
+{
+ m_cur_thread++;
+ if (m_cur_thread >= GetNumThreads()) m_cur_thread = 0;
+}
+
+inline void cHardwareGX::ThreadPrev()
+{
+ if (m_cur_thread == 0) m_cur_thread = GetNumThreads() - 1;
+ else m_cur_thread--;
+}
+
+inline void cHardwareGX::StackPush(int value)
+{
+ if (m_threads[m_cur_thread].cur_stack == 0) {
+ m_threads[m_cur_thread].stack.Push(value);
+ } else {
+ m_global_stack.Push(value);
+ }
+}
+
+inline int cHardwareGX::StackPop()
+{
+ int pop_value;
+
+ if (m_threads[m_cur_thread].cur_stack == 0) {
+ pop_value = m_threads[m_cur_thread].stack.Pop();
+ } else {
+ pop_value = m_global_stack.Pop();
+ }
+
+ return pop_value;
+}
+
+inline void cHardwareGX::StackFlip()
+{
+ if (m_threads[m_cur_thread].cur_stack == 0) {
+ m_threads[m_cur_thread].stack.Flip();
+ } else {
+ m_global_stack.Flip();
+ }
+}
+
+inline int cHardwareGX::GetStack(int depth, int stack_id, int in_thread) const
+{
+ int value = 0;
+
+ if(in_thread >= m_threads.GetSize() || in_thread < 0) in_thread = m_cur_thread;
+
+ if (stack_id == -1) stack_id = m_threads[in_thread].cur_stack;
+
+ if (stack_id == 0) value = m_threads[in_thread].stack.Get(depth);
+ else if (stack_id == 1) value = m_global_stack.Get(depth);
+
+ return value;
+}
+
+inline void cHardwareGX::StackClear()
+{
+ if (m_threads[m_cur_thread].cur_stack == 0) {
+ m_threads[m_cur_thread].stack.Clear();
+ } else {
+ m_global_stack.Clear();
+ }
+}
+
+inline void cHardwareGX::SwitchStack()
+{
+ m_threads[m_cur_thread].cur_stack++;
+ if (m_threads[m_cur_thread].cur_stack > 1) m_threads[m_cur_thread].cur_stack = 0;
+}
+
+#endif
Modified: development/source/cpu/cHardwareManager.cc
===================================================================
--- development/source/cpu/cHardwareManager.cc 2007-03-30 15:03:40 UTC (rev 1442)
+++ development/source/cpu/cHardwareManager.cc 2007-04-01 22:37:34 UTC (rev 1443)
@@ -28,6 +28,7 @@
#include "cHardwareExperimental.h"
#include "cHardwareSMT.h"
#include "cHardwareTransSMT.h"
+#include "cHardwareGX.h"
#include "cInitFile.h"
#include "cInstSet.h"
#include "cWorld.h"
@@ -59,6 +60,10 @@
m_inst_set = new cInstSet(world, cHardwareExperimental::GetInstLib());
default_filename = cHardwareExperimental::GetDefaultInstFilename();
break;
+ case HARDWARE_TYPE_CPU_GX:
+ m_inst_set = new cInstSet(world, cHardwareGX::GetInstLib());
+ default_filename = cHardwareGX::GetDefaultInstFilename();
+ break;
default:
m_world->GetDriver().RaiseFatalException(1, "Unknown/Unsupported HARDWARE_TYPE specified");
}
@@ -129,6 +134,8 @@
return new cHardwareTransSMT(m_world, in_org, m_inst_set);
case HARDWARE_TYPE_CPU_EXPERIMENTAL:
return new cHardwareExperimental(m_world, in_org, m_inst_set);
+ case HARDWARE_TYPE_CPU_GX:
+ return new cHardwareGX(m_world, in_org, m_inst_set);
default:
return NULL;
}
Modified: development/source/defs.h
===================================================================
--- development/source/defs.h 2007-03-30 15:03:40 UTC (rev 1442)
+++ development/source/defs.h 2007-04-01 22:37:34 UTC (rev 1443)
@@ -87,7 +87,8 @@
HARDWARE_TYPE_CPU_ORIGINAL = 0,
HARDWARE_TYPE_CPU_SMT,
HARDWARE_TYPE_CPU_TRANSSMT,
- HARDWARE_TYPE_CPU_EXPERIMENTAL
+ HARDWARE_TYPE_CPU_EXPERIMENTAL,
+ HARDWARE_TYPE_CPU_GX
};
enum tTIMESLICE
More information about the Avida-cvs
mailing list