Skip to content

Commit 3ea8a3c

Browse files
committed
multi-event scheduling
1 parent 0d42c1f commit 3ea8a3c

File tree

1 file changed

+88
-59
lines changed
  • crates/filament/src/ir_passes/schedule

1 file changed

+88
-59
lines changed

crates/filament/src/ir_passes/schedule/solve.rs

Lines changed: 88 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::CombDataflow;
22
use crate::ir_visitor::{Action, Construct, Visitor, VisitorData};
3+
use core::time;
34
use easy_smt::{self as smt, SExpr, SExprData};
45
use fil_ir::{self as ir, AddCtx, Ctx, DisplayCtx, MutCtx, PortOwner};
56
use fil_utils::{AttrCtx, CompNum};
@@ -30,6 +31,12 @@ pub struct Solve {
3031
goal: SchedulingGoal,
3132
/// The expression to minimize
3233
minimize_expr: smt::SExpr,
34+
// /// Map from ir elements to SExprs
35+
// expr_map: ir::SparseInfoMap<ir::Expr, SExpr>,
36+
// port_map: ir::SparseInfoMap<ir::PortIdx, SExpr>,
37+
// event_map: ir::SparseInfoMap<ir::EventIdx, SExpr>,
38+
// time_map: ir::SparseInfoMap<ir::TimeIdx, SExpr>,
39+
// prop_map: ir::SparseInfoMap<ir::PropIdx, SExpr>,
3340
}
3441

3542
impl Solve {
@@ -42,8 +49,12 @@ impl Solve {
4249
}
4350

4451
/// Get the constant name for the time of an event
45-
pub fn get_evt_name(&self, inv: ir::InvIdx, evt: ir::EventIdx) -> String {
46-
format!("inv{}ev{}", inv.get(), evt.get())
52+
pub fn get_evt_name(
53+
&self,
54+
inv: ir::InvIdx,
55+
evt: ir::Foreign<ir::Event, ir::Component>,
56+
) -> String {
57+
format!("inv{}ev{}", inv.get(), evt.key().get())
4758
}
4859

4960
/// Get the SExprs for the start and end of a port
@@ -56,7 +67,7 @@ impl Solve {
5667
pub fn get_inv_evt(
5768
&self,
5869
inv: ir::InvIdx,
59-
evt: ir::EventIdx,
70+
evt: ir::Foreign<ir::Event, ir::Component>,
6071
) -> smt::SExpr {
6172
self.sol.atom(self.get_evt_name(inv, evt))
6273
}
@@ -232,28 +243,27 @@ impl Visitor for Solve {
232243

233244
log::trace!("Scheduling invocation {}", comp.display(inv_idx));
234245

235-
// Make sure that the invocation is scheduled at a positive time
236-
self.sol
237-
.assert(self.sol.gte(sexpr, self.sol.numeral(0)))
238-
.unwrap();
239-
240246
let inv = comp.get(inv_idx);
241247

242248
// Get the events of the invocation as variables
243249
let events: ir::SparseInfoMap<ir::Event, SExpr> = inv
244250
.events
245251
.iter()
246-
.map(|ir::EventBind { arg, .. }| {
247-
let event = comp.get(*arg).event;
248-
(
249-
event,
250-
self.sol
251-
.declare_const(
252-
self.get_evt_name(inv_idx, event),
253-
self.sol.int_sort(),
254-
)
255-
.unwrap(),
256-
)
252+
.map(|ir::EventBind { base, .. }| {
253+
let sexpr = self
254+
.sol
255+
.declare_const(
256+
self.get_evt_name(inv_idx, *base),
257+
self.sol.int_sort(),
258+
)
259+
.unwrap();
260+
261+
// Make sure that the event is scheduled at a positive time
262+
self.sol
263+
.assert(self.sol.gte(sexpr, self.sol.numeral(0)))
264+
.unwrap();
265+
266+
(base.key(), sexpr)
257267
})
258268
.collect();
259269

@@ -265,13 +275,26 @@ impl Visitor for Solve {
265275

266276
for pidx in inv.ports.iter() {
267277
let port = comp.get(*pidx);
268-
let PortOwner::Inv {
269-
base: foreign_pidx, ..
270-
} = port.owner
278+
let ir::Port {
279+
owner:
280+
ir::PortOwner::Inv {
281+
base: foreign_pidx, ..
282+
},
283+
live:
284+
ir::Liveness {
285+
range: ir::Range { start, end },
286+
..
287+
},
288+
..
289+
} = port
271290
else {
272291
unreachable!("Port {} is not owned by an invocation", pidx)
273292
};
274293

294+
// Find the events associated with the start and end of the port
295+
let start_expr = *events.get(comp.get(*start).event);
296+
let end_expr = *events.get(comp.get(*end).event);
297+
275298
let (start, end) = foreign_pidx.apply(
276299
|p, foreign_comp| {
277300
let ir::Range { start, end } =
@@ -288,9 +311,9 @@ impl Visitor for Solve {
288311
);
289312

290313
// Create expressions for the ports relative to the invocation
291-
let start_expr = self.sol.plus(sexpr, self.sol.numeral(start));
314+
let start_expr = self.sol.plus(start_expr, self.sol.numeral(start));
292315

293-
let end_expr = self.sol.plus(sexpr, self.sol.numeral(end));
316+
let end_expr = self.sol.plus(end_expr, self.sol.numeral(end));
294317

295318
log::trace!(
296319
"Port {} is live from {} to {}",
@@ -397,41 +420,47 @@ impl Visitor for Solve {
397420
// Loop through invocations and find what they're bound to
398421
// collect here to let us mutate [data.comp] inside the loop
399422
for inv_idx in data.comp.invocations().idx_iter() {
400-
let name = self.get_inv(inv_idx);
401-
let SExprData::Atom(s) = self.sol.get(name) else {
402-
unreachable!(
403-
"Expected invocation {} to be an atom, got {}",
404-
inv_idx,
405-
self.sol.display(name)
406-
)
407-
};
408-
409-
let time = *bindings.get(s).unwrap();
410-
411-
let time = data.comp.add(ir::Expr::Concrete(time));
412-
413-
let time = data.comp.add(ir::Time {
414-
event,
415-
offset: time,
416-
});
417-
418-
log::debug!(
419-
"Invocation {} scheduled at cycle {}",
420-
data.comp.display(inv_idx),
421-
data.comp.display(time)
422-
);
423-
424-
// Set the time of the invocation
425-
let inv = data.comp.get_mut(inv_idx);
426-
427-
// make sure this invoke only has one event
428-
// assert_eq!(
429-
// inv.events.len(),
430-
// 1,
431-
// "Attempting to schedule an invocation with multiple events"
432-
// );
433-
434-
inv.events[0].arg = time;
423+
let new_times = data
424+
.comp
425+
.get(inv_idx)
426+
.events
427+
.iter()
428+
.map(|ir::EventBind { base, arg, .. }| {
429+
let SExprData::Atom(s) =
430+
self.sol.get(self.get_inv_evt(inv_idx, *base))
431+
else {
432+
unreachable!()
433+
};
434+
435+
(arg.event(&data.comp), *bindings.get(s).unwrap())
436+
})
437+
.collect_vec();
438+
439+
// Needds to be broken up because we need mutable access to data.comp
440+
let new_times = new_times
441+
.into_iter()
442+
.map(|(event, time)| {
443+
let time = data.comp.add(ir::Expr::Concrete(time));
444+
445+
let time = data.comp.add(ir::Time {
446+
event,
447+
offset: time,
448+
});
449+
450+
log::debug!(
451+
"Invocation {} scheduled at cycle {}",
452+
data.comp.display(inv_idx),
453+
data.comp.display(time)
454+
);
455+
time
456+
})
457+
.collect_vec();
458+
459+
for (ir::EventBind { arg, .. }, time) in
460+
data.comp.get_mut(inv_idx).events.iter_mut().zip(new_times)
461+
{
462+
*arg = time
463+
}
435464
}
436465

437466
// Loop through ports and set their live ranges

0 commit comments

Comments
 (0)