diff --git a/crlcore/src/ccore/CMakeLists.txt b/crlcore/src/ccore/CMakeLists.txt index 44e1913a..8168ed74 100644 --- a/crlcore/src/ccore/CMakeLists.txt +++ b/crlcore/src/ccore/CMakeLists.txt @@ -68,6 +68,10 @@ crlcore/Ispd04Bookshelf.h crlcore/Ispd05Bookshelf.h crlcore/Ioc.h + crlcore/VhdlBit.h + crlcore/VhdlSignal.h + crlcore/VhdlEntity.h + crlcore/VhdlPortMap.h crlcore/NetExtension.h crlcore/Measures.h crlcore/RoutingGauge.h @@ -130,7 +134,12 @@ toolbox/RoutingPads.cpp toolbox/NamingScheme.cpp ) - set ( vst_driver_cpps alliance/vst/VstDriver.cpp ) + set ( vst_driver_cpps alliance/vst/VhdlBit.cpp + alliance/vst/VhdlSignal.cpp + alliance/vst/VhdlPortMap.cpp + alliance/vst/VhdlEntity.cpp + alliance/vst/VstDriver.cpp + ) set ( properties_cpps properties/NetExtension.cpp properties/Measures.cpp ) diff --git a/crlcore/src/ccore/alliance/vst/VhdlBit.cpp b/crlcore/src/ccore/alliance/vst/VhdlBit.cpp new file mode 100644 index 00000000..10cf8dbc --- /dev/null +++ b/crlcore/src/ccore/alliance/vst/VhdlBit.cpp @@ -0,0 +1,176 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance VHDL / Hurricane Interface | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./alliance/vst/VhdlNetProperty.cpp" | +// +-----------------------------------------------------------------+ + + +#include "crlcore/VhdlBit.h" +#include "crlcore/VhdlSignal.h" + + +namespace Vhdl { + + using namespace std; + using Hurricane::_TName; + using Hurricane::Property; + + + const size_t Bit::nindex = std::numeric_limits::max(); + + +// ------------------------------------------------------------------- +// Class : "::Bit" (implementation). + + ptrdiff_t Bit::_offset = 0; + + + Bit::Bit ( BitProperty* property, const Net* net, Signal* signal, size_t index ) + : _signal(signal) + , _index (index) + { + if (not _offset) { + //_offset = offsetof(ScalarSignal,_toNet); + _offset = (ptrdiff_t)this - (ptrdiff_t)property; + } + } + + + Bit::Bit ( size_t index ) + : _signal(NULL) + , _index (index) + { } + + + Bit::~Bit () + { } + + + bool Bit::isExternal () const { return getNet()->isExternal(); } + bool Bit::isElement () const { return _index != nindex; } + const Signal* Bit::getSignal () const { return _signal; } + size_t Bit::getIndex () const { return _index; } + string Bit::getName () const { return _getString(); } + + + string Bit::_getString () const + { + string s = getSignal()->getName(); + + if (_index != nindex) { + if (getSignal()->isContiguous()) + s += "(" + getString(_index) + ")"; + else + s += "_" + getString(_index); + } + + return s; + } + + + Record* Bit::_getRecord () const + { + Record* record = new Record ( "" ); + if (record != NULL) { + record->add( getSlot("_signal", _signal) ); + record->add( getSlot("_index" , _index ) ); + } + return record; + } + + +// ------------------------------------------------------------------- +// Class : "BitProperty" + + Name BitProperty::_name = "Vhdl::Bit"; + + + BitProperty* BitProperty::create ( Net* owner, Signal* signal, size_t index ) + { + BitProperty *property = new BitProperty( owner, signal, index ); + + property->_postCreate (); + return property; + } + + + void BitProperty::onReleasedBy ( DBo* owner ) + { PrivateProperty::onReleasedBy( owner ); } + + + Name BitProperty::getPropertyName () + { return _name; } + + + Name BitProperty::getName () const + { return getPropertyName(); } + + + string BitProperty::_getTypeName () const + { return _TName( "BitProperty" ); } + + + string BitProperty::_getString () const + { + string s = PrivateProperty::_getString (); + s.insert ( s.length() - 1 , " " + getString(&_bit) ); + + return s; + } + + + Record* BitProperty::_getRecord () const + { + Record* record = PrivateProperty::_getRecord(); + if ( record ) { + record->add( getSlot( "_name", _name ) ); + record->add( getSlot( "_bit" , &_bit ) ); + } + return record; + } + + +// ------------------------------------------------------------------- +// Class : "BitExtension" + + + const Net* BitExtension::_owner = NULL; + Bit* BitExtension::_cache = NULL; + + + Bit* BitExtension::get ( const Net* net ) + { + if (net == _owner) return _cache; + _owner = net; + + Property* property = _owner->getProperty( BitProperty::getPropertyName() ); + if (property) _cache = static_cast(property)->getBit(); + else _cache = NULL; + + return _cache; + } + + + Bit* BitExtension::create ( Net* net, Signal* signal, size_t index ) + { + get( net ); + if (_cache) return _cache; + + BitProperty* property = new BitProperty( net, signal, index ); + net->put( property ); + + _cache = property->getBit(); + return _cache; + } + + +} // Vhdl namespace. diff --git a/crlcore/src/ccore/alliance/vst/VhdlEntity.cpp b/crlcore/src/ccore/alliance/vst/VhdlEntity.cpp new file mode 100644 index 00000000..4305ab88 --- /dev/null +++ b/crlcore/src/ccore/alliance/vst/VhdlEntity.cpp @@ -0,0 +1,526 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance VHDL / Hurricane Interface | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./alliance/vst/VhdlEntity.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include "hurricane/Warning.h" +#include "hurricane/Cell.h" +#include "crlcore/VhdlPortMap.h" +#include "crlcore/VhdlEntity.h" + + +namespace { + + using Hurricane::Net; + using Hurricane::Instance; + using Vhdl::Signal; + using Vhdl::PortMap; + using Vhdl::Entity; + + + class ComparePort { + public: + ComparePort ( unsigned int flags ) : _flags(flags) { }; + public: + inline bool operator() ( const Signal* lhs, const Signal* rhs ) const + { + bool isSupply1 = lhs->getNet()->isSupply(); + bool isSupply2 = rhs->getNet()->isSupply(); + if (isSupply1 != isSupply2) return not isSupply1; + + if (_flags & Entity::AsPortSignal) { + unsigned int dir1 = (unsigned int)lhs->getDirection() & Net::Direction::INOUT; + unsigned int dir2 = (unsigned int)rhs->getDirection() & Net::Direction::INOUT; + if (dir1 != dir2) { + if (not dir1) return false; + if (not dir2) return true; + return dir1 < dir2; + } + } + + bool isV1 = lhs->isVector(); + bool isV2 = rhs->isVector(); + if (isV1 != isV2) return not isV1; + + size_t range1 = lhs->getMax() - lhs->getMin(); + size_t range2 = rhs->getMax() - rhs->getMin(); + if (range1 != range2) return range1 < range2; + + return lhs->getName() < rhs->getName(); + } + private: + unsigned int _flags; + }; + + + class ComparePortMap { + public: + ComparePortMap () : _comparePort(Entity::AsPortSignal) { }; + public: + inline bool operator() ( const PortMap* lhs, const PortMap* rhs ) const + { return _comparePort( lhs->getSignal(), rhs->getSignal() ); } + private: + ComparePort _comparePort; + }; + + +} + + +namespace Vhdl { + + using namespace std; + using Hurricane::Warning; + using Hurricane::Property; + using Hurricane::_TName; + using Hurricane::ForEachIterator; + + + Tabulation tab (" "); + + +// ------------------------------------------------------------------- +// Class : "::Entity". + + vector Entity::_entities; + ptrdiff_t Entity::_offset = 0; + + + Entity::Entity ( EntityProperty* property, Cell* cell, unsigned int flags ) + : _signals() + , _globals() + , _flags (flags) + { + if (not _offset) { + //_offset = offsetof(EntityProperty,_entity); + _offset = (ptrdiff_t)this - (ptrdiff_t)property; + } + + if (_flags == NoFlags) _flags = EntityMode; + + forEach ( Net*, inet, cell->getNets() ) { + if (not inet->isExternal() and (flags & ComponentMode)) continue; + + string stem; + size_t index = 0; + if (parseNetName(*inet,stem,index)) { + if (inet->isGlobal()) { + cerr << Warning( "Vhdl::Entity::Entity(): Net is both vectorized and global, this is not allowed.\n" + " On Net <%s> of Cell <%s>." + , getString(inet->getName()).c_str() + , getString(cell->getName()).c_str() + ) << endl; + } + + VectorSignal* signal = const_cast( dynamic_cast( getSignal(stem) ) ); + if (not signal) + signal = new VectorSignal ( stem ); + signal->addNet( index, *inet ); + _signals.insert( signal ); + } else { + _signals.insert( new ScalarSignal(*inet) ); + if (inet->isGlobal()) + _globals.insert( new ScalarSignal(*inet) ); + } + } + + _entities.push_back( this ); + } + + + Entity::~Entity () + { + for ( auto signal : _signals ) delete signal; + for ( auto ientity=_entities.begin() ; ientity!=_entities.end() ; ++ientity ) { + if (*ientity == this) { + _entities.erase( ientity ); + break; + } + } + } + + + vector& Entity::getAllEntities () + { return _entities; } + + + bool Entity::parseNetName ( const Net* net, string& stem, size_t& index ) + { + string error; + string name = getString(net->getName()); + size_t leftpar = name.find( '(' ); + size_t rightpar = name.find( ')' ); + + if (leftpar == string::npos) { + stem = name; + index = 0; + + if (rightpar != string::npos) error = "unmatched right parenthesis"; + } else { + if (rightpar == string::npos) + error = "unmatched left parenthesis"; + else if (name.find('(',leftpar+1) != string::npos) + error = "multiple left parenthesis"; + else if (name.find(')',rightpar+1) != string::npos) + error = "multiple right parenthesis"; + else if (leftpar >= rightpar) + error = "left parenthesis *after* the right one"; + else { + size_t endindex = 0; + int value = stoi( name.substr(leftpar+1), &endindex ); + + if (endindex != rightpar-leftpar-1) + error = "unable to convert index (not a number)"; + else if (value < 0) + error = "negative index"; + else { + stem = name.substr( 0, leftpar ); + index = (size_t)value; + return true; + } + } + } + + if (not error.empty()) { + cerr << Warning( "Entity::parseVector() Net has not a valid VHDL name, %s.\n" + " %s\n" + , error.c_str() + , getString(net->getName()).c_str() + ) << endl; + } + + return false; + } + + + void Entity::toEntityMode () + { + if (isEntityMode()) return; + + forEach ( Net*, inet, getCell()->getNets() ) { + if (inet->isExternal()) continue; + + string stem; + size_t index = 0; + if (parseNetName(*inet,stem,index)) { + VectorSignal* signal = const_cast( dynamic_cast( getSignal(stem) ) ); + if (not signal) + signal = new VectorSignal ( stem ); + signal->addNet( index, *inet ); + _signals.insert( signal ); + } else { + _signals.insert( new ScalarSignal(*inet) ); + } + } + } + + + const Cell* Entity::getCell () const + { + EntityProperty* property = (EntityProperty*)((ptrdiff_t)(this) - _offset); + return (const Cell*)property->getOwner(); + } + + + const SignalSet* Entity::getSignals () const + { return &_signals; } + + + const Signal* Entity::getSignal ( string name ) const + { + VectorSignal key ( name ); + auto isignal = _signals.find( &key ); + if (isignal != _signals.end()) return *isignal; + + return NULL; + } + + + const Signal* Entity::getGlobal ( string name ) const + { + VectorSignal key ( name ); + auto isignal = _globals.find( &key ); + if (isignal != _globals.end()) return *isignal; + + return NULL; + } + + + void Entity::toSignals ( ostream& out ) const + { + size_t width = 0; + vector internalSignals; + for ( auto isignal=_signals.begin() ; isignal!=_signals.end() ; ++isignal ) { + if (not (*isignal)->isExternal()) { + width = max( width, (*isignal)->getName().size() ); + internalSignals.push_back( *isignal ); + } + } + sort( internalSignals.begin(), internalSignals.end(), ComparePort(Entity::AsInnerSignal) ); + + for ( auto isignal=internalSignals.begin(); isignal!=internalSignals.end() ; ++isignal ) { + out << tab; + (*isignal)->toVhdlPort( out, width, Entity::AsInnerSignal ); + out << ";\n"; + } + out << "\n"; + } + + + void Entity::toPort ( ostream& out ) const + { + out << tab << "port ( "; + + size_t width = 0; + vector ioSignals; + for ( auto isignal=_signals.begin() ; isignal!=_signals.end() ; ++isignal ) { + if ((*isignal)->isExternal()) { + width = max( width, (*isignal)->getName().size() ); + ioSignals.push_back( *isignal ); + } + } + sort( ioSignals.begin(), ioSignals.end(), ComparePort(Entity::AsPortSignal) ); + + size_t ioCount = 0; + for ( auto isignal=ioSignals.begin(); isignal!=ioSignals.end() ; ++isignal ) { + if (ioCount) out << "\n" << tab << " ; "; + (*isignal)->toVhdlPort( out, width, Entity::AsPortSignal ); + ++ioCount; + } + out << "\n" << tab << " );"; + } + + + void Entity::toEntity ( ostream& out ) const + { + time_t clock = time( nullptr ); + tm tm = *localtime( &clock ); + char stamp[1024]; + + strftime( stamp, 1024, "%b %d, %Y, %H:%M", &tm ); + + out << "\n"; + out << "-- =======================================================================\n"; + out << "-- Coriolis Structural VHDL Driver\n"; + out << "-- Generated on " << stamp << "\n"; + out << "-- \n"; + out << "-- To be interoperable with Alliance, it uses it's special VHDL subset.\n"; + out << "-- (\"man vhdl\" under Alliance for more informations)\n"; + out << "-- =======================================================================\n"; + out << "\n"; + out << tab++ << "entity " << getCell()->getName() << " is\n"; + toPort( out ); + out << --tab << "\nend " << getCell()->getName() << ";\n\n"; + + out << "architecture structural of " << getCell()->getName() << " is\n\n"; + ++tab; + + set masterCells; + forEach ( Instance*, iinstance, getCell()->getInstances() ) { + masterCells.insert( iinstance->getMasterCell() ); + } + + for ( auto icell : masterCells ) { + Vhdl::Entity* component = Vhdl::EntityExtension::create( icell, Vhdl::Entity::ComponentMode ); + component->toComponent( out ); + out << "\n"; + } + + toSignals( out ); + + out << "\n" << --tab << "begin\n\n"; + ++tab; + + forEach ( Instance*, iinstance, getCell()->getInstances() ) { + toInstance( out, *iinstance ); + out << "\n"; + } + + --tab; + out << "end structural;\n"; + } + + + void Entity::toComponent ( ostream& out ) const + { + out << tab++ << "component " << getCell()->getName() << "\n"; + toPort( out ); + out << "\n" << --tab << "end component;\n"; + } + + + void Entity::toInstance ( ostream& out, Instance* instance ) const + { + out << tab << instance->getName() << " : " << instance->getMasterCell()->getName() << "\n"; + out << tab << "port map ( "; + + Entity* masterEntity = EntityExtension::get( instance->getMasterCell() ); + if (not masterEntity) { + masterEntity = EntityExtension::create( instance->getMasterCell(), ComponentMode ); + } + + size_t width = 0; + vector portMaps; + const SignalSet* masterSignals = masterEntity->getSignals(); + for ( auto isignal=masterSignals->begin() ; isignal!=masterSignals->end() ; ++isignal ) { + if ((*isignal)->isExternal()) { + width = max( width, (*isignal)->getName().size() ); + portMaps.push_back( PortMap::create(*isignal) ); + portMaps.back()->doMapping( instance ); + } + } + sort( portMaps.begin(), portMaps.end(), ComparePortMap() ); + + size_t ioCount = 0; + for ( auto iportmap=portMaps.begin(); iportmap!=portMaps.end() ; ++iportmap ) { + if (ioCount) out << "\n" << tab << " , "; + (*iportmap)->toVhdlPortMap( out, width ); + ++ioCount; + + delete *iportmap; + } + + out << "\n" << tab << " );\n"; + } + + + string Entity::_getString () const + { + string s = getString(getCell()->getName()); + return s; + } + + + Record* Entity::_getRecord () const + { + Record* record = new Record ( "" ); + if (record != NULL) { + record->add( getSlot("_signals", _signals) ); + record->add( getSlot("_flags" , _flags ) ); + } + return record; + } + + +// ------------------------------------------------------------------- +// Class : "EntityProperty" + + Name EntityProperty::_name = "Vhdl::Entity"; + + + EntityProperty* EntityProperty::create ( Cell* owner, unsigned int flags ) + { + EntityProperty *property = new EntityProperty( owner, flags ); + + property->_postCreate (); + return property; + } + + + void EntityProperty::onReleasedBy ( DBo* owner ) + { PrivateProperty::onReleasedBy( owner ); } + + + Name EntityProperty::getPropertyName () + { return _name; } + + + Name EntityProperty::getName () const + { return getPropertyName(); } + + + string EntityProperty::_getTypeName () const + { return _TName( "EntityProperty" ); } + + + string EntityProperty::_getString () const + { + string s = PrivateProperty::_getString (); + s.insert ( s.length() - 1 , " " + getString(&_entity) ); + + return s; + } + + + Record* EntityProperty::_getRecord () const + { + Record* record = PrivateProperty::_getRecord(); + if ( record ) { + record->add( getSlot( "_name" , _name ) ); + record->add( getSlot( "_entity", &_entity ) ); + } + return record; + } + + +// ------------------------------------------------------------------- +// Class : "EntityExtension" + + + const Cell* EntityExtension::_owner = NULL; + Entity* EntityExtension::_cache = NULL; + + + Entity* EntityExtension::get ( const Cell* cell ) + { + if (cell != _owner) { + _owner = cell; + + Property* property = _owner->getProperty( EntityProperty::getPropertyName() ); + if (property) _cache = static_cast(property)->getEntity(); + else _cache = NULL; + } + return _cache; + } + + + Entity* EntityExtension::create ( Cell* cell, unsigned int flags ) + { + get( cell ); + if (not _cache) { + EntityProperty* property = new EntityProperty( cell, flags ); + cell->put( property ); + + _cache = property->getEntity(); + } else { + if ( (flags & Entity::EntityMode) and (not _cache->isEntityMode()) ) + _cache->toEntityMode(); + } + + return _cache; + } + + + void EntityExtension::destroy ( Cell* cell ) + { + Property* property = cell->getProperty( EntityProperty::getPropertyName() ); + if (property) static_cast(property)->destroy(); + + _owner = NULL; + _cache = NULL; + } + + + void EntityExtension::destroyAll () + { + vector& entities = Entity::getAllEntities(); + + while ( not entities.empty() ) destroy( const_cast(entities.back()->getCell()) ); + } + + + +} // Vhdl namespace. diff --git a/crlcore/src/ccore/alliance/vst/VhdlPortMap.cpp b/crlcore/src/ccore/alliance/vst/VhdlPortMap.cpp new file mode 100644 index 00000000..3cce1494 --- /dev/null +++ b/crlcore/src/ccore/alliance/vst/VhdlPortMap.cpp @@ -0,0 +1,250 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance VHDL / Hurricane Interface | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./alliance/vst/VhdlPortMap.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/Error.h" +#include "hurricane/Warning.h" +#include "hurricane/Cell.h" +#include "hurricane/Plug.h" +#include "hurricane/Instance.h" +#include "crlcore/VhdlPortMap.h" +#include "crlcore/VhdlEntity.h" + + +namespace Vhdl { + + using namespace std; + using Hurricane::Error; + using Hurricane::Plug; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::PortMap". + + + PortMap::PortMap () + { } + + + PortMap::~PortMap () + { } + + + const Bit* PortMap::_lookup ( const Bit* masterBit, Instance* instance ) + { + const Net* masterNet = masterBit->getNet(); + Plug* plug = instance->getPlug( masterNet ); + if (masterNet->isGlobal() and not plug->isConnected()) { + Entity* entity = EntityExtension::get( instance->getCell() ); + const Signal* signal = entity->getGlobal( getString(masterNet->getName()) ); + if (signal) return signal->getBit(); + + cerr << Error( "PortMap::_lookup() VHDL extension missing on parent of global <%s>." + , getString(masterNet).c_str() + ) << endl; + } else { + Net* net = plug->getNet(); + if (net) { + Bit* bit = BitExtension::get( net ); + if (bit) return bit; + + cerr << Error( "PortMap::_lookup() VHDL extension missing on <%s>." + , getString(net).c_str() + ) << endl; + } else { + cerr << Error( "PortMap::_lookup() Unconnected <%s>." + , getString(plug).c_str() + ) << endl; + } + } + return NULL; + } + + + PortMap* PortMap::create ( const Signal* signal ) + { + const ScalarSignal* scalarSignal = dynamic_cast( signal ); + if (not scalarSignal) { + const VectorSignal* vectorSignal = dynamic_cast( signal ); + if (vectorSignal) + return new VectorPortMap ( vectorSignal ); + else + throw Error( "PortMap::create() Unable to cast toward or ." ); + } + return new ScalarPortMap ( scalarSignal ); + } + + +// ------------------------------------------------------------------- +// Class : "Vhdl::ScalarPortMap". + + ScalarPortMap::ScalarPortMap ( const ScalarSignal* signal ) + : PortMap () + , _signal (signal) + , _mapping(NULL) + { } + + + ScalarPortMap::~ScalarPortMap () + { } + + + const ScalarSignal* ScalarPortMap::getSignal () const + { return _signal; } + + + void ScalarPortMap::doMapping ( Instance* instance ) + { _mapping = _lookup( _signal->getBit(0), instance ); } + + + void ScalarPortMap::toVhdlPortMap ( ostream& out, size_t width ) const + { + out << setw(width) << left << _signal->getName() << " => "; + if (_mapping) out << _mapping->getName(); + else out << "UNCONNECTED"; + } + + +// ------------------------------------------------------------------- +// Class : "Vhdl::VectorPortMap". + + VectorPortMap::VectorPortMap ( const VectorSignal* signal ) + : PortMap () + , _signal (signal) + , _mapping() + { + for ( size_t index=_signal->getMin() ; index<=_signal->getMax() ; ++index ) { + const Bit* bit = _signal->getBit( index ); + if (not bit) continue; + + _mapping.insert( pair(index,NULL) ); + } + } + + + VectorPortMap::~VectorPortMap () + { } + + + const VectorSignal* VectorPortMap::getSignal () const + { return _signal; } + + + void VectorPortMap::doMapping ( Instance* instance ) + { + for ( size_t index=_signal->getMin() ; index<=_signal->getMax() ; ++index ) { + if (not _signal->getBit(index)) continue; + _mapping[ index ] = _lookup( _signal->getBit(index), instance ); + } + } + + + void VectorPortMap::toVhdlPortMap ( ostream& out, size_t width ) const + { + if (getSignal()->isContiguous()) { + vector mappedNames; + int begin = -1; + int end = -1; + const Bit* bit = NULL; + const Bit* bitp = NULL; + string name = "UNCONNECTED"; + string namep = "UNCONNECTED"; + + auto imapping = _mapping.rbegin(); + auto imappingp = _mapping.rbegin(); + + for ( ++imapping ; imapping!=_mapping.rend() ; ++imapping, ++imappingp ) { + bit = imapping ->second; + bitp = imappingp->second; + name = (bit ) ? bit ->getSignal()->getName() : "UNCONNECTED"; + namep = (bitp) ? bitp->getSignal()->getName() : "UNCONNECTED"; + + if ( bit + and bitp + and bitp->getSignal()->isVector() + and bitp->getSignal()->isContiguous() + and (name == namep)) { + if (begin < 0) begin = bitp->getIndex(); + if (end < 0) end = bit ->getIndex(); + + int delta = (int)bit->getIndex() - (int)bitp->getIndex(); + if ( not ((delta > 0) xor (begin < end)) ) { + end = bit->getIndex(); + continue; + } + } + + if (begin != end) { + string vdir = (begin < end) ? "to" : "downto"; + mappedNames.push_back( namep + "(" + getString(begin) + " " + vdir + " " + getString(end) + ")" ); + } else { + if ( (bitp == NULL) or (not bitp->getSignal()->isVector()) ) { + mappedNames.push_back( namep ); + } else { + mappedNames.push_back( bitp->getName() ); + } + } + + begin = -1; + end = -1; + } + + bitp = imappingp->second; + namep = (bitp) ? bitp->getSignal()->getName() : "UNCONNECTED"; + + if (begin != end) { + string vdir = (begin < end) ? "to" : "downto"; + mappedNames.push_back( namep + "(" + getString(begin) + " " + vdir + " " + getString(end) + ")" ); + } else { + if ( (bitp == NULL) or (not bitp->getSignal()->isVector()) ) { + mappedNames.push_back( namep ); + } else { + mappedNames.push_back( bitp->getName() ); + } + } + + out << setw(width) << left << _signal->getName() << " => "; + + size_t lhsWidth = 90 - tab.getWidth() - width - 4; + size_t lhsLength = 0; + + bool first = true; + for ( auto name : mappedNames ) { + if (not first) { out << " & "; lhsLength += 3; } + + if (lhsLength + name.size() > lhsWidth) { + out << "\n" << tab << setw(width+15) << " "; + lhsLength = 0; + } + lhsLength += name.size(); + + out << name; + first = false; + } + } else { + auto imapping = _mapping.rbegin(); + bool first = true; + for ( ; imapping!=_mapping.rend() ; ++imapping ) { + if (not first) out << "\n" << tab << " , "; + + out << setw(width) << left << _signal->getBit(imapping->first)->getName() + << " => " << imapping->second->getName(); + first = false; + } + } + } + + +} // Vhdl namespace. diff --git a/crlcore/src/ccore/alliance/vst/VhdlSignal.cpp b/crlcore/src/ccore/alliance/vst/VhdlSignal.cpp new file mode 100644 index 00000000..2252dd12 --- /dev/null +++ b/crlcore/src/ccore/alliance/vst/VhdlSignal.cpp @@ -0,0 +1,285 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance VHDL / Hurricane Interface | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./alliance/vst/VhdlSignal.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include "hurricane/Warning.h" +#include "crlcore/VhdlSignal.h" +#include "crlcore/VhdlEntity.h" + + +namespace Vhdl { + + using namespace std; + using Hurricane::Warning; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::Signal". + + Signal::Signal ( string name ) + : _name(name) + { } + + Signal::~Signal () + { } + + + void Signal::_toVhdlPort ( ostream& out + , int width + , unsigned int flags + , string name + , string range + , Net::Direction direction ) + { + //out << tab; + if (flags & Entity::AsInnerSignal) out << "signal "; + + out << setw(width) << left << name << " : "; + + if (flags & Entity::AsPortSignal) { + switch ( (unsigned int)direction & (Net::Direction::DirIn|Net::Direction::DirOut) ) { + case Net::Direction::IN: out << "in"; break; + case Net::Direction::OUT: out << "out"; break; + case Net::Direction::INOUT: out << "inout"; break; + default: out << "linkage"; + } + } + + if (not range.empty()) { + switch ( (unsigned int)direction & (Net::Direction::ConnTristate + |Net::Direction::ConnWiredOr) ) { + case Net::Direction::ConnTristate: out << " mux_vector" << range << " bus"; break; + case Net::Direction::ConnWiredOr: out << " wor_vector" << range << " bus"; break; + default: out << " bit_vector" << range; + } + } else { + switch ( (unsigned int)direction & (Net::Direction::ConnTristate + |Net::Direction::ConnWiredOr) ) { + case Net::Direction::ConnTristate: out << " mux_bit bus"; break; + case Net::Direction::ConnWiredOr: out << " wor_bit bus"; break; + default: out << " bit"; + } + } + } + + + Record* Signal::_getRecord () const + { + Record* record = new Record ( getString(this) ); + record->add ( getSlot("_name", &_name) ); + return record; + } + + +// ------------------------------------------------------------------- +// Class : "Vhdl::ScalarSignal". + + + ScalarSignal::ScalarSignal ( Net* net ) + : Signal(getString(net->getName())) + , _bit (BitExtension::create(net,this)) + { } + + ScalarSignal::~ScalarSignal () + { } + + bool ScalarSignal::isScalar () const { return true; } + bool ScalarSignal::isVector () const { return false; } + bool ScalarSignal::isExternal () const { return _bit->isExternal(); } + bool ScalarSignal::isContiguous () const { return false; } + const Bit* ScalarSignal::getBit () const { return _bit; } + const Bit* ScalarSignal::getBit ( size_t ) const { return _bit; } + const Net* ScalarSignal::getNet () const { return _bit->getNet(); } + const Net* ScalarSignal::getNet ( size_t ) const { return _bit->getNet(); } + size_t ScalarSignal::getMin () const { return Bit::nindex; } + size_t ScalarSignal::getMax () const { return Bit::nindex; } + Net::Direction ScalarSignal::getDirection () const { return getNet(0)->getDirection(); } + + + void ScalarSignal::toVhdlPort ( ostream& out, int width, unsigned int flags ) const + { _toVhdlPort( out, width, flags, getName(), string(), getDirection() ); } + + + string ScalarSignal::_getString () const + { + string s = ""; + return s; + } + + + Record* ScalarSignal::_getRecord () const + { + Record* record = Signal::_getRecord(); + if (record) { + record->add ( getSlot("_bit", _bit) ); + } + return record; + } + + +// ------------------------------------------------------------------- +// Class : "Vhdl::VectorSignal". + + + VectorSignal::VectorSignal ( string name ) + : Signal (name) + , _bits () + , _direction(Net::Direction::UNDEFINED) + , _flags (Contiguous) + { } + + VectorSignal::~VectorSignal () + { for ( auto bit : _bits ) bit->getProperty()->destroy(); } + + + bool VectorSignal::isScalar () const { return false; } + bool VectorSignal::isVector () const { return true; } + bool VectorSignal::isExternal () const { return (*_bits. begin())->isExternal(); } + size_t VectorSignal::getMin () const { return (*_bits.rbegin())->getIndex(); } + size_t VectorSignal::getMax () const { return (*_bits. begin())->getIndex(); } + Net::Direction VectorSignal::getDirection () const { return _direction; } + + + const Bit* VectorSignal::getBit () const + { return *_bits.rend(); } + + + const Bit* VectorSignal::getBit ( size_t index ) const + { + Bit key ( index ); + auto inet = _bits.find( &key ); + if (inet != _bits.end()) return (*inet); + + return NULL; + } + + + const Net* VectorSignal::getNet () const + { + const Bit* bit = getBit( getMin() ); + return (bit) ? bit->getNet() : NULL; + } + + + const Net* VectorSignal::getNet ( size_t index ) const + { + const Bit* bit = getBit( index ); + return (bit) ? bit->getNet() : NULL; + } + + + bool VectorSignal::isContiguous () const + { + auto inet1 = _bits.rbegin(); + auto inet2 = inet1; + + for ( ++inet1; inet1!=_bits.rend() ; ++inet1, ++inet2 ) { + if ((*inet1)->getIndex() != (*inet2)->getIndex()+1) return false; + } + + return true; + } + + + void VectorSignal::toVhdlPort ( ostream& out, int width, unsigned int flags ) const + { + if (isContiguous()) { + string range = "(" + getString(getMax()) + " downto " + getString(getMin()) + ")"; + _toVhdlPort( out, width, flags, getName(), range, getDirection() ); + } else { + + bool first = true; + for ( auto bit : _bits ) { + string name = getName() + "_" + getString(bit->getIndex()); + if (not first) { + if (flags & Entity::AsPortSignal) out << "\n" << tab << " ; "; + else out << ";\n" << tab; + } + first = false; + + _toVhdlPort( out, width, flags, name, string(), getDirection() ); + } + + if (flags & Entity::AsPortSignal) + out << "\n" << tab << " -- Vector <" << getName() << "> is holed, unvectorized."; + else + out << ";\n" << tab << "-- Vector <" << getName() << "> is holed, unvectorized."; + } + } + + + bool VectorSignal::addNet ( size_t index, Net* net ) + { + const Net* check = getNet( index ); + if (check) { + if (check == net) return true; + + cerr << Warning( "VectorSignal::addNet() Attempt to create twice index %u for nets:\n" + " %s (previous)\n" + " %s (new)" + , index + , getString(check->getName()).c_str() + , getString(net ->getName()).c_str() + ) << endl; + return false; + } + + if (_direction == Net::Direction::UNDEFINED) + _direction = net->getDirection(); + else { + _direction |= net->getDirection(); + } + + _bits.insert( BitExtension::create(net,this,index) ); + + auto inet1 = _bits.rbegin(); + auto inet2 = inet1; + + _flags |= Contiguous; + for ( ++inet1; inet1!=_bits.rend() ; ++inet1, ++inet2 ) { + if ((*inet1)->getIndex() != (*inet2)->getIndex()+1) { + _flags &= ~Contiguous; + break; + } + } + + return true; + } + + + string VectorSignal::_getString () const + { + string s = "add ( getSlot("_bits" , &_bits ) ); + record->add ( getSlot("_direction", &_direction) ); + record->add ( getSlot("_flags" , &_flags ) ); + } + return record; + } + + +} // Vhdl namespace. diff --git a/crlcore/src/ccore/alliance/vst/VstDriver.cpp b/crlcore/src/ccore/alliance/vst/VstDriver.cpp index 8ef6fea8..ce610e3d 100644 --- a/crlcore/src/ccore/alliance/vst/VstDriver.cpp +++ b/crlcore/src/ccore/alliance/vst/VstDriver.cpp @@ -1,52 +1,39 @@ -// This file is part of the Coriolis Project. -// Copyright (C) Laboratoire LIP6 - Departement ASIM -// Universite Pierre et Marie Curie +// -*- C++ -*- // -// Main contributors : -// Christophe Alexandre -// Sophie Belloeil -// Hugo Clément -// Jean-Paul Chaput -// Damien Dupuis -// Christian Masson -// Marek Sroka -// -// 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 +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2004-2015, All Rights Reserved // -// License-Tag -// -// Date : 01/10/2004 -// Author : Christophe Alexandre -// -// Authors-Tag +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Yosys & Blif / Hurricane Interface | +// | | +// | Author : Christophe Alexandre | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./alliance/vst/VstDriver.cpp" | +// +-----------------------------------------------------------------+ -#include "hurricane/Cell.h" -#include "hurricane/Net.h" -#include "hurricane/Instance.h" -#include "hurricane/Plug.h" +#include +#include "hurricane/Warning.h" +#include "hurricane/Cell.h" +#include "hurricane/Net.h" +#include "hurricane/Instance.h" +#include "hurricane/Plug.h" using namespace Hurricane; -#include "crlcore/Catalog.h" -#include "crlcore/NetExtension.h" -#include "Vst.h" +#include "crlcore/Catalog.h" +#include "crlcore/NetExtension.h" +#include "crlcore/ToolBox.h" +#include "crlcore/VhdlBit.h" +#include "crlcore/VhdlSignal.h" +#include "crlcore/VhdlEntity.h" +#include "Vst.h" + namespace { - + using namespace std; using namespace CRL; @@ -153,13 +140,16 @@ unsigned FindIndex(const string& stringtosearch, string::size_type openpar) string getNetDirection(const Net* net) { - switch ( net->getDirection() & Net::Direction::INOUT ) { + switch ( net->getDirection() & (Net::Direction::INOUT | Net::Direction::UNDEFINED) ) { case Net::Direction::UNDEFINED: return "linkage"; case Net::Direction::IN: return "in"; case Net::Direction::OUT: return "out"; case Net::Direction::INOUT: return "inout"; default: - throw Error( "Unrecognized direction" ); + throw Error( "Unrecognized direction for Net <%s> of Cell <%s> (code:%u)" + , getString(net->getCell()->getName()).c_str() + , getString(net->getName()).c_str() + , (unsigned int)net->getDirection() ); } } @@ -606,15 +596,13 @@ void DumpConnectionList(ofstream &ccell, Instance*instance) string connectedNetName; if (plug1->isConnected()) { + cerr << plug1 << "plug is connected" << endl; Net* net = plug1->getNet(); - if (net->isExternal()) - { - const Name& portName = NetExtension::getPort(net); - if (!portName.isEmpty()) - connectedNetName = getString(portName); - else - connectedNetName = getString(net->getName()); - } + const Name& portName = NetExtension::getPort(net); + if (!portName.isEmpty()) + connectedNetName = getString(portName); + else + connectedNetName = getString(net->getName()); } else if (plug1->getMasterNet()->isGlobal()) { @@ -659,6 +647,16 @@ namespace CRL { void vstDriver ( const string cellPath, Cell *cell, unsigned int &saveState ) { + NamingScheme::toVhdl( cell, NamingScheme::FromVerilog ); + Vhdl::Entity* vhdlEntity = Vhdl::EntityExtension::create( cell, Vhdl::Entity::EntityMode ); + string celltest = cellPath; +//celltest.insert( celltest.size()-4, "_test" ); + ::std::ofstream ccelltest ( celltest.c_str() ); + vhdlEntity->toEntity(ccelltest); + ccelltest << endl; + ccelltest.close(); + +#if 0 __globalNets.clear (); ::std::ofstream ccell ( cellPath.c_str() ); @@ -714,6 +712,7 @@ void vstDriver ( const string cellPath, Cell *cell, unsigned int &saveState ) } ccell << "end structural;" << endl; ccell.close (); +#endif } } diff --git a/crlcore/src/ccore/blif/BlifParser.cpp b/crlcore/src/ccore/blif/BlifParser.cpp index cf9f8302..0f4a28f7 100644 --- a/crlcore/src/ccore/blif/BlifParser.cpp +++ b/crlcore/src/ccore/blif/BlifParser.cpp @@ -404,6 +404,7 @@ namespace { } else { net->addAlias( name ); if (isExternal) net->setExternal( true ); + direction &= ~Net::Direction::UNDEFINED; direction |= net->getDirection(); net->setDirection( (Net::Direction::Code)direction ); } diff --git a/crlcore/src/ccore/crlcore/VhdlBit.h b/crlcore/src/ccore/crlcore/VhdlBit.h new file mode 100644 index 00000000..ef069911 --- /dev/null +++ b/crlcore/src/ccore/crlcore/VhdlBit.h @@ -0,0 +1,162 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance VHDL / Hurricane Interface | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/VhdlBit.h" | +// +-----------------------------------------------------------------+ + + +#ifndef VHDL_BIT_H +#define VHDL_BIT_H + +#include +#include +#include "hurricane/Name.h" +#include "hurricane/Property.h" +#include "hurricane/Slot.h" +#include "hurricane/Net.h" + + +namespace Vhdl { + + using Hurricane::Record; + using Hurricane::Name; + using Hurricane::DBo; + using Hurricane::Net; + using Hurricane::PrivateProperty; + + class Signal; + class ScalarSignal; + class VectorSignal; + class BitProperty; + + +// ------------------------------------------------------------------- +// Class : "::Bit" (declaration). + + class Bit { + public: + static const size_t nindex; + public: + Bit ( BitProperty* + , const Net* + , Signal* + , size_t index ); + Bit ( size_t index ); + ~Bit (); + bool isExternal () const; + bool isElement () const; + inline BitProperty* getProperty () const; + inline const Net* getNet () const; + const Signal* getSignal () const; + std::string getName () const; + size_t getIndex () const; + std::string _getString () const; + Record* _getRecord () const; + private: + static ptrdiff_t _offset; + Signal* _signal; + size_t _index; + }; + + + struct GreaterBitByIndex { + inline bool operator() ( const Bit* lhs, const Bit* rhs ) const + { return lhs->getIndex() > rhs->getIndex(); } + }; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::BitProperty". + + class BitProperty : public Hurricane::PrivateProperty { + friend class BitExtension; + public: + static Name _name; + public: + static BitProperty* create ( Net* owner + , Signal* signal + , size_t index ); + static Name getPropertyName (); + virtual Name getName () const; + inline Bit* getBit (); + virtual void onReleasedBy ( DBo* owner ); + virtual std::string _getTypeName () const; + virtual std::string _getString () const; + virtual Record* _getRecord () const; + protected: + // Attributes. + Bit _bit; + + protected: + // Constructor. + inline BitProperty ( Net* owner, Signal*, size_t ); + }; + + + inline BitProperty::BitProperty ( Net* owner + , Signal* signal + , size_t index + ) + : PrivateProperty(), _bit(this,owner,signal,index) + { } + + inline Bit* BitProperty::getBit () { return &_bit; } + + +// ------------------------------------------------------------------- +// Class : "Vhdl::BitExtension". + + class BitExtension { + public: + static inline bool isElement ( const Net* ); + static inline const Signal* getSignal ( const Net* ); + static inline size_t getIndex ( const Net* ); + static Bit* get ( const Net* ); + static Bit* create ( Net*, Signal*, size_t index=Bit::nindex ); + private: + static const Net* _owner; + static Bit* _cache; + }; + + + inline bool BitExtension::isElement ( const Net* net ) + { + Bit* bit = get( net ); + return (bit == NULL) ? false : bit->isElement(); + } + + + inline const Signal* BitExtension::getSignal ( const Net* net ) + { + Bit* bit = get( net ); + return (bit == NULL) ? NULL : bit->getSignal(); + } + + + inline size_t BitExtension::getIndex ( const Net* net ) + { + Bit* bit = get( net ); + return (bit == NULL) ? false : bit->getIndex(); + } + + + inline BitProperty* Bit::getProperty () const { return (BitProperty*)((ptrdiff_t)(this) - _offset); } + inline const Net* Bit::getNet () const { return (const Net*)getProperty()->getOwner(); } + + +} // Vhdl Namespace. + + +INSPECTOR_P_SUPPORT(Vhdl::Bit); + + +#endif // VHDL_BIT_H diff --git a/crlcore/src/ccore/crlcore/VhdlEntity.h b/crlcore/src/ccore/crlcore/VhdlEntity.h new file mode 100644 index 00000000..bb69a6ff --- /dev/null +++ b/crlcore/src/ccore/crlcore/VhdlEntity.h @@ -0,0 +1,210 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance VHDL / Hurricane Interface | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/VhdlEntity.h" | +// +-----------------------------------------------------------------+ + + +#ifndef VHDL_ENTITY_H +#define VHDL_ENTITY_H + +#include +#include "hurricane/Name.h" +#include "hurricane/Property.h" +#include "hurricane/Slot.h" +namespace Hurricane { + class Net; + class Instance; +} +#include "crlcore/VhdlSignal.h" + + +namespace Vhdl { + + using Hurricane::Tabulation; + using Hurricane::Record; + using Hurricane::Name; + using Hurricane::DBo; + using Hurricane::Net; + using Hurricane::Cell; + using Hurricane::Instance; + using Hurricane::PrivateProperty; + + class Signal; + class ScalarSignal; + class VectorSignal; + class EntityProperty; + + + extern Tabulation tab; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::Entity". + + typedef std::set SignalSet; + + + class Entity { + public: + enum Flag { NoFlags = 0x0000 + , EntityMode = 0x0001 + , ComponentMode = 0x0002 + , AsPortSignal = 0x0004 + , AsInnerSignal = 0x0008 + }; + public: + static bool parseNetName ( const Net*, std::string& stem, size_t& index ); + static std::vector& + getAllEntities (); + public: + Entity ( EntityProperty*, Cell*, unsigned int flags ); + ~Entity (); + inline bool isEntityMode () const; + inline bool isComponentMode () const; + const Cell* getCell () const; + const Signal* getSignal ( std::string name ) const; + const Signal* getGlobal ( std::string name ) const; + const SignalSet* getSignals () const; + void toEntityMode (); + void toSignals ( std::ostream& ) const; + void toPort ( std::ostream& ) const; + void toComponent ( std::ostream& ) const; + void toInstance ( std::ostream&, Instance* ) const; + void toEntity ( std::ostream& ) const; + std::string _getString () const; + Record* _getRecord () const; + private: + static std::vector _entities; + static std::ptrdiff_t _offset; + SignalSet _signals; + SignalSet _globals; + unsigned int _flags; + }; + + + inline bool Entity::isEntityMode () const { return _flags & EntityMode; } + inline bool Entity::isComponentMode () const { return _flags & ComponentMode; } + + +// ------------------------------------------------------------------- +// Class : "Vhdl::EntityProperty". + + class EntityProperty : public Hurricane::PrivateProperty { + friend class EntityExtension; + public: + static Name _name; + public: + static EntityProperty* create ( Cell* owner, unsigned int flags ); + static Name getPropertyName (); + virtual Name getName () const; + inline Entity* getEntity (); + virtual void onReleasedBy ( DBo* owner ); + virtual std::string _getTypeName () const; + virtual std::string _getString () const; + virtual Record* _getRecord () const; + protected: + // Attributes. + Entity _entity; + + protected: + // Constructor. + inline EntityProperty ( Cell* owner, unsigned int flags ); + }; + + + inline EntityProperty::EntityProperty ( Cell* owner, unsigned int flags ) + : PrivateProperty(), _entity(this,owner,flags) + { } + + + inline Entity* EntityProperty::getEntity () { return &_entity; } + + +// ------------------------------------------------------------------- +// Class : "Vhdl::EntityExtension". + + class EntityExtension { + public: + static void destroyAll (); + static inline const SignalSet* getSignals ( const Cell* ); + static inline const Signal* getSignal ( const Cell*, std::string name ); + static inline void toSignals ( const Cell*, std::ostream& ); + static inline void toPort ( const Cell*, std::ostream& ); + static inline void toComponent ( const Cell*, std::ostream& ); + static inline void toInstance ( const Cell*, std::ostream&, Instance* ); + static inline void toEntity ( const Cell*, std::ostream& ); + static Entity* get ( const Cell* ); + static Entity* create ( Cell*, unsigned int flags ); + static void destroy ( Cell* ); + private: + static const Cell* _owner; + static Entity* _cache; + }; + + + inline const SignalSet* EntityExtension::getSignals ( const Cell* cell ) + { + Entity* entity = get( cell ); + return (entity == NULL) ? NULL : entity->getSignals(); + } + + + inline const Signal* EntityExtension::getSignal ( const Cell* cell, std::string name ) + { + Entity* entity = get( cell ); + return (entity == NULL) ? NULL : entity->getSignal(name); + } + + + inline void EntityExtension::toSignals ( const Cell* cell, std::ostream& out ) + { + Entity* entity = get( cell ); + if (entity) entity->toSignals(out); + } + + + inline void EntityExtension::toPort ( const Cell* cell, std::ostream& out ) + { + Entity* entity = get( cell ); + if (entity) entity->toPort(out); + } + + + inline void EntityExtension::toComponent ( const Cell* cell, std::ostream& out ) + { + Entity* entity = get( cell ); + if (entity) entity->toComponent(out); + } + + + inline void EntityExtension::toInstance ( const Cell* cell, std::ostream& out, Instance* instance ) + { + Entity* entity = get( cell ); + if (entity) entity->toInstance(out,instance); + } + + + inline void EntityExtension::toEntity ( const Cell* cell, std::ostream& out ) + { + Entity* entity = get( cell ); + if (entity) entity->toEntity(out); + } + + +} // Vhdl Namespace. + + +INSPECTOR_P_SUPPORT(Vhdl::Entity); + + +#endif // VHDL_ENTITY_H diff --git a/crlcore/src/ccore/crlcore/VhdlPortMap.h b/crlcore/src/ccore/crlcore/VhdlPortMap.h new file mode 100644 index 00000000..a2ae0aba --- /dev/null +++ b/crlcore/src/ccore/crlcore/VhdlPortMap.h @@ -0,0 +1,84 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance VHDL / Hurricane Interface | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/VhdlPortMap.h" | +// +-----------------------------------------------------------------+ + + +#ifndef VHDL_PORTMAP_H +#define VHDL_PORTMAP_H + +#include +#include +#include "hurricane/Net.h" +#include "crlcore/VhdlBit.h" +#include "crlcore/VhdlSignal.h" + + +namespace Vhdl { + + using Hurricane::Net; + using Hurricane::Instance; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::PortMap". + + class PortMap { + public: + static PortMap* create ( const Signal* ); + virtual const Signal* getSignal () const = 0; + virtual void doMapping ( Instance* ) = 0; + virtual void toVhdlPortMap ( std::ostream&, size_t ) const = 0; + PortMap (); + virtual ~PortMap (); + protected: + static const Bit* _lookup ( const Bit* masterBit, Instance* ); + }; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::ScalarPortMap". + + class ScalarPortMap : public PortMap { + public: + ScalarPortMap ( const ScalarSignal* ); + virtual ~ScalarPortMap (); + virtual const ScalarSignal* getSignal () const; + virtual void doMapping ( Instance* ); + virtual void toVhdlPortMap ( std::ostream&, size_t ) const; + private: + const ScalarSignal* _signal; + const Bit* _mapping; + }; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::VectorPortMap". + + class VectorPortMap : public PortMap { + public: + VectorPortMap ( const VectorSignal* ); + virtual ~VectorPortMap (); + virtual const VectorSignal* getSignal () const; + virtual void doMapping ( Instance* ); + virtual void toVhdlPortMap ( std::ostream&, size_t ) const; + private: + const VectorSignal* _signal; + std::map _mapping; + }; + + + +} // Vhdl namespace. + +#endif // VHDL_PORTMAP_H diff --git a/crlcore/src/ccore/crlcore/VhdlSignal.h b/crlcore/src/ccore/crlcore/VhdlSignal.h new file mode 100644 index 00000000..550dfd2c --- /dev/null +++ b/crlcore/src/ccore/crlcore/VhdlSignal.h @@ -0,0 +1,139 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance VHDL / Hurricane Interface | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/VhdlSignal.h" | +// +-----------------------------------------------------------------+ + + +#ifndef VHDL_SIGNAL_H +#define VHDL_SIGNAL_H + +#include +#include "hurricane/Net.h" +#include "crlcore/VhdlBit.h" + + +namespace Vhdl { + + using Hurricane::Net; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::Signal". + + class Signal { + public: + enum Flag { Contiguous = 0x0001 }; + public: + Signal ( std::string name ); + virtual ~Signal (); + virtual bool isScalar () const = 0; + virtual bool isVector () const = 0; + virtual bool isExternal () const = 0; + virtual bool isContiguous () const = 0; + inline std::string getName () const; + virtual const Bit* getBit () const = 0; + virtual const Bit* getBit ( size_t ) const = 0; + virtual const Net* getNet () const = 0; + virtual const Net* getNet ( size_t index ) const = 0; + virtual Net::Direction getDirection () const = 0; + virtual size_t getMin () const = 0; + virtual size_t getMax () const = 0; + virtual void toVhdlPort ( std::ostream&, int width, unsigned int flags ) const = 0; + virtual std::string _getString () const = 0; + virtual Record* _getRecord () const; + protected: + static void _toVhdlPort ( std::ostream& + , int width + , unsigned int flags + , std::string name + , std::string range + , Net::Direction ); + protected: + std::string _name; + }; + + + struct GreaterSignalByName { + inline bool operator() ( const Signal* lhs, const Signal* rhs ) const + { return lhs->getName() < rhs->getName(); } + }; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::ScalarSignal". + + class ScalarSignal : public Signal { + public: + ScalarSignal ( Net* ); + virtual ~ScalarSignal (); + virtual bool isScalar () const; + virtual bool isVector () const; + virtual bool isExternal () const; + virtual bool isContiguous () const; + virtual const Bit* getBit () const; + virtual const Bit* getBit ( size_t ) const; + virtual const Net* getNet () const; + virtual const Net* getNet ( size_t ) const; + virtual size_t getMin () const; + virtual size_t getMax () const; + virtual Net::Direction getDirection () const; + virtual void toVhdlPort ( std::ostream&, int width, unsigned int flags ) const; + virtual std::string _getString () const; + virtual Record* _getRecord () const; + protected: + Bit* _bit; + }; + + +// ------------------------------------------------------------------- +// Class : "Vhdl::VectorSignal". + + class VectorSignal : public Signal { + public: + VectorSignal ( std::string ); + virtual ~VectorSignal (); + virtual bool isScalar () const; + virtual bool isVector () const; + virtual bool isExternal () const; + virtual bool isContiguous () const; + virtual const Bit* getBit () const; + virtual const Bit* getBit ( size_t ) const; + virtual const Net* getNet () const; + virtual const Net* getNet ( size_t ) const; + virtual Net::Direction getDirection () const; + virtual size_t getMin () const; + virtual size_t getMax () const; + bool addNet ( size_t index, Net* ); + virtual void toVhdlPort ( std::ostream&, int width, unsigned int flags ) const; + virtual std::string _getString () const; + virtual Record* _getRecord () const; + protected: + std::set _bits; + Net::Direction _direction; + unsigned int _flags; + }; + + +// ------------------------------------------------------------------- +// Inline methods. + + inline std::string Signal::getName () const { return _name; } + +} + + +INSPECTOR_P_SUPPORT(Vhdl::Signal); +INSPECTOR_P_SUPPORT(Vhdl::ScalarSignal); +INSPECTOR_P_SUPPORT(Vhdl::VectorSignal); + +#endif // VHDL_SIGNAL_H diff --git a/crlcore/src/ccore/toolbox/NamingScheme.cpp b/crlcore/src/ccore/toolbox/NamingScheme.cpp index b08d53c0..75d9aea9 100644 --- a/crlcore/src/ccore/toolbox/NamingScheme.cpp +++ b/crlcore/src/ccore/toolbox/NamingScheme.cpp @@ -32,11 +32,13 @@ namespace CRL { { string vhdlName; - // VHDL reserved keywords (scalar). if (vlogName == Name("in" )) return "in_v"; if (vlogName == Name("out" )) return "out_v"; if (vlogName == Name("inout")) return "inout_v"; + if (vlogName == Name("true" )) return "bool_true"; + if (vlogName == Name("false")) return "bool_false"; + if (vlogName == Name("undef")) return "bool_undef"; size_t parCount = 0; size_t posLeftPar = 0; @@ -66,6 +68,7 @@ namespace CRL { vhdlName += 'n'; if (translated == '\\') translated = '_'; + if (translated == '.' ) translated = '_'; if (translated == '$' ) translated = '_'; if (translated == '?' ) translated = '_'; if (translated == ':' ) translated = '_'; @@ -85,6 +88,9 @@ namespace CRL { if (vhdlName.substr(0,3) == "in(" ) vhdlName.insert(2,"_v"); if (vhdlName.substr(0,4) == "out(" ) vhdlName.insert(3,"_v"); if (vhdlName.substr(0,6) == "inout(") vhdlName.insert(5,"_v"); + if (vhdlName == "true" ) vhdlName.insert(0,"value_"); + if (vhdlName == "false" ) vhdlName.insert(0,"value_"); + if (vhdlName == "undef" ) vhdlName.insert(0,"value_"); return Name(vhdlName); } diff --git a/crlcore/src/pyCRL/PyCRL.cpp b/crlcore/src/pyCRL/PyCRL.cpp index 3d712602..c59c56f3 100644 --- a/crlcore/src/pyCRL/PyCRL.cpp +++ b/crlcore/src/pyCRL/PyCRL.cpp @@ -31,6 +31,7 @@ #include "crlcore/PyAcmSigda.h" #include "crlcore/PyIspd05.h" #include "crlcore/PyBlif.h" +#include "crlcore/VhdlEntity.h" namespace CRL { @@ -39,27 +40,47 @@ namespace CRL { using std::endl; using Hurricane::tab; using Hurricane::in_trace; + using Hurricane::Error; + using Hurricane::Warning; + using Isobar::ProxyProperty; + using Isobar::ProxyError; + using Isobar::ConstructorError; + using Isobar::HurricaneError; + using Isobar::HurricaneWarning; using Isobar::__cs; + using Vhdl::EntityExtension; #if !defined(__PYTHON_MODULE__) -// x=================================================================x +// +=================================================================+ // | "PyCRL" Shared Library Code Part | -// x=================================================================x +// +=================================================================+ # else // End of PyHurricane Shared Library Code Part. -// x=================================================================x +// +=================================================================+ // | "PyCRL" Python Module Code Part | -// x=================================================================x +// +=================================================================+ extern "C" { + static PyObject* PyVhdl_destroyAllVHDL ( PyObject* module ) + { + trace << "PyVhdl_destroyAllVHDL()" << endl; + + HTRY + EntityExtension::destroyAll(); + HCATCH + + Py_RETURN_NONE; + } + + // x-------------------------------------------------------------x // | "PyCRL" Module Methods | // x-------------------------------------------------------------x @@ -68,6 +89,8 @@ extern "C" { static PyMethodDef PyCRL_Methods[] = { { "createPartRing" , (PyCFunction)PyToolBox_createPartRing, METH_VARARGS , "Partial build of a ring" } + , { "destroyAllVHDL" , (PyCFunction)PyVhdl_destroyAllVHDL, METH_NOARGS + , "Clear all VHDL informations on all cells." } , {NULL, NULL, 0, NULL} /* sentinel */ }; diff --git a/cumulus/src/plugins/RSavePlugin.py b/cumulus/src/plugins/RSavePlugin.py index f8d90ee9..8d9afbff 100644 --- a/cumulus/src/plugins/RSavePlugin.py +++ b/cumulus/src/plugins/RSavePlugin.py @@ -88,6 +88,7 @@ def ScriptMain ( **kw ): return 0 rsave( cell ) + CRL.destroyAllVHDL() except ErrorMessage, e: print e; errorCode = e.code diff --git a/cumulus/src/plugins/RSavePluginAll.py b/cumulus/src/plugins/RSavePluginAll.py index b30cb09e..1bb53a78 100644 --- a/cumulus/src/plugins/RSavePluginAll.py +++ b/cumulus/src/plugins/RSavePluginAll.py @@ -94,6 +94,7 @@ def ScriptMain ( **kw ): return 0 rsave( cell ) + CRL.destroyAllVHDL() except ErrorMessage, e: print e; errorCode = e.code diff --git a/hurricane/src/hurricane/Net.cpp b/hurricane/src/hurricane/Net.cpp index afa82bfe..26f385ef 100644 --- a/hurricane/src/hurricane/Net.cpp +++ b/hurricane/src/hurricane/Net.cpp @@ -800,6 +800,13 @@ Net::Direction& Net::Direction::operator=(const Direction& direction) return *this; } +Net::Direction& Net::Direction::operator|=(const Direction& direction) +// ****************************************************************** +{ + _code = (Code)((unsigned int)_code | (unsigned int)direction._code); + return *this; +} + string Net::Direction::_getString() const // ************************************** { diff --git a/hurricane/src/hurricane/NetAlias.cpp b/hurricane/src/hurricane/NetAlias.cpp index 6e3c7453..2868b797 100644 --- a/hurricane/src/hurricane/NetAlias.cpp +++ b/hurricane/src/hurricane/NetAlias.cpp @@ -119,7 +119,7 @@ namespace Hurricane { Record* NetAliasHook::_getRecord () const { Record* record = new Record ( getString(this) ); - record->add ( getSlot("_next", &_next) ); + record->add ( getSlot("_next", _next) ); return record; } @@ -169,7 +169,7 @@ namespace Hurricane { NetAliasName::NetAliasName ( Name name ) : NetAliasHook() - , _name (name) + , _name (name) { } diff --git a/hurricane/src/hurricane/hurricane/Net.h b/hurricane/src/hurricane/hurricane/Net.h index 2b4e9781..53ffa55b 100644 --- a/hurricane/src/hurricane/hurricane/Net.h +++ b/hurricane/src/hurricane/hurricane/Net.h @@ -81,9 +81,9 @@ class Net : public Entity { public: class Direction { // ******************** - public: enum Code { DirUndefined = 0x0000 - , DirIn = 0x0001 + public: enum Code { DirIn = 0x0001 , DirOut = 0x0002 + , DirUndefined = 0x0000 , ConnTristate = 0x0100 , ConnWiredOr = 0x0200 , UNDEFINED = DirUndefined @@ -94,6 +94,7 @@ class Net : public Entity { , TRANSCV = DirIn | DirOut | ConnTristate , WOR_OUT = DirOut | ConnWiredOr , WOR_INOUT = DirIn | DirOut | ConnWiredOr + , DirMask = DirIn | DirOut | DirUndefined }; private: Code _code; @@ -101,7 +102,8 @@ class Net : public Entity { public: Direction(const Code& code = UNDEFINED); public: Direction(const Direction& direction); - public: Direction& operator=(const Direction& direction); + public: Direction& operator =(const Direction& direction); + public: Direction& operator|=(const Direction& direction); public: operator const Code&() const {return _code;}; diff --git a/hurricane/src/hurricane/hurricane/Tabulation.h b/hurricane/src/hurricane/hurricane/Tabulation.h index 6cc28703..f5791afa 100644 --- a/hurricane/src/hurricane/hurricane/Tabulation.h +++ b/hurricane/src/hurricane/hurricane/Tabulation.h @@ -68,6 +68,7 @@ class Tabulation { // Others // ****** + public: unsigned getWidth() const { return _s.size()*_n; }; public: string _getTypeName() const { return _TName("Tabulation"); }; public: string _getString() const; public: Record* _getRecord() const { return NULL; };