board,dsn: move layer and net name bidirectional lookup to `Mesadata`

This commit is contained in:
Mikolaj Wielgus 2024-06-08 21:37:19 +02:00
parent 98363fbfd1
commit 7a02877eb4
10 changed files with 115 additions and 82 deletions

View File

@ -31,6 +31,7 @@ serde_json = "1.0.117"
enum_dispatch = "0.3.12"
itertools = "0.8.2"
contracts = "0.6.3"
bimap = "0.6.3"
log = "0.4"
[dependencies.serde]

View File

@ -67,8 +67,10 @@ impl Selection {
NodeIndex::Compound(compound) => board.layout().zone(compound).layer(),
};
if let (Some(pinname), Some(layername)) = (board.node_pinname(node), board.layername(layer))
{
if let (Some(pinname), Some(layername)) = (
board.node_pinname(node),
board.layout().rules().layer_layername(layer),
) {
Some(Selector {
pin: pinname.to_string(),
layer: layername.to_string(),

View File

@ -6,11 +6,10 @@ use spade::InsertionError;
use topola::{
autorouter::{ratsnest::Ratsnest, selection::Selection},
board::Board,
board::{mesadata::MesadataTrait, Board},
drawing::{
graph::{GetLayer, MakePrimitive},
primitive::MakePrimitiveShape,
rules::RulesTrait,
},
geometry::{
compound::CompoundManagerTrait,
@ -26,7 +25,7 @@ pub struct Overlay {
}
impl Overlay {
pub fn new(board: &Board<impl RulesTrait>) -> Result<Self, InsertionError> {
pub fn new(board: &Board<impl MesadataTrait>) -> Result<Self, InsertionError> {
Ok(Self {
ratsnest: Ratsnest::new(board.layout())?,
selection: Selection::new(),
@ -34,7 +33,7 @@ impl Overlay {
})
}
pub fn click(&mut self, board: &Board<impl RulesTrait>, at: Point) {
pub fn click(&mut self, board: &Board<impl MesadataTrait>, at: Point) {
let geoms: Vec<_> = board
.layout()
.drawing()
@ -65,7 +64,7 @@ impl Overlay {
fn toggle_selection_if_contains_point(
&mut self,
board: &Board<impl RulesTrait>,
board: &Board<impl MesadataTrait>,
node: NodeIndex,
p: Point,
) -> bool {

View File

@ -24,8 +24,6 @@ use crate::{
pub struct Board<M: MesadataTrait> {
layout: Layout<M>,
node_to_pinname: HashMap<NodeIndex, String>,
layer_to_layername: HashMap<u64, String>,
net_to_netname: HashMap<usize, String>,
pinname_pair_to_band: HashMap<(String, String), BandIndex>,
}
@ -34,8 +32,6 @@ impl<M: MesadataTrait> Board<M> {
Self {
layout,
node_to_pinname: HashMap::new(),
layer_to_layername: HashMap::new(),
net_to_netname: HashMap::new(),
pinname_pair_to_band: HashMap::new(),
}
}
@ -145,14 +141,6 @@ impl<M: MesadataTrait> Board<M> {
result
}
pub fn bename_layer(&mut self, layer: u64, layername: String) {
self.layer_to_layername.insert(layer, layername);
}
pub fn bename_net(&mut self, net: usize, netname: String) {
self.net_to_netname.insert(net, netname);
}
pub fn zone_apex(&mut self, zone: GenericIndex<ZoneWeight>) -> FixedDotIndex {
if let Some(apex) = self.layout.zone(zone).maybe_apex() {
apex
@ -176,14 +164,6 @@ impl<M: MesadataTrait> Board<M> {
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> {
self.net_to_netname.get(&net)
}
pub fn band_between_pins(&self, pinname1: &str, pinname2: &str) -> Option<BandIndex> {
if let Some(band) = self
.pinname_pair_to_band

View File

@ -2,9 +2,11 @@ use crate::{drawing::rules::RulesTrait, layout::NodeIndex};
// TODO: use this trait.
pub trait MesadataTrait: RulesTrait {
/*fn node_pinname(&self, node: NodeIndex);
fn layer_layername(&self, layer: u64) -> &str;
fn layername_layer(&self, layername: &str) -> u64;
fn net_netname(&self, net: usize) -> &str;
fn netname_net(&self, netname: &str) -> usize;*/
fn bename_layer(&mut self, layer: u64, layername: String);
fn layer_layername(&self, layer: u64) -> Option<&str>;
fn layername_layer(&self, layername: &str) -> Option<u64>;
fn bename_net(&mut self, net: usize, netname: String);
fn net_netname(&self, net: usize) -> Option<&str>;
fn netname_net(&self, netname: &str) -> Option<usize>;
}

View File

@ -836,6 +836,12 @@ impl<CW: Copy, R: RulesTrait> Drawing<CW, R> {
&self.rules
}
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn rules_mut(&mut self) -> &mut R {
&mut self.rules
}
pub fn guide(&self) -> Guide<CW, R> {
Guide::new(self)
}

View File

@ -4,7 +4,7 @@ use geo::{point, Point, Rotate, Translate};
use thiserror::Error;
use crate::{
board::Board,
board::{mesadata::MesadataTrait, Board},
drawing::{dot::FixedDotWeight, seg::FixedSegWeight, Drawing},
dsn::{
de,
@ -60,8 +60,7 @@ impl DsnDesign {
.layout()
.drawing()
.rules()
.netname_to_net
.get(&net_pin_assignments.name)
.netname_net(&net_pin_assignments.name)
.unwrap();
// take the list of pins
@ -70,7 +69,7 @@ impl DsnDesign {
.pins
.names
.iter()
.map(|id| (id.clone(), *net))
.map(move |pinname| (pinname.clone(), net))
})
// flatten the nested iters into a single stream of tuples
.flatten(),
@ -88,8 +87,8 @@ impl DsnDesign {
.unwrap();
for pin in &image.pin_vec {
let pin_name = format!("{}-{}", place.name, pin.id);
let net = pin_nets.get(&pin_name).unwrap();
let pinname = format!("{}-{}", place.name, pin.id);
let net = pin_nets.get(&pinname).unwrap();
let padstack = &self
.pcb
@ -117,7 +116,7 @@ impl DsnDesign {
circle.diameter as f64 / 2.0,
layer as u64,
*net,
Some(pin_name.clone()),
Some(pinname.clone()),
)
}
Shape::Rect(rect) => {
@ -139,7 +138,7 @@ impl DsnDesign {
rect.y2 as f64,
layer as u64,
*net,
Some(pin_name.clone()),
Some(pinname.clone()),
)
}
Shape::Path(path) => {
@ -159,7 +158,7 @@ impl DsnDesign {
path.width as f64,
layer as u64,
*net,
Some(pin_name.clone()),
Some(pinname.clone()),
)
}
Shape::Polygon(polygon) => {
@ -179,7 +178,7 @@ impl DsnDesign {
polygon.width as f64,
layer as u64,
*net,
Some(pin_name.clone()),
Some(pinname.clone()),
)
}
};
@ -189,12 +188,11 @@ impl DsnDesign {
}
for via in &self.pcb.wiring.via_vec {
let net = *board
let net = board
.layout()
.drawing()
.rules()
.netname_to_net
.get(&via.net)
.netname_net(&via.net)
.unwrap();
// find the padstack referenced by this via placement
@ -294,19 +292,17 @@ impl DsnDesign {
}
for wire in self.pcb.wiring.wire_vec.iter() {
let layer = *board
let layer = board
.layout()
.drawing()
.rules()
.layername_to_layer
.get(&wire.path.layer)
.layername_layer(&wire.path.layer)
.unwrap();
let net = *board
let net = board
.layout()
.drawing()
.rules()
.netname_to_net
.get(&wire.net)
.netname_net(&wire.net)
.unwrap();
Self::add_path(
@ -325,16 +321,22 @@ impl DsnDesign {
// The clones here are bad, we'll have something better later on.
let layername_to_layer = &board.layout().drawing().rules().layername_to_layer.clone();
let layername_to_layer = &board.layout().drawing().rules().layer_layername.clone();
for (layername, layer) in layername_to_layer.iter() {
board.bename_layer(*layer, layername.to_string());
for (layer, layername) in layername_to_layer.iter() {
board
.layout_mut()
.rules_mut()
.bename_layer(*layer, layername.to_string());
}
let netname_to_net = &board.layout().drawing().rules().netname_to_net.clone();
let netname_to_net = &board.layout().drawing().rules().net_netname.clone();
for (netname, net) in netname_to_net.iter() {
board.bename_net(*net, netname.to_string());
for (net, netname) in netname_to_net.iter() {
board
.layout_mut()
.rules_mut()
.bename_net(*net, netname.to_string());
}
board
@ -343,15 +345,14 @@ impl DsnDesign {
fn layer(
board: &Board<DsnMesadata>,
layer_vec: &Vec<Layer>,
layer_name: &str,
layername: &str,
front: bool,
) -> usize {
let image_layer = *board
let image_layer = board
.layout()
.drawing()
.rules()
.layername_to_layer
.get(layer_name)
.layername_layer(layername)
.unwrap();
if front {

View File

@ -1,5 +1,7 @@
use std::collections::HashMap;
use bimap::BiHashMap;
use crate::{
board::mesadata::MesadataTrait,
drawing::rules::{Conditions, RulesTrait},
@ -27,42 +29,44 @@ pub struct DsnMesadata {
// net class name -> rule
class_rules: HashMap<String, DsnRule>,
// layernames -> layers for Layout
pub layername_to_layer: HashMap<String, u64>,
// netnames -> nets for Layout
pub netname_to_net: HashMap<String, usize>,
// layername <-> layer for Layout
pub layer_layername: BiHashMap<u64, String>,
// netname <-> net for Layout
pub net_netname: BiHashMap<usize, String>,
// net -> netclass
net_to_netclass: HashMap<usize, String>,
net_netclass: HashMap<usize, String>,
}
impl DsnMesadata {
pub fn from_pcb(pcb: &Pcb) -> Self {
let layer_ids = HashMap::from_iter(
let layer_layername = BiHashMap::from_iter(
pcb.structure
.layer_vec
.iter()
.map(|layer| (layer.name.clone(), layer.property.index as u64)),
.map(|layer| (layer.property.index as u64, layer.name.clone())),
);
// keeping this as a separate iter pass because it might be moved into a different struct later?
let netname_to_net = HashMap::from_iter(
let net_netname = BiHashMap::from_iter(
pcb.network
.class_vec
.iter()
.flat_map(|class| &class.net_vec)
.enumerate()
.map(|(id, net)| (net.clone(), id)),
.map(|(net, netname)| (net, netname.clone())),
);
let mut net_id_classes = HashMap::new();
let mut net_netclass = HashMap::new();
let class_rules = HashMap::from_iter(
pcb.network
.class_vec
.iter()
.inspect(|class| {
for net in &class.net_vec {
let net_id = netname_to_net.get(net).unwrap();
net_id_classes.insert(*net_id, class.name.clone());
for netname in &class.net_vec {
let net = net_netname.get_by_right(netname).unwrap();
net_netclass.insert(*net, class.name.clone());
}
})
.map(|class| (class.name.clone(), DsnRule::from_dsn(&class.rule))),
@ -71,14 +75,14 @@ impl DsnMesadata {
Self {
structure_rule: DsnRule::from_dsn(&pcb.structure.rule),
class_rules,
layername_to_layer: layer_ids,
netname_to_net,
net_to_netclass: net_id_classes,
layer_layername,
net_netname,
net_netclass,
}
}
pub fn get_rule(&self, net: usize) -> &DsnRule {
if let Some(netclass) = self.net_to_netclass.get(&net) {
if let Some(netclass) = self.net_netclass.get(&net) {
self.class_rules
.get(netclass)
.unwrap_or(&self.structure_rule)
@ -118,5 +122,27 @@ impl RulesTrait for DsnMesadata {
}
impl MesadataTrait for DsnMesadata {
//
fn bename_layer(&mut self, layer: u64, layername: String) {
self.layer_layername.insert(layer, layername);
}
fn layer_layername(&self, layer: u64) -> Option<&str> {
self.layer_layername.get_by_left(&layer).map(|s| s.as_str())
}
fn layername_layer(&self, layername: &str) -> Option<u64> {
self.layer_layername.get_by_right(layername).copied()
}
fn bename_net(&mut self, net: usize, netname: String) {
self.net_netname.insert(net, netname);
}
fn net_netname(&self, net: usize) -> Option<&str> {
self.net_netname.get_by_left(&net).map(|s| s.as_str())
}
fn netname_net(&self, netname: &str) -> Option<usize> {
self.net_netname.get_by_right(netname).copied()
}
}

View File

@ -211,6 +211,14 @@ impl<R: RulesTrait> Layout<R> {
&self.drawing
}
pub fn rules(&self) -> &R {
self.drawing.rules()
}
pub fn rules_mut(&mut self) -> &mut R {
self.drawing.rules_mut()
}
pub fn zone(&self, index: GenericIndex<ZoneWeight>) -> Zone<R> {
Zone::new(index, self)
}

View File

@ -78,8 +78,16 @@ pub fn assert_single_layer_groundless_autoroute(
.layer();
if let (Some(source_layername), Some(target_layername)) = (
autorouter.board().layername(source_layer),
autorouter.board().layername(target_layer),
autorouter
.board()
.layout()
.rules()
.layer_layername(source_layer),
autorouter
.board()
.layout()
.rules()
.layer_layername(target_layer),
) {
dbg!(source_layername, target_layername);
assert_eq!(source_layername, target_layername);
@ -108,7 +116,7 @@ pub fn assert_single_layer_groundless_autoroute(
let net = source_net.unwrap();
if let Some(netname) = autorouter.board().netname(net) {
if let Some(netname) = autorouter.board().layout().rules().net_netname(net) {
// We don't route ground.
if netname != "GND" {
dbg!(source_dot, target_dot);