From d00a51029eb0f21695ae8b452f04cf34b853c41b Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Thu, 18 Feb 2021 00:07:03 +0100 Subject: [PATCH] External block wrapper support added in cumulus/plugins.macro. * New: In cumulus/plugins.macro.macro.Macro() to encapsulate foreign blocks. Round their size to an exact number of GCells and a guard of one GCell. External terminal must be on the periphery and will be made to stick out in the guard ring. This is sub-optimal for now but provide a workaround some Katana bad assumptions. A "perpandicular padding" is also added to terminals to limit the offgrid related problems. Have to optimize that in conjuction with Katana. --- cumulus/src/CMakeLists.txt | 4 + cumulus/src/plugins/alpha/macro/__init__.py | 0 cumulus/src/plugins/alpha/macro/macro.py | 216 ++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 cumulus/src/plugins/alpha/macro/__init__.py create mode 100644 cumulus/src/plugins/alpha/macro/macro.py diff --git a/cumulus/src/CMakeLists.txt b/cumulus/src/CMakeLists.txt index d781d743..f3eaf423 100644 --- a/cumulus/src/CMakeLists.txt +++ b/cumulus/src/CMakeLists.txt @@ -73,6 +73,9 @@ ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/pads.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/chip.py ) + set ( pyPluginAlphaMacro ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/macro/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/macro/macro.py + ) install ( FILES ${pySources} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus ) install ( FILES ${pyPlugins} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins ) @@ -83,4 +86,5 @@ install ( FILES ${pyPluginAlphaBlock} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins/alpha/block ) install ( FILES ${pyPluginAlphaC2C} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins/alpha/core2chip ) install ( FILES ${pyPluginAlphaChip} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins/alpha/chip ) + install ( FILES ${pyPluginAlphaMacro} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins/alpha/macro ) install ( PROGRAMS ${pyTools} DESTINATION bin ) diff --git a/cumulus/src/plugins/alpha/macro/__init__.py b/cumulus/src/plugins/alpha/macro/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cumulus/src/plugins/alpha/macro/macro.py b/cumulus/src/plugins/alpha/macro/macro.py new file mode 100644 index 00000000..f53e2111 --- /dev/null +++ b/cumulus/src/plugins/alpha/macro/macro.py @@ -0,0 +1,216 @@ + +# This file is part of the Coriolis Software. +# Copyright (c) SU 2021-2021, All Rights Reserved +# +# +-----------------------------------------------------------------+ +# | C O R I O L I S | +# | C u m u l u s - P y t h o n T o o l s | +# | | +# | Author : Jean-Paul CHAPUT | +# | E-mail : Jean-Paul.Chaput@lip6.fr | +# | =============================================================== | +# | Python : "./plugins/macro/macro.py" | +# +-----------------------------------------------------------------+ + + +from __future__ import print_function +import sys +import os.path +import Cfg +from Hurricane import Breakpoint, DbU, Box, Transformation, Point, \ + Box, Path, Layer, Occurrence, Net, \ + NetExternalComponents, RoutingPad, Pad, \ + Horizontal, Vertical, Contact, Pin, Plug, \ + Cell, Instance +import CRL +from CRL import RoutingLayerGauge +from helpers import trace, dots +from helpers.io import ErrorMessage, WarningMessage, catch +from helpers.overlay import UpdateSession + + +# ---------------------------------------------------------------------------- +# Class : "macro.Macro". + +class Macro ( object ): + """ + Encapsulate the layout of a user-defined block so it can be used + in the Coriolis P&R flow. Maintain a lookup table of already + processeds macros so they are modified only once. + """ + + LUT = {} + + @staticmethod + def lookup ( macroCell ): + if Macro.LUT.has_key(macroCell): return True + return False + + @staticmethod + def getPPitch ( rg, metal ): + depth = rg.getLayerDepth( metal ) + if depth < rg.getDepth(): pdepth = depth + 1 + else: pdepth = depth - 1 + return rg.getLayerPitch( pdepth ) + + @staticmethod + def place ( instance, transf, status ): + ab = instance.getMasterCell().getAbutmentBox() + abShift = Transformation( -ab.getXMin(), -ab.getYMin(), Transformation.Orientation.ID ) + abShift.applyOn( transf ) + instance.setTransformation( transf ) + instance.setPlacementStatus( status ) + + @staticmethod + def wrap ( macroCell, gaugeName, hMargin, vMargin ): + """ + Encapsulate the macro cell, if not already done. Returns True + if the encapsulation actually takes place. + + :param macroCell: The macro cell to be encapsulated. + :param gaugeName: The name of the RoutingGauge to use. + :param xMargin: The horizontal margin, expressed in pitchs of the + lowest vertical routing metal (usually METAL3). + :param yMargin: The vertical margin, expressed in pitchs of the + lowesthorizontal routing metal (usually METAL2). + + The abutment box of the block is enlarged so both it's dimensions + are a multiple of the sliceHeight. It is then enlarged of one more + sliceHeight on each side. The resulting block will: + + * Exactly fit the GCell grid. + * Eternal pins will be isolated in fully empty GCells on the side. + Due to some quirks in the P&R algorithm, putting them in GCells + that are half free and half occluded by the block itself may + cause (stupid) deadlock to appear. + """ + if Macro.lookup(macroCell): return False + + af = CRL.AllianceFramework.get() + rg = af.getRoutingGauge( gaugeName ) + ab = macroCell.getAbutmentBox() + sliceHeight = af.getCellGauge( gaugeName ).getSliceHeight() + westPins = [] + eastPins = [] + northPins = [] + southPins = [] + for net in macroCell.getNets(): + if not net.isExternal() or net.isSupply() or net.isClock(): + continue + for component in net.getComponents(): + if not NetExternalComponents.isExternal(component): + continue + bb = component.getBoundingBox() + if not ab.isConstrainedBy(bb): + continue + if ab.getXMax() == bb.getXMax(): eastPins.append( component ) + elif ab.getXMin() == bb.getXMin(): westPins.append( component ) + elif ab.getYMax() == bb.getYMax(): northPins.append( component ) + elif ab.getYMin() == bb.getYMin(): southPins.append( component ) + innerAb = ab + xAdjust = 0 + yAdjust = 0 + if ab.getWidth () % sliceHeight: xAdjust = sliceHeight - ab.getWidth () % sliceHeight + if ab.getHeight() % sliceHeight: yAdjust = sliceHeight - ab.getHeight() % sliceHeight + innerAb.inflate( 0, 0, xAdjust, yAdjust ) + outerAb = innerAb + outerAb.inflate( sliceHeight ) + + with UpdateSession(): + for component in westPins: + NetExternalComponents.setInternal( component ) + pitch = rg.getPitch( component.getLayer() ) + ppitch = Macro.getPPitch( rg, component.getLayer() ) + bb = component.getBoundingBox() + yAxis = bb.getYCenter() + xMax = bb.getXMin() + xMin = xMax - hMargin*ppitch + width = bb.getHeight() + horizontal = Horizontal.create( component.getNet() + , component.getLayer() + , yAxis + , width + , xMin + , xMax + ) + horizontal = Horizontal.create( component.getNet() + , component.getLayer() + , yAxis + , pitch + , xMin + , xMax - (hMargin-1) * ppitch + ) + NetExternalComponents.setExternal( horizontal ) + for component in eastPins: + NetExternalComponents.setInternal( component ) + pitch = rg.getPitch( component.getLayer() ) + ppitch = Macro.getPPitch( rg, component.getLayer() ) + bb = component.getBoundingBox() + yAxis = bb.getYCenter() + xMin = innerAb.getXMax() + xMax = xMin + hMargin*ppitch + width = bb.getHeight() + horizontal = Horizontal.create( component.getNet() + , component.getLayer() + , yAxis + , width + , xMin + , xMax + ) + horizontal = Horizontal.create( component.getNet() + , component.getLayer() + , yAxis + , pitch + , xMin + (hMargin-1) * ppitch + , xMax + ) + NetExternalComponents.setExternal( horizontal ) + for component in southPins: + NetExternalComponents.setInternal( component ) + pitch = rg.getPitch( component.getLayer() ) + ppitch = Macro.getPPitch( rg, component.getLayer() ) + bb = component.getBoundingBox() + xAxis = bb.getXCenter() + yMax = bb.getYMin() + yMin = xMax - vMargin*ppitch + width = bb.getWidth() + vertical = Vertical.create( component.getNet() + , component.getLayer() + , xAxis + , width + , yMin + , yMax + ) + vertical = Vertical.create( component.getNet() + , component.getLayer() + , xAxis + , width + , yMin + , yMax - (vMargin-1) * ppitch + ) + NetExternalComponents.setExternal( vertical ) + for component in northPins: + NetExternalComponents.setInternal( component ) + pitch = rg.getPitch( component.getLayer() ) + ppitch = Macro.getPPitch( rg, component.getLayer() ) + bb = component.getBoundingBox() + xAxis = bb.getXCenter() + yMin = innerAb.getYMax() + yMax = xMin + vMargin*ppitch + width = bb.getWidth() + vertical = Vertical.create( component.getNet() + , component.getLayer() + , xAxis + , width + , yMin + , yMax + ) + vertical = Vertical.create( component.getNet() + , component.getLayer() + , xAxis + , width + , yMin + (vMargin-1) * ppitch + , yMax + ) + NetExternalComponents.setExternal( vertical ) + macroCell.setAbutmentBox( outerAb )