2018-10-01 09:52:17 -05:00
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
|
|
|
// Copyright (c) UPMC 2009-2018, All Rights Reserved
|
|
|
|
//
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
// | C O R I O L I S |
|
|
|
|
// | H u r r i c a n e A n a l o g |
|
|
|
|
// | |
|
|
|
|
// | Authors : Christophe Alexandre, Damien Dupuis |
|
|
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
|
|
// | =============================================================== |
|
|
|
|
// | C++ Header : "./Device.cpp" |
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
#include <cfloat>
|
|
|
|
#include "hurricane/Warning.h"
|
|
|
|
#include "hurricane/DataBase.h"
|
|
|
|
#include "hurricane/Technology.h"
|
|
|
|
#include "hurricane/Pad.h"
|
|
|
|
#include "hurricane/Vertical.h"
|
|
|
|
#include "hurricane/Horizontal.h"
|
|
|
|
#include "hurricane/Library.h"
|
|
|
|
#include "hurricane/UpdateSession.h"
|
|
|
|
#include "hurricane/Reference.h"
|
|
|
|
#include "hurricane/analog/Device.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
using namespace Hurricane;
|
|
|
|
|
|
|
|
|
|
|
|
static Name anonymousNetName( "anonymous" );
|
|
|
|
|
|
|
|
} // anonymous namespace.
|
|
|
|
|
|
|
|
|
|
|
|
namespace Analog {
|
|
|
|
|
|
|
|
using namespace Hurricane;
|
|
|
|
|
|
|
|
|
|
|
|
Device::Device ( Library* library, const Name& name )
|
|
|
|
: Cell (library, name)
|
|
|
|
, _temperature (0.0)
|
|
|
|
, _parameterSet ()
|
|
|
|
, _layoutStyles (NULL)
|
|
|
|
, _subDevicesLibrary(NULL)
|
|
|
|
, _anonymous (NULL)
|
|
|
|
, _layouts ()
|
|
|
|
, _netRestrictions ()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
void Device::preCreate ( const Name& deviceName )
|
|
|
|
{
|
2018-10-18 11:10:01 -05:00
|
|
|
Technology* tech = DataBase::getDB()->getTechnology();
|
|
|
|
if (not tech)
|
|
|
|
throw Error( "Device::preCreate(): Technology database not initialied while called for \"%s\"."
|
|
|
|
, getString(deviceName).c_str() );
|
|
|
|
|
2018-10-01 09:52:17 -05:00
|
|
|
DeviceDescriptor* dd = tech->getDeviceDescriptor( deviceName );
|
|
|
|
if (not dd)
|
|
|
|
throw Error( "Device::preCreate(): No DeviceDescriptor for \"%s\"."
|
|
|
|
, getString(deviceName).c_str() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Device::_postCreate ( const Name& deviceName )
|
|
|
|
{
|
|
|
|
Super::_postCreate();
|
|
|
|
setTerminal( true );
|
|
|
|
|
|
|
|
_subDevicesLibrary = Library::create( getLibrary(), getName() );
|
|
|
|
_anonymous = Net::create( this, anonymousNetName );
|
|
|
|
_anonymous->setAutomatic( true );
|
|
|
|
Technology* tech = DataBase::getDB()->getTechnology();
|
|
|
|
DeviceDescriptor* dd = tech->getDeviceDescriptor( deviceName );
|
|
|
|
DeviceDescriptor::Layouts ddLayouts = dd->getLayouts();
|
|
|
|
|
|
|
|
for ( auto ddLayout : ddLayouts ) _layouts.insert( ddLayout );
|
|
|
|
|
|
|
|
Choices layouts;
|
|
|
|
for ( auto layout : _layouts ) layouts << getString(layout.first);
|
|
|
|
_layoutStyles = addChoiceParameter( "Layout Styles", layouts );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Device::_preDestroy ()
|
|
|
|
{
|
|
|
|
for ( Parameter* parameter : _parameterSet ) delete parameter;
|
|
|
|
_subDevicesLibrary->destroy();
|
|
|
|
Super::_preDestroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
Parameter* Device::getParameter ( const string& parameterId ) const
|
2018-10-01 09:52:17 -05:00
|
|
|
{
|
|
|
|
for ( Parameter* parameter : _parameterSet) {
|
|
|
|
if (parameter->getName() == parameterId)
|
|
|
|
return parameter;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const string Device::getLayoutScript ()
|
|
|
|
{
|
|
|
|
Name layoutName = Name( _layoutStyles->getValue() );
|
|
|
|
Layouts::iterator findLayout = _layouts.find( layoutName );
|
|
|
|
|
|
|
|
if (findLayout != _layouts.end()) return (*findLayout).second;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Device::destroyLayout ()
|
|
|
|
{
|
|
|
|
UpdateSession::open();
|
|
|
|
|
|
|
|
// size_t icomp = 0;
|
|
|
|
// for ( Component* component : getComponents() ) {
|
|
|
|
// cerr << setw(4) << icomp << " | " << component << endl;
|
|
|
|
// }
|
|
|
|
|
|
|
|
while ( not getComponents().isEmpty() ) getComponents().getFirst()->destroy();
|
|
|
|
while ( not getReferences().isEmpty() ) getReferences().getFirst()->destroy();
|
|
|
|
|
|
|
|
for ( Net* net : getNets() ) {
|
|
|
|
Rubbers rubbers = net->getRubbers();
|
|
|
|
while ( rubbers.getFirst() ) rubbers.getFirst()->_destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateSession::close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int Device::getRestriction( Hurricane::Net* net ) const
|
|
|
|
{ return 0xAA; }
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int Device::getRestrictions2 ( Hurricane::Net* net ) const
|
|
|
|
{
|
|
|
|
map<Net*,unsigned int>::const_iterator inet = _netRestrictions.find( net );
|
|
|
|
if (inet == _netRestrictions.end()) return AllBlocked;
|
|
|
|
return (*inet).second;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Device::setRestrictions2 ( Hurricane::Net* net, unsigned int flags )
|
|
|
|
{
|
|
|
|
if (not net) return;
|
|
|
|
if (net->getCell() != this) {
|
|
|
|
cerr << Hurricane::Warning( "Device::setRestrictions2(): Net \"%s\" (of Device \"%s\")"
|
|
|
|
" do not belong to \"%s\"."
|
|
|
|
, getString(net->getName()).c_str()
|
|
|
|
, getString(net->getCell()->getName()).c_str()
|
|
|
|
, getString(getName()).c_str()
|
|
|
|
) << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_netRestrictions[ net ] = flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Hurricane::Record* Device::_getRecord () const
|
|
|
|
{
|
|
|
|
Record* record = Super::_getRecord();
|
|
|
|
if (record) {
|
|
|
|
record->add( getSlot("_subDevicesLibrary", _subDevicesLibrary) );
|
|
|
|
record->add( getSlot("_netRestrictions" , &_netRestrictions ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
return record;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // Analog namespace.
|