mirror of https://codeberg.org/topola/topola.git
rules: implement `RulesTrait` for rules imported from DSN
This commit is contained in:
parent
bec701dbc9
commit
b53dc62df3
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue