Coolquest, Inc. | Home | Products | Support | About | Contact | |||
|
Design Home | << File View >> | Class View | Output (partial) | Parts Library | Examples Home |
// THIS FILE IS IN THE PUBLIC DOMAIN. // IT IS PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT // NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #ifndef _IrodPropH_ #define _IrodPropH_ #include "cb_prop.h" #include "monopins.h" // CP_MONOPIN25 is identified via RTTI class CR_MatchClock : public TProperty { private: char* ClassName; // instances having the same class name act logically as one property public: // custom members int LongLengthMatchTolerance; // tolerance in mils, set to <= 0 to turn off long length matching int ShortMaxLength; // max length in mils of short stubs (this is the relaxed rule after routing is complete) char* GetClassName() { return ClassName; } // standard members CR_MatchClock( char* aClassName = 0 ) { ClassName = aClassName; LongLengthMatchTolerance = 2000; ShortMaxLength = 2000; } virtual void Associate( TPortRange& aPortRange ) { TPart* Part = dynamic_cast<TPart*>( aPortRange.GetPort()->GetOwner() ); if ( Part == 0 ) BEGERR << "P_MatchClock may only be associated with a part's port or range thereof" << ENDERR; associate( aPortRange ); } // these Associate()'s are optional, but declaring them avoids compiler warning about hiding virtual function virtual void Associate( TModPar& aModPar ) { illegal( aModPar ); } virtual void Associate( TBundle& aBundle ) { illegal( aBundle ); } virtual void Associate( char* aName, TModule* aModule ) { illegal( aName, aModule ); } }; class TGenLayoutScript { private: // convenience variables ofstream Fromtos; // destination file for fromto definitions ofstream TightRules; // Tight = tight tolerance which is typically not achievable ofstream LooseRules; // Loose = relaxed tolerance for final conflict reporting TRootModule* Root; // root of design TNetList* NL; // netlist for design unsigned PropCount; // count of properties in the global property list void OutPS( ostream& Dest, TPinSpec PS ) { TPort* Port = PS.GetPort(); int Index = PS.GetIndex(); TPart* OP = dynamic_cast<TPart*>( Port->GetOwner() ); if ( !OP ) BEGERR << "TGenLayoutScript encountered non-part port owner " << OP << ENDERR; if ( Port->MultiPinNode() ) BEGERR << "TGenLayoutScript encountered multi-pin node " << PS << ENDERR; Dest << OP->GetReferenceDesignator(); Dest << '-' << Port->GetPin( Index ); } // one function for each part of the script void MatchClock() { int ClockCount = 0; // counter used to create unique names (class, long group, and short group) int MpCount = 0; // MonoPins, one per driver const char* ClassBase = "CLK_CNET_CLASS_"; // base of unique names const char* LongBase = "CLK_LONG_GROUP_"; const char* ShortBase = "CLK_SHRT_GROUP_"; // list of MatchClock properties vector<CR_MatchClock*> MCV_CC; // as associated with clocks (ClockCount) vector<CR_MatchClock*> MCV_VC; // as associated with MonoPins (MpCount) // spp_clocks.do calls the four do files created by this funtion // spp_clocks.do sets units to mils for ( unsigned prop = 0; prop < PropCount; ++ prop ) { // for each property in global list TProperty* P = Root->Properties.GetProperty( prop ); CR_MatchClock* MC = dynamic_cast<CR_MatchClock*>( P ); if ( MC ) { if ( MC->GetClassName() != 0 ) BEGERR << "ClassName feature not yet implemented for CR_MatchClock" << ENDERR; MCV_CC.push_back( MC ); // save for use below Fromtos << "\n"; Fromtos << "\ndefine (class " << ClassBase << ClockCount << ")"; // add nets to class later Fromtos << "\ndefine (group " << LongBase << ClockCount << ")"; // add fromto's to group later for ( unsigned pr = 0; pr < MC->GetPortRangeCount(); ++ pr ) { // for each port range associated with the property Fromtos << "\n"; TPortRange PortRange = MC->GetPortRange( pr ); for ( int i = PortRange.GetMinRange(); i <= PortRange.GetMaxRange(); ++ i ) { // for each pin in port range TPinSpec SourcePS = TPinSpec( PortRange.GetPort(), i ); TNet* N = NL->PinInNetList( SourcePS ); if ( N == 0 ) BEGERR << "TGenLayoutScript could not find pin " << SourcePS << " in netlist" << ENDERR; if ( N->DesignatorEquals( NoConnect ) ) continue; // >>> ignore pins on no-connect net if ( strncmp( "MEAS_", N->GetString(), 5 ) == 0 ) continue; // >>> ignore pins on nets starting with "MEAS_" if ( strncmp( "MPYI_", N->GetString(), 4 ) == 0 ) continue; // >>> ignore pins on nets starting with "MPYI_" int PS_Count = N->GetPinSpecCount(); int PinCount = N->GetPartPinSpecCount(); if ( PinCount < 2 ) continue; // >>> ignore single-node nets TPinSpec* MonoPSP = 0; // PinSpec for monopin, if any for ( int p = 0; p < PS_Count; ++p ) { // find PinSpec for monopin, if any TPinSpec* PSP = N->GetPinSpec( p ); if ( typeid( *PSP->GetPort()->GetOwner() ) == typeid ( CP_MONOPIN25 ) ) { // >>> alternative: identify monopin by counting its pins MonoPSP = PSP; } } if ( PinCount == 2 ) { // >>> two-node nets get no far-end cluster if ( MonoPSP != 0 ) BEGERR << "TGenLayoutScript::MatchClock(): two-node net " << N << "must contain no MonoPin" << ENDERR; Fromtos << "\ndefine (class " << ClassBase << ClockCount << "(add_net " << N << "))"; Fromtos << "\ndefine (group " << LongBase << ClockCount << "(add_fromto (fromto "; OutPS( Fromtos, SourcePS ); Fromtos << " "; for ( int p = 0; p < PS_Count; ++ p ) { // for each PinSpec TPinSpec LoadPS = *N->GetPinSpec( p ); if ( !LoadPS.OwnerIsPart() ) continue; if ( LoadPS == SourcePS ) continue; OutPS( Fromtos, LoadPS ); } Fromtos << ")))"; Fromtos << "\n#***** warning: Net " << N << " has fewer than two load pins.\n"; continue; } if ( MonoPSP == 0 ) BEGERR << "TGenLayoutScript::MatchClock() found no MonoPin connected to net " << N << ENDERR; TPinSpec MonoPS = *MonoPSP; if ( MonoPS == SourcePS ) BEGERR << "TGenLayoutScript::MatchClock(): CR_MatchClock must be associated with the source pin of net " << N << ", not the MonoPin" << ENDERR; // nets with >= two nodes: Fromtos << "\ndefine (class " << ClassBase << ClockCount << "(add_net " << N << "))"; Fromtos << "\ndefine (group " << LongBase << ClockCount << "(add_fromto (fromto "; OutPS( Fromtos, SourcePS ); Fromtos << " "; OutPS( Fromtos, MonoPS ); Fromtos << ")))"; Fromtos << "\ndefine (group " << ShortBase << MpCount; Fromtos << " (add_fromto"; for ( int p = 0; p < PS_Count; ++ p ) { // for each PinSpec in the net TPinSpec LoadPS = *N->GetPinSpec( p ); if ( !LoadPS.OwnerIsPart() ) continue; if ( LoadPS == SourcePS ) continue; if ( LoadPS == MonoPS ) continue; Fromtos << "\n(fromto "; OutPS( Fromtos, MonoPS ); Fromtos << " "; OutPS( Fromtos, LoadPS ); Fromtos << ")"; } Fromtos << "\n))"; MCV_VC.push_back( MC ); // save for use below MpCount++; } } ++ ClockCount; } } if ( ClockCount == 0 ) return; // assign rules to classes for ( int i = 0; i < ClockCount; ++ i ) { // TightRules << "\ncircuit class " << ClassBase << i << " (use_layer SURFACE SIG_SURF SIG_SURF2)"; // now handled in spp_clocks.do // layers on which to route clocks TightRules << "\nrule class " << ClassBase << i << " (length_amplitude 100 200)"; // amplitude and gap of wiggles used to lengthen traces TightRules << "\nrule class " << ClassBase << i << " (length_gap 50)"; } // assign rules to groups TightRules << "\n"; for ( int i = 0; i < ClockCount; ++ i ) { CR_MatchClock* MC = MCV_CC[ i ]; int Tol = MC->LongLengthMatchTolerance; // user can override default tolerance on long length matching tolerance if ( Tol > 0 ) { TightRules << "\ncircuit group " << LongBase << i << " (match_fromto_length on (tolerance " << Tol << "))"; // match length of long traces } } for ( int i = 0; i < MpCount; ++ i ) { CR_MatchClock* MC = MCV_VC[ i ]; // setting length impossibly short causes autorouter to minimize length of stubs TightRules << "\ncircuit group " << ShortBase << i << " (length 100)"; // minimize length of short traces LooseRules << "\ncircuit group " << ShortBase << i << " (length " << MC->ShortMaxLength << ")"; } for ( int i = 0; i < MpCount; ++ i ) { CR_MatchClock* MC = MCV_VC[ i ]; TightRules << "\ncircuit group " << ShortBase << i << " (match_fromto_length on (ratio_tolerance 0.10))"; LooseRules << "\ncircuit group " << ShortBase << i << " (match_fromto_length on (ratio_tolerance 0.20))"; } Fromtos << "\n"; TightRules << "\n"; LooseRules << "\n"; }; public: TGenLayoutScript() { } void GenerateScriptFile( TRootModule* aRoot ){ // initialize member variables Root = aRoot; NL = &Root->NetList; PropCount = Root->Properties.GetPropertyCount(); char* FromtosPath = OUTPUT_BASE "_clk_fromtos.do"; char* TightRulesPath = OUTPUT_BASE "_clk_tight_rules.do"; char* LooseRulesPath = OUTPUT_BASE "_clk_loose_rules.do"; Fromtos.open( FromtosPath, ios_base::out); if ( !Fromtos.good() ) BEGERR << "TGenLayoutScript could not open script file " << FromtosPath << ENDERR; TightRules.open( TightRulesPath, ios_base::out); if ( !TightRules.good() ) BEGERR << "TGenLayoutScript could not open script file " << TightRulesPath << ENDERR; LooseRules.open( LooseRulesPath, ios_base::out); if ( !LooseRules.good() ) BEGERR << "TGenLayoutScript could not open script file " << LooseRulesPath << ENDERR; // call functions that output to script file MatchClock(); Fromtos.close(); TightRules.close(); LooseRules.close(); } }; #endif
Design Home | << File View >> | Class View | Output (partial) | Parts Library | Examples Home |
Legal | Copyright © 2007 by Coolquest, Inc. | Contact |