Skip to content

Commit

Permalink
Merge pull request #13 from tscircuit/debug-scaling-issue
Browse files Browse the repository at this point in the history
fix scaling issue of dsn-converter
  • Loading branch information
imrishabh18 authored Nov 21, 2024
2 parents 3fd51e7 + efdccc1 commit 78695c2
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 13 deletions.
Binary file modified bun.lockb
Binary file not shown.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@types/bun": "latest",
"@types/debug": "^4.1.12",
"@types/react": "18.3.4",
"circuit-json-to-connectivity-map": "^0.0.17",
"debug": "^4.3.6",
"debug": "^4.3.7",
"next": "^14.2.5",
"performance-now": "^2.1.0",
"redaxios": "^0.5.1"
Expand All @@ -25,7 +26,8 @@
"@tscircuit/soup-util": "^0.0.38",
"bun-match-svg": "^0.0.6",
"circuit-to-svg": "^0.0.81",
"dsn-converter": "^0.0.16",
"dsn-converter": "^0.0.18",
"graphics-debug": "^0.0.1",
"kleur": "^4.1.5",
"schematic-symbols": "0.0.99",
"transformation-matrix": "^2.16.1",
Expand Down
62 changes: 51 additions & 11 deletions routes/_fake/run_autorouter.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { withRouteSpec } from "lib/middleware/with-winter-spec"
import { z } from "zod"
import {
parseDsnToCircuitJson,
convertCircuitJsonToDsnString,
MultilayerIjump,
getSimpleRouteJson,
} from "@tscircuit/infgrid-ijump-astar"
import type { AnyCircuitElement, PcbTrace } from "circuit-json"
import Debug from "debug"
import {
type DsnPcb,
convertCircuitJsonToDsnSession,
parseDsnToCircuitJson,
parseDsnToDsnJson,
type DsnPcb,
stringifyDsnSession,
} from "dsn-converter"
import type { AnyCircuitElement, PcbTrace } from "circuit-json"
import {
MultilayerIjump,
getSimpleRouteJson,
} from "@tscircuit/infgrid-ijump-astar"
import { su } from "@tscircuit/soup-util"
import { withRouteSpec } from "lib/middleware/with-winter-spec"
import { circuitJsonToMarkdownTable } from "tests/debug-utils/circuit-json-to-table"
import { analyzeWirePaths } from "tests/debug-utils/extract-trace-from-ses-file"
import { saveRouteAnalysis } from "tests/debug-utils/simple-route-json-to-table"
import { z } from "zod"

const debugGraphics = Debug("tscircuit:fake-autorouter")

