Skip to content

Commit

Permalink
Start implementing interop readback again
Browse files Browse the repository at this point in the history
  • Loading branch information
edusporto committed May 31, 2024
1 parent 7e547e0 commit 0e9c596
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 11 deletions.
6 changes: 3 additions & 3 deletions src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use TSPL::{new_parser, Parser};
use highlight_error::highlight_error;
use crate::hvm;
use crate::{hvm, interop};
use std::{collections::BTreeMap, fmt::{Debug, Display}};

// Types
Expand Down Expand Up @@ -344,7 +344,7 @@ impl Book {
// --------

impl Tree {
pub fn readback(net: &hvm::GNet, port: hvm::Port, fids: &BTreeMap<hvm::Val, String>) -> Option<Tree> {
pub fn readback<N: interop::NetReadback>(net: &N, port: hvm::Port, fids: &BTreeMap<hvm::Val, String>) -> Option<Tree> {
//println!("reading {}", port.show());
match port.get_tag() {
hvm::VAR => {
Expand Down Expand Up @@ -396,7 +396,7 @@ impl Tree {
}

impl Net {
pub fn readback(net: &hvm::GNet, book: &hvm::Book) -> Option<Net> {
pub fn readback<N: interop::NetReadback>(net: &N, book: &hvm::Book) -> Option<Net> {
let mut fids = BTreeMap::new();
for (fid, def) in book.defs.iter().enumerate() {
fids.insert(fid as hvm::Val, def.name.clone());
Expand Down
15 changes: 10 additions & 5 deletions src/hvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2110,8 +2110,7 @@ void pretty_print_port(Net* net, Book* book, Port port) {

// Main
// ----

void hvm_c(u32* book_buffer) {
void hvm_c(u32* book_buffer, Net* net_buffer) {
// Creates static TMs
alloc_static_tms();

Expand All @@ -2127,7 +2126,13 @@ void hvm_c(u32* book_buffer) {
u64 start = time64();

// GMem
Net *net = malloc(sizeof(Net));
Net *net;
if (net_buffer) {
// A buffer for the net has been allocated externally
net = net_buffer;
} else {
net = malloc(sizeof(Net));
}
net_init(net);

// Creates an initial redex that calls main
Expand All @@ -2152,13 +2157,13 @@ void hvm_c(u32* book_buffer) {

// Frees everything
free_static_tms();
free(net);
if (!net_buffer) { free(net); }
free(book);
}

#ifdef WITH_MAIN
int main() {
hvm_c((u32*)BOOK_BUF);
hvm_c((u32*)BOOK_BUF, NULL);
return 0;
}
#endif
Expand Down
4 changes: 4 additions & 0 deletions src/hvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@ pub type Val = u32; // Val ::= 29-bit (rounded up to u32)
pub type Rule = u8; // Rule ::= 8-bit (fits a u8)

// Port
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
pub struct Port(pub Val);

// Pair
#[repr(C)]
pub struct Pair(pub u64);

// Atomics
pub type AVal = AtomicU32;
#[repr(C)]
pub struct APort(pub AVal);
#[repr(C)]
pub struct APair(pub AtomicU64);

// Number
Expand Down
91 changes: 91 additions & 0 deletions src/interop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};

use crate::hvm::*;

// Abstract Global Net
// Allows any global net to be read back
// -------------

pub trait NetReadback {
fn enter(&self, var: Port) -> Port;
fn node_load(&self, loc: usize) -> Pair;
}

impl<'a> NetReadback for GNet<'a> {
fn enter(&self, var: Port) -> Port { self.enter(var) }
fn node_load(&self, loc: usize) -> Pair { self.node_load(loc) }
}

// Global Net equivalent to the C implementation.
// NOTE: If the C struct `Net` changes, this has to change as well.
// TODO: use `bindgen` crate (https://github.com/rust-lang/rust-bindgen) to generate C structs
// -------------

#[repr(C)]
pub struct NetC {
pub node: [APair; NetC::G_NODE_LEN], // global node buffer
pub vars: [APort; NetC::G_VARS_LEN], // global vars buffer
pub rbag: [APair; NetC::G_RBAG_LEN], // global rbag buffer
pub itrs: AtomicU64, // interaction count
pub idle: AtomicU32, // idle thread counter
}

impl NetC {
// Constants relevant in the C implementation
// NOTE: If any of these constants are changed in C, they have to be changed here as well.
pub const TPC_L2: usize = 3;
pub const TPC: usize = 1 << NetC::TPC_L2;
pub const CACHE_PAD: usize = 64; // Cache padding

pub const HLEN: usize = 1 << 16; // max 16k high-priority redexes
pub const RLEN: usize = 1 << 24; // max 16m low-priority redexes
pub const G_NODE_LEN: usize = 1 << 29; // max 536m nodes
pub const G_VARS_LEN: usize = 1 << 29; // max 536m vars
pub const G_RBAG_LEN: usize = NetC::TPC * NetC::RLEN;

pub fn vars_exchange(&self, var: usize, val: Port) -> Port {
Port(self.vars[var].0.swap(val.0, Ordering::Relaxed) as u32)
}

pub fn vars_take(&self, var: usize) -> Port {
self.vars_exchange(var, Port(0))
}

fn node_load(&self, loc:usize) -> Pair {
Pair(self.node[loc].0.load(Ordering::Relaxed))
}

fn enter(&self, mut var: Port) -> Port {
// While `B` is VAR: extend it (as an optimization)
while var.get_tag() == VAR {
// Takes the current `B` substitution as `B'`
let val = self.vars_exchange(var.get_val() as usize, NONE);
// If there was no `B'`, stop, as there is no extension
if val == NONE || val == Port(0) {
break;
}
// Otherwise, delete `B` (we own both) and continue as `A ~> B'`
self.vars_take(var.get_val() as usize);
var = val;
}
return var;
}
}

impl NetReadback for NetC {
fn node_load(&self, loc:usize) -> Pair {
self.node_load(loc)
}

fn enter(&self, var: Port) -> Port {
self.enter(var)
}
}

// Global Net equivalent to the CUDA implementation.
// NOTE: If the CUDA struct `Net` changes, this has to change as well.
// -------------

// TODO
// Problem: CUDA's `GNet` is allocated using `cudaMalloc`
// Solution: Write a CUDA kernel to compact GPU memory and then `memcpy` it to RAM
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
pub mod ast;
pub mod cmp;
pub mod hvm;
pub mod interop;
11 changes: 8 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
#![allow(unused_variables)]

use clap::{Arg, ArgAction, Command};
use ::hvm::{ast, cmp, hvm};
use ::hvm::{ast, cmp, hvm, interop};
use std::fs;
use std::alloc;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command as SysCommand;

#[cfg(feature = "c")]
extern "C" {
fn hvm_c(book_buffer: *const u32, run_io: bool);
fn hvm_c(book_buffer: *const u32, net_buffer: *const interop::NetC, run_io: bool);
}

#[cfg(feature = "cuda")]
Expand Down Expand Up @@ -81,7 +82,11 @@ fn main() {
let run_io = sub_matches.get_flag("io");
#[cfg(feature = "c")]
unsafe {
hvm_c(data.as_mut_ptr() as *mut u32, run_io);
let layout = alloc::Layout::new::<interop::NetC>();
let net_ptr = alloc::alloc(layout) as *mut interop::NetC;
hvm_c(data.as_mut_ptr() as *mut u32, net_ptr, run_io);
// hvm_c(data.as_mut_ptr() as *mut u32, std::ptr::null(), run_io);
alloc::dealloc(net_ptr as *mut u8, layout);
}
#[cfg(not(feature = "c"))]
println!("C runtime not available!\n");
Expand Down

0 comments on commit 0e9c596

Please sign in to comment.