{ "cells": [ { "cell_type": "markdown", "id": "1084cd34", "metadata": { "lines_to_next_cell": 2 }, "source": [ "# PCIE virtual compliance\n", "\n", "This example shows how to generate a compliance report in PyAEDT using\n", "the ``VirtualCompliance`` class.\n", "\n", "Keywords: **Circuit**, **Automatic report**, **virtual compliance**." ] }, { "cell_type": "markdown", "id": "f927454a", "metadata": {}, "source": [ "## Perform imports and define constants\n", "Import the required packages." ] }, { "cell_type": "code", "execution_count": null, "id": "9ef13dd2", "metadata": {}, "outputs": [], "source": [ "import os.path\n", "import tempfile\n", "import time" ] }, { "cell_type": "code", "execution_count": null, "id": "dfba9a56", "metadata": {}, "outputs": [], "source": [ "import ansys.aedt.core\n", "from ansys.aedt.core.visualization.post.compliance import VirtualCompliance" ] }, { "cell_type": "markdown", "id": "1ef87c8c", "metadata": {}, "source": [ "## Define constants" ] }, { "cell_type": "code", "execution_count": null, "id": "ee0f5186", "metadata": {}, "outputs": [], "source": [ "AEDT_VERSION = \"2024.2\"\n", "NUM_CORES = 4\n", "NG_MODE = False # Open AEDT UI when it is launched." ] }, { "cell_type": "markdown", "id": "7386a31b", "metadata": {}, "source": [ "## Create temporary directory\n", "\n", "Create a temporary directory where downloaded data or\n", "dumped data can be stored. In this example, the temporary directory\n", "in where the example is stored and simulation data is saved.\n", "If you'd like to retrieve the project data for subsequent use,\n", "the temporary folder name is given by ``temp_folder.name``." ] }, { "cell_type": "code", "execution_count": null, "id": "9d551e1f", "metadata": {}, "outputs": [], "source": [ "temp_folder = tempfile.TemporaryDirectory(suffix=\".ansys\")" ] }, { "cell_type": "markdown", "id": "2fbf6f3c", "metadata": {}, "source": [ "## Download example data" ] }, { "cell_type": "code", "execution_count": null, "id": "ed950f0c", "metadata": {}, "outputs": [], "source": [ "download_folder = ansys.aedt.core.downloads.download_file(\n", " source=\"pcie_compliance\", destination=temp_folder.name\n", ")\n", "project_folder = os.path.join(download_folder, \"project\")\n", "project_path = os.path.join(project_folder, \"PCIE_GEN5_only_layout.aedtz\")" ] }, { "cell_type": "markdown", "id": "c8a27a80", "metadata": {}, "source": [ "## Launch AEDT and solve layout\n", "\n", "Open the HFSS 3D Layout project and analyze it using the SIwave solver.\n", "Before solving, this code ensures that the model is solved from DC to 70GHz and that\n", "causality and passivity are enforced." ] }, { "cell_type": "code", "execution_count": null, "id": "cd35c454", "metadata": {}, "outputs": [], "source": [ "h3d = ansys.aedt.core.Hfss3dLayout(\n", " project=project_path, version=AEDT_VERSION, non_graphical=NG_MODE\n", ")\n", "h3d.remove_all_unused_definitions()\n", "h3d.edit_cosim_options(simulate_missing_solution=False)\n", "h3d.setups[0].sweeps[0].props[\"EnforcePassivity\"] = True\n", "h3d.setups[0].sweeps[0].props[\"Sweeps\"][\"Data\"] = \"LIN 0MHz 70GHz 0.1GHz\"\n", "h3d.setups[0].sweeps[0].props[\"EnforceCausality\"] = True\n", "h3d.setups[0].sweeps[0].update()\n", "h3d.analyze(cores=NUM_CORES)\n", "h3d = ansys.aedt.core.Hfss3dLayout()\n", "touchstone_path = h3d.export_touchstone()" ] }, { "cell_type": "markdown", "id": "686dfad0", "metadata": {}, "source": [ "## Create LNA project\n", "\n", "Use the LNA (linear network analysis) setup to retrieve Touchstone files\n", "and generate frequency domain reports." ] }, { "cell_type": "code", "execution_count": null, "id": "f2b51bf1", "metadata": {}, "outputs": [], "source": [ "circuit = ansys.aedt.core.Circuit(project=h3d.project_name, design=\"Touchstone\")\n", "status, diff_pairs, comm_pairs = circuit.create_lna_schematic_from_snp(\n", " input_file=touchstone_path,\n", " start_frequency=0,\n", " stop_frequency=70,\n", " auto_assign_diff_pairs=True,\n", " separation=\".\",\n", " pattern=[\"component\", \"pin\", \"net\"],\n", " analyze=True,\n", ")\n", "insertion = circuit.get_all_insertion_loss_list(\n", " drivers=diff_pairs,\n", " receivers=diff_pairs,\n", " drivers_prefix_name=\"X1\",\n", " receivers_prefix_name=\"U1\",\n", " math_formula=\"dB\",\n", " nets=[\"RX0\", \"RX1\", \"RX2\", \"RX3\"],\n", ")\n", "return_diff = circuit.get_all_return_loss_list(\n", " excitations=diff_pairs,\n", " excitation_name_prefix=\"X1\",\n", " math_formula=\"dB\",\n", " nets=[\"RX0\", \"RX1\", \"RX2\", \"RX3\"],\n", ")\n", "return_comm = circuit.get_all_return_loss_list(\n", " excitations=comm_pairs,\n", " excitation_name_prefix=\"COMMON_X1\",\n", " math_formula=\"dB\",\n", " nets=[\"RX0\", \"RX1\", \"RX2\", \"RX3\"],\n", ")" ] }, { "cell_type": "markdown", "id": "2de08a5e", "metadata": {}, "source": [ "## Create TDR project\n", "\n", "Create a TDR project to compute transient simulation and retrieve\n", "the TDR measurement on a differential pair.\n", "The original circuit schematic is duplicated and modified to achieve this target." ] }, { "cell_type": "code", "execution_count": null, "id": "8b1b938d", "metadata": {}, "outputs": [], "source": [ "result, tdr_probe_name = circuit.create_tdr_schematic_from_snp(\n", " input_file=touchstone_path,\n", " tx_schematic_pins=[\"X1.A2.PCIe_Gen4_RX0_P\"],\n", " tx_schematic_differential_pins=[\"X1.A3.PCIe_Gen4_RX0_N\"],\n", " termination_pins=[\"U1.AP26.PCIe_Gen4_RX0_P\", \"U1.AN26.PCIe_Gen4_RX0_N\"],\n", " differential=True,\n", " rise_time=35,\n", " use_convolution=True,\n", " analyze=True,\n", " design_name=\"TDR\",\n", ")" ] }, { "cell_type": "markdown", "id": "b019ad1a", "metadata": {}, "source": [ "## Create AMI project\n", "\n", "Create an Ibis AMI project to compute an eye diagram simulation and retrieve\n", "eye mask violations." ] }, { "cell_type": "code", "execution_count": null, "id": "231784b2", "metadata": {}, "outputs": [], "source": [ "_, eye_curve_tx, eye_curve_rx = circuit.create_ami_schematic_from_snp(\n", " input_file=touchstone_path,\n", " ibis_tx_file=os.path.join(project_folder, \"models\", \"pcieg5_32gt.ibs\"),\n", " tx_buffer_name=\"1p\",\n", " rx_buffer_name=\"2p\",\n", " tx_schematic_pins=[\"U1.AM25.PCIe_Gen4_TX0_CAP_P\"],\n", " rx_schematic_pins=[\"X1.B2.PCIe_Gen4_TX0_P\"],\n", " tx_schematic_differential_pins=[\"U1.AL25.PCIe_Gen4_TX0_CAP_N\"],\n", " rx_schematic_differentialial_pins=[\"X1.B3.PCIe_Gen4_TX0_N\"],\n", " ibis_tx_component_name=\"Spec_Model\",\n", " use_ibis_buffer=False,\n", " differential=True,\n", " bit_pattern=\"random_bit_count=2.5e3 random_seed=1\",\n", " unit_interval=\"31.25ps\",\n", " use_convolution=True,\n", " analyze=True,\n", " design_name=\"AMI\",\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "080955d7", "metadata": {}, "outputs": [], "source": [ "circuit.save_project()" ] }, { "cell_type": "markdown", "id": "52a6b8ba", "metadata": {}, "source": [ "## Create virtual compliance report\n", "\n", "Initialize the ``VirtualCompliance`` class\n", "and set up the main project information needed to generate the report.\n" ] }, { "cell_type": "markdown", "id": "2e88f5aa", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "id": "c5b0d0b5", "metadata": {}, "source": [ "" ] }, { "cell_type": "code", "execution_count": null, "id": "b5bdeb7d", "metadata": {}, "outputs": [], "source": [ "template = os.path.join(download_folder, \"pcie_gen5_templates\", \"main.json\")" ] }, { "cell_type": "code", "execution_count": null, "id": "7d81bc3b", "metadata": {}, "outputs": [], "source": [ "v = VirtualCompliance(circuit.desktop_class, str(template))" ] }, { "cell_type": "markdown", "id": "28cbac01", "metadata": {}, "source": [ "## Customize project and design\n", "\n", "Define the path to the project file and the\n", "design names to be used in each report generation.\n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "id": "fb7fc62d", "metadata": {}, "outputs": [], "source": [ "v.project_file = circuit.project_file\n", "v.reports[\"insertion losses\"].design_name = \"LNA\"\n", "v.reports[\"return losses\"].design_name = \"LNA\"\n", "v.reports[\"common mode return losses\"].design_name = \"LNA\"\n", "v.reports[\"tdr from circuit\"].design_name = \"TDR\"\n", "v.reports[\"eye1\"].design_name = \"AMI\"\n", "v.reports[\"eye3\"].design_name = \"AMI\"\n", "v.parameters[\"erl\"].design_name = \"LNA\"\n", "v.specs_folder = os.path.join(download_folder, \"readme_pictures\")" ] }, { "cell_type": "markdown", "id": "c2378637", "metadata": {}, "source": [ "## Define trace names\n", "\n", "Change the trace name with projects and users.\n", "Reuse the compliance template and update traces accordingly." ] }, { "cell_type": "code", "execution_count": null, "id": "b22ccfae", "metadata": {}, "outputs": [], "source": [ "v.reports[\"insertion losses\"].traces = insertion" ] }, { "cell_type": "code", "execution_count": null, "id": "3fa07544", "metadata": {}, "outputs": [], "source": [ "v.reports[\"return losses\"].traces = return_diff" ] }, { "cell_type": "code", "execution_count": null, "id": "85e4b126", "metadata": {}, "outputs": [], "source": [ "v.reports[\"common mode return losses\"].traces = return_comm" ] }, { "cell_type": "code", "execution_count": null, "id": "50624464", "metadata": {}, "outputs": [], "source": [ "v.reports[\"eye1\"].traces = eye_curve_tx\n", "v.reports[\"eye3\"].traces = eye_curve_tx\n", "v.reports[\"tdr from circuit\"].traces = tdr_probe_name\n", "v.parameters[\"erl\"].trace_pins = [\n", " [\n", " \"X1.A5.PCIe_Gen4_RX1_P\",\n", " \"X1.A6.PCIe_Gen4_RX1_N\",\n", " \"U1.AR25.PCIe_Gen4_RX1_P\",\n", " \"U1.AP25.PCIe_Gen4_RX1_N\",\n", " ],\n", " [7, 8, 18, 17],\n", "]" ] }, { "cell_type": "markdown", "id": "3bea982c", "metadata": {}, "source": [ "## Generate PDF report\n", "\n", "Generate the reports and produce a PDF report.\n", "\n", "\n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "id": "0b22849c", "metadata": {}, "outputs": [], "source": [ "v.create_compliance_report()" ] }, { "cell_type": "markdown", "id": "0dc35817", "metadata": {}, "source": [ "## Release AEDT" ] }, { "cell_type": "code", "execution_count": null, "id": "97df4da2", "metadata": {}, "outputs": [], "source": [ "h3d.release_desktop()\n", "# Wait 3 seconds to allow AEDT to shut down before cleaning the temporary directory.\n", "time.sleep(3)" ] }, { "cell_type": "markdown", "id": "615d5aad", "metadata": {}, "source": [ "## Clean up\n", "\n", "All project files are saved in the folder ``temp_folder.name``.\n", "If you've run this example as a Jupyter notebook, you\n", "can retrieve those project files. The following cell\n", "removes all temporary files, including the project folder." ] }, { "cell_type": "code", "execution_count": null, "id": "69d59c59", "metadata": {}, "outputs": [], "source": [ "temp_folder.cleanup()" ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-all", "main_language": "python", "notebook_metadata_filter": "-all" } }, "nbformat": 4, "nbformat_minor": 5 }