coriolis/stratus1/src/stratus/st_net.py

1194 lines
44 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 : Sophie BELLOEIL |
# | E-mail : Sophie.Belloeil@asim.lip6.fr |
# | =============================================================== |
# | Py Module : "./st_net.py" |
# | *************************************************************** |
# | U p d a t e s |
# | |
# x-----------------------------------------------------------------x
import CRL
from Hurricane import *
2010-07-12 10:33:22 -05:00
from st_model import Model
from st_instance import Inst
from st_generate import Generate
import re, types, inspect
## Class of nets ##
PORT = ( "st_net.SignalIn", "st_net.SignalOut", "st_net.SignalInOut" \
, "st_net.SignalUnknown", "st_net.TriState" \
)
#####################
##### Class net #####
#####################
class net :
# Creation of the instance : coded for each herited class
def __init__ ( self, nbit ) : pass
# Deletion of the instance : the same for each net
def Delete ( self ) :
# Erasement of the references to the net
if str ( self.__class__ ) in PORT :
for i in range ( len ( self._st_cell._st_ports ) ) :
if self._st_cell._st_ports[i] == self :
del self._st_cell._st_ports[i]
break
else :
for i in range ( len ( self._st_cell._st_sigs ) ) :
if self._st_cell._st_sigs[i] == self :
del self._st_cell._st_sigs[i]
break
for net in self._st_cell._st_sigs :
if "_to_merge" in net.__dict__ :
if len ( net._to_merge ) :
for i in range ( len ( net._to_merge ) ):
if net._to_merge[i] != 0 :
if net._to_merge[i][0] == self : net._to_merge[i] = 0 # Erasement of a reference of the net
non = False
# Erasement of the net which wes going to be merged to the net being deleted
for i in range ( len ( net._to_merge ) ) :
if net._to_merge[i] != 0 :
non = True
break
if not non : net.Delete()
# Erasement in the connections
for inst in self._st_cell._st_insts :
for pin in inst._map :
if self == inst._map[pin] :
del inst._map[pin]
break
# Erasement of the huricane nets associated
for hurNet in self._hur_net :
if hurNet : hurNet.Delete()
##### For buses #####
def __getitem__ ( self, indice ) :
if indice == -1:
return Sig ( self, self._ind + self._arity - 1 )
2010-07-12 10:33:22 -05:00
if ( indice < self._ind ) or ( indice >= ( self._ind + self._arity ) ) :
err = "\n[Stratus ERROR] [] : bad index " + str(indice) + " for net : " \
+ self._name + " of arity " + str(self._arity)
if self._ind != 0 : err += " and LSB " + str(self._ind)
err += ".\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
return Sig ( self, indice )
def __getslice__ ( self, ind1, ind2 ) :
if ind1 < ind2 :
indmin = ind1
indmax = ind2
else :
indmin = ind2
indmax = ind1
# Errors
if ( (indmax-indmin) < 1 ) or ( (indmax-indmin) > self._arity ) :
err = "\n[Stratus ERROR] [:] : bad indexes " + str(indmax) + ", and " + str(indmin) \
+ " for net : " + self._name + " of arity " + str(self._arity)
if self._ind != 0 : err += " and LSB " + str(self._ind)
err += ".\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
if ( indmax >= ( self._ind + self._arity ) ) or ( indmin < self._ind ) :
err = "\n[Stratus ERROR] [:] : bad indexes " + str(indmax) + ", and " + str(indmin) \
+ " for net : " + self._name + " of arity " + str(self._arity)
if self._ind != 0 : err += " and LSB " + str(self._ind)
err += ".\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
return Sig ( self, ind1, ind2 )
##### To affect a signal : <= #####
def __le__ ( self, net ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
### Initialisation of net representing a constant ###
if type ( net ) == types.StringType :
from st_const import Constant
if not ( cell._st_vdds ) or not ( cell._st_vsss ) :
err = "\n[Stratus ERROR] : there is no alim.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
constParam = { 'nb' : net }
string = Constant.getString ( constParam )
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "cst_o%d" % num_net, len ( string ) )]
2010-07-12 10:33:22 -05:00
# 3 possible constant operator output name (nq,q,output) => 3 differents map
if string == "0" :
inst_name = "zero"
map_cst = { 'nq' : cell._TAB_NETS_OUT[num_net]
, 'vdd': cell._st_vdds[0]
, 'vss': cell._st_vsss[0]
}
elif string == "1" :
inst_name = "one"
map_cst = { 'q' : cell._TAB_NETS_OUT[num_net]
, 'vdd': cell._st_vdds[0]
, 'vss': cell._st_vsss[0]
}
else :
inst_name = Constant.getModelName ( constParam )
2013-08-02 07:36:01 -05:00
map_cst = { 'o': cell._TAB_NETS_OUT[num_net]
2010-07-12 10:33:22 -05:00
, 'vdd': cell._st_vdds[0]
, 'vss': cell._st_vsss[0]
}
Generate ( "Constant", inst_name, param = constParam )
Inst ( inst_name
, map = map_cst
)
net = cell._TAB_NETS_OUT[num_net]
### Merging of two nets ###
# Resizement of the output net if needed thanks to the input net's lenght
if not ( self._arity ) : self.create_net ( self._name, net._arity )
# Error if the nets don t have the same size
if self._arity - net._arity :
err = "\n[Stratus ERROR] <= : the nets " + self._name + " " + str(self._arity) + " and " + net._name + " " + str(net._arity) \
+ " must have the same lenght\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# If the nets are virtual, Let s work with the corresponding real nets
if self._real_net : netInCell = self._real_net
else : netInCell = self
if net._real_net : netToMerge = net._real_net
else : netToMerge = net
# Error if self is an input net
if ( netInCell._ext ) and ( netInCell._direct == "IN" ) :
err = "\n[Stratus ERROR] <= : " + self._name + " One can not give a value to an input net.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
if netToMerge._ext :
err = "\n[Stratus ERROR] <= : " + self._name
# Error if net is an output net
if netToMerge._direct == "OUT" : err += " One can not initialise a net with an output net.\n"
# Error if net is an input net
elif netToMerge._direct == "IN" : err += " One can not initialise a net with an input net. The method Buffer() should be used.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# Construction of the tab if needed
if not ( len ( netToMerge._to_merge ) ) :
for i in range ( netToMerge._arity ) : netToMerge._to_merge.append ( 0 )
# Initialisation of _to_merge
for i in range ( net._arity ) : netToMerge._to_merge[i+net._ind] = [netInCell, i+self._ind]
# Puts the net in the list of nets to merge in order to have them in the right order
self._st_cell._st_merge.append ( net )
if self._st_cell._hur_cell :
net.hur_merge()
#for i in range ( net._arity ) :
# CRL.createPartRing ( self._st_cell._hur_cell, netInCell._hur_net[i+self._ind].getName() ) # FIXME plante avec le adder mixed dans un cas particulier indetermine ....
2010-07-12 10:33:22 -05:00
##### Instanciation of a buffer #####
def Buffer ( self ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
if not ( cell._st_vdds ) or not ( cell._st_vsss ) :
err = "\n[Stratus ERROR] : there is no alim.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# Creation of the output net with the right size
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "buf_o%d" % num_net, self._arity )]
2010-07-12 10:33:22 -05:00
buffMap = { 'q' : cell._TAB_NETS_OUT[num_net]
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
if self._st_cell._buff == 'DpgenBuff' : buffMap['i0'] = self
else : buffMap['i'] = self
# if ( self._st_cell._buff == "Buf" ) and ( self._arity == 1 ) :
# inst_name = self._st_cell._buff.lower()
# else :
inst_name = self._st_cell._buff.lower()
inst_name = re.sub ( "\.", "_", inst_name )
inst_name += "_"
inst_name += str(self._arity)
Generate ( self._st_cell._buff, inst_name, param = { 'nbit' : self._arity } )
Inst ( inst_name, map = buffMap )
return cell._TAB_NETS_OUT[num_net]
##### Boolean operators #####
def __and__ ( self, other_net ) : return self.bool ( other_net, self._st_cell._and )
def __or__ ( self, other_net ) : return self.bool ( other_net, self._st_cell._or )
def __xor__ ( self, other_net ) : return self.bool ( other_net, self._st_cell._xor )
def bool ( self, other_net, model ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
if model == self._st_cell._and : f = "&"
elif model == self._st_cell._or : f = "|"
elif model == self._st_cell._xor : f = "^"
if self._arity - other_net._arity :
err = "\n[Stratus ERROR] " + f + " : the nets " + self._name + " and " + other_net._name + " must have the same lenght.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# Creation of the output net with the right size
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "bool_o%d" % num_net, self._arity )]
2010-07-12 10:33:22 -05:00
if not ( cell._st_vdds ) or not ( cell._st_vsss ) :
err = "\n[Stratus ERROR] : there is no alim.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# if ( model in ( "A2", "O2", "Xr2" ) ) and ( self._arity == 1 ) and ( other_net._arity == 1 ) :
# inst_name = model.lower()
#
# else :
inst_name = model.lower()
inst_name = re.sub ( "\.", "_", inst_name )
inst_name += "_"
inst_name += str(self._arity)
Generate ( model, inst_name, param = { 'nbit' : self._arity } )
Inst ( inst_name
, map = { 'i0' : self
, 'i1' : other_net
, 'q' : cell._TAB_NETS_OUT[num_net]
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
)
return cell._TAB_NETS_OUT[num_net]
def __invert__ ( self ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
if not ( cell._st_vdds ) or not ( cell._st_vsss ) :
err = "\n[Stratus ERROR] : there is no alim.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# Creation of the output net with the right size
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "inv_o%d" % num_net, self._arity )]
2010-07-12 10:33:22 -05:00
invMap = { 'nq' : cell._TAB_NETS_OUT[num_net]
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
if self._st_cell._not == 'DpgenInv' : invMap['i0'] = self
else : invMap['i'] = self
# if ( self._st_cell._not == "Inv" ) and ( self._arity == 1 ) :
# inst_name = self._st_cell._not.lower()
# else :
inst_name = self._st_cell._not.lower()
inst_name = re.sub ( "\.", "_", inst_name )
inst_name += "_"
inst_name += str(self._arity)
Generate ( self._st_cell._not, inst_name, param = { 'nbit' : self._arity } )
Inst ( inst_name, map = invMap )
return cell._TAB_NETS_OUT[num_net]
##### Arithmetic operators #####
def __add__ ( self, other_net ) : return self.arithgen ( other_net, self._st_cell._add, {'signed' : self._st_cell._signed, 'extended' : self._st_cell._extended} )
def __sub__ ( self, other_net ) : return self.arithgen ( other_net, self._st_cell._sub, {'signed' : self._st_cell._signed, 'extended' : self._st_cell._extended} )
def __mul__ ( self, other_net ) : return self.arithgen ( other_net, self._st_cell._mult, {'signed' : self._st_cell._signed} )
def __div__ ( self, other_net ) : return self.arithgen ( other_net, self._st_cell._div )
def arithgen ( self, other_net, function, parameter = {} ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
if not function :
err = "\n[Stratus ERROR] / : to be done.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
if not ( cell._st_vdds ) or not ( cell._st_vsss ) :
err = "\n[Stratus ERROR] there is no alim in cell %s.\n" % str(cell._name)
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# Creation of the output net with the right size
num_net = len ( cell._TAB_NETS_OUT )
if function == self._st_cell._add :
if self._st_cell._extended :
cell._TAB_NETS_OUT += [Signal ( "add_o%d" % num_net, max ( self._arity, other_net._arity )+1 )]
2010-07-12 10:33:22 -05:00
else:
cell._TAB_NETS_OUT += [Signal ( "add_o%d" % num_net, max ( self._arity, other_net._arity ) )]
2010-07-12 10:33:22 -05:00
elif function == self._st_cell._sub :
if self._st_cell._extended :
cell._TAB_NETS_OUT += [Signal ( "sub_o%d" % num_net, max ( self._arity, other_net._arity )+1 )]
2010-07-12 10:33:22 -05:00
else:
cell._TAB_NETS_OUT += [Signal ( "sub_o%d" % num_net, max ( self._arity, other_net._arity ) )]
elif function == self._st_cell._mult : cell._TAB_NETS_OUT += [Signal ( "mul_o%d" % num_net, self._arity+other_net._arity )]
2010-07-12 10:33:22 -05:00
arithParam = parameter
if not self._st_cell._signed and function == self._st_cell._mult :
name1 = re.sub(r"\[([0-9]+):([0-9]+)\]",r"\1\2", self._name) + "ext"
name2 = re.sub(r"\[([0-9]+):([0-9]+)\]",r"\1\2", other_net._name) + "ext"
i0ext = Signal(name1, self._arity+1)
i1ext = Signal(name2, other_net._arity+1)
i0ext <= self.Extend(self._arity+1, 'zero')
i1ext <= other_net.Extend(other_net._arity+1, 'zero')
arithParam['nbit0'] = self._arity+1
arithParam['nbit1'] = other_net._arity+1
arithMap = { 'i0' : i0ext
, 'i1' : i1ext
, 'o' : cell._TAB_NETS_OUT[num_net]
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
else:
arithParam['nbit0'] = self._arity
arithParam['nbit1'] = other_net._arity
arithMap = { 'i0' : self
, 'i1' : other_net
, 'o' : cell._TAB_NETS_OUT[num_net]
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
inst_name = function.lower()
inst_name = re.sub ( "\.", "_", inst_name )
for p in arithParam : inst_name += "_%s_%s" % ( str(p).lower(), str(arithParam[p]).lower() )
Generate ( function, inst_name, param = arithParam )
Inst ( inst_name, map = arithMap )
return cell._TAB_NETS_OUT[num_net]
##### Shifter #####
def Shift ( self, inputNet, direction, type ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
if not inputNet._arity : raise Exception ( "\n[Stratus ERROR] Shift : The input net does not have a positive arity.\n" )
if not self._arity : raise Exception ( "\n[Stratus ERROR] Shift : The command net does not have a positive arity.\n" )
if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise Exception ( "\n[Stratus ERROR] there is no alim.\n" )
2010-07-12 10:33:22 -05:00
# Wrong parameters :
if direction not in ( "left", "right" ) : raise Exception ( "\n[Stratus ERROR] Shift : The direction parameter must be \"left\" or \"right\".\n" )
if type not in ( "logical", "arith", "circular" ) : raise Exception ( "\n[Stratus ERROR] Shift : The type parameter must be \"logical\" or \"arith\" or \"circular\".\n" )
2010-07-12 10:33:22 -05:00
# Creation of the output net with the right size
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "sh_o%d" % num_net, inputNet._arity )]
2010-07-12 10:33:22 -05:00
# Initialisation of shiftType
if direction is "left" :
if type is "logical" : shiftType = 0x12
elif type is "arith" : shiftType = 0xa
else : shiftType = 0x6
else :
if type is "logical" : shiftType = 0x11
elif type is "arith" : shiftType = 0x9
else : shiftType = 0x5
inst_name = self._st_cell._shift.lower()
inst_name = re.sub ( "\.", "_", inst_name )
inst_name += "_"
inst_name += type
inst_name += "_"
inst_name += str(inputNet._arity)
Generate ( self._st_cell._shift, inst_name, param = { 'nbit' : inputNet._arity, 'type' : shiftType } )
Inst ( inst_name
, map = { 'cmd' : self
, 'i' : inputNet
, 's' : cell._TAB_NETS_OUT[num_net]
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
)
return cell._TAB_NETS_OUT[num_net]
##### Register #####
def Reg ( self, inputNet ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
if not inputNet._arity : raise Exception ( "\n[Stratus ERROR] Reg : The input net does not have a positive arity.\n" )
if not self._arity : raise Exception ( "\n[Stratus ERROR] Reg : The clock does not have a positive arity.\n" )
if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise Exception ( "\n[Stratus ERROR] there is no alim.\n" )
2010-07-12 10:33:22 -05:00
# Creation of the output net with the right size
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "reg_o%d" % num_net, inputNet._arity )]
2010-07-12 10:33:22 -05:00
# if ( self._st_cell._reg == "Sff1" ) and ( inputNet._arity == 1 ) :
# inst_name = "sff1"
# else :
# inst_name = self._st_cell._reg.lower()
# inst_name = re.sub ( "\.", "_", inst_name )
# inst_name += "_"
# inst_name += str(inputNet._arity)
#
# Generate ( self._st_cell._reg, inst_name, param = { 'nbit' : inputNet._arity } )
inst_name = self._st_cell._reg.lower()
inst_name = re.sub ( "\.", "_", inst_name )
inst_name += "_"
inst_name += str(inputNet._arity)
Generate ( self._st_cell._reg, inst_name, param = { 'nbit' : inputNet._arity } )
Inst ( inst_name
, map = { 'i' : inputNet
, 'ck' : self
, 'q' : cell._TAB_NETS_OUT[num_net]
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
)
return cell._TAB_NETS_OUT[num_net]
##### Multiplexor #####
def Mux ( self, nets ) :
maxPossibility = pow ( 2, self._arity ) - 1
### List ###
if type ( nets ) == types.ListType :
if len ( nets ) != ( maxPossibility + 1 ) :
raise Exception ( "\n[Stratus ERROR] Mux : when using a list, all the nets must be precised. Maybe one should use a dictionnary.\n" )
2010-07-12 10:33:22 -05:00
return self.muxList ( nets )
### Dictionnary : Creation of the corresponding list ###
elif type ( nets ) == types.DictType :
# Initialisation of the by default to 0 net if no default net given
if "default" not in nets : nets["default"] = 0
# Traitement of lists, intervals and numbers
for net in nets.keys () :
if re.search ( "-", net ) or re.search ( ",", net ) or re.search ( "#", net ) :
chaine = net
while chaine :
interval = re.search ( "^([0-9]+)-([0-9]+)", chaine )
chiffre = re.search ( "^([0-9]+)", chaine )
diese = re.search ( "^#([0-9\?]+)", chaine )
#############
if interval :
nb1 = int ( interval.group(1) )
nb2 = int ( interval.group(2) )
# Error : wrong interval
if nb1 >= nb2 :
raise Exception ( "\n[Stratus ERROR] Mux : when an interval is specified, the second number of the interval must be the greater one.\n" )
2010-07-12 10:33:22 -05:00
# Error : if the interval does not correspond to the lenght of the command
if ( nb1 > maxPossibility ) or ( nb2 > maxPossibility ) :
raise Exception ( "\n[Stratus ERROR] Mux : One key does not match with the arity of the input nets.\n" )
2010-07-12 10:33:22 -05:00
for i in range ( nb1, nb2+1 ) : nets[i] = nets[net]
# Next element
temp = re.search ( "^[0-9]+-[0-9]+,(.+)$", chaine )
if temp : chaine = str ( temp.group(1) )
else : chaine = None
##############
elif chiffre :
if int ( chiffre.group(0) ) > maxPossibility :
raise Exception ( "\n[Stratus ERROR] Mux : One key does not match with the arity of the input nets.\n" )
2010-07-12 10:33:22 -05:00
nets[int(chiffre.group(0))] = nets[net]
# Next element
temp = re.search ( "^[0-9]+,(.+)$", chaine )
if temp : chaine = str ( temp.group(1) )
else : chaine = None
############
elif diese :
binaire = diese.group ( 1 )
# Error : if the binary number does not correspond to the lenght of the command
if len ( binaire ) != self._arity :
err = "\n[Stratus ERROR] Mux : the binary number " + str(binaire) \
+ " does not match with the lenght of the command. It has to be a " + str(self._arity) + "bits number.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# Error : if the number is not binary
for n in binaire :
if n not in ( "0", "1", "?", "#" ) :
err = "\n[Stratus ERROR] Mux : after #, the number has to be binary.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
nombrebit = self._arity
nb = 0
for i in range ( -1, -nombrebit - 1, -1 ) :
if binaire[i] == "1" : nb += pow ( 2, -i - 1 )
nombres = []
premierpassage = 1
for i in range ( -1, -nombrebit - 1, -1 ) :
if binaire[i] == "?" :
if premierpassage :
nombres += [nb]
nombres += [nb + pow ( 2, -i - 1 )]
premierpassage = 0
else :
enplus = []
for chaquenombre in nombres : enplus += [chaquenombre + pow ( 2, -i - 1 )]
nombres += enplus
for chaquenombre in nombres : nets[chaquenombre] = nets[net]
# Next element
temp = re.search ( "^#.*,(.+)$", chaine )
if temp : chaine = str ( temp.group (1) )
else : chaine = None
else :
err = "\n[Stratus ERROR] Mux : wrong key.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
del nets[net]
# Otherwise it must be a number :
elif re.search ( "^[0-9]+$", net ) :
chaine = re.search ( "^([0-9]+)$", net )
chiffre = str ( chaine.group ( 1 ) )
if int ( chiffre ) > maxPossibility :
err = "\n[Stratus ERROR] Mux : One key does not match with the arity of the input nets.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
nets[int(chiffre)] = nets[chiffre]
del nets[chiffre]
else :
if net != "default" :
err = "\n[Stratus ERROR] Mux : wrong key.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
clefs = nets.keys ()
clefs.sort ()
# Covering of the keys wich are not default
lenClefs = 0
for c in clefs :
if c != "default" : lenClefs += 1
liste = []
decalage = 0
for i in range ( lenClefs ) :
nb = clefs[i]
nb2 = i + decalage
if nb2 < nb :
while nb2 < nb :
liste.append ( nets["default"] )
nb2 += 1
decalage += 1
liste.append ( nets[clefs[i]] ) # it is the right one
else :
liste.append ( nets[clefs[i]] )
# Number of wanted nets :
lenList = pow ( 2, self._arity )
# If nets are missing theu are default nets
while len ( liste ) < lenList : liste.append ( nets["default"] )
# Creation of the list corresponding to the dictionnary
return self.muxList ( liste )
# Error : wrong argument
else :
err = "\n[Stratus ERROR] Mux : wrong argument type.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
### List ###
def muxList ( self, nets ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise Exception ( "\n[Stratus ERROR] : there is no alim.\n" )
2010-07-12 10:33:22 -05:00
long = 0
for i in range ( len ( nets ) ) :
if nets[i] : long = nets[i]._arity
# Error : if no input net
if not ( long ) : raise Exception ( "\n[Stratus ERROR] Mux : there are no input nets.\n" )
2010-07-12 10:33:22 -05:00
# Instanciation of a zero cell if needed
for net in nets :
if net == 0 :
from st_const import Zero
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "sig0_%d" % num_net, long )]
cell._TAB_NETS_OUT[num_net] <= Zero ( long )
break
# Creation of the map
map_mux = { 'cmd' : self
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
i = 0
for net in nets :
if net : map_mux['i%d' % i] = net
else : map_mux['i%d' % i] = cell._TAB_NETS_OUT[num_net]
i += 1
# Initialisation of the output net
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, long )]
map_mux ['q'] = cell._TAB_NETS_OUT[num_net]
inst_name = self._st_cell._mux.lower()
inst_name = re.sub ( "\.", "_", inst_name )
inst_name += "_"
inst_name += str(long)
inst_name += "_"
inst_name += str(self._arity)
Generate ( self._st_cell._mux, inst_name, param = { 'nbit' : long, 'nbit_cmd' : self._arity } )
Inst ( inst_name, map = map_mux )
return cell._TAB_NETS_OUT[num_net]
##### Comparison functions #####
def Eq ( self, nb ) : return self.comparaison ( nb, True )
def Ne ( self, nb ) : return self.comparaison ( nb, False )
# TODO : it could work with un string representing binary, decimal, or hexadecimal
def comparaison ( self, nb, egal ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
if not ( cell._st_vdds ) or not ( cell._st_vsss ) : raise Exception ( "\n[Stratus ERROR] : threre is no alim.\n" )
2010-07-12 10:33:22 -05:00
# Initialisation of the output net
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "net_out_%d" % num_net, 1 )]
inst_name = self._st_cell._comp.lower()
inst_name = re.sub ( "\.", "_", inst_name )
inst_name += "_"
inst_name += str(self._arity)
inst_name += "_"
inst_name += str(nb)
if egal : inst_name += "eq"
2010-07-12 10:33:22 -05:00
Generate ( self._st_cell._comp, inst_name, param = { 'nbit' : self._arity, 'nb' : nb, 'egal' : egal } )
Inst ( inst_name
, map = { "netin" : self
, "netout" : cell._TAB_NETS_OUT[num_net]
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
)
return cell._TAB_NETS_OUT[num_net]
##### Method Alias #####
def Alias ( self, net ) :
# Error : if the net already has an alias
if net._alias :
err = "\n[Stratus ERROR] Alias : the net " + net._name + " is already an alias.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# Resizement of the net if needed
if not ( net._arity ) : net.create_net ( net._name, self._arity )
# Error : if the nets don't have the same lenght
if self._arity != net._arity :
err = "\n[Stratus ERROR] Alias : the nets " + self._name + " and " + net._name + " must have the same lenght\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# If nets are virtual, let's work with the corresponding real nets
if net._real_net : realNet = net._real_net
else : realNet = net
if self._real_net : realSelf = self._real_net
else : realSelf = self
# Construction of the tab if needed
if not ( len ( realNet._alias ) ) :
for i in range ( realNet._arity ) : realNet._alias.append ( 0 )
# Initialisation of _alias
for i in range ( net._ind, net._ind + net._arity ) :
if not realSelf._alias :
realNet._alias[i] = {realSelf : i + self._ind - net._ind}
# Alias of an alias
else :
err = "\n[Stratus ERROR] Alias : 2 Alias in a row are not supported.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
# FIXME bug : for now, Alias of Alias are not permitted
# if realSelf._alias[i + self._ind - net._ind] :
# netAlias = realSelf._alias[i + self._ind - net._ind].keys()[0]
# bitAlias = realSelf._alias[i + self._ind - net._ind][netAlias]
# if netAlias._real_net : netAlias = netAlias._real_net
# realNet._alias[i] = {netAlias : bitAlias}
# # Error : more than 2 Alias in a row not supported
# if netAlias._alias :
# err = "\n[Stratus ERROR] Alias : more than 2 Alias in a row are not supported.\n"
# raise err
# else :
# realNet._alias[i] = {realSelf : i + self._ind - net._ind}
##### Method Extend #####
def Extend ( self, width, type ) :
global CELLS
from st_model import CELLS
from st_const import Zero, One
cell = CELLS[-1]
if self._arity >= width :
err = "\n[Stratus ERROR] Extend : the net " + self._name + \
" can not be extended to " + str(width) + " bits, it's arity is already " + str(self._arity) + ".\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
num_net = len ( cell._TAB_NETS_OUT )
cell._TAB_NETS_OUT += [Signal ( "%s_ext_%d_%d" % ( self._name, width, num_net ), width )]
name = "extend_%d_%d_%s" % ( self._arity, width, type )
Generate ( "Extend", name, param = { 'nbit0' : self._arity, 'nbit1' : width, 'type' : type } )
Inst ( name
, map = { 'i' : self
, 'o' : cell._TAB_NETS_OUT[num_net]
, 'vdd' : cell._st_vdds[0]
, 'vss' : cell._st_vsss[0]
}
)
return cell._TAB_NETS_OUT[num_net]
##################################################################################################################################
##### Initialisation of nets #####
def create_net ( self, nom, nbit, indice = 0, extern = False, direction = None, hType = None ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
# Error :
if re.search ( "[A-Z]", nom ) :
print "[Stratus Warning] : Upper case letters are not supported, the name", nom, "is lowered."
2012-08-10 10:00:08 -05:00
nom = nom.lower ()
2010-07-12 10:33:22 -05:00
if re.search ( " ", nom ) :
chaine = re.search ( "st_net\.(.*)", str ( self.__class__ ) )
classe = chaine.group(1)
err = "\n[Stratus ERROR] " + classe + " : \"" + nom + "\" the name of the net can not contain a space.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
self._st_cell = cell
self._name = nom
self._arity = nbit
self._ind = indice
self._hur_net = []
self._alias = []
self._to_merge = []
self._to_cat = []
self._real_net = None
self._ext = extern
2017-08-02 03:38:48 -05:00
self._h_type = hType
2010-07-12 10:33:22 -05:00
if extern : self._direct = direction
# Error :
if ( nbit == 1 ) and indice :
err = "\n[Stratus ERROR] " + str ( self.__class__ ) + " : " + self._name + " : one can not put an indice for a 1 bit net.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
if hType :
if hType == "POWER" : self._st_cell._st_vdds.append ( self )
elif hType == "GROUND" : self._st_cell._st_vsss.append ( self )
elif hType == "CLOCK" : self._st_cell._st_cks.append ( self )
# The net is put in the nets list of the cell
else :
if nbit :
if extern : self._st_cell._st_ports.append ( self )
else : self._st_cell._st_sigs.append ( self )
# Creation of the hurricane net if in hurricane mode
if self._st_cell._hur_cell : self.create_hur_net()
##### Initialisation of the hurricane nets for part nets #####
def create_part_hur_net ( self ) :
if self._ind2 < self._ind : pas = -1
else : pas = 1
if self._real_net._hur_net : # FIXME a priori pb du a l outil d optimisation
for i in range ( self._ind, self._ind2 + pas, pas ) : self._hur_net.append ( self._real_net._hur_net[i] )
##### Initialisation of the hurricane nets #####
def create_hur_net ( self ) :
if self._arity == 1 :
self.hur_net ( self._name, 0 )
else :
#for i in range ( self._ind+self._arity, self._ind, -1 ):
for i in range ( self._ind, self._ind+self._arity, 1 ):
#print 'create %s(%d)' % (self._name,i)
self.hur_net ( '%s(%d)' % (self._name,i), i )
2010-07-12 10:33:22 -05:00
##### hur_net one by one #####
def hur_net ( self, name, ind ) :
if ( self._alias ) and ( self._alias[ind] ) :
self._hur_net += [self._alias[ind].keys()[0]] # put the right hur_net
return
elif ( self._to_cat ) and ( self._to_cat[ind] ) :
cat = self._to_cat[ind]
self._hur_net += [cat[0]._hur_net[cat[1]]]
return
net = Net.create ( self._st_cell._hur_cell, name )
2010-07-12 10:33:22 -05:00
net.setType ( Net.Type.LOGICAL )
2010-07-12 10:33:22 -05:00
if self._ext : net.setExternal ( True )
else : net.setExternal ( False )
if self._ext :
if self._direct == "IN" : net.setDirection ( Net.Direction.IN )
elif self._direct == "OUT" : net.setDirection ( Net.Direction.OUT )
elif self._direct == "INOUT" : net.setDirection ( Net.Direction.INOUT )
elif self._direct == "TRISTATE" : net.setDirection ( Net.Direction.TRISTATE )
elif self._direct == "UNKNOWN" : net.setDirection ( Net.Direction.UNDEFINED )
2010-07-12 10:33:22 -05:00
if '_h_type' in self.__dict__ :
Migrating the initialisation system to be completely Python-like. * New: In bootstrap/coriolisEnv.py, add the "etc" directory to the PYTHONPATH as initialization are now Python modules. * New: In Hurricane/analogic, first groundwork for the integration of PIP/MIM/MOM multi-capacitors. Add C++ and Python interface for the allocation matrix and the list of capacities values. * Change: In Hurricane::RegularLayer, add a layer parameter to the constructor so the association between the RegularLayer and it's BasicLayer can readily be done. * Change: In Hurricane::Layer, add a new getCut() accessor to get the cut layer in ViaLayer. * Change: In Hurricane::DataBase::get(), the Python wrapper should no longer consider an error if the data-base has not been created yet. Just return None. * Bug: In Isobar::PyLayer::getEnclosure() wrapper, if the overall enclosure is requested, pass the right parameter to the C++ function. * Change: In AllianceFramework, make public _bindLibraries() and export it to the Python interface. * Change: In AllianceFramework::create(), do not longer call bindLibraries(). This now must be done explicitely and afterwards. * Change: In AllianceFramework::createLibrary() and Environement::addSYSTEM_LIBRARY(), minor bug corrections that I don't recall. * Change: In SearchPath::prepend(), set the selected index to zero and return it. * Change: In CRL::System CTOR, add "etc" to the PYTHONPATH as the configuration files are now organized as Python modules. * New: In PyCRL, export the CRL::System singleton, it's creation is no longer triggered by the one of AllianceFramework. * New: In CRL/etc/, convert most of the configuration files into the Python module format. For now, keep the old ".conf", but that are no longer used. For the real technologies, we cannot keep the directory name as "180" or "45" as it not allowed by Python syntax, so we create "node180" or "node45" instead. Most of the helpers and coriolisInit.py are no longer used now. To be removed in future commits after being sure that everything works... * Bug: In AutoSegment::makeDogleg(AutoContact*), the layer of the contacts where badly computed when one end of the original segment was attached to a non-preferred direction segment (mostly on terminal contacts). Now use the new AutoContact::updateLayer() method. * Bug: In Dijkstra::load(), limit symetric search area only if the net is a symmetric one ! * Change: In Katana/python/katanaInit.py, comply with the new initialisation scheme. * Change: In Unicorn/cgt.py, comply to the new inititalization scheme. * Change: In cumulus various Python scripts remove the call to helpers.staticInitialization() as they are not needed now (we run in only *one* interpreter, so we correctly share all init). In plugins/__init__.py, read the new NDA directory variable. * Bug: In cumulus/plugins/Chip.doCoronafloorplan(), self.railsNb was not correctly managed when there was no clock. * Change: In cumulus/plugins/Configuration.coronaContactArray(), compute the viaPitch from the technology instead of the hard-coded 4.0 lambdas. In Configuration.loadConfiguration(), read the "ioring.py" from the new user's settings module. * Bug: In stratus.dpgen_ADSB2F, gives coordinates translated into DbU to the XY functions. In st_model.Save(), use the VstUseConcat flag to get correct VST files. In st_net.hur_net(), when a net is POWER/GROUND or CLOCK also make it global. * Change: In Oroshi/python/WIP_Transistor.py, encapsulate the generator inside a try/except block to get prettier error (and stop at the first).
2019-10-28 12:09:14 -05:00
if self._h_type == "POWER" : net.setType ( Net.Type.POWER ); net.setGlobal( True )
elif self._h_type == "GROUND" : net.setType ( Net.Type.GROUND ); net.setGlobal( True )
elif self._h_type == "CLOCK" : net.setType ( Net.Type.CLOCK ); net.setGlobal( True )
2010-07-12 10:33:22 -05:00
self._hur_net += [net]
##### Hurricane merge #####
def hur_merge ( self ) :
if self._real_net : realNet = self._real_net
else : realNet = self
if self._to_cat :
err = "\n[Stratus ERROR] HurricanePlug <= : net " + self._name + " is a Cat net. Forbidden utilisation of <= and Cat.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
for i in range ( self._ind, self._arity + self._ind ) :
if realNet._to_merge[i] :
selfToMerge = realNet._to_merge[i][0]
bitToMerge = realNet._to_merge[i][1]
if selfToMerge._hur_net == [] :
print "[Stratus Warning] HurricanePlug <= : net", selfToMerge._name, "has no hurricane net."
return
if realNet._hur_net == [] :
err = "\n[Stratus ERROR] HurricanePlug <= : net " + realNet._name + " has no hurricane net.\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
if bitToMerge > ( len ( selfToMerge._hur_net ) - 1 ) :
err = "\n[Stratus ERROR] HurricanePlug <= : net " + selfToMerge._name + " with hur_net : " + str(selfToMerge._hur_net) \
+ " with asked bit : " + str(bitToMerge) + ".\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
if i > ( len ( realNet._hur_net ) - 1 ) :
err = "\n[Stratus ERROR] HurricanePlug <= : net " + realNet._name + " with hur_net : " + str(realNet._hur_net) \
+ " with asked bit : " + str(i) + ".\n"
raise Exception ( err )
2010-07-12 10:33:22 -05:00
selfToMerge._hur_net[bitToMerge].merge ( realNet._hur_net[i] )
# realNet._hur_net[i] = 0
# realNet.Delete()
# del realNet
##### Initialisation from a net hurricane #####
def create_from_hur ( self, hur_net ) :
global CELLS
from st_model import CELLS
cell = CELLS[-1]
self._st_cell = cell
self._alias = []
self._to_merge = []
self._to_cat = []
self._real_net = None
self._arity = 1
self._ind = 0
self._name = str ( hur_net.getName() )
if hur_net.isExternal() : self._ext = True
else : self._ext = False
if hur_net.isExternal() :
if hur_net.getDirection() == Net.Direction.IN : self._direct = "IN"
elif hur_net.getDirection() == Net.Direction.OUT : self._direct = "OUT"
elif hur_net.getDirection() == Net.Direction.INOUT : self._direct = "INOUT"
elif hur_net.getDirection() == Net.Direction.TRISTATE : self._direct = "TRISTATE"
elif hur_net.getDirection() == Net.Direction.UNDEFINED : self._direct = "UNDEFINED"
2010-07-12 10:33:22 -05:00
if hur_net.getType() == Net.Type.POWER : self._h_type = "POWER"
elif hur_net.getType() == Net.Type.GROUND : self._h_type = "GROUND"
elif hur_net.getType() == Net.Type.CLOCK : self._h_type = "CLOCK"
2010-07-12 10:33:22 -05:00
self._hur_net = [hur_net]
if ( self._ext ) and ( '_h_type' in self.__dict__ ) :
if self._h_type == "CLOCK" : cell._st_ports.append ( self ) # not alimentations
else :
cell._st_sigs.append ( self )
###########
# SignalIn #
###########
class SignalIn ( net ) :
def __init__ ( self, nom, nbit, indice = 0 ) :
if nbit < 1 : raise Exception ( "\n[Stratus ERROR] SignalIn : the lenght of the net must be a positive value\n" )
2010-07-12 10:33:22 -05:00
self.create_net ( nom, nbit, indice, True, "IN" )
class SignalInFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
############
# SignalOut #
############
class SignalOut ( net ) :
def __init__ ( self, nom, nbit, indice = 0 ) :
if nbit < 1 : raise Exception ( "\n[Stratus ERROR] SignalOut : the lenght of the net must be a positive value\n" )
2010-07-12 10:33:22 -05:00
self.create_net ( nom, nbit, indice, True, "OUT" )
class SignalOutFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
##############
# SignalInOut #
##############
class SignalInOut ( net ) :
def __init__ ( self, nom, nbit, indice = 0 ) :
if nbit < 1 : raise Exception ( "\n[Stratus ERROR] SignalInOut : the lenght of the net must be a positive value\n" )
2010-07-12 10:33:22 -05:00
self.create_net ( nom, nbit, indice, True, "INOUT" )
class SignalInOutFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
################
# SignalUnknown #
################
class SignalUnknown ( net ) :
def __init__ ( self, nom, nbit, indice = 0 ) :
if nbit < 1 : raise Exception ( "\n[Stratus ERROR] SignalUnknown : the lenght of the net must be a positive value\n" )
2010-07-12 10:33:22 -05:00
self.create_net ( nom, nbit, indice, True, "UNKNOWN" )
class SignalUnknownFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
############
# TriState #
############
class TriState ( net ) :
def __init__ ( self, nom, nbit, indice = 0 ) :
if nbit < 1 : raise Exception ( "\n[Stratus ERROR] TriState : the lenght of the net must be a positive value\n" )
2010-07-12 10:33:22 -05:00
self.create_net ( nom, nbit, indice, True, "TRISTATE" )
class SignalTriStateFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
#########
# Clock #
#########
class CkIn ( net ) :
def __init__ ( self, nom ) :
self.create_net ( nom, 1, extern = True, direction = "IN", hType = "CLOCK" )
class CkInFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
#########################
# Internal Clock Signal #
#########################
class SignalCk ( net ) :
def __init__ ( self, nom ) :
self.create_net ( nom, 1, direction = "IN", hType = "CLOCK" )
class SignalCkFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
2010-07-12 10:33:22 -05:00
###################
# Internal Signal #
###################
class Signal ( net ) :
def __init__ ( self, nom, nbit = 0, indice = 0 ) :
if nbit < 0 : raise Exception ( "\n[Stratus ERROR] Signal : the lenght of the net must be a positive value\n" )
2010-07-12 10:33:22 -05:00
self.create_net ( nom, nbit, indice )
class SignalFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
################
# Alimentation #
################
class VddIn ( net ) :
def __init__ ( self, nom ) : self.create_net ( nom, 1, extern = True, direction = "IN", hType = "POWER" )
class VssIn ( net ) :
def __init__ ( self, nom ) : self.create_net ( nom, 1, extern = True, direction = "IN", hType = "GROUND" )
class VddInFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
class VssInFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
class SignalVdd ( net ) :
def __init__ ( self, nom ) : self.create_net ( nom, 1, direction = "IN", hType = "POWER" )
class SignalVss ( net ) :
def __init__ ( self, nom ) : self.create_net ( nom, 1, direction = "IN", hType = "GROUND" )
class SignalVddFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
class SignalVssFromHur ( net ) :
def __init__ ( self, hur_net ) : self.create_from_hur ( hur_net )
2010-07-12 10:33:22 -05:00
##################
# Virtual signal #
##################
class Sig ( net ) :
def __init__ ( self, net, indiceFort, indiceFaible = -1 ) :
global CELLS
from st_model import CELLS
if indiceFaible == -1 : indiceFaible = indiceFort
self._st_cell = CELLS[-1]
self._ind = indiceFaible
self._ind2 = indiceFort
self._alias = []
self._to_merge = []
self._to_cat = []
self._real_net = net
self._ext = net._ext
self._arity = abs ( indiceFort - indiceFaible ) + 1
if indiceFort < indiceFaible : self._reverse = True
else : self._reverse = False
self._hur_net = []
self._st_cell._st_partsigs.append ( self )
# Initialisation of _hur_net if in hurricanePlug mode
# if CELLS[0]._hur_plug : self.create_part_hur_net()
if self._ext : self._direct = net._direct
if '_h_type' in net.__dict__ : self._h_type = net._h_type
if indiceFort == indiceFaible : self._name = net._name + "[" + str(indiceFaible) + "]"
else : self._name = net._name + "[" + str(indiceFort) + ":" + str(indiceFaible) + "]"