diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index a82449fd1..dff28bb2e 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -171,7 +171,7 @@ class Target: as results: library = results["output"].read() - _dump(os.getenv("ARTIQ_DUMP_ELF"), "Shared library", ".so", + _dump(os.getenv("ARTIQ_DUMP_ELF"), "Shared library", ".elf", lambda: library) return library diff --git a/artiq/frontend/artiq_run.py b/artiq/frontend/artiq_run.py index 09b46ea07..79bb4dcb7 100755 --- a/artiq/frontend/artiq_run.py +++ b/artiq/frontend/artiq_run.py @@ -47,9 +47,9 @@ class StubEmbeddingMap: class FileRunner(EnvExperiment): - def build(self): + def build(self, file): self.setattr_device("core") - self.setattr_argument("file") + self.file = file self.target = OR1KTarget() def run(self): @@ -58,7 +58,8 @@ class FileRunner(EnvExperiment): self.core.comm.load(kernel_library) self.core.comm.run() self.core.comm.serve(StubEmbeddingMap(), - lambda addresses: self.target.symbolize(kernel_library, addresses)) + lambda addresses: self.target.symbolize(kernel_library, addresses), \ + lambda symbols: self.target.demangle(symbols)) class ELFRunner(FileRunner): @@ -142,6 +143,9 @@ def get_argparser(with_file=True): def _build_experiment(device_mgr, dataset_mgr, args): + arguments = parse_arguments(args.arguments) + argument_mgr = ProcessArgumentManager(arguments) + managers = (device_mgr, dataset_mgr, argument_mgr) if hasattr(args, "file"): is_elf = args.file.endswith(".elf") is_ll = args.file.endswith(".ll") @@ -153,11 +157,11 @@ def _build_experiment(device_mgr, dataset_mgr, args): raise ValueError("experiment-by-name not supported " "for precompiled kernels") if is_elf: - return ELFRunner(device_mgr, dataset_mgr, file=args.file) + return ELFRunner(managers, file=args.file) elif is_ll: - return LLVMIRRunner(device_mgr, dataset_mgr, file=args.file) + return LLVMIRRunner(managers, file=args.file) elif is_bc: - return LLVMBitcodeRunner(device_mgr, dataset_mgr, file=args.file) + return LLVMBitcodeRunner(managers, file=args.file) else: import_cache.install_hook() module = file_import(args.file, prefix="artiq_run_") @@ -165,16 +169,13 @@ def _build_experiment(device_mgr, dataset_mgr, args): else: module = sys.modules["__main__"] file = getattr(module, "__file__") - exp = get_experiment(module, args.experiment) - arguments = parse_arguments(args.arguments) expid = { "file": file, "experiment": args.experiment, "arguments": arguments } device_mgr.virtual_devices["scheduler"].expid = expid - argument_mgr = ProcessArgumentManager(arguments) - return exp((device_mgr, dataset_mgr, argument_mgr)) + return get_experiment(module, args.experiment)(managers) def run(with_file=False): diff --git a/artiq/runtime.rs/Cargo.lock b/artiq/runtime.rs/Cargo.lock new file mode 100644 index 000000000..81e92fa04 --- /dev/null +++ b/artiq/runtime.rs/Cargo.lock @@ -0,0 +1,18 @@ +[root] +name = "runtime" +version = "0.0.0" +dependencies = [ + "std_artiq 0.0.0", +] + +[[package]] +name = "alloc_artiq" +version = "0.0.0" + +[[package]] +name = "std_artiq" +version = "0.0.0" +dependencies = [ + "alloc_artiq 0.0.0", +] + diff --git a/artiq/runtime.rs/Cargo.toml b/artiq/runtime.rs/Cargo.toml new file mode 100644 index 000000000..33d3225c8 --- /dev/null +++ b/artiq/runtime.rs/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["The ARTIQ Project Developers"] +name = "runtime" +version = "0.0.0" + +[lib] +name = "artiq_rust" +crate-type = ["staticlib"] +path = "src/lib.rs" + +[dependencies] +std_artiq = { path = "libstd_artiq" } + +[profile.dev] +panic = 'abort' +opt-level = 2 diff --git a/artiq/runtime.rs/liballoc_artiq/Cargo.toml b/artiq/runtime.rs/liballoc_artiq/Cargo.toml new file mode 100644 index 000000000..c7e86107d --- /dev/null +++ b/artiq/runtime.rs/liballoc_artiq/Cargo.toml @@ -0,0 +1,8 @@ +[package] +authors = ["The ARTIQ Project Developers"] +name = "alloc_artiq" +version = "0.0.0" + +[lib] +name = "alloc_artiq" +path = "lib.rs" diff --git a/artiq/runtime.rs/liballoc_artiq/lib.rs b/artiq/runtime.rs/liballoc_artiq/lib.rs new file mode 100644 index 000000000..28063a5e2 --- /dev/null +++ b/artiq/runtime.rs/liballoc_artiq/lib.rs @@ -0,0 +1,86 @@ +#![feature(allocator, libc)] +#![no_std] +#![allocator] + +// The minimum alignment guaranteed by the architecture. +const MIN_ALIGN: usize = 8; + +#[no_mangle] +pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 { + unsafe { imp::allocate(size, align) } +} + +#[no_mangle] +pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { + unsafe { imp::deallocate(ptr, old_size, align) } +} + +#[no_mangle] +pub extern "C" fn __rust_reallocate(ptr: *mut u8, + old_size: usize, + size: usize, + align: usize) + -> *mut u8 { + unsafe { imp::reallocate(ptr, old_size, size, align) } +} + +#[no_mangle] +pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8, + old_size: usize, + size: usize, + align: usize) + -> usize { + unsafe { imp::reallocate_inplace(ptr, old_size, size, align) } +} + +#[no_mangle] +pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize { + imp::usable_size(size, align) +} + +mod imp { + extern crate libc; + + use core::cmp; + use core::ptr; + use MIN_ALIGN; + + pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { + if align <= MIN_ALIGN { + libc::malloc(size as libc::size_t) as *mut u8 + } else { + aligned_malloc(size, align) + } + } + + unsafe fn aligned_malloc(_size: usize, _align: usize) -> *mut u8 { + panic!("aligned_malloc not implemented") + } + + pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, + size: usize, align: usize) -> *mut u8 { + if align <= MIN_ALIGN { + libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 + } else { + let new_ptr = allocate(size, align); + if !new_ptr.is_null() { + ptr::copy(ptr, new_ptr, cmp::min(size, old_size)); + deallocate(ptr, old_size, align); + } + new_ptr + } + } + + pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, + _size: usize, _align: usize) -> usize { + old_size + } + + pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { + libc::free(ptr as *mut libc::c_void) + } + + pub fn usable_size(size: usize, _align: usize) -> usize { + size + } +} diff --git a/artiq/runtime.rs/libstd_artiq/Cargo.toml b/artiq/runtime.rs/libstd_artiq/Cargo.toml new file mode 100644 index 000000000..dfd38df4a --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/Cargo.toml @@ -0,0 +1,11 @@ +[package] +authors = ["The ARTIQ Project Developers"] +name = "std_artiq" +version = "0.0.0" + +[lib] +name = "std_artiq" +path = "lib.rs" + +[dependencies] +alloc_artiq = { path = "../liballoc_artiq" } diff --git a/artiq/runtime.rs/libstd_artiq/lib.rs b/artiq/runtime.rs/libstd_artiq/lib.rs new file mode 100644 index 000000000..161bad789 --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/lib.rs @@ -0,0 +1,64 @@ +#![feature(lang_items, asm, collections, libc, needs_panic_runtime)] +#![no_std] +#![needs_panic_runtime] + +extern crate alloc_artiq; +extern crate collections; +extern crate libc; + +pub mod prelude { + pub mod v1 { + pub use core::prelude::v1::*; + pub use collections::*; + } +} + +use core::fmt::Write; + +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::print_fmt(format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! println { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} + +extern { + fn putchar(c: libc::c_int) -> libc::c_int; + fn readchar() -> libc::c_char; +} + +pub struct Console; + +impl core::fmt::Write for Console { + fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { + for c in s.bytes() { unsafe { putchar(c as i32); } } + Ok(()) + } +} + +pub fn print_fmt(args: self::core::fmt::Arguments) { + let _ = Console.write_fmt(args); +} + +#[lang = "panic_fmt"] +extern fn panic_fmt(args: self::core::fmt::Arguments, file: &'static str, line: u32) -> ! { + let _ = write!(Console, "panic at {}:{}: ", file, line); + let _ = Console.write_fmt(args); + let _ = write!(Console, "\nwaiting for debugger...\n"); + unsafe { + let _ = readchar(); + loop { asm!("l.trap 0") } + } +} + +// Allow linking with crates that are built as -Cpanic=unwind even when the root crate +// is built with -Cpanic=abort. +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn _Unwind_Resume() -> ! { + loop {} +} diff --git a/artiq/runtime.rs/src/lib.rs b/artiq/runtime.rs/src/lib.rs new file mode 100644 index 000000000..56a3c0184 --- /dev/null +++ b/artiq/runtime.rs/src/lib.rs @@ -0,0 +1,11 @@ +#![no_std] + +#[macro_use] +extern crate std_artiq as std; + +use std::prelude::v1::*; + +#[no_mangle] +pub extern "C" fn rust_main() { + println!("hello from rust!"); +} diff --git a/artiq/runtime/Makefile b/artiq/runtime/Makefile index d38b64ccf..e0c276a12 100644 --- a/artiq/runtime/Makefile +++ b/artiq/runtime/Makefile @@ -27,8 +27,9 @@ all: runtime.bin runtime.fbi %.fbi: %.bin @echo " MSCIMG " $@ && $(PYTHON) -m misoc.tools.mkmscimg -f -o $@ $< -runtime.elf: $(OBJECTS) +runtime.elf: $(OBJECTS) libartiq_rust.a $(LD) $(LDFLAGS) \ + --gc-sections \ -T $(RUNTIME_DIRECTORY)/runtime.ld \ -N -o $@ \ ../libbase/crt0-$(CPU).o \ @@ -38,7 +39,8 @@ runtime.elf: $(OBJECTS) -L../libm \ -L../liballoc \ -L../liblwip \ - -lbase -lm -lcompiler-rt -lalloc -llwip + -Lcargo/or1k-unknown-none/debug/ \ + -lartiq_rust -lbase -lm -lcompiler-rt -lalloc -llwip @chmod -x $@ ksupport.elf: $(OBJECTS_KSUPPORT) @@ -58,6 +60,14 @@ ksupport.elf: $(OBJECTS_KSUPPORT) ksupport_data.o: ksupport.elf $(LD) -r -b binary -o $@ $< +libartiq_rust.a: + CARGO_TARGET_DIR="./cargo" \ + cargo rustc --verbose \ + --manifest-path $(RUNTIME_DIRECTORY)/../runtime.rs/Cargo.toml \ + --target=or1k-unknown-none -- \ + -C target-feature=+mul,+div,+ffl1,+cmov,+addc -C opt-level=s \ + -L../libcompiler-rt + %.o: $(RUNTIME_DIRECTORY)/%.c $(compile) diff --git a/artiq/runtime/main.c b/artiq/runtime/main.c index a5a76c16d..9bf000754 100644 --- a/artiq/runtime/main.c +++ b/artiq/runtime/main.c @@ -262,6 +262,8 @@ static int check_test_mode(void) extern void _fheap, _eheap; +extern void rust_main(); + int main(void) { irq_setmask(0); @@ -276,6 +278,9 @@ int main(void) puts("Press 't' to enter test mode..."); blink_led(); + puts("Calling Rust..."); + rust_main(); + if(check_test_mode()) { puts("Entering test mode."); test_main(); diff --git a/conda/artiq-kc705-nist_clock/meta.yaml b/conda/artiq-kc705-nist_clock/meta.yaml index d53022965..6d43b182a 100644 --- a/conda/artiq-kc705-nist_clock/meta.yaml +++ b/conda/artiq-kc705-nist_clock/meta.yaml @@ -15,7 +15,9 @@ requirements: - migen 0.2 - misoc 0.2 - llvm-or1k - - binutils-or1k-linux + - binutils-or1k-linux >=2.27 + - rust-core-or1k + - cargo run: - artiq {{ "{tag} py_{number}+git{hash}".format(tag=environ.get("GIT_DESCRIBE_TAG"), number=environ.get("GIT_DESCRIBE_NUMBER"), hash=environ.get("GIT_DESCRIBE_HASH")[1:]) if "GIT_DESCRIBE_TAG" in environ else "" }} diff --git a/conda/artiq-kc705-nist_qc1/meta.yaml b/conda/artiq-kc705-nist_qc1/meta.yaml index 5a64a06c2..a9c4c2b99 100644 --- a/conda/artiq-kc705-nist_qc1/meta.yaml +++ b/conda/artiq-kc705-nist_qc1/meta.yaml @@ -15,7 +15,9 @@ requirements: - migen 0.2 - misoc 0.2 - llvm-or1k - - binutils-or1k-linux + - binutils-or1k-linux >=2.27 + - rust-core-or1k + - cargo run: - artiq {{ "{tag} py_{number}+git{hash}".format(tag=environ.get("GIT_DESCRIBE_TAG"), number=environ.get("GIT_DESCRIBE_NUMBER"), hash=environ.get("GIT_DESCRIBE_HASH")[1:]) if "GIT_DESCRIBE_TAG" in environ else "" }} diff --git a/conda/artiq-kc705-nist_qc2/meta.yaml b/conda/artiq-kc705-nist_qc2/meta.yaml index 33bf5437a..11ba30630 100644 --- a/conda/artiq-kc705-nist_qc2/meta.yaml +++ b/conda/artiq-kc705-nist_qc2/meta.yaml @@ -15,7 +15,9 @@ requirements: - migen 0.2 - misoc 0.2 - llvm-or1k - - binutils-or1k-linux + - binutils-or1k-linux >=2.27 + - rust-core-or1k + - cargo run: - artiq {{ "{tag} py_{number}+git{hash}".format(tag=environ.get("GIT_DESCRIBE_TAG"), number=environ.get("GIT_DESCRIBE_NUMBER"), hash=environ.get("GIT_DESCRIBE_HASH")[1:]) if "GIT_DESCRIBE_TAG" in environ else "" }} diff --git a/conda/artiq-pipistrello-nist_qc1/meta.yaml b/conda/artiq-pipistrello-nist_qc1/meta.yaml index 32e59910d..96827e3b0 100644 --- a/conda/artiq-pipistrello-nist_qc1/meta.yaml +++ b/conda/artiq-pipistrello-nist_qc1/meta.yaml @@ -15,7 +15,9 @@ requirements: - migen 0.2 - misoc 0.2 - llvm-or1k - - binutils-or1k-linux + - binutils-or1k-linux >=2.27 + - rust-core-or1k + - cargo run: - artiq {{ "{tag} py_{number}+git{hash}".format(tag=environ.get("GIT_DESCRIBE_TAG"), number=environ.get("GIT_DESCRIBE_NUMBER"), hash=environ.get("GIT_DESCRIBE_HASH")[1:]) if "GIT_DESCRIBE_TAG" in environ else "" }}