diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs index a01009bf0..22c28e480 100644 --- a/nac3artiq/src/lib.rs +++ b/nac3artiq/src/lib.rs @@ -163,6 +163,108 @@ impl Nac3 { } } +// ARTIQ timeline control with now-pinning optimization. +// This is a bit of mess due to endianness issues. +// Modify gateware to make `now` little-endian, since we don't have OpenRISC anymore? +fn timeline_builtins(primitive: &PrimitiveStore) -> Vec<(StrRef, FunSignature, Arc)> { + vec![( + "now_mu".into(), + FunSignature { + args: vec![], + ret: primitive.int64, + vars: HashMap::new(), + }, + Arc::new(GenCall::new(Box::new( + |ctx, _, _, _| { + let i64_type = ctx.ctx.i64_type(); + let now = ctx.module.get_global("now").unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); + let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now"); + if let BasicValueEnum::IntValue(now_raw) = now_raw { + let i64_32 = i64_type.const_int(32, false).into(); + let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now_shl"); + let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now_lshr").into(); + Some(ctx.builder.build_or(now_lo, now_hi, "now_or").into()) + } else { + unreachable!() + } + } + ))) + ),( + "at_mu".into(), + FunSignature { + args: vec![FuncArg { + name: "t".into(), + ty: primitive.int64, + default_value: None, + }], + ret: primitive.none, + vars: HashMap::new(), + }, + Arc::new(GenCall::new(Box::new( + |ctx, _, _, args| { + let i32_type = ctx.ctx.i64_type(); + let i64_type = ctx.ctx.i64_type(); + let i64_32 = i64_type.const_int(32, false).into(); + if let BasicValueEnum::IntValue(time) = args[0].1 { + let time_hi = ctx.builder.build_int_truncate(ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"), i32_type, "now_trunc"); + let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc"); + let now = ctx.module.get_global("now").unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); + let now_hiptr = ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::Generic), "now_bitcast"); + if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr { + let now_loptr = unsafe { ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false).into()], "now_gep") }; + ctx.builder.build_store(now_hiptr, time_hi); + ctx.builder.build_store(now_loptr, time_lo); + None + } else { + unreachable!(); + } + } else { + unreachable!(); + } + } + ))) + ),( + "delay_mu".into(), + FunSignature { + args: vec![FuncArg { + name: "dt".into(), + ty: primitive.int64, + default_value: None, + }], + ret: primitive.none, + vars: HashMap::new(), + }, + Arc::new(GenCall::new(Box::new( + |ctx, _, _, args| { + let i32_type = ctx.ctx.i64_type(); + let i64_type = ctx.ctx.i64_type(); + let i64_32 = i64_type.const_int(32, false).into(); + let now = ctx.module.get_global("now").unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); + let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now"); + if let (BasicValueEnum::IntValue(now_raw), BasicValueEnum::IntValue(dt)) = (now_raw, args[0].1) { + let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now_shl"); + let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now_lshr").into(); + let now_val = ctx.builder.build_or(now_lo, now_hi, "now_or"); + let time = ctx.builder.build_int_add(now_val, dt, "now_add"); + let time_hi = ctx.builder.build_int_truncate(ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"), i32_type, "now_trunc"); + let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc"); + let now_hiptr = ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::Generic), "now_bitcast"); + if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr { + let now_loptr = unsafe { ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false).into()], "now_gep") }; + ctx.builder.build_store(now_hiptr, time_hi); + ctx.builder.build_store(now_loptr, time_lo); + None + } else { + unreachable!(); + } + } else { + unreachable!(); + } + } + ))) + )] +} + #[pymethods] impl Nac3 { #[new] @@ -173,107 +275,7 @@ impl Nac3 { _ => return Err(exceptions::PyValueError::new_err("invalid ISA")), }; let primitive: PrimitiveStore = TopLevelComposer::make_primitives().0; - let mut builtins = vec![]; - if isa == Isa::RiscV { - builtins.push(( - "now_mu".into(), - FunSignature { - args: vec![], - ret: primitive.int64, - vars: HashMap::new(), - }, - Arc::new(GenCall::new(Box::new( - |ctx, _, _, _| { - let i64_type = ctx.ctx.i64_type(); - let now = ctx.module.get_global("now").unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); - let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now"); - if let BasicValueEnum::IntValue(now_raw) = now_raw { - let i64_32 = i64_type.const_int(32, false).into(); - let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now_shl"); - let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now_lshr").into(); - Some(ctx.builder.build_or(now_lo, now_hi, "now_or").into()) - } else { - unreachable!() - } - } - ))) - )); - builtins.push(( - "at_mu".into(), - FunSignature { - args: vec![FuncArg { - name: "t".into(), - ty: primitive.int64, - default_value: None, - }], - ret: primitive.none, - vars: HashMap::new(), - }, - Arc::new(GenCall::new(Box::new( - |ctx, _, _, args| { - let i32_type = ctx.ctx.i64_type(); - let i64_type = ctx.ctx.i64_type(); - let i64_32 = i64_type.const_int(32, false).into(); - if let BasicValueEnum::IntValue(time) = args[0].1 { - let time_hi = ctx.builder.build_int_truncate(ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"), i32_type, "now_trunc"); - let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc"); - let now = ctx.module.get_global("now").unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); - let now_hiptr = ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::Generic), "now_bitcast"); - if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr { - let now_loptr = unsafe { ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false).into()], "now_gep") }; - ctx.builder.build_store(now_hiptr, time_hi); - ctx.builder.build_store(now_loptr, time_lo); - None - } else { - unreachable!(); - } - } else { - unreachable!(); - } - } - ))) - )); - builtins.push(( - "delay_mu".into(), - FunSignature { - args: vec![FuncArg { - name: "dt".into(), - ty: primitive.int64, - default_value: None, - }], - ret: primitive.none, - vars: HashMap::new(), - }, - Arc::new(GenCall::new(Box::new( - |ctx, _, _, args| { - let i32_type = ctx.ctx.i64_type(); - let i64_type = ctx.ctx.i64_type(); - let i64_32 = i64_type.const_int(32, false).into(); - let now = ctx.module.get_global("now").unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); - let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now"); - if let (BasicValueEnum::IntValue(now_raw), BasicValueEnum::IntValue(dt)) = (now_raw, args[0].1) { - let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now_shl"); - let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now_lshr").into(); - let now_val = ctx.builder.build_or(now_lo, now_hi, "now_or"); - let time = ctx.builder.build_int_add(now_val, dt, "now_add"); - let time_hi = ctx.builder.build_int_truncate(ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"), i32_type, "now_trunc"); - let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc"); - let now_hiptr = ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::Generic), "now_bitcast"); - if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr { - let now_loptr = unsafe { ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false).into()], "now_gep") }; - ctx.builder.build_store(now_hiptr, time_hi); - ctx.builder.build_store(now_loptr, time_lo); - None - } else { - unreachable!(); - } - } else { - unreachable!(); - } - } - ))) - )); - } + let builtins = if isa == Isa::RiscV { timeline_builtins(&primitive) } else { vec![] }; let (composer, builtins_def, builtins_ty) = TopLevelComposer::new(builtins); Ok(Nac3 { isa,