-
Notifications
You must be signed in to change notification settings - Fork 113
Instruction Set
An instruction set is actually a whole set of configurations, usually contained in their own file and included in the avida.cfg file with #include INST_SET=instset.cfg
.
Instruction sets are actually part of the avida.cfg file. However, instead of writing the instruction set out in avida.cfg itself, which would be rather long and messy, each instruction set is placed in a separate file. A preprocessor include (of the form #include $filename
) is then used to include each instruction set in avida.cfg. Multiple instruction sets may be included.
For example, to include the two instruction sets contained in the files instset-heads.cfg and instset-heads-sex.cfg, these lines are placed in avida.cfg:
#include instset-heads.cfg
#include instset-heads-sex.cfg
You may optionally name each instruction set as you include it. This allows you to change which file the name refers to when running avida from the command line, using the -def option. The default avida.cfg contains this line:
#include INST_SET=instset-heads.cfg
This means you may change which file INST_SET refers (for example, change it to instset-heads-sex.cfg) to on the command line like this:
./avida -def INST_SET instset-heads-sex.cfg
In this case, INST_SET is simply a variable name with no special meaning. The line might just as easily been #include BOBS_YOUR_UNCLE=instset-heads.cfg
Organisms in an avida run may have different instruction sets. Therefore, it is necessary to specify the instruction used by each .org file. At the top of the .org file you must specify the instruction set with the #inst_set
keyword, and the hardware type with the hw_type
keyword. For example, default-heads.org starts with these two lines:
#inst_set heads_default
#hw_type 0
Note: the name of the instruction set may not be the same as the name of the file containing the instruction set. (Indeed, one file may contain multiple instruction sets.) The name of the instruction set is defined inside its .cfg file by the INSTSET keyword, which also defines the hardware type.
An instruction set consists of a name and hardware type, followed by a list of instructions that belong to that instruction set, each of which may be followed by a series of options that define how that instruction should be used. The exact format is as follows:
INSTSET instset-name:hw_type=$hardware_type
INST inst-name[:options]
...
Multiple instruction sets with unique names may be defined in the same file. All INST
statements must follow the
INSTSET
statement defining the instruction set.
The following options may be specified (as name=value
, separated by colons):
- redundancy (default = 1)
- The frequency of the instruction in the set. One instruction with twice the redundancy of another with also have twice the probability of being mutated to. A redundancy of zero is allowed, and indicates that injected organisms are allowed to have this instruction, but it can never be mutated to.
- cost
- The number of CPU cycles required to execute this instruction. One is the default if this value is not specified. CPU costs will pause the thread that executed the costly instruction, not the whole organism and only decrement the pause counter each time the paused thread attempts to run. If multiple threads execute costly instructions, the costs and pause counts are handled independently (i.e. unique pause count for each thread).
- initial_cost
- The additional cost to be paid the first time this instruction is executed. This is used to lower the diversity of instructions inside an organism. The default value here is 0.
- energy_cost
- The number of Energy units required to execute this instruction. Zero is the default if this value is not specified.
- addl_time_cost
- The additional cost in terms of phenotype 'age', but not actual instruction cycles. The default value here is 0.
- prob_fail
- The probability of this instruction not working properly. If an instruction fails it will simply do nothing, but still cost the CPU cycles to execute. The defailt probability of failure is zero.
- inst_code
- String of 1's and 0's defining the numeric value of a instruction as used by certain operations that 'numberate' instruction sequences.
- res_cost
- The cost in units (double) of COLLECT_SPECIFIC_RESOURCE stored in internal bins to execute the instruction. Organisms that execute an instruction with a res_cost higher than what is internally available will die. Res_cost is not applied if an instruction fails. In a multi-resource environment, any and all resources can be converted internally via reactions to a common COLLECT_SPECIFIC_RESOURCE for use with res_cost (COLLECT_SPECIFIC_RESOURCE must still be declared in environment file, likely with initial=0). Note that the use of res_cost typically needs to be coupled with RESOURCE_GIVEN_ON_INJECT and RESOURCE_GIVEN_AT_BIRTH in avida.cfg. The default res_cost is 0.
- post_cost
- CPU cost to be paid AFTER the instruction is executed the first time (e.g. pseudo post-kill handling time in predators). Post costs are only applied if the instruction executes successfully (differs from regular costs).
- bonus_cost
- The cost in units (double) of current bonus to successfully execute the instruction. bonus_cost is not applied if an instruction fails for some other reason. Ultimately this is similar to res_costs when converting a common, specific resource, but much simpiler.
For example, to specify that the nand instruction is both twice as common and twice as expensive as other instructions, you would use this line:
INST nand:redundancy=2:cost=2
Below are the descriptions of the instructions turned on in the file instset-classic.cfg. The one-letter codes are assigned automatically to each instruction in the set, so if additional instructions are turned on, the letters given below may no longer correspond to the instructions they are presented with. If more than 26 instructions are in a set, both lowercase and capital letters will be used, and then numbers. Currently, no more than 62 distinct instructions will be represented by unique symbols.
Most terminology below that may not be familiar to you has been given a link to a file containing its definition.
The instructions nop-A
(a), nop-B
(b), and nop-C
(c) are no-operation
instructions, and will not do
anything when executed. They will, however, modifiy the behavior of the
instruction preceeding it (by changing the [CPU](Glossary-- CPU)
component that it affects; see also
nop-register notation and
nop-head notation) or act as part
of a label to denote positions in the
genome.
This instruction compares the ?BX? register to its complement. If they are not equal, the next instruction (after a modifying no-operation instruction, if one is present) is executed. If they are equal, that next instruction is skipped.
This instruction compares the ?BX? register to its complement. If ?BX? is the lesser of the pair, the next instruction (after a modifying no-operation instruction, if one is present) is executed. If it is greater or equal, then that next instruction is skipped.
This instruction removes the top element from the active stack, and places it into the ?BX? register.
This instruction reads in the contents of the ?BX? register, and places it as a new entry at the top of the active stack. The ?BX? register itself remains unchanged.
This instruction toggles the active stack in the CPU. All other instructions that use a stack will always use the active one.
This instruction swaps the contents of the ?BX? register with its complement.
This instruction reads in the contents of the ?BX? register, and shifts all of the bits in that register to the right by one. In effect, it divides the value stored in the register by two, rounding down.
This instruction reads in the contents of the ?BX? register, and shifts all of the bits in that register to the left by one, placing a zero as the new rightmost bit, and trunkating any bits beyond the 32 maximum. For values that require fewer than 32 bits, it effectively multiplies that value by two.
These instructions read in the contents of the ?BX? register and increment or decrement it by one.
These instructions read in the contents of the BX and CX registers and either sums them together or subtracts CX from BX (respectively). The result of this operation is then placed in the ?BX? register.
This instruction reads in the contents of the BX and CX registers (each of which are 32-bit numbers) and performs a bitwise nand operation on them. The result of this operation is placed in the ?BX? register. Note that this is the only logic operation provided in the basic Avida instruction set.
This is the input/output instruction. It takes the contents of the ?BX? register and outputs it, checking it for any tasks that may have been performed. It will then place a new input into ?BX?.
This instruction allocates additional memory for the organism up to the maximum it is allowed to use for its offspring. If allocation is successful, the original memory size is loaded into the AX register.
This instruction is used for an organism to divide off an finnished offspring. The original organism keeps the state of its memory up until the read-head. The offspring's memory is initialized to everything between the read-head and the write-head. All memory past the write-head is removed entirely.
This instruction reads the contents of the organism's memory at the position of the read-head, and copy that to the position of the write-head. If a non-zero copy mutation rate is set, a test will be made based on this probability to determine if a mutation occurs. If so, a random instruction (chosen from the full set with equal probability) will be placed at the write-head instead.
This instruction will read in the label the follows it, and find the location of a complement label in the code. The BX register will be set to the distance to the complement from the current position of the instruction-pointer, and the CX register will be set to the size of the label. The flow-head will also be placed at the beginning of the complement label. If no label follows, both BX and CX will be set to zero, and the flow-head will be placed on the instruction immediatly following the h-search.
This instruction will cause the ?IP? to jump to the position in memory of the flow-head.
This instruction will read in the value of the CX register, and the move the ?IP? by that fixed amount through the organism's memory.
This instruction will copy the position of the ?IP? into the CX register.
This instruction reads in the label that follows it, and tests if its complement label was the most recent series of instructions copied. If so, it executed the next instruction, otherwise it skips it. This instruction is commonly used for an organism to determine when it has finished producing its offspring.
This instruction moves the flow-head to the memory position denoted in the ?CX? register.