From f4891a0aeefa9d7dc393d05df5caa1b34c0e3b93 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Mon, 29 Mar 2021 16:36:16 +0200 Subject: [PATCH] Added a "Matrix Placer" in Cumulus. * New: In Cumulus/plugins.block.matrix.RegisterMatrix, based on pattern matching the output of DFF, allow to rebuild and place a matrix of DFF constituting a RAM. It finally proven not useful because it is a too naive approach. Intermediate gates (buf_x2) must be found too. Most of the control signals have more than 20 sinks so gets splitted by HFNS and lastly, we would want the decoder to be integrated too, but they are not regulars. The right way to do it is to create a generator that build it then expose it in a way nMigen can understand (not the other way around, nMigen -> Yosys). --- cumulus/src/CMakeLists.txt | 1 + cumulus/src/plugins/alpha/block/matrix.py | 167 ++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 cumulus/src/plugins/alpha/block/matrix.py diff --git a/cumulus/src/CMakeLists.txt b/cumulus/src/CMakeLists.txt index 280da117..344f5556 100644 --- a/cumulus/src/CMakeLists.txt +++ b/cumulus/src/CMakeLists.txt @@ -59,6 +59,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/hfns2.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/hfns3.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/hfns4.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/matrix.py ) set ( pyPluginAlphaC2C ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/__init__.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/core2chip.py diff --git a/cumulus/src/plugins/alpha/block/matrix.py b/cumulus/src/plugins/alpha/block/matrix.py new file mode 100644 index 00000000..1eb537ca --- /dev/null +++ b/cumulus/src/plugins/alpha/block/matrix.py @@ -0,0 +1,167 @@ + +# 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/block/matrix.py" | +# +-----------------------------------------------------------------+ + + +import re +import sys +import os.path +import Cfg +from operator import itemgetter +from Hurricane import Breakpoint, DbU, Box, Transformation, Box, \ + Path, Layer, Occurrence, Net, RoutingPad, \ + Horizontal, Vertical, Contact, Pin, Plug, \ + Instance +import CRL +from CRL import RoutingLayerGauge +from helpers import trace, l, u, n +from helpers import dots +from helpers.io import ErrorMessage, WarningMessage, catch +from helpers.overlay import UpdateSession +from plugins import getParameter +from plugins.alpha import utils + + +af = CRL.AllianceFramework.get() + + +class RegisterMatrix ( object ): + + registerCell = af.getCell( 'sff1_x4', CRL.Catalog.State.Views ) + + def __init__ ( self, conf, cell, pattern ): + if not RegisterMatrix.registerCell: + raise ErrorMessage( 1, 'Matrix.__init__(): DFF Cell "sff1_x4" has not been found in the libraries.' ) + self.conf = conf + self.pattern = re.compile( pattern ) + self.matrix = [ [], ] + self.abutmentBox = Box() + for instance in cell.getInstances(): + if instance.getMasterCell() != RegisterMatrix.registerCell: + continue + output = instance.getPlug( instance.getMasterCell().getNet( 'q' ) ) + m = self.pattern.match( output.getNet().getName() ) + if not m: + continue + i = int( m.group('i') ) + j = int( m.group('j') ) + if len(self.matrix) <= i: + while len(self.matrix) <= i: + self.matrix.append( [] ) + if len(self.matrix[i]) <= j: + while len(self.matrix[i]) <= j: + self.matrix[i].append( None ) + if self.matrix[i][j] is not None: + print( ErrorMessage( 1, 'Matrix.__init__(): Duplicated matrix element [{},{}]' \ + .format(i,j) ) ) + continue + self.matrix[i][j] = instance + columns = len( self.matrix[0] ) + for i in range(1,self.rows): + if len(self.matrix[i]) != self.columns: + print( ErrorMessage( 1, 'Matrix.__init__(): Uneven matrix, column {} has a different size ({})' \ + .format(i,len(self.matrix[i])) ) ) + for j in range(len(self.matrix[i])): + if self.matrix[i][j] is None: + print( ErrorMessage( 1, '[ERROR] Holed matrix @[{},{}]' \ + .format(i,j) ) ) + regAb = RegisterMatrix.registerCell.getAbutmentBox() + print( ' o Matched matrix block on pattern "{}"'.format(self.pattern.pattern) ) + print( ' - Size {} x {}, {} x {} ' \ + .format( self.rows + , self.columns + , DbU.getValueString(regAb.getWidth ()*self.rows) + , DbU.getValueString(regAb.getHeight()*self.columns) + )) + + @property + def rows ( self ): + return len(self.matrix) + + @property + def columns ( self ): + return len(self.matrix[0]) + + def toXPitch ( self, x ): + """ + Returns the coordinate of the pitch immediately inferior to X. + If we are in a chip, compute coordinate in the *corona* system. + """ + offset = 0 + area = self.conf.coreAb + if self.conf.isCoreBlock: + offset = self.conf.icore.getTransformation().getTx() + self.conf.icore.getTransformation().applyOn( area ) + modulo = (x - offset - area.getXMin()) % self.conf.sliceStep + return x - modulo + + def toYSlice ( self, y ): + """ + Returns the coordinate of the slice immediately inferior to Y. + If we are in a chip, compute coordinate in the *corona* system. + """ + offset = 0 + area = self.conf.coreAb + if self.conf.isCoreBlock: + offset = self.conf.icore.getTransformation().getTy() + self.conf.icore.getTransformation().applyOn( area ) + #trace( 540, '\toffset:{}\n'.format(DbU.getValueString(offset)) ) + modulo = (y - offset - area.getYMin()) % self.conf.sliceHeight + return y - modulo + + def _getTransformation ( self, originX, originY ): + """Transform (originX,originY) into sliced coordinates relatives to the corona.""" + yoffset = 0 + if self.conf.isCoreBlock: + yoffset = self.conf.icore.getTransformation().getTy() + sliceHeight = self.conf.sliceHeight + x = self.toXPitch( originX ) + y = self.toYSlice( originY ) + slice = (y - yoffset) / sliceHeight + orientation = Transformation.Orientation.ID + y = slice * sliceHeight + yoffset + if slice % 2: + orientation = Transformation.Orientation.MY + y += sliceHeight + transf = Transformation( x, y, orientation ) + return transf + + def getWidth ( self ): + width = RegisterMatrix.registerCell.getAbutmentBox().getWidth() + return width * self.rows + + def getHeight ( self ): + height = RegisterMatrix.registerCell.getAbutmentBox().getHeight() + return height * self.columns + + def getAbutmentBox ( self ): + return self.abutmentBox + + def place ( self, origin ): + regAb = RegisterMatrix.registerCell.getAbutmentBox() + sliceHeight = self.conf.sliceHeight + regWidth = regAb.getWidth() + x = origin.getX() + for i in range(self.rows): + y = origin.getY() + for j in range(self.columns): + instance = self.matrix[i][j] + instance.setTransformation ( self._getTransformation(x,y) ) + instance.setPlacementStatus( Instance.PlacementStatus.FIXED ) + #print( '{} placed @{}'.format(instance,instance.getTransformation()) ) + y += sliceHeight + x += regWidth + self.abutmentBox = Box( origin.getX() + , origin.getY() + , origin.getX() + self.getWidth() + , origin.getY() + self.getHeight() )