function addPcbTracesToCircuitJson(
circuitJson: AnyCircuitElement[],
Expand Down Expand Up @@ -69,8 +73,25 @@ export default withRouteSpec({
const inputDsn = Buffer.from(job.input._input_dsn!, "base64").toString()
const dsnPcb = parseDsnToDsnJson(inputDsn) as DsnPcb
const circuitJson = parseDsnToCircuitJson(inputDsn)

if (debugGraphics.enabled) {
circuitJsonToMarkdownTable(
circuitJson as any,
"../routes/_fake/debug-files-stages/stage-1-circuit-json.md",
"Stage 1: Circuit JSON as input to fake",
)
}

const simpleRouteJson = getSimpleRouteJson(circuitJson)

if (debugGraphics.enabled) {
saveRouteAnalysis(
simpleRouteJson,
"../routes/_fake/debug-files-stages/stage-2-simple-route-json.md",
"Stage 2: Simple Route JSON as input to autorouter",
)
}

const autorouter = new MultilayerIjump({
input: simpleRouteJson,
OBSTACLE_MARGIN: 0.2,
Expand All @@ -83,6 +104,15 @@ export default withRouteSpec({
}
const routedCircuitJson = addPcbTracesToCircuitJson(circuitJson, traces)

if (debugGraphics.enabled) {
circuitJsonToMarkdownTable(
routedCircuitJson as any,
"../routes/_fake/debug-files-stages/stage-3-routed-circuit-json.md",
"Stage 3: Routed Circuit JSON as output from the fake autorouter",
)
// saveRouteAnalysis(traces, "routed-trace-points.md")
}

// console.dir(
// {
// simpleRouteJson,
Expand All @@ -99,6 +129,16 @@ export default withRouteSpec({
)

const routedDsnString = stringifyDsnSession(routedDsnSession)
if (debugGraphics.enabled) {
debugGraphics({
routedDsnString,
})
analyzeWirePaths(
routedDsnString,
"../routes/_fake/debug-files-stages/stage-4-ses-file-trace-points.md",
"Last stage: SES file conversion from routed circuit JSON",
)
}
// convert the DSN to a SES file

ctx.db.jobs[jobIndex] = {
Expand Down
98 changes: 98 additions & 0 deletions tests/debug-utils/circuit-json-to-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import type { AnyCircuitElement } from "@tscircuit/soup"
import fs from "node:fs"
import path from "node:path"

function formatNumber(num: number) {
return typeof num === "number" ? Number(num.toFixed(1)) : "N/A"
}

function formatPoint(x: number, y: number) {
return `(${formatNumber(x)}, ${formatNumber(y)})`
}

function convertCircuitJsonToMarkdown(circuitJson: any, title?: string) {
let markdown = title ? `# ${title}\n\n` : "# Circuit Component Analysis\n\n"

// Source Components
const sourceComponents = circuitJson.filter(
(item: AnyCircuitElement) => item.type === "source_component",
)
if (sourceComponents.length > 0) {
markdown += "## Source Components\n"
markdown += "| ID | Name | Type |\n"
markdown += "|----|------|------|\n"
for (const comp of sourceComponents) {
const shortId = comp.source_component_id.split(":").pop()
markdown += `| ${shortId} | ${comp.name} | ${comp.ftype} |\n`
}
markdown += "\n"
}

// PCB Ports
const ports = circuitJson.filter(
(item: AnyCircuitElement) => item.type === "pcb_port",
)
if (ports.length > 0) {
markdown += "## PCB Ports\n"
markdown += "| ID | Position (x,y) |\n"
markdown += "|-----|---------------|\n"
for (const port of ports) {
const shortId = port.pcb_port_id.split("-").slice(-2).join("-")
markdown += `| ${shortId} | ${formatPoint(port.x, port.y)} |\n`
}
markdown += "\n"
}

// SMT Pads
const pads = circuitJson.filter(
(item: AnyCircuitElement) => item.type === "pcb_smtpad",
)
if (pads.length > 0) {
markdown += "## SMT Pads\n"
markdown += "| Component | Position (x,y) | Size (w×h) |\n"
markdown += "|-----------|---------------|-------------|\n"
for (const pad of pads) {
const shortId = pad.pcb_smtpad_id.split("_").slice(-3).join("-")
markdown += `| ${shortId} | ${formatPoint(pad.x, pad.y)} | ${formatNumber(pad.width)} × ${formatNumber(pad.height)} |\n`
}
markdown += "\n"
}

// Traces
const traces = circuitJson.filter(
(item: AnyCircuitElement) => item.type === "pcb_trace",
)
if (traces.length > 0) {
markdown += "## Trace Route Points\n"
markdown += "| Point | Position (x,y) | Width |\n"
markdown += "|-------|---------------|--------|\n"
for (const trace of traces) {
for (const [index, point] of trace.route.entries()) {
if (point.route_type === "wire") {
markdown += `| ${index + 1} | ${formatPoint(point.x, point.y)} | ${formatNumber(point.width)} |\n`
}
}
}
}

return markdown
}

export function circuitJsonToMarkdownTable(
circuitJson: AnyCircuitElement[],
outputPath: string,
title?: string,
) {
try {
const markdown = convertCircuitJsonToMarkdown(circuitJson, title)
// Resolve the output path relative to the current file's directory
const resolvedOutputPath = path.resolve(__dirname, outputPath)
console.log(`Resolved output path: ${resolvedOutputPath}`)
fs.writeFileSync(resolvedOutputPath, markdown)
console.log(`Circuit JSON has been written to ${resolvedOutputPath}`)
return markdown
} catch (error) {
console.error("Error processing circuit JSON:", error)
throw error
}
}
80 changes: 80 additions & 0 deletions tests/debug-utils/extract-trace-from-ses-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import fs from "node:fs"
import path from "node:path"

function formatNumber(num: number) {
// Format number to 2 decimal places and remove trailing zeros
return parseFloat(num.toFixed(2)).toString()
}

function extractWirePathPoints(sesContent: string) {
const wirePathRegex = /path\s+([A-Za-z.]+)\s+([0-9.]+)\s+([\d.-\s]+)/g
const paths = []

let match: RegExpExecArray | null
while (true) {
match = wirePathRegex.exec(sesContent)
if (match === null) break
const layer = match[1]
const width = match[2]
const coordinates = match[3].trim().split(/\s+/)

const points = []
for (let i = 0; i < coordinates.length; i += 2) {
points.push({
x: parseFloat(coordinates[i]),
y: parseFloat(coordinates[i + 1]),
})
}

paths.push({
layer,
width,
points,
})
}

return paths
}

function generateMarkdownTable(paths: any, title?: string) {
let markdown = title ? `# ${title}\n\n` : "# Wire Path Points Analysis\n\n"

for (const [index, path] of paths.entries()) {
markdown += `## Wire Path ${index + 1}\n`
markdown += `- Layer: ${path.layer}\n`
markdown += `- Width: ${path.width}mm\n\n`

// Fixed width columns with padding
markdown += "| Point # | X (μm) | Y (μm) |\n"
markdown += "|---------|--------------|--------------||\n"

for (const [pointIndex, point] of path.points.entries()) {
const formattedX = formatNumber(point.x).padStart(12, " ")
const formattedY = formatNumber(point.y).padStart(12, " ")
markdown += `| ${(pointIndex + 1).toString().padStart(2)} |${formattedX}|${formattedY}|\n`
}

markdown += "\n"
}

return markdown
}

export function analyzeWirePaths(
sesContent: string,
outputPath: string,
title?: string,
) {
try {
const paths = extractWirePathPoints(sesContent)
const markdown = generateMarkdownTable(paths, title)
const resolvedOutputPath = path.resolve(__dirname, outputPath)
fs.writeFileSync(resolvedOutputPath, markdown)
console.log(`Wire path analysis has been written to ${resolvedOutputPath}`)

return paths
} catch (error) {
console.error("Error processing file:", error)
throw error
}
}
72 changes: 72 additions & 0 deletions tests/debug-utils/simple-route-json-to-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import fs from "node:fs"
import path from "node:path"

function formatNumber(num: number) {
return parseFloat(num.toFixed(2)).toString().padStart(8, " ")
}

function convertRouteJsonToMarkdown(routeJson: any, title?: string) {
let markdown = title ? `# ${title}\n\n` : "# Simple Route JSON Analysis\n\n"

// Basic Information
markdown += "## General Information\n"
markdown += `- Minimum Trace Width: ${routeJson.minTraceWidth}mm\n`
markdown += `- Layer Count: ${routeJson.layerCount}\n\n`

// Bounds Information
markdown += "## Board Bounds\n"
markdown += "| Dimension | Min (mm) | Max (mm) |\n"
markdown += "|-----------|----------|----------|\n"
markdown += `| X |${formatNumber(routeJson.bounds.minX)}|${formatNumber(routeJson.bounds.maxX)}|\n`
markdown += `| Y |${formatNumber(routeJson.bounds.minY)}|${formatNumber(routeJson.bounds.maxY)}|\n\n`

// Obstacles
markdown += "## Obstacles\n"
markdown +=
"| Type | Layer | X (mm) | Y (mm) | Width (mm) | Height (mm) | Connected To |\n"
markdown +=
"|-------|--------|---------|---------|------------|-------------|-------------|\n"

for (const obstacle of routeJson.obstacles) {
markdown += `| ${obstacle.type} | ${obstacle.layers.join(", ")} |`
markdown += `${formatNumber(obstacle.center.x)}|${formatNumber(obstacle.center.y)}|`
markdown += `${formatNumber(obstacle.width)}|${formatNumber(obstacle.height)}|`
markdown += ` ${obstacle.connectedTo.map((conn: any) => `\n- ${conn}`).join("")} |\n`
}
markdown += "\n"

// Connections
markdown += "## Connections\n"
for (const [index, connection] of routeJson.connections.entries()) {
markdown += `### Connection ${index + 1}: ${connection.name}\n`
markdown += "| Point | X (mm) | Y (mm) | Layer | Port ID |\n"
markdown += "|--------|---------|---------|--------|----------|\n"

for (const [pointIndex, point] of connection.pointsToConnect.entries()) {
markdown += `| ${pointIndex + 1} |`
markdown += `${formatNumber(point.x)}|${formatNumber(point.y)}|`
markdown += ` ${point.layer} | ${point.pcb_port_id} |\n`
}
markdown += "\n"
}

return markdown
}

export function saveRouteAnalysis(
routeJson: any,
outputPath: string,
title?: string,
) {
try {
const markdown = convertRouteJsonToMarkdown(routeJson, title)
// Resolve the output path relative to the current file's directory
const resolvedOutputPath = path.resolve(__dirname, outputPath)
fs.writeFileSync(resolvedOutputPath, markdown)
console.log(`Route analysis has been written to ${resolvedOutputPath}`)
return markdown
} catch (error) {
console.error("Error processing route JSON:", error)
throw error
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 78695c2

Please sign in to comment.