dsn: encapsulate DSN structure in new `DsnDesign` struct

Using a placeholder instead of rules and disabled routing for now. Also
did some formatting corrections.
This commit is contained in:
Mikolaj Wielgus 2024-02-22 04:49:55 +00:00
parent 3f6bad2ed6
commit 473a877845
14 changed files with 247 additions and 211 deletions

View File

@ -13,6 +13,7 @@ use geo::point;
use painter::Painter; use painter::Painter;
use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use topola::draw::DrawException; use topola::draw::DrawException;
use topola::dsn::design::DsnDesign;
use topola::layout::connectivity::BandIndex; use topola::layout::connectivity::BandIndex;
use topola::layout::dot::FixedDotWeight; use topola::layout::dot::FixedDotWeight;
use topola::layout::geometry::shape::{Shape, ShapeTrait}; use topola::layout::geometry::shape::{Shape, ShapeTrait};
@ -48,9 +49,6 @@ use topola::tracer::{Trace, Tracer};
use topola::math::Circle; use topola::math::Circle;
use topola::router::Router; use topola::router::Router;
use topola::dsn::de::from_str;
use topola::dsn::structure::Pcb;
struct SimpleRules { struct SimpleRules {
net_clearances: HashMap<(i64, i64), f64>, net_clearances: HashMap<(i64, i64), f64>,
} }
@ -237,7 +235,7 @@ fn main() -> Result<(), anyhow::Error> {
let mut event_pump = sdl_context.event_pump().unwrap(); let mut event_pump = sdl_context.event_pump().unwrap();
let _i = 0; let _i = 0;
let mut router = Router::new(SimpleRules { /*let mut router = Router::new(Layout::new(SimpleRules {
net_clearances: HashMap::from([ net_clearances: HashMap::from([
((1, 2), 8.0), ((1, 2), 8.0),
((2, 1), 8.0), ((2, 1), 8.0),
@ -246,88 +244,12 @@ fn main() -> Result<(), anyhow::Error> {
((3, 4), 15.0), ((3, 4), 15.0),
((4, 3), 15.0), ((4, 3), 15.0),
]), ]),
}); }));*/
let design = DsnDesign::load_from_file("tests/data/test.dsn")?;
let contents = std::fs::read_to_string("tests/data/test.dsn")?; let layout = design.make_layout();
let pcb = from_str::<Pcb>(&contents)?; let mut router = Router::new(layout);
//dbg!(&pcb); //dbg!(&pcb);
// this holds the mapping of net names to numerical IDs (here for now)
let net_ids: HashMap<String, usize> = HashMap::from_iter(
pcb.network.classes[0].nets
.iter()
.enumerate()
.map(|(id, net)| (net.clone(), id))
);
// add vias to layout and save indices of dots in the order they appear in the file
let dot_indices: Vec<_> = pcb.wiring.vias
.iter()
.map(|via| {
let net_id = net_ids.get(&via.net.0).unwrap();
let component = router.layout.add_component(*net_id as i64);
// no way to resolve the name or layer support yet
// pick the first layer of the first object found
let circle = &pcb.library.padstacks[0].shapes[0].0;
let circle = Circle {
pos: (
via.x as f64 / 100.0,
-via.y as f64 / 100.0,
).into(),
r: circle.radius as f64 / 100.0,
};
router.layout.add_fixed_dot(FixedDotWeight {
component,
circle,
}).unwrap()
})
.collect();
for wire in pcb.wiring.wires.iter() {
let net_id = net_ids.get(&wire.net.0).unwrap();
let component = router.layout.add_component(*net_id as i64);
// add the first coordinate in the wire path as a dot and save its index
let mut prev_index = router.layout.add_fixed_dot(FixedDotWeight {
component,
circle: Circle {
pos: (
wire.path.coords[0].x as f64 / 100.0,
-wire.path.coords[0].y as f64 / 100.0,
).into(),
r: wire.path.width as f64 / 100.0,
}
}).unwrap();
// iterate through path coords starting from the second
for coord in wire.path.coords.iter().skip(1) {
let index = router.layout.add_fixed_dot(FixedDotWeight {
component,
circle: Circle {
pos: (
coord.x as f64 / 100.0,
-coord.y as f64 / 100.0,
).into(),
r: wire.path.width as f64 / 100.0,
}
}).unwrap();
// add a seg between the current and previous coords
let _ = router.layout.add_fixed_seg(
prev_index,
index,
FixedSegWeight {
component,
width: wire.path.width as f64 / 100.0,
},
).unwrap();
prev_index = index;
}
}
render_times( render_times(
&mut event_pump, &mut event_pump,
&window, &window,
@ -343,13 +265,13 @@ fn main() -> Result<(), anyhow::Error> {
); );
// these are both on net 1 in the test file // these are both on net 1 in the test file
let _ = router.route_band( /*let _ = router.route_band(
dot_indices[1], dot_indices[1],
dot_indices[2], dot_indices[2],
3.0, 3.0,
//&mut EmptyRouterObserver, //&mut EmptyRouterObserver,
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
)?; )?;*/
render_times( render_times(
&mut event_pump, &mut event_pump,

View File

@ -1,5 +1,5 @@
use serde::de::{self, DeserializeSeed, SeqAccess, Visitor};
use serde::Deserialize; use serde::Deserialize;
use serde::de::{self, Visitor, SeqAccess, DeserializeSeed};
use thiserror::Error; use thiserror::Error;
type Result<T> = std::result::Result<T, Error>; type Result<T> = std::result::Result<T, Error>;
@ -32,8 +32,7 @@ impl de::Error for Error {
} }
} }
struct Deserializer<'de> struct Deserializer<'de> {
{
input: &'de str, input: &'de str,
line: usize, line: usize,
column: usize, column: usize,
@ -72,9 +71,11 @@ impl<'de> Deserializer<'de> {
let mut iter = self.input.chars(); let mut iter = self.input.chars();
if iter.next() != Some('(') { if iter.next() != Some('(') {
None None
} } else {
else { Some(
Some(iter.take_while(|c| c != &' ' && c != &'\r' && c != &'\n').collect::<String>()) iter.take_while(|c| c != &' ' && c != &'\r' && c != &'\n')
.collect::<String>(),
)
} }
} }
@ -88,8 +89,7 @@ impl<'de> Deserializer<'de> {
if chr == '\n' { if chr == '\n' {
self.line += 1; self.line += 1;
self.column = 0; self.column = 0;
} } else {
else {
self.column += 1; self.column += 1;
} }
Ok(chr) Ok(chr)
@ -99,8 +99,7 @@ impl<'de> Deserializer<'de> {
while let Ok(chr) = self.peek() { while let Ok(chr) = self.peek() {
if chr != ' ' && chr != '\r' && chr != '\n' { if chr != ' ' && chr != '\r' && chr != '\n' {
return; return;
} } else {
else {
self.next().unwrap(); self.next().unwrap();
} }
} }
@ -113,7 +112,7 @@ impl<'de> Deserializer<'de> {
"on" => Ok(true), "on" => Ok(true),
"off" => Ok(false), "off" => Ok(false),
_ => Err(Error::ExpectedBool), _ => Err(Error::ExpectedBool),
} },
Err(_) => Err(Error::ExpectedBool), Err(_) => Err(Error::ExpectedBool),
} }
} }
@ -126,8 +125,7 @@ impl<'de> Deserializer<'de> {
let chr = self.peek()?; let chr = self.peek()?;
if self.string_quote == Some(chr) { if self.string_quote == Some(chr) {
self.parse_quoted() self.parse_quoted()
} } else {
else {
self.parse_unquoted() self.parse_unquoted()
} }
} }
@ -138,12 +136,10 @@ impl<'de> Deserializer<'de> {
let chr = self.peek()?; let chr = self.peek()?;
if chr != ' ' && chr != '\r' && chr != '\n' && chr != '(' && chr != ')' { if chr != ' ' && chr != '\r' && chr != '\n' && chr != '(' && chr != ')' {
string.push(self.next()?); // can't fail because of earlier peek string.push(self.next()?); // can't fail because of earlier peek
} } else {
else {
if string.len() > 0 { if string.len() > 0 {
return Ok(string); return Ok(string);
} } else {
else {
dbg!(self.line, self.column); dbg!(self.line, self.column);
return Err(Error::ExpectedUnquoted); return Err(Error::ExpectedUnquoted);
} }
@ -170,8 +166,7 @@ impl<'de> Deserializer<'de> {
if Some(chr) == self.string_quote { if Some(chr) == self.string_quote {
self.next().unwrap(); self.next().unwrap();
return Ok(string); return Ok(string);
} } else {
else {
string.push(self.next()?); // can't fail because of earlier peek string.push(self.next()?); // can't fail because of earlier peek
} }
} }
@ -195,15 +190,15 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error; type Error = Error;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
where V: where
Visitor<'de>, V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value> fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where V: where
Visitor<'de>, V: Visitor<'de>,
{ {
let value = self.parse_bool()?; let value = self.parse_bool()?;
self.skip_ws(); self.skip_ws();
@ -220,17 +215,20 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
} }
fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_i16<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_i16<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value> fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
let value = self.parse_unquoted()?; let value = self.parse_unquoted()?;
self.skip_ws(); self.skip_ws();
@ -239,22 +237,26 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
visitor.visit_i32(value.parse().unwrap()) visitor.visit_i32(value.parse().unwrap())
} }
fn deserialize_i64<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_i64<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_u8<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_u8<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value> fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
let value = self.parse_unquoted()?; let value = self.parse_unquoted()?;
self.skip_ws(); self.skip_ws();
@ -263,12 +265,14 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
visitor.visit_u32(value.parse().unwrap()) visitor.visit_u32(value.parse().unwrap())
} }
fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value> fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
let value = self.parse_unquoted()?; let value = self.parse_unquoted()?;
self.skip_ws(); self.skip_ws();
@ -277,12 +281,14 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
visitor.visit_f32(value.parse().unwrap()) visitor.visit_f32(value.parse().unwrap())
} }
fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value> fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
let chr = self.next()?; let chr = self.next()?;
self.skip_ws(); self.skip_ws();
@ -299,14 +305,15 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
} }
fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value> fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
where V: where
Visitor<'de>, V: Visitor<'de>,
{ {
let string = self.parse_string()?; let string = self.parse_string()?;
self.skip_ws(); self.skip_ws();
@ -316,43 +323,40 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
} }
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_byte_buf<V>( fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value>
self, where
_visitor: V V: Visitor<'de>,
) -> Result<V::Value>
where V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value> fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
if self.next_option_empty_hint { if self.next_option_empty_hint {
visitor.visit_none() visitor.visit_none()
} } else {
else {
visitor.visit_some(self) visitor.visit_some(self)
} }
} }
fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_unit_struct<V>( fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value>
self, where
name: &'static str, V: Visitor<'de>,
visitor: V
) -> Result<V::Value>
where V: Visitor<'de>,
{ {
if self.next()? != '(' { if self.next()? != '(' {
return Err(Error::ExpectedOpeningParen); return Err(Error::ExpectedOpeningParen);
@ -374,12 +378,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
visitor.visit_unit() visitor.visit_unit()
} }
fn deserialize_newtype_struct<V>( fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value>
self, where
name: &'static str, V: Visitor<'de>,
visitor: V
) -> Result<V::Value>
where V: Visitor<'de>,
{ {
if self.next()? != '(' { if self.next()? != '(' {
return Err(Error::ExpectedOpeningParen); return Err(Error::ExpectedOpeningParen);
@ -413,18 +414,16 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
} }
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value> fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
self.last_deserialized_type = None; self.last_deserialized_type = None;
visitor.visit_seq(ArrayIndices::new(self)) visitor.visit_seq(ArrayIndices::new(self))
} }
fn deserialize_tuple<V>( fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
self, where
_len: usize, V: Visitor<'de>,
_visitor: V
) -> Result<V::Value>
where V: Visitor<'de>,
{ {
todo!(); todo!();
} }
@ -433,15 +432,17 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
self, self,
_name: &'static str, _name: &'static str,
_len: usize, _len: usize,
_visitor: V _visitor: V,
) -> Result<V::Value> ) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
@ -450,9 +451,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
self, self,
name: &'static str, name: &'static str,
fields: &'static [&'static str], fields: &'static [&'static str],
visitor: V visitor: V,
) -> Result<V::Value> ) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
if self.next()? != '(' { if self.next()? != '(' {
return Err(Error::ExpectedOpeningParen); return Err(Error::ExpectedOpeningParen);
@ -481,27 +483,24 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
self, self,
_name: &'static str, _name: &'static str,
_variants: &'static [&'static str], _variants: &'static [&'static str],
_visitor: V _visitor: V,
) -> Result<V::Value> ) -> Result<V::Value>
where V: Visitor<'de>, where
V: Visitor<'de>,
{ {
todo!(); todo!();
} }
fn deserialize_identifier<V>( fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
self, where
visitor: V V: Visitor<'de>,
) -> Result<V::Value>
where V: Visitor<'de>
{ {
visitor.visit_string(self.parse_string()?) visitor.visit_string(self.parse_string()?)
} }
fn deserialize_ignored_any<V>( fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value>
self, where
_visitor: V V: Visitor<'de>,
) -> Result<V::Value>
where V: Visitor<'de>
{ {
todo!(); todo!();
} }
@ -513,9 +512,7 @@ struct NewtypeStructFields<'a, 'de: 'a> {
impl<'a, 'de> NewtypeStructFields<'a, 'de> { impl<'a, 'de> NewtypeStructFields<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self { fn new(de: &'a mut Deserializer<'de>) -> Self {
Self { Self { de }
de,
}
} }
} }
@ -523,7 +520,8 @@ impl<'de, 'a> SeqAccess<'de> for NewtypeStructFields<'a, 'de> {
type Error = Error; type Error = Error;
fn next_element_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>> fn next_element_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>>
where S: DeserializeSeed<'de>, where
S: DeserializeSeed<'de>,
{ {
if self.de.peek()? == ')' { if self.de.peek()? == ')' {
return Ok(None); return Ok(None);
@ -539,9 +537,7 @@ struct ArrayIndices<'a, 'de: 'a> {
impl<'a, 'de> ArrayIndices<'a, 'de> { impl<'a, 'de> ArrayIndices<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self { fn new(de: &'a mut Deserializer<'de>) -> Self {
Self { Self { de }
de,
}
} }
} }
@ -549,7 +545,8 @@ impl<'de, 'a> SeqAccess<'de> for ArrayIndices<'a, 'de> {
type Error = Error; type Error = Error;
fn next_element_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>> fn next_element_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>>
where S: DeserializeSeed<'de>, where
S: DeserializeSeed<'de>,
{ {
if self.de.peek()? == ')' { if self.de.peek()? == ')' {
return Ok(None); return Ok(None);
@ -570,7 +567,6 @@ impl<'de, 'a> SeqAccess<'de> for ArrayIndices<'a, 'de> {
} }
} }
struct StructFields<'a, 'de: 'a> { struct StructFields<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>, de: &'a mut Deserializer<'de>,
current_field: usize, current_field: usize,
@ -591,7 +587,8 @@ impl<'de, 'a> SeqAccess<'de> for StructFields<'a, 'de> {
type Error = Error; type Error = Error;
fn next_element_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>> fn next_element_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>>
where S: DeserializeSeed<'de>, where
S: DeserializeSeed<'de>,
{ {
if self.de.peek()? == ')' { if self.de.peek()? == ')' {
if self.current_field < self.fields.len() { if self.current_field < self.fields.len() {
@ -606,8 +603,7 @@ impl<'de, 'a> SeqAccess<'de> for StructFields<'a, 'de> {
// then even though our bet here was wrong (and we just lied to serde) // then even though our bet here was wrong (and we just lied to serde)
// the deserializer we handed off to will see the same closing paren // the deserializer we handed off to will see the same closing paren
// (that we reacted to just now) and still return a sensible error. // (that we reacted to just now) and still return a sensible error.
} } else {
else {
return Ok(None); return Ok(None);
} }
} }
@ -616,12 +612,10 @@ impl<'de, 'a> SeqAccess<'de> for StructFields<'a, 'de> {
if let Some(lookahead) = self.de.next_name_lookahead() { if let Some(lookahead) = self.de.next_name_lookahead() {
if lookahead != self.fields[self.current_field] { if lookahead != self.fields[self.current_field] {
self.de.next_option_empty_hint = true; self.de.next_option_empty_hint = true;
} } else {
else {
self.de.next_option_empty_hint = false; self.de.next_option_empty_hint = false;
} }
} } else {
else {
self.de.next_option_empty_hint = false; self.de.next_option_empty_hint = false;
} }
@ -629,4 +623,3 @@ impl<'de, 'a> SeqAccess<'de> for StructFields<'a, 'de> {
seed.deserialize(&mut *self.de).map(Some) seed.deserialize(&mut *self.de).map(Some)
} }
} }

111
src/dsn/design.rs Normal file
View File

@ -0,0 +1,111 @@
use std::collections::HashMap;
use crate::{
layout::{dot::FixedDotWeight, seg::FixedSegWeight, Layout},
math::Circle,
};
use super::{
de::{from_str, Error},
structure::Pcb,
};
pub struct DsnDesign {
pcb: Pcb,
}
impl DsnDesign {
pub fn load_from_file(filename: &str) -> Result<Self, Error> {
let contents = std::fs::read_to_string(filename).unwrap(); // TODO: remove unwrap.
Ok(Self {
pcb: from_str::<Pcb>(&contents)?,
})
}
pub fn make_layout(&self) -> Layout<&Pcb> {
let mut layout = Layout::new(&self.pcb);
// this holds the mapping of net names to numerical IDs (here for now)
let net_ids: HashMap<String, usize> = HashMap::from_iter(
self.pcb.network.classes[0]
.nets
.iter()
.enumerate()
.map(|(id, net)| (net.clone(), id)),
);
// add vias to layout and save indices of dots in the order they appear in the file
let _dot_indices: Vec<_> = self
.pcb
.wiring
.vias
.iter()
.map(|via| {
let net_id = net_ids.get(&via.net.0).unwrap();
let component = layout.add_component(*net_id as i64);
// no way to resolve the name or layer support yet
// pick the first layer of the first object found
let circle = &self.pcb.library.padstacks[0].shapes[0].0;
let circle = Circle {
pos: (via.x as f64 / 100.0, -via.y as f64 / 100.0).into(),
r: circle.radius as f64 / 100.0,
};
layout
.add_fixed_dot(FixedDotWeight { component, circle })
.unwrap()
})
.collect();
for wire in self.pcb.wiring.wires.iter() {
let net_id = net_ids.get(&wire.net.0).unwrap();
let component = layout.add_component(*net_id as i64);
// add the first coordinate in the wire path as a dot and save its index
let mut prev_index = layout
.add_fixed_dot(FixedDotWeight {
component,
circle: Circle {
pos: (
wire.path.coords[0].x as f64 / 100.0,
-wire.path.coords[0].y as f64 / 100.0,
)
.into(),
r: wire.path.width as f64 / 100.0,
},
})
.unwrap();
// iterate through path coords starting from the second
for coord in wire.path.coords.iter().skip(1) {
let index = layout
.add_fixed_dot(FixedDotWeight {
component,
circle: Circle {
pos: (coord.x as f64 / 100.0, -coord.y as f64 / 100.0).into(),
r: wire.path.width as f64 / 100.0,
},
})
.unwrap();
// add a seg between the current and previous coords
let _ = layout
.add_fixed_seg(
prev_index,
index,
FixedSegWeight {
component,
width: wire.path.width as f64 / 100.0,
},
)
.unwrap();
prev_index = index;
}
}
layout
}
}

View File

@ -1,2 +1,4 @@
pub mod de; mod de;
pub mod structure; pub mod design;
mod rules;
mod structure;

15
src/dsn/rules.rs Normal file
View File

@ -0,0 +1,15 @@
use crate::layout::rules::{Conditions, RulesTrait};
use super::structure::Pcb;
impl<'a> RulesTrait for &'a Pcb {
fn clearance(&self, _conditions1: &Conditions, _conditions2: &Conditions) -> f64 {
// Placeholder for now.
10.0
}
fn clearance_net_limit(&self, _net: i64) -> f64 {
// Placeholder for now.
10.0
}
}

View File

@ -92,7 +92,7 @@ pub struct Placement;
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "library")] #[serde(rename = "library")]
pub struct Library { pub struct Library {
pub padstacks: Vec<Padstack> pub padstacks: Vec<Padstack>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
@ -192,7 +192,9 @@ impl From<FlatPath> for Path {
Path { Path {
layer: flat.layer, layer: flat.layer,
width: flat.width, width: flat.width,
coords: flat.coords.chunks(2) coords: flat
.coords
.chunks(2)
.map(|pair| Point { .map(|pair| Point {
x: pair[0], x: pair[0],
// it's possible to return an error instead of panicking if this From were TryFrom, // it's possible to return an error instead of panicking if this From were TryFrom,
@ -236,4 +238,3 @@ pub struct Clearance {
pub value: f32, pub value: f32,
pub r#type: Option<Type>, pub r#type: Option<Type>,
} }

View File

@ -2,9 +2,8 @@ use crate::wraparoundable::{GetWraparound, WraparoundableIndex};
use super::{ use super::{
bend::LooseBendIndex, bend::LooseBendIndex,
dot::DotIndex,
graph::GeometryIndex, graph::GeometryIndex,
primitive::{GetCore, GetInnerOuter, GetJoints}, primitive::{GetInnerOuter, GetJoints},
rules::RulesTrait, rules::RulesTrait,
Layout, Layout,
}; };

View File

@ -287,7 +287,7 @@ impl ShapeTrait for BendShape {
} }
} }
fn envelope(&self, margin: f64) -> AABB<[f64; 2]> { fn envelope(&self, _margin: f64) -> AABB<[f64; 2]> {
let halfwidth = self.c.r + self.width; let halfwidth = self.c.r + self.width;
AABB::from_corners( AABB::from_corners(
[self.c.pos.x() - halfwidth, self.c.pos.y() - halfwidth], [self.c.pos.x() - halfwidth, self.c.pos.y() - halfwidth],

View File

@ -122,7 +122,7 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
math::tangent_segment(from_circle, from_cw, to_circle, Some(cw)) math::tangent_segment(from_circle, from_cw, to_circle, Some(cw))
} }
pub fn head_around_dot_offset(&self, head: &Head, around: DotIndex, width: f64) -> f64 { pub fn head_around_dot_offset(&self, head: &Head, around: DotIndex, _width: f64) -> f64 {
self.layout.rules().clearance( self.layout.rules().clearance(
&self.conditions(around.into()), &self.conditions(around.into()),
&self.conditions(head.face().into()), &self.conditions(head.face().into()),
@ -158,7 +158,7 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
math::tangent_segment(from_circle, from_cw, to_circle, Some(cw)) math::tangent_segment(from_circle, from_cw, to_circle, Some(cw))
} }
pub fn head_around_bend_offset(&self, head: &Head, around: BendIndex, width: f64) -> f64 { pub fn head_around_bend_offset(&self, head: &Head, around: BendIndex, _width: f64) -> f64 {
self.layout.rules().clearance( self.layout.rules().clearance(
&self.conditions(head.face().into()), &self.conditions(head.face().into()),
&self.conditions(around.into()), &self.conditions(around.into()),

View File

@ -2,7 +2,6 @@ use contracts::debug_ensures;
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use geo::Point; use geo::Point;
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
use petgraph::visit::EdgeRef;
use rstar::RTreeObject; use rstar::RTreeObject;
use thiserror::Error; use thiserror::Error;
@ -26,15 +25,13 @@ use crate::layout::geometry::{
}; };
use crate::layout::guide::Guide; use crate::layout::guide::Guide;
use crate::layout::primitive::GetLimbs; use crate::layout::primitive::GetLimbs;
use crate::layout::rules::{Conditions, GetConditions}; use crate::layout::rules::GetConditions;
use crate::layout::{ use crate::layout::{
bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight}, bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight},
dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
geometry::shape::{Shape, ShapeTrait}, geometry::shape::{Shape, ShapeTrait},
graph::{GeometryIndex, GeometryWeight, GetComponentIndex, MakePrimitive}, graph::{GeometryIndex, GeometryWeight, GetComponentIndex, MakePrimitive},
primitive::{ primitive::{GenericPrimitive, GetCore, GetInnerOuter, GetJoints, GetOtherJoint, MakeShape},
GenericPrimitive, GetCore, GetInnerOuter, GetJoints, GetOtherJoint, GetWeight, MakeShape,
},
seg::{ seg::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
SeqLooseSegIndex, SeqLooseSegWeight, SeqLooseSegIndex, SeqLooseSegWeight,

View File

@ -15,8 +15,8 @@ use crate::layout::{
shape::{Shape, ShapeTrait}, shape::{Shape, ShapeTrait},
GetOffset, GetWidth, GetOffset, GetWidth,
}, },
graph::{GeometryIndex, GeometryWeight, GetBandIndex, GetComponentIndex, MakePrimitive, Retag}, graph::{GeometryIndex, GeometryWeight, GetBandIndex, GetComponentIndex, Retag},
loose::{Loose, LooseIndex}, loose::LooseIndex,
Layout, Layout,
}; };

View File

@ -5,10 +5,10 @@ pub mod draw;
pub mod graph; pub mod graph;
#[macro_use] #[macro_use]
pub mod layout; pub mod layout;
pub mod dsn;
pub mod math; pub mod math;
pub mod mesh; pub mod mesh;
pub mod router; pub mod router;
pub mod tracer; pub mod tracer;
pub mod triangulation; pub mod triangulation;
pub mod wraparoundable; pub mod wraparoundable;
pub mod dsn;

View File

@ -144,10 +144,8 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Mesh, f64>
} }
impl<R: RulesTrait> Router<R> { impl<R: RulesTrait> Router<R> {
pub fn new(rules: R) -> Self { pub fn new(layout: Layout<R>) -> Self {
Router { Router { layout }
layout: Layout::new(rules),
}
} }
pub fn route_band( pub fn route_band(

View File

@ -7,9 +7,7 @@ use crate::{
bend::{BendIndex, FixedBendIndex, LooseBendIndex}, bend::{BendIndex, FixedBendIndex, LooseBendIndex},
dot::FixedDotIndex, dot::FixedDotIndex,
graph::{GeometryIndex, MakePrimitive}, graph::{GeometryIndex, MakePrimitive},
primitive::{ primitive::{FixedBend, FixedDot, GetFirstRail, GetInnerOuter, LooseBend, Primitive},
FixedBend, FixedDot, GetFirstRail, GetInnerOuter, GetLayout, LooseBend, Primitive,
},
rules::RulesTrait, rules::RulesTrait,
Layout, Layout,
}, },