1
0
forked from M-Labs/nac3

Compare commits

..

No commits in common. "feature/invk" and "master" have entirely different histories.

8 changed files with 71 additions and 143 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -4,7 +4,6 @@ from types import SimpleNamespace
from numpy import int32, int64 from numpy import int32, int64
from typing import Generic, TypeVar from typing import Generic, TypeVar
from math import floor, ceil from math import floor, ceil
import builtins
import nac3artiq import nac3artiq
@ -17,8 +16,7 @@ __all__ = [
"rpc", "ms", "us", "ns", "rpc", "ms", "us", "ns",
"print_int32", "print_int64", "print_int32", "print_int64",
"Core", "TTLOut", "Core", "TTLOut",
"parallel", "legacy_parallel", "sequential", "parallel", "legacy_parallel", "sequential"
"StringWrapper"
] ]
@ -92,7 +90,6 @@ artiq_builtins = {
"virtual": virtual, "virtual": virtual,
"_ConstGenericMarker": _ConstGenericMarker, "_ConstGenericMarker": _ConstGenericMarker,
"Option": Option, "Option": Option,
"str": builtins.str,
} }
compiler = nac3artiq.NAC3(core_arguments["target"], artiq_builtins) compiler = nac3artiq.NAC3(core_arguments["target"], artiq_builtins)
allow_registration = True allow_registration = True
@ -246,8 +243,6 @@ class Core:
global allow_registration global allow_registration
embedding = EmbeddingMap() embedding = EmbeddingMap()
for value, str_id in sorted(string_store.items(), key=lambda x: x[1]):
embedding.string_map[value] = str_id
if allow_registration: if allow_registration:
compiler.analyze(registered_functions, registered_classes, special_ids, set()) compiler.analyze(registered_functions, registered_classes, special_ids, set())
@ -335,36 +330,6 @@ class KernelContextManager:
def __exit__(self): def __exit__(self):
pass pass
@nac3
class StringWrapper:
"""Wrapper for Python strings in NAC3"""
artiq_builtin = True
_value: str
_id: int
def __init__(self, value: str):
global next_string_id
self._value = value
if value not in string_store:
string_store[value] = next_string_id
next_string_id += 1
self._id = string_store[value]
def __str__(self):
return self._value
def get_identifier(self) -> int:
return self._id
string_store = {}
NAC3_INTERNAL_STRINGS = {
"0:artiq.coredevice.exceptions.RTIOUnderflow": 0,
"": 1,
}
for s, id in NAC3_INTERNAL_STRINGS.items():
string_store[s] = id
next_string_id = max(NAC3_INTERNAL_STRINGS.values()) + 1
@nac3 @nac3
class UnwrapNoneError(Exception): class UnwrapNoneError(Exception):
"""raised when unwrapping a none value""" """raised when unwrapping a none value"""

Binary file not shown.

1
nac3artiq/demo/nac3artiq.so Symbolic link
View File

@ -0,0 +1 @@
../../target/release/libnac3artiq.so

View File

@ -1,20 +0,0 @@
from min_artiq import *
from numpy import int32
@nac3
class StringListTest:
core: KernelInvariant[Core]
def __init__(self):
self.core = Core()
@kernel
def test_string_and_list(self, key: str, value: list[int32]):
print_int32(int32(42))
def test_params():
exp = StringListTest()
exp.test_string_and_list("x4", [])
if __name__ == "__main__":
test_params()

View File

