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)
|
||||
}
|
||||
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue