1use syn::{Expr, Ident};
2
3use crate::{
4 analyze::{Analysis, Location, Priority},
5 ast::{Access, App, LateResource},
6 Context, Core, Set,
7};
8
9impl App {
10 pub fn uses_schedule(&self, core: u8) -> bool {
12 assert!(core < self.args.cores);
13
14 self.inits
15 .get(&core)
16 .map(|init| !init.args.schedule.is_empty())
17 .unwrap_or(false)
18 || self
19 .idles
20 .get(&core)
21 .map(|idle| !idle.args.schedule.is_empty())
22 .unwrap_or(false)
23 || self
24 .hardware_tasks
25 .values()
26 .any(|task| task.args.core == core && !task.args.schedule.is_empty())
27 || self
28 .software_tasks
29 .values()
30 .any(|task| task.args.core == core && !task.args.schedule.is_empty())
31 }
32
33 pub fn resource(&self, name: &Ident) -> Option<(&LateResource, Option<&Expr>)> {
35 self.late_resources
36 .get(name)
37 .map(|late| (late, None))
38 .or_else(|| {
39 self.resources
40 .get(name)
41 .map(|res| (&res.late, Some(&*res.expr)))
42 })
43 }
44
45 pub fn resources<'a>(
47 &'a self,
48 analysis: &'a Analysis,
49 ) -> impl Iterator<Item = (&'a Ident, &'a LateResource, Option<&'a Expr>, &'a Location)> {
50 analysis.locations.iter().map(move |(name, loc)| {
51 let (res, expr) = self.resource(name).expect("UNREACHABLE");
52
53 (name, res, expr, loc)
54 })
55 }
56
57 pub fn schedule_callers<'a>(&'a self) -> impl Iterator<Item = (Context<'a>, &'a Set<Ident>)> {
59 self.inits
60 .iter()
61 .filter_map(|(&core, init)| {
62 if !init.args.schedule.is_empty() {
63 Some((Context::Init(core), &init.args.schedule))
64 } else {
65 None
66 }
67 })
68 .chain(self.idles.iter().filter_map(|(&core, idle)| {
69 if !idle.args.schedule.is_empty() {
70 Some((Context::Idle(core), &idle.args.schedule))
71 } else {
72 None
73 }
74 }))
75 .chain(self.hardware_tasks.iter().filter_map(|(name, task)| {
76 if !task.args.schedule.is_empty() {
77 Some((Context::HardwareTask(name), &task.args.schedule))
78 } else {
79 None
80 }
81 }))
82 .chain(self.software_tasks.iter().filter_map(|(name, task)| {
83 if !task.args.schedule.is_empty() {
84 Some((Context::SoftwareTask(name), &task.args.schedule))
85 } else {
86 None
87 }
88 }))
89 }
90
91 pub fn spawn_callers<'a>(&'a self) -> impl Iterator<Item = (Context<'a>, &'a Set<Ident>)> {
93 self.inits
94 .iter()
95 .filter_map(|(&core, init)| {
96 if !init.args.spawn.is_empty() {
97 Some((Context::Init(core), &init.args.spawn))
98 } else {
99 None
100 }
101 })
102 .chain(self.idles.iter().filter_map(|(&core, idle)| {
103 if !idle.args.spawn.is_empty() {
104 Some((Context::Idle(core), &idle.args.spawn))
105 } else {
106 None
107 }
108 }))
109 .chain(self.hardware_tasks.iter().filter_map(|(name, task)| {
110 if !task.args.spawn.is_empty() {
111 Some((Context::HardwareTask(name), &task.args.spawn))
112 } else {
113 None
114 }
115 }))
116 .chain(self.software_tasks.iter().filter_map(|(name, task)| {
117 if !task.args.spawn.is_empty() {
118 Some((Context::SoftwareTask(name), &task.args.spawn))
119 } else {
120 None
121 }
122 }))
123 }
124
125 pub(crate) fn resource_accesses(
126 &self,
127 ) -> impl Iterator<Item = (Core, Option<Priority>, &Ident, Access)> {
128 self.inits
129 .iter()
130 .flat_map(|(core, init)| {
131 init.args
132 .resources
133 .iter()
134 .map(move |(name, access)| (*core, None, name, *access))
135 })
136 .chain(self.idles.iter().flat_map(|(core, idle)| {
137 idle.args
138 .resources
139 .iter()
140 .map(move |(name, access)| (*core, Some(0), name, *access))
141 }))
142 .chain(self.hardware_tasks.values().flat_map(|task| {
143 task.args.resources.iter().map(move |(name, access)| {
144 (task.args.core, Some(task.args.priority), name, *access)
145 })
146 }))
147 .chain(self.software_tasks.values().flat_map(|task| {
148 task.args.resources.iter().map(move |(name, access)| {
149 (task.args.core, Some(task.args.priority), name, *access)
150 })
151 }))
152 }
153
154 pub(crate) fn schedule_calls(&self) -> impl Iterator<Item = (Core, Option<Priority>, &Ident)> {
155 self.inits
156 .iter()
157 .flat_map(|(&core, init)| {
158 init.args
159 .schedule
160 .iter()
161 .map(move |task| (core, None, task))
162 })
163 .chain(self.idles.iter().flat_map(|(&core, idle)| {
164 idle.args
165 .schedule
166 .iter()
167 .map(move |task| (core, Some(0), task))
168 }))
169 .chain(self.hardware_tasks.values().flat_map(|scheduler| {
170 scheduler.args.schedule.iter().map(move |schedulee| {
171 (
172 scheduler.args.core,
173 Some(scheduler.args.priority),
174 schedulee,
175 )
176 })
177 }))
178 .chain(self.software_tasks.values().flat_map(|scheduler| {
179 scheduler.args.schedule.iter().map(move |schedulee| {
180 (
181 scheduler.args.core,
182 Some(scheduler.args.priority),
183 schedulee,
184 )
185 })
186 }))
187 }
188
189 pub(crate) fn spawn_calls(&self) -> impl Iterator<Item = (Core, Option<Priority>, &Ident)> {
196 self.inits
197 .iter()
198 .flat_map(|(&core, init)| init.args.spawn.iter().map(move |task| (core, None, task)))
199 .chain(self.idles.iter().flat_map(|(&core, idle)| {
200 idle.args
201 .spawn
202 .iter()
203 .map(move |task| (core, Some(0), task))
204 }))
205 .chain(self.hardware_tasks.values().flat_map(|spawner| {
206 spawner
207 .args
208 .spawn
209 .iter()
210 .map(move |spawnee| (spawner.args.core, Some(spawner.args.priority), spawnee))
211 }))
212 .chain(self.software_tasks.values().flat_map(|spawner| {
213 spawner
214 .args
215 .spawn
216 .iter()
217 .map(move |spawnee| (spawner.args.core, Some(spawner.args.priority), spawnee))
218 }))
219 }
220
221 pub(crate) fn task_references(&self) -> impl Iterator<Item = &Ident> {
222 self.inits
223 .values()
224 .flat_map(|init| init.args.spawn.iter().chain(&init.args.schedule))
225 .chain(
226 self.idles
227 .values()
228 .flat_map(|idle| idle.args.spawn.iter().chain(&idle.args.schedule)),
229 )
230 .chain(
231 self.hardware_tasks
232 .values()
233 .flat_map(|task| task.args.spawn.iter().chain(&task.args.schedule)),
234 )
235 .chain(
236 self.software_tasks
237 .values()
238 .flat_map(|task| task.args.spawn.iter().chain(&task.args.schedule)),
239 )
240 }
241}