1use libreda_db::iron_shapes::traits::MapPointwise;
9use libreda_db::prelude::{self as db, NetlistEditUtil};
10use libreda_db::prelude::{Angle, CoordinateType, Direction, Scale, TerminalId, TryCastCoord};
11use libreda_db::traits::*;
12
13use crate::def_ast;
14use crate::def_ast::{NetTerminal, RoutingPoint, DEF};
15use crate::lef_ast::{Layer, RectOrPolygon, Shape, SignalUse, ViaDefinition, ViaShape, LEF};
16
17use crate::common::{Orient, PinDirection};
18use num_traits::{FromPrimitive, NumCast, PrimInt, Zero};
19use std::collections::HashMap;
20use std::fmt::Formatter;
21
22#[derive(Debug, Clone)]
24pub enum LefDefImportError {
25 ComponentModelNotFound {
27 component_name: String,
29 model_name: String,
31 },
32 ComponentNotFound(String),
34 ViaNotFound(String),
36 LayerNotFound(String),
38 CellNameAlreadyExists(String),
40 Other(String),
42}
43
44impl std::fmt::Display for LefDefImportError {
45 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46 match self {
47 LefDefImportError::ComponentModelNotFound { component_name, model_name } => {
48 write!(f, "Model of component '{}' not found: '{}'", component_name, model_name)
49 }
50 LefDefImportError::LayerNotFound(layer) => write!(f, "the layer '{}' could not be found in the target design and the creation of new layers is disabled", layer),
51 LefDefImportError::ComponentNotFound(component_name) => write!(f, "component was referenced but not found: '{}'", component_name),
52 LefDefImportError::ViaNotFound(via_name) => write!(f, "component is referenced but not found: '{}'", via_name),
53 LefDefImportError::CellNameAlreadyExists(cell_name) => write!(f, "cell '{}' already exists", cell_name),
54 LefDefImportError::Other(msg) => write!(f, "{}", msg)
55 };
56
57 Ok(())
58 }
59}
60
61#[derive(Clone)]
64pub struct LEFImportOptions<C: L2NEdit> {
65 pub import_pins: bool,
69 pub import_power_pins: bool,
71 pub pin_suffix: String,
73 pub import_obstructions: bool,
75 pub obstruction_suffix: String,
77 pub import_via_definitions: bool,
79 pub import_generated_vias: bool,
81 pub import_fixed_vias: bool,
83 pub import_cell_outlines: bool,
85 pub cell_outline_layer: Option<String>,
87 pub layer_mapping: HashMap<String, C::LayerId>,
89 pub create_missing_layers: bool,
91 pub skip_existing_vias: bool,
93}
94
95impl<C: L2NEdit> Default for LEFImportOptions<C> {
96 fn default() -> Self {
97 Self {
98 import_pins: true,
100 import_power_pins: true,
101 pin_suffix: ".PIN".to_string(),
102 import_obstructions: true,
103 obstruction_suffix: ".OBS".to_string(),
104 import_via_definitions: true,
105 import_generated_vias: true,
106 import_fixed_vias: true,
107 import_cell_outlines: true,
108 cell_outline_layer: Some("OUTLINE".to_string()),
109 layer_mapping: Default::default(),
110 create_missing_layers: true,
111 skip_existing_vias: false,
112 }
113 }
114}
115
116impl<C: L2NEdit> LEFImportOptions<C> {
117 fn get_or_create_layer_by_name(
120 &self,
121 chip: &mut C,
122 layer_name: &String,
123 ) -> Result<C::LayerId, LefDefImportError> {
124 let layer = {
125 if let Some(l) = self.layer_mapping.get(layer_name) {
127 Some(l.clone())
128 } else {
129 chip.layer_by_name(layer_name.as_str())
130 .or_else(|| {
132 if self.create_missing_layers {
133 let next_idx = chip
134 .each_layer()
135 .map(|id| chip.layer_info(&id).index)
136 .max()
137 .unwrap_or(0)
138 + 1;
139 log::debug!("Create layer: {}", layer_name);
140 let layer_id = chip.create_layer(next_idx, 0);
141 chip.set_layer_name(&layer_id, Some(layer_name.clone().into()));
142 Some(layer_id)
143 } else {
144 None
145 }
146 })
147 }
148 };
149
150 layer.ok_or_else(|| LefDefImportError::LayerNotFound(layer_name.clone()))
152 }
153}
154
155fn convert_geometry<C: CoordinateType + NumCast>(
157 dbu_per_micron: u64,
158 shape: &Shape,
159) -> db::Geometry<C> {
160 let dbu_per_micron = dbu_per_micron as f64;
161 let geo: db::Geometry<f64> = match shape {
163 Shape::Path(width, points) => db::Path::new(points, *width).scale(dbu_per_micron).into(),
164 Shape::Rect(p1, p2) => db::Rect::new(p1, p2).scale(dbu_per_micron).into(),
165 Shape::Polygon(points) => db::SimplePolygon::new(points.clone())
166 .scale(dbu_per_micron)
167 .into(),
168 };
169 let geo: db::Geometry<C> = geo.try_cast().expect("Cast from float failed."); geo
171}
172
173#[derive(Clone)]
175pub struct DEFImportOptions<C: L2NEdit> {
176 pub lef_import_options: LEFImportOptions<C>,
178 pub import_blockages: bool,
180 pub blockages_suffix: String,
182 pub import_nets: bool,
184 pub import_wiring: bool,
186 pub import_fixed_vias: bool,
188 pub skip_existing_vias: bool,
191}
192
193impl<C: L2NEdit> Default for DEFImportOptions<C> {
194 fn default() -> Self {
195 Self {
196 lef_import_options: Default::default(),
197 import_blockages: true,
198 blockages_suffix: ".BLOCKAGE".to_string(),
199 import_nets: true,
200 import_wiring: true,
201 import_fixed_vias: true,
202 skip_existing_vias: false,
203 }
204 }
205}
206
207pub fn lef_to_db<C, Crd>(lef: &LEF) -> Result<C, LefDefImportError>
210where
211 Crd: NumCast + Ord + CoordinateType,
212 C: L2NEdit<Coord = Crd> + Default,
213{
214 let mut chip = C::default();
215 let options = Default::default();
216 import_lef_into_db(&options, lef, &mut chip).map(|_| chip)
217}
218
219pub fn import_lef_into_db<C, Crd>(
221 options: &LEFImportOptions<C>,
222 lef: &LEF,
223 chip: &mut C,
224) -> Result<(), LefDefImportError>
225where
226 Crd: NumCast + Ord + CoordinateType,
227 C: L2NEdit<Coord = Crd>,
228{
229 assert!(
231 chip.dbu() > Crd::zero(),
232 "Data-base distance unit (DBU) must be a positive number"
233 );
234 let dbu_per_micron = chip.dbu().to_u64().expect("failed to convert DBU to u64");
235
236 for (i, layer) in lef.technology.layers.iter().enumerate() {
238 let result = options.get_or_create_layer_by_name(chip, layer.name());
239 if let Err(err) = result {
240 log::warn!("Failed to create layer: {} ({})", layer.name(), err)
243 }
244 }
245
246 if options.import_via_definitions {
248 import_lef_vias(options, lef, chip)?;
249 }
250
251 for (macro_name, lef_macro) in &lef.library.macros {
253 let cell = chip.create_cell(macro_name.to_string().into());
254
255 if options.import_pins {
257 let mut pin_layer_name_cache = HashMap::new();
259 for macro_pin in &lef_macro.pins {
260 let signal_use = macro_pin.signal_use.unwrap_or(SignalUse::Signal);
262 let is_power_ground_pin =
263 signal_use == SignalUse::Power || signal_use == SignalUse::Ground;
264 if !options.import_power_pins && is_power_ground_pin {
265 continue;
266 }
267
268 let direction = match ¯o_pin.direction {
270 None => Direction::None,
271 Some(d) => match d {
272 PinDirection::Input => Direction::Input,
273 PinDirection::Output(_tristate) => Direction::Output,
274 PinDirection::Inout => Direction::InOut,
275 PinDirection::Feedthru => Direction::InOut,
276 },
277 };
278
279 let pin = chip.create_pin(&cell, macro_pin.name.clone().into(), direction);
281
282 for port in ¯o_pin.ports {
284 for layer_geometry in &port.geometries {
285 let layer_name = pin_layer_name_cache
288 .entry(&layer_geometry.layer_name)
289 .or_insert_with(|| {
290 format!("{}{}", layer_geometry.layer_name, options.pin_suffix)
291 });
292 let layer = options.get_or_create_layer_by_name(chip, layer_name)?;
293
294 for g in &layer_geometry.geometries {
295 let geo = convert_geometry(dbu_per_micron, &g.shape);
296 let shape_id = chip.insert_shape(&cell, &layer, geo);
297 chip.set_pin_of_shape(&shape_id, Some(pin.clone()));
298 }
299 }
300 }
301 }
302 }
303
304 if options.import_cell_outlines {
306 if let Some((width, height)) = lef_macro.size {
307 if let Some(outline_layer_name) = &options.cell_outline_layer {
308 let shape = Shape::Rect(
310 lef_macro.origin,
311 lef_macro.origin + db::Point::new(width, height),
312 );
313 let geo = convert_geometry(dbu_per_micron, &shape);
315
316 let outline_layer =
317 options.get_or_create_layer_by_name(chip, outline_layer_name)?;
318
319 chip.insert_shape(&cell, &outline_layer, geo);
321 }
322 }
323 }
324
325 if options.import_obstructions {
327 let mut obs_layer_name_cache = HashMap::new();
328 for obs in &lef_macro.obs {
329 let layer_name = obs_layer_name_cache
332 .entry(&obs.layer_name)
333 .or_insert_with(|| format!("{}{}", obs.layer_name, options.obstruction_suffix));
334 let layer = options.get_or_create_layer_by_name(chip, layer_name)?;
335
336 for g in &obs.geometries {
337 let geo = convert_geometry(dbu_per_micron, &g.shape);
338 chip.insert_shape(&cell, &layer, geo);
339 }
340 }
341 }
342 }
343
344 Ok(())
345}
346
347pub fn import_lef_vias<C, Crd>(
350 options: &LEFImportOptions<C>,
351 lef: &LEF,
352 chip: &mut C,
353) -> Result<Vec<C::CellId>, LefDefImportError>
354where
355 Crd: NumCast + Ord + CoordinateType,
356 C: L2NEdit<Coord = Crd>,
357{
358 let dbu_per_micron: f64 = chip.dbu().to_f64().unwrap();
359
360 let mut via_cells = vec![];
361
362 for (via_name, via) in &lef.vias {
363 if chip.cell_by_name(via_name).is_some() {
365 if options.skip_existing_vias {
366 continue;
367 } else {
368 return Err(LefDefImportError::CellNameAlreadyExists(via_name.clone()));
369 }
370 }
371
372 let via_cell = chip.create_cell(via_name.clone().into());
373
374 match via {
375 ViaDefinition::GeneratedVia(via) => {
376 if options.import_generated_vias {
377 todo!("import of generated vias")
378 }
379 }
380 ViaDefinition::FixedVia(via) => {
381 if options.import_fixed_vias {
382 for (layer_name, shapes) in &via.geometry {
383 let layer = options.get_or_create_layer_by_name(chip, layer_name)?;
384
385 for shape in shapes {
386 let geometry: db::Geometry<f64> = match &shape.shape {
388 RectOrPolygon::Rect((p1, p2)) => {
389 db::Rect::new(*p1, *p2).scale(dbu_per_micron).into()
390 }
391 RectOrPolygon::Polygon(points) => {
392 let p = db::SimplePolygon::new(points.to_vec())
394 .scale(dbu_per_micron);
395 if let Some(p) = db::SimpleRPolygon::try_new(p.points()) {
396 p.into()
397 } else {
398 p.into()
399 }
400 }
401 };
402
403 let geo: db::Geometry<C::Coord> =
404 geometry.try_cast().expect("cast from f64 failed");
405
406 chip.insert_shape(&via_cell, &layer, geo);
408 }
409 }
410 }
411 }
412 _ => {}
413 };
414
415 via_cells.push(via_cell);
416 }
417
418 Ok(via_cells)
419}
420
421pub fn lefdef_to_db<C, Crd>(
424 options: &DEFImportOptions<C>,
425 lef: &LEF,
426 def: &DEF,
427) -> Result<C, LefDefImportError>
428where
429 Crd: NumCast + Ord + CoordinateType + PrimInt + std::fmt::Debug,
430 C: L2NEdit<Coord = Crd> + Default,
431{
432 let mut chip = C::default();
433
434 import_lef_into_db(&options.lef_import_options, lef, &mut chip)?;
436 import_def_into_db(&options, Some(lef), def, &mut chip).map(|_| chip)
437}
438
439pub fn import_def_netlist<C, Crd>(
444 options: &DEFImportOptions<C>,
445 def: &DEF,
446 top_cell: &C::CellId,
447 chip: &mut C,
448) -> Result<(), LefDefImportError>
449where
450 Crd: NumCast + Ord + CoordinateType + PrimInt,
451 C: L2NEdit<Coord = Crd>,
452{
453 log::info!(
454 "Import netlist from DEF. Number of nets: {}",
455 def.nets.len()
456 );
457 let mut nets_by_name = HashMap::new();
458
459 for net in &def.nets {
461 if let Some(net_name) = &net.name {
462 let net_id = nets_by_name
464 .entry(net_name)
465 .or_insert_with(|| chip.create_net(&top_cell, Some(net_name.to_string().into())));
466
467 for term in &net.terminals {
468 let term_id: TerminalId<C> = match term {
470 NetTerminal::ComponentPin {
471 component_name,
472 pin_name,
473 } => {
474 let inst = chip
476 .cell_instance_by_name(&top_cell, component_name.as_str())
477 .ok_or_else(|| {
478 LefDefImportError::ComponentNotFound(component_name.to_string())
479 })?;
480 let cell = chip.template_cell(&inst);
481 let pin_id =
482 chip.pin_by_name(&cell, pin_name.as_str()).ok_or_else(|| {
483 LefDefImportError::Other(format!(
484 "Pin of component not found: {}",
485 pin_name
486 ))
487 })?;
488 let pin_inst = chip.pin_instance(&inst, &pin_id);
489
490 TerminalId::PinInstId(pin_inst)
491 }
492 NetTerminal::IoPin(pin_name) => {
493 let pin_id =
495 chip.pin_by_name(&top_cell, pin_name.as_str())
496 .ok_or_else(|| {
497 LefDefImportError::Other(format!(
498 "Pin of top-level cell not found: {}",
499 pin_name
500 ))
501 })?;
502
503 TerminalId::PinId(pin_id)
504 }
505 };
506 chip.connect_terminal(&term_id, Some(net_id.clone()));
508 }
509 } else {
510 log::warn!("DEF import of nets without name (MUSTJOIN nets) is not implemented yet.");
511 }
512 }
513 Ok(())
514}
515
516pub fn import_def_vias<C, Crd>(
518 options: &DEFImportOptions<C>,
519 def: &DEF,
520 chip: &mut C,
521) -> Result<(), LefDefImportError>
522where
523 Crd: NumCast + Ord + CoordinateType,
524 C: L2NEdit<Coord = Crd>,
525{
526 log::debug!("import via definitions from DEF");
527
528 for (via_name, via) in &def.vias {
529 log::debug!("import via '{}'", via_name);
530
531 if chip.cell_by_name(via_name).is_some() {
533 if options.skip_existing_vias {
534 continue;
535 } else {
536 return Err(LefDefImportError::CellNameAlreadyExists(via_name.clone()));
537 }
538 }
539
540 let via_cell = chip.create_cell(via_name.clone().into());
541
542 match via {
543 def_ast::ViaDefinition::ViaGeometry(via_geometry) => {
544 log::debug!("import of via geometry '{}'", via_name);
545 for geometry in via_geometry {
546 if geometry.mask_num.is_some() {
548 log::warn!("via mask number is ignored");
549 }
550
551 let layer = options
552 .lef_import_options
553 .get_or_create_layer_by_name(chip, &geometry.layer)?;
554
555 let geometry: db::Geometry<db::Coord> = match &geometry.shape {
556 def_ast::RectOrPolygon::Rect(r) => r.clone().into(),
557 def_ast::RectOrPolygon::Polygon(p) => p.clone().into(),
558 };
559
560 let geo: db::Geometry<C::Coord> = geometry.try_cast().expect("cast failed");
561
562 chip.insert_shape(&via_cell, &layer, geo);
564 }
565 }
566 def_ast::ViaDefinition::ViaRule => {
567 log::debug!("skip import of via rule '{}'", via_name);
568 }
569 }
570 }
571
572 Ok(())
573}
574
575pub fn import_def_regular_wiring<C, Crd>(
577 options: &DEFImportOptions<C>,
578 lef: &LEF,
579 def: &DEF,
580 top_cell: &C::CellId,
581 chip: &mut C,
582) -> Result<(), LefDefImportError>
583where
584 Crd: NumCast + Ord + CoordinateType + PrimInt,
585 C: L2NEdit<Coord = Crd>,
586{
587 log::info!(
588 "Import wiring from DEF. Number of nets with wiring: {}",
589 def.nets
590 .iter()
591 .filter(|net| !net.regular_wiring.is_empty())
592 .count()
593 );
594
595 let default_wiring_widths = {
597 let mut default_wiring_widths = HashMap::new();
598 let units_per_micron: f64 = chip.dbu().to_f64().unwrap();
599
600 for layer in &lef.technology.layers {
601 match layer {
602 Layer::MasterSlice(_) => {
603 }
605 Layer::Cut(_) => {
606 }
608 Layer::Routing(routing_layer) => {
609 if let Some(layer_id) = chip.layer_by_name(routing_layer.name.as_str()) {
611 let default_widths_microns = routing_layer.width;
613 let default_widths_dbu =
614 db::Coord::from_f64(default_widths_microns * units_per_micron)
615 .expect("Failed to cast default path width to database units.");
616
617 default_wiring_widths.insert(layer_id, default_widths_dbu);
619 } else {
620 log::warn!("Layer '{}' is not present in the current design. Default wiring width will be ignored during import.", &routing_layer.name);
621 }
622 }
623 }
624 }
625 default_wiring_widths
626 };
627
628 for net in &def.nets {
630 let net_name = net.name.as_ref().ok_or_else(|| {
631 LefDefImportError::Other("Wiring for unnamed nets is not supported.".into())
632 })?;
633
634 log::debug!("Import wiring for net '{}'", &net_name);
635
636 let net_id = chip
637 .net_by_name(top_cell, net_name.as_str())
638 .ok_or_else(|| LefDefImportError::Other(format!("Net not found: {}", net_name)))?;
639
640 for regular_wiring in &net.regular_wiring {
641 let _wiring_class = regular_wiring.class; for wiring in ®ular_wiring.wiring {
643 let _style = wiring.style_num; let _taper_rule = &wiring.taper_rule; let mut current_layer = options
648 .lef_import_options
649 .get_or_create_layer_by_name(chip, &wiring.start_layer_name)?;
650 let mut current_point = None;
651
652 let path_width = *default_wiring_widths.get(¤t_layer).ok_or_else(|| {
654 LefDefImportError::Other(format!(
655 "No default wiring width defined for layer '{}'",
656 &wiring.start_layer_name
657 ))
658 })?;
659
660 let _2 = Crd::one() + Crd::one();
661
662 let mut begin_ext = path_width / 2;
663 let mut end_ext = path_width / 2;
664 let mut path: Vec<db::Point<_>> = Vec::new();
665 let mut paths: Vec<db::Path<Crd>> = Vec::new();
666
667 for routing_point in &wiring.routing_points {
668 match routing_point {
669 RoutingPoint::Point {
670 point,
671 ext_value,
672 mask_num,
673 } => {
674 if let Some(ext_value) = ext_value {
675 if current_point.is_none() {
676 begin_ext = *ext_value;
678 }
679 end_ext = *ext_value;
680 }
681 current_point = Some(point.clone());
682 path.push(point.clone());
683 }
684 RoutingPoint::Via {
685 via_name,
686 orient,
687 via_mask_num,
688 } => {
689 if let Some(p) = current_point {
691 let via_cell =
693 chip.cell_by_name(via_name.as_str()).ok_or_else(|| {
694 LefDefImportError::ViaNotFound(via_name.clone())
695 })?;
696
697 let transform = if let Some(orient) = orient {
699 def_orient_to_transform(orient)
700 } else {
701 db::SimpleTransform::identity()
702 }
703 .then(&db::SimpleTransform::translate(p.v().cast()));
704
705 let via_instance =
707 chip.create_cell_instance(&top_cell, &via_cell, None);
708
709 chip.set_transform(&via_instance, transform);
711 } else {
712 log::error!("current point in wiring path is not known");
713 }
714 }
715 RoutingPoint::Rect { rect, mask_num } => {
716 let rect = rect.cast();
718 let shape_id = chip.insert_shape(top_cell, ¤t_layer, rect.into());
719 chip.set_net_of_shape(&shape_id, Some(net_id.clone()));
721 }
722 RoutingPoint::Virtual(p) => {
723 current_point = Some(p.clone());
724 let finished_path = std::mem::replace(&mut path, vec![]);
725
726 let finished_path = db::Path::new_extended(
727 finished_path,
728 path_width,
729 begin_ext,
730 end_ext,
731 )
732 .cast();
733 paths.push(finished_path);
734 }
735 }
736 }
737
738 let finished_path =
740 db::Path::new_extended(path, path_width, begin_ext, end_ext).cast();
741 paths.push(finished_path);
742
743 for path in paths {
745 if path.len() > 1 {
746 let path = path.cast(); let shape_id = chip.insert_shape(top_cell, ¤t_layer, path.into());
749 chip.set_net_of_shape(&shape_id, Some(net_id.clone()));
751 }
752 }
753 }
754 }
755 }
756 Ok(())
757}
758
759pub fn import_def_into_db<C, Crd>(
764 options: &DEFImportOptions<C>,
765 lef: Option<&LEF>,
766 def: &DEF,
767 chip: &mut C,
768) -> Result<(), LefDefImportError>
769where
770 Crd: NumCast + Ord + CoordinateType + PrimInt + std::fmt::Debug,
771 C: L2NEdit<Coord = Crd>,
772{
773 if options.import_fixed_vias {
774 import_def_vias(options, def, chip)?;
775 }
776
777 let top_cell = chip.create_cell(def.design_name.clone().unwrap_or("TOP".to_string()).into());
778 log::info!("Import '{}' from DEF.", chip.cell_name(&top_cell));
779
780 log::info!("Import top-level pins: {}", def.pins.len());
782 for pin in &def.pins {
783 let pin_dir = match &pin.direction {
784 None => Direction::None,
785 Some(d) => match d {
786 PinDirection::Input => Direction::Input,
787 PinDirection::Output(_tristate) => Direction::Output,
788 PinDirection::Inout => Direction::InOut,
789 PinDirection::Feedthru => Direction::InOut,
790 },
791 };
792 chip.create_pin(&top_cell, pin.net_name.to_string().into(), pin_dir);
793 }
794
795 if options.lef_import_options.import_cell_outlines {
797 if let Some(die_area) = &def.die_area {
798 if let Some(outline_layer_name) = &options.lef_import_options.cell_outline_layer {
799 let outline_layer = options
800 .lef_import_options
801 .get_or_create_layer_by_name(chip, outline_layer_name)?;
802
803 let geometry = die_area.cast().into();
805 chip.insert_shape(&top_cell, &outline_layer, geometry);
806 }
807 }
808 }
809
810 log::info!(
812 "Import components from DEF. Number of components: {}",
813 def.components.len()
814 );
815
816 let outline_layer = {
817 let outline_layer_name = options
818 .lef_import_options
819 .cell_outline_layer
820 .as_ref()
821 .ok_or(LefDefImportError::Other(
822 "Outline layer name is not defined.".into(),
823 ))?;
824
825 chip.layer_by_name(outline_layer_name)
826 .ok_or(LefDefImportError::Other(format!(
827 "Outline layer '{}' is not created yet.",
828 outline_layer_name
829 )))?
830 };
831
832 for component in &def.components {
833 let module = chip.cell_by_name(component.model_name.as_str()).ok_or(
835 LefDefImportError::ComponentModelNotFound {
836 component_name: component.name.clone(),
837 model_name: component.model_name.clone(),
838 },
839 )?;
840
841 let bbox = chip.bounding_box_per_layer(&module, &outline_layer).ok_or(
843 LefDefImportError::Other(format!(
844 "Cell has no defined outline: {}",
845 chip.cell_name(&module)
846 )),
847 )?;
848
849 let inst =
851 chip.create_cell_instance(&top_cell, &module, Some(component.name.clone().into()));
852
853 if let Some((displacement, orientation, is_fixed)) = &component.position {
854 let tf = def_orient_to_transform(orientation);
855
856 let bbox = bbox.transform(|p| tf.transform_point(p));
857
858 let tf = tf.then(&db::SimpleTransform::translate(
860 displacement.cast() - bbox.lower_left(),
861 ));
862 chip.set_transform(&inst, tf);
863 }
864 }
865
866 if options.import_blockages {
867 }
869
870 if options.import_nets {
872 import_def_netlist(options, def, &top_cell, chip)?;
873 }
874
875 if options.import_wiring {
877 let lef = lef.ok_or_else(|| {
878 LefDefImportError::Other(
879 "No LEF data is provided but needed for import of wiring.".into(),
880 )
881 })?;
882 import_def_regular_wiring(options, lef, def, &top_cell, chip)?;
883 }
884
885 Ok(())
886}
887
888pub(crate) fn def_orient_to_transform<Crd>(orient: &Orient) -> db::SimpleTransform<Crd>
890where
891 Crd: CoordinateType,
892{
893 let my = &db::SimpleTransform::mirror_y();
894
895 match orient {
896 Orient::N => db::SimpleTransform::identity(),
897 Orient::S => db::SimpleTransform::rotate90(Angle::R180),
898 Orient::E => db::SimpleTransform::rotate90(Angle::R270),
899 Orient::W => db::SimpleTransform::rotate90(Angle::R90),
900 Orient::FN => db::SimpleTransform::identity().then(my),
901 Orient::FS => db::SimpleTransform::rotate90(Angle::R180).then(my),
902 Orient::FE => db::SimpleTransform::rotate90(Angle::R270).then(my),
903 Orient::FW => db::SimpleTransform::rotate90(Angle::R90).then(my),
904 }
905}
906
907pub(crate) fn transform_to_def_orient<Crd>(tf: &db::SimpleTransform<Crd>) -> Orient
908where
909 Crd: CoordinateType,
910{
911 let (angle, flip_y) = if tf.mirror {
912 let tf_unflipped_y = tf.then(&db::SimpleTransform::mirror_y());
914 (tf_unflipped_y.rotation, true)
915 } else {
916 (tf.rotation, false)
917 };
918
919 let orientation = match angle {
920 Angle::R0 => Orient::N,
921 Angle::R180 => Orient::S,
922 Angle::R270 => Orient::E,
923 Angle::R90 => Orient::W,
924 };
925
926 if flip_y {
927 orientation.flipped()
928 } else {
929 orientation
930 }
931}
932
933#[test]
934fn test_orient_to_transform() {
935 use Orient::*;
936 let orients = [N, S, W, E, FN, FS, FW, FE];
937 for o in orients {
938 assert_eq!(
939 o,
940 transform_to_def_orient(&def_orient_to_transform::<i32>(&o))
941 );
942 }
943}
944
945#[test]
946fn test_lefdef_to_chip() {
947 use crate::def_parser::read_def_chars;
948 use crate::lef_parser::read_lef_chars;
949 let data = r#"
950# Parts from gscl45nm.lef.
951
952VERSION 5.5 ;
953NAMESCASESENSITIVE ON ;
954BUSBITCHARS "[]" ;
955DIVIDERCHAR "/" ;
956
957PROPERTYDEFINITIONS
958 LAYER contactResistance REAL ;
959END PROPERTYDEFINITIONS
960
961UNITS
962 DATABASE MICRONS 2000 ;
963END UNITS
964MANUFACTURINGGRID 0.0025 ;
965LAYER poly
966 TYPE MASTERSLICE ;
967END poly
968
969LAYER contact
970 TYPE CUT ;
971 SPACING 0.075 ;
972 PROPERTY contactResistance 10.5 ;
973END contact
974
975LAYER metal1
976 TYPE ROUTING ;
977 DIRECTION HORIZONTAL ;
978 PITCH 0.19 ;
979 WIDTH 0.065 ;
980 SPACING 0.065 ;
981 RESISTANCE RPERSQ 0.38 ;
982END metal1
983
984LAYER via1
985 TYPE CUT ;
986 SPACING 0.075 ;
987 PROPERTY contactResistance 5.69 ;
988END via1
989
990LAYER metal2
991 TYPE ROUTING ;
992 DIRECTION VERTICAL ;
993 PITCH 0.19 ;
994 WIDTH 0.065 ;
995 SPACING 0.065 ;
996 RESISTANCE RPERSQ 0.38 ;
997END metal2
998
999LAYER OVERLAP
1000 TYPE OVERLAP ;
1001END OVERLAP
1002
1003VIA M2_M1_via DEFAULT
1004 LAYER metal1 ;
1005 RECT -0.0675 -0.0325 0.0675 0.0325 ;
1006 LAYER via1 ;
1007 RECT -0.0325 -0.0325 0.0325 0.0325 ;
1008 LAYER metal2 ;
1009 RECT -0.035 -0.0675 0.035 0.0675 ;
1010END M2_M1_via
1011
1012VIARULE M2_M1 GENERATE
1013 LAYER metal1 ;
1014 ENCLOSURE 0 0.035 ;
1015 LAYER metal2 ;
1016 ENCLOSURE 0 0.035 ;
1017 LAYER via1 ;
1018 RECT -0.0325 -0.0325 0.0325 0.0325 ;
1019 SPACING 0.14 BY 0.14 ;
1020END M2_M1
1021
1022VIARULE M1_POLY GENERATE
1023 LAYER poly ;
1024 ENCLOSURE 0 0 ;
1025 LAYER metal1 ;
1026 ENCLOSURE 0 0.035 ;
1027 LAYER contact ;
1028 RECT -0.0325 -0.0325 0.0325 0.0325 ;
1029 SPACING 0.14 BY 0.14 ;
1030END M1_POLY
1031
1032SPACING
1033 SAMENET metal1 metal1 0.1 ;
1034 SAMENET metal2 metal2 0.1 ;
1035END SPACING
1036
1037SITE CoreSite
1038 CLASS CORE ;
1039 SIZE 0.38 BY 2.47 ;
1040END CoreSite
1041
1042MACRO INVX1
1043 CLASS CORE ;
1044 ORIGIN 0 0 ;
1045 FOREIGN INVX1 0 0 ;
1046 SIZE 0.57 BY 2.47 ;
1047 SYMMETRY X Y ;
1048 SITE CoreSite ;
1049 PIN A
1050 DIRECTION INPUT ;
1051 USE SIGNAL ;
1052 PORT
1053 LAYER metal1 ;
1054 RECT 0.1575 0.4875 0.2575 0.6225 ;
1055 END
1056 END A
1057 PIN Y
1058 DIRECTION OUTPUT ;
1059 USE SIGNAL ;
1060 PORT
1061 LAYER metal1 ;
1062 RECT 0.3475 0.2175 0.4125 1.815 ;
1063 RECT 0.3125 0.2175 0.4475 0.4225 ;
1064 END
1065 END Y
1066 PIN gnd
1067 DIRECTION INOUT ;
1068 USE GROUND ;
1069 SHAPE ABUTMENT ;
1070 PORT
1071 LAYER metal1 ;
1072 RECT 0.1625 -0.065 0.2275 0.4225 ;
1073 RECT 0 -0.065 0.57 0.065 ;
1074 END
1075 END gnd
1076 PIN vdd
1077 DIRECTION INOUT ;
1078 USE POWER ;
1079 SHAPE ABUTMENT ;
1080 PORT
1081 LAYER metal1 ;
1082 RECT 0.1625 1.265 0.2275 2.535 ;
1083 RECT 0 2.405 0.57 2.535 ;
1084 END
1085 END vdd
1086END INVX1
1087
1088
1089MACRO INVX2
1090 CLASS CORE ;
1091 ORIGIN 0 0 ;
1092 FOREIGN INVX1 0 0 ;
1093 SIZE 0.57 BY 2.47 ;
1094 SYMMETRY X Y ;
1095 SITE CoreSite ;
1096 PIN A
1097 DIRECTION INPUT ;
1098 USE SIGNAL ;
1099 PORT
1100 LAYER metal1 ;
1101 RECT 0.1575 0.4875 0.2575 0.6225 ;
1102 END
1103 END A
1104 PIN Y
1105 DIRECTION OUTPUT ;
1106 USE SIGNAL ;
1107 PORT
1108 LAYER metal1 ;
1109 RECT 0.3475 0.2175 0.4125 1.815 ;
1110 RECT 0.3125 0.2175 0.4475 0.4225 ;
1111 END
1112 END Y
1113 PIN gnd
1114 DIRECTION INOUT ;
1115 USE GROUND ;
1116 SHAPE ABUTMENT ;
1117 PORT
1118 LAYER metal1 ;
1119 RECT 0.1625 -0.065 0.2275 0.4225 ;
1120 RECT 0 -0.065 0.57 0.065 ;
1121 END
1122 END gnd
1123 PIN vdd
1124 DIRECTION INOUT ;
1125 USE POWER ;
1126 SHAPE ABUTMENT ;
1127 PORT
1128 LAYER metal1 ;
1129 RECT 0.1625 1.265 0.2275 2.535 ;
1130 RECT 0 2.405 0.57 2.535 ;
1131 END
1132 END vdd
1133END INVX2
1134
1135END LIBRARY
1136
1137 "#;
1138
1139 let result = read_lef_chars(data.chars());
1140 let lef = result.expect("LEF parsing failed.");
1141
1142 let def_data = r#"
1143VERSION 5.7 ;
1144DIVIDERCHAR "/" ;
1145BUSBITCHARS "[]" ;
1146DESIGN test_design ;
1147UNITS DISTANCE MICRONS 2000 ;
1148TECHNOLOGY FreePDK45 ;
1149
1150DIEAREA ( 0 0 ) ( 10000 10000 ) ;
1151
1152PINS 2 ;
1153- IN + NET IN
1154 + DIRECTION INPUT
1155- OUT + NET OUT
1156 + DIRECTION OUTPUT
1157END PINS
1158
1159COMPONENTS 4 ;
1160 - _1_ INVX1
1161 + PLACED ( 0 0 ) N ;
1162 - _2_ INVX2
1163 + PLACED ( 0 0 ) S ;
1164 - _3_ INVX2
1165 + PLACED ( 0 0 ) FN ;
1166 - _4_ INVX1
1167 + PLACED ( 0 0 ) FW ;
1168END COMPONENTS
1169
1170NETS 6 ;
1171- IN ( PIN IN ) ;
1172- OUT ( PIN OUT ) ;
1173- net1 ( _1_ A ) ;
1174END NETS
1175
1176END DESIGN
1177"#;
1178
1179 let result = read_def_chars(def_data.chars());
1180 let def = result.expect("DEF parsing failed.");
1181
1182 let mut chip = db::Chip::new();
1183 chip.set_dbu(1000);
1184 let mut options = DEFImportOptions::default();
1185 options.lef_import_options.import_power_pins = false;
1186 {
1188 let result = import_lef_into_db(&options.lef_import_options, &lef, &mut chip);
1189 if result.is_err() {
1190 dbg!(&result);
1191 }
1192 }
1193 {
1195 let result = import_def_into_db(&options, Some(&lef), &def, &mut chip);
1196 if result.is_err() {
1197 dbg!(&result);
1198 }
1199 }
1200
1201 assert_eq!(chip.num_cells(), 1 + 2 + 1); let top = chip.cell_by_name("test_design").unwrap();
1204 assert_eq!(chip.num_child_instances(&top), 4);
1205
1206 let invx1 = chip.cell_by_name("INVX1").expect("Cell not found.");
1207 assert_eq!(chip.num_pins(&invx1), 2);
1208
1209 assert_eq!(chip.num_internal_nets(&top), 3 + 2); let pin_a = chip.pin_by_name(&invx1, "A").expect("Pin A not found.");
1213
1214 let [inst1, inst2, inst3, inst4] = ["_1_", "_2_", "_3_", "_4_"].map(|n| {
1215 chip.cell_instance_by_name(&top, n)
1216 .expect("Cell instance not found.")
1217 });
1218
1219 let net = chip
1220 .net_of_pin_instance(&chip.pin_instance(&inst1, &pin_a))
1221 .expect("No net connected to _1_:A.");
1222
1223 assert_eq!(chip.net_name(&net), Some("net1".to_string()));
1224
1225 let outline_layer = chip.layer_by_name("OUTLINE").unwrap();
1227 dbg!(chip.bounding_box_per_layer(&invx1, &outline_layer));
1228
1229 let tf1 = chip.get_transform(&inst1);
1231 assert_eq!(tf1, db::SimpleTransform::translate((0, 0)));
1232
1233 let tf2 = chip.get_transform(&inst2);
1235 assert_eq!(
1236 tf2,
1237 db::SimpleTransform::rotate90(Angle::R180)
1238 .then(&db::SimpleTransform::translate((570, 2470)))
1239 );
1240
1241 let tf3 = chip.get_transform(&inst3);
1243 assert_eq!(
1244 tf3,
1245 db::SimpleTransform::mirror_y().then(&db::SimpleTransform::translate((570, 0)))
1246 );
1247
1248 let tf4 = chip.get_transform(&inst4);
1250 assert_eq!(
1251 tf4,
1252 db::SimpleTransform::rotate90(Angle::R90)
1253 .then(&db::SimpleTransform::mirror_y())
1254 .then(&db::SimpleTransform::translate((0, 0)))
1255 );
1256}