@ -440,18 +440,6 @@ impl Nac3 {
py: Python, py: Python,
link_fn: &dyn Fn(&Module) -> PyResult<T>, link_fn: &dyn Fn(&Module) -> PyResult<T>,
) -> PyResult<T> { ) -> PyResult<T> {
Python::with_gil(|_py| {
let string_map_py = embedding_map.getattr("string_map")?;
let reverse_map_py = embedding_map.getattr("string_reverse_map")?;
let string_store = self.string_store.read();
for (s, key) in string_store.iter() {
string_map_py.set_item(s, key)?;
reverse_map_py.set_item(key, s)?;
}
Ok::<_, PyErr>(())
})?;
let size_t = self.isa.get_size_type(&Context::create()); let size_t = self.isa.get_size_type(&Context::create());
let (mut composer, mut builtins_def, mut builtins_ty) = TopLevelComposer::new( let (mut composer, mut builtins_def, mut builtins_ty) = TopLevelComposer::new(
self.builtins.clone(), self.builtins.clone(),
@ -655,16 +643,10 @@ impl Nac3 {
name_to_pyid.insert("base".into(), id_fun.call1((obj,))?.extract()?); name_to_pyid.insert("base".into(), id_fun.call1((obj,))?.extract()?);
let mut arg_names = vec![]; let mut arg_names = vec![];
for (i, arg) in args.into_iter().enumerate() { for (i, arg) in args.into_iter().enumerate() {
if let Ok(st) = arg.extract::<String>() { let name = format!("tmp{i}");
let literal = format!("{st:?}"); module.add(&name, arg)?;
arg_names.push(literal); name_to_pyid.insert(name.clone().into(), id_fun.call1((arg,))?.extract()?);
} else { arg_names.push(name);
let tmp_name = format!("tmp{i}");
module.add(&tmp_name, arg)?;
let pyid_val: u64 = id_fun.call1((arg,))?.extract()?;
name_to_pyid.insert(tmp_name.clone().into(), pyid_val);
arg_names.push(tmp_name);
}
} }
let synthesized = if method_name.is_empty() { let synthesized = if method_name.is_empty() {
format!("def __modinit__():\n base({})", arg_names.join(", ")) format!("def __modinit__():\n base({})", arg_names.join(", "))
@ -944,6 +926,20 @@ impl Nac3 {
panic!("Failed to run optimization for module `main`: {}", err.to_string()); panic!("Failed to run optimization for module `main`: {}", err.to_string());
} }
Python::with_gil(|py| {
let string_store = self.string_store.read();
let mut string_store_vec = string_store.iter().collect::<Vec<_>>();
string_store_vec.sort_by(|(_s1, key1), (_s2, key2)| key1.cmp(key2));
for (s, key) in string_store_vec {
let embed_key: i32 = helper.store_str.call1(py, (s,)).unwrap().extract(py).unwrap();
assert_eq!(
embed_key, *key,
"string {s} is out of sync between embedding map (key={embed_key}) and \
the internal string store (key={key})"
);
}
});
link_fn(&main) link_fn(&main)
} }
@ -1060,64 +1056,55 @@ impl Nac3 {
}; };
let (primitive, _) = let (primitive, _) =
TopLevelComposer::make_primitives(isa.get_size_type(&Context::create())); TopLevelComposer::make_primitives(isa.get_size_type(&Context::create()));
let builtins = { let builtins = vec![
let mut b = vec![ (
( "now_mu".into(),
"now_mu".into(), FunSignature { args: vec![], ret: primitive.int64, vars: VarMap::new() },
FunSignature { args: vec![], ret: primitive.int64, vars: VarMap::new() }, Arc::new(GenCall::new(Box::new(move |ctx, _, _, _, _| {
Arc::new(GenCall::new(Box::new(move |ctx, _, _, _, _| { Ok(Some(time_fns.emit_now_mu(ctx)))
Ok(Some(time_fns.emit_now_mu(ctx))) }))),
}))), ),
), (
( "at_mu".into(),
"at_mu".into(), FunSignature {
FunSignature { args: vec![FuncArg {
args: vec![FuncArg { name: "t".into(),
name: "t".into(), ty: primitive.int64,
ty: primitive.int64, default_value: None,
default_value: None, is_vararg: false,
is_vararg: false, }],
}], ret: primitive.none,
ret: primitive.none, vars: VarMap::new(),
vars: VarMap::new(), },
}, Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| {
Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| { let arg_ty = fun.0.args[0].ty;
let arg_ty = fun.0.args[0].ty; let arg =
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty).unwrap();
args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty).unwrap(); time_fns.emit_at_mu(ctx, arg);
time_fns.emit_at_mu(ctx, arg); Ok(None)
Ok(None) }))),
}))), ),
), (
( "delay_mu".into(),
"delay_mu".into(), FunSignature {
FunSignature { args: vec![FuncArg {
args: vec![FuncArg { name: "dt".into(),
name: "dt".into(), ty: primitive.int64,
ty: primitive.int64, default_value: None,
default_value: None, is_vararg: false,
is_vararg: false, }],
}], ret: primitive.none,
ret: primitive.none, vars: VarMap::new(),
vars: VarMap::new(), },
}, Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| {
Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| { let arg_ty = fun.0.args[0].ty;
let arg_ty = fun.0.args[0].ty; let arg =
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty).unwrap();
args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty).unwrap(); time_fns.emit_delay_mu(ctx, arg);
time_fns.emit_delay_mu(ctx, arg); Ok(None)
Ok(None) }))),
}))), ),
), ];
];
b.push((
"str".into(),
FunSignature { args: vec![], ret: primitive.str, vars: VarMap::new() },
Arc::new(GenCall::new(Box::new(|_, _, _, _, _| Ok(None)))),
));
b
};
let builtins_mod = PyModule::import(py, "builtins").unwrap(); let builtins_mod = PyModule::import(py, "builtins").unwrap();
let id_fn = builtins_mod.getattr("id").unwrap(); let id_fn = builtins_mod.getattr("id").unwrap();

