mirror of https://codeberg.org/topola/topola.git
board,dsn: move layer and net name bidirectional lookup to `Mesadata`
This commit is contained in:
parent
98363fbfd1
commit
7a02877eb4
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue