1use std::collections::HashMap;
4
5use layir::Cell;
6use layir::Direction;
7use layir::LibraryBuilder;
8use layir::Port;
9
10use super::element::Element;
11use super::element::RawCell;
12
13use super::element::CellId as SubCellId;
14use layir::CellId as LayCellId;
15
16#[derive(Debug, Default, Clone)]
20pub struct LayirLibConversion {
21 pub(crate) cells: HashMap<SubCellId, layir::CellId>,
23}
24
25#[derive(Debug, Clone)]
26pub(crate) struct LayirLibExportContext<L> {
27 lib: layir::LibraryBuilder<L>,
28 conv: LayirLibConversion,
29}
30
31pub struct RawLib<L> {
33 pub layir: layir::Library<L>,
35 pub conv: LayirLibConversion,
39}
40
41impl<L> Default for LayirLibExportContext<L> {
42 fn default() -> Self {
43 Self {
44 lib: LibraryBuilder::new(),
45 conv: LayirLibConversion::default(),
46 }
47 }
48}
49
50impl<L> LayirLibExportContext<L> {
51 #[inline]
52 fn new() -> Self {
53 Self::default()
54 }
55}
56
57#[derive(thiserror::Error, Clone, Debug)]
59#[error("error exporting layout cell to LayIR")]
60pub struct LayirExportError;
61
62impl<L: Clone> RawCell<L> {
63 pub(crate) fn to_layir_lib(&self) -> Result<RawLib<L>, LayirExportError> {
70 let mut lib_ctx = LayirLibExportContext::new();
71 self.to_layir_cell(&mut lib_ctx)?;
72
73 Ok(RawLib {
74 layir: lib_ctx.lib.build().map_err(|_| LayirExportError)?,
75 conv: lib_ctx.conv,
76 })
77 }
78
79 fn to_layir_cell(
82 &self,
83 lib_ctx: &mut LayirLibExportContext<L>,
84 ) -> Result<LayCellId, LayirExportError> {
85 if let Some(conv) = lib_ctx.conv.cells.get(&self.id) {
86 return Ok(*conv);
87 }
88
89 let mut cell = Cell::new(self.name.clone());
90 for elt in self.elements() {
91 match elt {
92 Element::Instance(inst) => {
93 let child = inst.raw_cell().to_layir_cell(lib_ctx)?;
94 let inst = layir::Instance::with_transformation(
95 child,
96 inst.raw_cell().name.clone(),
97 inst.trans,
98 );
99 cell.add_instance(inst);
100 }
101 Element::Shape(shape) => {
102 cell.add_element(shape.clone());
103 }
104 Element::Text(text) => {
105 cell.add_element(text.clone());
106 }
107 }
108 }
109 for (name, port) in self.ports() {
110 let mut lport = Port::new(Direction::InOut);
112 lport.add_element(port.primary.clone());
113 for shape in port.unnamed_shapes.iter() {
114 lport.add_element(shape.clone());
115 }
116 for (_, shape) in port.named_shapes.iter() {
117 lport.add_element(shape.clone());
118 }
119 cell.add_port(arcstr::format!("{}", name), lport);
120 }
121 let id = lib_ctx.lib.add_cell(cell);
122 lib_ctx.conv.cells.insert(self.id, id);
123 Ok(id)
124 }
125}
126
127pub(crate) fn export_multi_top_layir_lib<L: Clone>(
133 cells: &[&RawCell<L>],
134) -> Result<RawLib<L>, LayirExportError> {
135 let mut lib_ctx = LayirLibExportContext::new();
136
137 for &cell in cells {
138 cell.to_layir_cell(&mut lib_ctx)?;
139 }
140
141 Ok(RawLib {
142 layir: lib_ctx.lib.build().map_err(|_| LayirExportError)?,
143 conv: lib_ctx.conv,
144 })
145}