mirror of https://codeberg.org/topola/topola.git
dsn: make `DsnDesign` don't own the constructed `DsnRules` object
This commit is contained in:
parent
b661047ca8
commit
f8892f64a7
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue