1use std::{borrow::Cow, hash::Hash};
2
3use crate::{ControlNet, Design, Net, TargetCellPurity, Value};
4
5mod decision;
6mod flip_flop;
7mod memory;
8mod io_buffer;
9mod target;
10mod instance;
11
12pub use decision::{MatchCell, AssignCell};
13pub use flip_flop::FlipFlop;
14pub use memory::{Memory, MemoryWritePort, MemoryReadPort, MemoryReadFlipFlop, MemoryPortRelation};
15pub use io_buffer::IoBuffer;
16pub use target::TargetCell;
17pub use instance::Instance;
18
19#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25pub(crate) enum CellRepr {
26 Void,
32
33 Skip(u32),
36
37 Buf(Net),
38 Not(Net),
39 And(Net, Net),
40 Or(Net, Net),
41 Xor(Net, Net),
42 Mux(Net, Net, Net), Adc(Net, Net, Net), Aig(Net, bool, Net, bool),
45
46 Boxed(Box<Cell>),
47}
48
49#[derive(Clone, Debug, PartialEq, Eq, Hash)]
59pub enum Cell {
60 Buf(Value),
61 Not(Value),
62 And(Value, Value),
67 Or(Value, Value),
72 Xor(Value, Value),
73 Mux(Net, Value, Value),
79 Adc(Value, Value, Net), Aig(ControlNet, ControlNet),
91
92 Eq(Value, Value),
93 ULt(Value, Value),
94 SLt(Value, Value),
95
96 Shl(Value, Value, u32),
108 UShr(Value, Value, u32),
112 SShr(Value, Value, u32),
121 XShr(Value, Value, u32),
125
126 Mul(Value, Value),
128 UDiv(Value, Value),
129 UMod(Value, Value),
130 SDivTrunc(Value, Value),
131 SDivFloor(Value, Value),
132 SModTrunc(Value, Value),
133 SModFloor(Value, Value),
134
135 Match(MatchCell),
136 Assign(AssignCell),
137
138 Dff(FlipFlop),
139 Memory(Memory),
140 IoBuf(IoBuffer),
141 Target(TargetCell),
142 Other(Instance),
143
144 Input(String, usize),
150 Output(String, Value),
156 Name(String, Value),
168 Debug(String, Value),
180}
181
182impl Cell {
183 pub fn validate(&self, design: &Design) {
184 match self {
185 Cell::Buf(_) => (),
186 Cell::Not(_) => (),
187 Cell::Aig(..) => (),
188 Cell::And(arg1, arg2)
189 | Cell::Or(arg1, arg2)
190 | Cell::Xor(arg1, arg2)
191 | Cell::Mux(_, arg1, arg2)
192 | Cell::Adc(arg1, arg2, _)
193 | Cell::Eq(arg1, arg2)
194 | Cell::ULt(arg1, arg2)
195 | Cell::Mul(arg1, arg2)
196 | Cell::UDiv(arg1, arg2)
197 | Cell::UMod(arg1, arg2) => assert_eq!(arg1.len(), arg2.len()),
198 Cell::SLt(arg1, arg2)
199 | Cell::SDivTrunc(arg1, arg2)
200 | Cell::SDivFloor(arg1, arg2)
201 | Cell::SModTrunc(arg1, arg2)
202 | Cell::SModFloor(arg1, arg2) => {
203 assert_eq!(arg1.len(), arg2.len());
204 assert!(!arg1.is_empty());
205 }
206
207 Cell::Shl(..) => (),
208 Cell::UShr(..) => (),
209 Cell::SShr(arg1, _, _) => assert!(!arg1.is_empty()),
210 Cell::XShr(..) => (),
211
212 Cell::Match(match_cell) => {
213 for alternates in &match_cell.patterns {
214 for pattern in alternates {
215 assert_eq!(match_cell.value.len(), pattern.len());
216 }
217 }
218 }
219 Cell::Assign(assign_cell) => {
220 assert!(assign_cell.value.len() >= assign_cell.update.len() + assign_cell.offset);
221 }
222
223 Cell::Dff(flip_flop) => {
224 assert_eq!(flip_flop.data.len(), flip_flop.init_value.len());
225 assert_eq!(flip_flop.data.len(), flip_flop.clear_value.len());
226 assert_eq!(flip_flop.data.len(), flip_flop.reset_value.len());
227 }
228 Cell::Memory(memory) => {
229 assert_eq!(memory.init_value.len(), memory.depth * memory.width);
230 for port in &memory.write_ports {
231 assert_eq!(port.data.len(), port.mask.len());
232 if memory.width == 0 {
233 assert_eq!(port.data.len(), 0);
234 } else {
235 assert_eq!(port.data.len() % memory.width, 0);
236 let wide_factor = port.data.len() / memory.width;
237 assert!(wide_factor.is_power_of_two());
238 assert_eq!(memory.depth % wide_factor, 0);
239 }
240 }
241 for port in &memory.read_ports {
242 if memory.width == 0 {
243 assert_eq!(port.data_len, 0);
244 } else {
245 assert_eq!(port.data_len % memory.width, 0);
246 let wide_factor = port.data_len / memory.width;
247 assert!(wide_factor.is_power_of_two());
248 assert_eq!(memory.depth % wide_factor, 0);
249 }
250 if let Some(ref flip_flop) = port.flip_flop {
251 assert_eq!(flip_flop.clear_value.len(), port.data_len);
252 assert_eq!(flip_flop.reset_value.len(), port.data_len);
253 assert_eq!(flip_flop.init_value.len(), port.data_len);
254 assert_eq!(flip_flop.relations.len(), memory.write_ports.len());
255 for (write_port_index, &relation) in flip_flop.relations.iter().enumerate() {
256 if relation != MemoryPortRelation::Undefined {
257 assert_eq!(memory.write_ports[write_port_index].clock, flip_flop.clock);
258 }
259 }
260 }
261 }
262 }
263 Cell::IoBuf(io_buffer) => {
264 assert_eq!(io_buffer.output.len(), io_buffer.io.len());
265 }
266 Cell::Target(target_cell) => {
267 let prototype = design.target_prototype(target_cell);
268 assert_eq!(target_cell.params.len(), prototype.params.len());
269 for (param, value) in prototype.params.iter().zip(target_cell.params.iter()) {
270 assert!(param.kind.is_valid(value));
271 }
272 assert_eq!(target_cell.inputs.len(), prototype.input_len);
273 assert_eq!(target_cell.output_len, prototype.output_len);
274 assert_eq!(target_cell.ios.len(), prototype.io_len);
275 let target = design.target().unwrap();
276 target.validate(design, target_cell);
277 }
278 Cell::Other(_instance) => {
279 }
281 Cell::Input(..) => (),
282 Cell::Output(..) => (),
283 Cell::Name(..) | Cell::Debug(..) => (),
284 }
285 }
286
287 pub fn slice(&self, range: impl std::ops::RangeBounds<usize> + Clone) -> Option<Cell> {
290 match self {
291 Cell::Buf(arg) => Some(Cell::Buf(arg.slice(range))),
292 Cell::Not(arg) => Some(Cell::Not(arg.slice(range))),
293 Cell::And(arg1, arg2) => Some(Cell::And(arg1.slice(range.clone()), arg2.slice(range))),
294 Cell::Or(arg1, arg2) => Some(Cell::Or(arg1.slice(range.clone()), arg2.slice(range))),
295 Cell::Xor(arg1, arg2) => Some(Cell::Xor(arg1.slice(range.clone()), arg2.slice(range))),
296 Cell::Mux(arg1, arg2, arg3) => Some(Cell::Mux(*arg1, arg2.slice(range.clone()), arg3.slice(range))),
297 Cell::Dff(flip_flop) => Some(Cell::Dff(flip_flop.slice(range))),
298 Cell::IoBuf(io_buffer) => Some(Cell::IoBuf(io_buffer.slice(range))),
299 _ => None,
300 }
301 }
302}
303
304impl<'a> From<&'a Cell> for Cow<'a, Cell> {
305 fn from(value: &'a Cell) -> Self {
306 Cow::Borrowed(value)
307 }
308}
309
310impl From<Cell> for Cow<'_, Cell> {
311 fn from(value: Cell) -> Self {
312 Cow::Owned(value)
313 }
314}
315
316impl CellRepr {
317 pub fn get(&self) -> Cow<'_, Cell> {
318 match *self {
319 CellRepr::Void => unreachable!("void cell"),
320 CellRepr::Skip(_) => unreachable!("skip cell"),
321
322 CellRepr::Buf(arg) => Cow::Owned(Cell::Buf(Value::from(arg))),
323 CellRepr::Not(arg) => Cow::Owned(Cell::Not(Value::from(arg))),
324 CellRepr::And(arg1, arg2) => Cow::Owned(Cell::And(Value::from(arg1), Value::from(arg2))),
325 CellRepr::Or(arg1, arg2) => Cow::Owned(Cell::Or(Value::from(arg1), Value::from(arg2))),
326 CellRepr::Xor(arg1, arg2) => Cow::Owned(Cell::Xor(Value::from(arg1), Value::from(arg2))),
327 CellRepr::Mux(arg1, arg2, arg3) => Cow::Owned(Cell::Mux(arg1, Value::from(arg2), Value::from(arg3))),
328 CellRepr::Adc(arg1, arg2, arg3) => Cow::Owned(Cell::Adc(Value::from(arg1), Value::from(arg2), arg3)),
329 CellRepr::Aig(arg1, inv1, arg2, inv2) => {
330 Cow::Owned(Cell::Aig(ControlNet::from_net_invert(arg1, inv1), ControlNet::from_net_invert(arg2, inv2)))
331 }
332
333 CellRepr::Boxed(ref cell) => Cow::Borrowed(cell),
334 }
335 }
336}
337
338impl From<Cell> for CellRepr {
339 fn from(value: Cell) -> Self {
340 match value {
341 Cell::Buf(arg) if arg.len() == 1 => CellRepr::Buf(arg[0]),
342 Cell::Not(arg) if arg.len() == 1 => CellRepr::Not(arg[0]),
343 Cell::And(arg1, arg2) if arg1.len() == 1 && arg2.len() == 1 => CellRepr::And(arg1[0], arg2[0]),
344 Cell::Or(arg1, arg2) if arg1.len() == 1 && arg2.len() == 1 => CellRepr::Or(arg1[0], arg2[0]),
345 Cell::Xor(arg1, arg2) if arg1.len() == 1 && arg2.len() == 1 => CellRepr::Xor(arg1[0], arg2[0]),
346 Cell::Mux(arg1, arg2, arg3) if arg2.len() == 1 && arg3.len() == 1 => CellRepr::Mux(arg1, arg2[0], arg3[0]),
347 Cell::Adc(arg1, arg2, arg3) if arg1.len() == 1 && arg2.len() == 1 => CellRepr::Adc(arg1[0], arg2[0], arg3),
348 Cell::Aig(arg1, arg2) => CellRepr::Aig(arg1.net(), arg1.is_negative(), arg2.net(), arg2.is_negative()),
349
350 cell => CellRepr::Boxed(Box::new(cell)),
351 }
352 }
353}
354
355impl CellRepr {
356 pub fn output_len(&self) -> usize {
357 match self {
358 CellRepr::Void => unreachable!("void cell"),
359 CellRepr::Skip(_) => unreachable!("skip cell"),
360
361 CellRepr::Buf(..)
362 | CellRepr::Not(..)
363 | CellRepr::And(..)
364 | CellRepr::Or(..)
365 | CellRepr::Xor(..)
366 | CellRepr::Mux(..)
367 | CellRepr::Aig(..) => 1,
368 CellRepr::Adc(..) => 2,
369
370 CellRepr::Boxed(cell) => cell.output_len(),
371 }
372 }
373
374 pub(crate) fn visit(&self, mut f: impl FnMut(Net)) {
375 match self {
376 CellRepr::Void => unreachable!("void cell"),
377 CellRepr::Skip(_) => unreachable!("skip cell"),
378
379 CellRepr::Buf(arg) | CellRepr::Not(arg) => arg.visit(&mut f),
380 CellRepr::And(arg1, arg2)
381 | CellRepr::Or(arg1, arg2)
382 | CellRepr::Xor(arg1, arg2)
383 | CellRepr::Aig(arg1, _, arg2, _) => {
384 arg1.visit(&mut f);
385 arg2.visit(&mut f);
386 }
387 CellRepr::Mux(arg1, arg2, arg3) | CellRepr::Adc(arg1, arg2, arg3) => {
388 arg1.visit(&mut f);
389 arg2.visit(&mut f);
390 arg3.visit(&mut f);
391 }
392
393 CellRepr::Boxed(cell) => cell.visit(&mut f),
394 }
395 }
396
397 pub(crate) fn visit_mut(&mut self, mut f: impl FnMut(&mut Net)) {
398 match self {
399 CellRepr::Void => unreachable!("void cell"),
400 CellRepr::Skip(_) => unreachable!("skip cell"),
401
402 CellRepr::Buf(arg) | CellRepr::Not(arg) => arg.visit_mut(&mut f),
403 CellRepr::And(arg1, arg2)
404 | CellRepr::Or(arg1, arg2)
405 | CellRepr::Xor(arg1, arg2)
406 | CellRepr::Aig(arg1, _, arg2, _) => {
407 arg1.visit_mut(&mut f);
408 arg2.visit_mut(&mut f);
409 }
410 CellRepr::Mux(arg1, arg2, arg3) | CellRepr::Adc(arg1, arg2, arg3) => {
411 arg1.visit_mut(&mut f);
412 arg2.visit_mut(&mut f);
413 arg3.visit_mut(&mut f);
414 }
415
416 CellRepr::Boxed(cell) => cell.visit_mut(&mut f),
417 }
418 }
419}
420
421impl Cell {
422 pub fn output_len(&self) -> usize {
423 match self {
424 Cell::Buf(arg) | Cell::Not(arg) => arg.len(),
425 Cell::And(arg1, arg2) | Cell::Or(arg1, arg2) | Cell::Xor(arg1, arg2) | Cell::Mux(_, arg1, arg2) => {
426 debug_assert_eq!(arg1.len(), arg2.len());
427 arg1.len()
428 }
429 Cell::Adc(arg1, arg2, _) => {
430 debug_assert_eq!(arg1.len(), arg2.len());
431 arg1.len() + 1
432 }
433 Cell::Aig(..) => 1,
434
435 Cell::Eq(..) | Cell::ULt(..) | Cell::SLt(..) => 1,
436
437 Cell::Shl(arg1, _, _) | Cell::UShr(arg1, _, _) | Cell::SShr(arg1, _, _) | Cell::XShr(arg1, _, _) => {
438 arg1.len()
439 }
440
441 Cell::Mul(arg1, arg2)
442 | Cell::UDiv(arg1, arg2)
443 | Cell::UMod(arg1, arg2)
444 | Cell::SDivTrunc(arg1, arg2)
445 | Cell::SDivFloor(arg1, arg2)
446 | Cell::SModTrunc(arg1, arg2)
447 | Cell::SModFloor(arg1, arg2) => {
448 debug_assert_eq!(arg1.len(), arg2.len());
449 arg1.len()
450 }
451
452 Cell::Match(match_cell) => match_cell.output_len(),
453 Cell::Assign(assign_cell) => assign_cell.output_len(),
454
455 Cell::Dff(flip_flop) => flip_flop.output_len(),
456 Cell::Memory(memory) => memory.output_len(),
457 Cell::IoBuf(io_buffer) => io_buffer.output_len(),
458 Cell::Target(target_cell) => target_cell.output_len,
459 Cell::Other(instance) => instance.output_len(),
460
461 Cell::Input(_, width) => *width,
462 Cell::Output(..) => 0,
463 Cell::Name(..) | Cell::Debug(..) => 0,
464 }
465 }
466
467 pub fn has_effects(&self, design: &Design) -> bool {
468 match self {
469 Cell::IoBuf(_) | Cell::Other(_) | Cell::Input(..) | Cell::Output(..) | Cell::Name(..) => true,
470
471 Cell::Target(target_cell) => design.target_prototype(&target_cell).purity == TargetCellPurity::HasEffects,
472
473 _ => false,
474 }
475 }
476
477 pub fn visit(&self, mut f: impl FnMut(Net)) {
478 match self {
479 Cell::Input(..) => (),
480 Cell::Buf(arg) | Cell::Not(arg) | Cell::Output(_, arg) | Cell::Name(_, arg) | Cell::Debug(_, arg) => {
481 arg.visit(&mut f)
482 }
483 Cell::And(arg1, arg2)
484 | Cell::Or(arg1, arg2)
485 | Cell::Xor(arg1, arg2)
486 | Cell::Mul(arg1, arg2)
487 | Cell::UDiv(arg1, arg2)
488 | Cell::UMod(arg1, arg2)
489 | Cell::SDivTrunc(arg1, arg2)
490 | Cell::SDivFloor(arg1, arg2)
491 | Cell::SModTrunc(arg1, arg2)
492 | Cell::SModFloor(arg1, arg2)
493 | Cell::Eq(arg1, arg2)
494 | Cell::ULt(arg1, arg2)
495 | Cell::SLt(arg1, arg2)
496 | Cell::Shl(arg1, arg2, _)
497 | Cell::UShr(arg1, arg2, _)
498 | Cell::SShr(arg1, arg2, _)
499 | Cell::XShr(arg1, arg2, _) => {
500 arg1.visit(&mut f);
501 arg2.visit(&mut f);
502 }
503 Cell::Aig(arg1, arg2) => {
504 arg1.visit(&mut f);
505 arg2.visit(&mut f);
506 }
507 Cell::Mux(net, value1, value2) | Cell::Adc(value1, value2, net) => {
508 value1.visit(&mut f);
509 value2.visit(&mut f);
510 net.visit(&mut f);
511 }
512 Cell::Match(match_cell) => match_cell.visit(&mut f),
513 Cell::Assign(assign_cell) => assign_cell.visit(&mut f),
514 Cell::Dff(flip_flop) => flip_flop.visit(&mut f),
515 Cell::Memory(memory) => memory.visit(&mut f),
516 Cell::IoBuf(io_buffer) => io_buffer.visit(&mut f),
517 Cell::Target(target_cell) => target_cell.visit(&mut f),
518 Cell::Other(instance) => instance.visit(&mut f),
519 }
520 }
521
522 pub fn visit_mut(&mut self, mut f: impl FnMut(&mut Net)) {
523 match self {
524 Cell::Input(..) => (),
525 Cell::Buf(arg) | Cell::Not(arg) | Cell::Output(_, arg) | Cell::Name(_, arg) | Cell::Debug(_, arg) => {
526 arg.visit_mut(&mut f)
527 }
528 Cell::And(arg1, arg2)
529 | Cell::Or(arg1, arg2)
530 | Cell::Xor(arg1, arg2)
531 | Cell::Mul(arg1, arg2)
532 | Cell::UDiv(arg1, arg2)
533 | Cell::UMod(arg1, arg2)
534 | Cell::SDivTrunc(arg1, arg2)
535 | Cell::SDivFloor(arg1, arg2)
536 | Cell::SModTrunc(arg1, arg2)
537 | Cell::SModFloor(arg1, arg2)
538 | Cell::Eq(arg1, arg2)
539 | Cell::ULt(arg1, arg2)
540 | Cell::SLt(arg1, arg2)
541 | Cell::Shl(arg1, arg2, _)
542 | Cell::UShr(arg1, arg2, _)
543 | Cell::SShr(arg1, arg2, _)
544 | Cell::XShr(arg1, arg2, _) => {
545 arg1.visit_mut(&mut f);
546 arg2.visit_mut(&mut f);
547 }
548 Cell::Aig(arg1, arg2) => {
549 arg1.visit_mut(&mut f);
550 arg2.visit_mut(&mut f);
551 }
552 Cell::Mux(net, value1, value2) | Cell::Adc(value1, value2, net) => {
553 value1.visit_mut(&mut f);
554 value2.visit_mut(&mut f);
555 net.visit_mut(&mut f);
556 }
557 Cell::Match(match_cell) => match_cell.visit_mut(&mut f),
558 Cell::Assign(assign_cell) => assign_cell.visit_mut(&mut f),
559 Cell::Dff(flip_flop) => flip_flop.visit_mut(&mut f),
560 Cell::Memory(memory) => memory.visit_mut(&mut f),
561 Cell::IoBuf(io_buffer) => io_buffer.visit_mut(&mut f),
562 Cell::Target(target_cell) => target_cell.visit_mut(&mut f),
563 Cell::Other(instance) => instance.visit_mut(&mut f),
564 }
565 }
566}
567
568#[cfg(test)]
569mod test {
570 use crate::cell::CellRepr;
571
572 #[test]
573 fn test_size() {
574 assert!(size_of::<CellRepr>() == 16);
575 }
576}