1use crate::layout::prelude::{Geometry, SimpleTransform};
21use crate::netlist::direction::Direction;
22use crate::prelude::PropertyValue;
23use crate::traits::*;
24use std::ops::Deref;
25
26pub enum NetlistUndoOp<T: NetlistBase> {
28 HierarchyOp(HierarchyUndoOp<T>),
30 CreatePin(T::PinId),
32 RenamePin(T::PinId, T::NameType),
34 CreateNet(T::NetId),
36 ConnectPin(T::PinId, Option<T::NetId>),
38 ConnectPinInstance(T::PinInstId, Option<T::NetId>),
40 RenameNet(T::NetId, Option<T::NameType>),
42 }
45
46impl<T: NetlistBase> From<HierarchyUndoOp<T>> for NetlistUndoOp<T> {
47 fn from(op: HierarchyUndoOp<T>) -> Self {
48 Self::HierarchyOp(op)
49 }
50}
51
52pub enum LayoutUndoOp<T: LayoutBase> {
54 HierarchyOp(HierarchyUndoOp<T>),
56 SetDbu(T::Coord),
58 CreateLayer(T::LayerId),
60 SetLayerName(T::LayerId, Option<T::NameType>),
62 InsertShape(T::ShapeId),
64 RemoveShape {
66 parent_cell: T::CellId,
68 layer: T::LayerId,
70 geometry: Geometry<T::Coord>,
72 },
73 ReplaceShape(T::ShapeId, Geometry<T::Coord>),
75 SetTransform(T::CellInstId, SimpleTransform<T::Coord>),
77}
78
79impl<T: LayoutBase> From<HierarchyUndoOp<T>> for LayoutUndoOp<T> {
80 fn from(op: HierarchyUndoOp<T>) -> Self {
81 Self::HierarchyOp(op)
82 }
83}
84
85#[allow(missing_docs)]
87pub enum L2NUndoOp<T: L2NBase> {
88 HierarchyOp(HierarchyUndoOp<T>),
90 NetlistOp(NetlistUndoOp<T>),
92 LayoutOp(LayoutUndoOp<T>),
94 SetNetOfShape {
96 shape_id: T::ShapeId,
97 previous_net: Option<T::NetId>,
98 },
99 SetPinOfShape {
101 shape_id: T::ShapeId,
102 previous_pin: Option<T::PinId>,
103 },
104}
105
106impl<T: L2NBase> From<HierarchyUndoOp<T>> for L2NUndoOp<T> {
107 fn from(op: HierarchyUndoOp<T>) -> Self {
108 Self::HierarchyOp(op)
109 }
110}
111
112impl<T: L2NBase> From<NetlistUndoOp<T>> for L2NUndoOp<T> {
113 fn from(op: NetlistUndoOp<T>) -> Self {
114 Self::NetlistOp(op)
115 }
116}
117
118impl<T: L2NBase> From<LayoutUndoOp<T>> for L2NUndoOp<T> {
119 fn from(op: LayoutUndoOp<T>) -> Self {
120 Self::LayoutOp(op)
121 }
122}
123
124pub enum HierarchyUndoOp<T: HierarchyBase> {
126 CreateCell(T::CellId),
128 CreateCellInstance(T::CellInstId),
130 RenameCell {
132 cell: T::CellId,
134 previous_name: T::NameType,
136 },
137 RenameCellInst {
139 inst: T::CellInstId,
141 previous_name: Option<T::NameType>,
143 },
144}
145
146pub struct Undo<'a, T, U> {
152 chip: &'a mut T,
154 transactions: Vec<U>,
157}
158
159impl<'a, T, U> Undo<'a, T, U> {
160 pub fn num_transactions(&self) -> usize {
162 self.transactions.len()
163 }
164
165 pub fn flush(&mut self) {
167 self.transactions.clear()
168 }
169}
170
171impl<'a, T, U> Deref for Undo<'a, T, U> {
172 type Target = T;
173
174 fn deref(&self) -> &Self::Target {
175 self.chip
176 }
177}
178
179impl<'a, T: HierarchyEdit, U> Undo<'a, T, U> {
180 fn undo_hierarchy_op(&mut self, op: HierarchyUndoOp<T>) {
182 match op {
183 HierarchyUndoOp::CreateCell(c) => self.chip.remove_cell(&c),
184 HierarchyUndoOp::CreateCellInstance(c) => self.chip.remove_cell_instance(&c),
185 HierarchyUndoOp::RenameCell {
186 cell,
187 previous_name,
188 } => self.chip.rename_cell(&cell, previous_name),
189 HierarchyUndoOp::RenameCellInst {
190 inst,
191 previous_name,
192 } => self.chip.rename_cell_instance(&inst, previous_name),
193 }
194 }
195}
196
197impl<'a, T: L2NEdit, U> Undo<'a, T, U> {
198 fn undo_l2n_op(&mut self, op: L2NUndoOp<T>) {
200 match op {
201 L2NUndoOp::HierarchyOp(op) => self.undo_hierarchy_op(op),
203 L2NUndoOp::NetlistOp(op) => self.undo_netlist_op(op),
204 L2NUndoOp::LayoutOp(op) => self.undo_layout_op(op),
205 L2NUndoOp::SetNetOfShape {
207 shape_id,
208 previous_net,
209 } => {
210 self.chip.set_net_of_shape(&shape_id, previous_net);
211 }
212 L2NUndoOp::SetPinOfShape {
213 shape_id,
214 previous_pin,
215 } => {
216 self.chip.set_pin_of_shape(&shape_id, previous_pin);
217 }
218 }
219 }
220}
221
222impl<'a, T: L2NEdit> Undo<'a, T, L2NUndoOp<T>> {
223 pub fn new_l2n_undo(chip: &'a mut T) -> Self {
226 Self {
227 chip,
228 transactions: vec![],
229 }
230 }
231
232 pub fn undo(&mut self) {
235 if let Some(op) = self.transactions.pop() {
236 self.undo_l2n_op(op)
237 }
238 }
239}
240
241impl<'a, T: LayoutEdit, U> Undo<'a, T, U> {
242 fn undo_layout_op(&mut self, op: LayoutUndoOp<T>) {
244 match op {
245 LayoutUndoOp::HierarchyOp(op) => self.undo_hierarchy_op(op),
246 LayoutUndoOp::SetDbu(dbu) => self.chip.set_dbu(dbu),
247 LayoutUndoOp::CreateLayer(_id) => {
248 log::error!("Creating a layer cannot be undone.");
250 }
251 LayoutUndoOp::SetLayerName(id, old_name) => {
252 self.chip.set_layer_name(&id, old_name);
253 }
254 LayoutUndoOp::InsertShape(id) => {
255 self.chip.remove_shape(&id);
256 }
257 LayoutUndoOp::RemoveShape {
258 parent_cell,
259 layer,
260 geometry,
261 } => {
262 self.chip.insert_shape(&parent_cell, &layer, geometry);
263 }
264 LayoutUndoOp::ReplaceShape(id, geometry) => {
265 self.chip.replace_shape(&id, geometry);
266 }
267 LayoutUndoOp::SetTransform(inst, old_tf) => self.chip.set_transform(&inst, old_tf),
268 }
269 }
270}
271
272impl<'a, T: LayoutEdit> Undo<'a, T, LayoutUndoOp<T>> {
273 pub fn new_layout_undo(chip: &'a mut T) -> Self {
276 Self {
277 chip,
278 transactions: vec![],
279 }
280 }
281
282 pub fn undo(&mut self) {
285 if let Some(op) = self.transactions.pop() {
286 self.undo_layout_op(op)
287 }
288 }
289}
290
291impl<'a, T: NetlistEdit, U> Undo<'a, T, U> {
292 fn undo_netlist_op(&mut self, op: NetlistUndoOp<T>) {
294 match op {
295 NetlistUndoOp::HierarchyOp(op) => self.undo_hierarchy_op(op),
296 NetlistUndoOp::CreatePin(p) => self.chip.remove_pin(&p),
297 NetlistUndoOp::RenamePin(p, n) => {
298 self.chip.rename_pin(&p, n);
299 }
300 NetlistUndoOp::CreateNet(n) => self.chip.remove_net(&n),
301 NetlistUndoOp::ConnectPin(p, n) => {
302 self.chip.connect_pin(&p, n);
303 }
304 NetlistUndoOp::ConnectPinInstance(p, n) => {
305 self.chip.connect_pin_instance(&p, n);
306 }
307 NetlistUndoOp::RenameNet(net, name) => {
308 self.chip.rename_net(&net, name);
309 }
310 }
311 }
312}
313
314impl<'a, T: NetlistEdit> Undo<'a, T, NetlistUndoOp<T>> {
315 pub fn new_netlist_undo(chip: &'a mut T) -> Self {
318 Self {
319 chip,
320 transactions: vec![],
321 }
322 }
323
324 pub fn undo(&mut self) {
327 if let Some(op) = self.transactions.pop() {
328 self.undo_netlist_op(op)
329 }
330 }
331}
332
333impl<'a, T: HierarchyEdit> Undo<'a, T, HierarchyUndoOp<T>> {
334 pub fn new_hierarchy_undo(chip: &'a mut T) -> Self {
337 Self {
338 chip,
339 transactions: vec![],
340 }
341 }
342
343 pub fn undo(&mut self) {
346 if let Some(op) = self.transactions.pop() {
347 self.undo_hierarchy_op(op)
348 }
349 }
350
351 pub fn undo_all(&mut self) {
353 while !self.transactions.is_empty() {
354 self.undo();
355 }
356 }
357}
358
359#[portrait::fill(portrait::delegate(N))]
361impl<'a, N, U> HierarchyIds for Undo<'a, N, U> where N: HierarchyIds {}
362
363#[portrait::fill(portrait::delegate(N; self.chip))]
364impl<'b, N, U> HierarchyBase for Undo<'b, N, U> where N: HierarchyBase {}
365
366#[portrait::fill(portrait::delegate(N))]
367impl<'b, N, U> NetlistIds for Undo<'b, N, U> where N: NetlistIds {}
368
369#[portrait::fill(portrait::delegate(N; self.chip))]
370impl<'b, N, U> NetlistBase for Undo<'b, N, U> where N: NetlistBase {}
371
372#[portrait::fill(portrait::delegate(N))]
373impl<'b, N, U> LayoutIds for Undo<'b, N, U> where N: LayoutIds {}
374
375#[portrait::fill(portrait::delegate(N; self.chip))]
376impl<'b, N, U> LayoutBase for Undo<'b, N, U> where N: LayoutBase {}
377
378#[portrait::fill(portrait::delegate(N; self.chip))]
379impl<'b, N, U> L2NBase for Undo<'b, N, U> where N: L2NBase {}
380
381impl<'a, T: HierarchyEdit + 'static, U: From<HierarchyUndoOp<T>>> HierarchyEdit for Undo<'a, T, U> {
382 fn create_cell(&mut self, name: Self::NameType) -> Self::CellId {
383 let id = self.chip.create_cell(name);
384 self.transactions
385 .push(HierarchyUndoOp::CreateCell(id.clone()).into());
386 id
387 }
388
389 fn remove_cell(&mut self, _cell_id: &Self::CellId) {
390 unimplemented!()
391 }
392
393 fn create_cell_instance(
394 &mut self,
395 parent_cell: &Self::CellId,
396 template_cell: &Self::CellId,
397 name: Option<Self::NameType>,
398 ) -> Self::CellInstId {
399 let id = self
400 .chip
401 .create_cell_instance(parent_cell, template_cell, name);
402 self.transactions
403 .push(HierarchyUndoOp::CreateCellInstance(id.clone()).into());
404 id
405 }
406
407 fn remove_cell_instance(&mut self, _inst: &Self::CellInstId) {
408 unimplemented!()
409 }
410
411 fn rename_cell_instance(&mut self, inst: &Self::CellInstId, new_name: Option<Self::NameType>) {
412 let previous_name = self.cell_instance_name(inst);
413 self.chip.rename_cell_instance(inst, new_name);
414 self.transactions.push(
415 HierarchyUndoOp::RenameCellInst {
416 inst: inst.clone(),
417 previous_name,
418 }
419 .into(),
420 );
421 }
422
423 fn rename_cell(&mut self, cell: &Self::CellId, new_name: Self::NameType) {
424 let previous_name = self.cell_name(cell);
425 self.chip.rename_cell(cell, new_name);
426 self.transactions.push(
427 HierarchyUndoOp::RenameCell {
428 cell: cell.clone(),
429 previous_name,
430 }
431 .into(),
432 );
433 }
434}
435
436impl<'a, T, U> NetlistEdit for Undo<'a, T, U>
437where
438 T: NetlistEdit + 'static,
439 U: From<NetlistUndoOp<T>> + From<HierarchyUndoOp<T>>,
440{
441 fn create_pin(
442 &mut self,
443 circuit: &Self::CellId,
444 name: Self::NameType,
445 direction: Direction,
446 ) -> Self::PinId {
447 let id = self.chip.create_pin(circuit, name, direction);
448 self.transactions
449 .push(NetlistUndoOp::CreatePin(id.clone()).into());
450 id
451 }
452
453 fn remove_pin(&mut self, _id: &Self::PinId) {
454 unimplemented!("Removing a pin is not implemented to be undoable.")
455 }
456
457 fn rename_pin(&mut self, pin: &Self::PinId, new_name: Self::NameType) -> Self::NameType {
458 let prev_name = self.chip.pin_name(pin);
459 self.transactions
460 .push(NetlistUndoOp::RenamePin(pin.clone(), prev_name).into());
461 self.chip.rename_pin(pin, new_name)
462 }
463
464 fn create_net(&mut self, parent: &Self::CellId, name: Option<Self::NameType>) -> Self::NetId {
465 let id = self.chip.create_net(parent, name);
466 self.transactions
467 .push(NetlistUndoOp::CreateNet(id.clone()).into());
468 id
469 }
470
471 fn rename_net(
472 &mut self,
473 net_id: &Self::NetId,
474 new_name: Option<Self::NameType>,
475 ) -> Option<Self::NameType> {
476 let old_name = self.chip.rename_net(net_id, new_name);
477 self.transactions
478 .push(NetlistUndoOp::RenameNet(net_id.clone(), old_name.clone()).into());
479 old_name
480 }
481
482 fn remove_net(&mut self, _net: &Self::NetId) {
483 unimplemented!("Removing a net is not implemented to be undoable.")
488 }
489
490 fn connect_pin(&mut self, pin: &Self::PinId, net: Option<Self::NetId>) -> Option<Self::NetId> {
491 let prev_net = self.chip.connect_pin(pin, net);
492 self.transactions
493 .push(NetlistUndoOp::ConnectPin(pin.clone(), prev_net.clone()).into());
494 prev_net
495 }
496
497 fn connect_pin_instance(
498 &mut self,
499 pin: &Self::PinInstId,
500 net: Option<Self::NetId>,
501 ) -> Option<Self::NetId> {
502 let prev_net = self.chip.connect_pin_instance(pin, net);
503 self.transactions
504 .push(NetlistUndoOp::ConnectPinInstance(pin.clone(), prev_net.clone()).into());
505 prev_net
506 }
507}
508
509impl<'a, T, U> LayoutEdit for Undo<'a, T, U>
510where
511 T: LayoutEdit + 'static,
512 U: From<LayoutUndoOp<T>> + From<HierarchyUndoOp<T>>,
513{
514 fn set_dbu(&mut self, dbu: Self::Coord) {
515 self.transactions
516 .push(LayoutUndoOp::SetDbu(self.dbu()).into());
517 self.chip.set_dbu(dbu)
518 }
519
520 fn create_layer(&mut self, index: u32, datatype: u32) -> Self::LayerId {
521 let id = self.chip.create_layer(index, datatype);
522 self.transactions
523 .push(LayoutUndoOp::CreateLayer(id.clone()).into());
524 id
525 }
526
527 fn create_layer_with_id(
528 &mut self,
529 layer_id: Self::LayerId,
530 index: u32,
531 datatype: u32,
532 ) -> Result<(), ()> {
533 self.chip
534 .create_layer_with_id(layer_id.clone(), index, datatype)?;
535 self.transactions
536 .push(LayoutUndoOp::CreateLayer(layer_id).into());
537 Ok(())
538 }
539
540 fn set_layer_name(
541 &mut self,
542 layer: &Self::LayerId,
543 name: Option<Self::NameType>,
544 ) -> Option<Self::NameType> {
545 let old_name = self.layer_info(layer).name;
546 self.transactions
547 .push(LayoutUndoOp::SetLayerName(layer.clone(), old_name).into());
548 self.chip.set_layer_name(layer, name)
549 }
550
551 fn insert_shape(
552 &mut self,
553 parent_cell: &T::CellId,
554 layer: &T::LayerId,
555 geometry: Geometry<Self::Coord>,
556 ) -> Self::ShapeId {
557 let id = self.chip.insert_shape(parent_cell, layer, geometry);
558 self.transactions
559 .push(LayoutUndoOp::InsertShape(id.clone()).into());
560 id
561 }
562
563 fn remove_shape(&mut self, shape_id: &Self::ShapeId) -> Option<Geometry<Self::Coord>> {
564 let geometry = self.chip.remove_shape(shape_id);
565 let (parent_cell, layer) = self.parent_of_shape(shape_id);
566 if let Some(geometry) = &geometry {
567 self.transactions.push(
568 LayoutUndoOp::RemoveShape {
569 parent_cell,
570 layer,
571 geometry: geometry.clone(),
572 }
573 .into(),
574 );
575 }
576 geometry
577 }
578
579 fn replace_shape(
580 &mut self,
581 shape_id: &Self::ShapeId,
582 geometry: Geometry<Self::Coord>,
583 ) -> Geometry<Self::Coord> {
584 let old_geometry = self.chip.replace_shape(shape_id, geometry);
585
586 self.transactions
587 .push(LayoutUndoOp::ReplaceShape(shape_id.clone(), old_geometry.clone()).into());
588
589 old_geometry
590 }
591
592 fn set_transform(&mut self, cell_inst: &Self::CellInstId, tf: SimpleTransform<Self::Coord>) {
593 let old_transform = self.get_transform(cell_inst);
594 self.transactions
595 .push(LayoutUndoOp::SetTransform(cell_inst.clone(), old_transform).into());
596 self.chip.set_transform(cell_inst, tf)
597 }
598
599 fn set_shape_property(
600 &mut self,
601 shape: &Self::ShapeId,
602 key: Self::NameType,
603 _value: PropertyValue,
604 ) {
605 let _old_property = self.get_shape_property(shape, &key);
606 unimplemented!("set_shape_property() is currently not undoable.")
607 }
608}
609
610impl<'a, T, U> L2NEdit for Undo<'a, T, U>
611where
612 T: L2NEdit + 'static,
613 U: From<L2NUndoOp<T>>
614 + From<LayoutUndoOp<T>>
615 + From<NetlistUndoOp<T>>
616 + From<HierarchyUndoOp<T>>,
617{
618 fn set_pin_of_shape(
619 &mut self,
620 shape_id: &Self::ShapeId,
621 pin: Option<Self::PinId>,
622 ) -> Option<Self::PinId> {
623 let previous_pin = self.get_pin_of_shape(shape_id);
624 self.transactions.push(
625 L2NUndoOp::SetPinOfShape {
626 shape_id: shape_id.clone(),
627 previous_pin,
628 }
629 .into(),
630 );
631 self.chip.set_pin_of_shape(shape_id, pin)
632 }
633
634 fn set_net_of_shape(
635 &mut self,
636 shape_id: &Self::ShapeId,
637 net: Option<Self::NetId>,
638 ) -> Option<Self::NetId> {
639 let previous_net = self.get_net_of_shape(shape_id);
640 self.transactions.push(
641 L2NUndoOp::SetNetOfShape {
642 shape_id: shape_id.clone(),
643 previous_net,
644 }
645 .into(),
646 );
647 self.chip.set_net_of_shape(shape_id, net)
648 }
649}
650
651#[test]
652fn test_hierarchy_undoing() {
653 use crate::chip::Chip;
654 let mut chip = Chip::new();
655 let mut undo = Undo::new_netlist_undo(&mut chip);
656
657 let top = undo.create_cell("TOP".into());
658 let _top_a = undo.create_pin(&top, "A".into(), Direction::Input);
659 let sub = undo.create_cell("SUB".into());
660 let _sub_b = undo.create_pin(&sub, "B".into(), Direction::Input);
661 let inst = undo.create_cell_instance(&top, &sub, Some("inst1".into()));
662
663 undo.rename_cell(&top, "NewName".into());
665 undo.rename_cell_instance(&inst, None);
666 undo.undo();
667 undo.undo();
668 assert!(undo.cell_by_name("TOP").is_some());
669 assert!(undo.cell_instance_by_name(&top, "inst1").is_some());
670
671 assert_eq!(undo.num_child_instances(&top), 1);
673 undo.undo();
674 assert_eq!(undo.num_child_instances(&top), 0);
675
676 assert_eq!(undo.num_cells(), 2);
677 undo.undo();
679 undo.undo();
680 undo.undo();
681 undo.undo();
682 assert_eq!(undo.num_cells(), 0);
683}