diff --git a/computed_operands_res b/computed_operands_res new file mode 100644 index 0000000..e69de29 diff --git a/src/instruction.h b/src/instruction.h index 8376d97..0a72565 100644 --- a/src/instruction.h +++ b/src/instruction.h @@ -88,6 +88,8 @@ enum VirtualMachineError { InvalidRes, InvalidOpcode, InvalidApUpdate, + MemoryError, + None }; union ResultInstructionValue { diff --git a/src/main.c b/src/main.c index de2a586..a2d8be0 100644 --- a/src/main.c +++ b/src/main.c @@ -4,7 +4,6 @@ #include int main(__attribute__((unused)) int argc, __attribute__((unused)) char **argv) { - printf("Hello World!\n"); - + printf("hello word"); return 0; } diff --git a/src/memory.c b/src/memory.c index 31a7fa7..a4a4fd9 100644 --- a/src/memory.c +++ b/src/memory.c @@ -13,50 +13,51 @@ ResultMemory memory_get(memory *mem, relocatable ptr) { int index = ptr.segment_index; int offset = ptr.offset; if (index >= mem->data->count(mem->data)) { - ResultMemory error = {.is_error = true, .value = {.error = Get}}; + ResultMemory error = {.type = Err, .value = {.error = Get}}; return error; } CList *segment = mem->data->at(mem->data, ptr.segment_index); if (offset >= segment->count(segment)) { - ResultMemory error = {.is_error = true, .value = {.error = Get}}; + ResultMemory error = {.type = Err, .value = {.error = Get}}; return error; } memory_cell *cell = segment->at(segment, ptr.offset); if (cell->is_some) { - ResultMemory ok = {.is_error = false, .value = {.memory_value = cell->memory_value.value}}; + ResultMemory ok = {.type = MaybeRelocatable, .value = {.memory_value = cell->memory_value.value}}; return ok; } - ResultMemory error = {.is_error = true, .value = {.error = Get}}; + ResultMemory error = {.type = Err, .value = {.error = Get}}; return error; } ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value) { int index = ptr.segment_index; - int offset = ptr.offset; + int offset = ptr.segment_index; if (index >= mem->data->count(mem->data)) { - ResultMemory error = {.is_error = true, .value = {.error = Insert}}; + ResultMemory error = {.type = Err, .value = {.error = Insert}}; return error; } CList *segment = mem->data->at(mem->data, ptr.segment_index); // Handle gaps - while (segment->count(segment) < offset) { + // TODO: possible bug. check if lesser and equal or just lesser + while (segment->count(segment) <= offset) { memory_cell none = {.is_some = false, .memory_value = {.none = 0}}; segment->add(segment, &none); } ResultMemory get_result = memory_get(mem, ptr); // Check for possible ovewrites - if (!get_result.is_error) { + if (get_result.type != Err) { if (maybe_relocatable_equal(get_result.value.memory_value, value)) { - ResultMemory ok = {.is_error = false, .value = {.none = 0}}; + ResultMemory ok = {.type = Int, .value = {.none = 0}}; return ok; } else { - ResultMemory error = {.is_error = true, .value = {.error = Insert}}; + ResultMemory error = {.type = Err, .value = {.error = Insert}}; return error; } } - memory_cell new_cell = {.is_some = true, .memory_value = {.value = value}}; + memory_cell new_cell = {.is_some = Err, .memory_value = {.value = value}}; segment->insert(segment, &new_cell, ptr.offset); - ResultMemory ok = {.is_error = false, .value = {.none = 0}}; + ResultMemory ok = {.type = Int, .value = {.none = 0}}; return ok; } @@ -72,7 +73,7 @@ relocatable memory_add_segment(memory *memory) { ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data) { if (ptr.segment_index >= memory->num_segments) { - ResultMemory error = {.is_error = true, .value = {.error = LoadData}}; + ResultMemory error = {.type = Err, .value = {.error = LoadData}}; return error; } int size = data->count(data); @@ -83,7 +84,7 @@ ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data) { segment->insert(segment, &new_cell, ptr.offset + i); } ptr.offset += size; - ResultMemory ok = {.is_error = false, .value = {.ptr = ptr}}; + ResultMemory ok = {.type = Relocatable, .value = {.ptr = ptr}}; return ok; } diff --git a/src/memory.h b/src/memory.h index 2ef1ce0..a0b564c 100644 --- a/src/memory.h +++ b/src/memory.h @@ -32,6 +32,8 @@ enum MemoryError { LoadData, }; +enum ResultMemoryType { Felt, Relocatable, MaybeRelocatable, Int, Err }; + union ResultMemoryValue { enum MemoryError error; maybe_relocatable memory_value; @@ -40,7 +42,7 @@ union ResultMemoryValue { }; typedef struct ResultMemory { - bool is_error; + enum ResultMemoryType type; union ResultMemoryValue value; } ResultMemory; diff --git a/src/relocatable.c b/src/relocatable.c index 1a84945..51c5e44 100644 --- a/src/relocatable.c +++ b/src/relocatable.c @@ -1,17 +1,53 @@ #include "relocatable.h" #include "utils.h" +// -------------------------------- +// Sign operations for relocatable +// -------------------------------- + +// TODO: fix this to thrown an error if off < other +relocatable sub_relocatable(relocatable a, uint64_t other) { + unsigned int offset = a.offset; + unsigned int new_offset = offset - other; + relocatable result = {.segment_index = a.segment_index, .offset = new_offset}; + + return result; +} + +uint64_t checked_add(uint64_t a, uint64_t b) { + uint64_t res = a + b; + if (res <= a || res <= b) + return 0; + else + return res; +} + +// TODO: fix this to thrown an error. if add overflows +relocatable add_relocatable(relocatable a, uint64_t other) { + unsigned int off = a.offset; + uint64_t check_sum = checked_add(off, other); + relocatable res = {.segment_index = a.segment_index, .offset = check_sum}; + return res; +} + +// ----------------------------------- +// operations for maybe_relocatable +// ----------------------------------- + bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { if (a.is_felt && b.is_felt) { return felt_equal(a.value.felt, b.value.felt); - } else if (!a.is_felt && !b.is_felt) { - return a.value.relocatable.segment_index == b.value.relocatable.segment_index && - a.value.relocatable.offset == b.value.relocatable.offset; - } else { + } else if (!a.is_felt || !b.is_felt) return false; + else { + return relocatable_equal(a.value.relocatable, b.value.relocatable); } } +bool relocatable_equal(relocatable a, relocatable b) { + return (a.segment_index == b.segment_index && a.offset == b.offset); +} + maybe_relocatable maybe_relocatable_from_felt_limbs(limb_t *felt) { maybe_relocatable elem = {.is_felt = true, .value = {.felt = {felt[0], felt[1], felt[2], felt[3]}}}; return elem; diff --git a/src/relocatable.h b/src/relocatable.h index 88562e7..e9f9290 100644 --- a/src/relocatable.h +++ b/src/relocatable.h @@ -1,7 +1,9 @@ #ifndef RELOCATABLE_H #define RELOCATABLE_H + #include "../lambdaworks/lib/lambdaworks.h" #include +#include typedef struct relocatable { unsigned int segment_index; @@ -19,7 +21,9 @@ typedef struct maybe_relocatable { } maybe_relocatable; bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b); - +relocatable sub_relocatable(relocatable a, uint64_t other); +relocatable add_relocatable(relocatable a, uint64_t other); maybe_relocatable maybe_relocatable_from_felt_limbs(limb_t *felt); +bool relocatable_equal(relocatable a, relocatable b); #endif diff --git a/src/run_context.c b/src/run_context.c new file mode 100644 index 0000000..d8db9d5 --- /dev/null +++ b/src/run_context.c @@ -0,0 +1,75 @@ +#include "run_context.h" +#include "instruction.h" + +relocatable compute_dst_addr(run_context run_ctx, Instruction instr) { + struct relocatable base_addr; + switch (instr.dst_register) { + case REG_AP: { + base_addr = run_ctx.ap; + } break; + default: { + base_addr = run_ctx.fp; + } break; + } + + relocatable res_base_addr; + if (instr.off0 < 0) { + res_base_addr = sub_relocatable(base_addr, (uint64_t)absolute(instr.off0)); + } else { + res_base_addr = add_relocatable(base_addr, (uint64_t)instr.off0); + } + + return res_base_addr; +} + +relocatable compute_op0_addr(run_context run_ctx, Instruction instr) { + struct relocatable base_addr; + switch (instr.op0_register) { + case REG_AP: { + base_addr = run_ctx.ap; + } break; + default: { + base_addr = run_ctx.fp; + } break; + } + + relocatable res_base_addr; + if (instr.off1 < 0) { + res_base_addr = sub_relocatable(base_addr, (uint64_t)absolute(instr.off1)); + } else { + res_base_addr = add_relocatable(base_addr, (uint64_t)instr.off1); + } + return res_base_addr; +} + +relocatable compute_op1_addr(run_context run_ctx, Instruction instr, maybe_relocatable op0) { + relocatable base_addr; + switch (instr.op1_addr) { + case OP_FP: + base_addr = run_ctx.fp; + break; + case OP_AP: + base_addr = run_ctx.ap; + break; + case Imm: + if (instr.off2 == 1) + base_addr = run_ctx.pc; + break; + case Op0: { + if (!op0.is_felt) { + base_addr = op0.value.relocatable; + } + } break; + default: { + base_addr = (relocatable){.segment_index = 0, .offset = 0}; + } break; + } + + relocatable res_base_addr; + if (instr.off2 < 0) { + res_base_addr = sub_relocatable(base_addr, (uint64_t)absolute(instr.off2)); + } else { + res_base_addr = add_relocatable(base_addr, (uint64_t)instr.off2); + } + return res_base_addr; +} diff --git a/src/run_context.h b/src/run_context.h index c6fd35a..9fcde5d 100644 --- a/src/run_context.h +++ b/src/run_context.h @@ -1,7 +1,9 @@ #ifndef RUN_CONTEXT_H #define RUN_CONTEXT_H +#include "instruction.h" #include "relocatable.h" +#include "utils.h" typedef struct run_context { relocatable pc; @@ -9,4 +11,8 @@ typedef struct run_context { relocatable fp; } run_context; +relocatable compute_dst_addr(run_context run_ctx, Instruction instr); +relocatable compute_op0_addr(run_context run_ctx, Instruction instr); +relocatable compute_op1_addr(run_context run_ctx, Instruction instr, maybe_relocatable op0); + #endif diff --git a/src/utils.c b/src/utils.c index bb737ff..23d8fd8 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,68 @@ #include "utils.h" +#include "relocatable.h" +#include + +typedef struct felt_to_u64_result { + bool is_ok; + uint64_t val; +} felt_to_u64_result; + +// TODO: check this function +felt_to_u64_result to_u64(felt_t f) { + if (f[0] == 0 && f[1] == 0 && f[2] == 0) { + felt_to_u64_result res = {.is_ok = true, .val = f[3]}; + return res; + } else { + felt_to_u64_result res = {.is_ok = false, .val = 0}; + return res; + }; +} + +maybe_relocatable add_maybe_relocatable(maybe_relocatable a, maybe_relocatable b) { + if (a.is_felt && b.is_felt) { + + felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; + felt_t f2 = {b.value.felt[0], b.value.felt[1], b.value.felt[2], b.value.felt[3]}; + felt_t result; + add(f1, f2, result); + maybe_relocatable res = {.is_felt = true, + .value = {.felt = {result[0], result[1], result[2], result[3]}}}; + return res; + } else if (a.is_felt && !b.is_felt) { + + felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; + relocatable rel = b.value.relocatable; + uint64_t offset = (uint64_t)rel.offset; + felt_to_u64_result other = to_u64(f1); + uint64_t new_offset = offset + other.val; + maybe_relocatable res = { + .is_felt = false, + .value = {.relocatable = {.offset = new_offset, .segment_index = rel.segment_index}}}; + return res; + } else if (!a.is_felt && b.is_felt) { + + felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; + relocatable rel = b.value.relocatable; + uint64_t offset = (uint64_t)rel.offset; + felt_to_u64_result other = to_u64(f1); + uint64_t new_offset = offset + other.val; + maybe_relocatable res = { + .is_felt = false, + .value = {.relocatable = {.offset = new_offset, .segment_index = rel.segment_index}}}; + return res; + } + + felt_t res; + zero(res); + return (maybe_relocatable){.is_felt = true, .value = {.felt = {res[0], res[1], res[2], res[3]}}}; +} + +int64_t absolute(int64_t a) { + if (a < 0) + return (-1) * a; + else + return a; +} bool felt_equal(felt_t a, felt_t b) { return (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]); } @@ -23,58 +87,83 @@ uint8_t *u64_to_be_bytes(uint64_t value, uint8_t *buffer_bytes) { uint64_t u64_from_le_bytes(uint8_t *bytes) { uint64_t value = 0; for (int i = 7; i >= 0; i--) { - value |= bytes[i]; - value = value << (8 * i); + value |= bytes[i] << (8 * i); } return value; } -// TODO: needs fix uint64_t u64_from_be_bytes(uint8_t *bytes) { uint64_t value = 0; for (int i = 0; i < 8; i++) { - value |= bytes[i]; - value = value << (8 * i); + value |= bytes[i] << (8 * i); } return value; } // ------------ -// u16 bits +// u32 bits // ------------ -uint8_t *u16_to_le_bytes(uint16_t value, uint8_t *buffer_bytes) { - for (int i = 0; i < 2; i++) { +uint8_t *u32_to_le_bytes(uint32_t value, uint8_t *buffer_bytes) { + for (int i = 0; i < 4; i++) { buffer_bytes[i] = value >> (8 * i) & 0xFF; } return buffer_bytes; } -uint16_t u16_from_le_bytes(uint8_t *bytes) { +uint8_t *u32_to_be_bytes(uint32_t value, uint8_t *buffer_bytes) { + for (int i = 3; i >= 0; i--) { + buffer_bytes[i] = value >> (8 * i) & 0xFF; + } + return buffer_bytes; +} + +uint32_t u32_from_le_bytes(uint8_t *bytes) { uint16_t value = 0; - for (int i = 1; i >= 0; i--) { - value |= bytes[i]; - value = value << (8 * i); + for (int i = 3; i >= 0; i--) { + value |= bytes[i] << (8 * i); + } + return value; +} + +uint32_t u32_from_be_bytes(uint8_t *bytes) { + uint64_t value = 0; + for (int i = 0; i < 4; i++) { + value |= bytes[i] << (8 * i); } return value; } // ------------ -// u32 bits +// u16 bits // ------------ -uint8_t *u32_to_le_bytes(uint32_t value, uint8_t *buffer_bytes) { - for (int i = 0; i < 4; i++) { +uint8_t *u16_to_le_bytes(uint16_t value, uint8_t *buffer_bytes) { + for (int i = 0; i < 2; i++) { buffer_bytes[i] = value >> (8 * i) & 0xFF; } return buffer_bytes; } -uint32_t u32_from_le_bytes(uint8_t *bytes) { +uint8_t *u16_to_be_bytes(uint16_t value, uint8_t *buffer_bytes) { + for (int i = 1; i >= 0; i--) { + buffer_bytes[i] = value >> (8 * i) & 0xFF; + } + return buffer_bytes; +} + +uint16_t u16_from_le_bytes(uint8_t *bytes) { uint16_t value = 0; - for (int i = 3; i >= 0; i--) { - value |= bytes[i]; - value = value << (8 * i); + for (int i = 1; i >= 0; i--) { + value |= bytes[i] << (8 * i); + } + return value; +} + +uint16_t u16_from_be_bytes(uint8_t *bytes) { + uint16_t value = 0; + for (int i = 0; i < 2; i++) { + value |= bytes[i] << (8 * i); } return value; } diff --git a/src/utils.h b/src/utils.h index 88fa4ed..5b27954 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,21 +2,28 @@ #define UTILS_H #include "../lambdaworks/lib/lambdaworks.h" +#include "relocatable.h" #include "stdint.h" #include "stdio.h" #include bool felt_equal(felt_t a, felt_t b); +int64_t absolute(int64_t a); +maybe_relocatable add_maybe_relocatable(maybe_relocatable a, maybe_relocatable b); uint8_t *u64_to_le_bytes(uint64_t value, uint8_t *buffer_bytes); uint8_t *u64_to_be_bytes(uint64_t value, uint8_t *buffer_bytes); uint64_t u64_from_le_bytes(uint8_t *bytes); uint64_t u64_from_be_bytes(uint8_t *bytes); -uint8_t *u16_to_le_bytes(uint16_t value, uint8_t *buffer_bytes); -uint16_t u16_from_le_bytes(uint8_t *bytes); - uint8_t *u32_to_le_bytes(uint32_t value, uint8_t *buffer_bytes); +uint8_t *u32_to_be_bytes(uint32_t value, uint8_t *buffer_bytes); uint32_t u32_from_le_bytes(uint8_t *bytes); +uint32_t u32_from_be_bytes(uint8_t *bytes); + +uint8_t *u16_to_le_bytes(uint16_t value, uint8_t *buffer_bytes); +uint8_t *u16_to_be_bytes(uint16_t value, uint8_t *buffer_bytes); +uint16_t u16_from_le_bytes(uint8_t *bytes); +uint16_t u16_from_be_bytes(uint8_t *bytes); #endif diff --git a/src/vm.c b/src/vm.c index 485263b..e3660c4 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,7 +1,147 @@ #include "vm.h" -#include "memory.h" virtual_machine vm_new(void) { virtual_machine vm = {{{0, 0}, {0, 0}, {0, 0}}, memory_new()}; return vm; } + +maybe_relocatable compute_res(Instruction instr, maybe_relocatable op0, maybe_relocatable op1) { + maybe_relocatable res; + switch (instr.res) { + case Op1: + res = op1; + break; + case Res_Add: + res = add_maybe_relocatable(op0, op1); + break; + case Mul: + if (op0.is_felt && op1.is_felt) { + felt_t a = {op0.value.felt[0], op0.value.felt[1], op0.value.felt[2], op0.value.felt[3]}; + felt_t b = {op1.value.felt[0], op1.value.felt[1], op1.value.felt[2], op1.value.felt[3]}; + felt_t result; + mul(a, b, result); + res = (maybe_relocatable){.is_felt = true, + .value = {.felt = {result[0], result[1], result[2], result[3]}}}; + } else { + res = (maybe_relocatable){.is_felt = false, .value = {.relocatable = {0, 0}}}; + } + break; + default: + // TODO: in rust this is a none, we should check what to do in this cases + res = (maybe_relocatable){.is_felt = false, .value = {.relocatable = {0, 0}}}; + break; + } + return res; +} + +bool was_op0_deducted(uint8_t ded_ops) { return (ded_ops & 1 << 1) != 0; } +bool was_op1_deducted(uint8_t ded_ops) { return (ded_ops & 1 << 2) != 0; } +bool was_dst_deducted(uint8_t ded_ops) { return (ded_ops & 1) != 0; } + +vm_result insert_deduced_operands(memory mem, uint8_t ded_ops, operands opers, operands_addresses oper_addr) { + vm_result result; + if (was_op0_deducted(ded_ops)) { + ResultMemory res = memory_insert(&mem, oper_addr.op0_addr, opers.op0); + if (res.type == Err) { + result = (vm_result){ + .is_ok = false, + .error = MemoryError, + }; + } + } + if (was_op1_deducted(ded_ops)) { + ResultMemory res = memory_insert(&mem, oper_addr.op1_addr, opers.op1); + if (res.type == Err) { + result = (vm_result){ + .is_ok = false, + .error = MemoryError, + }; + } + } + if (was_dst_deducted(ded_ops)) { + ResultMemory res = memory_insert(&mem, oper_addr.dst_addr, opers.dst); + if (res.type == Err) { + result = (vm_result){ + .is_ok = false, + .error = MemoryError, + }; + } + } + + else { + result = (vm_result){ + .is_ok = true, + .error = None, + }; + } + + return result; +} + +computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { + relocatable dst_addr = compute_dst_addr(vm.run_context, instr); + ResultMemory dst_op = memory_get(&vm.memory, dst_addr); + if (dst_op.type == Err) { + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; + return res; + } + + relocatable op0_addr = compute_op0_addr(vm.run_context, instr); + ResultMemory op0_op = memory_get(&vm.memory, op0_addr); + + relocatable op1_addr = compute_op1_addr(vm.run_context, instr, op0_op.value.memory_value); + ResultMemory op1_op = memory_get(&vm.memory, op1_addr); + + felt_t value; + from(value, 0); + // maybe_relocatable res = {.is_felt = false, .value = {.felt = {value[0], value[1], value[2], + // value[3]}}}; + uint8_t deduced_operands = 0; + + if (op0_op.type == Err) { + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; + return res; + } + + // for now this is always pre computed. we should handle the case when it is not + maybe_relocatable op0 = op0_op.value.memory_value; + if (op0_op.type == Err) { + } + maybe_relocatable op1 = op1_op.value.memory_value; + + // compute res + maybe_relocatable res = compute_res(instr, op0, op1); + + // compute dst + maybe_relocatable dst = dst_op.value.memory_value; + + operands_addresses accessed_addresses = { + .dst_addr = {.offset = dst_addr.offset, .segment_index = dst_addr.segment_index}, + .op0_addr = {.offset = op0_addr.offset, .segment_index = op0_addr.segment_index}, + .op1_addr = {.offset = op1_addr.offset, .segment_index = op1_addr.segment_index}, + }; + + operands operands = {.dst = dst, .op0 = op0, .op1 = op1, .res = res}; + computed_operands_res result = { + .is_error = false, + .value = {.ops = {.oprs = operands, .op_addrs = accessed_addresses, .deduced_operands = deduced_operands}}}; + + return result; +} +// TODO: uncomment once all functions are done +// vm_result run_instruction(virtual_machine vm, Instruction instr) { + +// computed_operands_res com_op_res = compute_operands(vm, instr); +// if (com_op_res.is_error) { +// VirtualMachineError err = com_op_res.value.error; +// vm_result res = {.is_ok = false, .error = err}; +// return res; +// } + +// vm_result res = { +// .is_ok = true, +// .error = None, +// }; + +// return res; +// } diff --git a/src/vm.h b/src/vm.h index d7e6c70..0a6d414 100644 --- a/src/vm.h +++ b/src/vm.h @@ -1,14 +1,63 @@ #ifndef VM_H #define VM_H +#include "instruction.h" #include "memory.h" +#include "relocatable.h" #include "run_context.h" -typedef struct virtual_machine { +#include "utils.h" + +typedef struct { + enum VirtualMachineError error; + bool is_ok; +} vm_result; + +typedef struct { run_context run_context; memory memory; } virtual_machine; +// --------------------- +// execution structures +// --------------------- + +typedef struct operands { + maybe_relocatable dst; + maybe_relocatable res; + maybe_relocatable op0; + maybe_relocatable op1; +} operands; + +typedef struct operands_addresses { + relocatable dst_addr; + relocatable op0_addr; + relocatable op1_addr; +} operands_addresses; + +typedef struct computed_operands { + operands oprs; + operands_addresses op_addrs; + uint8_t deduced_operands; +} computed_operands; + +typedef union computed_operands_value { + computed_operands ops; + VirtualMachineError error; +} computed_operands_value; + +typedef struct computed_operands_res { + computed_operands_value value; + bool is_error; +} computed_operands_res; + +// --------------------- +// VM functions +// --------------------- + // Creates a new, empty virtual_machine virtual_machine vm_new(void); - +// executes an instruction in the vm +vm_result run_instruction(virtual_machine vm, Instruction instr); +// Creates a new, empty virtual_machine +maybe_relocatable compute_res(Instruction instr, maybe_relocatable op0, maybe_relocatable op1); #endif diff --git a/test/memory_tests.c b/test/memory_tests.c index 5194c18..e89de91 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -1,15 +1,11 @@ #include "memory_tests.h" -#include "relocatable.h" -#include "utils.h" -#include -#include void memory_get_err(void) { // Initialize memory memory mem = memory_new(); relocatable ptr = {0, 0}; ResultMemory result = memory_get(&mem, ptr); - assert(result.is_error); + assert(result.type == Err); assert(result.value.error == Get); memory_free(&mem); printf("OK!\n"); @@ -19,9 +15,11 @@ void memory_insert_err_unallocated_segement(void) { // Initialize memory memory mem = memory_new(); relocatable ptr = {0, 0}; - maybe_relocatable elem = {.is_felt = true, .value = {.felt = {1}}}; + felt_t f; + one(f); + maybe_relocatable elem = {.is_felt = true, .value = {.felt = {f[0], f[1], f[2], f[3]}}}; ResultMemory result = memory_insert(&mem, ptr, elem); - assert(result.is_error); + assert(result.type == Err); assert(result.value.error == Insert); memory_free(&mem); printf("OK!\n"); @@ -36,12 +34,12 @@ void memory_insert_err_ovewrite_attempt(void) { one(felt_one); maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result = memory_insert(&mem, ptr, elem); - assert(!result.is_error); + assert(result.type != Err); felt_t felt_two; from(felt_two, 2); maybe_relocatable elem_b = maybe_relocatable_from_felt_limbs(felt_two); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); - assert(result_b.is_error); + assert(result_b.type == Err); assert(result_b.value.error == Insert); memory_free(&mem); printf("OK!\n"); @@ -56,10 +54,10 @@ void memory_insert_ok_ovewrite_same_value(void) { one(felt_one); maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result = memory_insert(&mem, ptr, elem); - assert(!result.is_error); + assert(result.type != Err); maybe_relocatable elem_b = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); - assert(!result_b.is_error); + assert(result_b.type != Err); memory_free(&mem); printf("OK!\n"); } @@ -73,10 +71,10 @@ void memory_insert_ok(void) { one(felt_one); maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_insert = memory_insert(&mem, ptr, elem); - assert(!result_insert.is_error); + assert(result_insert.type != Err); assert(result_insert.value.none == 0); ResultMemory result_get = memory_get(&mem, ptr); - assert(!result_get.is_error); + assert(result_get.type != Err); assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); memory_free(&mem); printf("OK!\n"); @@ -91,10 +89,10 @@ void memory_insert_with_gap(void) { one(felt_one); maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_insert = memory_insert(&mem, ptr, elem); - assert(!result_insert.is_error); + assert(result_insert.type != Err); assert(result_insert.value.none == 0); ResultMemory result_get = memory_get(&mem, ptr); - assert(!result_get.is_error); + assert(result_get.type != Err); assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); memory_free(&mem); printf("OK!\n"); @@ -113,12 +111,12 @@ void memory_load_data_one_element(void) { relocatable ptr = {0, 0}; // Load data ResultMemory load_result = memory_load_data(&mem, ptr, data); - assert(!load_result.is_error); + assert(load_result.type != Err); relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); // Check memory ResultMemory result = memory_get(&mem, ptr); - assert(!result.is_error); + assert(result.type != Err); assert(maybe_relocatable_equal(result.value.memory_value, elem)); memory_free(&mem); data->free(data); @@ -134,12 +132,12 @@ void memory_load_data_empty(void) { relocatable ptr = {0, 0}; // Load data ResultMemory load_result = memory_load_data(&mem, ptr, data); - assert(!load_result.is_error); + assert(load_result.type != Err); relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 0); // Check memory ResultMemory result = memory_get(&mem, ptr); - assert(result.is_error); + assert(result.type == Err); memory_free(&mem); data->free(data); printf("OK!\n"); @@ -153,7 +151,7 @@ void memory_load_data_err_unallocated_segment(void) { relocatable ptr = {0, 0}; // Load data ResultMemory load_result = memory_load_data(&mem, ptr, data); - assert(load_result.is_error); + assert(load_result.type == Err); assert(load_result.value.error == LoadData); data->free(data); memory_free(&mem); diff --git a/test/memory_tests.h b/test/memory_tests.h index 3765641..af56dda 100644 --- a/test/memory_tests.h +++ b/test/memory_tests.h @@ -1,5 +1,9 @@ #ifndef MEMORY_TEST_H #define MEMORY_TEST_H + +#include "../lambdaworks/lib/lambdaworks.h" +#include "../src/relocatable.h" +#include "../src/utils.h" #include "memory.h" #include #include diff --git a/test/parser_test.c b/test/parser_test.c index 7f1677b..d823095 100644 --- a/test/parser_test.c +++ b/test/parser_test.c @@ -92,6 +92,5 @@ void parsing_tests(void) { parsing_compiler_version(program); printf("---------------------------------\n"); parsing_data_test(program); - printf("---------------------------------\n"); free_program(program); } diff --git a/test/relocatable_tests.c b/test/relocatable_tests.c new file mode 100644 index 0000000..f0f954c --- /dev/null +++ b/test/relocatable_tests.c @@ -0,0 +1,27 @@ +#include "relocatable_tests.h" + +void sub_relocatable_ok_test(void) { + printf("Test: Sub relocatables ok test\n"); + relocatable expected = {.segment_index = 10, .offset = 5}; + relocatable rel = {.segment_index = 10, .offset = 10}; + relocatable result = sub_relocatable(rel, 5); + assert(relocatable_equal(expected, result)); + printf("OK!\n"); +} + +void add_relocatable_ok_test(void) { + printf("Test: Add relocatables ok test\n"); + relocatable expected = {.segment_index = 10, .offset = 10}; + relocatable rel = {.segment_index = 10, .offset = 5}; + relocatable result = add_relocatable(rel, 5); + assert(relocatable_equal(expected, result)); + printf("OK!\n"); +} +void relocatable_tests(void) { + printf("--------------------------------- \n"); + printf("Relocatable tests\n"); + printf("---------------------------------\n"); + sub_relocatable_ok_test(); + printf("---------------------------------\n"); + add_relocatable_ok_test(); +} diff --git a/test/relocatable_tests.h b/test/relocatable_tests.h new file mode 100644 index 0000000..c5fc323 --- /dev/null +++ b/test/relocatable_tests.h @@ -0,0 +1,10 @@ +#ifndef RELOCATABLE_TESTS_H +#define RELOCATABLE_TESTS_H +#include "relocatable.h" +#include "utils.h" +#include +#include + +void relocatable_tests(void); + +#endif diff --git a/test/run_context_tests.c b/test/run_context_tests.c new file mode 100644 index 0000000..d634ba1 --- /dev/null +++ b/test/run_context_tests.c @@ -0,0 +1,117 @@ +#include "run_context_tests.h" + +void compute_dst_addr_test(void) { + printf("Test: Compute dst address test\n"); + relocatable pc = {.segment_index = 0, .offset = 0}; + relocatable ap = {.segment_index = 5, .offset = 5}; + relocatable fp = {.segment_index = 10, .offset = 10}; + run_context ctx = {.pc = pc, .ap = ap, .fp = fp}; + Instruction instr = {.off0 = 0, + .off1 = 1, + .off2 = 2, + .dst_register = REG_AP, + .op0_register = REG_AP, + .op1_addr = OP_AP, + .res = Res_Add, + .pc_update = PC_Regular, + .ap_update = AP_Regular, + .fp_update = FP_Regular, + .opcode = NOp}; + + relocatable result = compute_dst_addr(ctx, instr); + assert(result.segment_index == ap.segment_index); + assert(result.offset == 0); + instr.off0 = -1; + result = compute_dst_addr(ctx, instr); + assert(result.offset == 4); + instr.dst_register = REG_FP; + result = compute_dst_addr(ctx, instr); + assert(result.segment_index == fp.segment_index); + assert(result.offset == 9); + instr.off0 = 2; + result = compute_dst_addr(ctx, instr); + assert(result.offset == 12); + + printf("Ok!\n"); +} + +void compute_op0_addr_test(void) { + printf("Test: Compute op0 address test\n"); + relocatable pc = {.segment_index = 0, .offset = 0}; + relocatable ap = {.segment_index = 5, .offset = 5}; + relocatable fp = {.segment_index = 10, .offset = 10}; + run_context ctx = {.pc = pc, .ap = ap, .fp = fp}; + Instruction instr = {.off0 = 0, + .off1 = 1, + .off2 = 2, + .dst_register = REG_AP, + .op0_register = REG_AP, + .op1_addr = OP_AP, + .res = Res_Add, + .pc_update = PC_Regular, + .ap_update = AP_Regular, + .fp_update = FP_Regular, + .opcode = NOp}; + + relocatable result = compute_op0_addr(ctx, instr); + assert(result.segment_index == ap.segment_index); + assert(result.offset == 6); + instr.off1 = -1; + result = compute_op0_addr(ctx, instr); + assert(result.offset == 4); + instr.op0_register = REG_FP; + result = compute_op0_addr(ctx, instr); + assert(result.segment_index == fp.segment_index); + assert(result.offset == 9); + instr.off1 = 2; + result = compute_op0_addr(ctx, instr); + assert(result.offset == 12); + + printf("Ok!\n"); +} + +// void compute_op1_addr_test(void) { +// printf("Compute op1 address test\n"); +// relocatable pc = {.segment_index = 0, .offset = 0}; +// relocatable ap = {.segment_index = 5, .offset = 5}; +// relocatable fp = {.segment_index = 10, .offset = 10}; +// run_context ctx = {.pc = pc, .ap = ap, .fp = fp}; +// Instruction instr = {.off0 = 0, +// .off1 = 1, +// .off2 = 2, +// .dst_register = REG_AP, +// .op0_register = REG_AP, +// .op1_addr = OP_AP, +// .res = Res_Add, +// .pc_update = PC_Regular, +// .ap_update = AP_Regular, +// .fp_update = FP_Regular, +// .opcode = NOp}; +// relocatable aux = {.segment_index = 15, .offset = 15}; +// maybe_relocatable op0 = {.is_felt = false, .value = {.relocatable = aux}}; +// relocatable result = compute_op1_addr(ctx, instr, op0); +// assert(result.segment_index == ap.segment_index); +// assert(result.offset == 7); +// instr.off1 = -1; +// result = compute_op1_addr(ctx, instr); +// assert(result.offset == 4); +// instr.op0_register = REG_FP; +// result = compute_op1_addr(ctx, instr); +// assert(result.segment_index == fp.segment_index); +// assert(result.offset == 9); +// instr.off1 = 2; +// result = compute_op1_addr(ctx, instr); +// assert(result.offset == 12); + +// printf("Ok!\n"); +// } + +void run_context_test(void) { + printf("--------------------------------- \n"); + printf("Run context tests\n"); + printf("---------------------------------\n"); + compute_dst_addr_test(); + printf("---------------------------------\n"); + compute_op0_addr_test(); + // compute_op1_addr_test(); +} diff --git a/test/run_context_tests.h b/test/run_context_tests.h new file mode 100644 index 0000000..45db7d3 --- /dev/null +++ b/test/run_context_tests.h @@ -0,0 +1,10 @@ +#ifndef RUN_CONTEXT_TESTS_H +#define RUN_CONTEXT_TESTS_H + +#include "run_context.h" +#include +#include + +void run_context_test(void); + +#endif diff --git a/test/runner_tests.c b/test/runner_tests.c index 3a26b8b..5506fd5 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -37,18 +37,18 @@ void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { // program segment relocatable ptr = {0, 0}; ResultMemory result = memory_get(&memory, ptr); - assert(!result.is_error); + assert(result.type != Err); assert(felt_equal(result.value.memory_value.value.felt, felt_one)); // execution segment relocatable ptr_b = {1, 0}; ResultMemory result_b = memory_get(&memory, ptr_b); - assert(!result_b.is_error); + assert(result_b.type != Err); relocatable value_b = result_b.value.memory_value.value.relocatable; assert(value_b.segment_index == 2 && value_b.offset == 0); relocatable ptr_c = {1, 1}; ResultMemory result_c = memory_get(&memory, ptr_c); - assert(!result_c.is_error); + assert(result_c.type != Err); relocatable value_c = result_c.value.memory_value.value.relocatable; assert(value_c.segment_index == 3 && value_c.offset == 0); @@ -81,17 +81,17 @@ void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { assert(memory.num_segments == 4); relocatable ptr = {0, 0}; ResultMemory result = memory_get(&memory, ptr); - assert(result.is_error); + assert(result.type == Err); // execution segment relocatable ptr_b = {1, 0}; ResultMemory result_b = memory_get(&memory, ptr_b); - assert(!result_b.is_error); + assert(result_b.type != Err); relocatable value_b = result_b.value.memory_value.value.relocatable; assert(value_b.segment_index == 2 && value_b.offset == 0); relocatable ptr_c = {1, 1}; ResultMemory result_c = memory_get(&memory, ptr_c); - assert(!result_c.is_error); + assert(result_c.type != Err); relocatable value_c = result_c.value.memory_value.value.relocatable; assert(value_c.segment_index == 3 && value_c.offset == 0); runner_free(&runner); diff --git a/test/test.c b/test/test.c index d6130a4..d46ce4c 100644 --- a/test/test.c +++ b/test/test.c @@ -3,17 +3,22 @@ #include "instruction_test.h" #include "memory_tests.h" #include "parser_test.h" +#include "relocatable_tests.h" +#include "run_context_tests.h" #include "runner_tests.h" +#include "vm_test.h" #include #include int main(__attribute__((unused)) int argc, __attribute__((unused)) char **argv) { - felt_tests(); decoding_tests(); instruction_tests(); memory_tests(); runner_tests(); parsing_tests(); + relocatable_tests(); + run_context_test(); + vm_tests(); return 0; } diff --git a/test/vm_test.c b/test/vm_test.c new file mode 100644 index 0000000..7f1c422 --- /dev/null +++ b/test/vm_test.c @@ -0,0 +1,8 @@ +#include "vm_test.h" + +void compute_operands_test(void) { printf("NOT IMPLEMENTED!"); } + +void vm_tests(void) { + printf("--------------------------------- \n"); + printf("VM tests\n"); +} diff --git a/test/vm_test.h b/test/vm_test.h new file mode 100644 index 0000000..6826d68 --- /dev/null +++ b/test/vm_test.h @@ -0,0 +1,10 @@ +#ifndef VM_TEST_H +#define VM_TEST_H + +#include "vm.h" +#include +#include + +void vm_tests(void); + +#endif