0hmX/am62l-lpddr4-breakout-repro

This code defines React components that instantiate circuits representing dedicated DDR address control and byte0 data lines.

Version
1.0.11
License
unset
Stars
0

single-ddr-bus-layout.tsx

import { MT53E1G16D1ZW, ballMap } from "@tsci/0hmX.mt53e1g16d1zw-footprint"
import { AM62L32, AM62L32BOGHAANBR } from "@tsci/tscircuit.ti"
import { Children, cloneElement, Fragment, isValidElement } from "react"
import { DDR_CONNECTIONS, type DdrBusName } from "./ddr-connections"

const AM62L_BALL_PITCH_MM = 0.5
const REQUIRED_ESCAPE_CHANNEL_MM = 0.24384
const AM62L_PAD_DIAMETER_MM =
  AM62L_BALL_PITCH_MM - REQUIRED_ESCAPE_CHANNEL_MM
const AM62L_PAD_RADIUS_MM = AM62L_PAD_DIAMETER_MM / 2

const createAm62lEscapeFootprint = () => {
  const defaultChip = AM62L32BOGHAANBR({} as any)
  const defaultFootprint = defaultChip.props.footprint

  return cloneElement(
    defaultFootprint,
    {},
    Children.map(defaultFootprint.props.children, (child) =>
      isValidElement(child) && child.type === "smtpad"
        ? cloneElement(child, { radius: `${AM62L_PAD_RADIUS_MM}mm` } as any)
        : child,
    ),
  )
}

const AM62L_ESCAPE_FOOTPRINT = createAm62lEscapeFootprint()

const SIGNAL_LAYERS = [
  "top",
  "inner1",
  "inner2",
  "inner3",
  "inner4",
  "inner5",
  "inner6",
  "bottom",
] as const

const BUS_CONFIGS = {
  DDR_BYTE0: {
    socPins: [76, 91, 92, 93, 94, 103, 104, 105, 121, 122, 123],
    socDirection: "bottom_right",
    ramDirection: "bottom_left",
    fanoutGroups: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]],
    fanoutLayers: [undefined],
  },
  DDR_BYTE1: {
    socPins: [236, 238, 255, 256, 257, 272, 273, 275, 276, 284, 285],
    socDirection: "top_right",
    ramDirection: "top_left",
    // Group by physical AM62L ball row so each group can share one layer.
    fanoutGroups: [
      [1, 2],
      [3, 4, 6],
      [0, 5, 9, 10],
      [7, 8],
    ],
    fanoutLayers: ["inner2", "bottom", "inner3", "inner2"],
  },
  DDR_ADDR_CTRL: {
    socPins: [124, 125, 139, 140, 149, 150, 162, 164, 165, 215, 216],
    socDirection: "center_right",
    ramDirection: "center_left",
    fanoutGroups: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]],
    fanoutLayers: [undefined],
  },
} as const

export const SingleDdrBusCircuit = ({ busName }: { busName: DdrBusName }) => {
  const config = BUS_CONFIGS[busName]
  const breakoutPadding = busName === "DDR_BYTE1" ? "2mm" : "1mm"
  const connections = DDR_CONNECTIONS.filter(
    (connection) => connection.busName === busName,
  )
  const fanoutBuses = config.fanoutGroups.map((connectionIndices, index) => ({
    name: `${busName}_FANOUT_${index}`,
    connections: connectionIndices.map(
      (connectionIndex) => connections[connectionIndex]!.traceName,
    ),
    preferredLayer: config.fanoutLayers[index],
    routingPhaseIndex: index,
  }))
  const socFanoutDirections = Object.fromEntries(
    fanoutBuses.map((fanoutBus) => [
      fanoutBus.name,
      config.socDirection,
    ]),
  )
  const ramFanoutDirections = Object.fromEntries(
    fanoutBuses.map((fanoutBus) => [
      fanoutBus.name,
      config.ramDirection,
    ]),
  )

  const usedSocPins = new Set<number>(config.socPins)
  const socNoConnect = Array.from({ length: 373 }, (_, index) => index + 1)
    .filter((pin) => !usedSocPins.has(pin))
    .map((pin) => `pin${pin}`)

  const usedMemorySignals = new Set(
    connections.map(({ memorySignal }) => memorySignal),
  )
  const memoryNoConnect = ballMap
    .map(({ signal }, index) => ({ signal, selector: `pin${index + 1}` }))
    .filter(({ signal }) => !usedMemorySignals.has(signal))
    .map(({ selector }) => selector)

  return (
    <board
      name={`AM62L_LPDDR4_${busName}_ONLY`}
      width="45.2mm"
      height="25mm"
      layers={8}
      defaultTraceWidth="0.08128mm"
      minTraceWidth="0.08128mm"
      minTraceToPadEdgeClearance="0.05mm"
      minViaEdgeToPadEdgeClearance="0.08128mm"
      minViaHoleEdgeToViaHoleEdgeClearance="0.1016mm"
      minViaHoleDiameter="0.1mm"
      minViaPadDiameter="0.24mm"
      pcbStyle={{ viaHoleDiameter: "0.1mm", viaPadDiameter: "0.24mm" }}
      autorouter="beta_pipeline9"
      autorouterEffortLevel="1x"
    >
      <breakout
        name="SOC_BREAKOUT"
        pcbX={-10}
        pcbY={0}
        padding={breakoutPadding}
        fanoutRoutingLayers={[...SIGNAL_LAYERS]}
        busFanoutDirections={socFanoutDirections}
      >
        <AM62L32
          name="U1"
          footprintVariant="fccsp_373_anb"
          footprint={AM62L_ESCAPE_FOOTPRINT}
          pcbX={0}
          pcbY={0}
          pcbRotation={180}
          noSchematicRepresentation
          noConnect={socNoConnect as any}
        />
      </breakout>

      <breakout
        name="RAM_BREAKOUT"
        pcbX={10.116917}
        pcbY={-0.050917}
        padding={breakoutPadding}
        fanoutRoutingLayers={[...SIGNAL_LAYERS]}
        busFanoutDirections={ramFanoutDirections}
      >
        <MT53E1G16D1ZW
          name="U2"
          pcbX={0}
          pcbY={0}
          pcbRotation={90}
          noSchematicRepresentation
          noConnect={memoryNoConnect as any}
        />
      </breakout>

      {/* Each shared bus is consumed by both breakout phases, so this single
          preference assigns matching SoC and RAM escape layers. */}
      {fanoutBuses.map((fanoutBus) => (
        <Fragment key={fanoutBus.name}>
          <bus
            name={fanoutBus.name}
            connections={fanoutBus.connections}
            preferredLayer={fanoutBus.preferredLayer}
            routingPhaseIndex={fanoutBus.routingPhaseIndex}
          />
        </Fragment>
      ))}

      {connections.map(({ socSignal, memorySignal, traceName }) => (
        <Fragment key={traceName}>
          <trace
            name={traceName}
            from={`U1.${socSignal}`}
            to={`U2.${memorySignal}`}
          />
        </Fragment>
      ))}
    </board>
  )
}