Compare commits

..

18 Commits

Author SHA1 Message Date
ram
20248d0310 Merge upstream into feature/invk 2025-02-12 04:46:31 +00:00
ram
bd0c0c9dfb Merge upstream/master into feature/invk 2025-02-10 03:06:54 +00:00
ram
9f7dbecae2 Cleaned up implementation 2025-01-28 06:14:07 +00:00
ram
83fa1db6b8 Removed comments 2025-01-14 09:28:04 +00:00
ram
b4b3980ffb Add test case for passing strings into kernel invokation breaks 2025-01-10 08:14:42 +00:00
ram
29130d3ef4 Add string registration in NAC 2025-01-10 06:23:08 +00:00
ram
3d087160ca Add string registration in NAC 2025-01-10 06:22:53 +00:00
ram
37886fcfe3 Add string registration in NAC 2025-01-10 06:09:38 +00:00
ram
c3bcf101d4 Merge remote-tracking branch 'upstream/master' 2025-01-10 04:00:40 +00:00
ram
0d5be81ef4 Merge branch 2024-12-30 04:11:31 +00:00
ram
dd8bf1a35e Resolve merge conflicts 2024-12-30 04:09:18 +00:00
ram
cc18586363 Use llvm_usize for first GEP index, llvm_i32 for second GEP index 2024-12-16 14:35:09 +00:00
ram
e1a2f1239d Implement 64 bit function call 2024-12-16 09:48:51 +00:00
ram
0b6a9bd89b Updated to use memcmp instead of strncmp 2024-12-13 15:43:50 +00:00
ram
9b0d37b1f0 Amend to follow formatting of other C++ files 2024-12-12 10:35:47 +00:00
ram
543a648af8 Edit function call to support 32-bit and 64-bit str 2024-12-12 10:10:39 +00:00
ram
780d33c8a7 Edit function call to support 32-bit and 64-bit str 2024-12-12 10:05:11 +00:00
ram
e13d753329 Implement string equality operator using IRRT and optimise LLVM implementation 2024-12-11 17:14:11 +00:00
8 changed files with 143 additions and 71 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@ -4,6 +4,7 @@ from types import SimpleNamespace
from numpy import int32, int64
from typing import Generic, TypeVar
from math import floor, ceil
import builtins
import nac3artiq
@ -16,7 +17,8 @@ __all__ = [
"rpc", "ms", "us", "ns",
"print_int32", "print_int64",
"Core", "TTLOut",
"parallel", "legacy_parallel", "sequential"
"parallel", "legacy_parallel", "sequential",
"StringWrapper"
]
@ -90,6 +92,7 @@ artiq_builtins = {
"virtual": virtual,
"_ConstGenericMarker": _ConstGenericMarker,
"Option": Option,
"str": builtins.str,
}
compiler = nac3artiq.NAC3(core_arguments["target"], artiq_builtins)
allow_registration = True
@ -243,6 +246,8 @@ class Core:
global allow_registration
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:
compiler.analyze(registered_functions, registered_classes, special_ids, set())
@ -330,6 +335,36 @@ class KernelContextManager:
def __exit__(self):
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
class UnwrapNoneError(Exception):
"""raised when unwrapping a none value"""

BIN
nac3artiq/demo/module.elf Normal file

Binary file not shown.

View File

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

View File

@ -0,0 +1,20 @@
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,6 +440,18 @@ impl Nac3 {
py: Python,
link_fn: &dyn Fn(&Module) -> 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 (mut composer, mut builtins_def, mut builtins_ty) = TopLevelComposer::new(
self.builtins.clone(),
@ -643,10 +655,16 @@ impl Nac3 {
name_to_pyid.insert("base".into(), id_fun.call1((obj,))?.extract()?);
let mut arg_names = vec![];
for (i, arg) in args.into_iter().enumerate() {
let name = format!("tmp{i}");
module.add(&name, arg)?;
name_to_pyid.insert(name.clone().into(), id_fun.call1((arg,))?.extract()?);
arg_names.push(name);
if let Ok(st) = arg.extract::<String>() {
let literal = format!("{st:?}");
arg_names.push(literal);
} else {
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() {
format!("def __modinit__():\n base({})", arg_names.join(", "))
@ -926,20 +944,6 @@ impl Nac3 {
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)
}
@ -1056,7 +1060,8 @@ impl Nac3 {
};
let (primitive, _) =
TopLevelComposer::make_primitives(isa.get_size_type(&Context::create()));
let builtins = vec![
let builtins = {
let mut b = vec![
(
"now_mu".into(),
FunSignature { args: vec![], ret: primitive.int64, vars: VarMap::new() },
@ -1105,6 +1110,14 @@ impl Nac3 {
}))),
),
];
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 id_fn = builtins_mod.getattr("id").unwrap();

View File

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

View File