diff --git a/Cargo.lock b/Cargo.lock index 77ef387..13b7796 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "aluvm" -version = "0.12.0-alpha.1" +version = "0.12.0-nightly-zkaluvm.1" dependencies = [ "amplify", "ascii-armor", diff --git a/Cargo.toml b/Cargo.toml index 5db3b9b..2abfce5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "aluvm" description = "Functional registry-based RISC virtual machine" -version = "0.12.0-alpha.1" +version = "0.12.0-nightly-zkaluvm.1" authors = ["Dr Maxim Orlovsky "] repository = "https://github.com/aluvm/rust-aluvm" homepage = "https://aluvm.org" @@ -32,12 +32,9 @@ serde = { version = "1", optional = true } [features] default = [] -all = [ - "stl", "log", "armor", - # Instruction set architecture extensions - # "a1024", "array", "str", "float", "sha", "secp256k1", "curve25519", - "serde" -] +# `all` must exclude specific ISA, which may be in a conflict with each other +# The consumer of the library is expected to add required ISA manually +all = ["stl", "log", "armor", "serde"] armor = ["dep:ascii-armor"] stl = ["strict_types/armor"] @@ -46,10 +43,19 @@ alloc = ["amplify/alloc"] serde = ["dep:serde", "amplify/serde", "strict_encoding/serde"] # Instruction set architecture extensions -# a1024 = [] -# array = [] -# str = [] -# float = ["amplify/apfloat", "half"] +zk-aluvm = ["GFA"] # Feature ensuring zk-AluVM configuration excluding all zk-incompatible features +A64 = [] +A128 = ["A64"] +# A256 = ["A128"] +# A512 = ["A512"] +# A1024 = ["A1024"] +GFA = [] +STR = [] +# ARRAY = [] +# FL64 = [] +# FL80 = ["FL64", "amplify/apfloat"] +# FLQTR = ["FL80"] +# FLOCT = ["FLOCT"] [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = "0.2" diff --git a/src/core/core.rs b/src/core/core.rs index 04b0eef..62732ad 100644 --- a/src/core/core.rs +++ b/src/core/core.rs @@ -22,52 +22,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -use core::fmt::{self, Debug, Display, Formatter}; -use core::str::FromStr; +use core::fmt::{self, Debug, Formatter}; -//#[cfg(feature = "str")] -//use crate::util::ByteStr; +use super::{Site, SiteId, Status}; +#[cfg(feature = "GFA")] +use crate::core::gfa::Zp; /// Maximal size of call stack. /// /// Equals to 0xFFFF (i.e. maximum limited by `cy` and `cp` bit size). pub const CALL_STACK_SIZE_MAX: u16 = 0xFF; -#[derive(Copy, Clone, Eq, PartialEq, Debug, Display)] -#[repr(i8)] -pub enum Status { - #[display("ok")] - Ok = 0, - - #[display("fail")] - Fail = -1, -} - -impl Status { - pub fn is_ok(self) -> bool { self == Status::Ok } -} - -pub trait SiteId: Copy + Ord + Debug + Display + FromStr {} - -/// Location inside the instruction sequence which can be executed by the core. -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] -pub struct Site { - pub prog_id: Id, - pub offset: u16, -} - -impl Site { - #[inline] - pub fn new(prog_id: Id, offset: u16) -> Self { Self { prog_id, offset } } -} - -impl Display for Site { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}:{:04X}.h", self.prog_id, self.offset) } -} - /// Registers of a single CPU/VM core. #[derive(Clone)] -pub struct AluCore { +pub struct Core { + #[cfg(feature = "GFA")] + /// Finite field order. + pub(super) zp: Zp, + // ============================================================================================ // Arithmetic integer registers (ALU64 ISA). pub(super) a8: [Option; 32], @@ -121,8 +93,8 @@ pub struct AluCore { /// /// # See also /// - /// - [`AluCore::ck`] register - /// - [`AluCore::cf`] register + /// - [`Core::ck`] register + /// - [`Core::cf`] register ch: bool, /// Check register, which is set on any failure (accessing register in `None` state, zero @@ -130,16 +102,16 @@ pub struct AluCore { /// /// # See also /// - /// - [`AluCore::ch`] register - /// - [`AluCore::cf`] register + /// - [`Core::ch`] register + /// - [`Core::cf`] register pub(super) ck: Status, /// Failure register, which is set on the first time `ck` is set, and can't be reset. /// /// # See also /// - /// - [`AluCore::ch`] register - /// - [`AluCore::ck`] register + /// - [`Core::ch`] register + /// - [`Core::ck`] register cf: Status, /// Test register, which acts as boolean test result (also a carry flag). @@ -156,13 +128,13 @@ pub struct AluCore { /// /// # See also /// - /// - [`AluCore::cy`] register - /// - [`AluCore::cl`] register + /// - [`Core::cy`] register + /// - [`Core::cl`] register pub(super) ca: u64, /// Complexity limit. /// - /// If this register has a value set, once [`AluCore::ca`] will reach this value the VM will + /// If this register has a value set, once [`Core::ca`] will reach this value the VM will /// stop program execution setting `ck` to `false`. cl: Option, @@ -171,47 +143,64 @@ pub struct AluCore { /// # See also /// /// - [`CALL_STACK_SIZE_MAX`] constant - /// - [`AluCore::cp`] register + /// - [`Core::cp`] register pub(super) cs: Vec>, /// Defines "top" of the call stack. pub(super) cp: u16, } -/// Configuration for [`AluCore`] initialization. +/// Configuration for [`Core`] initialization. #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub struct CoreConfig { - /// Initial value for the [`AluCore::ch`] flag. + /// Initial value for the [`Core::ch`] flag. pub halt: bool, - /// Initial value for the [`AluCore::cl`] flag. + /// Initial value for the [`Core::cl`] flag. pub complexity_lim: Option, - /// Size of the call stack in the [`AluCore::cs`] register. + /// Size of the call stack in the [`Core::cs`] register. pub call_stack_size: u16, + #[cfg(feature = "GFA")] + /// Order of the finite field for modulo arithmetics. + pub field_order: Zp, } impl Default for CoreConfig { - /// Sets [`CoreConfig::halt`] to `true`, [`CoreConfig::complexity_lim`] to `None` and - /// [`CoreConfig::call_stack_size`] to [`CALL_STACK_SIZE_MAX`]. + /// Sets + /// - [`CoreConfig::halt`] to `true`, + /// - [`CoreConfig::complexity_lim`] to `None` + /// - [`CoreConfig::call_stack_size`] to [`CALL_STACK_SIZE_MAX`], + /// - [`CoreConfig::field_order`] to [`Zp::F1137119`] (if `GFA` feature is set). + /// + /// # See also + /// + /// - [`CoreConfig::halt`] + /// - [`CoreConfig::complexity_lim`] + /// - [`CoreConfig::call_stack_size`] + /// - [`CoreConfig::field_order`] fn default() -> Self { CoreConfig { halt: true, complexity_lim: None, call_stack_size: CALL_STACK_SIZE_MAX, + #[cfg(feature = "GFA")] + field_order: Zp::F1137119, } } } -impl AluCore { +impl Core { /// Initializes registers. Sets `st0` to `true`, counters to zero, call stack to empty and the /// rest of registers to `None` value. /// - /// An alias for [`AluCore::with`]`(RegConfig::default())`. + /// An alias for [`AluCore::with`]`(`[`CoreConfig::default()`]`)`. #[inline] - pub fn new() -> Self { AluCore::with(default!()) } + pub fn new() -> Self { Core::with(default!()) } /// Initializes registers using a configuration object [`CoreConfig`]. pub fn with(config: CoreConfig) -> Self { - AluCore { + Core { + #[cfg(feature = "GFA")] + zp: config.field_order, a8: Default::default(), a16: Default::default(), a32: Default::default(), @@ -234,7 +223,7 @@ impl AluCore { } /// Microcode for flag registers. -impl AluCore { +impl Core { /// Return whether check register `ck` was set to a failed state for at least once. pub fn had_failed(&self) -> bool { self.cf == Status::Fail } @@ -242,7 +231,7 @@ impl AluCore { pub fn cl(&self) -> Option { return self.cl; } } -impl Debug for AluCore { +impl Debug for Core { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let (sect, reg, val, reset) = if f.alternate() { ("\x1B[0;4;1m", "\x1B[0;1m", "\x1B[0;32m", "\x1B[0m") } else { ("", "", "", "") }; diff --git a/src/core/microcode.rs b/src/core/microcode/alu128.rs similarity index 63% rename from src/core/microcode.rs rename to src/core/microcode/alu128.rs index b6b7cd2..f58c8d7 100644 --- a/src/core/microcode.rs +++ b/src/core/microcode/alu128.rs @@ -26,149 +26,10 @@ use core::iter; -use amplify::num::{u3, u5}; - -use super::{AluCore, Idx32, SiteId, Status}; - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -pub enum A { - #[display("A8")] - A8, - #[display("A16")] - A16, - #[display("A32")] - A32, - #[display("A64")] - A64, - #[display("A128")] - A128, -} - -impl From for A { - fn from(reg: u3) -> Self { - match reg.to_u8() { - 0 => A::A8, - 1 => A::A16, - 2 => A::A32, - 3 => A::A64, - 4 => A::A128, - _ => panic!( - "A registers above A128 are not supported under the current architecture. Consider using architecture \ - extension." - ), - } - } -} - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -pub enum RegA { - #[display("A8{0}")] - A8(IdxA), - #[display("A16{0}")] - A16(IdxA), - #[display("A32{0}")] - A32(IdxA), - #[display("A64{0}")] - A64(IdxA), - #[display("A128{0}")] - A128(IdxA), -} - -impl RegA { - pub fn with(a: A, idx: IdxA) -> Self { - match a { - A::A8 => Self::A8(idx), - A::A16 => Self::A16(idx), - A::A32 => Self::A32(idx), - A::A64 => Self::A64(idx), - A::A128 => Self::A128(idx), - } - } - - pub fn bytes(self) -> u16 { - match self { - RegA::A8(_) => 1, - RegA::A16(_) => 16, - RegA::A32(_) => 32, - RegA::A64(_) => 64, - RegA::A128(_) => 128, - } - } - - pub fn a(self) -> A { - match self { - RegA::A8(_) => A::A8, - RegA::A16(_) => A::A16, - RegA::A32(_) => A::A32, - RegA::A64(_) => A::A64, - RegA::A128(_) => A::A128, - } - } -} - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -#[display(inner)] -pub struct IdxA(Idx32); - -impl IdxA { - #[doc(hidden)] - pub(crate) fn from_expected(val: usize) -> Self { Self(Idx32::from_expected(val)) } -} - -impl From for IdxA { - fn from(idx: u5) -> Self { Self(Idx32::from(idx)) } -} - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] -#[display(inner)] -pub enum Reg { - #[from] - A(RegA), -} - -impl Reg { - pub fn bytes(self) -> u16 { - match self { - Reg::A(a) => a.bytes(), - } - } -} - -impl IdxA { - #[inline] - pub fn pos(&self) -> usize { self.0 as usize } -} - -/// Microcode for flag registers. -impl AluCore { - /// Read overflow/carry flag. - pub fn co(&self) -> bool { self.co } - - /// Set overflow/carry flag to a value. - pub fn set_co(&mut self, co: bool) { self.co = co } - - /// Return whether check register `ck` was set to a failed state for at least once. - pub fn ck(&self) -> Status { self.ck } - - /// Set `ck` register to a failed state. - pub fn fail_ck(&mut self) { self.ck = Status::Fail } - - /// Reset `ck` register. - pub fn reset_ck(&mut self) { self.ck = Status::Ok } - - /// Accumulate complexity value. - /// - /// # Returns - /// - /// Boolean indicating wheather complexity limit is reached. - pub fn acc_complexity(&mut self, complexity: u64) -> bool { - self.ca = self.ca.saturating_add(complexity); - self.cl().map(|lim| self.ca >= lim).unwrap_or_default() - } -} +use crate::core::{Core, IdxA, Reg, RegA, SiteId}; /// Microcode for arithmetic registers. -impl AluCore { +impl Core { pub fn get(&self, reg: Reg) -> Option { match reg { Reg::A(a) => match a { diff --git a/src/core/microcode/base.rs b/src/core/microcode/base.rs new file mode 100644 index 0000000..124dbf9 --- /dev/null +++ b/src/core/microcode/base.rs @@ -0,0 +1,216 @@ +// Reference rust implementation of AluVM (arithmetic logic unit virtual machine). +// To find more on AluVM please check +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2021-2024 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2021-2024 UBIDECO Labs, +// Laboratories for Distributed and Cognitive Computing, Switzerland. +// All rights reserved. +// +// 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 +// +// http://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. + +use core::fmt::Debug; + +use amplify::num::{u3, u4, u5}; + +use crate::core::{Core, Idx16, Idx32, SiteId, Status}; + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] +pub enum A { + #[display("A8")] + A8, + #[display("A16")] + A16, + #[display("A32")] + A32, + #[display("A64")] + A64, + #[display("A128")] + A128, +} + +impl A { + pub fn to_u3(&self) -> u3 { + match self { + A::A8 => u3::with(0), + A::A16 => u3::with(1), + A::A32 => u3::with(2), + A::A64 => u3::with(3), + A::A128 => u3::with(4), + } + } +} + +impl From for A { + fn from(reg: u3) -> Self { + match reg.to_u8() { + 0 => A::A8, + 1 => A::A16, + 2 => A::A32, + 3 => A::A64, + 4 => A::A128, + _ => panic!( + "A registers above A128 are not supported under the current architecture. Consider using architecture \ + extension." + ), + } + } +} + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] +pub enum RegA { + #[display("A8{0}")] + A8(IdxA), + #[display("A16{0}")] + A16(IdxA), + #[display("A32{0}")] + A32(IdxA), + #[display("A64{0}")] + A64(IdxA), + #[display("A128{0}")] + A128(IdxA), +} + +impl RegA { + pub fn with(a: A, idx: IdxA) -> Self { + match a { + A::A8 => Self::A8(idx), + A::A16 => Self::A16(idx), + A::A32 => Self::A32(idx), + A::A64 => Self::A64(idx), + A::A128 => Self::A128(idx), + } + } + + pub fn bytes(self) -> u16 { + match self { + RegA::A8(_) => 1, + RegA::A16(_) => 16, + RegA::A32(_) => 32, + RegA::A64(_) => 64, + RegA::A128(_) => 128, + } + } + + pub fn a(self) -> A { + match self { + RegA::A8(_) => A::A8, + RegA::A16(_) => A::A16, + RegA::A32(_) => A::A32, + RegA::A64(_) => A::A64, + RegA::A128(_) => A::A128, + } + } + + pub fn idx(self) -> IdxA { + match self { + RegA::A8(idx) => idx, + RegA::A16(idx) => idx, + RegA::A32(idx) => idx, + RegA::A64(idx) => idx, + RegA::A128(idx) => idx, + } + } + + pub fn to_u8(&self) -> u8 { + let a = self.a().to_u3().to_u8(); + let idx = self.idx().to_u5().to_u8(); + a << 5 + idx + } +} + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] +#[display(inner)] +pub struct IdxA(Idx32); + +impl IdxA { + #[doc(hidden)] + pub(crate) fn from_expected(val: usize) -> Self { Self(Idx32::from_expected(val)) } + + pub fn to_u5(&self) -> u5 { u5::with(self.0 as u8) } +} + +impl From for IdxA { + fn from(idx: u5) -> Self { Self(Idx32::from(idx)) } +} + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] +#[display(inner)] +pub struct IdxAl(Idx16); + +impl IdxAl { + #[allow(dead_code)] + #[doc(hidden)] + pub(crate) fn from_expected(val: usize) -> Self { Self(Idx16::from_expected(val)) } + + pub fn to_u4(&self) -> u4 { u4::with(self.0 as u8) } +} + +impl From for IdxA { + fn from(idx: IdxAl) -> IdxA { IdxA::from_expected(idx.0 as usize) } +} + +impl From for IdxAl { + fn from(idx: u4) -> Self { Self(Idx16::from(idx)) } +} + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] +#[display(inner)] +pub enum Reg { + #[from] + A(RegA), +} + +impl Reg { + pub fn bytes(self) -> u16 { + match self { + Reg::A(a) => a.bytes(), + } + } +} + +impl IdxA { + #[inline] + pub fn pos(&self) -> usize { self.0 as usize } +} + +/// Microcode for flag registers. +impl Core { + /// Read overflow/carry flag. + pub fn co(&self) -> bool { self.co } + + /// Set overflow/carry flag to a value. + pub fn set_co(&mut self, co: bool) { self.co = co } + + /// Return whether check register `ck` was set to a failed state for at least once. + pub fn ck(&self) -> Status { self.ck } + + /// Set `ck` register to a failed state. + pub fn fail_ck(&mut self) { self.ck = Status::Fail } + + /// Reset `ck` register. + pub fn reset_ck(&mut self) { self.ck = Status::Ok } + + /// Accumulate complexity value. + /// + /// # Returns + /// + /// Boolean indicating wheather complexity limit is reached. + pub fn acc_complexity(&mut self, complexity: u64) -> bool { + self.ca = self.ca.saturating_add(complexity); + self.cl().map(|lim| self.ca >= lim).unwrap_or_default() + } +} diff --git a/src/core/microcode/gfa.rs b/src/core/microcode/gfa.rs new file mode 100644 index 0000000..3543c89 --- /dev/null +++ b/src/core/microcode/gfa.rs @@ -0,0 +1,113 @@ +// Reference rust implementation of AluVM (arithmetic logic unit virtual machine). +// To find more on AluVM please check +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2021-2024 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2021-2024 UBIDECO Labs, +// Laboratories for Distributed and Cognitive Computing, Switzerland. +// All rights reserved. +// +// 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 +// +// http://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. + +use crate::core::SiteId; +use crate::Core; + +const M31: u128 = (1 << 31u128) - 1; +const F1137119: u128 = 1 + 11 * 37 * (1 << 119u128); +const F1289: u128 = u128::MAX - 8; // it should be 9, but `u128::MAX` is 2^128-1 and not 2^128 + +/// Finite field orders. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Display)] +pub enum Zp { + #[display("M31", alt = "2^31-1")] + M31, // 2^31-1 + #[display("F1137119", alt = "1+11*37*2^119")] + F1137119, + #[display("F1289", alt = "2^128-9")] + F1289, + #[display("{0:x}.h")] + Other(u128), +} + +impl From for u128 { + fn from(zp: Zp) -> Self { zp.to_u128() } +} + +impl Zp { + pub fn to_u128(self) -> u128 { + match self { + Zp::M31 => M31, + Zp::F1137119 => F1137119, + Zp::F1289 => F1289, + Zp::Other(val) => val, + } + } +} + +/// Microcode for finite field arithmetics. +impl Core { + pub fn zp(&self) -> Zp { self.zp } + pub fn zp_u128(&self) -> u128 { self.zp.to_u128() } + + #[inline] + pub fn add_mod(&mut self, a: u128, b: u128) -> Option { + let order = self.zp.to_u128(); + if a >= order || b >= order { + return None; + } + + let (mut res, overflow) = a.overflowing_add(b); + if overflow { + res += u128::MAX - order; + } + res %= order; + + self.set_co(overflow); + Some(res) + } + + #[inline] + pub fn mul_mod(&mut self, a: u128, b: u128) -> Option { + let order = self.zp.to_u128(); + if a >= order || b >= order { + return None; + } + + let (res, overflow) = self.mul_mod_int(a, b); + + self.set_co(overflow); + Some(res) + } + + fn mul_mod_int(&mut self, a: u128, b: u128) -> (u128, bool) { + let order = self.zp.to_u128(); + let (mut res, overflow) = a.overflowing_mul(b); + if overflow { + let rem = u128::MAX - order; + res = self.mul_mod_int(res, rem).0; + } + (res % order, overflow) + } + + #[inline] + pub fn neg_mod(&self, a: u128) -> Option { + let order = self.zp_u128(); + if a >= order { + return None; + } + Some(order - a) + } +} diff --git a/src/core/microcode/mod.rs b/src/core/microcode/mod.rs new file mode 100644 index 0000000..619e677 --- /dev/null +++ b/src/core/microcode/mod.rs @@ -0,0 +1,30 @@ +// Reference rust implementation of AluVM (arithmetic logic unit virtual machine). +// To find more on AluVM please check +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2021-2024 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2021-2024 UBIDECO Labs, +// Laboratories for Distributed and Cognitive Computing, Switzerland. +// All rights reserved. +// +// 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 +// +// http://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. + +#[cfg(feature = "GFA")] +pub mod gfa; +mod alu128; +mod base; + +pub use base::{IdxA, IdxAl, Reg, RegA, A}; diff --git a/src/core/mod.rs b/src/core/mod.rs index 9ffc457..4698f22 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -28,6 +28,7 @@ mod core; mod microcode; mod regs; -pub use self::core::{AluCore, CoreConfig, Site, SiteId, Status, CALL_STACK_SIZE_MAX}; -pub use self::microcode::{IdxA, Reg, RegA, A}; -pub(self) use self::regs::Idx32; +pub use self::core::{Core, CoreConfig, CALL_STACK_SIZE_MAX}; +pub use self::microcode::{gfa, IdxA, IdxAl, Reg, RegA, A}; +pub(self) use self::regs::{Idx16, Idx32}; +pub use self::regs::{Site, SiteId, Status}; diff --git a/src/core/regs.rs b/src/core/regs.rs index 94b37b3..0715ed0 100644 --- a/src/core/regs.rs +++ b/src/core/regs.rs @@ -22,7 +22,42 @@ // See the License for the specific language governing permissions and // limitations under the License. -use amplify::num::u5; +use core::fmt::{self, Debug, Display, Formatter}; +use core::str::FromStr; + +use amplify::num::{u4, u5}; + +#[derive(Copy, Clone, Eq, PartialEq, Debug, Display)] +#[repr(i8)] +pub enum Status { + #[display("ok")] + Ok = 0, + + #[display("fail")] + Fail = -1, +} + +impl Status { + pub fn is_ok(self) -> bool { self == Status::Ok } +} + +pub trait SiteId: Copy + Ord + Debug + Display + FromStr {} + +/// Location inside the instruction sequence which can be executed by the core. +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +pub struct Site { + pub prog_id: Id, + pub offset: u16, +} + +impl Site { + #[inline] + pub fn new(prog_id: Id, offset: u16) -> Self { Self { prog_id, offset } } +} + +impl Display for Site { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}:{:04X}.h", self.prog_id, self.offset) } +} #[allow(dead_code)] #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] @@ -63,6 +98,47 @@ pub(super) enum Idx16 { F = 0xF, } +impl Idx16 { + pub const ALL: [Self; 16] = [ + Self::L1, + Self::L2, + Self::L3, + Self::L4, + Self::L5, + Self::L6, + Self::L7, + Self::L8, + Self::L9, + Self::L10, + Self::A, + Self::B, + Self::C, + Self::D, + Self::E, + Self::F, + ]; + + pub(super) fn from_expected(val: usize) -> Self { + for i in Self::ALL { + if i as usize == val { + return i; + } + } + panic!("invalid 4-bit integer index represented in a usize value") + } +} + +impl From for Idx16 { + fn from(idx: u4) -> Self { + for i in Self::ALL { + if i as u8 == idx.to_u8() { + return i; + } + } + unreachable!() + } +} + #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] #[repr(u8)] pub(super) enum Idx32 { diff --git a/src/isa/alu/exec.rs b/src/isa/alu/exec.rs index ed9bfa3..c9b7de7 100644 --- a/src/isa/alu/exec.rs +++ b/src/isa/alu/exec.rs @@ -25,7 +25,7 @@ use std::collections::BTreeSet; use super::{CtrlInstr, RegInstr}; -use crate::core::{AluCore, Reg, Site, SiteId}; +use crate::core::{Core, Reg, Site, SiteId}; use crate::isa::{ExecStep, Instr, Instruction, InstructionSet, ReservedInstr}; impl> Instruction for Instr { @@ -35,13 +35,11 @@ impl> Instruction for Instr { fn dst_regs(&self) -> BTreeSet { todo!() } - fn op_data_size(&self) -> u16 { todo!() } + fn op_data_bytes(&self) -> u16 { todo!() } - fn ext_data_size(&self) -> u16 { todo!() } + fn ext_data_bytes(&self) -> u16 { todo!() } - fn exec(&self, core: &mut AluCore, site: Site, context: &Self::Context<'_>) -> ExecStep> { - todo!() - } + fn exec(&self, core: &mut Core, site: Site, context: &Self::Context<'_>) -> ExecStep> { todo!() } } impl Instruction for ReservedInstr { @@ -51,13 +49,11 @@ impl Instruction for ReservedInstr { fn dst_regs(&self) -> BTreeSet { todo!() } - fn op_data_size(&self) -> u16 { todo!() } + fn op_data_bytes(&self) -> u16 { todo!() } - fn ext_data_size(&self) -> u16 { todo!() } + fn ext_data_bytes(&self) -> u16 { todo!() } - fn exec(&self, core: &mut AluCore, site: Site, context: &Self::Context<'_>) -> ExecStep> { - todo!() - } + fn exec(&self, core: &mut Core, site: Site, context: &Self::Context<'_>) -> ExecStep> { todo!() } } impl Instruction for CtrlInstr { @@ -67,13 +63,11 @@ impl Instruction for CtrlInstr { fn dst_regs(&self) -> BTreeSet { todo!() } - fn op_data_size(&self) -> u16 { todo!() } + fn op_data_bytes(&self) -> u16 { todo!() } - fn ext_data_size(&self) -> u16 { todo!() } + fn ext_data_bytes(&self) -> u16 { todo!() } - fn exec(&self, core: &mut AluCore, site: Site, context: &Self::Context<'_>) -> ExecStep> { - todo!() - } + fn exec(&self, core: &mut Core, site: Site, context: &Self::Context<'_>) -> ExecStep> { todo!() } } impl Instruction for RegInstr { @@ -83,11 +77,9 @@ impl Instruction for RegInstr { fn dst_regs(&self) -> BTreeSet { todo!() } - fn op_data_size(&self) -> u16 { todo!() } + fn op_data_bytes(&self) -> u16 { todo!() } - fn ext_data_size(&self) -> u16 { todo!() } + fn ext_data_bytes(&self) -> u16 { todo!() } - fn exec(&self, core: &mut AluCore, site: Site, context: &Self::Context<'_>) -> ExecStep> { - todo!() - } + fn exec(&self, core: &mut Core, site: Site, context: &Self::Context<'_>) -> ExecStep> { todo!() } } diff --git a/src/isa/bytecode.rs b/src/isa/bytecode.rs index e282f29..e3f2495 100644 --- a/src/isa/bytecode.rs +++ b/src/isa/bytecode.rs @@ -51,7 +51,9 @@ pub trait Bytecode { fn encode_instr(&self, writer: &mut W) -> Result<(), W::Error> where W: BytecodeWrite { writer.write_u8(self.opcode_byte())?; - self.encode_operands(writer) + self.encode_operands(writer)?; + writer.check_aligned(); + Ok(()) } /// Writes an instruction operands as bytecode, omitting opcode byte. @@ -65,7 +67,9 @@ pub trait Bytecode { R: BytecodeRead, { let opcode = reader.read_u8()?; - Self::decode_operands(reader, opcode) + let instr = Self::decode_operands(reader, opcode)?; + reader.check_aligned(); + Ok(instr) } /// Reads an instruction operands from bytecode, provided the opcode byte. @@ -150,6 +154,13 @@ pub trait BytecodeRead { /// Read external reference id. fn read_ref(&mut self) -> Result where Id: Sized; + + /// Check if the current cursor position is aligned to the next byte. + /// + /// # Panics + /// + /// If the position is not aligned, panics. + fn check_aligned(&self); } /// Writer converting instructions into a bytecode. @@ -189,4 +200,11 @@ pub trait BytecodeWrite { /// Write external reference id. fn write_ref(&mut self, id: Id) -> Result<(), Self::Error>; + + /// Check if the current cursor position is aligned to the next byte. + /// + /// # Panics + /// + /// If the position is not aligned, panics. + fn check_aligned(&self); } diff --git a/src/isa/gfa/bytecode.rs b/src/isa/gfa/bytecode.rs index 7ba6862..b3262ba 100644 --- a/src/isa/gfa/bytecode.rs +++ b/src/isa/gfa/bytecode.rs @@ -24,6 +24,8 @@ use std::ops::RangeInclusive; +use amplify::num::u1; + use super::FieldInstr; use crate::core::SiteId; use crate::isa::{Bytecode, BytecodeRead, BytecodeWrite, CodeEofError}; @@ -35,7 +37,34 @@ impl Bytecode for FieldInstr { fn encode_operands(&self, writer: &mut W) -> Result<(), W::Error> where W: BytecodeWrite { - todo!() + match *self { + FieldInstr::IncMod { src_dst, val } => { + writer.write_u8(src_dst.to_u8())?; + writer.write_u8(val)?; + } + FieldInstr::DecMod { src_dst, val } => { + writer.write_u8(src_dst.to_u8())?; + writer.write_u8(val)?; + } + FieldInstr::NegMod { src_dst } => { + writer.write_u8(src_dst.to_u8())?; + } + FieldInstr::AddMod { reg, dst, src1, src2 } => { + writer.write_u1(u1::ZERO)?; + writer.write_u3(reg.to_u3())?; + writer.write_u4(dst.to_u4())?; + writer.write_u4(src1.to_u4())?; + writer.write_u4(src2.to_u4())?; + } + FieldInstr::MulMod { reg, dst, src1, src2 } => { + writer.write_u1(u1::ONE)?; + writer.write_u3(reg.to_u3())?; + writer.write_u4(dst.to_u4())?; + writer.write_u4(src1.to_u4())?; + writer.write_u4(src2.to_u4())?; + } + } + Ok(()) } fn decode_operands(reader: &mut R, opcode: u8) -> Result diff --git a/src/isa/gfa/exec.rs b/src/isa/gfa/exec.rs index a46b7dc..7268eee 100644 --- a/src/isa/gfa/exec.rs +++ b/src/isa/gfa/exec.rs @@ -27,20 +27,14 @@ use std::collections::BTreeSet; use super::FieldInstr; use crate::core::{Reg, RegA, SiteId}; use crate::isa::{ExecStep, Instruction}; -use crate::{AluCore, Site}; +use crate::{Core, Site}; macro_rules! A { - [$reg:ident @ $core:ident] => {{ - let Some(val) = $core.a($reg) else { - return ExecStep::NextFail; - }; - val - }}; + [$reg:ident @ $core:ident] => { + checked!($core.a($reg)) + }; [$a:ident : $idx:ident @ $core:ident] => {{ - let Some(val) = $core.a(RegA::with($a.a(), $idx)) else { - return ExecStep::NextFail; - }; - val + checked!($core.a(RegA::with($a, $idx.into()))) }}; } @@ -52,6 +46,15 @@ macro_rules! check { }}; } +macro_rules! checked { + ($core:ident . $op:ident($($arg:expr),*)) => {{ + let Some(val) = $core.$op( $( $arg ),* ) else { + return ExecStep::NextFail; + }; + val + }}; +} + impl Instruction for FieldInstr { type Context<'ctx> = (); @@ -59,76 +62,47 @@ impl Instruction for FieldInstr { fn dst_regs(&self) -> BTreeSet { todo!() } - fn op_data_size(&self) -> u16 { todo!() } + fn op_data_bytes(&self) -> u16 { todo!() } - fn ext_data_size(&self) -> u16 { todo!() } + fn ext_data_bytes(&self) -> u16 { todo!() } - fn exec(&self, core: &mut AluCore, site: Site, context: &Self::Context<'_>) -> ExecStep> { - #[inline] - fn add_mod(a: u128, b: u128, order: impl Into) -> Option<(u128, bool)> { - let order = order.into(); - if a >= order || b >= order { - return None; - } - let (mut res, overflow) = a.overflowing_add(b); - if overflow { - res = res + u128::MAX - order; - } - Some((res, overflow)) - } + fn complexity(&self) -> u64 { + // Double the default complexity since each instruction performs two operations (and each arithmetic + // operations is x10 of move operation). + Instruction::::base_complexity(self) * 20 + } + fn exec(&self, core: &mut Core, site: Site, context: &Self::Context<'_>) -> ExecStep> { match *self { - FieldInstr::IncMod { src_dst, val, order } => { + FieldInstr::IncMod { src_dst, val } => { let src = A![src_dst @ core]; - let res = add_mod(src, val as u128, order); - let Some((res, overflow)) = res else { - return ExecStep::NextFail; - }; - core.set_co(overflow); + let val = val as u128; + let res = checked!(core.add_mod(src, val)); core.set_a(src_dst, res); } - FieldInstr::DecMod { src_dst, val, order } => { + FieldInstr::DecMod { src_dst, val } => { let src = A![src_dst @ core]; - // negate val - let val = order.to_u128() - val as u128; - let res = add_mod(src, val, order); - let Some((res, overflow)) = res else { - return ExecStep::NextFail; - }; - core.set_co(overflow); + let val = val as u128; + let val = checked!(core.neg_mod(val)); + let res = checked!(core.add_mod(src, val)); core.set_a(src_dst, res); } - FieldInstr::AddMod { src_dst, src, order } => { - let src1 = A![src_dst @ core]; - let src2 = A![src_dst : src @ core]; - let res = add_mod(src1, src2, order); - let Some((res, overflow)) = res else { - return ExecStep::NextFail; - }; - core.set_co(overflow); + FieldInstr::NegMod { src_dst } => { + let src = A![src_dst @ core]; + let res = checked!(core.neg_mod(src)); core.set_a(src_dst, res); } - FieldInstr::NegMod { dst, src, order } => { - let src = A![dst : src @ core]; - let order = order.to_u128(); - check!(src < order); - core.set_a(dst, order - src); + FieldInstr::AddMod { reg, dst, src1, src2 } => { + let src1 = A![reg : src1 @ core]; + let src2 = A![reg : src2 @ core]; + let res = checked!(core.add_mod(src1, src2)); + core.set_a(RegA::with(reg, dst.into()), res); } - FieldInstr::MulMod { src_dst, src, order } => { - let src1 = A![src_dst @ core]; - let src2 = A![src_dst : src @ core]; - - // negate src2 - let order = order.to_u128(); - check!(src2 < order); - let src2 = order - src2; - - let res = add_mod(src1, src2, order); - let Some((res, overflow)) = res else { - return ExecStep::NextFail; - }; - core.set_co(overflow); - core.set_a(src_dst, res); + FieldInstr::MulMod { reg, dst, src1, src2 } => { + let src1 = A![reg : src1 @ core]; + let src2 = A![reg : src2 @ core]; + let res = checked!(core.mul_mod(src1, src2)); + core.set_a(RegA::with(reg, dst.into()), res); } } ExecStep::Next diff --git a/src/isa/gfa/instr.rs b/src/isa/gfa/instr.rs index 922c0a6..1fac56b 100644 --- a/src/isa/gfa/instr.rs +++ b/src/isa/gfa/instr.rs @@ -22,39 +22,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::core::{IdxA, RegA}; - -const M31: u128 = (1 << 31u128) - 1; -const F1137119: u128 = 1 + 11 * 37 * (1 << 119u128); -const F1289: u128 = u128::MAX - 8; // it should be 9, but `u128::MAX` is 2^128-1 and not 2^128 - -/// Finite field orders. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Display)] -pub enum Zp { - #[display("M31", alt = "2^31-1")] - M31, // 2^31-1 - #[display("F1137119", alt = "1+11*37*2^119")] - F1137119, - #[display("F1289", alt = "2^128-9")] - F1289, - #[display("{0:x}.h")] - Other(u128), -} - -impl From for u128 { - fn from(zp: Zp) -> Self { zp.to_u128() } -} - -impl Zp { - pub fn to_u128(self) -> u128 { - match self { - Zp::M31 => M31, - Zp::F1137119 => F1137119, - Zp::F1289 => F1289, - Zp::Other(val) => val, - } - } -} +use crate::core::{IdxAl, RegA, A}; /// Arithmetic instructions for finite fields. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Display)] @@ -62,52 +30,43 @@ impl Zp { #[non_exhaustive] pub enum FieldInstr { /// Increment register value using finite-field (modulo) arithmetics of the `order`. - #[display("incmod {src_dst}, {val}, {order}")] + #[display("incmod {src_dst}, {val}")] IncMod { /// Destination register. src_dst: RegA, /// Value to add. val: u8, - /// Order of the finite field. - order: Zp, }, /// Decrement register value using finite-field (modulo) arithmetics of the `order`. - #[display("decmod {src_dst}, {val}, {order}")] + #[display("decmod {src_dst}, {val}")] DecMod { /// Destination register. src_dst: RegA, /// Value to add. val: u8, - /// Order of the finite field. - order: Zp, }, + /// Negate value using finite-field arithmetics. + #[display("negmod {src_dst}")] + NegMod { src_dst: RegA }, + /// Add `src` value to `src_dst` value using finite-field (modulo) arithmetics of the `order`. - #[display("addmod {src_dst}, {src}, {order}")] + #[display("addmod {reg}{dst}, {reg}{src1}, {reg}{src2}")] AddMod { - src_dst: RegA, - src: IdxA, - /// Order of the finite field. - order: Zp, - }, - - /// Negate value using finite-field arithmetics. - #[display("negmod {dst}, {src}, {order}")] - NegMod { - dst: RegA, - src: IdxA, - /// Order of the finite field. - order: Zp, + reg: A, + dst: IdxAl, + src1: IdxAl, + src2: IdxAl, }, /// Multiply `src` value to `src_dst` value using finite-field (modulo) arithmetics of the /// `order`. - #[display("mulmod {src_dst}, {src}, {order}")] + #[display("mulmod {reg}{dst}, {reg}{src1}, {reg}{src2}")] MulMod { - src_dst: RegA, - src: IdxA, - /// Order of the finite field. - order: Zp, + reg: A, + dst: IdxAl, + src1: IdxAl, + src2: IdxAl, }, } diff --git a/src/isa/gfa/mod.rs b/src/isa/gfa/mod.rs index 2fea66c..839a481 100644 --- a/src/isa/gfa/mod.rs +++ b/src/isa/gfa/mod.rs @@ -28,4 +28,4 @@ mod instr; mod bytecode; mod exec; -pub use instr::{FieldInstr, Zp}; +pub use instr::FieldInstr; diff --git a/src/isa/instr.rs b/src/isa/instr.rs index 0d25cbd..7344217 100644 --- a/src/isa/instr.rs +++ b/src/isa/instr.rs @@ -22,9 +22,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::fmt::{Debug, Display}; use std::collections::BTreeSet; -use crate::core::{AluCore, Reg, Site, SiteId}; +use crate::core::{Core, Reg, Site, SiteId}; /// Turing machine movement after instruction execution #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -49,7 +50,7 @@ pub enum ExecStep { } /// Trait for instructions -pub trait Instruction: core::fmt::Display + core::fmt::Debug { +pub trait Instruction: Display + Debug { /// Context: external data which are accessible to the ISA. type Context<'ctx>; @@ -66,28 +67,34 @@ pub trait Instruction: core::fmt::Display + core::fmt::Debug { /// List of registers which value may be changed by the instruction. fn dst_regs(&self) -> BTreeSet; + /// The number of bytes in the source registers. + fn src_reg_bytes(&self) -> u16 { self.src_regs().into_iter().map(Reg::bytes).sum() } + + /// The number of bytes in the destination registers. + fn dst_reg_bytes(&self) -> u16 { self.dst_regs().into_iter().map(Reg::bytes).sum() } + /// The size of the data coming as an instruction operands (i.e. except data coming from /// registers or read from outside the instruction operands). - fn op_data_size(&self) -> u16; + fn op_data_bytes(&self) -> u16; /// The size of the data read by the instruction from outside the registers (except data coming /// as a parameter). - fn ext_data_size(&self) -> u16; + fn ext_data_bytes(&self) -> u16; + + fn base_complexity(&self) -> u64 { + (self.op_data_bytes() as u64 // 1k of complexity units per input bit + + self.src_reg_bytes() as u64 * 10 // 10k of complexity units per input bit + + self.dst_reg_bytes() as u64 * 10 // 10k of complexity units per output bit + + self.ext_data_bytes() as u64 * 100) // x10 complexity units per byte of external + // memory + * 8 // per bit + * 1000 // by default use large unit + } /// Returns computational complexity of the instruction. /// /// Computational complexity is the number of "CPU ticks" required to process the instruction. - fn complexity(&self) -> u64 { - // By default, give the upper estimate - self.op_data_size() as u64 * 8_000 // 1k of complexity units per input bit - + self.src_regs() - .iter() - .chain(&self.dst_regs()) - .map(|reg| reg.bytes() as u64) - .sum::() - * 80_000 // 10k of complexity units per input and output bit - + self.ext_data_size() as u64 * 800_000 // x10 complexity units per byte of external memory - } + fn complexity(&self) -> u64 { self.base_complexity() } /// Executes given instruction taking all registers as input and output. /// @@ -99,5 +106,5 @@ pub trait Instruction: core::fmt::Display + core::fmt::Debug { /// # Returns /// /// Returns whether further execution should be stopped. - fn exec(&self, core: &mut AluCore, site: Site, context: &Self::Context<'_>) -> ExecStep>; + fn exec(&self, core: &mut Core, site: Site, context: &Self::Context<'_>) -> ExecStep>; } diff --git a/src/isa/mod.rs b/src/isa/mod.rs index 3233976..6b40e07 100644 --- a/src/isa/mod.rs +++ b/src/isa/mod.rs @@ -29,10 +29,12 @@ mod bytecode; mod arch; mod alu; +#[cfg(feature = "GFA")] mod gfa; pub use alu::{CtrlInstr, RegInstr}; pub use arch::{Instr, InstructionSet, IsaId, ReservedInstr, ISA_ALU64, ISA_AN, ISA_ID_MAX_LEN}; pub use bytecode::{Bytecode, BytecodeRead, BytecodeWrite, CodeEofError}; -pub use gfa::{FieldInstr, Zp}; +#[cfg(feature = "GFA")] +pub use gfa::FieldInstr; pub use instr::{ExecStep, Instruction}; diff --git a/src/lib.rs b/src/lib.rs index 2636622..d632995 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,6 +134,10 @@ //! //! [AluVM]: https://github.com/AluVM/aluvm-spec +// TODO: Extend the list of features not compatible with zk-aluvm as they appear. +#[cfg(all(feature = "zk-aluvm", any(feature = "A64", feature = "STR")))] +compile_error!("zk-AluVM is incompatible with any ISA extensions other then GFA"); + #[macro_use] extern crate amplify; #[macro_use] @@ -164,4 +168,4 @@ pub use library::{Lib, LibId, LibSite}; pub use paste::paste; pub use vm::Vm; -pub use self::core::{AluCore, Site, CALL_STACK_SIZE_MAX}; +pub use self::core::{Core, Site, CALL_STACK_SIZE_MAX}; diff --git a/src/library/exec.rs b/src/library/exec.rs index 2be30cc..f88b549 100644 --- a/src/library/exec.rs +++ b/src/library/exec.rs @@ -26,7 +26,7 @@ use baid64::DisplayBaid64; use super::{Lib, Marshaller}; use crate::isa::{Bytecode, BytecodeRead, ExecStep, Instruction}; -use crate::{AluCore, LibId, LibSite, Site}; +use crate::{Core, LibId, LibSite, Site}; impl Lib { /// Execute library code starting at entrypoint. @@ -37,7 +37,7 @@ impl Lib { pub fn exec( &self, entrypoint: u16, - registers: &mut AluCore, + registers: &mut Core, context: &Instr::Context<'_>, ) -> Option where diff --git a/src/library/marshaller.rs b/src/library/marshaller.rs index ee1fafd..7ab5401 100644 --- a/src/library/marshaller.rs +++ b/src/library/marshaller.rs @@ -341,7 +341,10 @@ where let pos = self.read_u8()? as usize; Ok(self.libs.iter().nth(pos).copied().unwrap_or_default()) } + + fn check_aligned(&self) { debug_assert_eq!(self.bit_pos, u3::ZERO, "not all instruction operands are read") } } + impl<'a, C, D> BytecodeWrite for Marshaller<'a, C, D> where C: AsRef<[u8]> + AsMut<[u8]>, @@ -421,6 +424,8 @@ where .ok_or(MarshallError::LibAbsent(id))?; self.write_u8(pos as u8) } + + fn check_aligned(&self) { debug_assert_eq!(self.bit_pos, u3::ZERO, "not all instruction operands are written") } } #[cfg(test)] diff --git a/src/vm.rs b/src/vm.rs index f435621..ebbdf79 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -26,7 +26,7 @@ use core::marker::PhantomData; -use crate::core::{AluCore, CoreConfig, Status}; +use crate::core::{Core, CoreConfig, Status}; use crate::isa::{Bytecode, Instr, Instruction, InstructionSet, ReservedInstr}; use crate::library::{Lib, LibId, LibSite}; @@ -36,7 +36,7 @@ pub struct Vm> where Isa: InstructionSet { /// A set of registers - pub registers: AluCore, + pub registers: Core, phantom: PhantomData, } @@ -48,7 +48,7 @@ where Isa: InstructionSet /// Constructs new virtual machine instance with default core configuration. pub fn new() -> Self { Self { - registers: AluCore::new(), + registers: Core::new(), phantom: Default::default(), } } @@ -56,7 +56,7 @@ where Isa: InstructionSet /// Constructs new virtual machine instance with default core configuration. pub fn with(config: CoreConfig) -> Self { Self { - registers: AluCore::with(config), + registers: Core::with(config), phantom: Default::default(), } }