board,dsn: introduce `MesadataTrait`, an extension of `RulesTrait`

The trait's contents aren't implemented yet.

"mesa" is supposed to mean the opposite of "meta". By "mesadata" I don't
mean mere content or payload: I mean data that is stored *inside* or
*under* such content or payload.

I found this meaning of "mesa" -- as opposite of "meta" -- by browsing
somewhere on the internet. Fair chance many classicists would think
poorly of this usage. But I don't care about etymology: I just need a
word to close a lexical gap.
This commit is contained in:
Mikolaj Wielgus 2024-06-08 16:09:23 +02:00
parent 1dc3718159
commit 19a4766cb5
12 changed files with 82 additions and 68 deletions

View File

@ -17,11 +17,10 @@ use crate::{
ratsnest::{Ratsnest, RatvertexIndex}, ratsnest::{Ratsnest, RatvertexIndex},
selection::Selection, selection::Selection,
}, },
board::Board, board::{mesadata::MesadataTrait, Board},
drawing::{ drawing::{
dot::FixedDotIndex, dot::FixedDotIndex,
graph::{GetLayer, GetMaybeNet}, graph::{GetLayer, GetMaybeNet},
rules::RulesTrait,
}, },
layout::Layout, layout::Layout,
router::{ router::{
@ -55,7 +54,7 @@ pub struct Autoroute {
impl Autoroute { impl Autoroute {
pub fn new( pub fn new(
ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static, ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
autorouter: &mut Autorouter<impl RulesTrait>, autorouter: &mut Autorouter<impl MesadataTrait>,
) -> Result<Self, AutorouterError> { ) -> Result<Self, AutorouterError> {
let mut ratlines_iter = Box::new(ratlines.into_iter()); let mut ratlines_iter = Box::new(ratlines.into_iter());
@ -75,10 +74,10 @@ impl Autoroute {
Ok(this) Ok(this)
} }
pub fn step<R: RulesTrait>( pub fn step<M: MesadataTrait>(
&mut self, &mut self,
autorouter: &mut Autorouter<R>, autorouter: &mut Autorouter<M>,
observer: &mut impl RouterObserverTrait<R>, observer: &mut impl RouterObserverTrait<M>,
) -> Result<AutorouterStatus, AutorouterError> { ) -> Result<AutorouterStatus, AutorouterError> {
let (new_navmesh, new_ratline) = if let Some(cur_ratline) = self.ratlines_iter.next() { let (new_navmesh, new_ratline) = if let Some(cur_ratline) = self.ratlines_iter.next() {
let (source, target) = autorouter.ratline_endpoints(cur_ratline); let (source, target) = autorouter.ratline_endpoints(cur_ratline);
@ -121,13 +120,13 @@ impl Autoroute {
} }
} }
pub struct Autorouter<R: RulesTrait> { pub struct Autorouter<M: MesadataTrait> {
board: Board<R>, board: Board<M>,
ratsnest: Ratsnest, ratsnest: Ratsnest,
} }
impl<R: RulesTrait> Autorouter<R> { impl<M: MesadataTrait> Autorouter<M> {
pub fn new(board: Board<R>) -> Result<Self, InsertionError> { pub fn new(board: Board<M>) -> Result<Self, InsertionError> {
let ratsnest = Ratsnest::new(board.layout())?; let ratsnest = Ratsnest::new(board.layout())?;
Ok(Self { board, ratsnest }) Ok(Self { board, ratsnest })
} }
@ -135,7 +134,7 @@ impl<R: RulesTrait> Autorouter<R> {
pub fn autoroute( pub fn autoroute(
&mut self, &mut self,
selection: &Selection, selection: &Selection,
observer: &mut impl RouterObserverTrait<R>, observer: &mut impl RouterObserverTrait<M>,
) -> Result<(), AutorouterError> { ) -> Result<(), AutorouterError> {
let mut autoroute = self.autoroute_walk(selection)?; let mut autoroute = self.autoroute_walk(selection)?;
@ -225,7 +224,7 @@ impl<R: RulesTrait> Autorouter<R> {
.collect() .collect()
} }
pub fn board(&self) -> &Board<R> { pub fn board(&self) -> &Board<M> {
&self.board &self.board
} }

View File

@ -7,7 +7,7 @@ use crate::{
selection::Selection, selection::Selection,
Autoroute, Autorouter, AutorouterError, AutorouterStatus, Autoroute, Autorouter, AutorouterError, AutorouterStatus,
}, },
drawing::rules::RulesTrait, board::mesadata::MesadataTrait,
layout::Layout, layout::Layout,
router::{EmptyRouterObserver, RouterObserverTrait}, router::{EmptyRouterObserver, RouterObserverTrait},
}; };
@ -35,10 +35,10 @@ pub enum Execute {
} }
impl Execute { impl Execute {
pub fn step<R: RulesTrait>( pub fn step<M: MesadataTrait>(
&mut self, &mut self,
invoker: &mut Invoker<R>, invoker: &mut Invoker<M>,
observer: &mut impl RouterObserverTrait<R>, observer: &mut impl RouterObserverTrait<M>,
) -> Result<InvokerStatus, InvokerError> { ) -> Result<InvokerStatus, InvokerError> {
match self { match self {
Execute::Autoroute(autoroute) => { Execute::Autoroute(autoroute) => {
@ -51,31 +51,31 @@ impl Execute {
} }
} }
pub struct Invoker<R: RulesTrait> { pub struct Invoker<M: MesadataTrait> {
autorouter: Autorouter<R>, autorouter: Autorouter<M>,
history: History, history: History,
} }
impl<R: RulesTrait> Invoker<R> { impl<M: MesadataTrait> Invoker<M> {
pub fn new(autorouter: Autorouter<R>) -> Self { pub fn new(autorouter: Autorouter<M>) -> Self {
Self::new_with_history(autorouter, History::new()) Self::new_with_history(autorouter, History::new())
} }
pub fn new_with_history(autorouter: Autorouter<R>, history: History) -> Self { pub fn new_with_history(autorouter: Autorouter<M>, history: History) -> Self {
Self { Self {
autorouter, autorouter,
history, history,
} }
} }
pub fn destruct(self) -> (Autorouter<R>, History) { pub fn destruct(self) -> (Autorouter<M>, History) {
(self.autorouter, self.history) (self.autorouter, self.history)
} }
pub fn execute( pub fn execute(
&mut self, &mut self,
command: Command, command: Command,
observer: &mut impl RouterObserverTrait<R>, observer: &mut impl RouterObserverTrait<M>,
) -> Result<(), InvokerError> { ) -> Result<(), InvokerError> {
let mut execute = self.execute_walk(command); let mut execute = self.execute_walk(command);
@ -142,7 +142,7 @@ impl<R: RulesTrait> Invoker<R> {
self.history.set_undone(undone.into_iter()); self.history.set_undone(undone.into_iter());
} }
pub fn autorouter(&self) -> &Autorouter<R> { pub fn autorouter(&self) -> &Autorouter<M> {
&self.autorouter &self.autorouter
} }

View File

@ -3,11 +3,8 @@ use std::collections::HashSet;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
board::Board, board::{mesadata::MesadataTrait, Board},
drawing::{ drawing::graph::{GetLayer, MakePrimitive, PrimitiveIndex},
graph::{GetLayer, MakePrimitive, PrimitiveIndex},
rules::RulesTrait,
},
graph::GenericIndex, graph::GenericIndex,
layout::NodeIndex, layout::NodeIndex,
}; };
@ -30,7 +27,7 @@ impl Selection {
} }
} }
pub fn toggle_at_node(&mut self, board: &Board<impl RulesTrait>, node: NodeIndex) { pub fn toggle_at_node(&mut self, board: &Board<impl MesadataTrait>, node: NodeIndex) {
let Some(selector) = self.node_selector(board, node) else { let Some(selector) = self.node_selector(board, node) else {
return; return;
}; };
@ -42,15 +39,15 @@ impl Selection {
} }
} }
fn select(&mut self, board: &Board<impl RulesTrait>, selector: Selector) { fn select(&mut self, board: &Board<impl MesadataTrait>, selector: Selector) {
self.selectors.insert(selector); self.selectors.insert(selector);
} }
fn deselect(&mut self, board: &Board<impl RulesTrait>, selector: &Selector) { fn deselect(&mut self, board: &Board<impl MesadataTrait>, selector: &Selector) {
self.selectors.remove(selector); self.selectors.remove(selector);
} }
pub fn contains_node(&self, board: &Board<impl RulesTrait>, node: NodeIndex) -> bool { pub fn contains_node(&self, board: &Board<impl MesadataTrait>, node: NodeIndex) -> bool {
let Some(selector) = self.node_selector(board, node) else { let Some(selector) = self.node_selector(board, node) else {
return false; return false;
}; };
@ -58,7 +55,11 @@ impl Selection {
self.selectors.contains(&selector) self.selectors.contains(&selector)
} }
fn node_selector(&self, board: &Board<impl RulesTrait>, node: NodeIndex) -> Option<Selector> { fn node_selector(
&self,
board: &Board<impl MesadataTrait>,
node: NodeIndex,
) -> Option<Selector> {
let layer = match node { let layer = match node {
NodeIndex::Primitive(primitive) => { NodeIndex::Primitive(primitive) => {
primitive.primitive(board.layout().drawing()).layer() primitive.primitive(board.layout().drawing()).layer()

View File

@ -22,7 +22,7 @@ use topola::{
rules::RulesTrait, rules::RulesTrait,
Drawing, Infringement, LayoutException, Drawing, Infringement, LayoutException,
}, },
dsn::{design::DsnDesign, rules::DsnRules}, dsn::{design::DsnDesign, mesadata::DsnMesadata},
geometry::{ geometry::{
compound::CompoundManagerTrait, compound::CompoundManagerTrait,
primitive::{BendShape, DotShape, PrimitiveShape, PrimitiveShapeTrait, SegShape}, primitive::{BendShape, DotShape, PrimitiveShape, PrimitiveShapeTrait, SegShape},
@ -59,7 +59,7 @@ pub struct App {
overlay: Option<Overlay>, overlay: Option<Overlay>,
#[serde(skip)] #[serde(skip)]
invoker: Option<Arc<Mutex<Invoker<DsnRules>>>>, invoker: Option<Arc<Mutex<Invoker<DsnMesadata>>>>,
#[serde(skip)] #[serde(skip)]
shared_data: Arc<Mutex<SharedData>>, shared_data: Arc<Mutex<SharedData>>,

View File

@ -21,7 +21,7 @@ use topola::drawing::rules::{Conditions, RulesTrait};
use topola::drawing::seg::FixedSegWeight; use topola::drawing::seg::FixedSegWeight;
use topola::drawing::{Infringement, LayoutException}; use topola::drawing::{Infringement, LayoutException};
use topola::dsn::design::DsnDesign; use topola::dsn::design::DsnDesign;
use topola::dsn::rules::DsnRules; use topola::dsn::mesadata::DsnMesadata;
use topola::geometry::primitive::{PrimitiveShape, PrimitiveShapeTrait}; use topola::geometry::primitive::{PrimitiveShape, PrimitiveShapeTrait};
use topola::geometry::shape::ShapeTrait; use topola::geometry::shape::ShapeTrait;
use topola::layout::zone::MakePolyShape; use topola::layout::zone::MakePolyShape;

View File

@ -1,6 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ use crate::{
board::mesadata::MesadataTrait,
drawing::{ drawing::{
band::BandIndex, band::BandIndex,
dot::{FixedDotIndex, FixedDotWeight}, dot::{FixedDotIndex, FixedDotWeight},
@ -20,16 +21,16 @@ use crate::{
}; };
#[derive(Debug)] #[derive(Debug)]
pub struct Board<R: RulesTrait> { pub struct Board<M: MesadataTrait> {
layout: Layout<R>, layout: Layout<M>,
node_to_pinname: 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>,
pinname_pair_to_band: HashMap<(String, String), BandIndex>, pinname_pair_to_band: HashMap<(String, String), BandIndex>,
} }
impl<R: RulesTrait> Board<R> { impl<M: MesadataTrait> Board<M> {
pub fn new(layout: Layout<R>) -> Self { pub fn new(layout: Layout<M>) -> Self {
Self { Self {
layout, layout,
node_to_pinname: HashMap::new(), node_to_pinname: HashMap::new(),
@ -122,7 +123,7 @@ impl<R: RulesTrait> Board<R> {
&mut self, &mut self,
navmesh: Navmesh, navmesh: Navmesh,
width: f64, width: f64,
observer: &mut impl RouterObserverTrait<R>, observer: &mut impl RouterObserverTrait<M>,
) -> Result<BandIndex, RouterError> { ) -> Result<BandIndex, RouterError> {
let source_pinname = self let source_pinname = self
.node_pinname(GenericNode::Primitive(navmesh.source().into())) .node_pinname(GenericNode::Primitive(navmesh.source().into()))
@ -199,11 +200,11 @@ impl<R: RulesTrait> Board<R> {
} }
} }
pub fn layout(&self) -> &Layout<R> { pub fn layout(&self) -> &Layout<M> {
&self.layout &self.layout
} }
pub fn layout_mut(&mut self) -> &mut Layout<R> { pub fn layout_mut(&mut self) -> &mut Layout<M> {
&mut self.layout &mut self.layout
} }
} }

10
src/board/mesadata.rs Normal file
View File

@ -0,0 +1,10 @@
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;*/
}

View File

@ -1,3 +1,4 @@
mod board; mod board;
pub mod mesadata;
pub use board::*; pub use board::*;

View File

@ -8,7 +8,7 @@ use crate::{
drawing::{dot::FixedDotWeight, seg::FixedSegWeight, Drawing}, drawing::{dot::FixedDotWeight, seg::FixedSegWeight, Drawing},
dsn::{ dsn::{
de, de,
rules::DsnRules, mesadata::DsnMesadata,
structure::{self, DsnFile, Layer, Pcb, Shape}, structure::{self, DsnFile, Layer, Pcb, Shape},
}, },
geometry::compound::CompoundManagerTrait, geometry::compound::CompoundManagerTrait,
@ -44,8 +44,8 @@ impl DsnDesign {
Ok(Self { pcb }) Ok(Self { pcb })
} }
pub fn make_board(&self) -> Board<DsnRules> { pub fn make_board(&self) -> Board<DsnMesadata> {
let rules = DsnRules::from_pcb(&self.pcb); let rules = DsnMesadata::from_pcb(&self.pcb);
let mut board = Board::new(Layout::new(Drawing::new(rules))); let mut board = Board::new(Layout::new(Drawing::new(rules)));
// mapping of pin -> net prepared for adding pins // mapping of pin -> net prepared for adding pins
@ -341,7 +341,7 @@ impl DsnDesign {
} }
fn layer( fn layer(
board: &Board<DsnRules>, board: &Board<DsnMesadata>,
layer_vec: &Vec<Layer>, layer_vec: &Vec<Layer>,
layer_name: &str, layer_name: &str,
front: bool, front: bool,
@ -362,7 +362,7 @@ impl DsnDesign {
} }
fn add_circle( fn add_circle(
board: &mut Board<DsnRules>, board: &mut Board<DsnMesadata>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -390,7 +390,7 @@ impl DsnDesign {
} }
fn add_rect( fn add_rect(
board: &mut Board<DsnRules>, board: &mut Board<DsnMesadata>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -517,7 +517,7 @@ impl DsnDesign {
} }
fn add_path( fn add_path(
board: &mut Board<DsnRules>, board: &mut Board<DsnMesadata>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -600,7 +600,7 @@ impl DsnDesign {
} }
fn add_polygon( fn add_polygon(
board: &mut Board<DsnRules>, board: &mut Board<DsnMesadata>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,

View File

@ -1,6 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ use crate::{
board::mesadata::MesadataTrait,
drawing::rules::{Conditions, RulesTrait}, drawing::rules::{Conditions, RulesTrait},
dsn::structure::Pcb, dsn::structure::Pcb,
}; };
@ -21,7 +22,7 @@ impl DsnRule {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct DsnRules { pub struct DsnMesadata {
structure_rule: DsnRule, structure_rule: DsnRule,
// net class name -> rule // net class name -> rule
class_rules: HashMap<String, DsnRule>, class_rules: HashMap<String, DsnRule>,
@ -34,7 +35,7 @@ pub struct DsnRules {
net_to_netclass: HashMap<usize, String>, net_to_netclass: HashMap<usize, String>,
} }
impl DsnRules { impl DsnMesadata {
pub fn from_pcb(pcb: &Pcb) -> Self { pub fn from_pcb(pcb: &Pcb) -> Self {
let layer_ids = HashMap::from_iter( let layer_ids = HashMap::from_iter(
pcb.structure pcb.structure
@ -87,7 +88,7 @@ impl DsnRules {
} }
} }
impl RulesTrait for DsnRules { impl RulesTrait for DsnMesadata {
fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64 { fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64 {
let (Some(net1), Some(net2)) = (conditions1.maybe_net, conditions2.maybe_net) else { let (Some(net1), Some(net2)) = (conditions1.maybe_net, conditions2.maybe_net) else {
return 0.0; return 0.0;
@ -115,3 +116,7 @@ impl RulesTrait for DsnRules {
largest largest
} }
} }
impl MesadataTrait for DsnMesadata {
//
}

View File

@ -1,4 +1,4 @@
mod de; mod de;
pub mod design; pub mod design;
pub mod rules; pub mod mesadata;
mod structure; mod structure;

View File

@ -7,16 +7,13 @@ use topola::{
invoker::{Invoker, InvokerError}, invoker::{Invoker, InvokerError},
Autorouter, Autorouter,
}, },
board::Board, board::{mesadata::MesadataTrait, Board},
drawing::{ drawing::graph::{GetLayer, GetMaybeNet},
graph::{GetLayer, GetMaybeNet}, dsn::{design::DsnDesign, mesadata::DsnMesadata},
rules::RulesTrait,
},
dsn::{design::DsnDesign, rules::DsnRules},
graph::GetNodeIndex, graph::GetNodeIndex,
}; };
pub fn load_design_and_assert(filename: &str) -> Invoker<DsnRules> { pub fn load_design_and_assert(filename: &str) -> Invoker<DsnMesadata> {
let design = DsnDesign::load_from_file(filename).unwrap(); let design = DsnDesign::load_from_file(filename).unwrap();
let mut invoker = Invoker::new(Autorouter::new(design.make_board()).unwrap()); let mut invoker = Invoker::new(Autorouter::new(design.make_board()).unwrap());
@ -32,7 +29,7 @@ pub fn load_design_and_assert(filename: &str) -> Invoker<DsnRules> {
invoker invoker
} }
pub fn replay_and_assert(invoker: &mut Invoker<DsnRules>, filename: &str) { pub fn replay_and_assert(invoker: &mut Invoker<DsnMesadata>, filename: &str) {
let file = File::open(filename).unwrap(); let file = File::open(filename).unwrap();
invoker.replay(serde_json::from_reader(file).unwrap()); invoker.replay(serde_json::from_reader(file).unwrap());
@ -59,7 +56,7 @@ pub fn replay_and_assert(invoker: &mut Invoker<DsnRules>, filename: &str) {
} }
pub fn assert_single_layer_groundless_autoroute( pub fn assert_single_layer_groundless_autoroute(
autorouter: &mut Autorouter<impl RulesTrait>, autorouter: &mut Autorouter<impl MesadataTrait>,
layername: &str, layername: &str,
) { ) {
let unionfind = unionfind(autorouter); let unionfind = unionfind(autorouter);
@ -125,7 +122,7 @@ pub fn assert_single_layer_groundless_autoroute(
} }
/*pub fn assert_number_of_conncomps( /*pub fn assert_number_of_conncomps(
autorouter: &mut Autorouter<impl RulesTrait>, autorouter: &mut Autorouter<impl MesadataTrait>,
conncomp_count: usize, conncomp_count: usize,
) { ) {
let unionfind = unionfind(autorouter); let unionfind = unionfind(autorouter);
@ -137,7 +134,7 @@ pub fn assert_single_layer_groundless_autoroute(
}*/ }*/
pub fn assert_band_length( pub fn assert_band_length(
board: &Board<impl RulesTrait>, board: &Board<impl MesadataTrait>,
source: &str, source: &str,
target: &str, target: &str,
length: f64, length: f64,
@ -149,7 +146,7 @@ pub fn assert_band_length(
assert!((band_length - length).abs() < epsilon); assert!((band_length - length).abs() < epsilon);
} }
fn unionfind(autorouter: &mut Autorouter<impl RulesTrait>) -> UnionFind<NodeIndex<usize>> { fn unionfind(autorouter: &mut Autorouter<impl MesadataTrait>) -> UnionFind<NodeIndex<usize>> {
for ratline in autorouter.ratsnest().graph().edge_indices() { for ratline in autorouter.ratsnest().graph().edge_indices() {
// Accessing endpoints may create new dots because apex construction is lazy, so we access // Accessing endpoints may create new dots because apex construction is lazy, so we access
// tem all before starting unionfind, as it requires a constant index bound. // tem all before starting unionfind, as it requires a constant index bound.