dsn: make `DsnDesign` don't own the constructed `DsnRules` object

This commit is contained in:
Mikolaj Wielgus 2024-03-09 12:54:35 +00:00
parent b661047ca8
commit f8892f64a7
3 changed files with 41 additions and 44 deletions

View File

@ -1,6 +1,6 @@
use std::fmt; use std::fmt;
use serde::de::{self, DeserializeSeed, SeqAccess, EnumAccess, VariantAccess, Visitor}; use serde::de::{self, DeserializeSeed, EnumAccess, SeqAccess, VariantAccess, Visitor};
use serde::Deserialize; use serde::Deserialize;
use thiserror::Error; use thiserror::Error;
@ -88,9 +88,9 @@ impl<'de> Deserializer<'de> {
fn keyword_lookahead(&self) -> Option<String> { fn keyword_lookahead(&self) -> Option<String> {
let mut iter = self.input.chars(); let mut iter = self.input.chars();
if let Some('(') = iter.next() { if let Some('(') = iter.next() {
Some(iter Some(
.take_while(|c| c != &' ' && c != &'\r' && c != &'\n') iter.take_while(|c| c != &' ' && c != &'\r' && c != &'\n')
.collect::<String>() .collect::<String>(),
) )
} else { } else {
None None
@ -387,9 +387,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let elem_type = self.vec_type.expect( let elem_type = self
"fields of type Vec<_> need to have names suffixed with _vec" .vec_type
); .expect("fields of type Vec<_> need to have names suffixed with _vec");
visitor.visit_seq(ArrayIndices::new(self, elem_type)) visitor.visit_seq(ArrayIndices::new(self, elem_type))
} }
@ -461,7 +461,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
V: Visitor<'de>, V: Visitor<'de>,
{ {
self.skip_ws(); self.skip_ws();
visitor.visit_string(self.parse_string().map_err(|err| DeError::ExpectedKeyword)?) visitor.visit_string(
self.parse_string()
.map_err(|err| DeError::ExpectedKeyword)?,
)
} }
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value>
@ -515,11 +518,7 @@ impl<'de, 'a> VariantAccess<'de> for Enum<'a, 'de> {
todo!(); todo!();
} }
fn struct_variant<V>( fn struct_variant<V>(self, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value>
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
@ -554,9 +553,10 @@ impl<'de, 'a> SeqAccess<'de> for ArrayIndices<'a, 'de> {
// anonymous field // anonymous field
seed.deserialize(&mut *self.de).map(Some) seed.deserialize(&mut *self.de).map(Some)
} else { } else {
let lookahead = self.de.keyword_lookahead().ok_or( let lookahead = self
DeError::ExpectedOpeningParen(self.elem_type) .de
)?; .keyword_lookahead()
.ok_or(DeError::ExpectedOpeningParen(self.elem_type))?;
if lookahead == self.elem_type { if lookahead == self.elem_type {
// cannot fail, consuming the lookahead // cannot fail, consuming the lookahead
self.de.next().unwrap(); self.de.next().unwrap();

View File

@ -9,7 +9,7 @@ use crate::{
use super::{ use super::{
de, de,
rules::Rules, rules::DsnRules,
structure::{DsnFile, Pcb, Shape}, structure::{DsnFile, Pcb, Shape},
}; };
@ -24,7 +24,6 @@ pub enum LoadingError {
#[derive(Debug)] #[derive(Debug)]
pub struct DsnDesign { pub struct DsnDesign {
pcb: Pcb, pcb: Pcb,
rules: Rules,
} }
impl DsnDesign { impl DsnDesign {
@ -34,21 +33,22 @@ impl DsnDesign {
.map_err(|err| LoadingError::Syntax(err))? .map_err(|err| LoadingError::Syntax(err))?
.pcb; .pcb;
let rules = Rules::from_pcb(&pcb); Ok(Self { pcb })
Ok(Self { pcb, rules })
} }
pub fn make_layout(&self) -> Layout<&Rules> { pub fn make_layout(&self) -> Layout<DsnRules> {
let mut layout = Layout::new(&self.rules); let rules = DsnRules::from_pcb(&self.pcb);
let mut layout = Layout::new(rules);
// mapping of pin id -> net id prepared for adding pins // mapping of pin id -> net id prepared for adding pins
let pin_nets = HashMap::<String, i64>::from_iter( let pin_nets = HashMap::<String, i64>::from_iter(
self.pcb.network.net_vec self.pcb
.network
.net_vec
.iter() .iter()
.map(|net| { .map(|net| {
// resolve the id so we don't work with strings // resolve the id so we don't work with strings
let net_id = self.rules.net_ids.get(&net.name).unwrap(); let net_id = layout.rules().net_ids.get(&net.name).unwrap();
// take the list of pins // take the list of pins
// and for each pin id output (pin id, net id) // and for each pin id output (pin id, net id)
@ -85,10 +85,7 @@ impl DsnDesign {
match &padstack.shape_vec[0] { match &padstack.shape_vec[0] {
Shape::Circle(circle) => { Shape::Circle(circle) => {
let circle = Circle { let circle = Circle {
pos: ( pos: ((place.x + pin.x) as f64, -(place.y + pin.y) as f64).into(),
(place.x + pin.x) as f64,
-(place.y + pin.y) as f64
).into(),
r: circle.diameter as f64 / 2.0, r: circle.diameter as f64 / 2.0,
}; };
@ -114,7 +111,7 @@ impl DsnDesign {
.via_vec .via_vec
.iter() .iter()
.map(|via| { .map(|via| {
let net_id = self.rules.net_ids.get(&via.net).unwrap(); let net_id = layout.rules().net_ids.get(&via.net).unwrap();
// find the padstack referenced by this via placement // find the padstack referenced by this via placement
let padstack = &self let padstack = &self
@ -147,12 +144,12 @@ impl DsnDesign {
.collect(); .collect();
for wire in self.pcb.wiring.wire_vec.iter() { for wire in self.pcb.wiring.wire_vec.iter() {
let net_id = self.rules.net_ids.get(&wire.net).unwrap(); let net_id = *layout.rules().net_ids.get(&wire.net).unwrap();
// add the first coordinate in the wire path as a dot and save its index // add the first coordinate in the wire path as a dot and save its index
let mut prev_index = layout let mut prev_index = layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
net: *net_id as i64, net: net_id as i64,
circle: Circle { circle: Circle {
pos: ( pos: (
wire.path.coord_vec[0].x as f64, wire.path.coord_vec[0].x as f64,
@ -168,7 +165,7 @@ impl DsnDesign {
for coord in wire.path.coord_vec.iter().skip(1) { for coord in wire.path.coord_vec.iter().skip(1) {
let index = layout let index = layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
net: *net_id as i64, net: net_id as i64,
circle: Circle { circle: Circle {
pos: (coord.x as f64, -coord.y as f64).into(), pos: (coord.x as f64, -coord.y as f64).into(),
r: wire.path.width as f64 / 2.0, r: wire.path.width as f64 / 2.0,
@ -182,7 +179,7 @@ impl DsnDesign {
prev_index, prev_index,
index, index,
FixedSegWeight { FixedSegWeight {
net: *net_id as i64, net: net_id as i64,
width: wire.path.width as f64, width: wire.path.width as f64,
}, },
) )

View File

@ -5,12 +5,12 @@ use crate::layout::rules::{Conditions, RulesTrait};
use super::structure::Pcb; use super::structure::Pcb;
#[derive(Debug)] #[derive(Debug)]
pub struct Rule { pub struct DsnRule {
pub width: f64, pub width: f64,
pub clearance: f64, pub clearance: f64,
} }
impl Rule { impl DsnRule {
fn from_dsn(rule: &super::structure::Rule) -> Self { fn from_dsn(rule: &super::structure::Rule) -> Self {
Self { Self {
width: rule.width as f64 / 100.0, width: rule.width as f64 / 100.0,
@ -20,10 +20,10 @@ impl Rule {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Rules { pub struct DsnRules {
structure_rule: Rule, structure_rule: DsnRule,
// net class name -> rule // net class name -> rule
class_rules: HashMap<String, Rule>, class_rules: HashMap<String, DsnRule>,
// net names -> net IDs for Layout // net names -> net IDs for Layout
pub net_ids: HashMap<String, i64>, pub net_ids: HashMap<String, i64>,
@ -31,7 +31,7 @@ pub struct Rules {
net_id_classes: HashMap<i64, String>, net_id_classes: HashMap<i64, String>,
} }
impl Rules { impl DsnRules {
pub fn from_pcb(pcb: &Pcb) -> Self { pub fn from_pcb(pcb: &Pcb) -> Self {
// keeping this as a separate iter pass because it might be moved into a different struct later? // keeping this as a separate iter pass because it might be moved into a different struct later?
let net_ids = HashMap::from_iter( let net_ids = HashMap::from_iter(
@ -54,18 +54,18 @@ impl Rules {
net_id_classes.insert(*net_id, class.name.clone()); net_id_classes.insert(*net_id, class.name.clone());
} }
}) })
.map(|class| (class.name.clone(), Rule::from_dsn(&class.rule))), .map(|class| (class.name.clone(), DsnRule::from_dsn(&class.rule))),
); );
Self { Self {
structure_rule: Rule::from_dsn(&pcb.structure.rule), structure_rule: DsnRule::from_dsn(&pcb.structure.rule),
class_rules, class_rules,
net_ids, net_ids,
net_id_classes, net_id_classes,
} }
} }
pub fn get_rule(&self, net: i64) -> &Rule { pub fn get_rule(&self, net: i64) -> &DsnRule {
if let Some(netclass) = self.net_id_classes.get(&net) { if let Some(netclass) = self.net_id_classes.get(&net) {
self.class_rules self.class_rules
.get(netclass) .get(netclass)
@ -76,7 +76,7 @@ impl Rules {
} }
} }
impl<'a> RulesTrait for &'a Rules { impl RulesTrait for DsnRules {
fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64 { fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64 {
let clr1 = self.get_rule(conditions1.net).clearance; let clr1 = self.get_rule(conditions1.net).clearance;
let clr2 = self.get_rule(conditions2.net).clearance; let clr2 = self.get_rule(conditions2.net).clearance;