-- Copyright 2019 Google LLC
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     https://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

local OUTPUT_BITS = {
    0x4d8, 0x4d6, 0x4d4, 0x4d2, 0x4d0, 0x4ce, 0x4cc, 0x4ca,
    0x4c8, 0x4c6, 0x4c4, 0x4c2, 0x4c0, 0x4be, 0x4bc, 0x4ba,
    0x4b8, 0x4b6, 0x4b4, 0x4b2, 0x4b0, 0x4ae, 0x4ac, 0x4aa,
    0x4a8, 0x4a6, 0x4a4, 0x4a2, 0x4a0, 0x49e, 0x49c, 0x49a,
    0x498, 0x496, 0x494, 0x492, 0x490, 0x48e, 0x48c, 0x48a,
    0x488, 0x486, 0x484, 0x482, 0x480, 0x47e, 0x47c, 0x47a,
    0x478, 0x476, 0x474, 0x472, 0x470, 0x46e, 0x46c, 0x46a,
    0x468, 0x466, 0x464, 0x462, 0x460, 0x45e, 0x45c, 0x45a,
    0x458, 0x456, 0x454, 0x452, 0x450, 0x44e, 0x44c, 0x44a,
    0x448, 0x446, 0x444, 0x442, 0x440, 0x43e, 0x43c, 0x43a,
    0x438, 0x436, 0x434, 0x432, 0x430, 0x42e, 0x42c, 0x42a,
    0x428, 0x426, 0x424, 0x422, 0x420, 0x41e, 0x41c, 0x41a,
    0x418, 0x416, 0x414, 0x412, 0x410, 0x40e, 0x40c, 0x40a,
    0x408, 0x406, 0x404, 0x402, 0x400, 0x3fe, 0x3fc, 0x3fa,
    0x3f8, 0x3f6, 0x3f4, 0x3f2, 0x3f0, 0x3ee, 0x3ec, 0x3ea,
    0x3e8, 0x3e6, 0x3e4, 0x3e2, 0x3e0, 0x3de, 0x3dc, 0x3da,
    0x3d8, 0x3d6, 0x3d4, 0x3d2, 0x3d0, 0x3ce, 0x3cc, 0x3ca,
    0x3c8, 0x3c6, 0x3c4, 0x3c2, 0x3c0, 0x3be, 0x3bc, 0x3ba,
    0x3b8, 0x3b6, 0x3b4, 0x3b2, 0x3b0, 0x3ae, 0x3ac, 0x3aa,
    0x3a8, 0x3a6, 0x3a4, 0x3a2, 0x3a0, 0x39e, 0x39c, 0x39a,
    0x398, 0x396, 0x394, 0x392, 0x390, 0x38e, 0x38c, 0x38a,
    0x388, 0x386, 0x384, 0x382, 0x380, 0x37e, 0x37c, 0x37a,
    0x378, 0x376, 0x374, 0x372, 0x370, 0x36e, 0x36c, 0x36a,
    0x368, 0x366, 0x364, 0x362, 0x360, 0x35e, 0x35c, 0x35a,
    0x358, 0x356, 0x354, 0x352, 0x350, 0x34e, 0x34c, 0x34a,
    0x348, 0x346, 0x344, 0x342, 0x340, 0x33e, 0x33c, 0x33a,
    0x338, 0x336, 0x334, 0x332, 0x330, 0x32e, 0x32c, 0x32a,
    0x328, 0x326, 0x324, 0x322, 0x320, 0x31e, 0x31c, 0x31a,
    0x318, 0x316, 0x314, 0x312, 0x310, 0x30e, 0x30c, 0x30a,
    0x308, 0x306, 0x304, 0x302, 0x300, 0x2fe, 0x2fc, 0x2fa,
    0x2f8, 0x2f6, 0x2f4, 0x2f2, 0x2f0, 0x2ee, 0x2ec, 0x2ea,
    0x2e8, 0x2e6, 0x2e4, 0x2e2, 0x2e0, 0x2de, 0x2dc, 0x2da,
}

local INPUT_BITS = {
    0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
    0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
    0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
    0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0,
    0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8,
    0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0,
    0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8,
    0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0,
    0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
    0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0,
    0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8,
    0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
    0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98,
    0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
    0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88,
    0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
    0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78,
    0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
    0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68,
    0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60,
    0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58,
    0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
    0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48,
    0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
    0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38,
    0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
    0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28,
    0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
    0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
    0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
    0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8,
    0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0,
}

local DONE_BIT = 0x4da

local EXPECTED_OUTPUT = {
    0x5c, 0xba, 0x23, 0xde, 0x38, 0x7a, 0x00, 0x67,
    0x7d, 0x8f, 0x7c, 0x6e, 0xf2, 0x11, 0x10, 0xe8,
    0x29, 0x0a, 0x1e, 0xb6, 0xad, 0x34, 0x36, 0x74,
    0x45, 0xfe, 0x3b, 0x6d, 0xf5, 0xa0, 0x8f, 0x9d,
}

local INPUT = "CTF{---------------------------}"

function is_done (sim)
    return sim:read_output_bit(DONE_BIT)
end

function execute (sim)
    sim:write_input_bytes(INPUT_BITS, {INPUT:byte(1, -1)})
    while sim:iteration_count() < 512 and not is_done(sim) do
        sim:run()
    end
    if not is_done(sim) then
        print("BUG: convergence failure!")
        return
    end
    local result = sim:read_output_bytes(OUTPUT_BITS)
    for i = 1, #EXPECTED_OUTPUT do
        if result[i] ~= EXPECTED_OUTPUT[i] then
            print("failed")
            return
        end
    end
    print("success!")
end
