coriolis/stratus1/src/stratus/st_shifter.py

218 lines
7.9 KiB
Python

# This file is part of the Coriolis Project.
# Copyright (C) Laboratoire LIP6 - Departement ASIM
# Universite Pierre et Marie Curie
#
# Main contributors :
# Christophe Alexandre <Christophe.Alexandre@lip6.fr>
# Sophie Belloeil <Sophie.Belloeil@lip6.fr>
# Hugo Clement <Hugo.Clement@lip6.fr>
# Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
# Damien Dupuis <Damien.Dupuis@lip6.fr>
# Christian Masson <Christian.Masson@lip6.fr>
# Marek Sroka <Marek.Sroka@lip6.fr>
#
# The Coriolis Project is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# The Coriolis Project is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with the Coriolis Project; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
#
# License-Tag
# Authors-Tag
# ===================================================================
#
# x-----------------------------------------------------------------x
# | |
# | C O R I O L I S |
# | S t r a t u s - Netlists/Layouts Description |
# | |
# | Author : Roselyne AVOT-CHOTIN - Sophie BELLOEIL |
# | E-mail : Sophie.Belloeil@asim.lip6.fr |
# | =============================================================== |
# | Py Module : "./st_shifter.py" |
# | *************************************************************** |
# | U p d a t e s |
# | |
# x-----------------------------------------------------------------x
from stratus import *
def getConfig ( type ) :
def getValue ( pos ) :
if (type & 2**pos) != 0 : return True
else : return False
config = { 'sticky' : None
, 'type' : {'log' : None, 'arith' : None, 'rot' : None, 'con' : None}
, 'dir' : {'left' : None, 'right' : None, 'con' : None}
}
config['sticky'] = getValue(5)
config['type']['log'] = getValue(4)
config['type']['arith'] = getValue(3)
config['type']['rot'] = getValue(2)
config['dir']['left'] = getValue(1)
config['dir']['right'] = getValue(0)
config['dir']['con'] = config['dir']['left'] and config['dir']['right']
config['type']['con'] = ((config['type']['log'] and config['type']['arith'])
or (config['type']['log'] and config['type']['rot'])
or (config['type']['arith'] and config['type']['rot']))
if not (config['dir']['left'] or config['dir']['right']):
raise Exception ( 'any of left or right directions are set' )
if not (config['type']['log'] or config['type']['arith'] or config['type']['rot']) :
raise Exception ( 'any of log or arith or rot types are set' )
return config
class Shifter ( Model ) :
def __init__ ( self, name, param ) :
Model.__init__ ( self, name, param )
self.nbit = param['nbit']
if self.nbit < 2: raise Exception ( "\n[Stratus ERROR] Shift : input arity should be greater than 1.\n" )
self.config = getConfig(param['type'])
self.cmd_width = log2 ( self.nbit )
def Interface ( self ) :
self.cmd = SignalIn ( "cmd", self.cmd_width )
self.i = SignalIn ( "i", self.nbit )
self.s = SignalOut ( "s", self.nbit )
if self.config['sticky'] : self.sticky = SignalOut ( "sticky", 1 )
if self.config['type']['con'] : self.type = SignalIn ( "typ", 3 )
if self.config['dir']['con'] : self.dir = SignalIn ( "dir", 1 )
self.vdd = VddIn ( "vdd" )
self.vss = VssIn ( "vss" )
def Netlist ( self ) :
nbStages = self.cmd_width
MuxOutput = {}
inj_lsb = {}
inj_msb = {}
mux_cmd = {}
one = Signal ( "one", 1 )
one <= One ( 1 )
zero = Signal ( "zero", 1 )
zero <= Zero ( 1 )
# Normalizing the input signals names
MuxOutput[0] = self.i
# signal giving the shift direction
if not self.config['dir']['con'] :
if self.config['dir']['left'] : dir = zero.Buffer()
else : dir = one.Buffer()
else :
dir = self.dir
# signals giving the type of shift
if self.config['type']['con'] :
log = self.type[2].Buffer()
arith = self.type[1].Buffer()
rot = self.type[0].Buffer()
else :
if self.config['type']['log'] : log = one.Buffer()
else : log = zero.Buffer()
if self.config['type']['arith'] : arith = one.Buffer()
else : arith = zero.Buffer()
if self.config['type']['rot'] : rot = one.Buffer()
else : rot = zero.Buffer()
# Building the control signals
c0 = Signal ( "c0", nbStages )
c1 = Signal ( "c1", nbStages )
for stage in range ( nbStages ) :
c1[stage] <= ~self.cmd[stage]
c0[stage] <= c1[stage] | dir
# Connecting the mux matrix
for stage in range ( nbStages ) :
valDec = 2**stage
inj_lsb[stage] = Signal ( "inj_lsb%d" % stage, valDec )
inj_msb[stage] = Signal ( "inj_msb%d" % stage, valDec )
MuxOutput[stage+1] = Signal ( "mxout%d" % (stage+1), self.nbit )
if ( self.nbit-valDec-1 ) == 0 : MuxInput0 = MuxOutput[stage][0]
else : MuxInput0 = MuxOutput[stage][self.nbit-valDec-1:0]
for i in range ( valDec ) :
inj_lsb[stage][i] <= (((MuxOutput[stage][i] & dir) | (MuxOutput[stage][self.nbit-valDec+i] & ~dir)) & rot) | (dir & ~rot)
MuxInput0 = Cat ( MuxInput0, inj_lsb[stage] )
MuxInput1 = MuxOutput[stage]
# mettre zero, signe ou rot
for i in range ( valDec ) :
inj_msb[stage][i] <= (inj_lsb[stage][i] & rot) | (self.i[self.nbit-1] & arith) | (zero & log)
if (self.nbit-1) == valDec : MuxInput2 = MuxOutput[stage][self.nbit-1]
else : MuxInput2 = MuxOutput[stage][self.nbit-1:valDec]
MuxInput2 = Cat ( inj_msb[stage], MuxInput2 )
mux_cmd[stage] = Cat ( c0[stage], c1[stage] )
MuxOutput[stage + 1] <= mux_cmd[stage].Mux ( { '0' : MuxInput0
, '1' : MuxInput0
, '2' : MuxInput2
, '3' : MuxInput1
}
)
# Normalizing the output signal names
self.s <= MuxOutput[nbStages]
def GetModelName ( cls, param ) :
modelName = "shifter"
modelName += "_"
modelName += str(param['nbit'])
if param['type'] == 0x12 : modelName += "_ll"
elif param['type'] == 0xa : modelName += "_al"
elif param['type'] == 0x6 : modelName += "_cl"
elif param['type'] == 0x11 : modelName += "_lr"
elif param['type'] == 0x9 : modelName += "_ar"
elif param['type'] == 0x5 : modelName += "_cr"
return modelName
GetModelName = classmethod ( GetModelName )
def GetParam ( cls ):
return {'nbit' : 'integer', 'type' : 'integer'}
GetParam = classmethod ( GetParam )