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:
parent
fa4084f3d9
commit
f4891a0aee
|
@ -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
|
||||
|
|
|
@ -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() )
|
Loading…
Reference in New Issue