View File

@ -720,6 +720,7 @@ impl InnerResolver {
self.pyid_to_type.write().insert(py_obj_id, ty); self.pyid_to_type.write().insert(py_obj_id, ty);
return Ok(Ok(ty)); return Ok(Ok(ty));
} }
let (extracted_ty, inst_check) = match self.get_pyty_obj_type( let (extracted_ty, inst_check) = match self.get_pyty_obj_type(
py, py,
{ {
@ -727,7 +728,6 @@ impl InnerResolver {
self.primitive_ids.typevar, self.primitive_ids.typevar,
self.primitive_ids.generic_alias.0, self.primitive_ids.generic_alias.0,
self.primitive_ids.generic_alias.1, self.primitive_ids.generic_alias.1,
self.primitive_ids.string,
] ]
.contains(&self.helper.id_fn.call1(py, (ty.clone(),))?.extract::<u64>(py)?) .contains(&self.helper.id_fn.call1(py, (ty.clone(),))?.extract::<u64>(py)?)
{ {
@ -985,11 +985,6 @@ impl InnerResolver {
|_| Ok(Err(format!("{obj} is not in the range of float64"))), |_| Ok(Err(format!("{obj} is not in the range of float64"))),
|_| Ok(Ok(extracted_ty)), |_| Ok(Ok(extracted_ty)),
) )
} else if unifier.unioned(extracted_ty, primitives.str) {
obj.extract::<String>().map_or_else(
|_| Ok(Err(format!("{obj} is not a valid string"))),
|_| Ok(Ok(primitives.str)),
)
} else { } else {
Ok(Ok(extracted_ty)) Ok(Ok(extracted_ty))
} }
@ -1035,7 +1030,7 @@ impl InnerResolver {
} else if ty_id == self.primitive_ids.string || ty_id == self.primitive_ids.np_str_ { } else if ty_id == self.primitive_ids.string || ty_id == self.primitive_ids.np_str_ {
let val: String = obj.extract().unwrap(); let val: String = obj.extract().unwrap();
self.id_to_primitive.write().insert(id, PrimitiveValue::Str(val.clone())); self.id_to_primitive.write().insert(id, PrimitiveValue::Str(val.clone()));
return Ok(Some(ctx.gen_string(generator, val).into())); Ok(Some(ctx.gen_string(generator, val).into()))
} else if ty_id == self.primitive_ids.float || ty_id == self.primitive_ids.float64 { } else if ty_id == self.primitive_ids.float || ty_id == self.primitive_ids.float64 {
let val: f64 = obj.extract().unwrap(); let val: f64 = obj.extract().unwrap();
self.id_to_primitive.write().insert(id, PrimitiveValue::F64(val)); self.id_to_primitive.write().insert(id, PrimitiveValue::F64(val));