coriolis/stratus1/src/stratus/st_slansky.py

410 lines
13 KiB
Python
Raw Normal View History

2010-07-12 10:33:22 -05:00
#!/usr/bin/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_slansky.py" |
# | *************************************************************** |
# | U p d a t e s |
# | |
# x-----------------------------------------------------------------x
from stratus import *
class Sub ( Model ) :
def __init__(self, name, param):
Model.__init__(self, name, param)
if 'nbit' in param:
self.nbit = param['nbit']
self.nbit0 = self.nbit
self.nbit1 = self.nbit
else:
self.nbit0 = param['nbit0']
self.nbit1 = param['nbit1']
self.nbit = max(self.nbit0,self.nbit1)
if 'signed' not in param : self._signed = True
else : self._signed = param['signed']
if 'extended' not in param : self._extended = False
else : self._extended = param['extended']
if (self.nbit < 2): raise Exception ( "\n[Stratus ERROR] slansky : input arity should be greater than 1.\n" )
2010-07-12 10:33:22 -05:00
def Interface(self):
self.i0 = SignalIn("i0", self.nbit0)
self.i1 = SignalIn("i1", self.nbit1)
if self._extended : self.o = SignalOut("o", self.nbit+1)
else : self.o = SignalOut("o", self.nbit)
self.vdd = VddIn("vdd")
self.vss = VssIn("vss")
def Netlist(self):
# extand the inputs to have the same width
if (self.nbit0 < self.nbit) :
i0e = Signal("i0e", self.nbit)
if self._signed : i0e <= self.i0.Extend(self.nbit,'signed')
else : i0e <= self.i0.Extend(self.nbit,'zero')
else:
i0e = self.i0
if (self.nbit1 < self.nbit) :
i1e = Signal("i1e", self.nbit)
if self._signed : i1e <= self.i1.Extend(self.nbit,'signed')
else : i1e <= self.i1.Extend(self.nbit,'zero')
else:
i1e = self.i1
Generate ( "Slansky", "slansky_cin_%d" % ( self.nbit ), param={'nbit':self.nbit,'cin':True, 'extended':self._extended} )
Inst ( "slansky_cin_%d" % ( self.nbit )
, map = { 'i0' : i0e
, 'i1' : ~i1e
, 'cin' : One(1)
, 'o' : self.o
, 'vdd' : self.vdd
, 'vss' : self.vss
}
)
def GetParam ( cls ):
return {'nbit' : 'integer', 'nbit0' : 'integer', 'nbit1' : 'integer'}
GetParam = classmethod ( GetParam )
class Slansky ( Model ) :
def __init__(self, name, param):
Model.__init__(self, name, param)
if 'nbit' in param:
self.nbit = param['nbit']
self.nbit0 = self.nbit
self.nbit1 = self.nbit
else:
self.nbit0 = param['nbit0']
self.nbit1 = param['nbit1']
self.nbit = max(self.nbit0,self.nbit1)
if 'signed' not in param : self._signed = True
else : self._signed = param['signed']
if 'extended' not in param : self._extended = False
else : self._extended = param['extended']
if 'cin' not in param : self._cin = False
else : self._cin = param['cin']
if (self.nbit < 2): raise Exception ( "\n[Stratus ERROR] slansky : input arity should be greater than 1.\n" )
2010-07-12 10:33:22 -05:00
def Interface(self):
self.i0 = SignalIn("i0", self.nbit0)
self.i1 = SignalIn("i1", self.nbit1)
if self._cin : self.cin = SignalIn("cin", 1)
if self._extended : self.o = SignalOut("o", self.nbit+1)
else : self.o = SignalOut("o", self.nbit)
self.vdd = VddIn("vdd")
self.vss = VssIn("vss")
def Netlist(self):
# extand the inputs to have the same width
if (self.nbit0 < self.nbit) :
i0e = Signal("i0e", self.nbit)
if self._signed : i0e <= self.i0.Extend(self.nbit,'signed')
else : i0e <= self.i0.Extend(self.nbit,'zero')
else:
i0e = self.i0
if (self.nbit1 < self.nbit) :
i1e = Signal("i1e", self.nbit)
if self._signed : i1e <= self.i1.Extend(self.nbit,'signed')
else : i1e <= self.i1.Extend(self.nbit,'zero')
else:
i1e = self.i1
# pigi preprocessing
[p,g] = pigi(i0e,i1e)
# Slansky algorithm
[pp,gg] = pg_tree(p,g,'slansky')
# postprocessing :
if self._cin : self.o[0] <= p[0] ^ self.cin
else : self.o[0] <= p[0].Buffer()
for i in range(1,self.nbit):
if self._cin : self.o[i] <= p[i] ^ (gg[i-1] | (pp[i-1] & self.cin))
else : self.o[i] <= p[i] ^ gg[i-1]
if self._extended:
if self._signed:
ovft = Signal("ovft",1)
if self._cin:
ovft <= (gg[self.nbit-1] | (pp[self.nbit-1] & self.cin)) ^ (gg[self.nbit-2] | (pp[self.nbit-2] & self.cin))
# pb inout asimut remplacement de o[nbit-1] par sa valeur
# self.o[self.nbit] <= (self.o[self.nbit-1] & ~ovf) | (cout & ovf)
self.o[self.nbit] <= ((p[self.nbit-1] ^ (gg[self.nbit-2] | (pp[self.nbit-2] & self.cin))) & ~ovft) | (gg[self.nbit-1] & ovft)
else:
ovft <= gg[self.nbit-1] ^ gg[self.nbit-2]
# pb inout asimut remplacement de o[nbit-1] par sa valeur
# self.o[self.nbit] <= (self.o[self.nbit-1] & ~ovf) | (cout & ovf)
self.o[self.nbit] <= ((p[self.nbit-1] ^ gg[self.nbit-2]) & ~ovft) | (gg[self.nbit-1] & ovft)
else:
if self._cin:
self.o[self.nbit] <= gg[self.nbit-1] | (pp[self.nbit-1] & self.cin)
else:
self.o[self.nbit] <= gg[self.nbit-1].Buffer()
def GetModelName ( cls, param ) :
name = 'slansky'
if 'nbit' in param:
name += '_%d' % (param['nbit'])
else:
if param['nbit0'] != param['nbit1'] : name += '_%dx%d' % (param['nbit0'], param['nbit1'])
else : name += '_%d' % (param['nbit0'])
name += "bits"
if ('cin' in param) and (param['cin']) : name += '_cin'
return name
GetModelName = classmethod ( GetModelName )
def GetParam ( cls ):
return {'nbit' : 'integer', 'nbit0' : 'integer', 'nbit1' : 'integer', 'cin' : 'boolean'}
GetParam = classmethod ( GetParam )
####################################################################################################
nb_pigi = 0
nb_pg_tree = 0
def pigi(a,b):
global nb_pigi
nb_pigi += 1
pi = Signal("pi%d_a" %nb_pigi,a._arity)
gi = Signal("gi%d_a" %nb_pigi,a._arity)
Generate ( "st_slansky.PiGiBus", "pigibus%d" % a._arity, param = {'nbit' : a._arity} )
Inst("pigibus%d" % a._arity,
map = {
'a' : a,
'b' : b,
'pi' : pi,
'gi' : gi,
'vdd' : a._st_cell._st_vdds[0],
'vss' : a._st_cell._st_vsss[0]
},
)
return [pi,gi]
class PiGiBus(Model):
def __init__(self, name, param):
Model.__init__(self, name, param)
self.nbit = param['nbit']
if self.nbit < 1:
raise Exception ( 'PiGiBus : input arity should be greater than 0' )
2010-07-12 10:33:22 -05:00
def Interface(self):
self.a = SignalIn("a",self.nbit)
self.b = SignalIn("b",self.nbit)
self.pi = SignalOut("pi",self.nbit)
self.gi = SignalOut("gi",self.nbit)
self.vdd = VddIn("vdd")
self.vss = VssIn("vss")
def Netlist(self):
for i in range (self.nbit):
Generate ( "st_slansky.PiGi", "pigi" )
Inst("pigi",
map = {
'a' : self.a[i],
'b' : self.b[i],
'pi' : self.pi[i],
'gi' : self.gi[i],
'vdd': self.vdd,
'vss': self.vss
}
)
def GetParam ( cls ):
return {'nbit' : 'integer'}
GetParam = classmethod ( GetParam )
class PiGi(Model):
def Interface(self):
self.a = SignalIn("a",1)
self.b = SignalIn("b",1)
self.pi = SignalOut("pi",1)
self.gi = SignalOut("gi",1)
self.vdd = VddIn("vdd")
self.vss = VssIn("vss")
def Netlist(self):
self.pi <= self.a ^ self.b
self.gi <= self.a & self.b
########################
def pg_tree(pi,gi,algo):
global nb_pg_tree
nb_pg_tree += 1
p = Signal("p%d_a" %nb_pg_tree,pi._arity)
g = Signal("g%d_a" %nb_pg_tree,pi._arity)
Generate ( "st_slansky.PGTree", "pgtree%d%s" % ( pi._arity, algo ), param = {'nbit' : pi._arity, 'algo' : algo} )
Inst("pgtree%d%s" % ( pi._arity, algo ),
map = {
'pi' : pi,
'gi' : gi,
'p' : p,
'g' : g,
'vdd' : pi._st_cell._st_vdds[0],
'vss' : pi._st_cell._st_vsss[0]
}
)
return [p,g]
class PGTree(Model):
def __init__(self, name, param):
Model.__init__(self, name, param)
self.nbit = param['nbit']
if self.nbit < 1:
raise Exception ( 'input arity should be greater than 0' )
2010-07-12 10:33:22 -05:00
self.algo = param['algo']
if self.algo != 'slansky':
raise Exception ( '%s algorithm is not yet implemented' %self.algo )
2010-07-12 10:33:22 -05:00
def Interface(self):
self.pi = SignalIn("pi",self.nbit)
self.gi = SignalIn("gi",self.nbit)
self.p = SignalOut("p",self.nbit)
self.g = SignalOut("g",self.nbit)
self.vdd = VddIn("vdd")
self.vss = VssIn("vss")
def Netlist(self):
nb_stages = log2(self.nbit)
matrix = prefixMatrix(self.algo,self.nbit)
p = []
g = []
p.append(self.pi)
g.append(self.gi)
# group propagation
Generate ( "st_slansky.PG", "pg" )
for i in range(0, nb_stages):
p.append(Signal("p%d" %(i+1), self.nbit))
g.append(Signal("g%d" %(i+1), self.nbit))
for j in range(0, self.nbit):
if (j % 2**i) == 0:
k = j-1
if matrix[i][j] == 1:
Inst("pg",
map = {
'p1' : p[i][j],
'g1' : g[i][j],
'p2' : p[i][k],
'g2' : g[i][k],
'p' : p[i+1][j],
'g' : g[i+1][j],
'vdd' : self.vdd,
'vss' : self.vss
}
)
else:
p[i+1][j] <= p[i][j].Buffer()
g[i+1][j] <= g[i][j].Buffer()
self.p <= p[nb_stages].Buffer()
self.g <= g[nb_stages].Buffer()
def GetParam ( cls ):
return {'nbit' : 'integer'}
GetParam = classmethod ( GetParam )
class PG(Model):
def Interface(self):
self.p1 = SignalIn("p1",1)
self.g1 = SignalIn("g1",1)
self.p2 = SignalIn("p2",1)
self.g2 = SignalIn("g2",1)
self.p = SignalOut("p",1)
self.g = SignalOut("g",1)
self.vdd = VddIn("vdd")
self.vss = VssIn("vss")
def Netlist(self):
self.p <= self.p1 & self.p2
self.g <= self.g1 | (self.g2 & self.p1)
def prefixMatrix(algo,size):
if algo == 'slansky':
nb_stages = log2(size)
matrix = []
for i in range(0, nb_stages):
matrix.append([])
connection = True
j = -1
while (j < size-1):
connection = not connection
k = -1
while((k < 2**i-1) and (j < size-1)):
j = j + 1
k = k + 1
if connection :
matrix[i].append(1)
else:
matrix[i].append(0)
return matrix
else:
raise Exception ( '%s algorithm is not yet implemented' %algo )