mirror of https://codeberg.org/topola/topola.git
Write Specctra module documentation for Topola's library API (#34)
Reviewed-on: https://codeberg.org/topola/topola/pulls/34 Co-authored-by: hakki <hakki@noreply.codeberg.org> Co-committed-by: hakki <hakki@noreply.codeberg.org>
This commit is contained in:
parent
d43983a84d
commit
ee9f4b5566
|
|
@ -126,3 +126,6 @@ contracts = { path = "vendored/contracts" }
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
clap_mangen = "0.2.23"
|
clap_mangen = "0.2.23"
|
||||||
clap = {version="4.5.8", features = ["derive"] }
|
clap = {version="4.5.8", features = ["derive"] }
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
|
||||||
|
|
|
||||||
2
build.rs
2
build.rs
|
|
@ -2,7 +2,7 @@ include!("src/bin/topola/cli.rs");
|
||||||
use clap::CommandFactory;
|
use clap::CommandFactory;
|
||||||
use clap_mangen::Man;
|
use clap_mangen::Man;
|
||||||
use std::fs::{create_dir_all, File};
|
use std::fs::{create_dir_all, File};
|
||||||
// https://rust-cli.github.io/book/in-depth/docs.html
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let cmd = Cli::command();
|
let cmd = Cli::command();
|
||||||
let man = Man::new(cmd);
|
let man = Man::new(cmd);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::BufReader;
|
||||||
|
use topola::autorouter::history::History;
|
||||||
|
use topola::autorouter::invoker::Command;
|
||||||
|
use topola::autorouter::invoker::Invoker;
|
||||||
|
use topola::autorouter::selection::PinSelection;
|
||||||
|
use topola::autorouter::Autorouter;
|
||||||
|
use topola::specctra::design::SpecctraDesign;
|
||||||
|
|
||||||
|
fn main() -> Result<(), std::io::Error> {
|
||||||
|
let design_file = File::open("example.dsn")?;
|
||||||
|
let mut design_bufread = BufReader::new(design_file);
|
||||||
|
|
||||||
|
let design = SpecctraDesign::load(design_bufread).unwrap();
|
||||||
|
let board = design.make_board();
|
||||||
|
|
||||||
|
let mut invoker = Invoker::new(Autorouter::new(board).unwrap());
|
||||||
|
|
||||||
|
let mut file = File::create("example.ses").unwrap();
|
||||||
|
design.write_ses(invoker.autorouter().board(), &mut file);
|
||||||
|
|
||||||
|
let filename = design.get_name();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![doc(html_favicon_url = "https://codeberg.org/topola/topola/raw/commit/e1b56875edf039aab9f41868826bcd3a92097133/assets/favicon.ico")]
|
||||||
|
#![doc(html_logo_url = "https://codeberg.org/topola/topola/raw/commit/e1b56875edf039aab9f41868826bcd3a92097133/assets/logo.svg")]
|
||||||
#![cfg_attr(not(feature = "disable_contracts"), feature(try_blocks))]
|
#![cfg_attr(not(feature = "disable_contracts"), feature(try_blocks))]
|
||||||
|
|
||||||
pub mod graph;
|
pub mod graph;
|
||||||
|
|
|
||||||
|
|
@ -24,19 +24,35 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
||||||
|
/// Errors raised by [`SpecctraDesign::load`]
|
||||||
pub enum LoadingError {
|
pub enum LoadingError {
|
||||||
|
/// I/O file reading error from [`std::io::Error`]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
|
/// File parsing errors containing information about unexpected end of file,
|
||||||
|
/// or any other parsing issues with provided DSN file
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Parse(#[from] read::ParseError),
|
Parse(#[from] read::ParseError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// This struct is responsible for managing the various Specctra components of a PCB design,
|
||||||
|
/// including parsing the DSN file, handling the resolution, unit of measurement,
|
||||||
|
/// and organizing the PCB's structure, placement, library, network, and wiring.
|
||||||
|
/// It provides functionality for reading from a DSN file and writing Specctra's .SES session files.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SpecctraDesign {
|
pub struct SpecctraDesign {
|
||||||
pcb: Pcb,
|
pcb: Pcb,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecctraDesign {
|
impl SpecctraDesign {
|
||||||
|
/// Loads a [`SpecctraDesign`] structure instance from a buffered reader.
|
||||||
|
///
|
||||||
|
/// This function reads the Specctra Design data from an input stream.
|
||||||
|
/// Later the data is parsed and loaded into a [`SpecctraDesign`] structure,
|
||||||
|
/// allowing further operations such as rule validation, routing, or netlist management.
|
||||||
|
///
|
||||||
pub fn load(reader: impl std::io::BufRead) -> Result<SpecctraDesign, LoadingError> {
|
pub fn load(reader: impl std::io::BufRead) -> Result<SpecctraDesign, LoadingError> {
|
||||||
let mut list_reader = ListTokenizer::new(reader);
|
let mut list_reader = ListTokenizer::new(reader);
|
||||||
let dsn = list_reader.read_value::<DsnFile>()?;
|
let dsn = list_reader.read_value::<DsnFile>()?;
|
||||||
|
|
@ -44,14 +60,23 @@ impl SpecctraDesign {
|
||||||
Ok(Self { pcb: dsn.pcb })
|
Ok(Self { pcb: dsn.pcb })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Function to get name of the DSN file
|
||||||
|
///
|
||||||
|
/// This function returns the name of the `Pcb` objects
|
||||||
pub fn get_name(&self) -> &str {
|
pub fn get_name(&self) -> &str {
|
||||||
&self.pcb.name
|
&self.pcb.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_ses(
|
/// Writes the Specctra Session (.ses) file format using the current board layout and mesadata.
|
||||||
|
///
|
||||||
|
/// This function generates a Specctra SES session file that represents the board's net routing and
|
||||||
|
/// writes it to the provided output stream. The session data includes routed nets, wires,
|
||||||
|
/// layers, and other essential information for routing management.
|
||||||
|
///
|
||||||
|
pub fn write_ses(
|
||||||
&self,
|
&self,
|
||||||
board: &Board<SpecctraMesadata>,
|
board: &Board<SpecctraMesadata>,
|
||||||
writer: impl std::io::Write,
|
writer: impl std::io::Write,
|
||||||
) -> Result<(), std::io::Error> {
|
) -> Result<(), std::io::Error> {
|
||||||
let mesadata = board.mesadata();
|
let mesadata = board.mesadata();
|
||||||
let drawing = board.layout().drawing();
|
let drawing = board.layout().drawing();
|
||||||
|
|
@ -124,8 +149,8 @@ impl SpecctraDesign {
|
||||||
structure::NetOut {
|
structure::NetOut {
|
||||||
name: mesadata.net_netname(net).unwrap().to_owned(),
|
name: mesadata.net_netname(net).unwrap().to_owned(),
|
||||||
wire: vec![wire],
|
wire: vec![wire],
|
||||||
via: Vec::new(),
|
via: Vec::new()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -152,7 +177,14 @@ impl SpecctraDesign {
|
||||||
|
|
||||||
ListWriter::new(writer).write_value(&ses)
|
ListWriter::new(writer).write_value(&ses)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates a [`Board<SpecctraMesadata>`] from the current PCB data.
|
||||||
|
///
|
||||||
|
/// This function takes the internal `Pcb` structure and transforms it into a [`Board`] object,
|
||||||
|
/// which is used for layout and routing operations. The board is initialized with [`SpecctraMesadata`],
|
||||||
|
/// which includes layer and net mappings, and is populated with components, pins, vias, and wires
|
||||||
|
/// from the PCB definition.
|
||||||
|
///
|
||||||
pub fn make_board(&self) -> Board<SpecctraMesadata> {
|
pub fn make_board(&self) -> Board<SpecctraMesadata> {
|
||||||
let mesadata = SpecctraMesadata::from_pcb(&self.pcb);
|
let mesadata = SpecctraMesadata::from_pcb(&self.pcb);
|
||||||
let mut board = Board::new(Layout::new(Drawing::new(
|
let mut board = Board::new(Layout::new(Drawing::new(
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,18 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
/// [`SpecctraRule`] represents the basic routing constraints used by an auto-router, such as
|
||||||
|
/// the Specctra auto-router, in a PCB design process. This struct defines two key design
|
||||||
|
/// rules: the width of the trace and the minimum clearance between electrical features.
|
||||||
pub struct SpecctraRule {
|
pub struct SpecctraRule {
|
||||||
|
/// Specifies the width of the trace (or conductor) in millimeters.
|
||||||
|
/// This value ensures that the traces meet electrical
|
||||||
|
/// and mechanical requirements, such as current-carrying capacity or signal integrity.
|
||||||
pub width: f64,
|
pub width: f64,
|
||||||
|
/// Defines the minimum clearance (spacing) between traces, pads,
|
||||||
|
/// or other conductive features on the PCB. Adequate clearance is important for
|
||||||
|
/// preventing electrical shorts or interference between signals, and is often
|
||||||
|
/// dictated by manufacturing constraints or voltage considerations.
|
||||||
pub clearance: f64,
|
pub clearance: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,22 +34,43 @@ impl SpecctraRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
/// [`SpecctraMesadata`] holds the metadata required by the Specctra auto-router to
|
||||||
|
/// understand and enforce design rules across various net classes and layers in a PCB layout.
|
||||||
|
/// This struct encapsulates information about rules for individual nets, net classes,
|
||||||
|
/// layers, and their corresponding relationships.
|
||||||
pub struct SpecctraMesadata {
|
pub struct SpecctraMesadata {
|
||||||
|
|
||||||
|
/// The default routing rule applied globally if no specific net class rule is defined.
|
||||||
structure_rule: SpecctraRule,
|
structure_rule: SpecctraRule,
|
||||||
|
|
||||||
// net class name -> rule
|
// net class name -> rule
|
||||||
|
/// A map from net class names to their specific `SpecctraRule` constraints.
|
||||||
|
/// These rules are applied to all nets belonging to the respective net clas
|
||||||
class_rules: HashMap<String, SpecctraRule>,
|
class_rules: HashMap<String, SpecctraRule>,
|
||||||
|
|
||||||
// layername <-> layer for Layout
|
// layername <-> layer for Layout
|
||||||
|
/// A bidirectional map between layer indices and layer names, allowing translation
|
||||||
|
/// between index-based layers in the layout and user-defined layer names.
|
||||||
pub layer_layername: BiHashMap<usize, String>,
|
pub layer_layername: BiHashMap<usize, String>,
|
||||||
|
|
||||||
// netname <-> net for Layout
|
// netname <-> net for Layout
|
||||||
|
/// A bidirectional map between network indices and network names in the PCB layout,
|
||||||
|
/// providing an easy way to reference nets by name or index.
|
||||||
pub net_netname: BiHashMap<usize, String>,
|
pub net_netname: BiHashMap<usize, String>,
|
||||||
|
|
||||||
// net -> netclass
|
// net -> netclass
|
||||||
|
/// A map that associates network indices with their respective net class names.
|
||||||
|
/// This is used to apply net class-specific routing rules to each net.
|
||||||
net_netclass: HashMap<usize, String>,
|
net_netclass: HashMap<usize, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl SpecctraMesadata {
|
impl SpecctraMesadata {
|
||||||
|
/// Creates a [`SpecctraMesadata`] instance from a given `Pcb` reference.
|
||||||
|
///
|
||||||
|
/// This function extracts the necessary metadata from the `Pcb` struct, such as
|
||||||
|
/// layer-to-layer name mappings, net-to-net name mappings, and net class rules.
|
||||||
|
///
|
||||||
pub fn from_pcb(pcb: &Pcb) -> Self {
|
pub fn from_pcb(pcb: &Pcb) -> Self {
|
||||||
let layer_layername = BiHashMap::from_iter(
|
let layer_layername = BiHashMap::from_iter(
|
||||||
pcb.structure
|
pcb.structure
|
||||||
|
|
@ -81,6 +112,13 @@ impl SpecctraMesadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves the Specctra routing rule associated with a specified net ID.
|
||||||
|
///
|
||||||
|
/// This function looks up the routing rule for a given net ID. It first checks if the net is
|
||||||
|
/// associated with a net class. If a net class is found, it retrieves the corresponding rule
|
||||||
|
/// from the class rules. If no class is associated, or if the class does not have a defined rule,
|
||||||
|
/// it defaults to the general structure rule.
|
||||||
|
///
|
||||||
pub fn get_rule(&self, net: usize) -> &SpecctraRule {
|
pub fn get_rule(&self, net: usize) -> &SpecctraRule {
|
||||||
if let Some(netclass) = self.net_netclass.get(&net) {
|
if let Some(netclass) = self.net_netclass.get(&net) {
|
||||||
self.class_rules
|
self.class_rules
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue