1use super::{
2 Assignment, Attribute, Attributes, BoolAttr, Builder, Cell, CellType,
3 CombGroup, Control, Direction, FSM, GetName, Group, Id, NumAttr, PortDef,
4 RRC, StaticGroup,
5};
6use crate::Nothing;
7use crate::guard::StaticTiming;
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 fsms: IdList<FSM>,
42 pub static_groups: IdList<StaticGroup>,
44 pub comb_groups: IdList<CombGroup>,
46 pub continuous_assignments: Vec<Assignment<Nothing>>,
49 pub control: RRC<Control>,
51 pub attributes: Attributes,
53 pub is_comb: bool,
55 pub latency: Option<NonZeroU64>,
57
58 #[cfg_attr(feature = "serialize", serde(skip))]
62 namegen: NameGenerator,
63}
64
65impl Component {
70 pub(super) fn extend_signature(sig: &mut Vec<PortDef<u64>>) {
72 let port_names: HashSet<_> = sig.iter().map(|pd| pd.name()).collect();
73 let mut namegen = NameGenerator::with_prev_defined_names(port_names);
74 for (attr, width, direction) in INTERFACE_PORTS.iter() {
75 if !sig.iter().any(|pd| pd.attributes.has(*attr)) {
78 let mut attributes = Attributes::default();
79 attributes.insert(*attr, 1);
80 let name = Id::from(attr.to_string());
81 sig.push(PortDef::new(
82 namegen.gen_name(name.to_string()),
83 *width,
84 direction.clone(),
85 attributes,
86 ));
87 }
88 }
89 }
90
91 pub fn new<S>(
98 name: S,
99 mut ports: Vec<PortDef<u64>>,
100 has_interface: bool,
101 is_comb: bool,
102 latency: Option<NonZeroU64>,
103 ) -> Self
104 where
105 S: Into<Id>,
106 {
107 if has_interface {
108 Self::extend_signature(&mut ports);
110 }
111
112 let prev_names: HashSet<_> = ports.iter().map(|pd| pd.name()).collect();
113
114 let this_sig = Builder::cell_from_signature(
115 THIS_ID.into(),
116 CellType::ThisComponent,
117 ports
118 .into_iter()
119 .map(|pd| {
121 PortDef::new(
122 pd.name(),
123 pd.width,
124 pd.direction.reverse(),
125 pd.attributes,
126 )
127 })
128 .collect(),
129 );
130
131 Component {
132 name: name.into(),
133 signature: this_sig,
134 cells: IdList::default(),
135 groups: IdList::default(),
136 fsms: IdList::default(),
137 static_groups: IdList::default(),
138 comb_groups: IdList::default(),
139 continuous_assignments: vec![],
140 control: super::rrc(Control::empty()),
141 namegen: NameGenerator::with_prev_defined_names(prev_names),
142 attributes: Attributes::default(),
143 is_comb,
144 latency,
147 }
148 }
149
150 pub(super) fn add_names(&mut self, names: HashSet<Id>) {
151 self.namegen.add_names(names)
152 }
153
154 pub fn get_groups(&self) -> &IdList<Group> {
156 &self.groups
157 }
158
159 pub fn get_fsms(&self) -> &IdList<FSM> {
161 &self.fsms
162 }
163
164 pub fn get_static_groups(&self) -> &IdList<StaticGroup> {
166 &self.static_groups
167 }
168
169 pub fn get_groups_mut(&mut self) -> &mut IdList<Group> {
171 &mut self.groups
172 }
173
174 pub fn get_fsms_mut(&mut self) -> &mut IdList<FSM> {
176 &mut self.fsms
177 }
178
179 pub fn get_static_groups_mut(&mut self) -> &mut IdList<StaticGroup> {
181 &mut self.static_groups
182 }
183
184 pub fn set_groups(&mut self, groups: IdList<Group>) {
186 self.groups = groups
187 }
188
189 pub fn set_static_groups(&mut self, static_groups: IdList<StaticGroup>) {
191 self.static_groups = static_groups
192 }
193
194 pub fn find_group<S>(&self, name: S) -> Option<RRC<Group>>
196 where
197 S: Into<Id>,
198 {
199 self.groups.find(name)
200 }
201
202 pub fn find_static_group<S>(&self, name: S) -> Option<RRC<StaticGroup>>
204 where
205 S: Into<Id>,
206 {
207 self.static_groups.find(name)
208 }
209
210 pub fn find_fsm<S>(&self, name: S) -> Option<RRC<FSM>>
212 where
213 S: Into<Id>,
214 {
215 self.fsms.find(name)
216 }
217
218 pub fn find_comb_group<S>(&self, name: S) -> Option<RRC<CombGroup>>
220 where
221 S: Into<Id>,
222 {
223 self.comb_groups.find(name)
224 }
225
226 pub fn find_cell<S>(&self, name: S) -> Option<RRC<Cell>>
228 where
229 S: Into<Id>,
230 {
231 self.cells.find(name)
232 }
233
234 pub fn find_guaranteed_cell<S>(&self, name: S) -> RRC<Cell>
236 where
237 S: Into<Id> + std::fmt::Debug + Copy,
238 {
239 self.cells.find(name).unwrap_or_else(|| {
240 unreachable!(
241 "called find_certain_cell on {:?} but it wasn't found",
242 name
243 )
244 })
245 }
246
247 pub fn generate_name<S>(&mut self, prefix: S) -> Id
249 where
250 S: Into<Id>,
251 {
252 self.namegen.gen_name(prefix)
253 }
254
255 pub fn is_structural(&self) -> bool {
257 self.groups.is_empty()
258 && self.comb_groups.is_empty()
259 && self.static_groups.is_empty()
260 && self.control.borrow().is_empty()
261 }
262
263 pub fn is_static(&self) -> bool {
266 self.latency.is_some()
267 }
268
269 pub fn for_each_static_assignment<F>(&mut self, mut f: F)
271 where
272 F: FnMut(&mut Assignment<StaticTiming>),
273 {
274 for group_ref in self.get_static_groups().iter() {
275 let mut assigns =
276 group_ref.borrow_mut().assignments.drain(..).collect_vec();
277 for assign in &mut assigns {
278 f(assign)
279 }
280 group_ref.borrow_mut().assignments = assigns;
281 }
282 }
283
284 pub fn for_each_assignment<F>(&mut self, mut f: F)
286 where
287 F: FnMut(&mut Assignment<Nothing>),
288 {
289 for group_ref in self.groups.iter() {
292 let mut assigns =
293 group_ref.borrow_mut().assignments.drain(..).collect_vec();
294 for assign in &mut assigns {
295 f(assign)
296 }
297 group_ref.borrow_mut().assignments = assigns;
298 }
299 for group_ref in self.comb_groups.iter() {
300 let mut assigns =
301 group_ref.borrow_mut().assignments.drain(..).collect_vec();
302 for assign in &mut assigns {
303 f(assign)
304 }
305 group_ref.borrow_mut().assignments = assigns;
306 }
307 self.continuous_assignments.iter_mut().for_each(f);
308 }
309
310 pub fn iter_assignments<F>(&self, mut f: F)
312 where
313 F: FnMut(&Assignment<Nothing>),
314 {
315 for group_ref in self.groups.iter() {
316 for assign in &group_ref.borrow().assignments {
317 f(assign)
318 }
319 }
320 for group_ref in self.comb_groups.iter() {
321 for assign in &group_ref.borrow().assignments {
322 f(assign)
323 }
324 }
325 self.continuous_assignments.iter().for_each(f);
326 }
327
328 pub fn iter_static_assignments<F>(&self, mut f: F)
330 where
331 F: FnMut(&Assignment<StaticTiming>),
332 {
333 for group_ref in self.get_static_groups().iter() {
334 for assign in &group_ref.borrow().assignments {
335 f(assign)
336 }
337 }
338 }
339}
340
341#[derive(Debug)]
346pub struct IdList<T: GetName>(LinkedHashMap<Id, RRC<T>>);
347
348impl<'a, T: GetName> IntoIterator for &'a IdList<T> {
350 type Item = &'a RRC<T>;
351
352 type IntoIter = linked_hash_map::Values<'a, Id, RRC<T>>;
353
354 fn into_iter(self) -> Self::IntoIter {
355 self.0.values()
356 }
357}
358
359impl<T, F> From<F> for IdList<T>
360where
361 T: GetName,
362 F: IntoIterator<Item = RRC<T>>,
363{
364 fn from(list: F) -> Self {
365 IdList(
366 list.into_iter()
367 .map(|item| {
368 let name = item.borrow().name();
369 (name, item)
370 })
371 .collect::<LinkedHashMap<Id, RRC<T>>>(),
372 )
373 }
374}
375
376impl<T: GetName> IdList<T> {
377 pub fn clear(&mut self) {
379 self.0.clear();
380 }
381
382 pub fn is_empty(&self) -> bool {
384 self.0.is_empty()
385 }
386
387 pub fn len(&self) -> usize {
389 self.0.len()
390 }
391
392 pub fn retain<F>(&mut self, mut f: F) -> u64
395 where
396 F: FnMut(&RRC<T>) -> bool,
397 {
398 let mut removed = 0;
399 for entry in self.0.entries() {
400 if !f(entry.get()) {
401 entry.remove();
402 removed += 1;
403 }
404 }
405 removed
406 }
407
408 pub fn add(&mut self, item: RRC<T>) {
410 let name = item.borrow().name();
411 self.0.insert(name, item);
412 }
413
414 pub fn remove<S>(&mut self, name: S) -> Option<RRC<T>>
416 where
417 S: Into<Id>,
418 {
419 self.0.remove(&name.into())
420 }
421
422 pub fn append(&mut self, items: impl Iterator<Item = RRC<T>>) {
424 let map = items.map(|i| {
425 let name = i.borrow().name();
426 (name, i)
427 });
428 self.0.extend(map);
429 }
430
431 pub fn iter(&self) -> impl Clone + Iterator<Item = &RRC<T>> {
433 self.0.values()
434 }
435
436 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut RRC<T>> {
439 self.0.iter_mut().map(|(_id, val)| val)
440 }
441
442 pub fn drain(&mut self) -> impl Iterator<Item = RRC<T>> + use<T> {
445 let drain = std::mem::take(&mut self.0);
446
447 drain.into_iter().map(|(_, cell)| cell)
448 }
449
450 pub fn find<S>(&self, name: S) -> Option<RRC<T>>
452 where
453 S: Into<Id>,
454 {
455 self.0.get(&name.into()).map(Rc::clone)
456 }
457}
458
459impl<T: GetName> Default for IdList<T> {
460 fn default() -> Self {
461 IdList(LinkedHashMap::new())
462 }
463}