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)
}
fn clearance_net_limit(&self, net: i64) -> f64 {
fn largest_clearance(&self, net: i64) -> f64 {
let mut highest_clearance = 0.0;
for ((net1, net2), clearance) in self.net_clearances.iter() {

View File

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

View File

@ -1,15 +1,97 @@
use std::collections::HashMap;
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
#[derive(Debug)]
pub struct Rule {
pub width: f64,
pub clearance: f64,
}
fn clearance_net_limit(&self, _net: i64) -> f64 {
// Placeholder for now.
10.0
impl Rule {
fn from_dsn(rule: &super::structure::Rule) -> Self {
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
.primitive(self)
.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 conditions = node.primitive(self).conditions();

View File

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