1 /*
2  *  cHardwareGX.h
3  *  Avida
4  *
5  *  Copyright 1999-2011 Michigan State University. All rights reserved.
6  *
7  *
8  *  This file is part of Avida.
9  *
10  *  Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
11  *  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
12  *
13  *  Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public License along with Avida.
17  *  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *
20  * cHardwareGX enables gene expression as follows:
21  * 1) Unlike cHardware{CPU,SMT,TransSMT}, the genome is not directly
22  *    executed by this organism.  Instead, cHardwareGX enables portions of the
23  *    genome to be transcribed into "programids," which are able to execute
24  *    independently.
25  * 2) The interaction between programids within cHardwareGX is based on
26  *    pattern-matching different genome fragments.  Each programid is able to
27  *    specify a "match" that will be probabilistically compared against other
28  *    programids.  When (if) a match is found, those two programids "bind"
29  *    together.  Different actions may be taken on bind, depending on the
30  *    type of match performed.
31  *
32  * \todo cHardwareGX is really not a new CPU architecture, but rather a way for
33  *  CPUs to interact.  It's much easier, however, to start off by implementing a
34  *  new CPU, so that's what we're doing.  Eventually we'll need to revisit this.
35  *
36  * \todo There should be better ways for promoter regions to work.  Right now,
37  * look for exact matches only and they have equal probabilities @JEB
38  *
39  * \todo We need to abstract cOrganism and derive a new class
40  * that can accommodate multiple genome fragments.
41  *
42  */
43 #ifndef cHardwareGX_h
44 #define cHardwareGX_h
45 
46 #include "avida/Avida.h"
47 
48 #include "cCodeLabel.h"
49 #include "cHeadCPU.h"
50 #include "cCPUMemory.h"
51 #include "cCPUStack.h"
52 #include "cHardwareBase.h"
53 #include "cString.h"
54 #include "cStats.h"
55 #include "tArray.h"
56 #include "tInstLib.h"
57 #include "nHardware.h"
58 #include "tBuffer.h"
59 
60 #include <iomanip>
61 #include <vector>
62 #include <list>
63 #include <utility>
64 
65 class cInstLib;
66 class cInstSet;
67 class cOrganism;
68 
69 /*! Each organism may have a cHardwareGX structure that keeps track of the
70 * current status of simulated hardware.  This particular CPU architecture is
71 * designed to explore the evolution of gene expression and also the effect
72 * of having persistent "protein-like" pieces of code that continually execute in parallel.
73 */
74 class cHardwareGX : public cHardwareBase
75 {
76 public:
77   typedef bool (cHardwareGX::*tMethod)(cAvidaContext& ctx); //!< Instruction type.
78 
79   static const int NUM_REGISTERS = 3; //!< Number of registers each cProgramid has.
80   //! Number of heads each cProgramid has.
81   static const int NUM_HEADS = nHardware::NUM_HEADS >= NUM_REGISTERS ? nHardware::NUM_HEADS : NUM_REGISTERS;
82   static const int NUM_NOPS = 3; //!< Number of NOPS that cHardwareGX supports.
83 
84   // GX "options" that haven't graduated to the Config File
85 
86   // "Normal" Model
87 
88   static const int PROGRAMID_REPLACEMENT_METHOD = 0;
89    //!< Controls what happens when we try to allocate a new cProgramid, but are up against the limit
90     // 0 = Fail if no programids available
91     // 1 = Replace the programid that has used the most cpu cycles
92   static const double EXECUTABLE_COPY_PROCESSIVITY; // Set to 1.0 by default
93   static const double READABLE_COPY_PROCESSIVITY;   // Set to 1.0 by default
94 
95   unsigned int m_last_unique_id_assigned; // Counter: so programids can be assigned unique IDs for tracking
96 
97   //! Enums for the different supported registers.
98   enum tRegisters { REG_AX=0, REG_BX, REG_CX };
99 
100   class cProgramid; // pre-declaration.
101   typedef cProgramid* programid_ptr; //!< It would be nice to change this to boost::shared_ptr.
102   typedef std::vector<programid_ptr> programid_list; //!< Type for the list of cProgramids.
103 
104   //! cMatchSite holds a couple useful pointers for cProgramid::Match, Bind.
105   struct cMatchSite {
cMatchSitecMatchSite106     cMatchSite() : m_programid(0), m_site(0) { }
107     cProgramid* m_programid; //!< The programid matched against; 0 if not matched.
108     int m_site; //!< Location in the cProgramid where a match occurred; 0 if not matched.
109     cCodeLabel m_label; //!< The label that was matched against.
110   };
111 
112   /*! cHeadProgramid is just cHeadCPU with a link back to the programid
113   so that we can tell when a head is on the programid that owns it.
114   */
115   class cHeadProgramid : public cHeadCPU
116   {
117   private:
118     cProgramid* m_programid;
119   public:
cHeadCPU(hw,pos,ms)120     cHeadProgramid(cHardwareBase* hw = NULL, int pos = 0, int ms = 0) : cHeadCPU(hw, pos, ms) , m_programid(NULL) {  };
~cHeadProgramid()121     ~cHeadProgramid() { ; }
122 
SetProgramid(cProgramid * _programid)123     void SetProgramid(cProgramid* _programid) { m_programid = _programid; }
GetProgramid()124     cProgramid* GetProgramid() { return m_programid; }
125   };
126 
127   /*! cProgramid is the "heart" of the gene expression hardware.  It encapsulates
128     the genome fragment that is used by both active and passive elements within
129     this organism, and enables these fragments to match against, and bind to, each
130     other depending on their particular instruction sequence.
131 
132     It is similar in spirit to a thread, but has certain operational characteristics
133     that make it unique (e.g., matching, disassociation, and a self-contained genome
134     fragment).
135 
136     \todo Need to rework cHeadCPU to not need a pointer to cHardwareBase.
137     */
138   class cProgramid {
139   public:
140     //! Constructs a cProgramid from a genome and CPU.
141     cProgramid(const Sequence& genome, cHardwareGX* hardware);
~cProgramid()142     ~cProgramid() {}
143 
144     //! Returns whether and where this cProgramid matches the passed-in label.
145     std::vector<cHardwareGX::cMatchSite> Sites(const cCodeLabel& label);
146     //! Binds one of this cProgramid's heads to the passed-in match site.
147     void Bind(nHardware::tHeads head, cMatchSite& site);
148     //! Detaches this cProgramid's heads from bound cProgramids.
149     void Detach();
150 
151     //! Removes regulation in implicit GX mode
152     void RemoveRegulation();
153 
154     // Programids keep a count of the total number
155     // of READ + WRITE heads of other programids that
156     // have been placed on them. They only execute
157     // if free of other heads and also initialized as executable.
RemoveContactingHead(cHeadProgramid & head)158     void RemoveContactingHead(cHeadProgramid& head) {
159       if(head.GetProgramid()->GetID() == m_id) return;
160       assert(m_contacting_heads > 0);
161       m_contacting_heads--;
162     }
163 
AddContactingHead(cHeadProgramid & head)164     void AddContactingHead(cHeadProgramid& head) {
165       if(head.GetProgramid()->GetID() == m_id) return;
166       m_contacting_heads++;
167     }
168 
169     void ResetHeads();
170     void Reset();
171 
172     // Accessors
GetExecute()173     bool GetExecute() { return m_executable && (m_contacting_heads == 0); }
GetExecutable()174     bool GetExecutable() { return m_executable; }
GetBindable()175     bool GetBindable() { return m_bindable; }
GetReadable()176     bool GetReadable() { return m_readable; }
GetID()177     int  GetID() { return m_id; }
GetInputBuf()178     tBuffer<int>& GetInputBuf() { return m_input_buf; }
GetOutputBuf()179     tBuffer<int>& GetOutputBuf() { return m_output_buf; }
GetCPUCyclesUsed()180     int  GetCPUCyclesUsed() { return m_cpu_cycles_used; }
ResetCPUCyclesUsed()181     void ResetCPUCyclesUsed() { m_cpu_cycles_used = 0; }
GetInst(cString inst)182     cInstruction GetInst(cString inst) { assert(m_gx_hardware); return m_gx_hardware->GetInstSet().GetInst(inst); }
183 
GetMemory()184     const cCPUMemory& GetMemory() const { return m_memory; }
185 
186     //! Append this programid's genome to the passed-in genome in linear format (includes tags).
187     void AppendLinearGenome(Sequence& genome);
188 
189     //! Print this programid's genome, in linear format.
190     void PrintGenome(std::ostream& out);
191 
GetHead(int head_id)192     cHeadProgramid& GetHead(int head_id) { return m_heads[head_id]; }
193 
194     // Assignment
SetExecutable(bool _executable)195     void SetExecutable(bool _executable) { m_executable = _executable; }
SetBindable(bool _bindable)196     void SetBindable(bool _bindable) { m_bindable = _bindable; }
SetReadable(bool _readable)197     void SetReadable(bool _readable) { m_readable = _readable; }
198 
IncCPUCyclesUsed()199     void IncCPUCyclesUsed() { m_cpu_cycles_used++; }
200 
201     cHardwareGX* m_gx_hardware;  //!< Back reference
202     int m_id; //!< Each programid is cross-referenced to a memory space.
203               // The index in cHardwareGX::m_programids and cHeadCPU::GetMemSpace() must match up.
204               // A programid also needs to be kept aware of its current index.
205     int m_unique_id; // ID unique to this programid (per hardware)
206 
207     int m_contacting_heads; //!< The number of read/write heads on this programid from other programids.
208     bool m_executable;  //!< Is this programid ever executable? Currently, a programid with head from another cProgramid on it is also stopped.
209     bool m_bindable; //!< Is this programid bindable, i.e. can other programids put their read heads on it?
210     bool m_readable; //!< Is this programid readable?
211     bool m_marked_for_death; //!< Is this programid marked for deletion?
212     int m_cpu_cycles_used; //!< Number of cpu cycles this programid has used.
213 
214     bool m_copying_site; //! Are we in the middle of copying a "site" (which could cause termination)
215     cCodeLabel m_copying_label; //! The current site label that we are copying
216     cCodeLabel m_terminator_label; //!< The label that this cProgramid must traverse to disassociate.
217 
218     // Core variables maintained from previous incarnation as a thread
219     cCodeLabel m_read_label; //!< ?
220     cCodeLabel m_next_label; //!< ?
221     cCPUMemory m_memory; //!< This cProgramid's genome fragment.
222     cCPUStack m_stack; //!< This cProgramid's stack (no global stack).
223     cHeadProgramid m_heads[NUM_HEADS]; //!< This cProgramid's heads.
224     int m_regs[NUM_REGISTERS]; //!< This cProgramid's registers.
225 
226     int m_input_pointer;
227     tBuffer<int> m_input_buf; //!< This programid's input buffer.
228     tBuffer<int> m_output_buf; //!< This programid's output buffer.
229 
230   };
231 
232 protected:
233   static tInstLib<tMethod>* initInstLib(void); //!< Initialize the instruction library.
234   static tInstLib<tMethod>* s_inst_slib; //!< Instruction library (method pointers for all instructions).
235 
236   programid_list m_programids; //!< The list of cProgramids.
237   programid_ptr m_current; //!< The currently-executing cProgramid.
238 
239   // Implicit RNAP Model only
240   cHeadProgramid m_promoter_update_head; //Promoter position that last executable programid was created from.
241   tArray<double> m_promoter_states;
242   tArray<double> m_promoter_rates; // CURRENT promoter rates. Regulation on top of default.
243   tArray<double> m_promoter_default_rates; // Rates sans regulation
244   tArray<int> m_promoter_occupied_sites; // Whether the site is blocked by a currently bound regulatory protein.
245   double m_recycle_state;
246   double m_promoter_sum;
247 
248   // --------  Member Variables  --------
249   const tMethod* m_functions;
250 
251   // Flags...
252   bool m_mal_active;         // Has an allocate occured since last divide?
253   bool m_advance_ip;         // Should the IP advance after this instruction?
254   bool m_executedmatchstrings;	// Have we already executed the match strings instruction?
255   bool m_just_divided; // Did we just divide (in which case end execution of programids until next cycle).
256   bool m_reset_inputs; // Flag to make it easy for instructions to reset all inputs (force task modularity).
257   bool m_reset_heads;  // Flas to make it easy for instructions to reset heads back (force task modularity).
258 
259   bool SingleProcess_ExecuteInst(cAvidaContext& ctx, const cInstruction& cur_inst);
260 
261   // --------  Stack Manipulation...  --------
StackPush(int value)262   inline void StackPush(int value) { assert(m_current); m_current->m_stack.Push(value); }
StackPop()263   inline int StackPop() { assert(m_current); return m_current->m_stack.Pop(); }
StackFlip()264   inline void StackFlip() { assert(m_current); m_current->m_stack.Flip(); }
StackClear()265   inline void StackClear() { assert(m_current); m_current->m_stack.Clear(); }
SwitchStack()266   inline void SwitchStack() { }
267 
268   // --------  Head Manipulation (including IP)  --------
269   void AdjustHeads();
270 
271   // --------  Label Manipulation  -------
GetLabel()272   const cCodeLabel& GetLabel() const { assert(m_current); return m_current->m_next_label; }
GetLabel()273   cCodeLabel& GetLabel() { assert(m_current); return m_current->m_next_label; }
274   void ReadLabel(int max_size=nHardware::MAX_LABEL_SIZE);
275   cHeadCPU FindLabel(int direction);
276   int FindLabel_Forward(const cCodeLabel & search_label, const Sequence& search_genome, int pos);
277   int FindLabel_Backward(const cCodeLabel & search_label, const Sequence& search_genome, int pos);
278   cHeadCPU FindLabel(const cCodeLabel & in_label, int direction);
GetReadLabel()279   const cCodeLabel& GetReadLabel() const { assert(m_current); return m_current->m_read_label; }
GetReadLabel()280   cCodeLabel& GetReadLabel() { assert(m_current); return m_current->m_read_label; }
281 
282   // ---------- Instruction Helpers -----------
283   int FindModifiedRegister(int default_register);
284   int FindModifiedNextRegister(int default_register);
285   int FindModifiedPreviousRegister(int default_register);
286   int FindModifiedHead(int default_head);
287   int FindNextRegister(int base_reg);
288 
289   bool Allocate_Necro(const int new_size);
290   bool Allocate_Random(cAvidaContext& ctx, const int old_size, const int new_size);
291   bool Allocate_Default(const int new_size);
292   bool Allocate_Main(cAvidaContext& ctx, const int allocated_size);
293 
294 
295   void internalReset();
296 	void internalResetOnFailedDivide();
297 
298 
299   int calcExecutedSize(const int parent_size);
300   int calcCopiedSize(const int parent_size, const int child_size);
301   bool Divide_Main(cAvidaContext& ctx);
302   bool HeadCopy_ErrorCorrect(cAvidaContext& ctx, double reduction);
303   void ReadInst(const int in_inst);
304 
305 public:
306   //! Main constructor for cHardwareGX; called from cHardwareManager for every organism.
307   cHardwareGX(cAvidaContext& ctx, cWorld* world, cOrganism* in_organism, cInstSet* in_inst_set);
308   virtual ~cHardwareGX(); //!< Destructor; removes all cProgramids.
309 
GetInstLib()310   static tInstLib<tMethod>* GetInstLib() { return s_inst_slib; }
GetDefaultInstFilename()311   static cString GetDefaultInstFilename() { return "instset-gx.cfg"; }
312 
313   bool SingleProcess(cAvidaContext& ctx, bool speculative = false);
314   void ProcessBonusInst(cAvidaContext& ctx, const cInstruction& inst);
315 
316 
317   // --------  Helper methods  --------
GetType()318   int GetType() const { return HARDWARE_TYPE_CPU_GX; }
SupportsSpeculative()319   bool SupportsSpeculative() const { return false; }
320   void PrintStatus(std::ostream& fp);
SetupMiniTraceFileHeader(const cString & filename,const int gen_id,const cString & genotype)321   void SetupMiniTraceFileHeader(const cString& filename, const int gen_id, const cString& genotype) { }
PrintMiniTraceStatus(cAvidaContext & ctx,std::ostream & fp,const cString & next_name)322   void PrintMiniTraceStatus(cAvidaContext& ctx, std::ostream& fp, const cString& next_name) { }
PrintMiniTraceSuccess(std::ostream & fp,const int exec_success)323   void PrintMiniTraceSuccess(std::ostream& fp, const int exec_success) { }
324 
325   // --------  Stack Manipulation...  --------
326   inline int GetStack(int depth=0, int stack_id=-1, int in_thread=-1) const { assert(m_current); return m_current->m_stack.Get(depth); }
GetNumStacks()327   inline int GetNumStacks() const { return 2; }
328 
329   // --------  Head Manipulation (including IP)  --------
GetHead(int head_id)330   const cHeadProgramid& GetHead(int head_id) const { assert(m_current); return m_current->m_heads[head_id]; }
GetHead(int head_id)331   cHeadProgramid& GetHead(int head_id) { assert(m_current); return m_current->m_heads[head_id];}
GetHead(int head_id,int thread)332   const cHeadProgramid& GetHead(int head_id, int thread) const { assert(m_current); return m_current->m_heads[head_id]; }
GetHead(int head_id,int thread)333   cHeadProgramid& GetHead(int head_id, int thread) { assert(m_current); return m_current->m_heads[head_id];}
GetNumHeads()334   int GetNumHeads() const { return NUM_HEADS; }
335 
IP()336   const cHeadCPU& IP() const { assert(m_current); return m_current->m_heads[nHardware::HEAD_IP]; }
IP()337   cHeadCPU& IP() { assert(m_current); return m_current->m_heads[nHardware::HEAD_IP]; }
IP(int thread)338   const cHeadCPU& IP(int thread) const { assert(m_current); return m_current->m_heads[nHardware::HEAD_IP]; }
IP(int thread)339   cHeadCPU& IP(int thread) { assert(m_current); return m_current->m_heads[nHardware::HEAD_IP]; }
340 
341 
342   // --------  Memory Manipulation  --------
343   //<! Each programid counts as a memory space.
344   // Heads from one programid can end up on another,
345   // so be careful to fix these when changing the programid list.
GetMemory()346   const cCPUMemory& GetMemory() const { assert(m_current); return m_current->m_memory; }
GetMemory()347   cCPUMemory& GetMemory() { assert(m_current); return m_current->m_memory; }
GetMemSize()348   int GetMemSize() const { assert(m_current); return m_current->m_memory.GetSize(); }
GetMemory(int value)349   const cCPUMemory& GetMemory(int value) const { return m_programids[value]->m_memory; }
GetMemory(int value)350   cCPUMemory& GetMemory(int value) { return m_programids[value]->m_memory; }
GetMemSize(int value)351   int GetMemSize(int value) const { return m_programids[value]->m_memory.GetSize(); }
GetNumMemSpaces()352   int GetNumMemSpaces() const { return m_programids.size(); }
353 
354 
355   // --------  Register Manipulation  --------
GetRegister(int reg_id)356   int GetRegister(int reg_id) const { assert(m_current); return m_current->m_regs[reg_id]; }
GetRegister(int reg_id)357   int& GetRegister(int reg_id) { assert(m_current); return m_current->m_regs[reg_id]; }
GetNumRegisters()358   int GetNumRegisters() const { return NUM_REGISTERS; }
359 
360   // --------  Thread Manipuluation --------
361   /* cHardwareGX does not support threads (at least, not as in other CPUs). */
ThreadSelect(const int thread_id)362   virtual bool ThreadSelect(const int thread_id) { return false; }
ThreadSelect(const cCodeLabel & in_label)363   virtual bool ThreadSelect(const cCodeLabel& in_label) { return false; }
ThreadPrev()364   virtual void ThreadPrev() { ; }
ThreadNext()365   virtual void ThreadNext() { ; }
ThreadGetOwner()366   virtual cBioUnit* ThreadGetOwner() { return m_organism; }
367 
GetNumThreads()368   virtual int GetNumThreads() const { return 1; }
GetCurThread()369   virtual int GetCurThread() const { return -1; }
GetCurThreadID()370   virtual int GetCurThreadID() const { return -1; }
371 
372   // interrupt current thread
InterruptThread(int interruptType)373   bool InterruptThread(int interruptType) { return false; }
GetThreadMessageTriggerType(int _index)374   int GetThreadMessageTriggerType(int _index) { return -1; }
375 
376    // --------  Parasite Stuff  --------
ParasiteInfectHost(cBioUnit * bu)377   bool ParasiteInfectHost(cBioUnit* bu) { return false; }
378 
379 
380   // --------  Input/Output Buffers  --------
GetInputBuf()381   virtual tBuffer<int>& GetInputBuf() { return m_current->GetInputBuf(); }
GetOutputBuf()382   virtual tBuffer<int>& GetOutputBuf() { return m_current->GetOutputBuf(); }
383 
384 private:
385   cHardwareGX& operator=(const cHardwareGX&); //!< Not implemented.
386   cHardwareGX(const cHardwareGX&); //!< Not implemented.
387 
388   // ---------- Instruction Library -----------
389 
390   // Flow Control
391   bool Inst_If0(cAvidaContext& ctx);
392   bool Inst_IfEqu(cAvidaContext& ctx);
393   bool Inst_IfNot0(cAvidaContext& ctx);
394   bool Inst_IfNEqu(cAvidaContext& ctx);
395   bool Inst_IfGr0(cAvidaContext& ctx);
396   bool Inst_IfGr(cAvidaContext& ctx);
397   bool Inst_IfGrEqu0(cAvidaContext& ctx);
398   bool Inst_IfGrEqu(cAvidaContext& ctx);
399   bool Inst_IfLess0(cAvidaContext& ctx);
400   bool Inst_IfLess(cAvidaContext& ctx);
401   bool Inst_IfLsEqu0(cAvidaContext& ctx);
402   bool Inst_IfLsEqu(cAvidaContext& ctx);
403   bool Inst_IfBit1(cAvidaContext& ctx);
404   bool Inst_IfANotEqB(cAvidaContext& ctx);
405   bool Inst_IfBNotEqC(cAvidaContext& ctx);
406   bool Inst_IfANotEqC(cAvidaContext& ctx);
407 
408 //  bool Inst_JumpF(cAvidaContext& ctx);
409 //  bool Inst_JumpB(cAvidaContext& ctx);
410   bool Inst_Call(cAvidaContext& ctx);
411   bool Inst_Return(cAvidaContext& ctx);
412 
413   bool Inst_Throw(cAvidaContext& ctx);
414   bool Inst_ThrowIf0(cAvidaContext& ctx);
415   bool Inst_ThrowIfNot0(cAvidaContext& ctx);
Inst_Catch(cAvidaContext & ctx)416   bool Inst_Catch(cAvidaContext& ctx) { ReadLabel(); return true; };
417 
418   bool Inst_Goto(cAvidaContext& ctx);
419   bool Inst_GotoIf0(cAvidaContext& ctx);
420   bool Inst_GotoIfNot0(cAvidaContext& ctx);
Inst_Label(cAvidaContext & ctx)421   bool Inst_Label(cAvidaContext& ctx) { ReadLabel(); return true; };
422 
423   // Stack and Register Operations
424   bool Inst_Pop(cAvidaContext& ctx);
425   bool Inst_Push(cAvidaContext& ctx);
426   bool Inst_HeadPop(cAvidaContext& ctx);
427   bool Inst_HeadPush(cAvidaContext& ctx);
428 
429   bool Inst_PopA(cAvidaContext& ctx);
430   bool Inst_PopB(cAvidaContext& ctx);
431   bool Inst_PopC(cAvidaContext& ctx);
432   bool Inst_PushA(cAvidaContext& ctx);
433   bool Inst_PushB(cAvidaContext& ctx);
434   bool Inst_PushC(cAvidaContext& ctx);
435 
436   bool Inst_SwitchStack(cAvidaContext& ctx);
437   bool Inst_FlipStack(cAvidaContext& ctx);
438   bool Inst_Swap(cAvidaContext& ctx);
439   bool Inst_SwapAB(cAvidaContext& ctx);
440   bool Inst_SwapBC(cAvidaContext& ctx);
441   bool Inst_SwapAC(cAvidaContext& ctx);
442   bool Inst_CopyReg(cAvidaContext& ctx);
443   bool Inst_CopyRegAB(cAvidaContext& ctx);
444   bool Inst_CopyRegAC(cAvidaContext& ctx);
445   bool Inst_CopyRegBA(cAvidaContext& ctx);
446   bool Inst_CopyRegBC(cAvidaContext& ctx);
447   bool Inst_CopyRegCA(cAvidaContext& ctx);
448   bool Inst_CopyRegCB(cAvidaContext& ctx);
449   bool Inst_Reset(cAvidaContext& ctx);
450 
451   // Single-Argument Math
452   bool Inst_ShiftR(cAvidaContext& ctx);
453   bool Inst_ShiftL(cAvidaContext& ctx);
454   bool Inst_Bit1(cAvidaContext& ctx);
455   bool Inst_SetNum(cAvidaContext& ctx);
456   bool Inst_ValGrey(cAvidaContext& ctx);
457   bool Inst_ValDir(cAvidaContext& ctx);
458   bool Inst_ValAddP(cAvidaContext& ctx);
459   bool Inst_ValFib(cAvidaContext& ctx);
460   bool Inst_ValPolyC(cAvidaContext& ctx);
461   bool Inst_Inc(cAvidaContext& ctx);
462   bool Inst_Dec(cAvidaContext& ctx);
463   bool Inst_Zero(cAvidaContext& ctx);
464   bool Inst_Not(cAvidaContext& ctx);
465   bool Inst_Neg(cAvidaContext& ctx);
466   bool Inst_Square(cAvidaContext& ctx);
467   bool Inst_Sqrt(cAvidaContext& ctx);
468   bool Inst_Log(cAvidaContext& ctx);
469   bool Inst_Log10(cAvidaContext& ctx);
470   bool Inst_Minus17(cAvidaContext& ctx);
471 
472   // Double Argument Math
473   bool Inst_Add(cAvidaContext& ctx);
474   bool Inst_Sub(cAvidaContext& ctx);
475   bool Inst_Mult(cAvidaContext& ctx);
476   bool Inst_Div(cAvidaContext& ctx);
477   bool Inst_Mod(cAvidaContext& ctx);
478   bool Inst_Nand(cAvidaContext& ctx);
479   bool Inst_Nor(cAvidaContext& ctx);
480   bool Inst_And(cAvidaContext& ctx);
481   bool Inst_Order(cAvidaContext& ctx);
482   bool Inst_Xor(cAvidaContext& ctx);
483 
484   // Biological
485   bool Inst_Copy(cAvidaContext& ctx);
486   bool Inst_ReadInst(cAvidaContext& ctx);
487   bool Inst_WriteInst(cAvidaContext& ctx);
488   bool Inst_StackReadInst(cAvidaContext& ctx);
489   bool Inst_StackWriteInst(cAvidaContext& ctx);
490   bool Inst_Compare(cAvidaContext& ctx);
491   bool Inst_IfNCpy(cAvidaContext& ctx);
492   bool Inst_Allocate(cAvidaContext& ctx);
493   bool Inst_CAlloc(cAvidaContext& ctx);
494   bool Inst_MaxAlloc(cAvidaContext& ctx);
495 
496   bool Inst_Repro(cAvidaContext& ctx);
497 
498   bool Inst_SpawnDeme(cAvidaContext& ctx);
499   bool Inst_Kazi(cAvidaContext& ctx);
500   bool Inst_Kazi5(cAvidaContext& ctx);
501   bool Inst_Die(cAvidaContext& ctx);
502 
503   // I/O and Sensory
504   bool Inst_TaskGet(cAvidaContext& ctx);
505   bool Inst_TaskGet2(cAvidaContext& ctx);
506   bool Inst_TaskStackGet(cAvidaContext& ctx);
507   bool Inst_TaskStackLoad(cAvidaContext& ctx);
508   bool Inst_TaskPut(cAvidaContext& ctx);
509   bool Inst_TaskPutResetInputs(cAvidaContext& ctx);
510   bool Inst_TaskIO(cAvidaContext& ctx);
511   bool Inst_TaskIO_DecayBonus(cAvidaContext& ctx);
512   bool Inst_TaskIO_Feedback(cAvidaContext& ctx);
513   bool Inst_MatchStrings(cAvidaContext& ctx);
514   bool Inst_Sell(cAvidaContext& ctx);
515   bool Inst_Buy(cAvidaContext& ctx);
516   bool Inst_Send(cAvidaContext& ctx);
517   bool Inst_Receive(cAvidaContext& ctx);
518   bool Inst_SenseLog2(cAvidaContext& ctx);
519   bool Inst_SenseUnit(cAvidaContext& ctx);
520   bool Inst_SenseMult100(cAvidaContext& ctx);
521   bool DoSense(cAvidaContext& ctx, int conversion_method, double base);
522 
523   void DoDonate(cOrganism * to_org);
524   bool Inst_DonateRandom(cAvidaContext& ctx);
525   bool Inst_DonateEditDist(cAvidaContext& ctx);
526   bool Inst_DonateGreenBeardGene(cAvidaContext& ctx);
527   bool Inst_DonateTrueGreenBeard(cAvidaContext& ctx);
528   bool Inst_DonateThreshGreenBeard(cAvidaContext& ctx);
529   bool Inst_DonateQuantaThreshGreenBeard(cAvidaContext& ctx);
530   bool Inst_DonateNULL(cAvidaContext& ctx);
531 
532   bool Inst_SearchF(cAvidaContext& ctx);
533   bool Inst_SearchB(cAvidaContext& ctx);
534   bool Inst_MemSize(cAvidaContext& ctx);
535 
536   // Environment
537   bool Inst_RotateL(cAvidaContext& ctx);
538   bool Inst_RotateR(cAvidaContext& ctx);
539   bool Inst_SetCopyMut(cAvidaContext& ctx);
540   bool Inst_ModCopyMut(cAvidaContext& ctx);
541 
542   // Energy use
543   bool Inst_ZeroEnergyUsed(cAvidaContext& ctx);
544 
545   // Head-based instructions...
546   bool Inst_AdvanceHead(cAvidaContext& ctx);
547   bool Inst_MoveHead(cAvidaContext& ctx);
548   bool Inst_JumpHead(cAvidaContext& ctx);
549   bool Inst_GetHead(cAvidaContext& ctx);
550   bool Inst_IfLabel(cAvidaContext& ctx);
551   bool Inst_IfLabel2(cAvidaContext& ctx);
552   bool Inst_HeadDivide(cAvidaContext& ctx);
553   bool Inst_HeadRead(cAvidaContext& ctx);
554   bool Inst_HeadWrite(cAvidaContext& ctx);
555   bool Inst_HeadCopy(cAvidaContext& ctx);
556   bool Inst_HeadSearch(cAvidaContext& ctx);
557   bool Inst_SetFlow(cAvidaContext& ctx);
558 
559   bool Inst_HeadCopy2(cAvidaContext& ctx);
560   bool Inst_HeadCopy3(cAvidaContext& ctx);
561   bool Inst_HeadCopy4(cAvidaContext& ctx);
562   bool Inst_HeadCopy5(cAvidaContext& ctx);
563   bool Inst_HeadCopy6(cAvidaContext& ctx);
564   bool Inst_HeadCopy7(cAvidaContext& ctx);
565   bool Inst_HeadCopy8(cAvidaContext& ctx);
566   bool Inst_HeadCopy9(cAvidaContext& ctx);
567   bool Inst_HeadCopy10(cAvidaContext& ctx);
568 
569   //// Placebo ////
570   bool Inst_Skip(cAvidaContext& ctx);
571 
572   // -= Gene expression instructions =-
573   bool Inst_NewProgramid(cAvidaContext& ctx, bool executable, bool bindable, bool readable); //!< Allocate a new programid and place the write head there.
Inst_NewExecutableProgramid(cAvidaContext & ctx)574   bool Inst_NewExecutableProgramid(cAvidaContext& ctx) { return Inst_NewProgramid(ctx, true, false, false); } //!< Allocate a "protein". Cannot be bound or read.
Inst_NewGenomeProgramid(cAvidaContext & ctx)575   bool Inst_NewGenomeProgramid(cAvidaContext& ctx) { return Inst_NewProgramid(ctx, false, true, true); } //!< Allocate a "genomic" fragment. Cannot execute.
576 
577   bool Inst_Site(cAvidaContext& ctx); //!< A binding site (execution simply advances past label)
578   bool Inst_Bind(cAvidaContext& ctx); //!< Attempt to match the currently executing cProgramid against other cProgramids.
579   bool Inst_Bind2(cAvidaContext& ctx); //!< Attempt to locate two programids with the same site.
580   bool Inst_IfBind(cAvidaContext& ctx); //!< Attempt to match the currently executing cProgramid against other cProgramids. Execute next inst if successful.
581   bool Inst_IfBind2(cAvidaContext& ctx); //!< Attempt to match and bind two programids.
582   bool Inst_NumSites(cAvidaContext& ctx); //!< Count the number of corresponding binding sites
583   bool Inst_ProgramidCopy(cAvidaContext& ctx); //!< Like h-copy, but fails if read/write heads not on other programids and will not write over
584   bool Inst_ProgramidDivide(cAvidaContext& ctx); //!< Like h-divide,
585   bool Inst_ProgramidImplicitAllocate(cAvidaContext& ctx);
586   bool Inst_ProgramidImplicitDivide(cAvidaContext& ctx);
587   bool Inst_EndProgramidExecution(cAvidaContext& ctx);
588 
589   bool Inst_Promoter(cAvidaContext& ctx);
590   bool Inst_Terminator(cAvidaContext& ctx);
591   bool Inst_HeadActivate(cAvidaContext& ctx);
592   bool Inst_HeadRepress(cAvidaContext& ctx);
593 
594   //!< Add/Remove a new programid to/from the list and give it the proper index within the list so we keep track of memory spaces...
595   void AddProgramid(programid_ptr programid);
596   void RemoveProgramid(unsigned int remove_index);
597 
598   // Create executable programids in the implicit GX model
599   void ProcessImplicitGeneExpression(int in_limit = -1);
600   void AdjustPromoterRates(); //Call after a change to occupied array to correctly update rates.
601   int FindRegulatoryMatch(const cCodeLabel& label);
602 };
603 
604 #endif
605