1use crate::coord::{Bbox, Point, Trans};
16use crate::hash::ContentHash;
17use crate::instance::{Instance, Repetition};
18use crate::layer::LayerIndex;
19use crate::library::Library;
20use crate::port::Port;
21use crate::properties::{Properties, PropertyValue};
22use crate::shape::Shape;
23use smol_str::SmolStr;
24use std::collections::BTreeMap;
25use std::fmt;
26use std::num::NonZeroU32;
27
28#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
29pub struct CellName(pub SmolStr);
30
31impl CellName {
32 pub fn new(s: impl Into<SmolStr>) -> Self {
33 Self(s.into())
34 }
35
36 pub fn as_str(&self) -> &str {
37 self.0.as_str()
38 }
39
40 pub fn is_empty(&self) -> bool {
41 self.0.is_empty()
42 }
43}
44
45impl fmt::Display for CellName {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 f.write_str(self.0.as_str())
48 }
49}
50
51impl<S: Into<SmolStr>> From<S> for CellName {
52 fn from(s: S) -> Self {
53 Self(s.into())
54 }
55}
56
57#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
58pub struct CellId(NonZeroU32);
59
60impl CellId {
61 pub(crate) fn from_slot(slot: usize) -> Self {
62 let n = u32::try_from(slot + 1)
67 .expect("CellId arena slot exceeded u32::MAX (≈4B cells)");
68 Self(NonZeroU32::new(n).expect("CellId: slot+1 ≥ 1 by construction"))
69 }
70
71 pub(crate) fn slot(self) -> usize {
72 self.0.get() as usize - 1
73 }
74
75 pub fn raw(self) -> u32 {
76 self.0.get()
77 }
78}
79
80#[derive(Clone, Debug, Default)]
81pub struct ShapeBag {
82 shapes: Vec<Shape>,
83}
84
85impl ShapeBag {
86 pub fn new() -> Self {
87 Self::default()
88 }
89
90 pub fn push(&mut self, s: Shape) {
91 self.shapes.push(s);
92 }
93
94 pub fn iter(&self) -> impl Iterator<Item = &Shape> {
95 self.shapes.iter()
96 }
97
98 pub fn len(&self) -> usize {
99 self.shapes.len()
100 }
101
102 pub fn is_empty(&self) -> bool {
103 self.shapes.is_empty()
104 }
105}
106
107#[derive(Clone, Debug)]
108pub struct Cell {
109 pub(crate) name: CellName,
110 pub(crate) shapes: BTreeMap<LayerIndex, ShapeBag>,
111 pub(crate) instances: Vec<Instance>,
112 pub(crate) ports: Vec<Port>,
113 pub(crate) properties: Properties,
114 pub(crate) local_bbox: Bbox,
115 pub(crate) content_hash: ContentHash,
116}
117
118impl Cell {
119 pub fn name(&self) -> &CellName {
120 &self.name
121 }
122
123 pub fn content_hash(&self) -> ContentHash {
124 self.content_hash
125 }
126
127 pub fn local_bbox(&self) -> Bbox {
128 self.local_bbox
129 }
130
131 pub fn shapes_on(&self, layer: LayerIndex) -> impl Iterator<Item = &Shape> {
132 self.shapes
133 .get(&layer)
134 .map(|b| b.iter())
135 .into_iter()
136 .flatten()
137 }
138
139 pub fn layers(&self) -> impl Iterator<Item = LayerIndex> + '_ {
140 self.shapes.keys().copied()
141 }
142
143 pub fn instances(&self) -> &[Instance] {
144 &self.instances
145 }
146
147 pub fn ports(&self) -> &[Port] {
148 &self.ports
149 }
150
151 pub fn port(&self, name: &str) -> Option<&Port> {
152 self.ports.iter().find(|p| p.name == name)
153 }
154
155 pub fn properties(&self) -> &Properties {
156 &self.properties
157 }
158
159 pub fn full_bbox(&self, lib: &Library) -> Bbox {
162 let mut b = self.local_bbox;
163 for inst in &self.instances {
164 let child = lib.get(inst.cell);
165 let child_b = child.full_bbox(lib);
166 let placed = inst.trans.apply_bbox(child_b);
167 if let Some(rep) = &inst.repetition {
168 let rb = rep.placement_bbox();
169 if !rb.is_empty() {
170 b = b.union(&Bbox::new(
171 Point::new(placed.min.x + rb.min.x, placed.min.y + rb.min.y),
172 Point::new(placed.max.x + rb.max.x, placed.max.y + rb.max.y),
173 ));
174 continue;
175 }
176 }
177 b = b.union(&placed);
178 }
179 b
180 }
181}
182
183#[derive(Clone, Debug)]
184pub struct CellBuilder {
185 name: CellName,
186 shapes: BTreeMap<LayerIndex, ShapeBag>,
187 instances: Vec<Instance>,
188 ports: Vec<Port>,
189 properties: Properties,
190}
191
192impl CellBuilder {
193 pub fn new(name: impl Into<CellName>) -> Self {
194 Self {
195 name: name.into(),
196 shapes: BTreeMap::new(),
197 instances: Vec::new(),
198 ports: Vec::new(),
199 properties: Properties::new(),
200 }
201 }
202
203 pub fn name(&self) -> &CellName {
204 &self.name
205 }
206
207 pub fn set_name(&mut self, name: impl Into<CellName>) {
208 self.name = name.into();
209 }
210
211 pub fn add_shape(&mut self, layer: LayerIndex, shape: impl Into<Shape>) {
212 self.shapes.entry(layer).or_default().push(shape.into());
213 }
214
215 pub fn add_instance(&mut self, inst: Instance) {
216 self.instances.push(inst);
217 }
218
219 pub fn instantiate(&mut self, cell: CellId, trans: Trans) {
220 self.instances.push(Instance::new(cell, trans));
221 }
222
223 pub fn add_port(&mut self, port: Port) {
224 self.ports.push(port);
225 }
226
227 pub fn set_property(&mut self, key: impl Into<SmolStr>, value: PropertyValue) {
228 self.properties.set(key, value);
229 }
230
231 pub fn properties_mut(&mut self) -> &mut Properties {
232 &mut self.properties
233 }
234
235 pub fn freeze(self, lib: &Library) -> Cell {
236 let local_bbox = compute_local_bbox(&self.shapes);
237 let content_hash = canonical_hash(
238 &self.name,
239 &self.shapes,
240 &self.instances,
241 &self.ports,
242 &self.properties,
243 lib,
244 );
245 Cell {
246 name: self.name,
247 shapes: self.shapes,
248 instances: self.instances,
249 ports: self.ports,
250 properties: self.properties,
251 local_bbox,
252 content_hash,
253 }
254 }
255}
256
257fn compute_local_bbox(shapes: &BTreeMap<LayerIndex, ShapeBag>) -> Bbox {
258 let mut b = Bbox::EMPTY;
259 for bag in shapes.values() {
260 for s in bag.iter() {
261 b = b.union(&s.bbox());
262 }
263 }
264 b
265}
266
267fn canonical_hash(
270 name: &CellName,
271 shapes: &BTreeMap<LayerIndex, ShapeBag>,
272 instances: &[Instance],
273 ports: &[Port],
274 properties: &Properties,
275 lib: &Library,
276) -> ContentHash {
277 let mut h = blake3::Hasher::new();
278
279 let _ = name;
283
284 let mut by_gds: Vec<((u16, u16), &ShapeBag)> = shapes
289 .iter()
290 .map(|(idx, bag)| (lib.layer_info(*idx).key(), bag))
291 .collect();
292 by_gds.sort_by_key(|(k, _)| *k);
293 write_u32(&mut h, by_gds.len() as u32);
294 for ((l, dt), bag) in by_gds {
295 write_u16(&mut h, l);
296 write_u16(&mut h, dt);
297 let mut encoded: Vec<Vec<u8>> = bag.iter().map(canonical_shape_bytes).collect();
298 encoded.sort();
299 write_u32(&mut h, encoded.len() as u32);
300 for e in &encoded {
301 write_bytes(&mut h, e);
302 }
303 }
304
305 let mut inst_enc: Vec<Vec<u8>> = instances
308 .iter()
309 .map(|i| canonical_instance_bytes(i, lib))
310 .collect();
311 inst_enc.sort();
312 write_u32(&mut h, inst_enc.len() as u32);
313 for e in &inst_enc {
314 write_bytes(&mut h, e);
315 }
316
317 let mut port_enc: Vec<Vec<u8>> = ports
320 .iter()
321 .map(|p| canonical_port_bytes(p, lib))
322 .collect();
323 port_enc.sort();
324 write_u32(&mut h, port_enc.len() as u32);
325 for e in &port_enc {
326 write_bytes(&mut h, e);
327 }
328
329 let props_sorted = properties.sorted_iter();
331 write_u32(&mut h, props_sorted.len() as u32);
332 for (k, v) in props_sorted {
333 write_bytes(&mut h, k.as_bytes());
334 write_property(&mut h, v);
335 }
336
337 ContentHash(*h.finalize().as_bytes())
338}
339
340fn canonical_shape_bytes(s: &Shape) -> Vec<u8> {
341 let mut buf = Vec::with_capacity(64);
342 buf.push(s.discriminant());
343 match s {
344 Shape::Polygon(p) => {
345 put_u32(&mut buf, p.hull.len() as u32);
346 for pt in &p.hull {
347 put_point(&mut buf, *pt);
348 }
349 put_u32(&mut buf, p.holes.len() as u32);
350 for hole in &p.holes {
351 put_u32(&mut buf, hole.len() as u32);
352 for pt in hole {
353 put_point(&mut buf, *pt);
354 }
355 }
356 }
357 Shape::Path(p) => {
358 put_u32(&mut buf, p.points.len() as u32);
359 for pt in &p.points {
360 put_point(&mut buf, *pt);
361 }
362 put_i64(&mut buf, p.width);
363 put_i64(&mut buf, p.begin_ext);
364 put_i64(&mut buf, p.end_ext);
365 buf.push(match p.cap {
366 crate::shape::PathCap::Flat => 0,
367 crate::shape::PathCap::Round => 1,
368 crate::shape::PathCap::Extended => 2,
369 });
370 }
371 Shape::Box(r) => {
372 put_point(&mut buf, r.bbox.min);
373 put_point(&mut buf, r.bbox.max);
374 }
375 Shape::Text(t) => {
376 put_u32(&mut buf, t.string.len() as u32);
377 buf.extend_from_slice(t.string.as_bytes());
378 put_point(&mut buf, t.anchor);
379 put_i32(&mut buf, t.size);
380 buf.push(t.halign as u8);
381 buf.push(t.valign as u8);
382 }
383 }
384 buf
385}
386
387fn canonical_trans_bytes(buf: &mut Vec<u8>, t: &Trans) {
388 buf.push(t.rot as u8);
389 buf.push(t.mirror as u8);
390 put_i64(buf, t.disp.x);
391 put_i64(buf, t.disp.y);
392}
393
394fn canonical_repetition_bytes(buf: &mut Vec<u8>, r: &Option<Repetition>) {
395 match r {
396 None => buf.push(0),
397 Some(Repetition::Regular {
398 row,
399 col,
400 n_rows,
401 n_cols,
402 }) => {
403 buf.push(1);
404 put_i64(buf, row.x);
405 put_i64(buf, row.y);
406 put_i64(buf, col.x);
407 put_i64(buf, col.y);
408 put_u32(buf, *n_rows);
409 put_u32(buf, *n_cols);
410 }
411 Some(Repetition::Irregular { offsets }) => {
412 buf.push(2);
413 put_u32(buf, offsets.len() as u32);
414 for o in offsets {
415 put_i64(buf, o.x);
416 put_i64(buf, o.y);
417 }
418 }
419 }
420}
421
422fn canonical_instance_bytes(i: &Instance, lib: &Library) -> Vec<u8> {
423 let mut buf = Vec::with_capacity(64);
424 let child = lib.get(i.cell);
425 buf.extend_from_slice(&child.content_hash.0);
426 canonical_trans_bytes(&mut buf, &i.trans);
427 canonical_repetition_bytes(&mut buf, &i.repetition);
428 let props = i.properties.sorted_iter();
429 put_u32(&mut buf, props.len() as u32);
430 for (k, v) in props {
431 put_u32(&mut buf, k.len() as u32);
432 buf.extend_from_slice(k.as_bytes());
433 canonical_property(&mut buf, v);
434 }
435 buf
436}
437
438fn canonical_port_bytes(p: &Port, lib: &Library) -> Vec<u8> {
439 let mut buf = Vec::with_capacity(48);
440 put_u32(&mut buf, p.name.len() as u32);
441 buf.extend_from_slice(p.name.as_bytes());
442 put_u32(&mut buf, p.kind.0);
443 put_point(&mut buf, p.center);
444 buf.push(p.angle as u8);
445 put_i64(&mut buf, p.width);
446 let info = lib.layer_info(p.layer);
447 put_u16(&mut buf, info.layer);
448 put_u16(&mut buf, info.datatype);
449 buf
450}
451
452fn canonical_property(buf: &mut Vec<u8>, v: &PropertyValue) {
453 match v {
454 PropertyValue::Int(i) => {
455 buf.push(0);
456 put_i64(buf, *i);
457 }
458 PropertyValue::Float(f) => {
459 buf.push(1);
460 buf.extend_from_slice(&f.to_bits().to_le_bytes());
461 }
462 PropertyValue::String(s) => {
463 buf.push(2);
464 put_u32(buf, s.len() as u32);
465 buf.extend_from_slice(s.as_bytes());
466 }
467 PropertyValue::Bytes(b) => {
468 buf.push(3);
469 put_u32(buf, b.len() as u32);
470 buf.extend_from_slice(b);
471 }
472 PropertyValue::List(items) => {
473 buf.push(4);
474 put_u32(buf, items.len() as u32);
475 for it in items {
476 canonical_property(buf, it);
477 }
478 }
479 }
480}
481
482fn write_property(h: &mut blake3::Hasher, v: &PropertyValue) {
483 let mut buf = Vec::new();
484 canonical_property(&mut buf, v);
485 write_bytes(h, &buf);
486}
487
488fn put_u16(buf: &mut Vec<u8>, v: u16) {
490 buf.extend_from_slice(&v.to_le_bytes());
491}
492fn put_u32(buf: &mut Vec<u8>, v: u32) {
493 buf.extend_from_slice(&v.to_le_bytes());
494}
495fn put_i32(buf: &mut Vec<u8>, v: i32) {
496 buf.extend_from_slice(&v.to_le_bytes());
497}
498fn put_i64(buf: &mut Vec<u8>, v: i64) {
499 buf.extend_from_slice(&v.to_le_bytes());
500}
501fn put_point(buf: &mut Vec<u8>, p: Point) {
502 put_i64(buf, p.x);
503 put_i64(buf, p.y);
504}
505
506fn write_u16(h: &mut blake3::Hasher, v: u16) {
507 h.update(&v.to_le_bytes());
508}
509fn write_u32(h: &mut blake3::Hasher, v: u32) {
510 h.update(&v.to_le_bytes());
511}
512fn write_bytes(h: &mut blake3::Hasher, b: &[u8]) {
513 h.update(&(b.len() as u32).to_le_bytes());
514 h.update(b);
515}