#ifndef _IrodPropH_
#define _IrodPropH_
#include "cb_prop.h"
#include "monopins.h"
class CR_MatchClock : public TProperty {
private:
char* ClassName;
public:
int LongLengthMatchTolerance;
int ShortMaxLength;
char* GetClassName() { return ClassName; }
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 );
}
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:
ofstream Fromtos;
ofstream TightRules;
ofstream LooseRules;
TRootModule* Root;
TNetList* NL;
unsigned PropCount;
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 );
}
void MatchClock() {
int ClockCount = 0;
int MpCount = 0;
const char* ClassBase = "CLK_CNET_CLASS_";
const char* LongBase = "CLK_LONG_GROUP_";
const char* ShortBase = "CLK_SHRT_GROUP_";
vector<CR_MatchClock*> MCV_CC;
vector<CR_MatchClock*> MCV_VC;
for ( unsigned prop = 0; prop < PropCount; ++ prop ) {
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 );
Fromtos << "\n";
Fromtos << "\ndefine (class " << ClassBase << ClockCount << ")";
Fromtos << "\ndefine (group " << LongBase << ClockCount << ")";
for ( unsigned pr = 0; pr < MC->GetPortRangeCount(); ++ pr ) {
Fromtos << "\n";
TPortRange PortRange = MC->GetPortRange( pr );
for ( int i = PortRange.GetMinRange(); i <= PortRange.GetMaxRange(); ++ i ) {
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;
if ( strncmp( "MEAS_", N->GetString(), 5 ) == 0 ) continue;
if ( strncmp( "MPYI_", N->GetString(), 4 ) == 0 ) continue;
int PS_Count = N->GetPinSpecCount();
int PinCount = N->GetPartPinSpecCount();
if ( PinCount < 2 ) continue;
TPinSpec* MonoPSP = 0;
for ( int p = 0; p < PS_Count; ++p ) {
TPinSpec* PSP = N->GetPinSpec( p );
if ( typeid( *PSP->GetPort()->GetOwner() ) == typeid ( CP_MONOPIN25 ) ) {
MonoPSP = PSP;
}
}
if ( PinCount == 2 ) {
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 ) {
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;
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 ) {
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 );
MpCount++;
}
}
++ ClockCount;
}
}
if ( ClockCount == 0 ) return;
for ( int i = 0; i < ClockCount; ++ i ) {
TightRules << "\nrule class " << ClassBase << i << " (length_amplitude 100 200)";
TightRules << "\nrule class " << ClassBase << i << " (length_gap 50)";
}
TightRules << "\n";
for ( int i = 0; i < ClockCount; ++ i ) {
CR_MatchClock* MC = MCV_CC[ i ];
int Tol = MC->LongLengthMatchTolerance;
if ( Tol > 0 ) {
TightRules << "\ncircuit group " << LongBase << i << " (match_fromto_length on (tolerance " << Tol << "))";
}
}
for ( int i = 0; i < MpCount; ++ i ) {
CR_MatchClock* MC = MCV_VC[ i ];
TightRules << "\ncircuit group " << ShortBase << i << " (length 100)";
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 ){
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;
MatchClock();
Fromtos.close();
TightRules.close();
LooseRules.close();
}
};
#endif