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).
This commit is contained in:
Jean-Paul Chaput 2021-03-29 16:36:16 +02:00
parent fa4084f3d9
commit f4891a0aee
2 changed files with 168 additions and 0 deletions

View File

@ -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

View File

@ -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() )