coriolis/bora/src/HVSetState.cpp

403 lines
11 KiB
C++
Raw Normal View History

Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2015-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | B o r a - A n a l o g S l i c i n g T r e e |
// | |
// | Authors : Eric LAO |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./HVSetState.cpp" |
// +-----------------------------------------------------------------+
#include "bora/HVSetState.h"
#include "bora/HSlicingNode.h"
#include "bora/VSlicingNode.h"
namespace Bora {
using namespace std;
// -------------------------------------------------------------------
// Class : "Bora::HVSetState".
HVSetState::HVSetState ( HVSlicingNode* node )
: _HVSnode ( node )
, _counter ( 1 )
, _currentSet()
, _nextSet ()
, _nodeSets ( NodeSets::create() )
{
initSet();
initModulos();
}
HVSetState::~HVSetState ()
{ }
NodeSets* HVSetState::getNodeSets ()
{
_nodeSets->sort();
return _nodeSets;
}
void HVSetState::print ()
{
int index = 0;
cerr << "currentSet:" << endl;
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {
NodeSets* nodes = children[ ichild ]->getNodeSets();
cerr << index << ": H = " << nodes->at(_currentSet[ichild])->getHeight()
<< ", W = " << nodes->at(_currentSet[ichild])->getWidth () << endl;
}
cerr << "counter = " << _counter << endl;
cerr << "end counter = " << _modulos.back() << endl;
cerr << "modulos:" << endl;
for ( size_t i=0 ; i<_modulos.size() ; ++i )
cerr << i << ": modulo = " << _modulos[i] << endl;
_nodeSets->print();
}
void HVSetState::initSet ()
{
_nextSet.clear();
for ( SlicingNode* child : _HVSnode->getChildren() ) {
if (child->isPreset())
_nextSet.push_back( child->getNodeSets()->findIndex( child->getHeight()
, child->getWidth () ) );
else
_nextSet.push_back( 0 );
}
_currentSet = _nextSet;
}
// Notes:
//
// Considering a horizontal/vertical node with X children and each children
// has N possibilities:
//
// child 0: N0 possibilities,
// child 1: N1 possibilities,
// .
// .
// .
// child X: NX possibilities.
//
// If a child is preset then, it only has 1 possibility and N = 1. So we have:
//
// number of possibilities to be studied = N0 * N1 * ... * NX.
//
// Children are seen like a <vector> and modulos are used to know when a
// child needs to choose its next possibility.
//
// It starts like this:
// - Child 0 goes through its N0 possibilities
// - When child 0 was at its last possibility, it goes back to its first one
// and child 1 pick its second possibility.
// - And we keep going . . .
void HVSetState::initModulos ()
{
cdebug_log(535,0) << "HVSetState::initModulos()" << endl;
int modulo = 1;
_modulos.clear();
_modulos.push_back( 1 );
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {
if (ichild) _modulos.push_back( modulo );
if (isSymmetry(ichild)) {
cdebug_log(535,0) << "child:" << ichild << " is symmetric, one choice." << endl;
continue;
}
if (children[ichild]->isPreset() ) {
cdebug_log(535,0) << "child:" << ichild << " is preset, one choice." << endl;
continue;
}
cdebug_log(535,0) << "child:" << ichild << " is ordinary, "
<< "has " << children[ichild]->getNodeSets()->size() << " choices."
<< endl;
modulo *= children[ichild]->getNodeSets()->size();
}
_modulos.push_back( modulo );
for ( size_t i=0 ; i<_modulos.size() ; ++i )
cdebug_log(535,0) << "_modulos[" << i << "]:" << _modulos[i] << endl;
}
void HVSetState::next ()
{
// Notes: Set the next combination. See notes above.
cdebug_log(535,0) << "HVSetState::next(): counter_:" << _counter << endl;
Groudwork for routing density driven placement. Compliance with clang 5.0.1. This commit contains two set of features that should have been commited separately. 1. Compliance with clang 5.0.1, tested with the RedHat collection llvm-toolset-7. This allow Coriolis to be compiled under Darwin (MacOS) with Xcode & macports. The bootstrap install system has been modificated accordingly. 2. The basic support for routing density driven placement. Related features are: * Bloat property. Each Occurrence of an Instance can be individually bloated. This property not attached to any tool to allow the placer and router to share it as wanted. Nevertheless, it is defined in Etesian. * BloatProfile in Katana, add individual Bloat properties to Instances occurrences based on the East & North overflowed edges of each GCell. * Support in ToolEngine for a "pass number" of a tool. This pass number is mainly used to make "per pass" measurements. The MeasureSet system is improved accordingly to support multiple values of a same measure. * Embryo of "P&R Conductor" to perform the place & route loop until the design is successfully placed. May be the first brick of a Silicon Compiler. * Change: In boostrap/FindBoostrap.cmake, in setup_boost(), added tag to the python component for macport (ex: python27). * Change: In boostrap/build.conf, put etesian before anabatic for instance occurrence BloatProperty dependency. Added option support for the "llvm-toolset-7" collection to build against clang 5.0.1. * Bug: In Hurricane::getRecord( const pair<T,U>& ), the getSlot<> templates for first & second arguments must be called with <const T> and <const U> as the pair itself is const (and not simply <T> & <U>). * Change: In Hurricane::getSlot() temlate, only use "string" arguments and not const string&, simpler for template argument deduction. * Bug: In Hurricane::AnalogCellExtension, the StandardPrivateProperty<> template has a static member "_name". Clang did show that the template for this static number has to be put inside the namespace where the template *is defined* (i.e. Hurricane) instead of the namespace where it is instanciated (i.e. Analog). * Bug: In Isobar, Matrix_FromListOfList(), PyInt_AsPlacementStatus() must be put outside the C linkage back in the Isobar C++ namespace (clang). * Bug: In Hurricane::DBo::~DBo, and derived add a throw() specification (clang). * Bug: In Hurricane::RegularLayer::getEnclosure() & setEnclosure(), change signature so it matches the one of the base class (clang). * Bug: In Hurricane::CellPrinter, use double brackets for initializer list (clang). * Change: In Hurricane::Breakpoint, reverse the meaning of the error level. Only error level *lesser or equal* than the stop level will be enabled. * Bug: In CRL/python/helpers/__init__.loadUserSettings(), must put the current working directory in the sys.path as in certain configuration it may not be included. * Bug: In CRL::ApDriver, DumpSegments(), no longer generate segments when encountering a RoutingPad on a top-level Pin Occurrence. The segment was generated in the wrong direction, creating DRC violations on the "mips_core_flat" example. * Change: In CRL::Measures, partial re-design of the measurements management. Now, each kind of measure can accept multiple values put in a vector. The index is intented to match a tool run number. * Change: In CRL::Histogram, add support for multiple sets of datas, indexeds with tool run number. * Change: In CRL::ToolEngine, add support for multiple pass number, add addMeasure<> templates for the various data-types. * Change: In CRL::gdsDriver & CRL::gdsParser(), comment out unused GDS record name constants. * New: Etesian::BloatProperty, property to attach to Instance occurrences that contains the extra number of pitch to add to the cell width. * Bug: In AutoSegment::CompareByDepthLength, the segment length comparison was wrong, it was always returning true, which broke the "strick weak ordering" of the comparison. This was producing a core-dump in GCell::updateDensity() when sorting a vector<>. The end() iterator was being dereferenced, leading to the problem. * Bug: In Katana::DataSymmetric::checkPairing(), the test for segments whose axis is perpandicular to the symmetry axis was wrong ("!=" instead of "-"). * New: In Katana/GlobalRoute, new ::selectSegments(), selectOverloadedgcells() and selectBloatedInstances() to automatically select segments from overloaded edges, overloaded GCells and bloated cells. * Change: In KatanaEngine, return a more detailed success state, distinguish between global and detailed. Add support for multiple routing iterations. * New: In cumulus/python/plugins/ConductorPlugin.py, embryo of routing driven placement.
2019-12-08 18:57:44 -06:00
Symmetry symmetry;
Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {
if (isSymmetry(ichild,symmetry))
_nextSet[ ichild ] = _nextSet[ symmetry.first ];
else {
if ( (((_counter-1)%_modulos[ichild]) == _modulos[ichild]-1)
and not children[ichild]->isPreset() ) {
if (_nextSet[ichild]+1 != children[ichild]->getNodeSets()->size() ) _nextSet[ichild]++;
else _nextSet[ichild] = 0;
}
}
}
_counter += 1;
_currentSet = _nextSet;
}
// -------------------------------------------------------------------
// Class : "Bora::HSetState".
HSetState::HSetState ( HSlicingNode* node )
: HVSetState(node)
{ }
HSetState::~HSetState ()
{ }
pair<DbU::Unit,DbU::Unit> HSetState::getCurrentWs ()
{
// Notes:
// Calculate the min and max width of the current combination Routing nodes
// need to be taken into account to not calculate a wrong width.
DbU::Unit wmin = 0;
DbU::Unit wmax = 0;
if (not _currentSet.empty()) {
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; (wmin == 0) and (ichild<children.size()) ; ++ichild ) {
NodeSets* nodes = children[ichild]->getNodeSets();
wmin = nodes->at( _currentSet[ichild] )->getWidth();
}
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {
NodeSets* nodes = children[ichild]->getNodeSets();
DbU::Unit width = nodes->at( _currentSet[ichild] )->getWidth();
if ( width and (width < wmin) ) wmin = width;
if (width > wmax) wmax = width;
}
}
return pair<DbU::Unit,DbU::Unit>( wmin, wmax );
}
DbU::Unit HSetState::getCurrentH ()
{
// Notes:
// Calculate the height of the current combination.
// Routing nodes need to be taken into account to not calculate a wrong height.
DbU::Unit currentH = 0;
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {
NodeSets* nodes = children[ichild]->getNodeSets();
currentH += nodes->at( _currentSet[ichild] )->getHeight();
}
return currentH;
}
DbU::Unit HSetState::getCurrentW ()
{
// Notes:
// Calculate the width of the current combination
// Routing nodes need to be taken into account to not calculate a wrong width.
DbU::Unit currentW = 0;
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {
NodeSets* nodes = children[ichild]->getNodeSets();
currentW = std::max( currentW, nodes->at( _currentSet[ichild] )->getWidth() );
}
return currentW;
}
void HSetState::print ()
{
HVSetState::print();
cerr << "currentH = " << getCurrentH() << endl;
cerr << "currentW = " << getCurrentW() << endl;
cerr << endl;
}
void HSetState::next ()
{
push_back();
HVSetState::next();
}
void HSetState::push_back ()
{
// Notes:
// Check if conditions on tolerance are filled.
// If yes, add the current set to the NodeSets
pair<DbU::Unit,DbU::Unit> paireWidths = getCurrentWs();
DbU::Unit width = paireWidths.second;
DbU::Unit wmin = paireWidths.first;
DbU::Unit height = 0;
if (width - wmin <= _HVSnode->getToleranceBandW()) {
vector<BoxSet*> bss;
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {
NodeSets* nodes = children[ichild]->getNodeSets();
bss.push_back( nodes->at( _currentSet[ichild] ) );
height += bss.back()->getHeight();
}
// create the BoxSet of the current accepted set.
_nodeSets->push_back( bss, height, width, HorizontalSNode );
}
}
// -------------------------------------------------------------------
// Class : "Bora::VSetState".
VSetState::VSetState ( VSlicingNode* node )
: HVSetState(node)
{ }
VSetState::~VSetState ()
{ }
pair<DbU::Unit,DbU::Unit> VSetState::getCurrentHs ()
{
// Note: Same as HSetState but for Vertical Node (see above).
DbU::Unit hmin = 0;
DbU::Unit hmax = 0;
if (not _currentSet.empty()) {
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; (hmin == 0) and (ichild<children.size()) ; ++ichild ) {
NodeSets* nodes = children[ichild]->getNodeSets();
DbU::Unit height = nodes->at( _currentSet[ichild] )->getHeight();
if ( height and (height < hmin) ) hmin = height;
if (height > hmax) hmax = height;
}
}
return pair<DbU::Unit,DbU::Unit>( hmin, hmax );
}
DbU::Unit VSetState::getCurrentH ()
{
DbU::Unit currentH = 0;
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {
NodeSets* nodes = children[ichild]->getNodeSets();
currentH = std::max( currentH, nodes->at( _currentSet[ichild] )->getHeight() );
}
return currentH;
}
DbU::Unit VSetState::getCurrentW ()
{
DbU::Unit currentW = 0;
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {
NodeSets* nodes = children[ichild]->getNodeSets();
currentW += nodes->at( _currentSet[ichild] )->getWidth();
}
return currentW;
}
void VSetState::print ()
{
HVSetState::print();
cerr << "currentH = " << getCurrentH() << endl;
cerr << "currentW = " << getCurrentW() << endl;
cerr << endl;
}
void VSetState::next ()
{
push_back();
HVSetState::next();
}
void VSetState::push_back ()
{
pair<DbU::Unit,DbU::Unit> paireHeights = getCurrentHs();
DbU::Unit height = paireHeights.second;
DbU::Unit hmin = paireHeights.first;
DbU::Unit width = 0;
if (height - hmin <= _HVSnode->getToleranceBandH()) {
vector<BoxSet*> bss;
const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; (hmin == 0) and (ichild<children.size()) ; ++ichild ) {
NodeSets* nodes = children[ichild]->getNodeSets();
bss.push_back( nodes->at( _currentSet[ichild] ) );
width += bss.back()->getWidth();
}
_nodeSets->push_back( bss, height, width, VerticalSNode );
}
}
} // Bora namespace.