Skip to content

Commit

Permalink
zkaluvm: complete initial GPA implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Oct 21, 2024
1 parent 4ce41df commit e313223
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 28 deletions.
12 changes: 6 additions & 6 deletions src/core/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use core::fmt::{self, Debug, Formatter};

use super::{Site, SiteId, Status};
#[cfg(feature = "GFA")]
use crate::core::gfa::Zp;
use crate::core::gfa::Fq;

/// Maximal size of call stack.
///
Expand All @@ -38,7 +38,7 @@ pub const CALL_STACK_SIZE_MAX: u16 = 0xFF;
pub struct Core<Id: SiteId> {
#[cfg(feature = "GFA")]
/// Finite field order.
pub(super) zp: Zp,
pub(super) fq: Fq,

// ============================================================================================
// Arithmetic integer registers (ALU64 ISA).
Expand Down Expand Up @@ -161,15 +161,15 @@ pub struct CoreConfig {
pub call_stack_size: u16,
#[cfg(feature = "GFA")]
/// Order of the finite field for modulo arithmetics.
pub field_order: Zp,
pub field_order: Fq,
}

impl Default for CoreConfig {
/// 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).
/// - [`CoreConfig::field_order`] to [`Fq::F1137119`] (if `GFA` feature is set).
///
/// # See also
///
Expand All @@ -183,7 +183,7 @@ impl Default for CoreConfig {
complexity_lim: None,
call_stack_size: CALL_STACK_SIZE_MAX,
#[cfg(feature = "GFA")]
field_order: Zp::F1137119,
field_order: Fq::F1137119,
}
}
}
Expand All @@ -200,7 +200,7 @@ impl<Id: SiteId> Core<Id> {
pub fn with(config: CoreConfig) -> Self {
Core {
#[cfg(feature = "GFA")]
zp: config.field_order,
fq: config.field_order,
a8: Default::default(),
a16: Default::default(),
a32: Default::default(),
Expand Down
8 changes: 8 additions & 0 deletions src/core/microcode/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ impl RegA {
}
}

impl From<u8> for RegA {
fn from(val: u8) -> Self {
let a = u3::with(val >> 5);
let idx = u5::with(val & 0x1F);
RegA::with(A::from(a), IdxA::from(idx))
}
}

#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
#[display(inner)]
pub struct IdxA(Idx32);
Expand Down
28 changes: 14 additions & 14 deletions src/core/microcode/gfa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const F1289: u128 = u128::MAX - 8; // it should be 9, but `u128::MAX` is 2^128-1

/// Finite field orders.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Display)]
pub enum Zp {
pub enum Fq {
#[display("M31", alt = "2^31-1")]
M31, // 2^31-1
#[display("F1137119", alt = "1+11*37*2^119")]
Expand All @@ -42,29 +42,29 @@ pub enum Zp {
Other(u128),
}

impl From<Zp> for u128 {
fn from(zp: Zp) -> Self { zp.to_u128() }
impl From<Fq> for u128 {
fn from(fq: Fq) -> Self { fq.to_u128() }
}

impl Zp {
impl Fq {
pub fn to_u128(self) -> u128 {
match self {
Zp::M31 => M31,
Zp::F1137119 => F1137119,
Zp::F1289 => F1289,
Zp::Other(val) => val,
Fq::M31 => M31,
Fq::F1137119 => F1137119,
Fq::F1289 => F1289,
Fq::Other(val) => val,
}
}
}

/// Microcode for finite field arithmetics.
impl<Id: SiteId> Core<Id> {
pub fn zp(&self) -> Zp { self.zp }
pub fn zp_u128(&self) -> u128 { self.zp.to_u128() }
pub fn fq(&self) -> Fq { self.fq }
pub fn fq_u128(&self) -> u128 { self.fq.to_u128() }

#[inline]
pub fn add_mod(&mut self, a: u128, b: u128) -> Option<u128> {
let order = self.zp.to_u128();
let order = self.fq.to_u128();
if a >= order || b >= order {
return None;
}
Expand All @@ -81,7 +81,7 @@ impl<Id: SiteId> Core<Id> {

#[inline]
pub fn mul_mod(&mut self, a: u128, b: u128) -> Option<u128> {
let order = self.zp.to_u128();
let order = self.fq.to_u128();
if a >= order || b >= order {
return None;
}
Expand All @@ -93,7 +93,7 @@ impl<Id: SiteId> Core<Id> {
}

fn mul_mod_int(&mut self, a: u128, b: u128) -> (u128, bool) {
let order = self.zp.to_u128();
let order = self.fq.to_u128();
let (mut res, overflow) = a.overflowing_mul(b);
if overflow {
let rem = u128::MAX - order;
Expand All @@ -104,7 +104,7 @@ impl<Id: SiteId> Core<Id> {

#[inline]
pub fn neg_mod(&self, a: u128) -> Option<u128> {
let order = self.zp_u128();
let order = self.fq.to_u128();
if a >= order {
return None;
}
Expand Down
53 changes: 49 additions & 4 deletions src/isa/gfa/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,30 @@ use std::ops::RangeInclusive;
use amplify::num::u1;

use super::FieldInstr;
use crate::core::SiteId;
use crate::core::{IdxAl, RegA, SiteId, A};
use crate::isa::{Bytecode, BytecodeRead, BytecodeWrite, CodeEofError};

impl FieldInstr {
const START: u8 = 64;
const END: u8 = Self::START + Self::ADD_MUL;
const INC_MOD: u8 = 0;
const DEC_MOD: u8 = 1;
const NEG_MOD: u8 = 2;
const ADD_MUL: u8 = 3;
}

impl<Id: SiteId> Bytecode<Id> for FieldInstr {
fn op_range() -> RangeInclusive<u8> { todo!() }
fn op_range() -> RangeInclusive<u8> { Self::START..=Self::END }

fn opcode_byte(&self) -> u8 { todo!() }
fn opcode_byte(&self) -> u8 {
Self::START
+ match *self {
FieldInstr::IncMod { .. } => Self::INC_MOD,
FieldInstr::DecMod { .. } => Self::DEC_MOD,
FieldInstr::NegMod { .. } => Self::NEG_MOD,
FieldInstr::AddMod { .. } | FieldInstr::MulMod { .. } => Self::ADD_MUL,
}
}

fn encode_operands<W>(&self, writer: &mut W) -> Result<(), W::Error>
where W: BytecodeWrite<Id> {
Expand Down Expand Up @@ -72,6 +89,34 @@ impl<Id: SiteId> Bytecode<Id> for FieldInstr {
Self: Sized,
R: BytecodeRead<Id>,
{
todo!()
Ok(match opcode - Self::START {
Self::INC_MOD => {
let src_dst = RegA::from(reader.read_u8()?);
let val = reader.read_u8()?;
FieldInstr::IncMod { src_dst, val }
}
Self::DEC_MOD => {
let src_dst = RegA::from(reader.read_u8()?);
let val = reader.read_u8()?;
FieldInstr::IncMod { src_dst, val }
}
Self::NEG_MOD => {
let src_dst = RegA::from(reader.read_u8()?);
FieldInstr::NegMod { src_dst }
}
Self::ADD_MUL => {
let subop = reader.read_u1()?;
let reg = A::from(reader.read_u3()?);
let dst = IdxAl::from(reader.read_u4()?);
let src1 = IdxAl::from(reader.read_u4()?);
let src2 = IdxAl::from(reader.read_u4()?);
match subop {
u1::ZERO => FieldInstr::AddMod { reg, dst, src1, src2 },
u1::ONE => FieldInstr::MulMod { reg, dst, src1, src2 },
_ => unreachable!(),
}
}
_ => unreachable!(),
})
}
}
53 changes: 49 additions & 4 deletions src/isa/gfa/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,58 @@ macro_rules! checked {
impl<Id: SiteId> Instruction<Id> for FieldInstr {
type Context<'ctx> = ();

fn src_regs(&self) -> BTreeSet<Reg> { todo!() }
fn src_regs(&self) -> BTreeSet<Reg> {
match *self {
FieldInstr::IncMod { src_dst, val: _ }
| FieldInstr::DecMod { src_dst, val: _ }
| FieldInstr::NegMod { src_dst } => {
bset![src_dst.into()]
}
FieldInstr::AddMod {
reg,
dst,
src1: _,
src2: _,
}
| FieldInstr::MulMod {
reg,
dst,
src1: _,
src2: _,
} => bset![RegA::with(reg, dst.into()).into()],
}
}

fn dst_regs(&self) -> BTreeSet<Reg> { todo!() }
fn dst_regs(&self) -> BTreeSet<Reg> {
match *self {
FieldInstr::IncMod { src_dst, val: _ }
| FieldInstr::DecMod { src_dst, val: _ }
| FieldInstr::NegMod { src_dst } => {
bset![src_dst.into()]
}
FieldInstr::AddMod {
reg,
dst: _,
src1,
src2,
}
| FieldInstr::MulMod {
reg,
dst: _,
src1,
src2,
} => bset![RegA::with(reg, src1.into()).into(), RegA::with(reg, src2.into()).into()],
}
}

fn op_data_bytes(&self) -> u16 { todo!() }
fn op_data_bytes(&self) -> u16 {
match self {
FieldInstr::IncMod { .. } | FieldInstr::DecMod { .. } => 1,
FieldInstr::NegMod { .. } | FieldInstr::AddMod { .. } | FieldInstr::MulMod { .. } => 0,
}
}

fn ext_data_bytes(&self) -> u16 { todo!() }
fn ext_data_bytes(&self) -> u16 { 0 }

fn complexity(&self) -> u64 {
// Double the default complexity since each instruction performs two operations (and each arithmetic
Expand Down

0 comments on commit e313223

Please sign in to comment.