rules: implement `RulesTrait` for rules imported from DSN

This commit is contained in:
Tomasz Cichoń 2024-02-28 04:17:59 +01:00
parent bec701dbc9
commit b53dc62df3
5 changed files with 110 additions and 31 deletions

View File

@ -61,7 +61,7 @@ impl RulesTrait for SimpleRules {
.unwrap_or(&10.0) .unwrap_or(&10.0)
} }
fn clearance_net_limit(&self, net: i64) -> f64 { fn largest_clearance(&self, net: i64) -> f64 {
let mut highest_clearance = 0.0; let mut highest_clearance = 0.0;
for ((net1, net2), clearance) in self.net_clearances.iter() { for ((net1, net2), clearance) in self.net_clearances.iter() {

View File

@ -8,41 +8,38 @@ use crate::{
use super::{ use super::{
de::{from_str, Error}, de::{from_str, Error},
structure::Pcb, structure::Pcb,
rules::Rules,
}; };
#[derive(Debug)] #[derive(Debug)]
pub struct DsnDesign { pub struct DsnDesign {
pcb: Pcb, pcb: Pcb,
rules: Rules,
} }
impl DsnDesign { impl DsnDesign {
pub fn load_from_file(filename: &str) -> Result<Self, Error> { pub fn load_from_file(filename: &str) -> Result<Self, Error> {
let contents = std::fs::read_to_string(filename).unwrap(); // TODO: remove unwrap. let contents = std::fs::read_to_string(filename).unwrap(); // TODO: remove unwrap.
let pcb = from_str::<Pcb>(&contents)?;
let rules = Rules::from_pcb(&pcb);
Ok(Self { Ok(Self {
pcb: from_str::<Pcb>(&contents)?, pcb,
rules,
}) })
} }
pub fn make_layout(&self) -> Layout<&Pcb> { pub fn make_layout(&self) -> Layout<&Rules> {
let mut layout = Layout::new(&self.pcb); let mut layout = Layout::new(&self.rules);
// 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)),
);
// mapping of pin id -> net id prepared for adding pins // mapping of pin id -> net id prepared for adding pins
let pin_nets = if let Some(nets) = self.pcb.network.nets.as_ref() { let pin_nets = if let Some(nets) = self.pcb.network.nets.as_ref() {
HashMap::<String, usize>::from_iter( HashMap::<String, i64>::from_iter(
nets.iter() nets.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 = net_ids.get(&net.name).unwrap(); let net_id = self.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)
@ -52,7 +49,7 @@ impl DsnDesign {
.flatten(), .flatten(),
) )
} else { } else {
HashMap::<String, usize>::new() HashMap::<String, i64>::new()
}; };
// add pins from components // add pins from components
@ -70,7 +67,7 @@ impl DsnDesign {
for pin in &image.pins { for pin in &image.pins {
let pin_name = format!("{}-{}", place.name, pin.id); let pin_name = format!("{}-{}", place.name, pin.id);
let net_id = pin_nets.get(&pin_name).unwrap(); let net_id = pin_nets.get(&pin_name).unwrap();
let continent = layout.add_continent(*net_id as i64); let continent = layout.add_continent(*net_id);
let padstack = &self let padstack = &self
.pcb .pcb
@ -102,8 +99,8 @@ impl DsnDesign {
.vias .vias
.iter() .iter()
.map(|via| { .map(|via| {
let net_id = net_ids.get(&via.net.0).unwrap(); let net_id = self.rules.net_ids.get(&via.net.0).unwrap();
let continent = layout.add_continent(*net_id as i64); let continent = layout.add_continent(*net_id);
// find the padstack referenced by this via placement // find the padstack referenced by this via placement
let padstack = &self let padstack = &self
@ -128,8 +125,8 @@ impl DsnDesign {
.collect(); .collect();
for wire in self.pcb.wiring.wires.iter() { for wire in self.pcb.wiring.wires.iter() {
let net_id = net_ids.get(&wire.net.0).unwrap(); let net_id = self.rules.net_ids.get(&wire.net.0).unwrap();
let continent = layout.add_continent(*net_id as i64); let continent = layout.add_continent(*net_id);
// 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

View File

@ -1,15 +1,97 @@
use std::collections::HashMap;
use crate::layout::rules::{Conditions, RulesTrait}; use crate::layout::rules::{Conditions, RulesTrait};
use super::structure::Pcb; use super::structure::Pcb;
impl<'a> RulesTrait for &'a Pcb { #[derive(Debug)]
fn clearance(&self, _conditions1: &Conditions, _conditions2: &Conditions) -> f64 { pub struct Rule {
// Placeholder for now. pub width: f64,
10.0 pub clearance: f64,
} }
fn clearance_net_limit(&self, _net: i64) -> f64 { impl Rule {
// Placeholder for now. fn from_dsn(rule: &super::structure::Rule) -> Self {
10.0 Self {
width: rule.width.0 as f64 / 100.0,
clearance: rule.clearances[0].value as f64 / 100.0, // picks the generic clearance only for now
}
}
}
#[derive(Debug)]
pub struct Rules {
structure_rule: Rule,
// net class name -> rule
class_rules: HashMap<String, Rule>,
// net names -> net IDs for Layout
pub net_ids: HashMap<String, i64>,
// net ID -> net class
net_id_classes: HashMap<i64, String>,
}
impl Rules {
pub fn from_pcb(pcb: &Pcb) -> Self {
let net_ids = HashMap::from_iter(
pcb.network.classes[0]
.nets
.iter()
.enumerate()
.map(|(id, net)| (net.clone(), id as i64)),
);
let mut net_id_classes = HashMap::new();
let class_rules = HashMap::from_iter(
pcb.network.classes
.iter()
.inspect(|class| {
for net in &class.nets {
let net_id = net_ids.get(net).unwrap();
net_id_classes.insert(*net_id, class.name.clone());
}
})
.map(|class| (class.name.clone(), Rule::from_dsn(&class.rule)))
);
Self {
structure_rule: Rule::from_dsn(&pcb.structure.rule),
class_rules,
net_ids,
net_id_classes,
}
}
pub fn get_rule(&self, net: i64) -> &Rule {
if let Some(netclass) = self.net_id_classes.get(&net) {
self.class_rules.get(netclass).unwrap_or(&self.structure_rule)
} else {
&self.structure_rule
}
}
}
impl<'a> RulesTrait for &'a Rules {
fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64 {
let clr1 = self.get_rule(conditions1.net).clearance;
let clr2 = self.get_rule(conditions2.net).clearance;
if clr1 > clr2 {
clr1
} else {
clr2
}
}
fn largest_clearance(&self, _net: i64) -> f64 {
let mut largest: f64 = 0.0;
for (class, rule) in &self.class_rules {
if rule.clearance > largest {
largest = rule.clearance;
}
}
largest
} }
} }

View File

@ -796,7 +796,7 @@ impl<R: RulesTrait> Layout<R> {
let limiting_shape = node let limiting_shape = node
.primitive(self) .primitive(self)
.shape() .shape()
.inflate(self.rules.clearance_net_limit(node.primitive(self).net())); .inflate(self.rules.largest_clearance(node.primitive(self).net()));
let mut inflated_shape = limiting_shape; // Unused temporary value just for initialization. let mut inflated_shape = limiting_shape; // Unused temporary value just for initialization.
let conditions = node.primitive(self).conditions(); let conditions = node.primitive(self).conditions();

View File

@ -16,5 +16,5 @@ pub struct Conditions {
pub trait RulesTrait { pub trait RulesTrait {
fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64; fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64;
fn clearance_net_limit(&self, net: i64) -> f64; fn largest_clearance(&self, net: i64) -> f64;
} }