def test_decode():
    offsets = [randrange(0, 2**OFFSET_BITS) for _ in range(3)]
    flags = randrange(0, 2**N_FLAGS)
    instruction = 0
    for part in [flags] + offsets[::-1]:
        instruction = (instruction << OFFSET_BITS) | part
    assert [flags] + offsets == list(decode_instruction_values(instruction))
示例#2
0
文件: vm.py 项目: LexiccLabs/BeamNet
def get_perm_range_check_limits(trace: List[TraceEntry[int]],
                                memory: MemoryDict) -> Tuple[int, int]:
    """
    Returns the minimum value and maximum value in the perm_range_check component.
    """
    offsets: List[int] = []
    for entry in trace:
        encoded_instruction = memory[entry.pc]
        _, off0, off1, off2 = decode_instruction_values(encoded_instruction)
        offsets += [off0, off1, off2]
    return min(offsets), max(offsets)
示例#3
0
def decode_instruction(encoding: int,
                       imm: Optional[int] = None) -> Instruction:
    """
    Given 1 or 2 integers representing an instruction, returns the Instruction.
    If imm is given for an instruction with no immediate, it will be ignored.
    """
    flags, off0_enc, off1_enc, off2_enc = decode_instruction_values(encoding)

    # Get dst_register.
    dst_register = Register.FP if (flags >> DST_REG_BIT) & 1 else Register.AP

    # Get op0_register.
    op0_register = Register.FP if (flags >> OP0_REG_BIT) & 1 else Register.AP

    # Get op1.
    op1_addr = {
        (1, 0, 0): Instruction.Op1Addr.IMM,
        (0, 1, 0): Instruction.Op1Addr.AP,
        (0, 0, 1): Instruction.Op1Addr.FP,
        (0, 0, 0): Instruction.Op1Addr.OP0
    }[(flags >> OP1_IMM_BIT) & 1, (flags >> OP1_AP_BIT) & 1,
      (flags >> OP1_FP_BIT) & 1]

    if op1_addr is Instruction.Op1Addr.IMM:
        assert imm is not None, 'op1_addr is Op1Addr.IMM, but no immediate given'
    else:
        imm = None

    # Get pc_update.
    pc_update = {
        (1, 0, 0): Instruction.PcUpdate.JUMP,
        (0, 1, 0): Instruction.PcUpdate.JUMP_REL,
        (0, 0, 1): Instruction.PcUpdate.JNZ,
        (0, 0, 0): Instruction.PcUpdate.REGULAR
    }[(flags >> PC_JUMP_ABS_BIT) & 1, (flags >> PC_JUMP_REL_BIT) & 1,
      (flags >> PC_JNZ_BIT) & 1]

    # Get res.
    res = {
        (1, 0):
        Instruction.Res.ADD,
        (0, 1):
        Instruction.Res.MUL,
        (0, 0):
        Instruction.Res.UNCONSTRAINED
        if pc_update is Instruction.PcUpdate.JNZ else Instruction.Res.OP1,
    }[(flags >> RES_ADD_BIT) & 1, (flags >> RES_MUL_BIT) & 1]

    # JNZ opcode means res must be UNCONSTRAINED.
    if pc_update is Instruction.PcUpdate.JNZ:
        assert res is Instruction.Res.UNCONSTRAINED

    # Get ap_update.
    ap_update = {
        (1, 0): Instruction.ApUpdate.ADD,
        (0, 1): Instruction.ApUpdate.ADD1,
        (0, 0): Instruction.ApUpdate.
        REGULAR,  # OR ADD2, depending if we have CALL opcode.
    }[(flags >> AP_ADD_BIT) & 1, (flags >> AP_ADD1_BIT) & 1]

    # Get opcode.
    opcode = {
        (1, 0, 0): Instruction.Opcode.CALL,
        (0, 1, 0): Instruction.Opcode.RET,
        (0, 0, 1): Instruction.Opcode.ASSERT_EQ,
        (0, 0, 0): Instruction.Opcode.NOP
    }[(flags >> OPCODE_CALL_BIT) & 1, (flags >> OPCODE_RET_BIT) & 1,
      (flags >> OPCODE_ASSERT_EQ_BIT) & 1]

    # CALL opcode means ap_update must be ADD2.
    if opcode is Instruction.Opcode.CALL:
        assert ap_update is Instruction.ApUpdate.REGULAR, 'CALL must have update_ap is ADD2'
        ap_update = Instruction.ApUpdate.ADD2

    # Get fp_update.
    if opcode is Instruction.Opcode.CALL:
        fp_update = Instruction.FpUpdate.AP_PLUS2
    elif opcode is Instruction.Opcode.RET:
        fp_update = Instruction.FpUpdate.DST
    else:
        fp_update = Instruction.FpUpdate.REGULAR

    return Instruction(
        off0=off0_enc - 2**(OFFSET_BITS - 1),
        off1=off1_enc - 2**(OFFSET_BITS - 1),
        off2=off2_enc - 2**(OFFSET_BITS - 1),
        imm=imm,
        dst_register=dst_register,
        op0_register=op0_register,
        op1_addr=op1_addr,
        res=res,
        pc_update=pc_update,
        ap_update=ap_update,
        fp_update=fp_update,
        opcode=opcode,
    )
def test_unsupported_instruction():
    with pytest.raises(AssertionError, match='Unsupported instruction.'):
        decode_instruction_values(1 << (3 * OFFSET_BITS + N_FLAGS))