2018-10-01 09:52:17 -05:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
from Hurricane import DataBase
|
|
|
|
from Hurricane import UpdateSession
|
|
|
|
from Hurricane import DbU
|
|
|
|
from Hurricane import Box
|
|
|
|
import helpers
|
|
|
|
from helpers import trace
|
|
|
|
|
2020-04-10 05:15:23 -05:00
|
|
|
#helpers.setTraceLevel( 1000 )
|
2018-10-01 09:52:17 -05:00
|
|
|
|
2020-04-08 04:24:42 -05:00
|
|
|
try:
|
|
|
|
import Analog
|
|
|
|
import oroshi
|
|
|
|
import oroshi.paramsmatrix
|
|
|
|
import oroshi.stack
|
|
|
|
except Exception, e:
|
|
|
|
helpers.io.catch( e )
|
2018-10-01 09:52:17 -05:00
|
|
|
|
|
|
|
|
2018-10-18 11:10:01 -05:00
|
|
|
def checkCoherency ( device, bbMode ):
|
|
|
|
message = '[ERROR] DifferentialPair.checkCoherency():\n'
|
2018-10-01 09:52:17 -05:00
|
|
|
|
|
|
|
techno = DataBase.getDB().getTechnology()
|
2018-10-18 11:10:01 -05:00
|
|
|
rules = oroshi.getRules()
|
2018-10-01 09:52:17 -05:00
|
|
|
|
2018-10-18 11:10:01 -05:00
|
|
|
W = device.getParameter( 'W' ).getValue()
|
|
|
|
M = device.getParameter( 'M' ).getValue()
|
|
|
|
mMax = W / rules.transistorMinW
|
2018-10-01 09:52:17 -05:00
|
|
|
if M > mMax:
|
|
|
|
message += \
|
2018-10-18 11:10:01 -05:00
|
|
|
' W/M ratio must be greater than transistor minimal width (%s)\n' \
|
2018-10-01 09:52:17 -05:00
|
|
|
' Please increase W or decrease M.' \
|
2018-10-18 11:10:01 -05:00
|
|
|
% DbU.getValueString(rules.transistorMinW)
|
2018-10-01 09:52:17 -05:00
|
|
|
return False, message
|
|
|
|
|
2018-10-18 11:10:01 -05:00
|
|
|
Mint = device.getParameter( 'Mint' ).getValue()
|
|
|
|
if Mint != 2:
|
|
|
|
message += ' For interdigitaded layout style, Mint *must* be equal to 2 (not %d)\n' % Mint
|
2018-10-01 09:52:17 -05:00
|
|
|
return False, message
|
|
|
|
|
|
|
|
return True, ''
|
|
|
|
|
|
|
|
|
2018-10-18 11:10:01 -05:00
|
|
|
def layout ( device, bbMode ):
|
2018-10-01 09:52:17 -05:00
|
|
|
|
|
|
|
trace( 100, ',+', '\tWIP_DP.layout() called.\n' )
|
|
|
|
nerc = device.getParameter( 'NERC' ).getValue()
|
|
|
|
nirc = device.getParameter( 'NIRC' ).getValue()
|
|
|
|
|
2020-04-08 04:24:42 -05:00
|
|
|
stack = oroshi.stack.Stack( device, nerc, nirc )
|
2018-10-01 09:52:17 -05:00
|
|
|
|
|
|
|
bw = str(device.getParameter( 'B.w' ).getValue())
|
|
|
|
d1w = str(device.getParameter( 'D1.w' ).getValue())
|
|
|
|
d2w = str(device.getParameter( 'D2.w' ).getValue())
|
|
|
|
g1w = str(device.getParameter( 'G1.w' ).getValue())
|
|
|
|
g2w = str(device.getParameter( 'G2.w' ).getValue())
|
|
|
|
sw = str(device.getParameter( 'S.w' ).getValue())
|
|
|
|
|
|
|
|
diffMap = { 'D1w':str(device.getParameter( 'D1.w' ).getValue())
|
|
|
|
, 'D2w':str(device.getParameter( 'D2.w' ).getValue())
|
|
|
|
, 'Sw' :str(device.getParameter( 'S.w' ).getValue())
|
|
|
|
, 'G1w':str(device.getParameter( 'G1.w' ).getValue())
|
|
|
|
, 'G2w':str(device.getParameter( 'G2.w' ).getValue())
|
|
|
|
, 'Bw' :str(device.getParameter( 'B.w' ).getValue())
|
|
|
|
}
|
|
|
|
|
|
|
|
M = device.getM()
|
|
|
|
remain = M % device.getMint()
|
|
|
|
westWirings = ''
|
|
|
|
eastWirings = ''
|
|
|
|
for i in range(device.getExternalDummy()):
|
|
|
|
westWirings = westWirings + 'B.bX.{Bw} B.bX.{Bw} '
|
|
|
|
eastWirings = ' B.bX.{Bw} B.bX.{Bw}' + eastWirings
|
|
|
|
if remain:
|
|
|
|
westWirings = westWirings + 'D1.b1.{D1w} G1.b0.{G1w} '
|
|
|
|
eastWirings = ' G2.t0.{G2w} D2.t1.{D2w}' + eastWirings
|
|
|
|
westWirings = westWirings + 'S.b2.{Sw} '
|
|
|
|
|
|
|
|
|
|
|
|
mintWirings = ''
|
|
|
|
for i in range( (M / device.getMint())*2 ):
|
|
|
|
if (i + remain) % 2: mintWirings += 'G2.t0.{G2w} D2.t1.{D2w} G2.t0.{G2w} S.b2.{Sw} '
|
|
|
|
else: mintWirings += 'G1.b0.{G1w} D1.b1.{D1w} G1.b0.{G1w} S.b2.{Sw} '
|
|
|
|
|
|
|
|
wirings = westWirings + mintWirings + eastWirings
|
|
|
|
|
|
|
|
stack.setWirings( wirings.format( **diffMap ) )
|
|
|
|
stack.doLayout ( bbMode )
|
|
|
|
|
2020-04-08 04:24:42 -05:00
|
|
|
paramsMatrix = oroshi.paramsmatrix.ParamsMatrix()
|
First stage in analog capacitor integration
* Bug: In Technology::getPhysicalRule(), if the named layerdo not exists,
throw an exception instead of silently putting a NULL pointer inside
a rule.
* New: In Hurricane/Analog, new parameters classes for capacitor devices:
- Analog::Matrix, a matrix of null or positives integers to encode
capacitor matrix matching.
- Analog::Capacities, a list of float values for all component of a
multi-capacitor.
* New: In Hurricane::Script, add a "getFileName()" method to get the full
path name of the Python module.
* Change: In Analog::LayoutGenerator, completly remove the logger utility
as it is no longer used. Simply print error messages instead.
* Change: In Analog::MetaCapacitor, rename top & bottom plate 'T' & 'B'.
Accessors renamed in "getTopPlate()" & "getBottomPlate()".
* New: In Analog::MultiCapacitor, complete rewrite. Makes use of the
new parameters "capacities" and "matrix". Dynamically generates it's
terminals as we do not know beforehand how many capacitors could be
put in it.
* Bug: In isobar/PyHurricane.h, in Type object definition, do not prepend
a "Py" to class name (so the keep the C++ name).
* Change: In CRL/etc/scn6m_deep_09/devices.py, add entry for the new
capacitor generator.
* New: In oroshi/python/ParamsMatrix, add a "family" entry in the [0,0]
element to distinguish between transistor, capacitor and resistor.
(this is the matrix of values returned to the LayoutGenerator after
device generation).
Now have one "setGlobalParams()" function per family.
* New: In oroshi/python/Rules.py, added DTR rules needed by capacitors.
Catch exceptions if something wrong append when we extract the rules
from the technology.
* New: In Bora, the devices are no longer *only* transistors, so the
possibles configurations are no longer defined only by a number of
fingers. We must be able to support any kind of range of configuration.
So the explicit range of number of fingers is replaced by a base
class ParameterRange, and it's derived classes:
- Bora::StepParameterRange, to encode the possible number of fingers
of a transistor (the former only possibility).
- Bora::MatrixParameterRange, to encode all the possible matching
scheme for a capacitor. As there is no way to compress it, this
is a vector of Matrix (from Analog).
* Change: In Bora::DSlicingNode::_place(), the ParameterRange has to be set
on the right configuration (through the index) before being called.
The generation parameters are taken from the active item in the
ParameterRange.
* Change: In Bora::NodeSets::create(), iterate over the ParameterRange
to build all the configuration. Adjustement to the routing gauge
pitchs are moved into the DBoxSet CTOR to save a lot of code.
Semantic change: the index in the NodeSets is now the index in
the associated ParameterRange and no longer the number of fingers
of a transistor.
Check that the ParameterRange dynamic class is consitent with the
device family.
* Change: In Bora::DBoxSet, same semantic change as for NodeSets, the
number of finger become an index in ParameterRange.
In DBoxSet::create(), now also perform the abutment box adjustement
to the RoutingGauge, if possible.
* New: In Karakaze/python/AnalogDesign.py, add support for Capacitor
devices.
2019-11-07 10:05:49 -06:00
|
|
|
paramsMatrix.setGlobalTransistorParams( oroshi.toUnity(stack.w)
|
|
|
|
, oroshi.toUnity(stack.L)
|
|
|
|
, device.getM()
|
|
|
|
, stack.boundingBox
|
|
|
|
)
|
2018-10-01 09:52:17 -05:00
|
|
|
paramsMatrix.setStacks( [ stack ] )
|
|
|
|
trace( 100, '++' )
|
|
|
|
paramsMatrix.trace()
|
|
|
|
trace( 100, '---' )
|
|
|
|
|
|
|
|
return paramsMatrix.getMatrix()
|