diff --git a/prjcombine_int/src/db.rs b/prjcombine_int/src/db.rs index 5b5c857b..41748454 100644 --- a/prjcombine_int/src/db.rs +++ b/prjcombine_int/src/db.rs @@ -373,13 +373,13 @@ impl IntDb { }, "is_intf_in": pin.is_intf_in, })))), - }))), + }))), })) })), "terms": serde_json::Map::from_iter(self.terms.iter().map(|(_, name, term)| { (name.into(), json!({ "dir": term.dir.to_string(), - "wires": serde_json::Map::from_iter(term.wires.iter().map(|(wire, ti)| + "wires": serde_json::Map::from_iter(term.wires.iter().map(|(wire, ti)| (self.wires.key(wire).to_string(), match *ti { TermInfo::BlackHole => json!({ "kind": "BLACKHOLE", diff --git a/prjcombine_int/src/grid.rs b/prjcombine_int/src/grid.rs index 6aa81f37..cd652698 100644 --- a/prjcombine_int/src/grid.rs +++ b/prjcombine_int/src/grid.rs @@ -28,7 +28,13 @@ pub struct SimpleIoCoord { impl std::fmt::Display for SimpleIoCoord { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "IOB_X{x}Y{y}B{b}", x = self.col, y = self.row, b = self.iob) + write!( + f, + "IOB_X{x}Y{y}B{b}", + x = self.col, + y = self.row, + b = self.iob + ) } } diff --git a/prjcombine_rawdump/src/bin/rd2html.rs b/prjcombine_rawdump/src/bin/rd2html.rs index d0767f3a..3805e402 100644 --- a/prjcombine_rawdump/src/bin/rd2html.rs +++ b/prjcombine_rawdump/src/bin/rd2html.rs @@ -2368,8 +2368,16 @@ const ULTRASCALEPLUS_TILES: &[TileInfo] = &[ ), TileInfo("AMS_M12BUF_SYSMON_BOT_L_FT", (0, 0, 29, 0), &["sysmon"]), TileInfo("AMS_M12BUF_SYSMON_TOP_L_FT", (0, 0, 29, 0), &["sysmon"]), - TileInfo("AMS_M12BUF_AMS_LASSEN_TERM_BOT_L_FT", (0, 0, 29, 0), &["sysmon"]), - TileInfo("AMS_M12BUF_AMS_LASSEN_TERM_TOP_L_FT", (0, 0, 29, 0), &["sysmon"]), + TileInfo( + "AMS_M12BUF_AMS_LASSEN_TERM_BOT_L_FT", + (0, 0, 29, 0), + &["sysmon"], + ), + TileInfo( + "AMS_M12BUF_AMS_LASSEN_TERM_TOP_L_FT", + (0, 0, 29, 0), + &["sysmon"], + ), TileInfo("CFG_M12BUF", (0, 0, 29, 0), &[]), TileInfo("CFG_M12BUF_TERM_L", (0, 0, 29, 0), &[]), TileInfo("CFG_M12BUF_CFG_BOT_L_FT", (0, 0, 29, 0), &[]), @@ -2423,7 +2431,11 @@ const ULTRASCALEPLUS_TILES: &[TileInfo] = &[ TileInfo("CFG_M12BUF_IO_CFG_ALTO_TOP_L_FT", (0, 0, 29, 0), &[]), // specials for left HDIOLC TileInfo("CFRM_CBRK_HDIOL_L_FT", (0, 0, 29, 0), &["vbrk"]), - TileInfo("RCLK_RCLK_CBRK_HDIOL_M12BUF_L_FT", (1, 0, 0, 0), &["clk-row"]), + TileInfo( + "RCLK_RCLK_CBRK_HDIOL_M12BUF_L_FT", + (1, 0, 0, 0), + &["clk-row"], + ), TileInfo("CFG_M12BUF_HDIOL_L_FT", (0, 0, 29, 0), &[]), // specials for left of cfg col TileInfo("CFRM_CBRK_CTR_RIGHT_L_FT", (0, 0, 29, 0), &["vbrk"]), @@ -2452,8 +2464,16 @@ const ULTRASCALEPLUS_TILES: &[TileInfo] = &[ TileInfo("AMS_M12BUF_CTR_RIGHT_TOP_L_FT", (0, 0, 29, 0), &["sysmon"]), TileInfo("AMS_M12BUF_CTR_RIGHT_BOT_R_FT", (0, 0, 29, 0), &["sysmon"]), TileInfo("AMS_M12BUF_CTR_RIGHT_TOP_R_FT", (0, 0, 29, 0), &["sysmon"]), - TileInfo("AMS_M12BUF_AMS_LASSEN_IO_BOT_L_FT", (0, 0, 29, 0), &["sysmon"]), - TileInfo("AMS_M12BUF_AMS_LASSEN_IO_TOP_L_FT", (0, 0, 29, 0), &["sysmon"]), + TileInfo( + "AMS_M12BUF_AMS_LASSEN_IO_BOT_L_FT", + (0, 0, 29, 0), + &["sysmon"], + ), + TileInfo( + "AMS_M12BUF_AMS_LASSEN_IO_TOP_L_FT", + (0, 0, 29, 0), + &["sysmon"], + ), TileInfo("CFG_M12BUF_CTR_RIGHT_FT", (0, 0, 29, 0), &[]), TileInfo("CFG_M12BUF_CTR_RIGHT_CFG_OLY_BOT_L_FT", (0, 0, 29, 0), &[]), TileInfo("CFG_M12BUF_CTR_RIGHT_CFG_OLY_TOP_L_FT", (0, 0, 29, 0), &[]), @@ -2524,8 +2544,16 @@ const ULTRASCALEPLUS_TILES: &[TileInfo] = &[ TileInfo("AMS_M12BUF_TOP_R_FT", (0, 0, 29, 0), &["sysmon"]), TileInfo("AMS_M12BUF_AMS_BOT_R_FT", (0, 0, 29, 0), &["sysmon"]), TileInfo("AMS_M12BUF_AMS_TOP_R_FT", (0, 0, 29, 0), &["sysmon"]), - TileInfo("AMS_M12BUF_AMS_LASSEN_IO_BOT_R_FT", (0, 0, 29, 0), &["sysmon"]), - TileInfo("AMS_M12BUF_AMS_LASSEN_IO_TOP_R_FT", (0, 0, 29, 0), &["sysmon"]), + TileInfo( + "AMS_M12BUF_AMS_LASSEN_IO_BOT_R_FT", + (0, 0, 29, 0), + &["sysmon"], + ), + TileInfo( + "AMS_M12BUF_AMS_LASSEN_IO_TOP_R_FT", + (0, 0, 29, 0), + &["sysmon"], + ), TileInfo("CFG_M12BUF_CFG_BOT_R", (0, 0, 29, 0), &[]), TileInfo("CFG_M12BUF_CFG_TOP_R", (0, 0, 29, 0), &[]), TileInfo("CFG_M12BUF_CFG_BOT_R_FT", (0, 0, 29, 0), &[]), diff --git a/prjcombine_spartan6/Cargo.toml b/prjcombine_spartan6/Cargo.toml index 45e988b9..3f738e1f 100644 --- a/prjcombine_spartan6/Cargo.toml +++ b/prjcombine_spartan6/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +itertools.workspace = true serde_json.workspace = true zstd.workspace = true bincode.workspace = true diff --git a/prjcombine_spartan6/src/bond.rs b/prjcombine_spartan6/src/bond.rs index fe72a51b..3d5bb760 100644 --- a/prjcombine_spartan6/src/bond.rs +++ b/prjcombine_spartan6/src/bond.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use prjcombine_int::grid::SimpleIoCoord; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -129,3 +130,63 @@ impl Bond { }) } } + +fn pad_sort_key(name: &str) -> (usize, &str, u32) { + let pos = name.find(|x: char| x.is_ascii_digit()).unwrap(); + (pos, &name[..pos], name[pos..].parse().unwrap()) +} + +impl std::fmt::Display for Bond { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tBANKS:")?; + for (k, v) in &self.io_banks { + writeln!(f, "\t\t{k}: {v}")?; + } + writeln!(f, "\tPINS:")?; + for (pin, pad) in self.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { + write!(f, "\t\t{pin:4}: ")?; + match pad { + BondPin::Io(io) => write!(f, "{io}")?, + BondPin::Gt(bank, gtpin) => { + write!(f, "GT{bank}.")?; + match gtpin { + GtPin::RxP(idx) => write!(f, "RXP{idx}")?, + GtPin::RxN(idx) => write!(f, "RXN{idx}")?, + GtPin::TxP(idx) => write!(f, "TXP{idx}")?, + GtPin::TxN(idx) => write!(f, "TXN{idx}")?, + GtPin::VtRx => write!(f, "VTRX")?, + GtPin::VtTx => write!(f, "VTTX")?, + GtPin::ClkP(idx) => write!(f, "CLKP{idx}")?, + GtPin::ClkN(idx) => write!(f, "CLKN{idx}")?, + GtPin::AVcc => write!(f, "AVCC")?, + GtPin::AVccPll(idx) => write!(f, "AVCCPLL{idx}")?, + GtPin::RRef => write!(f, "RREF")?, + GtPin::AVttRCal => write!(f, "AVTTRCAL")?, + } + } + BondPin::Nc => write!(f, "NC")?, + BondPin::Gnd => write!(f, "GND")?, + BondPin::VccInt => write!(f, "VCCINT")?, + BondPin::VccAux => write!(f, "VCCAUX")?, + BondPin::VccO(bank) => write!(f, "VCCO{bank}")?, + BondPin::VccBatt => write!(f, "VCC_BATT")?, + BondPin::Cfg(CfgPin::Done) => write!(f, "DONE")?, + BondPin::Cfg(CfgPin::ProgB) => write!(f, "PROG_B")?, + BondPin::Cfg(CfgPin::Tck) => write!(f, "TCK")?, + BondPin::Cfg(CfgPin::Tms) => write!(f, "TMS")?, + BondPin::Cfg(CfgPin::Tdi) => write!(f, "TDI")?, + BondPin::Cfg(CfgPin::Tdo) => write!(f, "TDO")?, + BondPin::Cfg(CfgPin::Suspend) => write!(f, "SUSPEND")?, + BondPin::Cfg(CfgPin::CmpCsB) => write!(f, "CMPCS_B")?, + BondPin::Vfs => write!(f, "VFS")?, + BondPin::RFuse => write!(f, "RFUSE")?, + } + writeln!(f)?; + } + writeln!(f, "\tVREF:")?; + for v in &self.vref { + writeln!(f, "\t\t{v}")?; + } + Ok(()) + } +} diff --git a/prjcombine_spartan6/src/grid.rs b/prjcombine_spartan6/src/grid.rs index 5500b470..1a9d4684 100644 --- a/prjcombine_spartan6/src/grid.rs +++ b/prjcombine_spartan6/src/grid.rs @@ -351,3 +351,168 @@ impl Grid { }) } } + +impl std::fmt::Display for Grid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tKIND: Spartan6")?; + writeln!(f, "\tCOLS:")?; + for (col, cd) in &self.columns { + write!(f, "\t\tX{col}: ")?; + match cd.kind { + ColumnKind::Io => write!(f, "IO")?, + ColumnKind::CleXL => write!(f, "CLEXL")?, + ColumnKind::CleXM => write!(f, "CLEXM")?, + ColumnKind::CleClk => write!(f, "CLEXL+CLK")?, + ColumnKind::Bram => write!(f, "BRAM")?, + ColumnKind::Dsp => write!(f, "DSP")?, + ColumnKind::DspPlus => write!(f, "DSP*")?, + } + match cd.bio { + ColumnIoKind::None => (), + ColumnIoKind::Inner => write!(f, " BIO: I-")?, + ColumnIoKind::Outer => write!(f, " BIO: -O")?, + ColumnIoKind::Both => write!(f, " BIO: IO")?, + } + match cd.tio { + ColumnIoKind::None => (), + ColumnIoKind::Inner => write!(f, " TIO: I-")?, + ColumnIoKind::Outer => write!(f, " TIO: -O")?, + ColumnIoKind::Both => write!(f, " TIO: IO")?, + } + if let Some((cl, cr)) = self.cols_clk_fold { + if col == cl || col == cr { + write!(f, " FOLD")?; + } + } + if col == self.cols_reg_buf.0 || col == self.cols_reg_buf.1 { + write!(f, " REGBUF")?; + } + if let Gts::Single(cl) | Gts::Double(cl, _) | Gts::Quad(cl, _) = self.gts { + if col == cl { + write!(f, " LGT")?; + } + } + if let Gts::Double(_, cr) | Gts::Quad(_, cr) = self.gts { + if col == cr { + write!(f, " RGT")?; + } + } + writeln!(f,)?; + } + writeln!(f, "\tROWS:")?; + for (row, rd) in &self.rows { + if row.to_idx() != 0 && row.to_idx() % 16 == 0 { + writeln!(f, "\t\t--- clock break")?; + } + if row.to_idx() % 16 == 8 { + writeln!(f, "\t\t--- clock row")?; + } + if row == self.row_clk() { + writeln!(f, "\t\t--- spine row")?; + } + if let Some((rl, rr)) = self.rows_bank_split { + if row == rl { + writeln!(f, "\t\t--- left bank split")?; + } + if row == rr { + writeln!(f, "\t\t--- right bank split")?; + } + } + if Some(row) == self.row_mcb_split { + writeln!(f, "\t\t--- MCB split")?; + } + write!(f, "\t\tY{r}: ", r = row.to_idx())?; + if rd.lio { + write!(f, " LIO")?; + } + if rd.rio { + write!(f, " RIO")?; + } + if row == self.rows_midbuf.0 || row == self.rows_midbuf.1 { + write!(f, " MIDBUF")?; + } + if row == self.rows_hclkbuf.0 || row == self.rows_hclkbuf.1 { + write!(f, " HCLKBUF")?; + } + for (i, mcb) in self.mcbs.iter().enumerate() { + if row == mcb.row_mcb { + write!(f, " MCB{i}.MCB")?; + } + for (j, &r) in mcb.row_mui.iter().enumerate() { + if row == r { + write!(f, " MCB{i}.MUI{j}")?; + } + } + for (j, &r) in mcb.iop_dq.iter().enumerate() { + if row == r { + write!(f, " MCB{i}.DQ({jj0},{jj1})", jj0 = j * 2, jj1 = j * 2 + 1)?; + } + } + for (j, &r) in mcb.iop_dqs.iter().enumerate() { + if row == r { + write!(f, " MCB{i}.DQS{j}")?; + } + } + if row == mcb.iop_clk { + write!(f, " MCB{i}.CLK")?; + } + let mut pins: [Option<&'static str>; 2] = [None, None]; + for (pin, io) in [ + ("DM0", mcb.io_dm[0]), + ("DM1", mcb.io_dm[1]), + ("A0", mcb.io_addr[0]), + ("A1", mcb.io_addr[1]), + ("A2", mcb.io_addr[2]), + ("A3", mcb.io_addr[3]), + ("A4", mcb.io_addr[4]), + ("A5", mcb.io_addr[5]), + ("A6", mcb.io_addr[6]), + ("A7", mcb.io_addr[7]), + ("A8", mcb.io_addr[8]), + ("A9", mcb.io_addr[9]), + ("A10", mcb.io_addr[10]), + ("A11", mcb.io_addr[11]), + ("A12", mcb.io_addr[12]), + ("A13", mcb.io_addr[13]), + ("A14", mcb.io_addr[14]), + ("BA0", mcb.io_ba[0]), + ("BA1", mcb.io_ba[1]), + ("BA2", mcb.io_ba[2]), + ("RAS", mcb.io_ras), + ("CAS", mcb.io_cas), + ("WE", mcb.io_we), + ("ODT", mcb.io_odt), + ("CKE", mcb.io_cke), + ("RST", mcb.io_reset), + ] { + if row == io.row { + pins[io.iob.to_idx()] = Some(pin); + } + } + if pins.iter().any(|x| x.is_some()) { + write!( + f, + " MCB{i}.({p0},{p1})", + p0 = pins[0].unwrap(), + p1 = pins[1].unwrap() + )?; + } + } + writeln!(f)?; + } + match self.gts { + Gts::None => (), + Gts::Single(..) => writeln!(f, "\tGTS: SINGLE")?, + Gts::Double(..) => writeln!(f, "\tGTS: DOUBLE")?, + Gts::Quad(..) => writeln!(f, "\tGTS: QUAD")?, + } + writeln!(f, "\tCFG PINS:")?; + for (k, v) in &self.cfg_io { + writeln!(f, "\t\t{k:?}: {v}")?; + } + if self.has_encrypt { + writeln!(f, "\tHAS ENCRYPT")?; + } + Ok(()) + } +} diff --git a/prjcombine_types/src/tiledb.rs b/prjcombine_types/src/tiledb.rs index 99127f6b..6b7a1b81 100644 --- a/prjcombine_types/src/tiledb.rs +++ b/prjcombine_types/src/tiledb.rs @@ -1,5 +1,10 @@ use core::fmt::Debug; -use std::{collections::{btree_map, BTreeMap}, error::Error, fs::File, path::Path}; +use std::{ + collections::{btree_map, BTreeMap}, + error::Error, + fs::File, + path::Path, +}; use bitvec::vec::BitVec; use itertools::*; diff --git a/prjcombine_ultrascale/Cargo.toml b/prjcombine_ultrascale/Cargo.toml index e5d2fccc..1b3e4b96 100644 --- a/prjcombine_ultrascale/Cargo.toml +++ b/prjcombine_ultrascale/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +itertools.workspace = true serde_json.workspace = true zstd.workspace = true bincode.workspace = true diff --git a/prjcombine_ultrascale/src/bond.rs b/prjcombine_ultrascale/src/bond.rs index 981d8cf3..1014d54b 100644 --- a/prjcombine_ultrascale/src/bond.rs +++ b/prjcombine_ultrascale/src/bond.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use prjcombine_int::grid::{DieId, TileIobId}; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -451,3 +452,205 @@ impl Bond { }) } } + +fn pad_sort_key(name: &str) -> (usize, &str, u32) { + let pos = name.find(|x: char| x.is_ascii_digit()).unwrap(); + (pos, &name[..pos], name[pos..].parse().unwrap()) +} + +impl std::fmt::Display for Bond { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tPINS:")?; + for (pin, pad) in self.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { + write!(f, "\t\t{pin:4}: ")?; + match pad { + BondPin::Hpio(bank, idx) => write!(f, "HPIOB_{bank}_{idx}")?, + BondPin::Hdio(bank, idx) => write!(f, "HDIOB_{bank}_{idx}")?, + BondPin::HdioLc(bank, idx) => write!(f, "HDIOBLC_{bank}_{idx}")?, + BondPin::IoVref(bank) => write!(f, "IO_{bank}_VREF")?, + BondPin::Gt(bank, gtpin) => { + write!(f, "GT{bank}.")?; + match gtpin { + GtPin::RxP(idx) => write!(f, "RXP{idx}")?, + GtPin::RxN(idx) => write!(f, "RXN{idx}")?, + GtPin::TxP(idx) => write!(f, "TXP{idx}")?, + GtPin::TxN(idx) => write!(f, "TXN{idx}")?, + GtPin::ClkP(idx) => write!(f, "CLKP{idx}")?, + GtPin::ClkN(idx) => write!(f, "CLKN{idx}")?, + GtPin::AVcc => write!(f, "AVCC")?, + GtPin::RRef => write!(f, "RREF")?, + GtPin::AVttRCal => write!(f, "AVTTRCAL")?, + GtPin::AVtt => write!(f, "AVTT")?, + } + } + BondPin::GtRegion(region, gtpin) => { + write!(f, "GTREG")?; + match region { + GtRegion::All => (), + GtRegion::L => write!(f, "L")?, + GtRegion::R => write!(f, "R")?, + GtRegion::LS => write!(f, "LS")?, + GtRegion::RS => write!(f, "RS")?, + GtRegion::LN => write!(f, "LN")?, + GtRegion::RN => write!(f, "RN")?, + GtRegion::LLC => write!(f, "LLC")?, + GtRegion::RLC => write!(f, "RLC")?, + GtRegion::LC => write!(f, "LC")?, + GtRegion::RC => write!(f, "RC")?, + GtRegion::LUC => write!(f, "LUC")?, + GtRegion::RUC => write!(f, "RUC")?, + } + write!(f, ".")?; + match gtpin { + GtRegionPin::AVtt => write!(f, "AVTT")?, + GtRegionPin::AVcc => write!(f, "AVCC")?, + GtRegionPin::VccAux => write!(f, "VCCAUX")?, + GtRegionPin::VccInt => write!(f, "VCCINT")?, + } + } + BondPin::Nc => write!(f, "NC")?, + BondPin::Gnd => write!(f, "GND")?, + BondPin::VccInt => write!(f, "VCCINT")?, + BondPin::VccAux => write!(f, "VCCAUX")?, + BondPin::VccBram => write!(f, "VCCBRAM")?, + BondPin::VccO(bank) => write!(f, "VCCO{bank}")?, + BondPin::VccBatt => write!(f, "VCC_BATT")?, + BondPin::Cfg(CfgPin::Cclk) => write!(f, "CCLK")?, + BondPin::Cfg(CfgPin::Done) => write!(f, "DONE")?, + BondPin::Cfg(CfgPin::M0) => write!(f, "M0")?, + BondPin::Cfg(CfgPin::M1) => write!(f, "M1")?, + BondPin::Cfg(CfgPin::M2) => write!(f, "M2")?, + BondPin::Cfg(CfgPin::ProgB) => write!(f, "PROG_B")?, + BondPin::Cfg(CfgPin::InitB) => write!(f, "INIT_B")?, + BondPin::Cfg(CfgPin::RdWrB) => write!(f, "RDWR_B")?, + BondPin::Cfg(CfgPin::Tck) => write!(f, "TCK")?, + BondPin::Cfg(CfgPin::Tms) => write!(f, "TMS")?, + BondPin::Cfg(CfgPin::Tdi) => write!(f, "TDI")?, + BondPin::Cfg(CfgPin::Tdo) => write!(f, "TDO")?, + BondPin::Cfg(CfgPin::HswapEn) => write!(f, "HSWAP_EN")?, + BondPin::Cfg(CfgPin::Data(idx)) => write!(f, "DATA{idx}")?, + BondPin::Cfg(CfgPin::CfgBvs) => write!(f, "CFGBVS")?, + BondPin::Cfg(CfgPin::PorOverride) => write!(f, "POR_OVERRIDE")?, + BondPin::Dxn => write!(f, "DXN")?, + BondPin::Dxp => write!(f, "DXP")?, + BondPin::Rsvd => write!(f, "RSVD")?, + BondPin::RsvdGnd => write!(f, "RSVDGND")?, + BondPin::SysMon(bank, pin) => { + write!(f, "SYSMON{bank}.")?; + match pin { + SysMonPin::VP => write!(f, "VP")?, + SysMonPin::VN => write!(f, "VN")?, + } + } + BondPin::VccPsAux => write!(f, "VCC_PS_AUX")?, + BondPin::VccPsPll => write!(f, "VCC_PS_PLL")?, + BondPin::IoPs(bank, pin) => { + write!(f, "PS{bank}.")?; + match pin { + PsPin::Mio(i) => write!(f, "MIO{i}")?, + PsPin::Clk => write!(f, "CLK")?, + PsPin::PorB => write!(f, "POR_B")?, + PsPin::SrstB => write!(f, "SRST_B")?, + PsPin::DdrDq(i) => write!(f, "DDR_DQ{i}")?, + PsPin::DdrDm(i) => write!(f, "DDR_DM{i}")?, + PsPin::DdrDqsP(i) => write!(f, "DDR_DQS_P{i}")?, + PsPin::DdrDqsN(i) => write!(f, "DDR_DQS_N{i}")?, + PsPin::DdrA(i) => write!(f, "DDR_A{i}")?, + PsPin::DdrBa(i) => write!(f, "DDR_BA{i}")?, + PsPin::DdrCkP(idx) => write!(f, "DDR_CKP{idx}")?, + PsPin::DdrCkN(idx) => write!(f, "DDR_CKN{idx}")?, + PsPin::DdrCke(idx) => write!(f, "DDR_CKE{idx}")?, + PsPin::DdrOdt(idx) => write!(f, "DDR_ODT{idx}")?, + PsPin::DdrCsB(idx) => write!(f, "DDR_CS_B{idx}")?, + PsPin::DdrDrstB => write!(f, "DDR_DRST_B")?, + PsPin::DdrActN => write!(f, "DDR_ACT_N")?, + PsPin::DdrAlertN => write!(f, "DDR_ALERT_N")?, + PsPin::DdrBg(idx) => write!(f, "DDR_BG{idx}")?, + PsPin::DdrParity => write!(f, "DDR_PARITY")?, + PsPin::DdrZq => write!(f, "DDR_ZQ")?, + PsPin::ErrorOut => write!(f, "ERROR_OUT")?, + PsPin::ErrorStatus => write!(f, "ERROR_STATUS")?, + PsPin::Done => write!(f, "DONE")?, + PsPin::InitB => write!(f, "INIT_B")?, + PsPin::ProgB => write!(f, "PROG_B")?, + PsPin::JtagTck => write!(f, "JTAG_TCK")?, + PsPin::JtagTdi => write!(f, "JTAG_TDI")?, + PsPin::JtagTdo => write!(f, "JTAG_TDO")?, + PsPin::JtagTms => write!(f, "JTAG_TMS")?, + PsPin::Mode(i) => write!(f, "MODE{i}")?, + PsPin::PadI => write!(f, "PAD_I")?, + PsPin::PadO => write!(f, "PAD_O")?, + } + } + BondPin::SysMonVRefP => write!(f, "SYSMON_VREFP")?, + BondPin::SysMonVRefN => write!(f, "SYSMON_VREFN")?, + BondPin::SysMonGnd => write!(f, "SYSMON_GND")?, + BondPin::SysMonVcc => write!(f, "SYSMON_VCC")?, + BondPin::PsSysMonGnd => write!(f, "PS_SYSMON_GND")?, + BondPin::PsSysMonVcc => write!(f, "PS_SYSMON_VCC")?, + BondPin::VccAuxHpio => write!(f, "VCCAUX_HPIO")?, + BondPin::VccAuxHdio => write!(f, "VCCAUX_HDIO")?, + BondPin::VccAuxIo => write!(f, "VCCAUX_IO")?, + BondPin::VccIntIo => write!(f, "VCCINT_IO")?, + BondPin::VccPsIntLp => write!(f, "VCC_PS_INT_LP")?, + BondPin::VccPsIntFp => write!(f, "VCC_PS_INT_FP")?, + BondPin::VccPsIntFpDdr => write!(f, "VCC_PS_INT_FP_DDR")?, + BondPin::VccPsBatt => write!(f, "VCC_PS_BATT")?, + BondPin::VccPsDdrPll => write!(f, "VCC_PS_DDR_PLL")?, + BondPin::VccIntVcu => write!(f, "VCCINT_VCU")?, + BondPin::GndSense => write!(f, "GND_SENSE")?, + BondPin::VccIntSense => write!(f, "VCCINT_SENSE")?, + BondPin::VccIntAms => write!(f, "VCCINT_AMS")?, + BondPin::VccSdfec => write!(f, "VCC_SDFEC")?, + BondPin::RfDacGnd => write!(f, "RFDAC_GND")?, + BondPin::RfDacSubGnd => write!(f, "RFDAC_AGND")?, + BondPin::RfDacAVcc => write!(f, "RFDAC_AVCC")?, + BondPin::RfDacAVccAux => write!(f, "RFDAC_AVCCAUX")?, + BondPin::RfDacAVtt => write!(f, "RFDAC_AVTT")?, + BondPin::RfAdcGnd => write!(f, "RFADC_GND")?, + BondPin::RfAdcSubGnd => write!(f, "RFADC_SUBGND")?, + BondPin::RfAdcAVcc => write!(f, "RFADC_AVCC")?, + BondPin::RfAdcAVccAux => write!(f, "RFADC_AVCCAUX")?, + BondPin::Hbm(bank, pin) => { + write!(f, "HBM{bank}.")?; + match pin { + HbmPin::Vcc => write!(f, "VCC")?, + HbmPin::VccIo => write!(f, "VCCIO")?, + HbmPin::VccAux => write!(f, "VCCAUX")?, + HbmPin::Rsvd => write!(f, "RSVD")?, + HbmPin::RsvdGnd => write!(f, "RSVD_GND")?, + } + } + BondPin::RfDac(bank, pin) => { + write!(f, "RFDAC{bank}.")?; + match pin { + RfDacPin::VOutP(idx) => write!(f, "VOUT{idx}P")?, + RfDacPin::VOutN(idx) => write!(f, "VOUT{idx}N")?, + RfDacPin::ClkP => write!(f, "CLKP")?, + RfDacPin::ClkN => write!(f, "CLKN")?, + RfDacPin::RExt => write!(f, "REXT")?, + RfDacPin::SysRefP => write!(f, "SYSREFP")?, + RfDacPin::SysRefN => write!(f, "SYSREFN")?, + } + } + BondPin::RfAdc(bank, pin) => { + write!(f, "RFADC{bank}.")?; + match pin { + RfAdcPin::VInP(idx) => write!(f, "VIN{idx}_P")?, + RfAdcPin::VInN(idx) => write!(f, "VIN{idx}_N")?, + RfAdcPin::VInPairP(idx) => write!(f, "VIN_PAIR{idx}_P")?, + RfAdcPin::VInPairN(idx) => write!(f, "VIN_PAIR{idx}_N")?, + RfAdcPin::ClkP => write!(f, "CLKP")?, + RfAdcPin::ClkN => write!(f, "CLKN")?, + RfAdcPin::VCm(idx) => write!(f, "VCM{idx}")?, + RfAdcPin::RExt => write!(f, "REXT")?, + RfAdcPin::PllTestOutP => write!(f, "PLL_TEST_OUT_P")?, + RfAdcPin::PllTestOutN => write!(f, "PLL_TEST_OUT_N")?, + } + } + } + writeln!(f)?; + } + Ok(()) + } +} diff --git a/prjcombine_ultrascale/src/grid.rs b/prjcombine_ultrascale/src/grid.rs index c5764865..fcba512f 100644 --- a/prjcombine_ultrascale/src/grid.rs +++ b/prjcombine_ultrascale/src/grid.rs @@ -382,3 +382,166 @@ impl Grid { }) } } + +impl std::fmt::Display for Grid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tKIND: {v:?}", v = self.kind)?; + if let Some(ps) = self.ps { + write!(f, "\tPS {v:?}", v = ps.intf_kind)?; + if ps.has_vcu { + write!(f, " VCU")?; + } + writeln!(f)?; + } + if self.has_hbm { + writeln!(f, "\tHAS HBM")?; + } + if self.has_csec { + writeln!(f, "\tHAS CSEC")?; + } + if self.is_dmc { + writeln!(f, "\tIS DMC")?; + } + if self.is_alt_cfg { + writeln!(f, "\tIS ALT CFG")?; + } + writeln!(f, "\tCOLS:")?; + for (col, cd) in &self.columns { + if self.cols_vbrk.contains(&col) { + writeln!(f, "\t\t--- break")?; + } + if self.cols_fsr_gap.contains(&col) { + writeln!(f, "\t\t--- FSR gap")?; + } + if matches!( + cd.l, + ColumnKindLeft::Uram + | ColumnKindLeft::Hard(_, _) + | ColumnKindLeft::DfeC + | ColumnKindLeft::DfeDF + | ColumnKindLeft::DfeE + ) { + write!(f, "\t\tX{cl}.R-X{c}.L: ", cl = col - 1, c = col)?; + } else { + write!(f, "\t\tX{c}.L: ", c = col.to_idx())?; + } + match cd.l { + ColumnKindLeft::Io(_) => write!(f, "IO")?, + ColumnKindLeft::Gt(_) => write!(f, "GT")?, + ColumnKindLeft::CleL => write!(f, "CLEL")?, + ColumnKindLeft::CleM(CleMKind::Plain) => write!(f, "CLEM")?, + ColumnKindLeft::CleM(CleMKind::ClkBuf) => write!(f, "CLEM.CLK")?, + ColumnKindLeft::CleM(CleMKind::Laguna) => write!(f, "CLEM.LAGUNA")?, + ColumnKindLeft::Bram(BramKind::Plain) => write!(f, "BRAM")?, + ColumnKindLeft::Bram(BramKind::AuxClmp) => write!(f, "BRAM.AUX_CLMP")?, + ColumnKindLeft::Bram(BramKind::BramClmp) => write!(f, "BRAM.BRAM_CLMP")?, + ColumnKindLeft::Bram(BramKind::AuxClmpMaybe) => write!(f, "BRAM.AUX_CLMP*")?, + ColumnKindLeft::Bram(BramKind::BramClmpMaybe) => write!(f, "BRAM.BRAM_CLMP*")?, + ColumnKindLeft::Bram(BramKind::Td) => write!(f, "BRAM.TD")?, + ColumnKindLeft::Uram => write!(f, "URAM")?, + ColumnKindLeft::Hard(hk, _) => { + write!(f, "HARD{}", if hk == HardKind::Clk { " CLK" } else { "" })? + } + ColumnKindLeft::Sdfec => write!(f, "SDFEC")?, + ColumnKindLeft::DfeC => write!(f, "DFE_C")?, + ColumnKindLeft::DfeDF => write!(f, "DFE_DF")?, + ColumnKindLeft::DfeE => write!(f, "DFE_E")?, + } + if cd.clk_l.iter().any(|x| x.is_some()) { + write!(f, " CLK")?; + for v in cd.clk_l { + if let Some(v) = v { + write!(f, " {v}")?; + } else { + write!(f, " -")?; + } + } + } + if let Some(ps) = self.ps { + if ps.col == col { + write!(f, " PS")?; + } + } + writeln!(f,)?; + if let ColumnKindLeft::Io(idx) | ColumnKindLeft::Gt(idx) = cd.l { + let ioc = &self.cols_io[idx]; + for (reg, kind) in &ioc.regs { + writeln!( + f, + "\t\t\tY{y}: {kind:?}", + y = self.row_reg_bot(reg).to_idx() + )?; + } + } + if let ColumnKindLeft::Hard(_, idx) = cd.l { + let hc = &self.cols_hard[idx]; + for (reg, kind) in &hc.regs { + writeln!( + f, + "\t\t\tY{y}: {kind:?}", + y = self.row_reg_bot(reg).to_idx() + )?; + } + } + if matches!( + cd.r, + ColumnKindRight::Uram + | ColumnKindRight::Hard(HardKind::Clk | HardKind::NonClk, _) + | ColumnKindRight::DfeC + | ColumnKindRight::DfeDF + | ColumnKindRight::DfeE + ) { + continue; + } + write!(f, "\t\tX{c}.R: ", c = col.to_idx())?; + match cd.r { + ColumnKindRight::Io(_) => write!(f, "IO")?, + ColumnKindRight::Gt(_) => write!(f, "GT")?, + ColumnKindRight::CleL(CleLKind::Plain) => write!(f, "CLEL")?, + ColumnKindRight::CleL(CleLKind::Dcg10) => write!(f, "CLEL.DCG10")?, + ColumnKindRight::Dsp(DspKind::Plain) => write!(f, "DSP")?, + ColumnKindRight::Dsp(DspKind::ClkBuf) => write!(f, "DSP.CLK")?, + ColumnKindRight::Uram => write!(f, "URAM")?, + ColumnKindRight::Hard(_, _) => write!(f, "HARD TERM")?, + ColumnKindRight::DfeB => write!(f, "DFE_B")?, + ColumnKindRight::DfeC => write!(f, "DFE_C")?, + ColumnKindRight::DfeDF => write!(f, "DFE_DF")?, + ColumnKindRight::DfeE => write!(f, "DFE_E")?, + } + if cd.clk_r.iter().any(|x| x.is_some()) { + write!(f, " CLK")?; + for v in cd.clk_r { + if let Some(v) = v { + write!(f, " {v}")?; + } else { + write!(f, " -")?; + } + } + } + writeln!(f)?; + if let ColumnKindRight::Io(idx) | ColumnKindRight::Gt(idx) = cd.r { + let ioc = &self.cols_io[idx]; + for (reg, kind) in &ioc.regs { + writeln!( + f, + "\t\t\tY{y}: {kind:?}", + y = self.row_reg_bot(reg).to_idx() + )?; + } + } + if let ColumnKindRight::Hard(__, idx) = cd.r { + let hc = &self.cols_hard[idx]; + for (reg, kind) in &hc.regs { + writeln!( + f, + "\t\t\tY{y}: {kind:?}", + y = self.row_reg_bot(reg).to_idx() + )?; + } + } + } + writeln!(f, "\tREGS: {r}", r = self.regs)?; + + Ok(()) + } +} diff --git a/prjcombine_versal/src/bond.rs b/prjcombine_versal/src/bond.rs index 361e9c13..8d8cf8c6 100644 --- a/prjcombine_versal/src/bond.rs +++ b/prjcombine_versal/src/bond.rs @@ -13,3 +13,10 @@ impl Bond { ExpandedBond { bond: self } } } + +impl std::fmt::Display for Bond { + fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // well. + Ok(()) + } +} \ No newline at end of file diff --git a/prjcombine_versal/src/grid.rs b/prjcombine_versal/src/grid.rs index 30641c37..0e16fdc3 100644 --- a/prjcombine_versal/src/grid.rs +++ b/prjcombine_versal/src/grid.rs @@ -198,3 +198,125 @@ impl Grid { self.cols_hard.iter().find(|x| x.col == col) } } + +impl std::fmt::Display for Grid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tKIND: Versal")?; + writeln!(f, "\tPS: {v:?}", v = self.ps)?; + writeln!(f, "\tCPM: {v:?}", v = self.cpm)?; + writeln!(f, "\tXRAM TOP: {v:?}", v = self.has_xram_top)?; + writeln!(f, "\tTOP: {v:?}", v = self.top)?; + writeln!(f, "\tBOTTOM: {v:?}", v = self.bottom)?; + writeln!(f, "\tCOLS:")?; + for (col, cd) in &self.columns { + if self.cols_vbrk.contains(&col) { + writeln!(f, "\t\t--- break")?; + } + if self.cols_cpipe.contains(&col) { + writeln!(f, "\t\t--- CPIPE")?; + } + if matches!( + cd.l, + ColumnKind::Cle(_) + | ColumnKind::Dsp + | ColumnKind::Hard + | ColumnKind::VNoc + | ColumnKind::VNoc2 + ) { + write!(f, "\t\tX{cl}.R-X{col}.L: ", cl = col - 1)?; + } else { + write!(f, "\t\tX{col}.L: ")?; + } + match cd.l { + ColumnKind::None => write!(f, "---")?, + ColumnKind::Cle(CleKind::Plain) => write!(f, "CLE")?, + ColumnKind::Cle(CleKind::Sll) => write!(f, "CLE.SLL")?, + ColumnKind::Cle(CleKind::Sll2) => write!(f, "CLE.SLL2")?, + ColumnKind::Dsp => write!(f, "DSP")?, + ColumnKind::Bram(BramKind::Plain) => write!(f, "BRAM")?, + ColumnKind::Bram(BramKind::ClkBuf) => write!(f, "BRAM.CLKBUF")?, + ColumnKind::Bram(BramKind::ClkBufNoPd) => write!(f, "BRAM.CLKBUF.NOPD")?, + ColumnKind::Uram => write!(f, "URAM")?, + ColumnKind::Hard => write!(f, "HARD")?, + ColumnKind::Gt => write!(f, "GT")?, + ColumnKind::Cfrm => write!(f, "CFRM")?, + ColumnKind::VNoc => write!(f, "VNOC")?, + ColumnKind::VNoc2 => write!(f, "VNOC2")?, + } + if cd.has_bli_bot_l { + write!(f, " BLI.BOT")?; + } + if cd.has_bli_top_l { + write!(f, " BLI.TOP")?; + } + writeln!(f,)?; + for hc in &self.cols_hard { + if hc.col == col { + for (reg, kind) in &hc.regs { + writeln!(f, "\t\t\tY{y}: {kind:?}", y = self.row_reg_bot(reg))?; + } + } + } + if matches!( + cd.r, + ColumnKind::Cle(_) + | ColumnKind::Dsp + | ColumnKind::Hard + | ColumnKind::VNoc + | ColumnKind::VNoc2 + ) { + continue; + } + write!(f, "\t\tX{col}.R: ")?; + match cd.r { + ColumnKind::None => write!(f, "---")?, + ColumnKind::Cle(CleKind::Plain) => write!(f, "CLE")?, + ColumnKind::Cle(CleKind::Sll) => write!(f, "CLE.SLL")?, + ColumnKind::Cle(CleKind::Sll2) => write!(f, "CLE.SLL2")?, + ColumnKind::Dsp => write!(f, "DSP")?, + ColumnKind::Bram(BramKind::Plain) => write!(f, "BRAM")?, + ColumnKind::Bram(BramKind::ClkBuf) => write!(f, "BRAM.CLKBUF")?, + ColumnKind::Bram(BramKind::ClkBufNoPd) => write!(f, "BRAM.CLKBUF.NOPD")?, + ColumnKind::Uram => write!(f, "URAM")?, + ColumnKind::Hard => write!(f, "HARD")?, + ColumnKind::Gt => write!(f, "GT")?, + ColumnKind::Cfrm => write!(f, "CFRM")?, + ColumnKind::VNoc => write!(f, "VNOC")?, + ColumnKind::VNoc2 => write!(f, "VNOC2")?, + } + if cd.has_bli_bot_r { + write!(f, " BLI.BOT")?; + } + if cd.has_bli_top_r { + write!(f, " BLI.TOP")?; + } + writeln!(f,)?; + } + writeln!(f, "\tGT LEFT:")?; + for (reg, kind) in &self.regs_gt_left { + writeln!(f, "\t\tY{y}: {kind:?}", y = self.row_reg_bot(reg))?; + } + match self.right { + RightKind::Term => { + writeln!(f, "\tRIGHT: TERM")?; + } + RightKind::Term2 => { + writeln!(f, "\tRIGHT: TERM2")?; + } + RightKind::Gt(ref regs_gt_right) => { + writeln!(f, "\tRIGHT: GT:\n")?; + for (reg, kind) in regs_gt_right { + writeln!(f, "\t\tY{y}: {kind:?}", y = self.row_reg_bot(reg))?; + } + } + RightKind::HNicX => { + writeln!(f, "\tRIGHT: HNIC")?; + } + RightKind::Cidb => { + writeln!(f, "\tRIGHT: CIDB")?; + } + } + writeln!(f, "\tREGS: {r}", r = self.regs)?; + Ok(()) + } +} diff --git a/prjcombine_virtex/Cargo.toml b/prjcombine_virtex/Cargo.toml index e3778e7b..94d66b40 100644 --- a/prjcombine_virtex/Cargo.toml +++ b/prjcombine_virtex/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +itertools.workspace = true serde.workspace = true serde_json.workspace = true zstd.workspace = true diff --git a/prjcombine_virtex/src/bond.rs b/prjcombine_virtex/src/bond.rs index 43300ddc..80202853 100644 --- a/prjcombine_virtex/src/bond.rs +++ b/prjcombine_virtex/src/bond.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use prjcombine_int::grid::SimpleIoCoord; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -106,3 +107,56 @@ impl Bond { }) } } + +fn pad_sort_key(name: &str) -> (usize, &str, u32) { + let pos = name.find(|x: char| x.is_ascii_digit()).unwrap(); + (pos, &name[..pos], name[pos..].parse().unwrap()) +} + +impl std::fmt::Display for Bond { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tBANKS:")?; + for (k, v) in &self.io_banks { + writeln!(f, "\t\t{k}: {v}")?; + } + writeln!(f, "\tPINS:")?; + for (pin, pad) in self.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { + write!(f, "\t\t{pin:4}: ")?; + match pad { + BondPin::Io(io) => write!(f, "{io}")?, + BondPin::Clk(idx) => write!(f, "CLK{idx}")?, + BondPin::Nc => write!(f, "NC")?, + BondPin::Gnd => write!(f, "GND")?, + BondPin::VccInt => write!(f, "VCCINT")?, + BondPin::VccAux => write!(f, "VCCAUX")?, + BondPin::VccO(bank) => write!(f, "VCCO{bank}")?, + BondPin::Cfg(CfgPin::Cclk) => write!(f, "CCLK")?, + BondPin::Cfg(CfgPin::Done) => write!(f, "DONE")?, + BondPin::Cfg(CfgPin::M0) => write!(f, "M0")?, + BondPin::Cfg(CfgPin::M1) => write!(f, "M1")?, + BondPin::Cfg(CfgPin::M2) => write!(f, "M2")?, + BondPin::Cfg(CfgPin::ProgB) => write!(f, "PROG_B")?, + BondPin::Cfg(CfgPin::Tck) => write!(f, "TCK")?, + BondPin::Cfg(CfgPin::Tms) => write!(f, "TMS")?, + BondPin::Cfg(CfgPin::Tdi) => write!(f, "TDI")?, + BondPin::Cfg(CfgPin::Tdo) => write!(f, "TDO")?, + BondPin::Dxn => write!(f, "DXN")?, + BondPin::Dxp => write!(f, "DXP")?, + } + writeln!(f)?; + } + writeln!(f, "\tVREF:")?; + for v in &self.vref { + writeln!(f, "\t\t{v}")?; + } + writeln!(f, "\tDIFFP:")?; + for v in &self.diffp { + writeln!(f, "\t\t{v}")?; + } + writeln!(f, "\tDIFFN:")?; + for v in &self.diffn { + writeln!(f, "\t\t{v}")?; + } + Ok(()) + } +} diff --git a/prjcombine_virtex/src/grid.rs b/prjcombine_virtex/src/grid.rs index ca92210d..50924d97 100644 --- a/prjcombine_virtex/src/grid.rs +++ b/prjcombine_virtex/src/grid.rs @@ -102,3 +102,40 @@ impl Grid { }) } } + +impl std::fmt::Display for Grid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tKIND: {k:?}", k = self.kind)?; + writeln!(f, "\tDIMS: {c}×{r}", c = self.columns, r = self.rows)?; + writeln!(f, "\tCOLS:")?; + let mut clkv_idx = 0; + for col in self.columns() { + if col == self.cols_clkv[clkv_idx].0 { + writeln!(f, "\t\t--- clock column")?; + } + if col == self.cols_clkv[clkv_idx].2 { + writeln!(f, "\t\t--- clock break")?; + clkv_idx += 1; + } + writeln!( + f, + "\t\tX{c}: {kind}", + c = col.to_idx(), + kind = if self.cols_bram.contains(&col) { + "BRAM" + } else if col == self.col_lio() { + "LIO" + } else if col == self.col_rio() { + "RIO" + } else { + "CLB" + } + )?; + } + writeln!(f, "\tCFG PINS:")?; + for (k, v) in &self.cfg_io { + writeln!(f, "\t\t{k:?}: {v}",)?; + } + Ok(()) + } +} diff --git a/prjcombine_virtex2/Cargo.toml b/prjcombine_virtex2/Cargo.toml index 73925904..39d404ce 100644 --- a/prjcombine_virtex2/Cargo.toml +++ b/prjcombine_virtex2/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +itertools.workspace = true serde_json.workspace = true zstd.workspace = true bincode.workspace = true diff --git a/prjcombine_virtex2/src/bond.rs b/prjcombine_virtex2/src/bond.rs index 0e9b6b78..38aab638 100644 --- a/prjcombine_virtex2/src/bond.rs +++ b/prjcombine_virtex2/src/bond.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use prjcombine_int::grid::SimpleIoCoord; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -135,3 +136,66 @@ impl Bond { }) } } + +fn pad_sort_key(name: &str) -> (usize, &str, u32) { + let pos = name.find(|x: char| x.is_ascii_digit()).unwrap(); + (pos, &name[..pos], name[pos..].parse().unwrap()) +} + +impl std::fmt::Display for Bond { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tBANKS:")?; + for (k, v) in &self.io_banks { + writeln!(f, "\t\t{k}: {v}")?; + } + writeln!(f, "\tPINS:")?; + for (pin, pad) in self.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { + write!(f, "\t\t{pin:4}: ")?; + match pad { + BondPin::Io(io) => write!(f, "{io}")?, + BondPin::Gt(bank, gtpin) => { + write!(f, "GT{bank}.")?; + match gtpin { + GtPin::RxP => write!(f, "RXP")?, + GtPin::RxN => write!(f, "RXN")?, + GtPin::TxP => write!(f, "TXP")?, + GtPin::TxN => write!(f, "TXN")?, + GtPin::GndA => write!(f, "GNDA")?, + GtPin::VtRx => write!(f, "VTRX")?, + GtPin::VtTx => write!(f, "VTTX")?, + GtPin::AVccAuxRx => write!(f, "AVCCAUXRX")?, + GtPin::AVccAuxTx => write!(f, "AVCCAUXTX")?, + } + } + BondPin::Nc => write!(f, "NC")?, + BondPin::Gnd => write!(f, "GND")?, + BondPin::VccInt => write!(f, "VCCINT")?, + BondPin::VccAux => write!(f, "VCCAUX")?, + BondPin::VccO(bank) => write!(f, "VCCO{bank}")?, + BondPin::VccBatt => write!(f, "VCC_BATT")?, + BondPin::Cfg(CfgPin::Cclk) => write!(f, "CCLK")?, + BondPin::Cfg(CfgPin::Done) => write!(f, "DONE")?, + BondPin::Cfg(CfgPin::M0) => write!(f, "M0")?, + BondPin::Cfg(CfgPin::M1) => write!(f, "M1")?, + BondPin::Cfg(CfgPin::M2) => write!(f, "M2")?, + BondPin::Cfg(CfgPin::ProgB) => write!(f, "PROG_B")?, + BondPin::Cfg(CfgPin::Tck) => write!(f, "TCK")?, + BondPin::Cfg(CfgPin::Tms) => write!(f, "TMS")?, + BondPin::Cfg(CfgPin::Tdi) => write!(f, "TDI")?, + BondPin::Cfg(CfgPin::Tdo) => write!(f, "TDO")?, + BondPin::Cfg(CfgPin::PwrdwnB) => write!(f, "PWRDWN_B")?, + BondPin::Cfg(CfgPin::HswapEn) => write!(f, "HSWAP_EN")?, + BondPin::Cfg(CfgPin::Suspend) => write!(f, "SUSPEND")?, + BondPin::Dxn => write!(f, "DXN")?, + BondPin::Dxp => write!(f, "DXP")?, + BondPin::Rsvd => write!(f, "RSVD")?, + } + writeln!(f)?; + } + writeln!(f, "\tVREF:")?; + for v in &self.vref { + writeln!(f, "\t\t{v}")?; + } + Ok(()) + } +} diff --git a/prjcombine_virtex2/src/grid.rs b/prjcombine_virtex2/src/grid.rs index c72bf075..9a0b096f 100644 --- a/prjcombine_virtex2/src/grid.rs +++ b/prjcombine_virtex2/src/grid.rs @@ -710,3 +710,121 @@ impl Grid { }) } } + +impl std::fmt::Display for Grid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tKIND: {k:?}", k = self.kind)?; + writeln!(f, "\tCOLS:")?; + for (col, cd) in &self.columns { + if let Some((cl, cr)) = self.cols_clkv { + if col == cl { + writeln!(f, "\t\t--- clock left spine")?; + } + if col == cr { + writeln!(f, "\t\t--- clock right spine")?; + } + } + if col == self.col_clk { + writeln!(f, "\t\t--- clock spine")?; + } + write!(f, "\t\tX{c}: ", c = col.to_idx())?; + match cd.kind { + ColumnKind::Io => write!(f, "IO")?, + ColumnKind::Clb => write!(f, "CLB ")?, + ColumnKind::Bram => write!(f, "BRAM ")?, + ColumnKind::BramCont(i) => write!(f, "BRAM.{i}")?, + ColumnKind::Dsp => write!(f, "DSP ")?, + } + match cd.io { + ColumnIoKind::None => (), + ColumnIoKind::Single => write!(f, " IO: 1")?, + ColumnIoKind::Double(i) => write!(f, " IO: 2.{i}")?, + ColumnIoKind::Triple(i) => write!(f, " IO: 3.{i}")?, + ColumnIoKind::Quad(i) => write!(f, " IO: 4.{i}")?, + ColumnIoKind::SingleLeft => write!(f, " IO: 1L")?, + ColumnIoKind::SingleRight => write!(f, " IO: 1R")?, + ColumnIoKind::SingleLeftAlt => write!(f, " IO: 1LA")?, + ColumnIoKind::SingleRightAlt => write!(f, " IO: 1RA")?, + ColumnIoKind::DoubleLeft(i) => write!(f, " IO: 2L.{i}")?, + ColumnIoKind::DoubleRight(i) => write!(f, " IO: 2R.{i}")?, + ColumnIoKind::DoubleRightClk(i) => write!(f, " IO: 2R.CLK.{i}")?, + } + if let Some(&(bb, bt)) = self.cols_gt.get(&col) { + write!(f, " GT: BOT {bb} TOP {bt}")?; + } + writeln!(f,)?; + } + let mut clkv_idx = 0; + writeln!(f, "\tROWS:")?; + for (row, rd) in &self.rows { + if row == self.rows_hclk[clkv_idx].0 { + writeln!(f, "\t\t--- clock row")?; + } + if row == self.rows_hclk[clkv_idx].2 { + writeln!(f, "\t\t--- clock break")?; + clkv_idx += 1; + } + if Some(row) == self.row_pci { + writeln!(f, "\t\t--- PCI row")?; + } + if row == self.row_mid() { + writeln!(f, "\t\t--- spine row")?; + } + write!(f, "\t\tY{r}: ", r = row.to_idx())?; + match rd { + RowIoKind::None => (), + RowIoKind::Single => write!(f, " IO: 1")?, + RowIoKind::Double(i) => write!(f, " IO: 2.{i}")?, + RowIoKind::Triple(i) => write!(f, " IO: 3.{i}")?, + RowIoKind::Quad(i) => write!(f, " IO: 4.{i}")?, + RowIoKind::DoubleBot(i) => write!(f, " IO: 2B.{i}")?, + RowIoKind::DoubleTop(i) => write!(f, " IO: 2T.{i}")?, + } + if let Some((rb, rt)) = self.rows_ram { + if row == rb { + write!(f, " BRAM BOT TERM")?; + } + if row == rt { + write!(f, " BRAM TOP TERM")?; + } + } + writeln!(f,)?; + } + for &(col, row) in &self.holes_ppc { + writeln!( + f, + "\tPPC: X{xl}:X{xr} Y{yb}:Y{yt}", + xl = col.to_idx(), + xr = col.to_idx() + 10, + yb = row.to_idx(), + yt = row.to_idx() + 16 + )?; + } + if let Some(dcms) = self.dcms { + writeln!(f, "\tDCMS: {dcms:?}")?; + } + if self.has_ll { + writeln!(f, "\tHAS LL SPLITTERS")?; + } + writeln!(f, "\tHAS_SMALL_INT: {v:?}", v = self.has_small_int)?; + writeln!(f, "\tCFG PINS:")?; + for (k, v) in &self.cfg_io { + writeln!(f, "\t\t{k:?}: {v}")?; + } + if !self.dci_io.is_empty() { + writeln!(f, "\tDCI:")?; + for k in 0..8 { + writeln!(f, "\t\t{k}:")?; + if let Some(&(vp, vn)) = self.dci_io.get(&k) { + writeln!(f, "\t\t\tVP: {vp}")?; + writeln!(f, "\t\t\tVN: {vn}")?; + } + if let Some(&(vp, vn)) = self.dci_io_alt.get(&k) { + writeln!(f, "\t\t\tALT VP: {vp}")?; + writeln!(f, "\t\t\tALT VN: {vn}")?; + } + } + } + Ok(()) + } +} diff --git a/prjcombine_virtex4/Cargo.toml b/prjcombine_virtex4/Cargo.toml index 34dd8ed3..50ed25b7 100644 --- a/prjcombine_virtex4/Cargo.toml +++ b/prjcombine_virtex4/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +itertools.workspace = true serde_json.workspace = true zstd.workspace = true bincode.workspace = true diff --git a/prjcombine_virtex4/src/bond.rs b/prjcombine_virtex4/src/bond.rs index 1e018c94..6aa63993 100644 --- a/prjcombine_virtex4/src/bond.rs +++ b/prjcombine_virtex4/src/bond.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use serde::{Deserialize, Serialize}; use serde_json::json; use std::collections::BTreeMap; @@ -386,3 +387,172 @@ impl Bond { }) } } + +fn pad_sort_key(name: &str) -> (usize, &str, u32) { + let pos = name.find(|x: char| x.is_ascii_digit()).unwrap(); + (pos, &name[..pos], name[pos..].parse().unwrap()) +} + +impl std::fmt::Display for Bond { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tPINS:")?; + for (pin, pad) in self.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { + write!(f, "\t\t{pin:4}: ")?; + match pad { + BondPin::Io(bank, idx) => write!(f, "IOB_{bank}_{idx}")?, + BondPin::Gt(bank, gtpin) => { + write!(f, "GT{bank}.")?; + match gtpin { + GtPin::RxP(idx) => write!(f, "RXP{idx}")?, + GtPin::RxN(idx) => write!(f, "RXN{idx}")?, + GtPin::TxP(idx) => write!(f, "TXP{idx}")?, + GtPin::TxN(idx) => write!(f, "TXN{idx}")?, + GtPin::ClkP(idx) => write!(f, "CLKP{idx}")?, + GtPin::ClkN(idx) => write!(f, "CLKN{idx}")?, + GtPin::GndA => write!(f, "GNDA")?, + GtPin::AVccAuxTx => write!(f, "AVCCAUXTX")?, + GtPin::AVccAuxRx(idx) => write!(f, "AVCCAUXRX{idx}")?, + GtPin::AVccAuxMgt => write!(f, "AVCCAUXMGT")?, + GtPin::RTerm => write!(f, "RTERM")?, + GtPin::MgtVRef => write!(f, "MGTVREF")?, + GtPin::VtRx(idx) => write!(f, "VTRX{idx}")?, + GtPin::VtTx(idx) => write!(f, "VTTX{idx}")?, + GtPin::AVcc => write!(f, "AVCC")?, + GtPin::AVccPll => write!(f, "AVCCPLL")?, + GtPin::RRef => write!(f, "RREF")?, + GtPin::AVttRCal => write!(f, "AVTTRCAL")?, + GtPin::RBias => write!(f, "RBIAS")?, + } + } + BondPin::Gtz(bank, gtpin) => { + write!(f, "GTZ{bank}.")?; + match gtpin { + GtzPin::RxP(idx) => write!(f, "RXP{idx}")?, + GtzPin::RxN(idx) => write!(f, "RXN{idx}")?, + GtzPin::TxP(idx) => write!(f, "TXP{idx}")?, + GtzPin::TxN(idx) => write!(f, "TXN{idx}")?, + GtzPin::ClkP(idx) => write!(f, "CLKP{idx}")?, + GtzPin::ClkN(idx) => write!(f, "CLKN{idx}")?, + GtzPin::AGnd => write!(f, "AGND")?, + GtzPin::AVcc => write!(f, "AVCC")?, + GtzPin::VccH => write!(f, "VCCH")?, + GtzPin::VccL => write!(f, "VCCL")?, + GtzPin::ObsClkP => write!(f, "OBSCLKP")?, + GtzPin::ObsClkN => write!(f, "OBSCLKN")?, + GtzPin::ThermIn => write!(f, "THERM_IN")?, + GtzPin::ThermOut => write!(f, "THERM_OUT")?, + GtzPin::SenseAGnd => write!(f, "SENSE_AGND")?, + GtzPin::SenseGnd => write!(f, "SENSE_GND")?, + GtzPin::SenseGndL => write!(f, "SENSE_GNDL")?, + GtzPin::SenseAVcc => write!(f, "SENSE_AVCC")?, + GtzPin::SenseVcc => write!(f, "SENSE_VCC")?, + GtzPin::SenseVccL => write!(f, "SENSE_VCCL")?, + GtzPin::SenseVccH => write!(f, "SENSE_VCCH")?, + } + } + BondPin::GtRegion(region, gtpin) => { + write!(f, "GTREG")?; + match region { + GtRegion::All => (), + GtRegion::S => write!(f, "S")?, + GtRegion::N => write!(f, "N")?, + GtRegion::L => write!(f, "L")?, + GtRegion::R => write!(f, "R")?, + GtRegion::LS => write!(f, "LS")?, + GtRegion::RS => write!(f, "RS")?, + GtRegion::LN => write!(f, "LN")?, + GtRegion::RN => write!(f, "RN")?, + GtRegion::H => write!(f, "H")?, + GtRegion::LH => write!(f, "LH")?, + GtRegion::RH => write!(f, "RH")?, + GtRegion::Num(n) => write!(f, "{n}")?, + } + write!(f, ".")?; + match gtpin { + GtRegionPin::AVtt => write!(f, "AVTT")?, + GtRegionPin::AGnd => write!(f, "AGND")?, + GtRegionPin::AVcc => write!(f, "AVCC")?, + GtRegionPin::AVccRx => write!(f, "AVCCRX")?, + GtRegionPin::AVccPll => write!(f, "AVCCPLL")?, + GtRegionPin::AVttRxC => write!(f, "AVTTRXC")?, + GtRegionPin::VccAux => write!(f, "VCCAUX")?, + } + } + BondPin::Nc => write!(f, "NC")?, + BondPin::Gnd => write!(f, "GND")?, + BondPin::VccInt => write!(f, "VCCINT")?, + BondPin::VccAux => write!(f, "VCCAUX")?, + BondPin::VccAuxIo(idx) => write!(f, "VCCAUX_IO{idx}")?, + BondPin::VccBram => write!(f, "VCCBRAM")?, + BondPin::VccO(bank) => write!(f, "VCCO{bank}")?, + BondPin::VccBatt => write!(f, "VCC_BATT")?, + BondPin::Cfg(CfgPin::Cclk) => write!(f, "CCLK")?, + BondPin::Cfg(CfgPin::Done) => write!(f, "DONE")?, + BondPin::Cfg(CfgPin::M0) => write!(f, "M0")?, + BondPin::Cfg(CfgPin::M1) => write!(f, "M1")?, + BondPin::Cfg(CfgPin::M2) => write!(f, "M2")?, + BondPin::Cfg(CfgPin::ProgB) => write!(f, "PROG_B")?, + BondPin::Cfg(CfgPin::InitB) => write!(f, "INIT_B")?, + BondPin::Cfg(CfgPin::RdWrB) => write!(f, "RDWR_B")?, + BondPin::Cfg(CfgPin::CsiB) => write!(f, "CSI_B")?, + BondPin::Cfg(CfgPin::Tck) => write!(f, "TCK")?, + BondPin::Cfg(CfgPin::Tms) => write!(f, "TMS")?, + BondPin::Cfg(CfgPin::Tdi) => write!(f, "TDI")?, + BondPin::Cfg(CfgPin::Tdo) => write!(f, "TDO")?, + BondPin::Cfg(CfgPin::PwrdwnB) => write!(f, "PWRDWN_B")?, + BondPin::Cfg(CfgPin::HswapEn) => write!(f, "HSWAP_EN")?, + BondPin::Cfg(CfgPin::Din) => write!(f, "DIN")?, + BondPin::Cfg(CfgPin::Dout) => write!(f, "DOUT")?, + BondPin::Cfg(CfgPin::CfgBvs) => write!(f, "CFGBVS")?, + BondPin::Dxn => write!(f, "DXN")?, + BondPin::Dxp => write!(f, "DXP")?, + BondPin::Rsvd => write!(f, "RSVD")?, + BondPin::RsvdGnd => write!(f, "RSVDGND")?, + BondPin::Vfs => write!(f, "VFS")?, + BondPin::SysMon(bank, pin) => { + write!(f, "SYSMON{bank}.")?; + match pin { + SysMonPin::VP => write!(f, "VP")?, + SysMonPin::VN => write!(f, "VN")?, + SysMonPin::AVss => write!(f, "AVSS")?, + SysMonPin::AVdd => write!(f, "AVDD")?, + SysMonPin::VRefP => write!(f, "VREFP")?, + SysMonPin::VRefN => write!(f, "VREFN")?, + } + } + BondPin::VccPsInt => write!(f, "VCC_PS_INT")?, + BondPin::VccPsAux => write!(f, "VCC_PS_AUX")?, + BondPin::VccPsPll => write!(f, "VCC_PS_PLL")?, + BondPin::PsVref(bank, idx) => write!(f, "PS{bank}.VREF{idx}")?, + BondPin::PsIo(bank, pin) => { + write!(f, "PS{bank}.")?; + match pin { + PsPin::Mio(i) => write!(f, "MIO{i}")?, + PsPin::Clk => write!(f, "CLK")?, + PsPin::PorB => write!(f, "POR_B")?, + PsPin::SrstB => write!(f, "SRST_B")?, + PsPin::DdrDq(i) => write!(f, "DDR_DQ{i}")?, + PsPin::DdrDm(i) => write!(f, "DDR_DM{i}")?, + PsPin::DdrDqsP(i) => write!(f, "DDR_DQS_P{i}")?, + PsPin::DdrDqsN(i) => write!(f, "DDR_DQS_N{i}")?, + PsPin::DdrA(i) => write!(f, "DDR_A{i}")?, + PsPin::DdrBa(i) => write!(f, "DDR_BA{i}")?, + PsPin::DdrVrP => write!(f, "DDR_VRP")?, + PsPin::DdrVrN => write!(f, "DDR_VRN")?, + PsPin::DdrCkP => write!(f, "DDR_CKP")?, + PsPin::DdrCkN => write!(f, "DDR_CKN")?, + PsPin::DdrCke => write!(f, "DDR_CKE")?, + PsPin::DdrOdt => write!(f, "DDR_ODT")?, + PsPin::DdrDrstB => write!(f, "DDR_DRST_B")?, + PsPin::DdrCsB => write!(f, "DDR_CS_B")?, + PsPin::DdrRasB => write!(f, "DDR_RAS_B")?, + PsPin::DdrCasB => write!(f, "DDR_CAS_B")?, + PsPin::DdrWeB => write!(f, "DDR_WE_B")?, + } + } + } + writeln!(f)?; + } + Ok(()) + } +} diff --git a/prjcombine_virtex4/src/grid.rs b/prjcombine_virtex4/src/grid.rs index a9247ae8..ce0b3d4d 100644 --- a/prjcombine_virtex4/src/grid.rs +++ b/prjcombine_virtex4/src/grid.rs @@ -286,3 +286,131 @@ impl Grid { }) } } + +impl std::fmt::Display for Grid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "\tKIND: {v:?}", v = self.kind)?; + if self.has_ps { + writeln!(f, "\tHAS PS")?; + } + if self.has_slr { + writeln!(f, "\tHAS SLR")?; + } + if self.has_no_tbuturn { + writeln!(f, "\tHAS NO TB UTURN")?; + } + writeln!(f, "\tCOLS:")?; + for (col, &cd) in &self.columns { + if self.cols_vbrk.contains(&col) { + writeln!(f, "\t\t--- break")?; + } + write!(f, "\t\tX{c}: ", c = col.to_idx())?; + match cd { + ColumnKind::Io => write!(f, "IO")?, + ColumnKind::ClbLL => write!(f, "CLBLL")?, + ColumnKind::ClbLM => write!(f, "CLBLM")?, + ColumnKind::Bram => write!(f, "BRAM")?, + ColumnKind::Dsp => write!(f, "DSP")?, + ColumnKind::Gt => write!(f, "GT")?, + ColumnKind::Cmt => write!(f, "CMT")?, + ColumnKind::Clk => write!(f, "CLK")?, + ColumnKind::Cfg => write!(f, "CFG")?, + } + if self.cols_mgt_buf.contains(&col) { + write!(f, " MGT_BUF")?; + } + if let Some((cl, cr)) = self.cols_qbuf { + if col == cl || col == cr { + write!(f, " QBUF")?; + } + } + writeln!(f)?; + if let Some(ref hard) = self.col_hard { + if hard.col == col { + for &row in &hard.rows_pcie { + writeln!(f, "\t\t\tY{y}: PCIE", y = row.to_idx())?; + } + for &row in &hard.rows_emac { + writeln!(f, "\t\t\tY{y}: EMAC", y = row.to_idx())?; + } + } + } + for ioc in &self.cols_io { + if ioc.col == col { + for (reg, kind) in &ioc.regs { + if let Some(kind) = kind { + writeln!( + f, + "\t\t\tY{y}: {kind:?}", + y = self.row_reg_bot(reg).to_idx() + )?; + } + } + } + } + for gtc in &self.cols_gt { + if gtc.col == col { + let mid = if gtc.is_middle { "MID " } else { "" }; + for (reg, kind) in >c.regs { + if let Some(kind) = kind { + writeln!( + f, + "\t\t\tY{y}: {mid}{kind:?}", + y = self.row_reg_bot(reg).to_idx() + )?; + } + } + } + } + if cd == ColumnKind::Cfg { + for &(row, kind) in &self.rows_cfg { + writeln!(f, "\t\t\tY{y}: {kind:?}", y = row.to_idx())?; + } + } + } + writeln!(f, "\tREGS: {r}", r = self.regs)?; + writeln!(f, "\tCFG REG: {v:?}", v = self.reg_cfg.to_idx())?; + writeln!(f, "\tCLK REG: {v:?}", v = self.reg_clk.to_idx())?; + for &(col, row) in &self.holes_ppc { + let (col_r, row_t): (ColId, RowId) = match self.kind { + GridKind::Virtex4 => (col + 9, row + 24), + GridKind::Virtex5 => (col + 14, row + 40), + _ => unreachable!(), + }; + writeln!( + f, + "\tPPC: X{xl}:X{xr} Y{yb}:Y{yt}", + xl = col.to_idx(), + xr = col_r.to_idx(), + yb = row.to_idx(), + yt = row_t.to_idx(), + )?; + } + for pcie in &self.holes_pcie2 { + writeln!( + f, + "\tPCIE2.{lr}: X{xl}:X{xr} Y{yb}:Y{yt}", + lr = match pcie.kind { + Pcie2Kind::Left => 'L', + Pcie2Kind::Right => 'R', + }, + xl = pcie.col.to_idx(), + xr = pcie.col.to_idx() + 4, + yb = pcie.row.to_idx(), + yt = pcie.row.to_idx() + 25 + )?; + } + for &(col, row) in &self.holes_pcie3 { + writeln!( + f, + "\tPCIE3: X{xl}:X{xr} Y{yb}:Y{yt}", + xl = col.to_idx(), + xr = col.to_idx() + 6, + yb = row.to_idx(), + yt = row.to_idx() + 50 + )?; + } + writeln!(f, "\tHAS BRAM_FX: {v:?}", v = self.has_bram_fx)?; + Ok(()) + } +} diff --git a/prjcombine_xact_data/src/die.rs b/prjcombine_xact_data/src/die.rs index 8f7236e5..8a736869 100644 --- a/prjcombine_xact_data/src/die.rs +++ b/prjcombine_xact_data/src/die.rs @@ -865,10 +865,16 @@ impl Die { assert_eq!(num_prims, prims.len()); assert_eq!(num_primdefs, primdefs.len()); assert_eq!(num_boxdefs, boxdefs.len()); - assert_eq!(num_pins, prims.values().map(|prim| prim.pins.len()).sum::()); + assert_eq!( + num_pins, + prims.values().map(|prim| prim.pins.len()).sum::() + ); assert_eq!( num_pindefs, - primdefs.values().map(|primdef| primdef.pins.len()).sum::() + primdefs + .values() + .map(|primdef| primdef.pins.len()) + .sum::() ); assert_eq!(num_tile_cols * num_tile_rows, num_tiles); if is_tiled { diff --git a/prjcombine_xc2000/src/grid.rs b/prjcombine_xc2000/src/grid.rs index ec48d7ad..03dba9f0 100644 --- a/prjcombine_xc2000/src/grid.rs +++ b/prjcombine_xc2000/src/grid.rs @@ -338,13 +338,7 @@ impl Display for Grid { writeln!(f)?; writeln!(f, "\tCFG PINS:")?; for (k, v) in &self.cfg_io { - writeln!( - f, - "\t\t{k:?}: IOB_X{x}Y{y}B{b}", - x = v.col, - y = v.row, - b = v.iob - )?; + writeln!(f, "\t\t{k:?}: {v}")?; } Ok(()) } diff --git a/prjcombine_xilinx_finish/src/spartan6.rs b/prjcombine_xilinx_finish/src/spartan6.rs index f651f436..eb3dbf60 100644 --- a/prjcombine_xilinx_finish/src/spartan6.rs +++ b/prjcombine_xilinx_finish/src/spartan6.rs @@ -1,11 +1,11 @@ use std::collections::{btree_map, BTreeMap, BTreeSet}; -use prjcombine_types::tiledb::TileDb; use prjcombine_spartan6::{ bond::Bond, db::{Database, DeviceCombo, Part}, grid::{DisabledPart, Grid}, }; +use prjcombine_types::tiledb::TileDb; use prjcombine_xilinx_geom::GeomDb; use unnamed_entity::{EntityMap, EntitySet, EntityVec}; diff --git a/prjcombine_xilinx_geom/src/bin/xgprint.rs b/prjcombine_xilinx_geom/src/bin/xgprint.rs index 5f879e03..9851e798 100644 --- a/prjcombine_xilinx_geom/src/bin/xgprint.rs +++ b/prjcombine_xilinx_geom/src/bin/xgprint.rs @@ -1,5 +1,5 @@ use clap::Parser; -use prjcombine_xilinx_geom::{Bond, DeviceNaming, GeomDb, Grid}; +use prjcombine_xilinx_geom::{DeviceNaming, GeomDb}; use std::{error::Error, path::PathBuf}; #[derive(Debug, Parser)] @@ -23,1333 +23,6 @@ pub fn pad_sort_key(name: &str) -> (usize, &str, u32) { (pos, &name[..pos], name[pos..].parse().unwrap()) } -mod virtex { - use itertools::Itertools; - use prjcombine_virtex::{ - bond::{Bond, BondPin, CfgPin}, - grid::Grid, - }; - use unnamed_entity::EntityId; - - use crate::pad_sort_key; - - pub fn print_grid(grid: &Grid) { - println!("\tKIND: {k:?}", k = grid.kind); - println!("\tDIMS: {c}×{r}", c = grid.columns, r = grid.rows); - println!("\tCOLS:"); - let mut clkv_idx = 0; - for col in grid.columns() { - if col == grid.cols_clkv[clkv_idx].0 { - println!("\t\t--- clock column"); - } - if col == grid.cols_clkv[clkv_idx].2 { - println!("\t\t--- clock break"); - clkv_idx += 1; - } - println!( - "\t\tX{c}: {kind}", - c = col.to_idx(), - kind = if grid.cols_bram.contains(&col) { - "BRAM" - } else if col == grid.col_lio() { - "LIO" - } else if col == grid.col_rio() { - "RIO" - } else { - "CLB" - } - ); - } - println!("\tCFG PINS:"); - for (k, v) in &grid.cfg_io { - println!( - "\t\t{k:?}: IOB_X{x}Y{y}B{b}", - x = v.col.to_idx(), - y = v.row.to_idx(), - b = v.iob.to_idx() - ); - } - } - - pub fn print_bond(bond: &Bond) { - println!("\tBANKS:"); - for (k, v) in &bond.io_banks { - println!("\t\t{k}: {v}"); - } - println!("\tPINS:"); - for (pin, pad) in bond.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { - print!("\t\t{pin:4}: "); - match pad { - BondPin::Io(io) => print!("IOB_X{x}Y{y}B{b}", x = io.col, y = io.row, b = io.iob), - BondPin::Clk(idx) => print!("CLK{idx}"), - BondPin::Nc => print!("NC"), - BondPin::Gnd => print!("GND"), - BondPin::VccInt => print!("VCCINT"), - BondPin::VccAux => print!("VCCAUX"), - BondPin::VccO(bank) => print!("VCCO{bank}"), - BondPin::Cfg(CfgPin::Cclk) => print!("CCLK"), - BondPin::Cfg(CfgPin::Done) => print!("DONE"), - BondPin::Cfg(CfgPin::M0) => print!("M0"), - BondPin::Cfg(CfgPin::M1) => print!("M1"), - BondPin::Cfg(CfgPin::M2) => print!("M2"), - BondPin::Cfg(CfgPin::ProgB) => print!("PROG_B"), - BondPin::Cfg(CfgPin::Tck) => print!("TCK"), - BondPin::Cfg(CfgPin::Tms) => print!("TMS"), - BondPin::Cfg(CfgPin::Tdi) => print!("TDI"), - BondPin::Cfg(CfgPin::Tdo) => print!("TDO"), - BondPin::Dxn => print!("DXN"), - BondPin::Dxp => print!("DXP"), - } - println!(); - } - println!("\tVREF:"); - for v in &bond.vref { - println!( - "\t\tIOB_X{x}Y{y}B{b}", - x = v.col.to_idx(), - y = v.row.to_idx(), - b = v.iob.to_idx() - ); - } - println!("\tDIFFP:"); - for v in &bond.diffp { - println!( - "\t\tIOB_X{x}Y{y}B{b}", - x = v.col.to_idx(), - y = v.row.to_idx(), - b = v.iob.to_idx() - ); - } - println!("\tDIFFN:"); - for v in &bond.diffn { - println!( - "\t\tIOB_X{x}Y{y}B{b}", - x = v.col.to_idx(), - y = v.row.to_idx(), - b = v.iob.to_idx() - ); - } - } -} - -mod virtex2 { - use itertools::Itertools; - use prjcombine_virtex2::{ - bond::{Bond, BondPin, CfgPin, GtPin}, - grid::{ColumnIoKind, ColumnKind, Grid, RowIoKind}, - }; - use unnamed_entity::EntityId; - - use crate::pad_sort_key; - - pub fn print_grid(grid: &Grid) { - println!("\tKIND: {k:?}", k = grid.kind); - println!("\tCOLS:"); - for (col, cd) in &grid.columns { - if let Some((cl, cr)) = grid.cols_clkv { - if col == cl { - println!("\t\t--- clock left spine"); - } - if col == cr { - println!("\t\t--- clock right spine"); - } - } - if col == grid.col_clk { - println!("\t\t--- clock spine"); - } - print!("\t\tX{c}: ", c = col.to_idx()); - match cd.kind { - ColumnKind::Io => print!("IO"), - ColumnKind::Clb => print!("CLB "), - ColumnKind::Bram => print!("BRAM "), - ColumnKind::BramCont(i) => print!("BRAM.{i}"), - ColumnKind::Dsp => print!("DSP "), - } - match cd.io { - ColumnIoKind::None => (), - ColumnIoKind::Single => print!(" IO: 1"), - ColumnIoKind::Double(i) => print!(" IO: 2.{i}"), - ColumnIoKind::Triple(i) => print!(" IO: 3.{i}"), - ColumnIoKind::Quad(i) => print!(" IO: 4.{i}"), - ColumnIoKind::SingleLeft => print!(" IO: 1L"), - ColumnIoKind::SingleRight => print!(" IO: 1R"), - ColumnIoKind::SingleLeftAlt => print!(" IO: 1LA"), - ColumnIoKind::SingleRightAlt => print!(" IO: 1RA"), - ColumnIoKind::DoubleLeft(i) => print!(" IO: 2L.{i}"), - ColumnIoKind::DoubleRight(i) => print!(" IO: 2R.{i}"), - ColumnIoKind::DoubleRightClk(i) => print!(" IO: 2R.CLK.{i}"), - } - if let Some(&(bb, bt)) = grid.cols_gt.get(&col) { - print!(" GT: BOT {bb} TOP {bt}"); - } - println!(); - } - let mut clkv_idx = 0; - println!("\tROWS:"); - for (row, rd) in &grid.rows { - if row == grid.rows_hclk[clkv_idx].0 { - println!("\t\t--- clock row"); - } - if row == grid.rows_hclk[clkv_idx].2 { - println!("\t\t--- clock break"); - clkv_idx += 1; - } - if Some(row) == grid.row_pci { - println!("\t\t--- PCI row"); - } - if row == grid.row_mid() { - println!("\t\t--- spine row"); - } - print!("\t\tY{r}: ", r = row.to_idx()); - match rd { - RowIoKind::None => (), - RowIoKind::Single => print!(" IO: 1"), - RowIoKind::Double(i) => print!(" IO: 2.{i}"), - RowIoKind::Triple(i) => print!(" IO: 3.{i}"), - RowIoKind::Quad(i) => print!(" IO: 4.{i}"), - RowIoKind::DoubleBot(i) => print!(" IO: 2B.{i}"), - RowIoKind::DoubleTop(i) => print!(" IO: 2T.{i}"), - } - if let Some((rb, rt)) = grid.rows_ram { - if row == rb { - print!(" BRAM BOT TERM"); - } - if row == rt { - print!(" BRAM TOP TERM"); - } - } - println!(); - } - for &(col, row) in &grid.holes_ppc { - println!( - "\tPPC: X{xl}:X{xr} Y{yb}:Y{yt}", - xl = col.to_idx(), - xr = col.to_idx() + 10, - yb = row.to_idx(), - yt = row.to_idx() + 16 - ); - } - if let Some(dcms) = grid.dcms { - println!("\tDCMS: {dcms:?}"); - } - if grid.has_ll { - println!("\tHAS LL SPLITTERS"); - } - println!("\tHAS_SMALL_INT: {v:?}", v = grid.has_small_int); - println!("\tCFG PINS:"); - for (k, v) in &grid.cfg_io { - println!( - "\t\t{k:?}: IOB_X{x}Y{y}B{b}", - x = v.col.to_idx(), - y = v.row.to_idx(), - b = v.iob.to_idx() - ); - } - if !grid.dci_io.is_empty() { - println!("\tDCI:"); - for k in 0..8 { - println!("\t\t{k}:"); - if let Some(&(vp, vn)) = grid.dci_io.get(&k) { - println!( - "\t\t\tVP: X{x}Y{y}B{b}", - x = vp.col.to_idx(), - y = vp.row.to_idx(), - b = vp.iob.to_idx() - ); - println!( - "\t\t\tVN: X{x}Y{y}B{b}", - x = vn.col.to_idx(), - y = vn.row.to_idx(), - b = vn.iob.to_idx() - ); - } - if let Some(&(vp, vn)) = grid.dci_io_alt.get(&k) { - println!( - "\t\t\tALT VP: X{x}Y{y}B{b}", - x = vp.col.to_idx(), - y = vp.row.to_idx(), - b = vp.iob.to_idx() - ); - println!( - "\t\t\tALT VN: X{x}Y{y}B{b}", - x = vn.col.to_idx(), - y = vn.row.to_idx(), - b = vn.iob.to_idx() - ); - } - } - } - } - - pub fn print_bond(bond: &Bond) { - println!("\tBANKS:"); - for (k, v) in &bond.io_banks { - println!("\t\t{k}: {v}"); - } - println!("\tPINS:"); - for (pin, pad) in bond.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { - print!("\t\t{pin:4}: "); - match pad { - BondPin::Io(io) => print!("IOB_X{x}Y{y}B{b}", x = io.col, y = io.row, b = io.iob), - BondPin::Gt(bank, gtpin) => { - print!("GT{bank}."); - match gtpin { - GtPin::RxP => print!("RXP"), - GtPin::RxN => print!("RXN"), - GtPin::TxP => print!("TXP"), - GtPin::TxN => print!("TXN"), - GtPin::GndA => print!("GNDA"), - GtPin::VtRx => print!("VTRX"), - GtPin::VtTx => print!("VTTX"), - GtPin::AVccAuxRx => print!("AVCCAUXRX"), - GtPin::AVccAuxTx => print!("AVCCAUXTX"), - } - } - BondPin::Nc => print!("NC"), - BondPin::Gnd => print!("GND"), - BondPin::VccInt => print!("VCCINT"), - BondPin::VccAux => print!("VCCAUX"), - BondPin::VccO(bank) => print!("VCCO{bank}"), - BondPin::VccBatt => print!("VCC_BATT"), - BondPin::Cfg(CfgPin::Cclk) => print!("CCLK"), - BondPin::Cfg(CfgPin::Done) => print!("DONE"), - BondPin::Cfg(CfgPin::M0) => print!("M0"), - BondPin::Cfg(CfgPin::M1) => print!("M1"), - BondPin::Cfg(CfgPin::M2) => print!("M2"), - BondPin::Cfg(CfgPin::ProgB) => print!("PROG_B"), - BondPin::Cfg(CfgPin::Tck) => print!("TCK"), - BondPin::Cfg(CfgPin::Tms) => print!("TMS"), - BondPin::Cfg(CfgPin::Tdi) => print!("TDI"), - BondPin::Cfg(CfgPin::Tdo) => print!("TDO"), - BondPin::Cfg(CfgPin::PwrdwnB) => print!("PWRDWN_B"), - BondPin::Cfg(CfgPin::HswapEn) => print!("HSWAP_EN"), - BondPin::Cfg(CfgPin::Suspend) => print!("SUSPEND"), - BondPin::Dxn => print!("DXN"), - BondPin::Dxp => print!("DXP"), - BondPin::Rsvd => print!("RSVD"), - } - println!(); - } - println!("\tVREF:"); - for v in &bond.vref { - println!( - "\t\tIOB_X{x}Y{y}B{b}", - x = v.col.to_idx(), - y = v.row.to_idx(), - b = v.iob.to_idx() - ); - } - } -} - -mod spartan6 { - use itertools::Itertools; - use prjcombine_spartan6::{ - bond::{Bond, BondPin, CfgPin, GtPin}, - grid::{ColumnIoKind, ColumnKind, Grid, Gts}, - }; - use unnamed_entity::EntityId; - - use crate::pad_sort_key; - - pub fn print_grid(grid: &Grid) { - println!("\tKIND: Spartan6"); - println!("\tCOLS:"); - for (col, cd) in &grid.columns { - print!("\t\tX{c}: ", c = col.to_idx()); - match cd.kind { - ColumnKind::Io => print!("IO"), - ColumnKind::CleXL => print!("CLEXL"), - ColumnKind::CleXM => print!("CLEXM"), - ColumnKind::CleClk => print!("CLEXL+CLK"), - ColumnKind::Bram => print!("BRAM"), - ColumnKind::Dsp => print!("DSP"), - ColumnKind::DspPlus => print!("DSP*"), - } - match cd.bio { - ColumnIoKind::None => (), - ColumnIoKind::Inner => print!(" BIO: I-"), - ColumnIoKind::Outer => print!(" BIO: -O"), - ColumnIoKind::Both => print!(" BIO: IO"), - } - match cd.tio { - ColumnIoKind::None => (), - ColumnIoKind::Inner => print!(" TIO: I-"), - ColumnIoKind::Outer => print!(" TIO: -O"), - ColumnIoKind::Both => print!(" TIO: IO"), - } - if let Some((cl, cr)) = grid.cols_clk_fold { - if col == cl || col == cr { - print!(" FOLD"); - } - } - if col == grid.cols_reg_buf.0 || col == grid.cols_reg_buf.1 { - print!(" REGBUF"); - } - if let Gts::Single(cl) | Gts::Double(cl, _) | Gts::Quad(cl, _) = grid.gts { - if col == cl { - print!(" LGT"); - } - } - if let Gts::Double(_, cr) | Gts::Quad(_, cr) = grid.gts { - if col == cr { - print!(" RGT"); - } - } - println!(); - } - println!("\tROWS:"); - for (row, rd) in &grid.rows { - if row.to_idx() != 0 && row.to_idx() % 16 == 0 { - println!("\t\t--- clock break"); - } - if row.to_idx() % 16 == 8 { - println!("\t\t--- clock row"); - } - if row == grid.row_clk() { - println!("\t\t--- spine row"); - } - if let Some((rl, rr)) = grid.rows_bank_split { - if row == rl { - println!("\t\t--- left bank split"); - } - if row == rr { - println!("\t\t--- right bank split"); - } - } - if Some(row) == grid.row_mcb_split { - println!("\t\t--- MCB split"); - } - print!("\t\tY{r}: ", r = row.to_idx()); - if rd.lio { - print!(" LIO"); - } - if rd.rio { - print!(" RIO"); - } - if row == grid.rows_midbuf.0 || row == grid.rows_midbuf.1 { - print!(" MIDBUF"); - } - if row == grid.rows_hclkbuf.0 || row == grid.rows_hclkbuf.1 { - print!(" HCLKBUF"); - } - for (i, mcb) in grid.mcbs.iter().enumerate() { - if row == mcb.row_mcb { - print!(" MCB{i}.MCB"); - } - for (j, &r) in mcb.row_mui.iter().enumerate() { - if row == r { - print!(" MCB{i}.MUI{j}"); - } - } - for (j, &r) in mcb.iop_dq.iter().enumerate() { - if row == r { - print!(" MCB{i}.DQ({jj0},{jj1})", jj0 = j * 2, jj1 = j * 2 + 1); - } - } - for (j, &r) in mcb.iop_dqs.iter().enumerate() { - if row == r { - print!(" MCB{i}.DQS{j}"); - } - } - if row == mcb.iop_clk { - print!(" MCB{i}.CLK"); - } - let mut pins: [Option<&'static str>; 2] = [None, None]; - for (pin, io) in [ - ("DM0", mcb.io_dm[0]), - ("DM1", mcb.io_dm[1]), - ("A0", mcb.io_addr[0]), - ("A1", mcb.io_addr[1]), - ("A2", mcb.io_addr[2]), - ("A3", mcb.io_addr[3]), - ("A4", mcb.io_addr[4]), - ("A5", mcb.io_addr[5]), - ("A6", mcb.io_addr[6]), - ("A7", mcb.io_addr[7]), - ("A8", mcb.io_addr[8]), - ("A9", mcb.io_addr[9]), - ("A10", mcb.io_addr[10]), - ("A11", mcb.io_addr[11]), - ("A12", mcb.io_addr[12]), - ("A13", mcb.io_addr[13]), - ("A14", mcb.io_addr[14]), - ("BA0", mcb.io_ba[0]), - ("BA1", mcb.io_ba[1]), - ("BA2", mcb.io_ba[2]), - ("RAS", mcb.io_ras), - ("CAS", mcb.io_cas), - ("WE", mcb.io_we), - ("ODT", mcb.io_odt), - ("CKE", mcb.io_cke), - ("RST", mcb.io_reset), - ] { - if row == io.row { - pins[io.iob.to_idx()] = Some(pin); - } - } - if pins.iter().any(|x| x.is_some()) { - print!( - " MCB{i}.({p0},{p1})", - p0 = pins[0].unwrap(), - p1 = pins[1].unwrap() - ); - } - } - println!(); - } - match grid.gts { - Gts::None => (), - Gts::Single(..) => println!("\tGTS: SINGLE"), - Gts::Double(..) => println!("\tGTS: DOUBLE"), - Gts::Quad(..) => println!("\tGTS: QUAD"), - } - println!("\tCFG PINS:"); - for (k, v) in &grid.cfg_io { - println!( - "\t\t{k:?}: IOB_X{x}Y{y}B{b}", - x = v.col.to_idx(), - y = v.row.to_idx(), - b = v.iob.to_idx() - ); - } - if grid.has_encrypt { - println!("\tHAS ENCRYPT"); - } - } - - pub fn print_bond(bond: &Bond) { - println!("\tBANKS:"); - for (k, v) in &bond.io_banks { - println!("\t\t{k}: {v}"); - } - println!("\tPINS:"); - for (pin, pad) in bond.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { - print!("\t\t{pin:4}: "); - match pad { - BondPin::Io(io) => print!("IOB_X{x}Y{y}B{b}", x = io.col, y = io.row, b = io.iob), - BondPin::Gt(bank, gtpin) => { - print!("GT{bank}."); - match gtpin { - GtPin::RxP(idx) => print!("RXP{idx}"), - GtPin::RxN(idx) => print!("RXN{idx}"), - GtPin::TxP(idx) => print!("TXP{idx}"), - GtPin::TxN(idx) => print!("TXN{idx}"), - GtPin::VtRx => print!("VTRX"), - GtPin::VtTx => print!("VTTX"), - GtPin::ClkP(idx) => print!("CLKP{idx}"), - GtPin::ClkN(idx) => print!("CLKN{idx}"), - GtPin::AVcc => print!("AVCC"), - GtPin::AVccPll(idx) => print!("AVCCPLL{idx}"), - GtPin::RRef => print!("RREF"), - GtPin::AVttRCal => print!("AVTTRCAL"), - } - } - BondPin::Nc => print!("NC"), - BondPin::Gnd => print!("GND"), - BondPin::VccInt => print!("VCCINT"), - BondPin::VccAux => print!("VCCAUX"), - BondPin::VccO(bank) => print!("VCCO{bank}"), - BondPin::VccBatt => print!("VCC_BATT"), - BondPin::Cfg(CfgPin::Done) => print!("DONE"), - BondPin::Cfg(CfgPin::ProgB) => print!("PROG_B"), - BondPin::Cfg(CfgPin::Tck) => print!("TCK"), - BondPin::Cfg(CfgPin::Tms) => print!("TMS"), - BondPin::Cfg(CfgPin::Tdi) => print!("TDI"), - BondPin::Cfg(CfgPin::Tdo) => print!("TDO"), - BondPin::Cfg(CfgPin::Suspend) => print!("SUSPEND"), - BondPin::Cfg(CfgPin::CmpCsB) => print!("CMPCS_B"), - BondPin::Vfs => print!("VFS"), - BondPin::RFuse => print!("RFUSE"), - } - println!(); - } - println!("\tVREF:"); - for v in &bond.vref { - println!( - "\t\tIOB_X{x}Y{y}B{b}", - x = v.col.to_idx(), - y = v.row.to_idx(), - b = v.iob.to_idx() - ); - } - } -} - -mod virtex4 { - use itertools::Itertools; - use prjcombine_int::grid::{ColId, RowId}; - use prjcombine_virtex4::{ - bond::{Bond, BondPin, CfgPin, GtPin, GtRegion, GtRegionPin, GtzPin, PsPin, SysMonPin}, - grid::{ColumnKind, Grid, GridKind, Pcie2Kind}, - }; - use unnamed_entity::EntityId; - - use crate::pad_sort_key; - - pub fn print_grid(grid: &Grid) { - println!("\tKIND: {v:?}", v = grid.kind); - if grid.has_ps { - println!("\tHAS PS"); - } - if grid.has_slr { - println!("\tHAS SLR"); - } - if grid.has_no_tbuturn { - println!("\tHAS NO TB UTURN"); - } - println!("\tCOLS:"); - for (col, &cd) in &grid.columns { - if grid.cols_vbrk.contains(&col) { - println!("\t\t--- break"); - } - print!("\t\tX{c}: ", c = col.to_idx()); - match cd { - ColumnKind::Io => print!("IO"), - ColumnKind::ClbLL => print!("CLBLL"), - ColumnKind::ClbLM => print!("CLBLM"), - ColumnKind::Bram => print!("BRAM"), - ColumnKind::Dsp => print!("DSP"), - ColumnKind::Gt => print!("GT"), - ColumnKind::Cmt => print!("CMT"), - ColumnKind::Clk => print!("CLK"), - ColumnKind::Cfg => print!("CFG"), - } - if grid.cols_mgt_buf.contains(&col) { - print!(" MGT_BUF"); - } - if let Some((cl, cr)) = grid.cols_qbuf { - if col == cl || col == cr { - print!(" QBUF"); - } - } - println!(); - if let Some(ref hard) = grid.col_hard { - if hard.col == col { - for &row in &hard.rows_pcie { - println!("\t\t\tY{y}: PCIE", y = row.to_idx()); - } - for &row in &hard.rows_emac { - println!("\t\t\tY{y}: EMAC", y = row.to_idx()); - } - } - } - for ioc in &grid.cols_io { - if ioc.col == col { - for (reg, kind) in &ioc.regs { - if let Some(kind) = kind { - println!("\t\t\tY{y}: {kind:?}", y = grid.row_reg_bot(reg).to_idx()); - } - } - } - } - for gtc in &grid.cols_gt { - if gtc.col == col { - let mid = if gtc.is_middle { "MID " } else { "" }; - for (reg, kind) in >c.regs { - if let Some(kind) = kind { - println!( - "\t\t\tY{y}: {mid}{kind:?}", - y = grid.row_reg_bot(reg).to_idx() - ); - } - } - } - } - if cd == ColumnKind::Cfg { - for &(row, kind) in &grid.rows_cfg { - println!("\t\t\tY{y}: {kind:?}", y = row.to_idx()); - } - } - } - println!("\tREGS: {r}", r = grid.regs); - println!("\tCFG REG: {v:?}", v = grid.reg_cfg.to_idx()); - println!("\tCLK REG: {v:?}", v = grid.reg_clk.to_idx()); - for &(col, row) in &grid.holes_ppc { - let (col_r, row_t): (ColId, RowId) = match grid.kind { - GridKind::Virtex4 => (col + 9, row + 24), - GridKind::Virtex5 => (col + 14, row + 40), - _ => unreachable!(), - }; - println!( - "\tPPC: X{xl}:X{xr} Y{yb}:Y{yt}", - xl = col.to_idx(), - xr = col_r.to_idx(), - yb = row.to_idx(), - yt = row_t.to_idx(), - ); - } - for pcie in &grid.holes_pcie2 { - println!( - "\tPCIE2.{lr}: X{xl}:X{xr} Y{yb}:Y{yt}", - lr = match pcie.kind { - Pcie2Kind::Left => 'L', - Pcie2Kind::Right => 'R', - }, - xl = pcie.col.to_idx(), - xr = pcie.col.to_idx() + 4, - yb = pcie.row.to_idx(), - yt = pcie.row.to_idx() + 25 - ); - } - for &(col, row) in &grid.holes_pcie3 { - println!( - "\tPCIE3: X{xl}:X{xr} Y{yb}:Y{yt}", - xl = col.to_idx(), - xr = col.to_idx() + 6, - yb = row.to_idx(), - yt = row.to_idx() + 50 - ); - } - println!("\tHAS BRAM_FX: {v:?}", v = grid.has_bram_fx); - } - - pub fn print_bond(bond: &Bond) { - println!("\tPINS:"); - for (pin, pad) in bond.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { - print!("\t\t{pin:4}: "); - match pad { - BondPin::Io(bank, idx) => print!("IOB_{bank}_{idx}"), - BondPin::Gt(bank, gtpin) => { - print!("GT{bank}."); - match gtpin { - GtPin::RxP(idx) => print!("RXP{idx}"), - GtPin::RxN(idx) => print!("RXN{idx}"), - GtPin::TxP(idx) => print!("TXP{idx}"), - GtPin::TxN(idx) => print!("TXN{idx}"), - GtPin::ClkP(idx) => print!("CLKP{idx}"), - GtPin::ClkN(idx) => print!("CLKN{idx}"), - GtPin::GndA => print!("GNDA"), - GtPin::AVccAuxTx => print!("AVCCAUXTX"), - GtPin::AVccAuxRx(idx) => print!("AVCCAUXRX{idx}"), - GtPin::AVccAuxMgt => print!("AVCCAUXMGT"), - GtPin::RTerm => print!("RTERM"), - GtPin::MgtVRef => print!("MGTVREF"), - GtPin::VtRx(idx) => print!("VTRX{idx}"), - GtPin::VtTx(idx) => print!("VTTX{idx}"), - GtPin::AVcc => print!("AVCC"), - GtPin::AVccPll => print!("AVCCPLL"), - GtPin::RRef => print!("RREF"), - GtPin::AVttRCal => print!("AVTTRCAL"), - GtPin::RBias => print!("RBIAS"), - } - } - BondPin::Gtz(bank, gtpin) => { - print!("GTZ{bank}."); - match gtpin { - GtzPin::RxP(idx) => print!("RXP{idx}"), - GtzPin::RxN(idx) => print!("RXN{idx}"), - GtzPin::TxP(idx) => print!("TXP{idx}"), - GtzPin::TxN(idx) => print!("TXN{idx}"), - GtzPin::ClkP(idx) => print!("CLKP{idx}"), - GtzPin::ClkN(idx) => print!("CLKN{idx}"), - GtzPin::AGnd => print!("AGND"), - GtzPin::AVcc => print!("AVCC"), - GtzPin::VccH => print!("VCCH"), - GtzPin::VccL => print!("VCCL"), - GtzPin::ObsClkP => print!("OBSCLKP"), - GtzPin::ObsClkN => print!("OBSCLKN"), - GtzPin::ThermIn => print!("THERM_IN"), - GtzPin::ThermOut => print!("THERM_OUT"), - GtzPin::SenseAGnd => print!("SENSE_AGND"), - GtzPin::SenseGnd => print!("SENSE_GND"), - GtzPin::SenseGndL => print!("SENSE_GNDL"), - GtzPin::SenseAVcc => print!("SENSE_AVCC"), - GtzPin::SenseVcc => print!("SENSE_VCC"), - GtzPin::SenseVccL => print!("SENSE_VCCL"), - GtzPin::SenseVccH => print!("SENSE_VCCH"), - } - } - BondPin::GtRegion(region, gtpin) => { - print!("GTREG"); - match region { - GtRegion::All => (), - GtRegion::S => print!("S"), - GtRegion::N => print!("N"), - GtRegion::L => print!("L"), - GtRegion::R => print!("R"), - GtRegion::LS => print!("LS"), - GtRegion::RS => print!("RS"), - GtRegion::LN => print!("LN"), - GtRegion::RN => print!("RN"), - GtRegion::H => print!("H"), - GtRegion::LH => print!("LH"), - GtRegion::RH => print!("RH"), - GtRegion::Num(n) => print!("{n}"), - } - print!("."); - match gtpin { - GtRegionPin::AVtt => print!("AVTT"), - GtRegionPin::AGnd => print!("AGND"), - GtRegionPin::AVcc => print!("AVCC"), - GtRegionPin::AVccRx => print!("AVCCRX"), - GtRegionPin::AVccPll => print!("AVCCPLL"), - GtRegionPin::AVttRxC => print!("AVTTRXC"), - GtRegionPin::VccAux => print!("VCCAUX"), - } - } - BondPin::Nc => print!("NC"), - BondPin::Gnd => print!("GND"), - BondPin::VccInt => print!("VCCINT"), - BondPin::VccAux => print!("VCCAUX"), - BondPin::VccAuxIo(idx) => print!("VCCAUX_IO{idx}"), - BondPin::VccBram => print!("VCCBRAM"), - BondPin::VccO(bank) => print!("VCCO{bank}"), - BondPin::VccBatt => print!("VCC_BATT"), - BondPin::Cfg(CfgPin::Cclk) => print!("CCLK"), - BondPin::Cfg(CfgPin::Done) => print!("DONE"), - BondPin::Cfg(CfgPin::M0) => print!("M0"), - BondPin::Cfg(CfgPin::M1) => print!("M1"), - BondPin::Cfg(CfgPin::M2) => print!("M2"), - BondPin::Cfg(CfgPin::ProgB) => print!("PROG_B"), - BondPin::Cfg(CfgPin::InitB) => print!("INIT_B"), - BondPin::Cfg(CfgPin::RdWrB) => print!("RDWR_B"), - BondPin::Cfg(CfgPin::CsiB) => print!("CSI_B"), - BondPin::Cfg(CfgPin::Tck) => print!("TCK"), - BondPin::Cfg(CfgPin::Tms) => print!("TMS"), - BondPin::Cfg(CfgPin::Tdi) => print!("TDI"), - BondPin::Cfg(CfgPin::Tdo) => print!("TDO"), - BondPin::Cfg(CfgPin::PwrdwnB) => print!("PWRDWN_B"), - BondPin::Cfg(CfgPin::HswapEn) => print!("HSWAP_EN"), - BondPin::Cfg(CfgPin::Din) => print!("DIN"), - BondPin::Cfg(CfgPin::Dout) => print!("DOUT"), - BondPin::Cfg(CfgPin::CfgBvs) => print!("CFGBVS"), - BondPin::Dxn => print!("DXN"), - BondPin::Dxp => print!("DXP"), - BondPin::Rsvd => print!("RSVD"), - BondPin::RsvdGnd => print!("RSVDGND"), - BondPin::Vfs => print!("VFS"), - BondPin::SysMon(bank, pin) => { - print!("SYSMON{bank}."); - match pin { - SysMonPin::VP => print!("VP"), - SysMonPin::VN => print!("VN"), - SysMonPin::AVss => print!("AVSS"), - SysMonPin::AVdd => print!("AVDD"), - SysMonPin::VRefP => print!("VREFP"), - SysMonPin::VRefN => print!("VREFN"), - } - } - BondPin::VccPsInt => print!("VCC_PS_INT"), - BondPin::VccPsAux => print!("VCC_PS_AUX"), - BondPin::VccPsPll => print!("VCC_PS_PLL"), - BondPin::PsVref(bank, idx) => print!("PS{bank}.VREF{idx}"), - BondPin::PsIo(bank, pin) => { - print!("PS{bank}."); - match pin { - PsPin::Mio(i) => print!("MIO{i}"), - PsPin::Clk => print!("CLK"), - PsPin::PorB => print!("POR_B"), - PsPin::SrstB => print!("SRST_B"), - PsPin::DdrDq(i) => print!("DDR_DQ{i}"), - PsPin::DdrDm(i) => print!("DDR_DM{i}"), - PsPin::DdrDqsP(i) => print!("DDR_DQS_P{i}"), - PsPin::DdrDqsN(i) => print!("DDR_DQS_N{i}"), - PsPin::DdrA(i) => print!("DDR_A{i}"), - PsPin::DdrBa(i) => print!("DDR_BA{i}"), - PsPin::DdrVrP => print!("DDR_VRP"), - PsPin::DdrVrN => print!("DDR_VRN"), - PsPin::DdrCkP => print!("DDR_CKP"), - PsPin::DdrCkN => print!("DDR_CKN"), - PsPin::DdrCke => print!("DDR_CKE"), - PsPin::DdrOdt => print!("DDR_ODT"), - PsPin::DdrDrstB => print!("DDR_DRST_B"), - PsPin::DdrCsB => print!("DDR_CS_B"), - PsPin::DdrRasB => print!("DDR_RAS_B"), - PsPin::DdrCasB => print!("DDR_CAS_B"), - PsPin::DdrWeB => print!("DDR_WE_B"), - } - } - } - println!(); - } - } -} - -mod ultrascale { - use itertools::Itertools; - use prjcombine_ultrascale::{ - bond::{ - Bond, BondPin, CfgPin, GtPin, GtRegion, GtRegionPin, HbmPin, PsPin, RfAdcPin, RfDacPin, - SysMonPin, - }, - grid::{ - BramKind, CleLKind, CleMKind, ColumnKindLeft, ColumnKindRight, DspKind, Grid, HardKind, - }, - }; - use unnamed_entity::EntityId; - - use crate::pad_sort_key; - - pub fn print_grid(grid: &Grid) { - println!("\tKIND: {v:?}", v = grid.kind); - if let Some(ps) = grid.ps { - print!("\tPS {v:?}", v = ps.intf_kind); - if ps.has_vcu { - print!(" VCU"); - } - println!(); - } - if grid.has_hbm { - println!("\tHAS HBM"); - } - if grid.has_csec { - println!("\tHAS CSEC"); - } - if grid.is_dmc { - println!("\tIS DMC"); - } - if grid.is_alt_cfg { - println!("\tIS ALT CFG"); - } - println!("\tCOLS:"); - for (col, cd) in &grid.columns { - if grid.cols_vbrk.contains(&col) { - println!("\t\t--- break"); - } - if grid.cols_fsr_gap.contains(&col) { - println!("\t\t--- FSR gap"); - } - if matches!( - cd.l, - ColumnKindLeft::Uram - | ColumnKindLeft::Hard(_, _) - | ColumnKindLeft::DfeC - | ColumnKindLeft::DfeDF - | ColumnKindLeft::DfeE - ) { - print!("\t\tX{cl}.R-X{c}.L: ", cl = col - 1, c = col); - } else { - print!("\t\tX{c}.L: ", c = col.to_idx()); - } - match cd.l { - ColumnKindLeft::Io(_) => print!("IO"), - ColumnKindLeft::Gt(_) => print!("GT"), - ColumnKindLeft::CleL => print!("CLEL"), - ColumnKindLeft::CleM(CleMKind::Plain) => print!("CLEM"), - ColumnKindLeft::CleM(CleMKind::ClkBuf) => print!("CLEM.CLK"), - ColumnKindLeft::CleM(CleMKind::Laguna) => print!("CLEM.LAGUNA"), - ColumnKindLeft::Bram(BramKind::Plain) => print!("BRAM"), - ColumnKindLeft::Bram(BramKind::AuxClmp) => print!("BRAM.AUX_CLMP"), - ColumnKindLeft::Bram(BramKind::BramClmp) => print!("BRAM.BRAM_CLMP"), - ColumnKindLeft::Bram(BramKind::AuxClmpMaybe) => print!("BRAM.AUX_CLMP*"), - ColumnKindLeft::Bram(BramKind::BramClmpMaybe) => print!("BRAM.BRAM_CLMP*"), - ColumnKindLeft::Bram(BramKind::Td) => print!("BRAM.TD"), - ColumnKindLeft::Uram => print!("URAM"), - ColumnKindLeft::Hard(hk, _) => { - print!("HARD{}", if hk == HardKind::Clk { " CLK" } else { "" }) - } - ColumnKindLeft::Sdfec => print!("SDFEC"), - ColumnKindLeft::DfeC => print!("DFE_C"), - ColumnKindLeft::DfeDF => print!("DFE_DF"), - ColumnKindLeft::DfeE => print!("DFE_E"), - } - if cd.clk_l.iter().any(|x| x.is_some()) { - print!(" CLK"); - for v in cd.clk_l { - if let Some(v) = v { - print!(" {v}"); - } else { - print!(" -"); - } - } - } - if let Some(ps) = grid.ps { - if ps.col == col { - print!(" PS"); - } - } - println!(); - if let ColumnKindLeft::Io(idx) | ColumnKindLeft::Gt(idx) = cd.l { - let ioc = &grid.cols_io[idx]; - for (reg, kind) in &ioc.regs { - println!("\t\t\tY{y}: {kind:?}", y = grid.row_reg_bot(reg).to_idx()); - } - } - if let ColumnKindLeft::Hard(_, idx) = cd.l { - let hc = &grid.cols_hard[idx]; - for (reg, kind) in &hc.regs { - println!("\t\t\tY{y}: {kind:?}", y = grid.row_reg_bot(reg).to_idx()); - } - } - if matches!( - cd.r, - ColumnKindRight::Uram - | ColumnKindRight::Hard(HardKind::Clk | HardKind::NonClk, _) - | ColumnKindRight::DfeC - | ColumnKindRight::DfeDF - | ColumnKindRight::DfeE - ) { - continue; - } - print!("\t\tX{c}.R: ", c = col.to_idx()); - match cd.r { - ColumnKindRight::Io(_) => print!("IO"), - ColumnKindRight::Gt(_) => print!("GT"), - ColumnKindRight::CleL(CleLKind::Plain) => print!("CLEL"), - ColumnKindRight::CleL(CleLKind::Dcg10) => print!("CLEL.DCG10"), - ColumnKindRight::Dsp(DspKind::Plain) => print!("DSP"), - ColumnKindRight::Dsp(DspKind::ClkBuf) => print!("DSP.CLK"), - ColumnKindRight::Uram => print!("URAM"), - ColumnKindRight::Hard(_, _) => print!("HARD TERM"), - ColumnKindRight::DfeB => print!("DFE_B"), - ColumnKindRight::DfeC => print!("DFE_C"), - ColumnKindRight::DfeDF => print!("DFE_DF"), - ColumnKindRight::DfeE => print!("DFE_E"), - } - if cd.clk_r.iter().any(|x| x.is_some()) { - print!(" CLK"); - for v in cd.clk_r { - if let Some(v) = v { - print!(" {v}"); - } else { - print!(" -"); - } - } - } - println!(); - if let ColumnKindRight::Io(idx) | ColumnKindRight::Gt(idx) = cd.r { - let ioc = &grid.cols_io[idx]; - for (reg, kind) in &ioc.regs { - println!("\t\t\tY{y}: {kind:?}", y = grid.row_reg_bot(reg).to_idx()); - } - } - if let ColumnKindRight::Hard(__, idx) = cd.r { - let hc = &grid.cols_hard[idx]; - for (reg, kind) in &hc.regs { - println!("\t\t\tY{y}: {kind:?}", y = grid.row_reg_bot(reg).to_idx()); - } - } - } - println!("\tREGS: {r}", r = grid.regs); - } - - pub fn print_bond(bond: &Bond) { - println!("\tPINS:"); - for (pin, pad) in bond.pins.iter().sorted_by_key(|(k, _)| pad_sort_key(k)) { - print!("\t\t{pin:4}: "); - match pad { - BondPin::Hpio(bank, idx) => print!("HPIOB_{bank}_{idx}"), - BondPin::Hdio(bank, idx) => print!("HDIOB_{bank}_{idx}"), - BondPin::HdioLc(bank, idx) => print!("HDIOBLC_{bank}_{idx}"), - BondPin::IoVref(bank) => print!("IO_{bank}_VREF"), - BondPin::Gt(bank, gtpin) => { - print!("GT{bank}."); - match gtpin { - GtPin::RxP(idx) => print!("RXP{idx}"), - GtPin::RxN(idx) => print!("RXN{idx}"), - GtPin::TxP(idx) => print!("TXP{idx}"), - GtPin::TxN(idx) => print!("TXN{idx}"), - GtPin::ClkP(idx) => print!("CLKP{idx}"), - GtPin::ClkN(idx) => print!("CLKN{idx}"), - GtPin::AVcc => print!("AVCC"), - GtPin::RRef => print!("RREF"), - GtPin::AVttRCal => print!("AVTTRCAL"), - GtPin::AVtt => print!("AVTT"), - } - } - BondPin::GtRegion(region, gtpin) => { - print!("GTREG"); - match region { - GtRegion::All => (), - GtRegion::L => print!("L"), - GtRegion::R => print!("R"), - GtRegion::LS => print!("LS"), - GtRegion::RS => print!("RS"), - GtRegion::LN => print!("LN"), - GtRegion::RN => print!("RN"), - GtRegion::LLC => print!("LLC"), - GtRegion::RLC => print!("RLC"), - GtRegion::LC => print!("LC"), - GtRegion::RC => print!("RC"), - GtRegion::LUC => print!("LUC"), - GtRegion::RUC => print!("RUC"), - } - print!("."); - match gtpin { - GtRegionPin::AVtt => print!("AVTT"), - GtRegionPin::AVcc => print!("AVCC"), - GtRegionPin::VccAux => print!("VCCAUX"), - GtRegionPin::VccInt => print!("VCCINT"), - } - } - BondPin::Nc => print!("NC"), - BondPin::Gnd => print!("GND"), - BondPin::VccInt => print!("VCCINT"), - BondPin::VccAux => print!("VCCAUX"), - BondPin::VccBram => print!("VCCBRAM"), - BondPin::VccO(bank) => print!("VCCO{bank}"), - BondPin::VccBatt => print!("VCC_BATT"), - BondPin::Cfg(CfgPin::Cclk) => print!("CCLK"), - BondPin::Cfg(CfgPin::Done) => print!("DONE"), - BondPin::Cfg(CfgPin::M0) => print!("M0"), - BondPin::Cfg(CfgPin::M1) => print!("M1"), - BondPin::Cfg(CfgPin::M2) => print!("M2"), - BondPin::Cfg(CfgPin::ProgB) => print!("PROG_B"), - BondPin::Cfg(CfgPin::InitB) => print!("INIT_B"), - BondPin::Cfg(CfgPin::RdWrB) => print!("RDWR_B"), - BondPin::Cfg(CfgPin::Tck) => print!("TCK"), - BondPin::Cfg(CfgPin::Tms) => print!("TMS"), - BondPin::Cfg(CfgPin::Tdi) => print!("TDI"), - BondPin::Cfg(CfgPin::Tdo) => print!("TDO"), - BondPin::Cfg(CfgPin::HswapEn) => print!("HSWAP_EN"), - BondPin::Cfg(CfgPin::Data(idx)) => print!("DATA{idx}"), - BondPin::Cfg(CfgPin::CfgBvs) => print!("CFGBVS"), - BondPin::Cfg(CfgPin::PorOverride) => print!("POR_OVERRIDE"), - BondPin::Dxn => print!("DXN"), - BondPin::Dxp => print!("DXP"), - BondPin::Rsvd => print!("RSVD"), - BondPin::RsvdGnd => print!("RSVDGND"), - BondPin::SysMon(bank, pin) => { - print!("SYSMON{bank}."); - match pin { - SysMonPin::VP => print!("VP"), - SysMonPin::VN => print!("VN"), - } - } - BondPin::VccPsAux => print!("VCC_PS_AUX"), - BondPin::VccPsPll => print!("VCC_PS_PLL"), - BondPin::IoPs(bank, pin) => { - print!("PS{bank}."); - match pin { - PsPin::Mio(i) => print!("MIO{i}"), - PsPin::Clk => print!("CLK"), - PsPin::PorB => print!("POR_B"), - PsPin::SrstB => print!("SRST_B"), - PsPin::DdrDq(i) => print!("DDR_DQ{i}"), - PsPin::DdrDm(i) => print!("DDR_DM{i}"), - PsPin::DdrDqsP(i) => print!("DDR_DQS_P{i}"), - PsPin::DdrDqsN(i) => print!("DDR_DQS_N{i}"), - PsPin::DdrA(i) => print!("DDR_A{i}"), - PsPin::DdrBa(i) => print!("DDR_BA{i}"), - PsPin::DdrCkP(idx) => print!("DDR_CKP{idx}"), - PsPin::DdrCkN(idx) => print!("DDR_CKN{idx}"), - PsPin::DdrCke(idx) => print!("DDR_CKE{idx}"), - PsPin::DdrOdt(idx) => print!("DDR_ODT{idx}"), - PsPin::DdrCsB(idx) => print!("DDR_CS_B{idx}"), - PsPin::DdrDrstB => print!("DDR_DRST_B"), - PsPin::DdrActN => print!("DDR_ACT_N"), - PsPin::DdrAlertN => print!("DDR_ALERT_N"), - PsPin::DdrBg(idx) => print!("DDR_BG{idx}"), - PsPin::DdrParity => print!("DDR_PARITY"), - PsPin::DdrZq => print!("DDR_ZQ"), - PsPin::ErrorOut => print!("ERROR_OUT"), - PsPin::ErrorStatus => print!("ERROR_STATUS"), - PsPin::Done => print!("DONE"), - PsPin::InitB => print!("INIT_B"), - PsPin::ProgB => print!("PROG_B"), - PsPin::JtagTck => print!("JTAG_TCK"), - PsPin::JtagTdi => print!("JTAG_TDI"), - PsPin::JtagTdo => print!("JTAG_TDO"), - PsPin::JtagTms => print!("JTAG_TMS"), - PsPin::Mode(i) => print!("MODE{i}"), - PsPin::PadI => print!("PAD_I"), - PsPin::PadO => print!("PAD_O"), - } - } - BondPin::SysMonVRefP => print!("SYSMON_VREFP"), - BondPin::SysMonVRefN => print!("SYSMON_VREFN"), - BondPin::SysMonGnd => print!("SYSMON_GND"), - BondPin::SysMonVcc => print!("SYSMON_VCC"), - BondPin::PsSysMonGnd => print!("PS_SYSMON_GND"), - BondPin::PsSysMonVcc => print!("PS_SYSMON_VCC"), - BondPin::VccAuxHpio => print!("VCCAUX_HPIO"), - BondPin::VccAuxHdio => print!("VCCAUX_HDIO"), - BondPin::VccAuxIo => print!("VCCAUX_IO"), - BondPin::VccIntIo => print!("VCCINT_IO"), - BondPin::VccPsIntLp => print!("VCC_PS_INT_LP"), - BondPin::VccPsIntFp => print!("VCC_PS_INT_FP"), - BondPin::VccPsIntFpDdr => print!("VCC_PS_INT_FP_DDR"), - BondPin::VccPsBatt => print!("VCC_PS_BATT"), - BondPin::VccPsDdrPll => print!("VCC_PS_DDR_PLL"), - BondPin::VccIntVcu => print!("VCCINT_VCU"), - BondPin::GndSense => print!("GND_SENSE"), - BondPin::VccIntSense => print!("VCCINT_SENSE"), - BondPin::VccIntAms => print!("VCCINT_AMS"), - BondPin::VccSdfec => print!("VCC_SDFEC"), - BondPin::RfDacGnd => print!("RFDAC_GND"), - BondPin::RfDacSubGnd => print!("RFDAC_AGND"), - BondPin::RfDacAVcc => print!("RFDAC_AVCC"), - BondPin::RfDacAVccAux => print!("RFDAC_AVCCAUX"), - BondPin::RfDacAVtt => print!("RFDAC_AVTT"), - BondPin::RfAdcGnd => print!("RFADC_GND"), - BondPin::RfAdcSubGnd => print!("RFADC_SUBGND"), - BondPin::RfAdcAVcc => print!("RFADC_AVCC"), - BondPin::RfAdcAVccAux => print!("RFADC_AVCCAUX"), - BondPin::Hbm(bank, pin) => { - print!("HBM{bank}."); - match pin { - HbmPin::Vcc => print!("VCC"), - HbmPin::VccIo => print!("VCCIO"), - HbmPin::VccAux => print!("VCCAUX"), - HbmPin::Rsvd => print!("RSVD"), - HbmPin::RsvdGnd => print!("RSVD_GND"), - } - } - BondPin::RfDac(bank, pin) => { - print!("RFDAC{bank}."); - match pin { - RfDacPin::VOutP(idx) => print!("VOUT{idx}P"), - RfDacPin::VOutN(idx) => print!("VOUT{idx}N"), - RfDacPin::ClkP => print!("CLKP"), - RfDacPin::ClkN => print!("CLKN"), - RfDacPin::RExt => print!("REXT"), - RfDacPin::SysRefP => print!("SYSREFP"), - RfDacPin::SysRefN => print!("SYSREFN"), - } - } - BondPin::RfAdc(bank, pin) => { - print!("RFADC{bank}."); - match pin { - RfAdcPin::VInP(idx) => print!("VIN{idx}_P"), - RfAdcPin::VInN(idx) => print!("VIN{idx}_N"), - RfAdcPin::VInPairP(idx) => print!("VIN_PAIR{idx}_P"), - RfAdcPin::VInPairN(idx) => print!("VIN_PAIR{idx}_N"), - RfAdcPin::ClkP => print!("CLKP"), - RfAdcPin::ClkN => print!("CLKN"), - RfAdcPin::VCm(idx) => print!("VCM{idx}"), - RfAdcPin::RExt => print!("REXT"), - RfAdcPin::PllTestOutP => print!("PLL_TEST_OUT_P"), - RfAdcPin::PllTestOutN => print!("PLL_TEST_OUT_N"), - } - } - } - println!(); - } - } -} - -mod versal { - use prjcombine_versal::{ - bond::Bond, - grid::{BramKind, CleKind, ColumnKind, Grid, RightKind}, - }; - use unnamed_entity::EntityId; - - pub fn print_grid(grid: &Grid) { - println!("\tKIND: Versal"); - println!("\tPS: {v:?}", v = grid.ps); - println!("\tCPM: {v:?}", v = grid.cpm); - println!("\tXRAM TOP: {v:?}", v = grid.has_xram_top); - println!("\tTOP: {v:?}", v = grid.top); - println!("\tBOTTOM: {v:?}", v = grid.bottom); - println!("\tCOLS:"); - for (col, cd) in &grid.columns { - if grid.cols_vbrk.contains(&col) { - println!("\t\t--- break"); - } - if grid.cols_cpipe.contains(&col) { - println!("\t\t--- CPIPE"); - } - if matches!( - cd.l, - ColumnKind::Cle(_) - | ColumnKind::Dsp - | ColumnKind::Hard - | ColumnKind::VNoc - | ColumnKind::VNoc2 - ) { - print!("\t\tX{cl}.R-X{col}.L: ", cl = col - 1); - } else { - print!("\t\tX{c}.L: ", c = col.to_idx()); - } - match cd.l { - ColumnKind::None => print!("---"), - ColumnKind::Cle(CleKind::Plain) => print!("CLE"), - ColumnKind::Cle(CleKind::Sll) => print!("CLE.SLL"), - ColumnKind::Cle(CleKind::Sll2) => print!("CLE.SLL2"), - ColumnKind::Dsp => print!("DSP"), - ColumnKind::Bram(BramKind::Plain) => print!("BRAM"), - ColumnKind::Bram(BramKind::ClkBuf) => print!("BRAM.CLKBUF"), - ColumnKind::Bram(BramKind::ClkBufNoPd) => print!("BRAM.CLKBUF.NOPD"), - ColumnKind::Uram => print!("URAM"), - ColumnKind::Hard => print!("HARD"), - ColumnKind::Gt => print!("GT"), - ColumnKind::Cfrm => print!("CFRM"), - ColumnKind::VNoc => print!("VNOC"), - ColumnKind::VNoc2 => print!("VNOC2"), - } - if cd.has_bli_bot_l { - print!(" BLI.BOT"); - } - if cd.has_bli_top_l { - print!(" BLI.TOP"); - } - println!(); - for hc in &grid.cols_hard { - if hc.col == col { - for (reg, kind) in &hc.regs { - println!("\t\t\tY{y}: {kind:?}", y = grid.row_reg_bot(reg).to_idx()); - } - } - } - if matches!( - cd.r, - ColumnKind::Cle(_) - | ColumnKind::Dsp - | ColumnKind::Hard - | ColumnKind::VNoc - | ColumnKind::VNoc2 - ) { - continue; - } - print!("\t\tX{c}.R: ", c = col.to_idx()); - match cd.r { - ColumnKind::None => print!("---"), - ColumnKind::Cle(CleKind::Plain) => print!("CLE"), - ColumnKind::Cle(CleKind::Sll) => print!("CLE.SLL"), - ColumnKind::Cle(CleKind::Sll2) => print!("CLE.SLL2"), - ColumnKind::Dsp => print!("DSP"), - ColumnKind::Bram(BramKind::Plain) => print!("BRAM"), - ColumnKind::Bram(BramKind::ClkBuf) => print!("BRAM.CLKBUF"), - ColumnKind::Bram(BramKind::ClkBufNoPd) => print!("BRAM.CLKBUF.NOPD"), - ColumnKind::Uram => print!("URAM"), - ColumnKind::Hard => print!("HARD"), - ColumnKind::Gt => print!("GT"), - ColumnKind::Cfrm => print!("CFRM"), - ColumnKind::VNoc => print!("VNOC"), - ColumnKind::VNoc2 => print!("VNOC2"), - } - if cd.has_bli_bot_r { - print!(" BLI.BOT"); - } - if cd.has_bli_top_r { - print!(" BLI.TOP"); - } - println!(); - } - println!("\tGT LEFT:"); - for (reg, kind) in &grid.regs_gt_left { - println!("\t\tY{y}: {kind:?}", y = grid.row_reg_bot(reg).to_idx()); - } - match grid.right { - RightKind::Term => { - println!("\tRIGHT: TERM"); - } - RightKind::Term2 => { - println!("\tRIGHT: TERM2"); - } - RightKind::Gt(ref regs_gt_right) => { - println!("\tRIGHT: GT:\n"); - for (reg, kind) in regs_gt_right { - println!("\t\tY{y}: {kind:?}", y = grid.row_reg_bot(reg).to_idx()); - } - } - RightKind::HNicX => { - println!("\tRIGHT: HNIC"); - } - RightKind::Cidb => { - println!("\tRIGHT: CIDB"); - } - } - println!("\tREGS: {r}", r = grid.regs); - } - - pub fn print_bond(_bond: &Bond) { - // well. - } -} - fn main() -> Result<(), Box> { let args = Args::parse(); let geom = GeomDb::from_file(args.file)?; @@ -1379,15 +52,7 @@ fn main() -> Result<(), Box> { } println!(); if args.grids { - match grid { - Grid::Xc2000(g) => print!("{}", g), - Grid::Virtex(g) => virtex::print_grid(g), - Grid::Virtex2(g) => virtex2::print_grid(g), - Grid::Spartan6(g) => spartan6::print_grid(g), - Grid::Virtex4(g) => virtex4::print_grid(g), - Grid::Ultrascale(g) => ultrascale::print_grid(g), - Grid::Versal(g) => versal::print_grid(g), - } + print!("{grid}"); } } for (ipid, ip) in &geom.interposers { @@ -1416,15 +81,7 @@ fn main() -> Result<(), Box> { } println!(); if args.pkgs { - match bond { - Bond::Xc2000(bond) => print!("{}", bond), - Bond::Virtex(bond) => virtex::print_bond(bond), - Bond::Virtex2(bond) => virtex2::print_bond(bond), - Bond::Spartan6(bond) => spartan6::print_bond(bond), - Bond::Virtex4(bond) => virtex4::print_bond(bond), - Bond::Ultrascale(bond) => ultrascale::print_bond(bond), - Bond::Versal(bond) => versal::print_bond(bond), - } + print!("{bond}"); } } } diff --git a/prjcombine_xilinx_geom/src/lib.rs b/prjcombine_xilinx_geom/src/lib.rs index 17ea61bb..666d1728 100644 --- a/prjcombine_xilinx_geom/src/lib.rs +++ b/prjcombine_xilinx_geom/src/lib.rs @@ -30,6 +30,20 @@ pub enum Grid { Versal(prjcombine_versal::grid::Grid), } +impl std::fmt::Display for Grid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Grid::Xc2000(grid) => write!(f, "{grid}"), + Grid::Virtex(grid) => write!(f, "{grid}"), + Grid::Virtex2(grid) => write!(f, "{grid}"), + Grid::Spartan6(grid) => write!(f, "{grid}"), + Grid::Virtex4(grid) => write!(f, "{grid}"), + Grid::Ultrascale(grid) => write!(f, "{grid}"), + Grid::Versal(grid) => write!(f, "{grid}"), + } + } +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DeviceBond { pub name: String, @@ -84,6 +98,20 @@ pub enum Bond { Versal(prjcombine_versal::bond::Bond), } +impl std::fmt::Display for Bond { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Bond::Xc2000(bond) => write!(f, "{bond}"), + Bond::Virtex(bond) => write!(f, "{bond}"), + Bond::Virtex2(bond) => write!(f, "{bond}"), + Bond::Spartan6(bond) => write!(f, "{bond}"), + Bond::Virtex4(bond) => write!(f, "{bond}"), + Bond::Ultrascale(bond) => write!(f, "{bond}"), + Bond::Versal(bond) => write!(f, "{bond}"), + } + } +} + pub enum ExpandedBond<'a> { Xc2000(prjcombine_xc2000::bond::ExpandedBond<'a>), Virtex(prjcombine_virtex::bond::ExpandedBond<'a>),