diff --git a/source/sgp_mode/hardware/GenomeLibrary.h b/source/sgp_mode/hardware/GenomeLibrary.h index f756b433..b262760a 100644 --- a/source/sgp_mode/hardware/GenomeLibrary.h +++ b/source/sgp_mode/hardware/GenomeLibrary.h @@ -52,7 +52,7 @@ namespace lib_info { {"Reproduce", 0}, {"PrivateIO", 1}, {"SharedIO", 1}, {"Donate", 0}, {"Reuptake", 1}, {"Steal", 0}, {"Infect", 0}, {"DynamicInst", 3}, {"SenseTask", 2}, - {"IO", 1}, {"JumpIfNEq", 2}, {"JumpIfEq", 2}, {"JumpIfLess", 2} + {"IO", 1} }; } diff --git a/source/sgp_mode/hardware/Instructions.h b/source/sgp_mode/hardware/Instructions.h index fa074860..07b8a7a1 100644 --- a/source/sgp_mode/hardware/Instructions.h +++ b/source/sgp_mode/hardware/Instructions.h @@ -130,7 +130,6 @@ INST(Reproduce, { state.MarkReproAttempt(); }); -// NOTE - what is the intended difference between SharedIO and PrivateIO? INST(IO, { // (1) Add output to output buffer state.GetOutputBuffer().emplace_back(a); diff --git a/source/sgp_mode/hardware/SGPHardware.h b/source/sgp_mode/hardware/SGPHardware.h index d4908e04..95381a84 100644 --- a/source/sgp_mode/hardware/SGPHardware.h +++ b/source/sgp_mode/hardware/SGPHardware.h @@ -303,16 +303,18 @@ void SGPHardware::PrintOp( } else { tag_name = ""; } - - if (name == "JumpIfNEq" || name == "JumpIfLess") { + + if (name == "JumpIfNEq" || name == "JumpIfLess" || name == "JumpIfEq") { + out << " " << emp::to_lower(name); for (size_t i = 0; i < 12 - name.length(); i++) { out << ' '; } out << 'r' << (int)ins.args[0] << ", r" << (int)ins.args[1] << ", " << tag_name; + } else if (name == "Global Anchor") { - out << tag_name << " " << ins.tag << ':'; + out << tag_name << ':'; } else { out << ""; } diff --git a/source/test/sgp_mode_test/unit_tests/SGPHardware.test.cc b/source/test/sgp_mode_test/unit_tests/SGPHardware.test.cc new file mode 100644 index 00000000..869abbad --- /dev/null +++ b/source/test/sgp_mode_test/unit_tests/SGPHardware.test.cc @@ -0,0 +1,199 @@ +#include "emp/math/Random.hpp" + +#include "../../../sgp_mode/hardware/SGPHardware.h" +#include "../../../sgp_mode/SGPWorld.h" +#include "../../../sgp_mode/SGPWorld.cc" +#include "../../../sgp_mode/SGPWorldSetup.cc" +#include "../../../sgp_mode/SGPWorldData.cc" +#include "../../../sgp_mode/ProgramBuilder.h" + +#include "../../../catch/catch.hpp" + +#include +#include + +TEST_CASE("Test Printing Simple Instructions", "[sgp]"){ + using world_t = sgpmode::SGPWorld; + using cpu_state_t = sgpmode::CPUState; + using hw_spec_t = sgpmode::SGPHardwareSpec; + using hardware_t = sgpmode::SGPHardware; + using program_t = typename world_t::sgp_prog_t; + using sgp_host_t = sgpmode::SGPHost; + using tag_t = typename hw_spec_t::tag_t; + + sgpmode::SymConfigSGP config; + config.CYCLES_PER_UPDATE(0); + config.HOST_REPRO_RES(1); + config.SEED(61); + config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json"); + config.FILE_PATH("hardware_test_output"); + config.POP_SIZE(1); + config.START_MOI(0); + config.TASK_IO_UNIQUE_OUTPUT(true); + + emp::Random random(config.SEED()); + world_t world(random, &config); + world.Setup(); + auto& prog_builder = world.GetProgramBuilder(); + + auto& org = world.GetOrg(0); + auto& sgp_host = static_cast(org); + hardware_t& hw = sgp_host.GetHardware(); + + std::ostringstream output; + + WHEN("Program contains Nop Instruction"){ + program_t program; + prog_builder.AddStartAnchor(program); + prog_builder.AddInst(program, "Nop-0", 0); + hw.Reset(); + hw.SetProgram(program); + + hw.PrintCode(output); + + THEN("Global Anchor and Nop Instruction should be printed"){ + REQUIRE(output.str() == "AA:\n nop-0 \n"); + } + } + WHEN("Program contains Increment Instruction"){ + program_t program; + prog_builder.AddStartAnchor(program); + prog_builder.AddInst(program, "Increment", 0); + hw.Reset(); + hw.SetProgram(program); + + hw.PrintCode(output); + + THEN("Global Anchor and Increment Instruction should be printed"){ + REQUIRE(output.str() == "AA:\n increment r0\n"); + } + } + WHEN("Program contains Decrement Instruction"){ + program_t program; + prog_builder.AddStartAnchor(program); + prog_builder.AddInst(program, "Decrement", 0); + hw.Reset(); + hw.SetProgram(program); + + hw.PrintCode(output); + + THEN("Global Anchor and Increment Instruction should be printed"){ + REQUIRE(output.str() == "AA:\n decrement r0\n"); + } + } + + WHEN("Program contains Nand Instruction"){ + program_t program; + prog_builder.AddStartAnchor(program); + prog_builder.AddInst(program, "Nand", 0, 1, 0); + hw.Reset(); + hw.SetProgram(program); + + hw.PrintCode(output); + + THEN("Global Anchor and Nand Instruction should be printed"){ + REQUIRE(output.str() == "AA:\n nand r0, r1, r0\n"); + } + } +} + +TEST_CASE("Test Printing Complex Instructions", "[sgp]"){ + using world_t = sgpmode::SGPWorld; + using cpu_state_t = sgpmode::CPUState; + using hw_spec_t = sgpmode::SGPHardwareSpec; + using hardware_t = sgpmode::SGPHardware; + using program_t = typename world_t::sgp_prog_t; + using sgp_host_t = sgpmode::SGPHost; + using tag_t = typename hw_spec_t::tag_t; + + sgpmode::SymConfigSGP config; + config.CYCLES_PER_UPDATE(0); + config.HOST_REPRO_RES(1); + config.SEED(61); + config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json"); + config.FILE_PATH("hardware_test_output"); + config.POP_SIZE(1); + config.START_MOI(0); + config.TASK_IO_UNIQUE_OUTPUT(true); + + emp::Random random(config.SEED()); + world_t world(random, &config); + world.Setup(); + auto& prog_builder = world.GetProgramBuilder(); + + auto& org = world.GetOrg(0); + auto& sgp_host = static_cast(org); + hardware_t& hw = sgp_host.GetHardware(); + + std::ostringstream output; + + WHEN("Program contains JumpIfNEq Instruction"){ + program_t program; + tag_t start_tag(prog_builder.GetStartTag()); + tag_t tag1("0000000000000000000000000000000000000000000000000000000000000001"); + + prog_builder.AddStartAnchor(program); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Global Anchor", tag1); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "JumpIfNEq", 0, 1, 0, tag1); + hw.Reset(); + hw.SetProgram(program); + + hw.PrintCode(output); + + THEN("Global Anchor and Nop Instruction should be printed"){ + REQUIRE(output.str() == "AA:\n nop-0 \n nop-0 \n nop-0 \nAB:\n nop-0 \n nop-0 \n jumpifneq r0, r1, AB\n"); + } + } + + WHEN("Program contains JumpIfEq Instruction"){ + program_t program; + tag_t start_tag(prog_builder.GetStartTag()); + tag_t tag1("0000000000000000000000000000000000000000000000000000000000000001"); + + prog_builder.AddStartAnchor(program); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Global Anchor", tag1); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "JumpIfEq", 0, 1, 0, tag1); + hw.Reset(); + hw.SetProgram(program); + + hw.PrintCode(output); + + THEN("Global Anchor and Nop Instruction should be printed"){ + REQUIRE(output.str() == "AA:\n nop-0 \n nop-0 \n nop-0 \nAB:\n nop-0 \n nop-0 \n jumpifeq r0, r1, AB\n"); + } + } + + WHEN("Program contains JumpIfLess Instruction"){ + program_t program; + tag_t start_tag(prog_builder.GetStartTag()); + tag_t tag1("0000000000000000000000000000000000000000000000000000000000000010"); + + prog_builder.AddStartAnchor(program); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Global Anchor", tag1); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "Nop-0", 0); + prog_builder.AddInst(program, "JumpIfLess", 0, 1, 0, tag1); + hw.Reset(); + hw.SetProgram(program); + + hw.PrintCode(output); + + THEN("Global Anchor and Nop Instruction should be printed"){ + REQUIRE(output.str() == "AA:\n nop-0 \n nop-0 \n nop-0 \nAB:\n nop-0 \n nop-0 \n jumpifless r0, r1, AB\n"); + } + } + +} \ No newline at end of file