handle time cursor functions on the Rust side entirely

This is preparation for with sequential/with parallel support.
escape-analysis
Sebastien Bourdeauducq 2021-10-08 23:13:46 +08:00
parent a07674a042
commit d3a21d75fa
4 changed files with 46 additions and 203 deletions

View File

@ -2,11 +2,6 @@ from numpy import int32, int64
from language import *
import device_db
if device_db.device_db["core"]["arguments"]["target"] == "cortexa9":
from artiq_timeline_extern import *
@extern
def rtio_init():
raise NotImplementedError("syscall not simulated")

View File

@ -1,20 +0,0 @@
from numpy import int32, int64
from language import *
__all__ = ["now_mu", "at_mu", "delay_mu"]
@extern
def now_mu() -> int64:
raise NotImplementedError("syscall not simulated")
@extern
def at_mu(t: int64):
raise NotImplementedError("syscall not simulated")
@extern
def delay_mu(dt: int64):
raise NotImplementedError("syscall not simulated")

View File

@ -1,167 +0,0 @@
use inkwell::{values::BasicValueEnum, AddressSpace, AtomicOrdering};
use nac3core::{
toplevel::GenCall,
typecheck::{
type_inferencer::PrimitiveStore,
typedef::{FunSignature, FuncArg},
},
};
use rustpython_parser::ast::StrRef;
use std::{collections::HashMap, sync::Arc};
// ARTIQ timeline control with now-pinning optimization.
pub fn timeline_builtins(primitive: &PrimitiveStore) -> Vec<(StrRef, FunSignature, Arc<GenCall>)> {
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.i32_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)
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap();
ctx.builder
.build_store(now_loptr, time_lo)
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap();
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.i32_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)
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap();
ctx.builder
.build_store(now_loptr, time_lo)
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap();
None
} else {
unreachable!();
}
} else {
unreachable!();
}
}))),
),
]
}

View File

@ -21,19 +21,18 @@ use parking_lot::{RwLock, Mutex};
use nac3core::{
codegen::{CodeGenTask, WithCall, WorkerRegistry},
symbol_resolver::SymbolResolver,
toplevel::{composer::TopLevelComposer, TopLevelContext, TopLevelDef},
typecheck::typedef::FunSignature,
};
use nac3core::{
toplevel::DefinitionId,
toplevel::{composer::TopLevelComposer, TopLevelContext, TopLevelDef, DefinitionId, GenCall},
typecheck::typedef::{FunSignature, FuncArg},
typecheck::{type_inferencer::PrimitiveStore, typedef::Type},
};
use crate::symbol_resolver::Resolver;
mod builtins;
mod timeline;
mod symbol_resolver;
use timeline::TimeFns;
#[derive(PartialEq, Clone, Copy)]
enum Isa {
RiscV,
@ -186,12 +185,48 @@ impl Nac3 {
"cortexa9" => Isa::CortexA9,
_ => return Err(exceptions::PyValueError::new_err("invalid ISA")),
};
let primitive: PrimitiveStore = TopLevelComposer::make_primitives().0;
let builtins = if isa == Isa::RiscV {
builtins::timeline_builtins(&primitive)
} else {
vec![]
let time_fns: &(dyn TimeFns + Sync) = match isa {
Isa::RiscV => &timeline::NOW_PINNING_TIME_FNS,
Isa::CortexA9 => &timeline::EXTERN_TIME_FNS,
};
let primitive: PrimitiveStore = TopLevelComposer::make_primitives().0;
let builtins = vec![
(
"now_mu".into(),
FunSignature {
args: vec![],
ret: primitive.int64,
vars: HashMap::new(),
},
Arc::new(GenCall::new(Box::new(move |ctx, _, _, _| Some(time_fns.emit_now_mu(ctx))))),
),
(
"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(move |ctx, _, _, args| { time_fns.emit_at_mu(ctx, args[0].1); None }))),
),
(
"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(move |ctx, _, _, args| { time_fns.emit_delay_mu(ctx, args[0].1); None }))),
),
];
let (composer, builtins_def, builtins_ty) = TopLevelComposer::new(builtins);
let builtins_mod = PyModule::import(py, "builtins").unwrap();