Skip to content

Commit

Permalink
🚧 CairoVm.updatePc case PcUpdate.Regular
Browse files Browse the repository at this point in the history
  • Loading branch information
AbdelStark committed Oct 20, 2023
1 parent e8fc471 commit 066f6ec
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 8 deletions.
133 changes: 133 additions & 0 deletions src/vm/core.zig
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,64 @@ pub const CairoVM = struct {
_ = self;
return null;
}

/// Updates the value of PC according to the executed instruction.
/// # Arguments
/// - `instruction`: The instruction that was executed.
/// - `operands`: The operands of the instruction.
pub fn updatePc(self: *CairoVM, instruction: *const instructions.Instruction, operands: OperandsResult) !void {
_ = operands;

switch (instruction.pc_update) {
instructions.PcUpdate.Regular => {
self.run_context.pc.*.addUintInPlace(instruction.size());
},
instructions.PcUpdate.Jump => {
// TODO: Implement this.
return;
},
instructions.PcUpdate.JumpRel => {
// TODO: Implement this.
return;
},
instructions.PcUpdate.Jnz => {
// TODO: Implement this.
return;
},
}
}

// ************************************************************
// * ACCESSORS *
// ************************************************************

/// Returns whether the run is finished or not.
/// # Returns
/// - `bool`: Whether the run is finished or not.
pub fn isRunFinished(self: *const CairoVM) bool {
return self.is_run_finished;
}

/// Returns the current ap.
/// # Returns
/// - `MaybeRelocatable`: The current ap.
pub fn getAp(self: *const CairoVM) relocatable.Relocatable {
return self.run_context.ap.*;
}

/// Returns the current fp.
/// # Returns
/// - `MaybeRelocatable`: The current fp.
pub fn getFp(self: *const CairoVM) relocatable.Relocatable {
return self.run_context.fp.*;
}

/// Returns the current pc.
/// # Returns
/// - `MaybeRelocatable`: The current pc.
pub fn getPc(self: *const CairoVM) relocatable.Relocatable {
return self.run_context.pc.*;
}
};

// *****************************************************************************
Expand All @@ -182,4 +240,79 @@ const OperandsResult = struct {
dst_addr: relocatable.MaybeRelocatable,
op_0_addr: relocatable.MaybeRelocatable,
op_1_addr: relocatable.MaybeRelocatable,

/// Returns a default instance of the OperandsResult struct.
pub fn default() OperandsResult {
return OperandsResult{
.dst = relocatable.fromU64(0),
.res = relocatable.fromU64(0),
.op_0 = relocatable.fromU64(0),
.op_1 = relocatable.fromU64(0),
.dst_addr = relocatable.fromU64(0),
.op_0_addr = relocatable.fromU64(0),
.op_1_addr = relocatable.fromU64(0),
};
}
};

// ************************************************************
// * TESTS *
// ************************************************************
const expectEqual = std.testing.expectEqual;
const expectError = std.testing.expectError;

test "update pc regular no imm" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.Regular;
instruction.op_1_addr = instructions.Op1Src.AP;
const operands = OperandsResult.default();
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try vm.updatePc(&instruction, operands);

// ************************************************************
// * TEST CHECKS *
// ************************************************************
const pc = vm.getPc();
try expectEqual(pc.offset, 1);
}

test "update pc regular with imm" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.Regular;
instruction.op_1_addr = instructions.Op1Src.Imm;
const operands = OperandsResult.default();
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try vm.updatePc(&instruction, operands);

// ************************************************************
// * TEST CHECKS *
// ************************************************************
const pc = vm.getPc();
try expectEqual(pc.offset, 2);
}
37 changes: 29 additions & 8 deletions src/vm/instructions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const std = @import("std");
// *****************************************************************************

/// Error type to represent different error conditions during instruction decoding.
const Error = error{
pub const Error = error{
NonZeroHighBit,
InvalidOp1Reg,
Invalidpc_update,
Expand All @@ -34,19 +34,19 @@ const Error = error{
// * CUSTOM TYPES DEFINITIONS *
// *****************************************************************************

const Register = enum { AP, FP };
pub const Register = enum { AP, FP };

const Op1Src = enum { Imm, AP, FP, Op0 };
pub const Op1Src = enum { Imm, AP, FP, Op0 };

const ResLogic = enum { Op1, Add, Mul, Unconstrained };
pub const ResLogic = enum { Op1, Add, Mul, Unconstrained };

const PcUpdate = enum { Regular, Jump, JumpRel, Jnz };
pub const PcUpdate = enum { Regular, Jump, JumpRel, Jnz };

const ApUpdate = enum { Regular, Add, Add1, Add2 };
pub const ApUpdate = enum { Regular, Add, Add1, Add2 };

const FpUpdate = enum { Regular, APPlus2, Dst };
pub const FpUpdate = enum { Regular, APPlus2, Dst };

const Opcode = enum { NOp, AssertEq, Call, Ret };
pub const Opcode = enum { NOp, AssertEq, Call, Ret };

/// Represents a decoded instruction.
pub const Instruction = struct {
Expand All @@ -61,6 +61,27 @@ pub const Instruction = struct {
ap_update: ApUpdate,
fp_update: FpUpdate,
opcode: Opcode,

/// Returns the size of an instruction.
/// # Returns
/// Size of the instruction.
pub fn size(self: Instruction) usize {
if (self.op_1_addr == Op1Src.Imm) {
return 2;
} else {
return 1;
}
}

/// Returns a default instruction.
pub fn default() Instruction {
// 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg
// 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0
// | CALL| ADD| JUMP| ADD| IMM| FP| FP
// 0 0 0 1 0 1 0 0 1 0 1 0 0 1 1 1
// 0001 0100 1010 0111 = 0x14A7; offx = 0
return decode(0x14A7800080008000) catch unreachable;
}
};

/// Decode a 64-bit instruction into its component parts.
Expand Down
9 changes: 9 additions & 0 deletions src/vm/memory/relocatable.zig
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ pub const Relocatable = struct {
};
}

/// Add a u64 to this Relocatable, modifying it in place.
/// # Arguments
/// - self: Pointer to the Relocatable object to modify.
/// - other: The u64 to add to `self.offset`.
pub fn addUintInPlace(self: *Relocatable, other: u64) void {
// Modify the offset of the existing Relocatable object
self.offset += other;
}

// Add a i64 to a Relocatable and return a new Relocatable.
// # Arguments
// - other: The i64 to add.
Expand Down

0 comments on commit 066f6ec

Please sign in to comment.