1use super::{
2 Assignment, Attribute, Attributes, BoolAttr, Builder, Cell, CellType,
3 CombGroup, Control, Direction, GetName, Group, Id, NumAttr, PortDef,
4 StaticGroup, RRC,
5};
6use crate::guard::StaticTiming;
7use crate::Nothing;
8use calyx_utils::NameGenerator;
9use itertools::Itertools;
10use linked_hash_map::LinkedHashMap;
11use std::collections::HashSet;
12use std::iter::Extend;
13use std::num::NonZeroU64;
14use std::rc::Rc;
15
16const THIS_ID: &str = "_this";
19
20const INTERFACE_PORTS: [(Attribute, u64, Direction); 4] = [
22 (Attribute::Num(NumAttr::Go), 1, Direction::Input),
23 (Attribute::Bool(BoolAttr::Clk), 1, Direction::Input),
24 (Attribute::Bool(BoolAttr::Reset), 1, Direction::Input),
25 (Attribute::Num(NumAttr::Done), 1, Direction::Output),
26];
27
28#[derive(Debug)]
30#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
31pub struct Component {
32 pub name: Id,
34 pub signature: RRC<Cell>,
36 pub cells: IdList<Cell>,
38 pub groups: IdList<Group>,
40 pub static_groups: IdList<StaticGroup>,
42 pub comb_groups: IdList<CombGroup>,
44 pub continuous_assignments: Vec<Assignment<Nothing>>,
47 pub control: RRC<Control>,
49 pub attributes: Attributes,
51 pub is_comb: bool,
53 pub latency: Option<NonZeroU64>,
55
56 #[cfg_attr(feature = "serialize", serde(skip))]
60 namegen: NameGenerator,
61}
62
63impl Component {
68 pub(super) fn extend_signature(sig: &mut Vec<PortDef<u64>>) {
70 let port_names: HashSet<_> = sig.iter().map(|pd| pd.name()).collect();
71 let mut namegen = NameGenerator::with_prev_defined_names(port_names);
72 for (attr, width, direction) in INTERFACE_PORTS.iter() {
73 if !sig.iter().any(|pd| pd.attributes.has(*attr)) {
76 let mut attributes = Attributes::default();
77 attributes.insert(*attr, 1);
78 let name = Id::from(attr.to_string());
79 sig.push(PortDef::new(
80 namegen.gen_name(name.to_string()),
81 *width,
82 direction.clone(),
83 attributes,
84 ));
85 }
86 }
87 }
88
89 pub fn new<S>(
96 name: S,
97 mut ports: Vec<PortDef<u64>>,
98 has_interface: bool,
99 is_comb: bool,
100 latency: Option<NonZeroU64>,
101 ) -> Self
102 where
103 S: Into<Id>,
104 {
105 if has_interface {
106 Self::extend_signature(&mut ports);
108 }
109
110 let prev_names: HashSet<_> = ports.iter().map(|pd| pd.name()).collect();
111
112 let this_sig = Builder::cell_from_signature(
113 THIS_ID.into(),
114 CellType::ThisComponent,
115 ports
116 .into_iter()
117 .map(|pd| {
119 PortDef::new(
120 pd.name(),
121 pd.width,
122 pd.direction.reverse(),
123 pd.attributes,
124 )
125 })
126 .collect(),
127 );
128
129 Component {
130 name: name.into(),
131 signature: this_sig,
132 cells: IdList::default(),
133 groups: IdList::default(),
134 static_groups: IdList::default(),
135 comb_groups: IdList::default(),
136 continuous_assignments: vec![],
137 control: super::rrc(Control::empty()),
138 namegen: NameGenerator::with_prev_defined_names(prev_names),
139 attributes: Attributes::default(),
140 is_comb,
141 latency,
144 }
145 }
146
147 pub(super) fn add_names(&mut self, names: HashSet<Id>) {
148 self.namegen.add_names(names)
149 }
150
151 pub fn get_groups(&self) -> &IdList<Group> {
153 &self.groups
154 }
155
156 pub fn get_static_groups(&self) -> &IdList<StaticGroup> {
158 &self.static_groups
159 }
160
161 pub fn get_groups_mut(&mut self) -> &mut IdList<Group> {
163 &mut self.groups
164 }
165
166 pub fn get_static_groups_mut(&mut self) -> &mut IdList<StaticGroup> {
168 &mut self.static_groups
169 }
170
171 pub fn set_groups(&mut self, groups: IdList<Group>) {
173 self.groups = groups
174 }
175
176 pub fn set_static_groups(&mut self, static_groups: IdList<StaticGroup>) {
178 self.static_groups = static_groups
179 }
180
181 pub fn find_group<S>(&self, name: S) -> Option<RRC<Group>>
183 where
184 S: Into<Id>,
185 {
186 self.groups.find(name)
187 }
188
189 pub fn find_static_group<S>(&self, name: S) -> Option<RRC<StaticGroup>>
191 where
192 S: Into<Id>,
193 {
194 self.static_groups.find(name)
195 }
196
197 pub fn find_comb_group<S>(&self, name: S) -> Option<RRC<CombGroup>>
199 where
200 S: Into<Id>,
201 {
202 self.comb_groups.find(name)
203 }
204
205 pub fn find_cell<S>(&self, name: S) -> Option<RRC<Cell>>
207 where
208 S: Into<Id>,
209 {
210 self.cells.find(name)
211 }
212
213 pub fn find_guaranteed_cell<S>(&self, name: S) -> RRC<Cell>
215 where
216 S: Into<Id> + std::fmt::Debug + Copy,
217 {
218 self.cells.find(name).unwrap_or_else(|| {
219 unreachable!(
220 "called find_certain_cell on {:?} but it wasn't found",
221 name
222 )
223 })
224 }
225
226 pub fn generate_name<S>(&mut self, prefix: S) -> Id
228 where
229 S: Into<Id>,
230 {
231 self.namegen.gen_name(prefix)
232 }
233
234 pub fn is_structural(&self) -> bool {
236 self.groups.is_empty()
237 && self.comb_groups.is_empty()
238 && self.static_groups.is_empty()
239 && self.control.borrow().is_empty()
240 }
241
242 pub fn is_static(&self) -> bool {
245 self.latency.is_some()
246 }
247
248 pub fn for_each_static_assignment<F>(&mut self, mut f: F)
250 where
251 F: FnMut(&mut Assignment<StaticTiming>),
252 {
253 for group_ref in self.get_static_groups().iter() {
254 let mut assigns =
255 group_ref.borrow_mut().assignments.drain(..).collect_vec();
256 for assign in &mut assigns {
257 f(assign)
258 }
259 group_ref.borrow_mut().assignments = assigns;
260 }
261 }
262
263 pub fn for_each_assignment<F>(&mut self, mut f: F)
265 where
266 F: FnMut(&mut Assignment<Nothing>),
267 {
268 for group_ref in self.groups.iter() {
271 let mut assigns =
272 group_ref.borrow_mut().assignments.drain(..).collect_vec();
273 for assign in &mut assigns {
274 f(assign)
275 }
276 group_ref.borrow_mut().assignments = assigns;
277 }
278 for group_ref in self.comb_groups.iter() {
279 let mut assigns =
280 group_ref.borrow_mut().assignments.drain(..).collect_vec();
281 for assign in &mut assigns {
282 f(assign)
283 }
284 group_ref.borrow_mut().assignments = assigns;
285 }
286 self.continuous_assignments.iter_mut().for_each(f);
287 }
288
289 pub fn iter_assignments<F>(&self, mut f: F)
291 where
292 F: FnMut(&Assignment<Nothing>),
293 {
294 for group_ref in self.groups.iter() {
295 for assign in &group_ref.borrow().assignments {
296 f(assign)
297 }
298 }
299 for group_ref in self.comb_groups.iter() {
300 for assign in &group_ref.borrow().assignments {
301 f(assign)
302 }
303 }
304 self.continuous_assignments.iter().for_each(f);
305 }
306
307 pub fn iter_static_assignments<F>(&self, mut f: F)
309 where
310 F: FnMut(&Assignment<StaticTiming>),
311 {
312 for group_ref in self.get_static_groups().iter() {
313 for assign in &group_ref.borrow().assignments {
314 f(assign)
315 }
316 }
317 }
318}
319
320#[derive(Debug)]
325pub struct IdList<T: GetName>(LinkedHashMap<Id, RRC<T>>);
326
327impl<'a, T: GetName> IntoIterator for &'a IdList<T> {
329 type Item = &'a RRC<T>;
330
331 type IntoIter = linked_hash_map::Values<'a, Id, RRC<T>>;
332
333 fn into_iter(self) -> Self::IntoIter {
334 self.0.values()
335 }
336}
337
338impl<T, F> From<F> for IdList<T>
339where
340 T: GetName,
341 F: IntoIterator<Item = RRC<T>>,
342{
343 fn from(list: F) -> Self {
344 IdList(
345 list.into_iter()
346 .map(|item| {
347 let name = item.borrow().name();
348 (name, item)
349 })
350 .collect::<LinkedHashMap<Id, RRC<T>>>(),
351 )
352 }
353}
354
355impl<T: GetName> IdList<T> {
356 pub fn clear(&mut self) {
358 self.0.clear();
359 }
360
361 pub fn is_empty(&self) -> bool {
363 self.0.is_empty()
364 }
365
366 pub fn len(&self) -> usize {
368 self.0.len()
369 }
370
371 pub fn retain<F>(&mut self, mut f: F) -> u64
374 where
375 F: FnMut(&RRC<T>) -> bool,
376 {
377 let mut removed = 0;
378 for entry in self.0.entries() {
379 if !f(entry.get()) {
380 entry.remove();
381 removed += 1;
382 }
383 }
384 removed
385 }
386
387 pub fn add(&mut self, item: RRC<T>) {
389 let name = item.borrow().name();
390 self.0.insert(name, item);
391 }
392
393 pub fn remove<S>(&mut self, name: S) -> Option<RRC<T>>
395 where
396 S: Into<Id>,
397 {
398 self.0.remove(&name.into())
399 }
400
401 pub fn append(&mut self, items: impl Iterator<Item = RRC<T>>) {
403 let map = items.map(|i| {
404 let name = i.borrow().name();
405 (name, i)
406 });
407 self.0.extend(map);
408 }
409
410 pub fn iter(&self) -> impl Clone + Iterator<Item = &RRC<T>> {
412 self.0.values()
413 }
414
415 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut RRC<T>> {
418 self.0.iter_mut().map(|(_id, val)| val)
419 }
420
421 pub fn drain(&mut self) -> impl Iterator<Item = RRC<T>> {
424 let drain = std::mem::take(&mut self.0);
425
426 drain.into_iter().map(|(_, cell)| cell)
427 }
428
429 pub fn find<S>(&self, name: S) -> Option<RRC<T>>
431 where
432 S: Into<Id>,
433 {
434 self.0.get(&name.into()).map(Rc::clone)
435 }
436}
437
438impl<T: GetName> Default for IdList<T> {
439 fn default() -> Self {
440 IdList(LinkedHashMap::new())
441 }
442}