mirror of https://codeberg.org/topola/topola.git
autorouter: select nodes with pin-layer pairs, not only pins
We call these pairs "selectors".
The command file format has been thus changed. I've upgraded the command
files in tests with the following command:
jq ".done?.[].Autoroute |= {selectors: ([.pins.[] | {pin: ., layer: \"F.Cu\"}])}" $FILE | sponge $FILE
Where $FILE is the name of the upgraded command file.
This commit is contained in:
parent
bb6d975dac
commit
5eeeb5a004
|
|
@ -22,7 +22,7 @@ pub type NodeIndex = GenericNode<PrimitiveIndex, GenericIndex<ZoneWeight>>;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Board<R: RulesTrait> {
|
pub struct Board<R: RulesTrait> {
|
||||||
layout: Layout<R>,
|
layout: Layout<R>,
|
||||||
node_to_pin: HashMap<NodeIndex, String>,
|
node_to_pinname: HashMap<NodeIndex, String>,
|
||||||
layer_to_layername: HashMap<u64, String>,
|
layer_to_layername: HashMap<u64, String>,
|
||||||
net_to_netname: HashMap<usize, String>,
|
net_to_netname: HashMap<usize, String>,
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ impl<R: RulesTrait> Board<R> {
|
||||||
pub fn new(layout: Layout<R>) -> Self {
|
pub fn new(layout: Layout<R>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
layout,
|
layout,
|
||||||
node_to_pin: HashMap::new(),
|
node_to_pinname: HashMap::new(),
|
||||||
layer_to_layername: HashMap::new(),
|
layer_to_layername: HashMap::new(),
|
||||||
net_to_netname: HashMap::new(),
|
net_to_netname: HashMap::new(),
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +45,7 @@ impl<R: RulesTrait> Board<R> {
|
||||||
let dot = self.layout.add_fixed_dot(weight)?;
|
let dot = self.layout.add_fixed_dot(weight)?;
|
||||||
|
|
||||||
if let Some(ref pin) = maybe_pin {
|
if let Some(ref pin) = maybe_pin {
|
||||||
self.node_to_pin
|
self.node_to_pinname
|
||||||
.insert(GenericNode::Primitive(dot.into()), pin.clone());
|
.insert(GenericNode::Primitive(dot.into()), pin.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,8 +59,8 @@ impl<R: RulesTrait> Board<R> {
|
||||||
) -> Result<FixedDotIndex, Infringement> {
|
) -> Result<FixedDotIndex, Infringement> {
|
||||||
let dot = self.layout.add_zone_fixed_dot(weight, zone)?;
|
let dot = self.layout.add_zone_fixed_dot(weight, zone)?;
|
||||||
|
|
||||||
if let Some(pin) = self.node_pin(GenericNode::Compound(zone)) {
|
if let Some(pin) = self.node_pinname(GenericNode::Compound(zone)) {
|
||||||
self.node_to_pin
|
self.node_to_pinname
|
||||||
.insert(GenericNode::Primitive(dot.into()), pin.to_string());
|
.insert(GenericNode::Primitive(dot.into()), pin.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ impl<R: RulesTrait> Board<R> {
|
||||||
let seg = self.layout.add_fixed_seg(from, to, weight)?;
|
let seg = self.layout.add_fixed_seg(from, to, weight)?;
|
||||||
|
|
||||||
if let Some(pin) = maybe_pin {
|
if let Some(pin) = maybe_pin {
|
||||||
self.node_to_pin
|
self.node_to_pinname
|
||||||
.insert(GenericNode::Primitive(seg.into()), pin.to_string());
|
.insert(GenericNode::Primitive(seg.into()), pin.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,8 +93,8 @@ impl<R: RulesTrait> Board<R> {
|
||||||
) -> Result<FixedSegIndex, Infringement> {
|
) -> Result<FixedSegIndex, Infringement> {
|
||||||
let seg = self.layout.add_zone_fixed_seg(from, to, weight, zone)?;
|
let seg = self.layout.add_zone_fixed_seg(from, to, weight, zone)?;
|
||||||
|
|
||||||
if let Some(pin) = self.node_pin(GenericNode::Compound(zone)) {
|
if let Some(pin) = self.node_pinname(GenericNode::Compound(zone)) {
|
||||||
self.node_to_pin
|
self.node_to_pinname
|
||||||
.insert(GenericNode::Primitive(seg.into()), pin.to_string());
|
.insert(GenericNode::Primitive(seg.into()), pin.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ impl<R: RulesTrait> Board<R> {
|
||||||
let zone = self.layout.add_zone(weight);
|
let zone = self.layout.add_zone(weight);
|
||||||
|
|
||||||
if let Some(pin) = maybe_pin {
|
if let Some(pin) = maybe_pin {
|
||||||
self.node_to_pin
|
self.node_to_pinname
|
||||||
.insert(GenericNode::Compound(zone.into()), pin.to_string());
|
.insert(GenericNode::Compound(zone.into()), pin.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,8 +143,12 @@ impl<R: RulesTrait> Board<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_pin(&self, node: NodeIndex) -> Option<&String> {
|
pub fn node_pinname(&self, node: NodeIndex) -> Option<&String> {
|
||||||
self.node_to_pin.get(&node)
|
self.node_to_pinname.get(&node)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn layername(&self, layer: u64) -> Option<&String> {
|
||||||
|
self.layer_to_layername.get(&layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn netname(&self, net: usize) -> Option<&String> {
|
pub fn netname(&self, net: usize) -> Option<&String> {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ pub enum HistoryError {
|
||||||
NoNextCommand,
|
NoNextCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct History {
|
pub struct History {
|
||||||
done: Vec<Command>,
|
done: Vec<Command>,
|
||||||
undone: Vec<Command>,
|
undone: Vec<Command>,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use core::fmt;
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -26,7 +25,7 @@ pub enum InvokerStatus {
|
||||||
Finished,
|
Finished,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Autoroute(Selection),
|
Autoroute(Selection),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,78 @@
|
||||||
use core::fmt;
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
autorouter::board::{Board, NodeIndex},
|
autorouter::board::{Board, NodeIndex},
|
||||||
drawing::{graph::PrimitiveIndex, rules::RulesTrait},
|
drawing::{
|
||||||
|
graph::{GetLayer, MakePrimitive, PrimitiveIndex},
|
||||||
|
rules::RulesTrait,
|
||||||
|
},
|
||||||
graph::GenericIndex,
|
graph::GenericIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Selector {
|
||||||
|
pin: String,
|
||||||
|
layer: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Selection {
|
pub struct Selection {
|
||||||
pins: HashSet<String>,
|
selectors: HashSet<Selector>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Selection {
|
impl Selection {
|
||||||
pub fn new() -> Selection {
|
pub fn new() -> Selection {
|
||||||
Self {
|
Self {
|
||||||
pins: HashSet::new(),
|
selectors: HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_at_node(&mut self, board: &Board<impl RulesTrait>, node: NodeIndex) {
|
pub fn toggle_at_node(&mut self, board: &Board<impl RulesTrait>, node: NodeIndex) {
|
||||||
let maybe_pin = board.node_pin(node);
|
let Some(selector) = self.node_selector(board, node) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(ref pin) = maybe_pin {
|
if self.contains_node(board, node) {
|
||||||
if self.contains_node(board, node) {
|
self.deselect(board, &selector);
|
||||||
self.remove_pin(board, pin);
|
} else {
|
||||||
} else {
|
self.select(board, selector);
|
||||||
self.add_pin(board, pin);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_pin(&mut self, board: &Board<impl RulesTrait>, pin: &String) {
|
fn select(&mut self, board: &Board<impl RulesTrait>, selector: Selector) {
|
||||||
self.pins.insert(pin.clone());
|
self.selectors.insert(selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_pin(&mut self, board: &Board<impl RulesTrait>, pin: &String) {
|
fn deselect(&mut self, board: &Board<impl RulesTrait>, selector: &Selector) {
|
||||||
self.pins.remove(pin);
|
self.selectors.remove(selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_node(&self, board: &Board<impl RulesTrait>, node: NodeIndex) -> bool {
|
pub fn contains_node(&self, board: &Board<impl RulesTrait>, node: NodeIndex) -> bool {
|
||||||
if let Some(pin) = board.node_pin(node) {
|
let Some(selector) = self.node_selector(board, node) else {
|
||||||
self.pins.contains(pin)
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.selectors.contains(&selector)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_selector(&self, board: &Board<impl RulesTrait>, node: NodeIndex) -> Option<Selector> {
|
||||||
|
let layer = match node {
|
||||||
|
NodeIndex::Primitive(primitive) => {
|
||||||
|
primitive.primitive(board.layout().drawing()).layer()
|
||||||
|
}
|
||||||
|
NodeIndex::Compound(compound) => board.layout().zone(compound).layer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let (Some(pinname), Some(layername)) = (board.node_pinname(node), board.layername(layer))
|
||||||
|
{
|
||||||
|
Some(Selector {
|
||||||
|
pin: pinname.to_string(),
|
||||||
|
layer: layername.to_string(),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
false
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::drawing::rules::{Conditions, RulesTrait};
|
use crate::{
|
||||||
|
drawing::rules::{Conditions, RulesTrait},
|
||||||
use super::structure::Pcb;
|
dsn::structure::Pcb,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DsnRule {
|
pub struct DsnRule {
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,29 @@
|
||||||
"done": [
|
"done": [
|
||||||
{
|
{
|
||||||
"Autoroute": {
|
"Autoroute": {
|
||||||
"pins": [
|
"selectors": [
|
||||||
"R1-2",
|
{
|
||||||
"J1-2"
|
"pin": "R1-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "J1-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Autoroute": {
|
"Autoroute": {
|
||||||
"pins": [
|
"selectors": [
|
||||||
"J1-1",
|
{
|
||||||
"R1-1"
|
"pin": "J1-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "R1-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,69 +2,201 @@
|
||||||
"done": [
|
"done": [
|
||||||
{
|
{
|
||||||
"Autoroute": {
|
"Autoroute": {
|
||||||
"pins": [
|
"selectors": [
|
||||||
"L3-1",
|
{
|
||||||
"L3-2",
|
"pin": "L3-1",
|
||||||
"C3-1",
|
"layer": "F.Cu"
|
||||||
"L1-2",
|
},
|
||||||
"C2-1",
|
{
|
||||||
"L2-2",
|
"pin": "L3-2",
|
||||||
"J2-1",
|
"layer": "F.Cu"
|
||||||
"J1-1",
|
},
|
||||||
"L1-1",
|
{
|
||||||
"C1-1",
|
"pin": "C3-1",
|
||||||
"L2-1"
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L1-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "C2-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L2-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "J2-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "J1-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L1-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "C1-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L2-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Autoroute": {
|
"Autoroute": {
|
||||||
"pins": [
|
"selectors": [
|
||||||
"C6-1",
|
{
|
||||||
"J4-1",
|
"pin": "C6-1",
|
||||||
"L5-1",
|
"layer": "F.Cu"
|
||||||
"J3-1",
|
},
|
||||||
"C5-1",
|
{
|
||||||
"L6-2",
|
"pin": "J4-1",
|
||||||
"L5-2",
|
"layer": "F.Cu"
|
||||||
"C4-1",
|
},
|
||||||
"L6-1",
|
{
|
||||||
"L4-1",
|
"pin": "L5-1",
|
||||||
"L4-2"
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "J3-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "C5-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L6-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L5-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "C4-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L6-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L4-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L4-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Autoroute": {
|
"Autoroute": {
|
||||||
"pins": [
|
"selectors": [
|
||||||
"C9-1",
|
{
|
||||||
"J5-1",
|
"pin": "C9-1",
|
||||||
"L7-1",
|
"layer": "F.Cu"
|
||||||
"J6-1",
|
},
|
||||||
"L9-2",
|
{
|
||||||
"C7-1",
|
"pin": "J5-1",
|
||||||
"L8-2",
|
"layer": "F.Cu"
|
||||||
"L9-1",
|
},
|
||||||
"L8-1",
|
{
|
||||||
"L7-2",
|
"pin": "L7-1",
|
||||||
"C8-1"
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "J6-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L9-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "C7-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L8-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L9-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L8-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L7-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "C8-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Autoroute": {
|
"Autoroute": {
|
||||||
"pins": [
|
"selectors": [
|
||||||
"L10-1",
|
{
|
||||||
"L12-1",
|
"pin": "L10-1",
|
||||||
"J7-1",
|
"layer": "F.Cu"
|
||||||
"L10-2",
|
},
|
||||||
"C10-1",
|
{
|
||||||
"C12-1",
|
"pin": "L12-1",
|
||||||
"L12-2",
|
"layer": "F.Cu"
|
||||||
"L11-1",
|
},
|
||||||
"C11-1",
|
{
|
||||||
"L11-2",
|
"pin": "J7-1",
|
||||||
"J8-1"
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L10-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "C10-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "C12-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L12-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L11-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "C11-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "L11-2",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pin": "J8-1",
|
||||||
|
"layer": "F.Cu"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue