Implement time-domain length tuning

- Adds time and delay units
- Adds time domain tuning parameters entry and storage
- Adds pad-to-die delay property
- Adds time domain parameter interface for length / delay calculations
- Adds unit tracking for numerical constants through LIBEVAL
   - Will need future work to truly propagate through binary expressions
- Adds time domain tuning to meander placers
- Adds time delay display to net inspector panel
- Modifies DRC to handle time domain constraints
This commit is contained in:
JamesJCode 2025-02-10 20:57:51 +00:00
parent 0820e90c73
commit eb17ebee4e
113 changed files with 13444 additions and 1101 deletions

View File

@ -49,6 +49,9 @@ message NetClassBoardSettings
optional kiapi.board.types.PadStack microvia_stack = 7;
optional kiapi.common.types.Color color = 8;
// Since: 10.0.0
optional string tuning_profile = 9;
}
message NetClassSchematicSettings

View File

@ -118,6 +118,7 @@ set( KICOMMON_SRCS
project/project_archiver.cpp
project/project_file.cpp
project/project_local_settings.cpp
project/time_domain_parameters.cpp
# This is basically a settings object, but for the toolbar
tool/ui/toolbar_configuration.cpp
@ -864,7 +865,9 @@ set( PCB_COMMON_SRCS
${CMAKE_SOURCE_DIR}/pcbnew/tools/pcb_editor_conditions.cpp
${CMAKE_SOURCE_DIR}/pcbnew/tools/pcb_viewer_tools.cpp
${CMAKE_SOURCE_DIR}/pcbnew/length_calculation.cpp
${CMAKE_SOURCE_DIR}/pcbnew/length_delay_calculation/length_delay_calculation.cpp
${CMAKE_SOURCE_DIR}/pcbnew/length_delay_calculation/length_delay_calculation_item.cpp
${CMAKE_SOURCE_DIR}/pcbnew/length_delay_calculation/time_domain_parameters_user_defined.cpp
widgets/net_selector.cpp
)

View File

@ -61,6 +61,7 @@ enum
GRID_uVIADRILL,
GRID_DIFF_PAIR_WIDTH,
GRID_DIFF_PAIR_GAP,
GRID_TUNING_PROFILE,
GRID_PCB_COLOR,
GRID_FIRST_EESCHEMA,
@ -297,6 +298,7 @@ void PANEL_SETUP_NETCLASSES::loadNetclasses()
[&]( int aRow, const NETCLASS* nc )
{
m_netclassGrid->SetCellValue( aRow, GRID_NAME, nc->GetName() );
m_netclassGrid->SetCellValue( aRow, GRID_TUNING_PROFILE, nc->GetTuningProfile() );
m_netclassGrid->SetOptionalUnitValue( aRow, GRID_WIREWIDTH,
nc->GetWireWidthOpt() );
@ -502,6 +504,7 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow()
nc->SetPriority( aRow );
nc->SetName( m_netclassGrid->GetCellValue( aRow, GRID_NAME ) );
nc->SetTuningProfile( m_netclassGrid->GetCellValue( aRow, GRID_TUNING_PROFILE ) );
nc->SetWireWidth( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_WIREWIDTH ) );
nc->SetBusWidth( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_BUSWIDTH ) );
@ -1100,3 +1103,19 @@ void PANEL_SETUP_NETCLASSES::OnMoveNetclassDownClick( wxCommandEvent& event )
m_netclassesDirty = true;
}
void PANEL_SETUP_NETCLASSES::UpdateTuningProfileNames( const std::vector<wxString>& aNames ) const
{
wxArrayString profileNames;
profileNames.push_back( wxEmptyString );
std::ranges::for_each( aNames,
[&]( const wxString& aName )
{
profileNames.push_back( aName );
} );
wxGridCellAttr* attr = new wxGridCellAttr;
attr->SetEditor( new wxGridCellChoiceEditor( profileNames, false ) );
m_netclassGrid->SetColAttr( GRID_TUNING_PROFILE, attr );
}

View File

@ -39,7 +39,7 @@ PANEL_SETUP_NETCLASSES_BASE::PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWi
m_netclassGrid = new WX_GRID( m_netclassesPane, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL );
// Grid
m_netclassGrid->CreateGrid( 3, 14 );
m_netclassGrid->CreateGrid( 3, 15 );
m_netclassGrid->EnableEditing( true );
m_netclassGrid->EnableGridLines( true );
m_netclassGrid->EnableDragGridSize( false );
@ -57,11 +57,12 @@ PANEL_SETUP_NETCLASSES_BASE::PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWi
m_netclassGrid->SetColLabelValue( 6, _("uVia Hole") );
m_netclassGrid->SetColLabelValue( 7, _("DP Width") );
m_netclassGrid->SetColLabelValue( 8, _("DP Gap") );
m_netclassGrid->SetColLabelValue( 9, _("PCB Color") );
m_netclassGrid->SetColLabelValue( 10, _("Wire Thickness") );
m_netclassGrid->SetColLabelValue( 11, _("Bus Thickness") );
m_netclassGrid->SetColLabelValue( 12, _("Color") );
m_netclassGrid->SetColLabelValue( 13, _("Line Style") );
m_netclassGrid->SetColLabelValue( 9, _("Delay Profile") );
m_netclassGrid->SetColLabelValue( 10, _("PCB Color") );
m_netclassGrid->SetColLabelValue( 11, _("Wire Thickness") );
m_netclassGrid->SetColLabelValue( 12, _("Bus Thickness") );
m_netclassGrid->SetColLabelValue( 13, _("Color") );
m_netclassGrid->SetColLabelValue( 14, _("Line Style") );
m_netclassGrid->SetColLabelSize( wxGRID_AUTOSIZE );
m_netclassGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );

View File

@ -290,9 +290,9 @@
<property name="close_button">1</property>
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
<property name="col_label_size">wxGRID_AUTOSIZE</property>
<property name="col_label_values">&quot;Name&quot; &quot;Clearance&quot; &quot;Track Width&quot; &quot;Via Size&quot; &quot;Via Hole&quot; &quot;uVia Size&quot; &quot;uVia Hole&quot; &quot;DP Width&quot; &quot;DP Gap&quot; &quot;PCB Color&quot; &quot;Wire Thickness&quot; &quot;Bus Thickness&quot; &quot;Color&quot; &quot;Line Style&quot;</property>
<property name="col_label_values">&quot;Name&quot; &quot;Clearance&quot; &quot;Track Width&quot; &quot;Via Size&quot; &quot;Via Hole&quot; &quot;uVia Size&quot; &quot;uVia Hole&quot; &quot;DP Width&quot; &quot;DP Gap&quot; &quot;Delay Profile&quot; &quot;PCB Color&quot; &quot;Wire Thickness&quot; &quot;Bus Thickness&quot; &quot;Color&quot; &quot;Line Style&quot;</property>
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
<property name="cols">14</property>
<property name="cols">15</property>
<property name="column_sizes"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>

View File

@ -117,6 +117,23 @@ bool EDA_UNIT_UTILS::FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS
aUnits = EDA_UNITS::INCH;
else if( unit == wxT( "de" ) || unit == wxT( "ra" ) ) // "deg" or "rad"
aUnits = EDA_UNITS::DEGREES;
else if( unit == wxT("fs" ) )
aUnits = EDA_UNITS::FS;
else if( unit == wxT( "ps" ) )
{
wxString timeUnit( buf.Mid( brk_point ).Strip( wxString::leading ).Left( 5 ).Lower() );
if( timeUnit == wxT( "ps" ) )
aUnits = EDA_UNITS::PS;
else if( timeUnit == wxT( "ps/in" ) )
aUnits = EDA_UNITS::PS_PER_INCH;
else if( timeUnit == wxT( "ps/cm" ) )
aUnits = EDA_UNITS::PS_PER_CM;
else if( timeUnit == wxT( "ps/mm" ) )
aUnits = EDA_UNITS::PS_PER_MM;
else
return false;
}
else
return false;
@ -130,15 +147,20 @@ wxString EDA_UNIT_UTILS::GetText( EDA_UNITS aUnits, EDA_DATA_TYPE aType )
switch( aUnits )
{
case EDA_UNITS::UM: label = wxT( " \u00B5m" ); break; //00B5 for µ
case EDA_UNITS::MM: label = wxT( " mm" ); break;
case EDA_UNITS::CM: label = wxT( " cm" ); break;
case EDA_UNITS::DEGREES: label = wxT( "°" ); break;
case EDA_UNITS::MILS: label = wxT( " mils" ); break;
case EDA_UNITS::INCH: label = wxT( " in" ); break;
case EDA_UNITS::PERCENT: label = wxT( "%" ); break;
case EDA_UNITS::UNSCALED: break;
default: UNIMPLEMENTED_FOR( wxS( "Unknown units" ) ); break;
case EDA_UNITS::UM: label = wxT( " \u00B5m" ); break; //00B5 for µ
case EDA_UNITS::MM: label = wxT( " mm" ); break;
case EDA_UNITS::CM: label = wxT( " cm" ); break;
case EDA_UNITS::DEGREES: label = wxT( "°" ); break;
case EDA_UNITS::MILS: label = wxT( " mils" ); break;
case EDA_UNITS::INCH: label = wxT( " in" ); break;
case EDA_UNITS::PERCENT: label = wxT( "%" ); break;
case EDA_UNITS::FS: label = wxT( " fs" ); break;
case EDA_UNITS::PS: label = wxT( " ps" ); break;
case EDA_UNITS::PS_PER_INCH: label = wxT( " ps/in" ); break;
case EDA_UNITS::PS_PER_CM: label = wxT( " ps/cm"); break;
case EDA_UNITS::PS_PER_MM: label = wxT( " ps/mm"); break;
case EDA_UNITS::UNSCALED: break;
default: UNIMPLEMENTED_FOR( wxS( "Unknown units" ) ); break;
}
switch( aType )
@ -146,6 +168,8 @@ wxString EDA_UNIT_UTILS::GetText( EDA_UNITS aUnits, EDA_DATA_TYPE aType )
case EDA_DATA_TYPE::VOLUME: label += wxT( "³" ); break;
case EDA_DATA_TYPE::AREA: label += wxT( "²" ); break;
case EDA_DATA_TYPE::DISTANCE: break;
case EDA_DATA_TYPE::TIME: break;
case EDA_DATA_TYPE::LENGTH_DELAY: break;
default: UNIMPLEMENTED_FOR( wxS( "Unknown measurement" ) ); break;
}
@ -253,9 +277,13 @@ bool EDA_UNIT_UTILS::ParseInternalUnits( const std::string& aInput, const EDA_IU
#define IU_TO_MM( x, scale ) ( x / scale.IU_PER_MM )
#define IU_TO_IN( x, scale ) ( x / scale.IU_PER_MILS / 1000 )
#define IU_TO_MILS( x, scale ) ( x / scale.IU_PER_MILS )
#define IU_TO_PS( x, scale ) ( x / scale.IU_PER_PS )
#define IU_TO_PS_PER_MM( x, scale ) ( x / scale.IU_PER_PS_PER_MM )
#define MM_TO_IU( x, scale ) ( x * scale.IU_PER_MM )
#define IN_TO_IU( x, scale ) ( x * scale.IU_PER_MILS * 1000 )
#define MILS_TO_IU( x, scale ) ( x * scale.IU_PER_MILS )
#define PS_TO_IU( x, scale ) ( x * scale.IU_PER_PS )
#define PS_PER_MM_TO_IU( x, scale ) ( x * scale.IU_PER_PS_PER_MM )
double EDA_UNIT_UTILS::UI::ToUserUnit( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnit,
@ -263,13 +291,18 @@ double EDA_UNIT_UTILS::UI::ToUserUnit( const EDA_IU_SCALE& aIuScale, EDA_UNITS a
{
switch( aUnit )
{
case EDA_UNITS::UM: return IU_TO_MM( aValue, aIuScale ) * 1000;
case EDA_UNITS::MM: return IU_TO_MM( aValue, aIuScale );
case EDA_UNITS::CM: return IU_TO_MM( aValue, aIuScale ) / 10;
case EDA_UNITS::MILS: return IU_TO_MILS( aValue, aIuScale );
case EDA_UNITS::INCH: return IU_TO_IN( aValue, aIuScale );
case EDA_UNITS::DEGREES: return aValue;
default: return aValue;
case EDA_UNITS::UM: return IU_TO_MM( aValue, aIuScale ) * 1000;
case EDA_UNITS::MM: return IU_TO_MM( aValue, aIuScale );
case EDA_UNITS::CM: return IU_TO_MM( aValue, aIuScale ) / 10;
case EDA_UNITS::MILS: return IU_TO_MILS( aValue, aIuScale );
case EDA_UNITS::INCH: return IU_TO_IN( aValue, aIuScale );
case EDA_UNITS::DEGREES: return aValue;
case EDA_UNITS::FS: return IU_TO_PS( aValue, aIuScale ) * 1000.0;
case EDA_UNITS::PS: return IU_TO_PS( aValue, aIuScale );
case EDA_UNITS::PS_PER_INCH: return IU_TO_PS_PER_MM( aValue, aIuScale ) * 25.4;
case EDA_UNITS::PS_PER_CM: return IU_TO_PS_PER_MM( aValue, aIuScale ) * 10;
case EDA_UNITS::PS_PER_MM: return IU_TO_PS_PER_MM( aValue, aIuScale );
default: return aValue;
}
}
@ -297,6 +330,14 @@ wxString EDA_UNIT_UTILS::UI::StringFromValue( const EDA_IU_SCALE& aIuScale, EDA_
case EDA_DATA_TYPE::UNITLESS:
break;
case EDA_DATA_TYPE::TIME:
value_to_print = ToUserUnit( aIuScale, aUnits, value_to_print );
break;
case EDA_DATA_TYPE::LENGTH_DELAY:
value_to_print = ToUserUnit( aIuScale, aUnits, value_to_print );
break;
}
const wxChar* format = nullptr;
@ -304,10 +345,13 @@ wxString EDA_UNIT_UTILS::UI::StringFromValue( const EDA_IU_SCALE& aIuScale, EDA_
switch( aUnits )
{
case EDA_UNITS::MILS: format = is_eeschema ? wxT( "%.3f" ) : wxT( "%.5f" ); break;
case EDA_UNITS::INCH: format = is_eeschema ? wxT( "%.6f" ) : wxT( "%.8f" ); break;
case EDA_UNITS::DEGREES: format = wxT( "%.4f" ); break;
default: format = wxT( "%.10f" ); break;
case EDA_UNITS::MILS: format = is_eeschema ? wxT( "%.3f" ) : wxT( "%.5f" ); break;
case EDA_UNITS::INCH: format = is_eeschema ? wxT( "%.6f" ) : wxT( "%.8f" ); break;
case EDA_UNITS::DEGREES: format = wxT( "%.4f" ); break;
case EDA_UNITS::PS_PER_INCH: format = wxT( "%.4f" ); break;
case EDA_UNITS::PS_PER_CM: format = wxT( "%.3f" ); break;
case EDA_UNITS::PS_PER_MM: format = wxT( "%.3f" ); break;
default: format = wxT( "%.10f" ); break;
}
wxString text;
@ -385,18 +429,31 @@ wxString EDA_UNIT_UTILS::UI::MessageTextFromValue( const EDA_IU_SCALE& aIuScale,
case EDA_DATA_TYPE::UNITLESS:
break;
case EDA_DATA_TYPE::TIME:
value = ToUserUnit( aIuScale, aUnits, value );
break;
case EDA_DATA_TYPE::LENGTH_DELAY:
value = ToUserUnit( aIuScale, aUnits, value );
break;
}
switch( aUnits )
{
default:
case EDA_UNITS::UM: format = is_eeschema ? wxT( "%.0f" ) : wxT( "%.1f" ); break;
case EDA_UNITS::MM: format = is_eeschema ? wxT( "%.2f" ) : wxT( "%.4f" ); break;
case EDA_UNITS::CM: format = is_eeschema ? wxT( "%.3f" ) : wxT( "%.5f" ); break;
case EDA_UNITS::MILS: format = is_eeschema ? wxT( "%.0f" ) : wxT( "%.2f" ); break;
case EDA_UNITS::INCH: format = is_eeschema ? wxT( "%.3f" ) : wxT( "%.4f" ); break;
case EDA_UNITS::DEGREES: format = wxT( "%.3f" ); break;
case EDA_UNITS::UNSCALED: format = wxT( "%.0f" ); break;
case EDA_UNITS::UM: format = is_eeschema ? wxT( "%.0f" ) : wxT( "%.1f" ); break;
case EDA_UNITS::MM: format = is_eeschema ? wxT( "%.2f" ) : wxT( "%.4f" ); break;
case EDA_UNITS::CM: format = is_eeschema ? wxT( "%.3f" ) : wxT( "%.5f" ); break;
case EDA_UNITS::MILS: format = is_eeschema ? wxT( "%.0f" ) : wxT( "%.2f" ); break;
case EDA_UNITS::INCH: format = is_eeschema ? wxT( "%.3f" ) : wxT( "%.4f" ); break;
case EDA_UNITS::DEGREES: format = wxT( "%.3f" ); break;
case EDA_UNITS::UNSCALED: format = wxT( "%.0f" ); break;
case EDA_UNITS::FS: format = wxT( "%.4f" ); break;
case EDA_UNITS::PS: format = wxT( "%.2f" ); break;
case EDA_UNITS::PS_PER_INCH: format = wxT( "%.2f" ); break;
case EDA_UNITS::PS_PER_CM: format = wxT( "%.2f" ); break;
case EDA_UNITS::PS_PER_MM: format = wxT( "%.2f" ); break;
}
text.Printf( format, value );
@ -444,15 +501,20 @@ double EDA_UNIT_UTILS::UI::FromUserUnit( const EDA_IU_SCALE& aIuScale, EDA_UNITS
{
switch( aUnits )
{
case EDA_UNITS::UM: return MM_TO_IU( aValue / 1000.0, aIuScale );
case EDA_UNITS::MM: return MM_TO_IU( aValue, aIuScale );
case EDA_UNITS::CM: return MM_TO_IU( aValue * 10, aIuScale );
case EDA_UNITS::MILS: return MILS_TO_IU( aValue, aIuScale );
case EDA_UNITS::INCH: return IN_TO_IU( aValue, aIuScale );
case EDA_UNITS::UM: return MM_TO_IU( aValue / 1000.0, aIuScale );
case EDA_UNITS::MM: return MM_TO_IU( aValue, aIuScale );
case EDA_UNITS::CM: return MM_TO_IU( aValue * 10, aIuScale );
case EDA_UNITS::MILS: return MILS_TO_IU( aValue, aIuScale );
case EDA_UNITS::INCH: return IN_TO_IU( aValue, aIuScale );
case EDA_UNITS::FS: return PS_TO_IU( aValue / 1000.0, aIuScale );
case EDA_UNITS::PS: return PS_TO_IU( aValue, aIuScale );
case EDA_UNITS::PS_PER_INCH: return PS_PER_MM_TO_IU( aValue / 25.4, aIuScale );
case EDA_UNITS::PS_PER_CM: return PS_PER_MM_TO_IU( aValue / 10, aIuScale );
case EDA_UNITS::PS_PER_MM: return PS_PER_MM_TO_IU( aValue, aIuScale );
default:
case EDA_UNITS::DEGREES:
case EDA_UNITS::UNSCALED:
case EDA_UNITS::PERCENT: return aValue;
case EDA_UNITS::PERCENT: return aValue;
}
}
@ -566,6 +628,23 @@ double EDA_UNIT_UTILS::UI::DoubleValueFromString( const EDA_IU_SCALE& aIuScale,
if( unit == wxT( "ra" ) ) // Radians
dtmp *= 180.0f / M_PI;
}
else if( aUnits == EDA_UNITS::FS || aUnits == EDA_UNITS::PS || aUnits == EDA_UNITS::PS_PER_INCH
|| aUnits == EDA_UNITS::PS_PER_CM || aUnits == EDA_UNITS::PS_PER_MM )
{
wxString timeUnit( buf.Mid( brk_point ).Strip( wxString::leading ).Left( 5 ).Lower() );
if( timeUnit == wxT( "fs" ) )
aUnits = EDA_UNITS::FS;
if( timeUnit == wxT( "ps" ) )
aUnits = EDA_UNITS::PS;
else if( timeUnit == wxT( "ps/in" ) )
aUnits = EDA_UNITS::PS_PER_INCH;
else if( timeUnit == wxT( "ps/cm" ) )
aUnits = EDA_UNITS::PS_PER_CM;
else if( timeUnit == wxT( "ps/mm" ) )
aUnits = EDA_UNITS::PS_PER_MM;
}
switch( aType )
{
@ -583,6 +662,14 @@ double EDA_UNIT_UTILS::UI::DoubleValueFromString( const EDA_IU_SCALE& aIuScale,
case EDA_DATA_TYPE::UNITLESS:
break;
case EDA_DATA_TYPE::TIME:
dtmp = FromUserUnit( aIuScale, aUnits, dtmp );
break;
case EDA_DATA_TYPE::LENGTH_DELAY:
dtmp = FromUserUnit( aIuScale, aUnits, dtmp );
break;
}
return dtmp;

View File

@ -82,12 +82,17 @@ void NUMERIC_EVALUATOR::SetDefaultUnits( EDA_UNITS aUnits )
{
switch( aUnits )
{
case EDA_UNITS::MM: m_defaultUnits = Unit::MM; break;
case EDA_UNITS::MILS: m_defaultUnits = Unit::Mil; break;
case EDA_UNITS::INCH: m_defaultUnits = Unit::Inch; break;
case EDA_UNITS::DEGREES: m_defaultUnits = Unit::Degrees; break;
case EDA_UNITS::UNSCALED: m_defaultUnits = Unit::SI; break;
default: m_defaultUnits = Unit::MM; break;
case EDA_UNITS::MM: m_defaultUnits = Unit::MM; break;
case EDA_UNITS::MILS: m_defaultUnits = Unit::Mil; break;
case EDA_UNITS::INCH: m_defaultUnits = Unit::Inch; break;
case EDA_UNITS::DEGREES: m_defaultUnits = Unit::Degrees; break;
case EDA_UNITS::FS: m_defaultUnits = Unit::Femtoseconds; break;
case EDA_UNITS::PS: m_defaultUnits = Unit::Picoseconds; break;
case EDA_UNITS::PS_PER_INCH: m_defaultUnits = Unit::PsPerInch; break;
case EDA_UNITS::PS_PER_CM: m_defaultUnits = Unit::PsPerCm; break;
case EDA_UNITS::PS_PER_MM: m_defaultUnits = Unit::PsPerMm; break;
case EDA_UNITS::UNSCALED: m_defaultUnits = Unit::SI; break;
default: m_defaultUnits = Unit::MM; break;
}
}
@ -282,7 +287,7 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
};
// Lamda: Get unit for current token.
// Valid units are ", in, um, cm, mm, mil and thou. Returns Unit::Invalid otherwise.
// Valid units are ", in, um, cm, mm, mil, ps and thou. Returns Unit::Invalid otherwise.
auto checkUnit =
[&]( double* siScaler ) -> Unit
{
@ -315,6 +320,39 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
return Unit::UM;
}
if( sizeLeft >= 5 && ch == 'p' && cptr[1] == 's' && cptr[2] == '/' && cptr[3] == 'i'
&& cptr[4] == 'n' && !isalnum( cptr[5] ) )
{
m_token.pos += 5;
return Unit::PsPerInch;
}
if( sizeLeft >= 5 && ch == 'p' && cptr[1] == 's' && cptr[2] == '/' && cptr[3] == 'c'
&& cptr[4] == 'm' && !isalnum( cptr[5] ) )
{
m_token.pos += 5;
return Unit::PsPerCm;
}
if( sizeLeft >= 5 && ch == 'p' && cptr[1] == 's' && cptr[2] == '/' && cptr[3] == 'm'
&& cptr[4] == 'm' && !isalnum( cptr[5] ) )
{
m_token.pos += 5;
return Unit::PsPerMm;
}
if( sizeLeft >= 2 && ch == 'f' && cptr[1] == 's' && !isalnum( cptr[2] ) )
{
m_token.pos += 2;
return Unit::Femtoseconds;
}
if( sizeLeft >= 2 && ch == 'p' && cptr[1] == 's' && !isalnum( cptr[2] ) )
{
m_token.pos += 2;
return Unit::Picoseconds;
}
if( sizeLeft >= 2 && ch == 'm' && cptr[ 1 ] == 'm' && !isalnum( cptr[ 2 ] ) )
{
m_token.pos += 2;
@ -443,6 +481,59 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
{
retval.value.dValue = siScaler;
}
else if( m_defaultUnits == Unit::Picoseconds )
{
switch( convertFrom )
{
case Unit::Picoseconds: retval.value.dValue = 1.0; break;
case Unit::Femtoseconds: retval.value.dValue = 1.0 / 1000.0; break;
default:
case Unit::Invalid: break;
}
}
else if( m_defaultUnits == Unit::Femtoseconds )
{
switch( convertFrom )
{
case Unit::Picoseconds: retval.value.dValue = 1000.0; break;
case Unit::Femtoseconds: retval.value.dValue = 1.0; break;
default:
case Unit::Invalid: break;
}
}
else if( m_defaultUnits == Unit::PsPerInch )
{
switch( convertFrom )
{
case Unit::PsPerInch: retval.value.dValue = 1.0; break;
case Unit::PsPerCm: retval.value.dValue = 2.54; break;
case Unit::PsPerMm: retval.value.dValue = 25.4; break;
default:
case Unit::Invalid: break;
}
}
else if( m_defaultUnits == Unit::PsPerCm )
{
switch( convertFrom )
{
case Unit::PsPerInch: retval.value.dValue = 1.0 / 2.54; break;
case Unit::PsPerCm: retval.value.dValue = 1.0; break;
case Unit::PsPerMm: retval.value.dValue = 10.0; break;
default:
case Unit::Invalid: break;
}
}
else if( m_defaultUnits == Unit::PsPerMm )
{
switch( convertFrom )
{
case Unit::PsPerInch: retval.value.dValue = 1.0 / 25.4; break;
case Unit::PsPerCm: retval.value.dValue = 1.0 / 10.0; break;
case Unit::PsPerMm: retval.value.dValue = 1.0; break;
default:
case Unit::Invalid: break;
}
}
}
else if( isalpha( ch ) )
{

View File

@ -719,11 +719,12 @@ void COMPILER::freeTree( LIBEVAL::TREE_NODE *tree )
}
void TREE_NODE::SetUop( int aOp, double aValue )
void TREE_NODE::SetUop( int aOp, double aValue, EDA_UNITS aUnits )
{
delete uop;
std::unique_ptr<VALUE> val = std::make_unique<VALUE>( aValue );
val->SetUnits( aUnits );
uop = new UOP( aOp, std::move( val ) );
}
@ -872,7 +873,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
node->leaf[0]->isVisited = true;
node->leaf[1]->isVisited = true;
node->SetUop( TR_UOP_PUSH_VALUE, 0.0 );
node->SetUop( TR_UOP_PUSH_VALUE, 0.0, EDA_UNITS::UNSCALED );
node->isTerminal = true;
break;
}
@ -1005,7 +1006,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
node->leaf[0]->isVisited = true;
node->leaf[1]->isVisited = true;
node->SetUop( TR_UOP_PUSH_VALUE, 0.0 );
node->SetUop( TR_UOP_PUSH_VALUE, 0.0, EDA_UNITS::UNSCALED );
node->isTerminal = true;
break;
}
@ -1017,6 +1018,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
{
TREE_NODE* son = node->leaf[0];
double value;
EDA_UNITS unitsType = EDA_UNITS::UNSCALED;
if( !node->value.str )
{
@ -1031,6 +1033,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
}
int units = son->value.idx;
unitsType = m_unitResolver->GetSupportedUnitsTypes().at( units );
value = m_unitResolver->Convert( formatNode( node ), units );
son->isVisited = true;
}
@ -1047,7 +1050,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
value = EDA_UNIT_UTILS::UI::DoubleValueFromString( formatNode( node ) );
}
node->SetUop( TR_UOP_PUSH_VALUE, value );
node->SetUop( TR_UOP_PUSH_VALUE, value, unitsType );
node->isTerminal = true;
break;
}
@ -1170,19 +1173,45 @@ void UOP::Exec( CONTEXT* ctx )
}
}
// TODO: This doesn't fully calculate units correctly yet. We really need to work out the dimensional analysis
// TODO: (and do this independently of unit specifics - e.g. MM + INCH needs to return one of the dimension
// TODO: types, but our units framework doesn't currently allow this. Therefore, use some heuristics to
// TODO: determine the resulting operation unit type for now
auto getOpResultUnits = []( const VALUE* aVal1, const VALUE* aVal2 )
{
// This condition can occur in, e.g., a unary negation operation
if( aVal1->GetUnits() == EDA_UNITS::UNSCALED && aVal2->GetUnits() != EDA_UNITS::UNSCALED )
{
return aVal2->GetUnits();
}
if( aVal1->GetUnits() != EDA_UNITS::UNSCALED && aVal2->GetUnits() == EDA_UNITS::UNSCALED )
{
return aVal1->GetUnits();
}
return aVal2->GetUnits();
};
EDA_UNITS resultUnits = EDA_UNITS::UNSCALED;
switch( m_op )
{
case TR_OP_ADD:
result = AS_DOUBLE( arg1 ) + AS_DOUBLE( arg2 );
resultUnits = getOpResultUnits( arg1, arg2 );
break;
case TR_OP_SUB:
result = AS_DOUBLE( arg1 ) - AS_DOUBLE( arg2 );
resultUnits = getOpResultUnits( arg1, arg2 );
break;
case TR_OP_MUL:
result = AS_DOUBLE( arg1 ) * AS_DOUBLE( arg2 );
resultUnits = getOpResultUnits( arg1, arg2 );
break;
case TR_OP_DIV:
result = AS_DOUBLE( arg1 ) / AS_DOUBLE( arg2 );
resultUnits = getOpResultUnits( arg1, arg2 );
break;
case TR_OP_LESS_EQUAL:
result = AS_DOUBLE( arg1 ) <= AS_DOUBLE( arg2 ) ? 1 : 0;
@ -1225,6 +1254,7 @@ void UOP::Exec( CONTEXT* ctx )
auto rp = ctx->AllocValue();
rp->Set( result );
rp->SetUnits( resultUnits );
ctx->Push( rp );
return;
}
@ -1246,6 +1276,7 @@ void UOP::Exec( CONTEXT* ctx )
auto rp = ctx->AllocValue();
rp->Set( result );
rp->SetUnits( arg1->GetUnits() );
ctx->Push( rp );
return;
}

View File

@ -59,6 +59,7 @@ NETCLASS::NETCLASS( const wxString& aName, bool aInitWithDefaults ) : m_isDefaul
SetName( aName );
SetPriority( -1 );
SetTuningProfile( wxEmptyString );
// Colors are a special optional case - always set, but UNSPECIFIED used in place of optional
SetPcbColor( COLOR4D::UNSPECIFIED );
@ -101,6 +102,7 @@ void NETCLASS::ResetParents()
SetBusWidthParent( this );
SetSchematicColorParent( this );
SetLineStyleParent( this );
SetTuningProfileParent( this );
}
@ -178,6 +180,9 @@ void NETCLASS::Serialize( google::protobuf::Any &aContainer ) const
if( m_pcbColor != COLOR4D::UNSPECIFIED )
PackColor( *board->mutable_color(), m_pcbColor );
if( HasTuningProfile() )
board->set_tuning_profile( m_TuningProfile );
project::NetClassSchematicSettings* schematic = nc.mutable_schematic();
if( m_wireWidth )
@ -244,6 +249,9 @@ bool NETCLASS::Deserialize( const google::protobuf::Any &aContainer )
if( nc.board().has_color() )
m_pcbColor = UnpackColor( nc.board().color() );
if( nc.board().has_tuning_profile() )
m_TuningProfile = nc.board().tuning_profile();
if( nc.schematic().has_wire_width() )
m_wireWidth = nc.schematic().wire_width().value_nm();

View File

@ -96,6 +96,7 @@ data
date
defaults
descr
die_delay
die_length
dielectric_constraints
dimension

View File

@ -45,14 +45,19 @@ wxString KIGFX::PREVIEW::DimensionLabel( const wxString& prefix, double aVal,
// nanometre
switch( aUnits )
{
case EDA_UNITS::UM: fmtStr = wxT( "%.0f" ); break; // 1um
case EDA_UNITS::MM: fmtStr = wxT( "%.3f" ); break; // 1um
case EDA_UNITS::CM: fmtStr = wxT( "%.4f" ); break; // 1um
case EDA_UNITS::MILS: fmtStr = wxT( "%.1f" ); break; // 0.1mil
case EDA_UNITS::INCH: fmtStr = wxT( "%.4f" ); break; // 0.1mil
case EDA_UNITS::DEGREES: fmtStr = wxT( "%.1f" ); break; // 0.1deg
case EDA_UNITS::PERCENT: fmtStr = wxT( "%.1f" ); break; // 0.1%
case EDA_UNITS::UNSCALED: fmtStr = wxT( "%f" ); break;
case EDA_UNITS::UM: fmtStr = wxT( "%.0f" ); break; // 1um
case EDA_UNITS::MM: fmtStr = wxT( "%.3f" ); break; // 1um
case EDA_UNITS::CM: fmtStr = wxT( "%.4f" ); break; // 1um
case EDA_UNITS::MILS: fmtStr = wxT( "%.1f" ); break; // 0.1mil
case EDA_UNITS::INCH: fmtStr = wxT( "%.4f" ); break; // 0.1mil
case EDA_UNITS::DEGREES: fmtStr = wxT( "%.1f" ); break; // 0.1deg
case EDA_UNITS::PERCENT: fmtStr = wxT( "%.1f" ); break; // 0.1%
case EDA_UNITS::FS: fmtStr = wxT( "%.4f" ); break; // 0.0001ps
case EDA_UNITS::PS: fmtStr = wxT( "%.3f" ); break; // 0.001ps
case EDA_UNITS::PS_PER_INCH: fmtStr = wxT( "%.3f" ); break; // 0.001ps/in
case EDA_UNITS::PS_PER_CM: fmtStr = wxT( "%.3f" ); break; // 0.001ps/cm
case EDA_UNITS::PS_PER_MM: fmtStr = wxT( "%.3f" ); break; // 0.001ps/mm
case EDA_UNITS::UNSCALED: fmtStr = wxT( "%f" ); break;
}
str << wxString::Format( fmtStr, EDA_UNIT_UTILS::UI::ToUserUnit( aIuScale, aUnits, aVal ) );

View File

@ -35,7 +35,8 @@
// const int netSettingsSchemaVersion = 1; // new overbar syntax
// const int netSettingsSchemaVersion = 2; // exclude buses from netclass members
// const int netSettingsSchemaVersion = 3; // netclass assignment patterns
const int netSettingsSchemaVersion = 4; // netclass ordering
// const int netSettingsSchemaVersion = 4; // netclass ordering
const int netSettingsSchemaVersion = 5; // Tuning profile names
static std::optional<int> getInPcbUnits( const nlohmann::json& aObj, const std::string& aKey,
@ -73,7 +74,8 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
nlohmann::json nc_json = { { "name", nc->GetName().ToUTF8() },
{ "priority", nc->GetPriority() },
{ "schematic_color", nc->GetSchematicColor( true ) },
{ "pcb_color", nc->GetPcbColor( true ) } };
{ "pcb_color", nc->GetPcbColor( true ) },
{ "tuning_profile", nc->GetTuningProfile() } };
auto saveInPcbUnits =
[]( nlohmann::json& json, const std::string& aKey, int aValue )
@ -131,6 +133,8 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
int priority = entry["priority"];
nc->SetPriority( priority );
nc->SetTuningProfile( entry["tuning_profile"] );
if( auto value = getInPcbUnits( entry, "clearance" ) )
nc->SetClearance( *value );
@ -327,6 +331,7 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
registerMigration( 1, 2, std::bind( &NET_SETTINGS::migrateSchema1to2, this ) );
registerMigration( 2, 3, std::bind( &NET_SETTINGS::migrateSchema2to3, this ) );
registerMigration( 3, 4, std::bind( &NET_SETTINGS::migrateSchema3to4, this ) );
registerMigration( 4, 5, std::bind( &NET_SETTINGS::migrateSchema4to5, this ) );
}
@ -466,6 +471,21 @@ bool NET_SETTINGS::migrateSchema3to4()
}
bool NET_SETTINGS::migrateSchema4to5()
{
// Add tuning profile name field to netclasses
if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() )
{
const wxString emptyStr = "";
for( auto& netClass : m_internals->At( "classes" ).items() )
netClass.value()["tuning_profile"] = emptyStr.ToUTF8();
}
return true;
}
void NET_SETTINGS::SetDefaultNetclass( std::shared_ptr<NETCLASS> netclass )
{
m_defaultNetClass = netclass;
@ -907,6 +927,12 @@ void NET_SETTINGS::makeEffectiveNetclass( std::shared_ptr<NETCLASS>& effectiveNe
effectiveNetclass->SetSchematicColor( schColor );
effectiveNetclass->SetSchematicColorParent( nc );
}
if( nc->HasTuningProfile() )
{
effectiveNetclass->SetTuningProfile( nc->GetTuningProfile() );
effectiveNetclass->SetTuningProfileParent( nc );
}
}
// Fill in any required defaults
@ -997,6 +1023,14 @@ bool NET_SETTINGS::addMissingDefaults( NETCLASS* nc ) const
nc->SetBusWidthParent( m_defaultNetClass.get() );
}
// The tuning profile can be empty - only fill if a default tuning profile is set
if( !nc->HasTuningProfile() && m_defaultNetClass->HasTuningProfile() )
{
addedDefault = true;
nc->SetTuningProfile( m_defaultNetClass->GetTuningProfile() );
nc->SetTuningProfileParent( m_defaultNetClass.get() );
}
return addedDefault;
}

View File

@ -22,10 +22,13 @@
#include <project.h>
#include <project/component_class_settings.h>
#include <project/net_settings.h>
#include <project/time_domain_parameters.h>
#include <settings/json_settings_internals.h>
#include <project/project_file.h>
#include <settings/common_settings.h>
#include <settings/parameters.h>
#include <wildcards_and_files_ext.h>
#include <project/project_file.h>
#include <wx/config.h>
#include <wx/log.h>
@ -36,8 +39,13 @@ const int projectFileSchemaVersion = 3;
PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) :
JSON_SETTINGS( aFullPath, SETTINGS_LOC::PROJECT, projectFileSchemaVersion ),
m_ErcSettings( nullptr ), m_SchematicSettings( nullptr ), m_BoardSettings(),
m_project( nullptr ), m_wasMigrated( false )
m_ErcSettings( nullptr ),
m_SchematicSettings( nullptr ),
m_BoardSettings(),
m_sheets(),
m_boards(),
m_project( nullptr ),
m_wasMigrated( false )
{
// Keep old files around
m_deleteLegacyAfterMigration = false;
@ -117,6 +125,9 @@ PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) :
m_ComponentClassSettings =
std::make_shared<COMPONENT_CLASS_SETTINGS>( this, "component_class_settings" );
m_timeDomainParameters =
std::make_shared<TIME_DOMAIN_PARAMETERS>( this, "time_domain_parameters" );
m_params.emplace_back( new PARAM_LAYER_PRESET( "board.layer_presets", &m_LayerPresets ) );
m_params.emplace_back( new PARAM_VIEWPORT( "board.viewports", &m_Viewports ) );

View File

@ -230,6 +230,8 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
&m_NetInspectorPanel.show_zero_pad_nets, false ) );
m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.show_unconnected_nets",
&m_NetInspectorPanel.show_unconnected_nets, false ) );
m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.show_time_domain_details",
&m_NetInspectorPanel.show_time_domain_details, false ) );
m_params.emplace_back( new PARAM<int>( "net_inspector_panel.sorting_column",
&m_NetInspectorPanel.sorting_column, -1 ) );
m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.sort_ascending",

View File

@ -0,0 +1,197 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 CERN
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
* @author Jon Evans <jon@craftyjon.com>
*
* This program 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 3 of the License, or (at your
* option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <lset.h>
#include <netclass.h>
#include <io/cadstar/cadstar_archive_parser.h>
#include <project/time_domain_parameters.h>
#include <nlohmann/json.hpp>
#include <settings/parameters.h>
constexpr int timeDomainParametersSchemaVersion = 0;
TIME_DOMAIN_PARAMETERS::TIME_DOMAIN_PARAMETERS( JSON_SETTINGS* aParent, const std::string& aPath ) :
NESTED_SETTINGS( "time_domain_parameters", timeDomainParametersSchemaVersion, aParent,
aPath, false )
{
auto saveViaOverrideConfigurationLine =
[]( nlohmann::json& json_array, const TUNING_PROFILE_VIA_OVERRIDE_ENTRY& item )
{
const nlohmann::json item_json = { { "signal_layer_from", LSET::Name( item.m_SignalLayerFrom ) },
{ "signal_layer_to", LSET::Name( item.m_SignalLayerTo ) },
{ "via_layer_from", LSET::Name( item.m_ViaLayerFrom ) },
{ "via_layer_to", LSET::Name( item.m_ViaLayerTo ) },
{ "delay", item.m_Delay } };
json_array.push_back( item_json );
};
auto readViaOverrideConfigurationLine = []( const nlohmann::json& entry )
{
wxString signalLayerFromName = entry["signal_layer_from"];
int signalLayerFromId = LSET::NameToLayer( signalLayerFromName );
wxString signalLayerToName = entry["signal_layer_to"];
int signalLayerToId = LSET::NameToLayer( signalLayerToName );
wxString viaLayerFromName = entry["via_layer_from"];
int viaLayerFromId = LSET::NameToLayer( viaLayerFromName );
wxString viaLayerToName = entry["via_layer_to"];
int viaLayerToId = LSET::NameToLayer( viaLayerToName );
int delay = entry["delay"];
TUNING_PROFILE_VIA_OVERRIDE_ENTRY item{ static_cast<PCB_LAYER_ID>( signalLayerFromId ),
static_cast<PCB_LAYER_ID>( signalLayerToId ),
static_cast<PCB_LAYER_ID>( viaLayerFromId ),
static_cast<PCB_LAYER_ID>( viaLayerToId ), delay };
return item;
};
auto saveUserDefinedProfileConfigurationLine =
[&saveViaOverrideConfigurationLine]( nlohmann::json& json_array, const TIME_DOMAIN_TUNING_PROFILE& item )
{
nlohmann::json layer_velocities = nlohmann::json::array();
for( const auto& [layerId, velocity] : item.m_LayerPropagationDelays )
{
nlohmann::json layer_json = { { "layer", LSET::Name( layerId ) }, { "delay", velocity } };
layer_velocities.push_back( layer_json );
}
nlohmann::json via_overrides = nlohmann::json::array();
for( const TUNING_PROFILE_VIA_OVERRIDE_ENTRY& viaOverride : item.m_ViaOverrides )
{
saveViaOverrideConfigurationLine( via_overrides, viaOverride );
}
const nlohmann::json item_json = { { "profile_name", item.m_ProfileName.ToUTF8() },
{ "via_prop_delay", item.m_ViaPropagationDelay },
{ "layer_delays", layer_velocities },
{ "via_overrides", via_overrides } };
json_array.push_back( item_json );
};
auto readUserDefinedProfileConfigurationLine = [&readViaOverrideConfigurationLine]( const nlohmann::json& entry )
{
const wxString profileName = entry["profile_name"];
const int viaPropDelay = entry["via_prop_delay"];
std::map<PCB_LAYER_ID, int> traceDelays;
for( const nlohmann::json& layerEntry : entry["layer_delays"] )
{
if( !layerEntry.is_object() || !layerEntry.contains( "layer" ) )
continue;
wxString layerName = layerEntry["layer"];
int layerId = LSET::NameToLayer( layerName );
const int velocity = layerEntry["delay"];
traceDelays[static_cast<PCB_LAYER_ID>( layerId )] = velocity;
}
std::vector<TUNING_PROFILE_VIA_OVERRIDE_ENTRY> viaOverrides;
for( const nlohmann::json& viaEntry : entry["via_overrides"] )
{
if( !viaEntry.is_object() || !viaEntry.contains( "signal_layer_from" ) )
continue;
viaOverrides.push_back( readViaOverrideConfigurationLine( viaEntry ) );
}
TIME_DOMAIN_TUNING_PROFILE item{ profileName, viaPropDelay, std::move( traceDelays ),
std::move( viaOverrides ) };
return item;
};
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
"delay_profiles_user_defined",
[&]() -> nlohmann::json
{
nlohmann::json ret = nlohmann::json::array();
for( const auto& entry : m_delayProfiles )
saveUserDefinedProfileConfigurationLine( ret, entry );
return ret;
},
[&]( const nlohmann::json& aJson )
{
if( !aJson.is_array() )
return;
ClearDelayProfiles();
for( const nlohmann::json& entry : aJson )
{
if( !entry.is_object() || !entry.contains( "profile_name" ) )
continue;
m_delayProfiles.emplace_back( readUserDefinedProfileConfigurationLine( entry ) );
}
},
{} ) );
}
TIME_DOMAIN_PARAMETERS::~TIME_DOMAIN_PARAMETERS()
{
// Release early before destroying members
if( m_parent )
{
m_parent->ReleaseNestedSettings( this );
m_parent = nullptr;
}
}
bool TIME_DOMAIN_PARAMETERS::operator==( const TIME_DOMAIN_PARAMETERS& aOther ) const
{
/*
if( !std::equal( std::begin( m_netClasses ), std::end( m_netClasses ),
std::begin( aOther.m_netClasses ) ) )
return false;
if( !std::equal( std::begin( m_netClassPatternAssignments ),
std::end( m_netClassPatternAssignments ),
std::begin( aOther.m_netClassPatternAssignments ) ) )
return false;
if( !std::equal( std::begin( m_netClassLabelAssignments ),
std::end( m_netClassLabelAssignments ),
std::begin( aOther.m_netClassLabelAssignments ) ) )
return false;
if( !std::equal( std::begin( m_netColorAssignments ), std::end( m_netColorAssignments ),
std::begin( aOther.m_netColorAssignments ) ) )
return false;
*/
return true;
}

View File

@ -102,6 +102,10 @@ wxPGWindowList PG_UNIT_EDITOR::CreateControls( wxPropertyGrid* aPropGrid, wxPGPr
m_unitBinder->SetCoordType( ORIGIN_TRANSFORMS::NOT_A_COORD );
m_unitBinder->SetUnits( EDA_UNITS::DEGREES );
}
else if( dynamic_cast<PGPROPERTY_TIME*>( aProperty ) != nullptr )
{
m_unitBinder->SetUnits( EDA_UNITS::PS );
}
UpdateControl( aProperty, win );

View File

@ -210,6 +210,11 @@ wxPGProperty* PGPropertyFactory( const PROPERTY_BASE* aProperty, EDA_DRAW_FRAME*
switch( display )
{
case PROPERTY_DISPLAY::PT_TIME:
ret = new PGPROPERTY_TIME( aFrame );
ret->SetEditor( PG_UNIT_EDITOR::BuildEditorName( aFrame ) );
break;
case PROPERTY_DISPLAY::PT_SIZE:
ret = new PGPROPERTY_SIZE( aFrame );
ret->SetEditor( PG_UNIT_EDITOR::BuildEditorName( aFrame ) );
@ -724,3 +729,66 @@ wxString PGPROPERTY_COLOR4D::ValueToString( wxVariant& aValue, int aFlags ) cons
return ret;
}
PGPROPERTY_TIME::PGPROPERTY_TIME( EDA_DRAW_FRAME* aParentFrame ) :
wxIntProperty( wxPG_LABEL, wxPG_LABEL, 0 ),
m_parentFrame( aParentFrame )
{
}
#if wxCHECK_VERSION( 3, 3, 0 )
bool PGPROPERTY_AREA::StringToValue( wxVariant& aVariant, const wxString& aText,
wxPGPropValFormatFlags aArgFlags ) const
#else
bool PGPROPERTY_TIME::StringToValue( wxVariant& aVariant, const wxString& aText,
int aArgFlags ) const
#endif
{
wxCHECK_MSG( false, false, wxS( "PGPROPERTY_RATIO::StringToValue should not be used." ) );
}
#if wxCHECK_VERSION( 3, 3, 0 )
wxString PGPROPERTY_AREA::ValueToString( wxVariant& aVariant,
wxPGPropValFormatFlags aArgFlags ) const
#else
wxString PGPROPERTY_TIME::ValueToString( wxVariant& aVariant, int aArgFlags ) const
#endif
{
int value;
if( aVariant.GetType() == wxT( "std::optional<int>" ) )
{
auto* variantData = static_cast<STD_OPTIONAL_INT_VARIANT_DATA*>( aVariant.GetData() );
if( !variantData->Value().has_value() )
return wxEmptyString;
value = variantData->Value().value();
}
else if( aVariant.GetType() == wxPG_VARIANT_TYPE_LONG )
{
value = static_cast<int>( aVariant.GetInteger() );
}
else
{
wxFAIL_MSG( wxT( "Expected int (or std::optional<int>) value type" ) );
return wxEmptyString;
}
return m_parentFrame->StringFromValue( value, true, EDA_DATA_TYPE::TIME );
}
bool PGPROPERTY_TIME::ValidateValue( wxVariant& aValue, wxPGValidationInfo& aValidationInfo ) const
{
return true;
}
wxValidator* PGPROPERTY_TIME::DoGetValidator() const
{
return nullptr;
}

View File

@ -34,13 +34,14 @@
#include <wx/config.h>
#include <wx/log.h>
#include <wx/regex.h>
#include <wx/tokenzr.h>
///! The following environment variables will never be migrated from a previous version
const wxRegEx versionedEnvVarRegex( wxS( "KICAD[0-9]+_[A-Z0-9_]+(_DIR)?" ) );
///! Update the schema version whenever a migration is required
const int commonSchemaVersion = 3;
const int commonSchemaVersion = 4;
COMMON_SETTINGS::COMMON_SETTINGS() :
JSON_SETTINGS( "kicad_common", SETTINGS_LOC::USER, commonSchemaVersion ),
@ -357,10 +358,10 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
&m_NetclassPanel.sash_pos, 160 ) );
m_params.emplace_back( new PARAM<wxString>( "netclass_panel.eeschema_shown_columns",
&m_NetclassPanel.eeschema_visible_columns, "0 10 11 12 13" ) );
&m_NetclassPanel.eeschema_visible_columns, "0 11 12 13 14" ) );
m_params.emplace_back( new PARAM<wxString>( "netclass_panel.pcbnew_shown_columns",
&m_NetclassPanel.pcbnew_visible_columns, "0 1 2 3 4 5 6 7 8 9" ) );
&m_NetclassPanel.pcbnew_visible_columns, "0 1 2 3 4 5 6 7 8 9 10" ) );
m_params.emplace_back( new PARAM<int>( "package_manager.sash_pos",
&m_PackageManager.sash_pos, 380 ) );
@ -434,6 +435,7 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
registerMigration( 0, 1, std::bind( &COMMON_SETTINGS::migrateSchema0to1, this ) );
registerMigration( 1, 2, std::bind( &COMMON_SETTINGS::migrateSchema1to2, this ) );
registerMigration( 2, 3, std::bind( &COMMON_SETTINGS::migrateSchema2to3, this ) );
registerMigration( 3, 4, std::bind( &COMMON_SETTINGS::migrateSchema3to4, this ) );
}
@ -561,6 +563,66 @@ bool COMMON_SETTINGS::migrateSchema2to3()
}
bool COMMON_SETTINGS::migrateSchema3to4()
{
// >= 10 = add 1
try
{
// Update netclass panel shown columns for eeschema
const nlohmann::json::json_pointer v3_pointer_eeschema( "/netclass_panel/eeschema_shown_columns"_json_pointer );
wxString eeSchemaColumnList_old = m_internals->at( v3_pointer_eeschema );
wxStringTokenizer eeSchemaShownTokens( eeSchemaColumnList_old );
wxString eeSchemaColumnList_new;
while( eeSchemaShownTokens.HasMoreTokens() )
{
long colNumber;
eeSchemaShownTokens.GetNextToken().ToLong( &colNumber );
if( colNumber >= 10 )
++colNumber;
eeSchemaColumnList_new += wxString::Format( wxT( "%ld " ), colNumber );
}
eeSchemaColumnList_new.Trim( true );
eeSchemaColumnList_new.Trim( false );
m_internals->at( v3_pointer_eeschema ) = eeSchemaColumnList_new.ToUTF8();
// Update netclass panel shown columns for pcbnew
const nlohmann::json::json_pointer v3_pointer_pcbnew( "/netclass_panel/pcbnew_shown_columns"_json_pointer );
wxString pcbnewColumnList_old = m_internals->at( v3_pointer_pcbnew );
wxStringTokenizer pcbnewShownTokens( pcbnewColumnList_old );
wxString pcbnewColumnList_new;
while( pcbnewShownTokens.HasMoreTokens() )
{
long colNumber;
pcbnewShownTokens.GetNextToken().ToLong( &colNumber );
if( colNumber >= 10 )
++colNumber;
pcbnewColumnList_new += wxString::Format( wxT( "%ld " ), colNumber );
}
pcbnewColumnList_new.Trim( true );
pcbnewColumnList_new.Trim( false );
m_internals->at( v3_pointer_pcbnew ) = pcbnewColumnList_new.ToUTF8();
}
catch( ... )
{
wxLogTrace( traceSettings, wxT( "COMMON_SETTINGS::Migrate 3->4: /netclass_panel/shown_columns not found" ) );
}
return true;
}
bool COMMON_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
{
bool ret = true;

View File

@ -371,17 +371,20 @@ void WX_GRID::onCellEditorShown( wxGridEvent& aEvent )
void WX_GRID::onCellEditorHidden( wxGridEvent& aEvent )
{
if( alg::contains( m_autoEvalCols, aEvent.GetCol() ) )
const int col = aEvent.GetCol();
if( alg::contains( m_autoEvalCols, col ) )
{
UNITS_PROVIDER* unitsProvider = m_unitsProviders[ aEvent.GetCol() ];
if( !unitsProvider )
unitsProvider = m_unitsProviders.begin()->second;
m_eval->SetDefaultUnits( unitsProvider->GetUserUnits() );
auto [cellUnits, cellDataType] = getColumnUnits( col );
int row = aEvent.GetRow();
int col = aEvent.GetCol();
m_eval->SetDefaultUnits( cellUnits );
const int row = aEvent.GetRow();
// Determine if this cell is marked as holding nullable values
bool isNullable = false;
@ -399,7 +402,7 @@ void WX_GRID::onCellEditorHidden( wxGridEvent& aEvent )
}
CallAfter(
[this, row, col, isNullable, unitsProvider]()
[this, row, col, isNullable, unitsProvider, cellDataType]()
{
wxString stringValue = GetCellValue( row, col );
bool processedOk = true;
@ -418,19 +421,22 @@ void WX_GRID::onCellEditorHidden( wxGridEvent& aEvent )
if( stringValue == UNITS_PROVIDER::NullUiString )
{
val = unitsProvider->OptionalValueFromString(
UNITS_PROVIDER::NullUiString );
UNITS_PROVIDER::NullUiString, cellDataType );
}
else
{
val = unitsProvider->OptionalValueFromString( m_eval->Result() );
val = unitsProvider->OptionalValueFromString( m_eval->Result(),
cellDataType );
}
evalValue = unitsProvider->StringFromOptionalValue( val, true );
evalValue = unitsProvider->StringFromOptionalValue( val, true,
cellDataType );
}
else
{
int val = unitsProvider->ValueFromString( m_eval->Result() );
evalValue = unitsProvider->StringFromValue( val, true );
int val = unitsProvider->ValueFromString( m_eval->Result(),
cellDataType );
evalValue = unitsProvider->StringFromValue( val, true, cellDataType );
}
if( stringValue != evalValue )
@ -702,6 +708,19 @@ void WX_GRID::SetUnitsProvider( UNITS_PROVIDER* aProvider, int aCol )
}
void WX_GRID::SetAutoEvalColUnits( const int col, EDA_UNITS aUnit, EDA_DATA_TYPE aUnitType )
{
m_autoEvalColsUnits[col] = std::make_pair( aUnit, aUnitType );
}
void WX_GRID::SetAutoEvalColUnits( const int col, EDA_UNITS aUnit )
{
const EDA_DATA_TYPE type = UNITS_PROVIDER::GetTypeFromUnits( aUnit );
SetAutoEvalColUnits( col, aUnit, type );
}
int WX_GRID::GetUnitValue( int aRow, int aCol )
{
UNITS_PROVIDER* unitsProvider = m_unitsProviders[ aCol ];
@ -711,15 +730,17 @@ int WX_GRID::GetUnitValue( int aRow, int aCol )
wxString stringValue = GetCellValue( aRow, aCol );
auto [cellUnits, cellDataType] = getColumnUnits( aCol );
if( alg::contains( m_autoEvalCols, aCol ) )
{
m_eval->SetDefaultUnits( unitsProvider->GetUserUnits() );
m_eval->SetDefaultUnits( cellUnits );
if( m_eval->Process( stringValue ) )
stringValue = m_eval->Result();
}
return unitsProvider->ValueFromString( stringValue );
return unitsProvider->ValueFromString( stringValue, cellDataType );
}
@ -732,15 +753,17 @@ std::optional<int> WX_GRID::GetOptionalUnitValue( int aRow, int aCol )
wxString stringValue = GetCellValue( aRow, aCol );
auto [cellUnits, cellDataType] = getColumnUnits( aCol );
if( alg::contains( m_autoEvalCols, aCol ) )
{
m_eval->SetDefaultUnits( unitsProvider->GetUserUnits() );
m_eval->SetDefaultUnits( cellUnits );
if( stringValue != UNITS_PROVIDER::NullUiString && m_eval->Process( stringValue ) )
stringValue = m_eval->Result();
}
return unitsProvider->OptionalValueFromString( stringValue );
return unitsProvider->OptionalValueFromString( stringValue, cellDataType );
}
@ -751,7 +774,14 @@ void WX_GRID::SetUnitValue( int aRow, int aCol, int aValue )
if( !unitsProvider )
unitsProvider = m_unitsProviders.begin()->second;
SetCellValue( aRow, aCol, unitsProvider->StringFromValue( aValue, true ) );
EDA_DATA_TYPE cellDataType;
if( m_autoEvalColsUnits.contains( aCol ) )
cellDataType = m_autoEvalColsUnits[aCol].second;
else
cellDataType = EDA_DATA_TYPE::DISTANCE;
SetCellValue( aRow, aCol, unitsProvider->StringFromValue( aValue, true, cellDataType ) );
}
@ -840,3 +870,20 @@ void WX_GRID::EnsureColLabelsVisible()
if( initial_row_height != row_height )
SetColLabelSize( row_height );
}
std::pair<EDA_UNITS, EDA_DATA_TYPE> WX_GRID::getColumnUnits( const int aCol ) const
{
if( m_autoEvalColsUnits.contains( aCol ) )
return { m_autoEvalColsUnits.at( aCol ).first, m_autoEvalColsUnits.at( aCol ).second };
UNITS_PROVIDER* unitsProvider;
if( m_unitsProviders.contains( aCol ) )
unitsProvider = m_unitsProviders.at( aCol );
else
unitsProvider = m_unitsProviders.begin()->second;
// Legacy - default always DISTANCE
return { unitsProvider->GetUserUnits(), EDA_DATA_TYPE::DISTANCE };
}

View File

@ -75,6 +75,8 @@ struct EDA_IU_SCALE
{
const double IU_PER_MM;
const double IU_PER_MILS;
const double IU_PER_PS{ 1e6 }; ///< Internal time units are attoseconds
const double IU_PER_PS_PER_MM{ 1e6 }; ///< Internal velocity units are attoseconds/mm
const double MM_PER_IU;

View File

@ -48,6 +48,8 @@ public:
void ImportSettingsFrom( const std::shared_ptr<NET_SETTINGS>& aNetSettings );
void UpdateTuningProfileNames( const std::vector<wxString>& aNames ) const;
private:
void OnAddNetclassClick( wxCommandEvent& event ) override;
void OnRemoveNetclassClick( wxCommandEvent& event ) override;

View File

@ -36,22 +36,29 @@
*/
enum class EDA_DATA_TYPE
{
DISTANCE = 0,
AREA = 1,
VOLUME = 2,
UNITLESS = 3
DISTANCE = 0,
AREA = 1,
VOLUME = 2,
UNITLESS = 3,
TIME = 4,
LENGTH_DELAY = 5
};
enum class EDA_UNITS
{
INCH = 0, // Do not use IN: it conflicts with a Windows header
MM = 1,
UNSCALED = 2,
DEGREES = 3,
PERCENT = 4,
MILS = 5,
UM = 6,
CM = 7
INCH = 0, // Do not use IN: it conflicts with a Windows header
MM = 1,
UNSCALED = 2,
DEGREES = 3,
PERCENT = 4,
MILS = 5,
UM = 6,
CM = 7,
FS = 8, // Femtoseconds
PS = 9, // Picoseconds
PS_PER_INCH = 10,
PS_PER_CM = 11,
PS_PER_MM = 12
};
namespace EDA_UNIT_UTILS

View File

@ -94,7 +94,22 @@ namespace numEval
class KICOMMON_API NUMERIC_EVALUATOR
{
enum class Unit { Invalid, UM, MM, CM, Inch, Mil, Degrees, SI };
enum class Unit
{
Invalid,
UM,
MM,
CM,
Inch,
Mil,
Degrees,
SI,
Femtoseconds,
Picoseconds,
PsPerInch,
PsPerCm,
PsPerMm
};
public:
NUMERIC_EVALUATOR( EDA_UNITS aUnits );

View File

@ -144,7 +144,7 @@ public:
bool isVisited;
int srcPos;
void SetUop( int aOp, double aValue );
void SetUop( int aOp, double aValue, EDA_UNITS aUnits );
void SetUop( int aOp, const wxString& aValue, bool aStringIsWildcard );
void SetUop( int aOp, std::unique_ptr<VAR_REF> aRef = nullptr );
void SetUop( int aOp, FUNC_CALL_REF aFunc, std::unique_ptr<VAR_REF> aRef = nullptr );
@ -172,6 +172,14 @@ public:
return nullUnits;
}
virtual const std::vector<EDA_UNITS>& GetSupportedUnitsTypes() const
{
static const std::vector<EDA_UNITS> nullUnits;
return nullUnits;
}
virtual wxString GetSupportedUnitsMessage() const
{
return wxEmptyString;
@ -188,29 +196,16 @@ class KICOMMON_API VALUE
{
public:
VALUE() :
m_type( VT_UNDEFINED ),
m_valueDbl( 0 ),
m_stringIsWildcard( false ),
m_isDeferredDbl( false ),
m_isDeferredStr( false )
{};
m_type( VT_UNDEFINED ), m_valueDbl( 0 ), m_stringIsWildcard( false ), m_isDeferredDbl( false ),
m_isDeferredStr( false ), m_units( EDA_UNITS::UNSCALED ) {};
VALUE( const wxString& aStr, bool aIsWildcard = false ) :
m_type( VT_STRING ),
m_valueDbl( 0 ),
m_valueStr( aStr ),
m_stringIsWildcard( aIsWildcard ),
m_isDeferredDbl( false ),
m_isDeferredStr( false )
{};
m_type( VT_STRING ), m_valueDbl( 0 ), m_valueStr( aStr ), m_stringIsWildcard( aIsWildcard ),
m_isDeferredDbl( false ), m_isDeferredStr( false ), m_units( EDA_UNITS::UNSCALED ) {};
VALUE( const double aVal ) :
m_type( VT_NUMERIC ),
m_valueDbl( aVal ),
m_stringIsWildcard( false ),
m_isDeferredDbl( false ),
m_isDeferredStr( false )
{};
m_type( VT_NUMERIC ), m_valueDbl( aVal ), m_stringIsWildcard( false ), m_isDeferredDbl( false ),
m_isDeferredStr( false ), m_units( EDA_UNITS::UNSCALED ) {};
static VALUE* MakeNullValue()
{
@ -286,6 +281,10 @@ public:
m_valueStr = val.m_valueStr;
}
void SetUnits( const EDA_UNITS aUnits ) { m_units = aUnits; }
EDA_UNITS GetUnits() const { return m_units; }
private:
VAR_TYPE_T m_type;
mutable double m_valueDbl; // mutable to support deferred evaluation
@ -297,6 +296,8 @@ private:
mutable bool m_isDeferredStr;
std::function<wxString()> m_lambdaStr;
EDA_UNITS m_units;
};
class KICOMMON_API VAR_REF

View File

@ -238,6 +238,12 @@ public:
void SetPriority( int aPriority ) { m_Priority = aPriority; }
int GetPriority() const { return m_Priority; }
bool HasTuningProfile() const { return !m_TuningProfile.empty(); }
void SetTuningProfile( const wxString& aTuningProfile ) { m_TuningProfile = aTuningProfile; }
wxString GetTuningProfile() const { return m_TuningProfile; }
void SetTuningProfileParent( NETCLASS* aParent ) { m_tuningProfileParent = aParent; }
NETCLASS* GetTuningProfileParent() const { return m_tuningProfileParent; }
protected:
bool m_isDefault; ///< Mark if this instance is the default netclass
@ -267,6 +273,8 @@ protected:
COLOR4D m_pcbColor; ///< Optional PCB color override for this netclass
wxString m_TuningProfile; ///< The tuning profile name being used by this netclass
// The NETCLASS providing each parameter
NETCLASS* m_clearanceParent;
NETCLASS* m_trackWidthParent;
@ -282,6 +290,7 @@ protected:
NETCLASS* m_busWidthParent;
NETCLASS* m_schematicColorParent;
NETCLASS* m_lineStyleParent;
NETCLASS* m_tuningProfileParent;
};
#endif // CLASS_NETCLASS_H

View File

@ -352,6 +352,7 @@ struct KICOMMON_API PANEL_NET_INSPECTOR_SETTINGS
std::vector<wxString> custom_group_rules;
bool show_zero_pad_nets;
bool show_unconnected_nets;
bool show_time_domain_details;
int sorting_column;
bool sort_order_asc;
std::vector<int> col_order;
@ -369,6 +370,7 @@ struct KICOMMON_API PANEL_NET_INSPECTOR_SETTINGS
group_by_constraint = false;
show_zero_pad_nets = false;
show_unconnected_nets = false;
show_time_domain_details = false;
sorting_column = -1;
sort_order_asc = true;
}

View File

@ -187,6 +187,7 @@ private:
bool migrateSchema1to2();
bool migrateSchema2to3();
bool migrateSchema3to4();
bool migrateSchema4to5();
/**
* @brief Creates an effective aggregate netclass from the given constituent netclasses

View File

@ -32,6 +32,7 @@ class BOARD_DESIGN_SETTINGS;
class ERC_SETTINGS;
class NET_SETTINGS;
class COMPONENT_CLASS_SETTINGS;
class TIME_DOMAIN_PARAMETERS;
class LAYER_PAIR_SETTINGS;
class SCHEMATIC_SETTINGS;
class TEMPLATES;
@ -111,6 +112,11 @@ public:
return m_ComponentClassSettings;
}
std::shared_ptr<TIME_DOMAIN_PARAMETERS>& TimeDomainParameters()
{
return m_timeDomainParameters;
}
/**
* @return true if it should be safe to auto-save this file without user action
*/
@ -193,6 +199,11 @@ public:
*/
std::shared_ptr<COMPONENT_CLASS_SETTINGS> m_ComponentClassSettings;
/**
* Time domain parameters for this project
*/
std::shared_ptr<TIME_DOMAIN_PARAMETERS> m_timeDomainParameters;
std::vector<LAYER_PRESET> m_LayerPresets; /// List of stored layer presets
std::vector<VIEWPORT> m_Viewports; /// List of stored viewports (pos + zoom)
std::vector<VIEWPORT3D> m_Viewports3D; /// List of stored 3D viewports (view matrixes)

View File

@ -0,0 +1,80 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 CERN
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
* @author Jon Evans <jon@craftyjon.com>
*
* This program 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 3 of the License, or (at your
* option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KICAD_TIME_DOMAIN_PARAMETERS_H
#define KICAD_TIME_DOMAIN_PARAMETERS_H
#include <settings/nested_settings.h>
#include <layer_ids.h>
/**
* Represents a single line in the time domain configuration via overrides configuration grid
*/
struct TUNING_PROFILE_VIA_OVERRIDE_ENTRY
{
PCB_LAYER_ID m_SignalLayerFrom;
PCB_LAYER_ID m_SignalLayerTo;
PCB_LAYER_ID m_ViaLayerFrom;
PCB_LAYER_ID m_ViaLayerTo;
int m_Delay;
};
/**
* Represents a single line in the time domain configuration net class configuration grid
*/
struct TIME_DOMAIN_TUNING_PROFILE
{
wxString m_ProfileName;
int m_ViaPropagationDelay;
std::map<PCB_LAYER_ID, int> m_LayerPropagationDelays;
std::vector<TUNING_PROFILE_VIA_OVERRIDE_ENTRY> m_ViaOverrides;
};
/**
* TIME_DOMAIN_PARAMETERS stores the configuration for time-domain tuning
*/
class KICOMMON_API TIME_DOMAIN_PARAMETERS final : public NESTED_SETTINGS
{
public:
TIME_DOMAIN_PARAMETERS( JSON_SETTINGS* aParent, const std::string& aPath );
virtual ~TIME_DOMAIN_PARAMETERS();
bool operator==( const TIME_DOMAIN_PARAMETERS& aOther ) const;
bool operator!=( const TIME_DOMAIN_PARAMETERS& aOther ) const { return !operator==( aOther ); }
void ClearDelayProfiles() { m_delayProfiles.clear(); }
void AddDelayProfile( TIME_DOMAIN_TUNING_PROFILE&& aTraceEntry )
{
m_delayProfiles.emplace_back( std::move( aTraceEntry ) );
}
const std::vector<TIME_DOMAIN_TUNING_PROFILE>& GetDelayProfiles() const { return m_delayProfiles; }
private:
std::vector<TIME_DOMAIN_TUNING_PROFILE> m_delayProfiles;
};
#endif // KICAD_NET_SETTINGS_H

View File

@ -336,4 +336,34 @@ public:
KIGFX::COLOR4D m_backgroundColor;
};
class PGPROPERTY_TIME : public wxIntProperty
{
public:
PGPROPERTY_TIME( EDA_DRAW_FRAME* aParentFrame );
virtual ~PGPROPERTY_TIME() = default;
protected:
#if wxCHECK_VERSION( 3, 3, 0 )
bool StringToValue( wxVariant& aVariant, const wxString& aText,
wxPGPropValFormatFlags aFlags = wxPGPropValFormatFlags::Null ) const override;
wxString ValueToString( wxVariant& aVariant,
wxPGPropValFormatFlags aFlags = wxPGPropValFormatFlags::Null ) const override;
#else
bool StringToValue( wxVariant& aVariant, const wxString& aText,
int aArgFlags = 0 ) const override;
wxString ValueToString( wxVariant& aVariant, int aArgFlags = 0 ) const override;
#endif
bool ValidateValue( wxVariant& aValue, wxPGValidationInfo& aValidationInfo ) const override;
wxValidator* DoGetValidator() const override;
protected:
EDA_DRAW_FRAME* m_parentFrame;
};
#endif /* PG_PROPERTIES_H */

View File

@ -64,7 +64,8 @@ enum PROPERTY_DISPLAY
PT_COORD, ///< Coordinate expressed in distance units (mm/inch)
PT_DEGREE, ///< Angle expressed in degrees
PT_DECIDEGREE, ///< Angle expressed in decidegrees
PT_RATIO
PT_RATIO,
PT_TIME, ///< Time expressed in ps
};
///< Macro to generate unique identifier for a type

View File

@ -194,6 +194,7 @@ private:
bool migrateSchema0to1();
bool migrateSchema1to2();
bool migrateSchema2to3();
bool migrateSchema3to4();
struct LEGACY_3D_SEARCH_PATH
{

View File

@ -79,7 +79,7 @@ public:
wxString StringFromValue( double aValue, bool aAddUnitLabel = false,
EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE ) const
{
return EDA_UNIT_UTILS::UI::StringFromValue( GetIuScale(), GetUserUnits(), aValue,
return EDA_UNIT_UTILS::UI::StringFromValue( GetIuScale(), GetUnitsFromType( aType ), aValue,
aAddUnitLabel, aType );
}
@ -103,7 +103,7 @@ public:
if( !aValue )
return NullUiString;
else
return EDA_UNIT_UTILS::UI::StringFromValue( GetIuScale(), GetUserUnits(),
return EDA_UNIT_UTILS::UI::StringFromValue( GetIuScale(), GetUnitsFromType( aType ),
aValue.value(), aAddUnitLabel, aType );
}
@ -123,8 +123,8 @@ public:
wxString MessageTextFromValue( double aValue, bool aAddUnitLabel = true,
EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE ) const
{
return EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUserUnits(), aValue,
aAddUnitLabel, aType );
return EDA_UNIT_UTILS::UI::MessageTextFromValue( GetIuScale(), GetUnitsFromType( aType ),
aValue, aAddUnitLabel, aType );
}
wxString MessageTextFromValue( const EDA_ANGLE& aValue, bool aAddUnitLabel = true ) const
@ -134,9 +134,10 @@ public:
EDA_DATA_TYPE::DISTANCE );
}
wxString MessageTextFromMinOptMax( const MINOPTMAX<int>& aValue ) const
wxString MessageTextFromMinOptMax( const MINOPTMAX<int>& aValue,
EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE ) const
{
return EDA_UNIT_UTILS::UI::MessageTextFromMinOptMax( GetIuScale(), GetUserUnits(), aValue );
return EDA_UNIT_UTILS::UI::MessageTextFromMinOptMax( GetIuScale(), GetUnitsFromType( aType ), aValue );
};
/**
@ -151,8 +152,9 @@ public:
int ValueFromString( const wxString& aTextValue,
EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE ) const
{
double value = EDA_UNIT_UTILS::UI::DoubleValueFromString( GetIuScale(), GetUserUnits(),
aTextValue, aType );
double value = EDA_UNIT_UTILS::UI::DoubleValueFromString(
GetIuScale(), GetUnitsFromType( aType ), aTextValue, aType );
return KiROUND<double, int>( value );
}
@ -175,8 +177,8 @@ public:
if( aTextValue == NullUiString )
return {};
double value = EDA_UNIT_UTILS::UI::DoubleValueFromString( GetIuScale(), GetUserUnits(),
aTextValue, aType );
double value = EDA_UNIT_UTILS::UI::DoubleValueFromString(
GetIuScale(), GetUnitsFromType( aType ), aTextValue, aType );
return KiROUND<double, int>( value );
}
@ -189,6 +191,58 @@ public:
return EDA_ANGLE( angle, DEGREES_T );
}
/**
* Gets the units to use in the conversion based on the underlying user units
*/
EDA_UNITS GetUnitsFromType( EDA_DATA_TYPE aType ) const
{
// Get the unit type depending on the requested unit type and the underlying user setting
if( aType == EDA_DATA_TYPE::TIME )
{
return EDA_UNITS::PS;
}
else if( aType == EDA_DATA_TYPE::LENGTH_DELAY )
{
if( EDA_UNIT_UTILS::IsMetricUnit( GetUserUnits() ) )
return EDA_UNITS::PS_PER_CM;
else
return EDA_UNITS::PS_PER_INCH;
}
return GetUserUnits();
}
/**
* Gets the inferred type from the given units. Note: will always return the most simple
* type (e.g. a DISTANCE rather than AREA or VOLUME for a measurement unit).
*/
static EDA_DATA_TYPE GetTypeFromUnits( const EDA_UNITS aUnits )
{
switch( aUnits )
{
case EDA_UNITS::INCH:
case EDA_UNITS::MM:
case EDA_UNITS::UM:
case EDA_UNITS::CM:
case EDA_UNITS::MILS:
return EDA_DATA_TYPE::DISTANCE;
case EDA_UNITS::DEGREES:
case EDA_UNITS::PERCENT:
case EDA_UNITS::UNSCALED:
return EDA_DATA_TYPE::UNITLESS;
case EDA_UNITS::FS:
case EDA_UNITS::PS:
return EDA_DATA_TYPE::TIME;
case EDA_UNITS::PS_PER_INCH:
case EDA_UNITS::PS_PER_CM:
case EDA_UNITS::PS_PER_MM:
return EDA_DATA_TYPE::LENGTH_DELAY;
}
wxString msg = wxString::Format( wxT( "Unhandled unit data type %d" ), static_cast<int>( aUnits ) );
wxCHECK_MSG( false, EDA_DATA_TYPE::UNITLESS, msg );
}
/// @brief The string that is used in the UI to represent a null value
static inline const wxString NullUiString = "";

View File

@ -127,6 +127,16 @@ public:
void SetAutoEvalCols( const std::vector<int>& aCols ) { m_autoEvalCols = aCols; }
/**
* Set the unit and unit data type to use for a given column
*/
void SetAutoEvalColUnits( int col, EDA_UNITS aUnit, EDA_DATA_TYPE aUnitType );
/**
* Set the unit to use for a given column. The unit data type is inferred from the unit type
*/
void SetAutoEvalColUnits( int col, EDA_UNITS aUnit );
/**
* Apply standard KiCad unit and eval services to a numeric cell.
*
@ -250,12 +260,18 @@ protected:
void onDPIChanged(wxDPIChangedEvent& event);
/**
* Returns the units and data type associated with a given column
*/
std::pair<EDA_UNITS, EDA_DATA_TYPE> getColumnUnits( int aCol ) const;
protected:
bool m_weOwnTable;
std::map<int, UNITS_PROVIDER*> m_unitsProviders;
std::unique_ptr<NUMERIC_EVALUATOR> m_eval;
std::vector<int> m_autoEvalCols;
std::unordered_map<int, std::pair<EDA_UNITS, EDA_DATA_TYPE>> m_autoEvalColsUnits;
std::map< std::pair<int, int>, std::pair<wxString, wxString> > m_evalBeforeAfter;

View File

@ -201,6 +201,8 @@ set( PCBNEW_DIALOGS
dialogs/panel_setup_tracks_and_vias_base.cpp
dialogs/panel_setup_tuning_patterns.cpp
dialogs/panel_setup_tuning_patterns_base.cpp
dialogs/panel_setup_time_domain_parameters.cpp
dialogs/panel_setup_time_domain_parameters_base.cpp
footprint_wizard.cpp
footprint_wizard_frame.cpp
footprint_wizard_frame_functions.cpp

View File

@ -79,7 +79,7 @@ BOARD::BOARD() :
m_timeStamp( 1 ), m_paper( PAGE_INFO::A4 ), m_project( nullptr ), m_userUnits( EDA_UNITS::MM ),
m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ), m_NetInfo( this ),
m_embedFonts( false ), m_componentClassManager( std::make_unique<COMPONENT_CLASS_MANAGER>( this ) ),
m_lengthCalc( std::make_unique<LENGTH_CALCULATION>( this ) )
m_lengthDelayCalc( std::make_unique<LENGTH_DELAY_CALCULATION>( this ) )
{
// A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected
// A too large value do not allow safely connecting 2 shapes like very short segments.
@ -2141,6 +2141,12 @@ void BOARD::SynchronizeProperties()
}
void BOARD::SynchronizeTimeDomainProperties()
{
m_lengthDelayCalc->SynchronizeTimeDomainProperties();
}
void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes )
{
if( !m_project )
@ -2377,26 +2383,29 @@ BOARD_STACKUP BOARD::GetStackupOrDefault() const
}
std::tuple<int, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack ) const
std::tuple<int, double, double, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack ) const
{
auto connectivity = GetBoard()->GetConnectivity();
std::vector<LENGTH_CALCULATION_ITEM> items;
std::vector<LENGTH_DELAY_CALCULATION_ITEM> items;
for( BOARD_CONNECTED_ITEM* boardItem : connectivity->GetConnectedItems( &aTrack, EXCLUDE_ZONES ) )
{
LENGTH_CALCULATION_ITEM item = GetLengthCalculation()->GetLengthCalculationItem( boardItem );
LENGTH_DELAY_CALCULATION_ITEM item = GetLengthCalculation()->GetLengthCalculationItem( boardItem );
if( item.Type() != LENGTH_CALCULATION_ITEM::TYPE::UNKNOWN )
if( item.Type() != LENGTH_DELAY_CALCULATION_ITEM::TYPE::UNKNOWN )
items.push_back( item );
}
constexpr PATH_OPTIMISATIONS opts = {
.OptimiseViaLayers = true, .MergeTracks = true, .OptimiseTracesInPads = true, .InferViaInPad = false
};
LENGTH_DETAILS details = GetLengthCalculation()->CalculateLengthDetails( items, opts );
LENGTH_DELAY_STATS details = GetLengthCalculation()->CalculateLengthDetails(
items, opts, nullptr, nullptr, LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL,
LENGTH_DELAY_DOMAIN_OPT::WITH_DELAY_DETAIL );
return std::make_tuple( items.size(), details.TrackLength + details.ViaLength, details.PadToDieLength );
return std::make_tuple( items.size(), details.TrackLength + details.ViaLength, details.PadToDieLength,
details.TrackDelay + details.ViaDelay, details.PadToDieDelay );
}

View File

@ -33,7 +33,7 @@
#include <convert_shape_list_to_polygon.h> // for OUTLINE_ERROR_HANDLER
#include <hash.h>
#include <layer_ids.h>
#include <length_calculation.h>
#include <length_delay_calculation/length_delay_calculation.h>
#include <lset.h>
#include <netinfo.h>
#include <pcb_item_containers.h>
@ -1015,6 +1015,11 @@ public:
*/
void SynchronizeProperties();
/**
* Ensure that all time domain properties providers are in sync with current settings
*/
void SynchronizeTimeDomainProperties();
/**
* Return the Similarity. Because we compare board to board, we just return 1.0 here
*/
@ -1159,9 +1164,9 @@ public:
* This uses the connectivity data for the board to calculate connections
*
* @param aTrack Starting track (can also be a via) to check against for connection.
* @return a tuple containing <number, length, package length>
* @return a tuple containing <number, length, package length, delay, package delay>
*/
std::tuple<int, double, double> GetTrackLength( const PCB_TRACK& aTrack ) const;
std::tuple<int, double, double, double, double> GetTrackLength( const PCB_TRACK& aTrack ) const;
/**
* Collect all the TRACKs and VIAs that are members of a net given by aNetCode.
@ -1283,7 +1288,7 @@ public:
/**
* Returns the track length calculator
*/
LENGTH_CALCULATION* GetLengthCalculation() const { return m_lengthCalc.get(); }
LENGTH_DELAY_CALCULATION* GetLengthCalculation() const { return m_lengthDelayCalc.get(); }
/**
* Gets the component class manager
@ -1410,7 +1415,7 @@ private:
std::unique_ptr<COMPONENT_CLASS_MANAGER> m_componentClassManager;
std::unique_ptr<LENGTH_CALCULATION> m_lengthCalc;
std::unique_ptr<LENGTH_DELAY_CALCULATION> m_lengthDelayCalc;
};

View File

@ -38,6 +38,7 @@
#include <dialogs/panel_setup_tuning_patterns.h>
#include <dialogs/panel_setup_netclasses.h>
#include <dialogs/panel_assign_component_classes.h>
#include <dialogs/panel_setup_time_domain_parameters.h>
#include <panel_text_variables.h>
#include <project.h>
#include <project/project_file.h>
@ -48,6 +49,7 @@
#include "dialog_board_setup.h"
#include <advanced_config.h>
#include <footprint.h>
@ -60,6 +62,7 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
m_layers( nullptr ),
m_boardFinish( nullptr ),
m_physicalStackup( nullptr ),
m_timeDomainParameters( nullptr ),
m_currentPage( 0 ),
m_layersPage( 0 ),
m_physicalStackupPage( 0 ),
@ -73,7 +76,8 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
m_tuningPatternsPage( 0 ),
m_netclassesPage( 0 ),
m_customRulesPage( 0 ),
m_severitiesPage( 0 )
m_severitiesPage( 0 ),
m_timeDomainParametersPage( 0 )
{
SetEvtHandlerEnabled( false );
@ -199,42 +203,56 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
},
_( "Component Classes" ) );
m_customRulesPage = m_treebook->GetPageCount();
m_treebook->AddLazySubPage(
[this]( wxWindow* aParent ) -> wxWindow*
{
return new PANEL_SETUP_RULES( aParent, m_frame );
}, _( "Custom Rules" ) );
m_timeDomainParametersPage = m_treebook->GetPageCount();
m_treebook->AddLazySubPage(
[this]( wxWindow* aParent ) -> wxWindow*
{
BOARD* board = m_frame->GetBoard();
return new PANEL_SETUP_TIME_DOMAIN_PARAMETERS(
aParent, m_frame, board, m_frame->Prj().GetProjectFile().TimeDomainParameters() );
},
_( "Time Domain Parameters" ) );
m_severitiesPage = m_treebook->GetPageCount();
m_treebook->AddLazySubPage(
[this]( wxWindow* aParent ) -> wxWindow*
{
BOARD* board = m_frame->GetBoard();
return new PANEL_SETUP_SEVERITIES( aParent, DRC_ITEM::GetItemsWithSeverities(),
board->GetDesignSettings().m_DRCSeverities );
}, _( "Violation Severity" ) );
m_customRulesPage = m_treebook->GetPageCount();
m_treebook->AddLazySubPage(
[this]( wxWindow* aParent ) -> wxWindow*
{
return new PANEL_SETUP_RULES( aParent, m_frame );
},
_( "Custom Rules" ) );
m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Data" ) );
m_embeddedFilesPage = m_treebook->GetPageCount();
m_treebook->AddLazySubPage(
[this]( wxWindow* aParent ) -> wxWindow*
{
return new PANEL_EMBEDDED_FILES( aParent, m_frame->GetBoard() );
}, _( "Embedded Files" ) );
m_severitiesPage = m_treebook->GetPageCount();
m_treebook->AddLazySubPage(
[this]( wxWindow* aParent ) -> wxWindow*
{
BOARD* board = m_frame->GetBoard();
return new PANEL_SETUP_SEVERITIES( aParent, DRC_ITEM::GetItemsWithSeverities(),
board->GetDesignSettings().m_DRCSeverities );
},
_( "Violation Severity" ) );
for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
m_treebook->ExpandNode( i );
m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Data" ) );
m_embeddedFilesPage = m_treebook->GetPageCount();
m_treebook->AddLazySubPage(
[this]( wxWindow* aParent ) -> wxWindow*
{
return new PANEL_EMBEDDED_FILES( aParent, m_frame->GetBoard() );
},
_( "Embedded Files" ) );
SetEvtHandlerEnabled( true );
for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
m_treebook->ExpandNode( i );
finishDialogSettings();
SetEvtHandlerEnabled( true );
if( Prj().IsReadOnly() )
{
m_infoBar->ShowMessage( _( "Project is missing or read-only. Some settings will not "
"be editable." ), wxICON_WARNING );
}
finishDialogSettings();
if( Prj().IsReadOnly() )
{
m_infoBar->ShowMessage( _( "Project is missing or read-only. Some settings will not "
"be editable." ),
wxICON_WARNING );
}
wxBookCtrlEvent evt( wxEVT_TREEBOOK_PAGE_CHANGED, wxID_ANY, 0 );
@ -255,20 +273,41 @@ void DIALOG_BOARD_SETUP::onPageChanged( wxBookCtrlEvent& aEvent )
if( m_physicalStackupPage > 0 ) // Don't run this during initialization
{
if( m_currentPage == m_physicalStackupPage || page == m_physicalStackupPage )
if( m_currentPage == m_physicalStackupPage || m_currentPage == m_timeDomainParametersPage
|| page == m_physicalStackupPage || page == m_timeDomainParametersPage || page == m_netclassesPage )
{
m_layers = RESOLVE_PAGE( PANEL_SETUP_LAYERS, m_layersPage );
m_physicalStackup = RESOLVE_PAGE( PANEL_SETUP_BOARD_STACKUP, m_physicalStackupPage );
m_timeDomainParameters = RESOLVE_PAGE( PANEL_SETUP_TIME_DOMAIN_PARAMETERS, m_timeDomainParametersPage );
m_netClasses = RESOLVE_PAGE( PANEL_SETUP_NETCLASSES, m_netclassesPage );
}
// Ensure layer page always gets updated even if we aren't moving towards it
if( m_currentPage == m_physicalStackupPage )
{
m_layers->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
// Avoid calling SyncCopperLayers twice if moving from stackup to time domain directly
m_timeDomainParameters->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
}
if( page == m_physicalStackupPage )
{
m_physicalStackup->OnLayersOptionsChanged( m_layers->GetUILayerMask() );
else if( Prj().IsReadOnly() )
}
else if( page == m_netclassesPage || m_currentPage == m_timeDomainParametersPage )
{
m_netClasses->UpdateTuningProfileNames( m_timeDomainParameters->GetDelayProfileNames() );
}
else if( page == m_timeDomainParametersPage )
{
m_timeDomainParameters->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
}
if( Prj().IsReadOnly() )
{
KIUI::Disable( m_treebook->GetPage( page ) );
}
}
m_currentPage = page;
@ -437,6 +476,14 @@ void DIALOG_BOARD_SETUP::onAuxiliaryAction( wxCommandEvent& aEvent )
m_severitiesPage )->ImportSettingsFrom( otherSettings.m_DRCSeverities );
}
if( importDlg.m_TimeDomainParametersOpt->GetValue() )
{
PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
RESOLVE_PAGE( PANEL_SETUP_TIME_DOMAIN_PARAMETERS, m_timeDomainParametersPage )
->ImportSettingsFrom( otherProjectFile.TimeDomainParameters() );
}
if( otherPrj != &m_frame->Prj() )
otherBoard->ClearProject();
}

View File

@ -29,6 +29,7 @@ class PANEL_SETUP_CONSTRAINTS;
class PANEL_SETUP_LAYERS;
class PANEL_SETUP_TEXT_AND_GRAPHICS;
class PANEL_SETUP_NETCLASSES;
class PANEL_SETUP_TIME_DOMAIN_PARAMETERS;
class PANEL_SETUP_RULES;
class PANEL_SETUP_TRACKS_AND_VIAS;
class PANEL_SETUP_MASK_AND_PASTE;
@ -49,10 +50,12 @@ protected:
void onPageChanged( wxBookCtrlEvent& aEvent ) override;
void onAuxiliaryAction( wxCommandEvent& aEvent ) override;
PCB_EDIT_FRAME* m_frame;
PANEL_SETUP_LAYERS* m_layers;
PANEL_SETUP_BOARD_FINISH* m_boardFinish;
PANEL_SETUP_BOARD_STACKUP* m_physicalStackup;
PCB_EDIT_FRAME* m_frame;
PANEL_SETUP_LAYERS* m_layers;
PANEL_SETUP_BOARD_FINISH* m_boardFinish;
PANEL_SETUP_BOARD_STACKUP* m_physicalStackup;
PANEL_SETUP_TIME_DOMAIN_PARAMETERS* m_timeDomainParameters;
PANEL_SETUP_NETCLASSES* m_netClasses;
private:
size_t m_currentPage; // the current page index
@ -71,6 +74,7 @@ private:
size_t m_customRulesPage;
size_t m_severitiesPage;
size_t m_embeddedFilesPage;
size_t m_timeDomainParametersPage;
};

View File

@ -79,12 +79,12 @@ void DIALOG_IMPORT_SETTINGS::OnCheckboxClicked( wxCommandEvent& event )
bool DIALOG_IMPORT_SETTINGS::UpdateImportSettingsButton()
{
// Enable "Import Settings" button if at least one import option is selected
bool buttonEnableState = ( m_LayersOpt->IsChecked() || m_MaskAndPasteOpt->IsChecked()
|| m_ConstraintsOpt->IsChecked() || m_NetclassesOpt->IsChecked()
|| m_SeveritiesOpt->IsChecked() || m_TextAndGraphicsOpt->IsChecked()
|| m_FormattingOpt->IsChecked() || m_TracksAndViasOpt->IsChecked()
|| m_TuningPatternsOpt->IsChecked() || m_CustomRulesOpt->IsChecked()
|| m_ComponentClassesOpt->IsChecked() );
bool buttonEnableState =
( m_LayersOpt->IsChecked() || m_MaskAndPasteOpt->IsChecked() || m_ConstraintsOpt->IsChecked()
|| m_NetclassesOpt->IsChecked() || m_SeveritiesOpt->IsChecked() || m_TextAndGraphicsOpt->IsChecked()
|| m_FormattingOpt->IsChecked() || m_TracksAndViasOpt->IsChecked() || m_TuningPatternsOpt->IsChecked()
|| m_CustomRulesOpt->IsChecked() || m_ComponentClassesOpt->IsChecked()
|| m_TimeDomainParametersOpt->IsChecked() );
m_sdbSizer1OK->Enable( buttonEnableState );
@ -150,6 +150,7 @@ void DIALOG_IMPORT_SETTINGS::OnSelectAll( wxCommandEvent& event )
m_TeardropsOpt->SetValue( m_showSelectAllOnBtn );
m_TuningPatternsOpt->SetValue( m_showSelectAllOnBtn );
m_CustomRulesOpt->SetValue( m_showSelectAllOnBtn );
m_TimeDomainParametersOpt->SetValue( m_showSelectAllOnBtn );
// Ensure "Import Settings" button state is enabled as appropriate
UpdateImportSettingsButton();

View File

@ -78,6 +78,9 @@ DIALOG_IMPORT_SETTINGS_BASE::DIALOG_IMPORT_SETTINGS_BASE( wxWindow* parent, wxWi
m_ComponentClassesOpt = new wxCheckBox( this, wxID_ANY, _("Component classes"), wxDefaultPosition, wxDefaultSize, 0 );
bLeftCol->Add( m_ComponentClassesOpt, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
m_TimeDomainParametersOpt = new wxCheckBox( this, wxID_ANY, _("Time domain parameters"), wxDefaultPosition, wxDefaultSize, 0 );
bLeftCol->Add( m_TimeDomainParametersOpt, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
m_CustomRulesOpt = new wxCheckBox( this, wxID_ANY, _("Custom rules"), wxDefaultPosition, wxDefaultSize, 0 );
bLeftCol->Add( m_CustomRulesOpt, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
@ -124,6 +127,7 @@ DIALOG_IMPORT_SETTINGS_BASE::DIALOG_IMPORT_SETTINGS_BASE( wxWindow* parent, wxWi
m_TuningPatternsOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_NetclassesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_ComponentClassesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_TimeDomainParametersOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_CustomRulesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_SeveritiesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_selectAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnSelectAll ), NULL, this );
@ -141,6 +145,7 @@ DIALOG_IMPORT_SETTINGS_BASE::~DIALOG_IMPORT_SETTINGS_BASE()
m_TuningPatternsOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_NetclassesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_ComponentClassesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_TimeDomainParametersOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_CustomRulesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_SeveritiesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
m_selectAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnSelectAll ), NULL, this );

View File

@ -1015,6 +1015,72 @@
<event name="OnCheckBox">OnCheckboxClicked</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Time domain parameters</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_TimeDomainParametersOpt</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">public</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnCheckboxClicked</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>

View File

@ -65,6 +65,7 @@ class DIALOG_IMPORT_SETTINGS_BASE : public DIALOG_SHIM
wxCheckBox* m_TuningPatternsOpt;
wxCheckBox* m_NetclassesOpt;
wxCheckBox* m_ComponentClassesOpt;
wxCheckBox* m_TimeDomainParametersOpt;
wxCheckBox* m_CustomRulesOpt;
wxCheckBox* m_SeveritiesOpt;

View File

@ -117,10 +117,7 @@ void PCB_BASE_FRAME::ShowPadPropertiesDialog( PAD* aPad )
DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, PAD* aPad ) :
DIALOG_PAD_PROPERTIES_BASE( aParent ),
m_parent( aParent ),
m_initialized( false ),
m_editLayer( F_Cu ),
DIALOG_PAD_PROPERTIES_BASE( aParent ), m_parent( aParent ), m_initialized( false ), m_editLayer( F_Cu ),
m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits ),
@ -128,21 +125,19 @@ DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, PAD* aPad
m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits ),
m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits ),
m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits ),
m_padToDieDelay( aParent, m_padToDieDelayLabel, m_padToDieDelayCtrl, m_padToDieDelayUnits ),
m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits ),
m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
m_cornerRatio( aParent, m_cornerRatioLabel, m_cornerRatioCtrl, m_cornerRatioUnits ),
m_chamferRatio( aParent, m_chamferRatioLabel, m_chamferRatioCtrl, m_chamferRatioUnits ),
m_mixedCornerRatio( aParent, m_mixedCornerRatioLabel, m_mixedCornerRatioCtrl,
m_mixedCornerRatioUnits ),
m_mixedChamferRatio( aParent, m_mixedChamferRatioLabel, m_mixedChamferRatioCtrl,
m_mixedChamferRatioUnits ),
m_mixedCornerRatio( aParent, m_mixedCornerRatioLabel, m_mixedCornerRatioCtrl, m_mixedCornerRatioUnits ),
m_mixedChamferRatio( aParent, m_mixedChamferRatioLabel, m_mixedChamferRatioCtrl, m_mixedChamferRatioUnits ),
m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits ),
m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits ),
m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
m_maskMargin( aParent, m_maskMarginLabel, m_maskMarginCtrl, m_maskMarginUnits ),
m_pasteMargin( aParent, m_pasteMarginLabel, m_pasteMarginCtrl, m_pasteMarginUnits ),
m_pasteMarginRatio( aParent, m_pasteMarginRatioLabel, m_pasteMarginRatioCtrl,
m_pasteMarginRatioUnits ),
m_pasteMarginRatio( aParent, m_pasteMarginRatioLabel, m_pasteMarginRatioCtrl, m_pasteMarginRatioUnits ),
m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits ),
m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
m_spokeAngle( aParent, m_spokeAngleLabel, m_spokeAngleCtrl, m_spokeAngleUnits ),
@ -230,6 +225,8 @@ DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, PAD* aPad
m_pasteMarginRatio.SetUnits( EDA_UNITS::PERCENT );
m_pasteMarginRatio.SetNegativeZero();
m_padToDieDelay.SetUnits( EDA_UNITS::PS );
initValues();
wxFont infoFont = KIUI::GetInfoFont( this );
@ -652,6 +649,9 @@ void DIALOG_PAD_PROPERTIES::initValues()
m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 );
m_padToDie.ChangeValue( m_previewPad->GetPadToDieLength() );
m_padToDieDelayOpt->SetValue( m_previewPad->GetPadToDieDelay() != 0 );
m_padToDieDelay.ChangeValue( m_previewPad->GetPadToDieDelay() );
if( m_previewPad->GetLocalClearance().has_value() )
m_clearance.ChangeValue( m_previewPad->GetLocalClearance().value() );
else
@ -1147,6 +1147,7 @@ void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
m_padNumCtrl->ChangeValue( wxEmptyString );
m_padNetSelector->SetSelectedNetcode( 0 );
m_padToDieOpt->SetValue( false );
m_padToDieDelayOpt->SetValue( false );
}
else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
{
@ -1212,14 +1213,19 @@ void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
// Enable/disable pad length-to-die
m_padToDieOpt->Enable( hasConnection );
m_padToDieDelayOpt->Enable( hasConnection );
if( !m_padToDieOpt->IsEnabled() )
m_padToDieOpt->SetValue( false );
if( !m_padToDieDelayOpt->IsEnabled() )
m_padToDieDelayOpt->SetValue( false );
// We can show/hide this here because it doesn't require the layout to be refreshed.
// All the others have to be done in their event handlers because doing a layout here
// causes infinite looping on MSW.
m_padToDie.Show( m_padToDieOpt->GetValue() );
m_padToDieDelay.Show( m_padToDieDelayOpt->GetValue() );
// Enable/disable Copper Layers control
m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
@ -1574,6 +1580,7 @@ bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow()
m_currentPad->SetAttribute( m_masterPad->GetAttribute() );
m_currentPad->SetFPRelativeOrientation( m_masterPad->GetOrientation() );
m_currentPad->SetPadToDieLength( m_masterPad->GetPadToDieLength() );
m_currentPad->SetPadToDieDelay( m_masterPad->GetPadToDieDelay() );
m_currentPad->SetLayerSet( m_masterPad->GetLayerSet() );
m_currentPad->SetNumber( m_masterPad->GetNumber() );
@ -1839,6 +1846,11 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
else
aPad->SetPadToDieLength( 0 );
if( m_padToDieDelayOpt->GetValue() )
aPad->SetPadToDieDelay( m_padToDieDelay.GetIntValue() );
else
aPad->SetPadToDieDelay( 0 );
aPad->SetNumber( m_padNumCtrl->GetValue() );
aPad->SetNetCode( m_padNetSelector->GetSelectedNetcode() );
@ -2068,6 +2080,15 @@ void DIALOG_PAD_PROPERTIES::OnPadToDieCheckbox( wxCommandEvent& event )
}
void DIALOG_PAD_PROPERTIES::OnPadToDieDelayCheckbox( wxCommandEvent& event )
{
if( m_padToDieDelayOpt->GetValue() && m_currentPad )
m_padToDieDelay.SetValue( m_currentPad->GetPadToDieDelay() );
OnValuesChanged( event );
}
void DIALOG_PAD_PROPERTIES::onModify( wxSpinDoubleEvent& aEvent )
{
if( m_initialized )

View File

@ -88,6 +88,7 @@ private:
void onChangePadMode( wxCommandEvent& event ) override;
void OnOffsetCheckbox( wxCommandEvent& event ) override;
void OnPadToDieCheckbox( wxCommandEvent& event ) override;
void OnPadToDieDelayCheckbox( wxCommandEvent& event ) override;
void PadOrientEvent( wxCommandEvent& event ) override;
void PadTypeSelected( wxCommandEvent& event ) override;
@ -155,6 +156,7 @@ private:
UNIT_BINDER m_sizeX, m_sizeY;
UNIT_BINDER m_offsetX, m_offsetY;
UNIT_BINDER m_padToDie;
UNIT_BINDER m_padToDieDelay;
UNIT_BINDER m_trapDelta;
UNIT_BINDER m_cornerRadius;
UNIT_BINDER m_cornerRatio;

View File

@ -501,6 +501,26 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
m_padToDieUnits->Wrap( -1 );
fgSizerPadToDie->Add( m_padToDieUnits, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN|wxRIGHT, 5 );
wxBoxSizer* bSizer341;
bSizer341 = new wxBoxSizer( wxHORIZONTAL );
m_padToDieDelayOpt = new wxCheckBox( m_panelGeneral, wxID_ANY, _("Specify pad to die delay"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer341->Add( m_padToDieDelayOpt, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_padToDieDelayLabel = new wxStaticText( m_panelGeneral, wxID_ANY, _(":"), wxDefaultPosition, wxDefaultSize, 0 );
m_padToDieDelayLabel->Wrap( -1 );
bSizer341->Add( m_padToDieDelayLabel, 0, wxALIGN_CENTER_VERTICAL|wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
fgSizerPadToDie->Add( bSizer341, 1, wxEXPAND, 5 );
m_padToDieDelayCtrl = new wxTextCtrl( m_panelGeneral, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerPadToDie->Add( m_padToDieDelayCtrl, 0, wxEXPAND|wxLEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN|wxTOP, 5 );
m_padToDieDelayUnits = new wxStaticText( m_panelGeneral, wxID_ANY, _("ps"), wxDefaultPosition, wxDefaultSize, 0 );
m_padToDieDelayUnits->Wrap( -1 );
fgSizerPadToDie->Add( m_padToDieDelayUnits, 0, wxALL, 5 );
m_LeftBoxSizer->Add( fgSizerPadToDie, 0, wxEXPAND, 5 );
@ -1268,6 +1288,7 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
m_holeXCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_holeYCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_padToDieOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPadToDieCheckbox ), NULL, this );
m_padToDieDelayOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPadToDieDelayCheckbox ), NULL, this );
m_rbCopperLayersSel->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetCopperLayers ), NULL, this );
m_layerFrontAdhesive->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_layerBackAdhesive->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
@ -1355,6 +1376,7 @@ DIALOG_PAD_PROPERTIES_BASE::~DIALOG_PAD_PROPERTIES_BASE()
m_holeXCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_holeYCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnValuesChanged ), NULL, this );
m_padToDieOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPadToDieCheckbox ), NULL, this );
m_padToDieDelayOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPadToDieDelayCheckbox ), NULL, this );
m_rbCopperLayersSel->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetCopperLayers ), NULL, this );
m_layerFrontAdhesive->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );
m_layerBackAdhesive->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnSetLayers ), NULL, this );

View File

@ -5694,11 +5694,11 @@
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="false">
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxFlexGridSizer" expanded="false">
<object class="wxFlexGridSizer" expanded="true">
<property name="cols">3</property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1</property>
@ -5710,7 +5710,7 @@
<property name="permission">none</property>
<property name="rows">14</property>
<property name="vgap">0</property>
<object class="sizeritem" expanded="false">
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxRIGHT</property>
<property name="proportion">0</property>
@ -5976,6 +5976,272 @@
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="false">
<property name="minimum_size"></property>
<property name="name">bSizer341</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Specify pad to die delay</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_padToDieDelayOpt</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnPadToDieDelayCheckbox</event>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRESERVE_SPACE_EVEN_IF_HIDDEN</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_padToDieDelayLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxLEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN|wxTOP</property>
<property name="proportion">0</property>
<object class="wxTextCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_padToDieDelayCtrl</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">ps</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_padToDieDelayUnits</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</object>
</object>
</object>

View File

@ -147,6 +147,10 @@ class DIALOG_PAD_PROPERTIES_BASE : public DIALOG_SHIM
wxStaticText* m_padToDieLabel;
wxTextCtrl* m_padToDieCtrl;
wxStaticText* m_padToDieUnits;
wxCheckBox* m_padToDieDelayOpt;
wxStaticText* m_padToDieDelayLabel;
wxTextCtrl* m_padToDieDelayCtrl;
wxStaticText* m_padToDieDelayUnits;
wxBoxSizer* m_middleBoxSizer;
wxBoxSizer* m_FlippedWarningSizer;
wxStaticBitmap* m_FlippedWarningIcon;
@ -273,6 +277,7 @@ class DIALOG_PAD_PROPERTIES_BASE : public DIALOG_SHIM
virtual void OnOffsetCheckbox( wxCommandEvent& event ) { event.Skip(); }
virtual void OnDrillShapeSelected( wxCommandEvent& event ) { event.Skip(); }
virtual void OnPadToDieCheckbox( wxCommandEvent& event ) { event.Skip(); }
virtual void OnPadToDieDelayCheckbox( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSetCopperLayers( wxCommandEvent& event ) { event.Skip(); }
virtual void onModify( wxCommandEvent& event ) { event.Skip(); }
virtual void onTeardropsUpdateUi( wxUpdateUIEvent& event ) { event.Skip(); }

View File

@ -18,26 +18,27 @@
*/
#include "dialog_tuning_pattern_properties.h"
#include <advanced_config.h>
#include <bitmaps.h>
#include <pcb_base_edit_frame.h>
#include <board_design_settings.h>
#include <drc/drc_engine.h>
DIALOG_TUNING_PATTERN_PROPERTIES::DIALOG_TUNING_PATTERN_PROPERTIES( PCB_BASE_EDIT_FRAME* aFrame,
DIALOG_TUNING_PATTERN_PROPERTIES::DIALOG_TUNING_PATTERN_PROPERTIES( PCB_BASE_EDIT_FRAME* aFrame,
PNS::MEANDER_SETTINGS& aSettings,
PNS::ROUTER_MODE aMeanderType,
const DRC_CONSTRAINT& aConstraint ) :
DIALOG_TUNING_PATTERN_PROPERTIES_BASE( aFrame ),
m_constraint( aConstraint ),
PNS::ROUTER_MODE aMeanderType,
const DRC_CONSTRAINT& aConstraint ) :
DIALOG_TUNING_PATTERN_PROPERTIES_BASE( aFrame ), m_constraint( aConstraint ),
m_targetLength( aFrame, m_targetLengthLabel, m_targetLengthCtrl, m_targetLengthUnits ),
m_targetDelay( aFrame, m_targetDelayLabel, m_targetDelayCtrl, m_targetDelayUnits ),
m_minA( aFrame, m_track_minALabel, m_minACtrl, m_minAUnits ),
m_maxA( aFrame, m_maxALabel, m_maxACtrl, m_maxAUnits ),
m_spacing( aFrame, m_spacingLabel, m_spacingCtrl, m_spacingUnits ),
m_r( aFrame, m_rLabel, m_rCtrl, m_rUnits ),
m_settings( aSettings ),
m_mode( aMeanderType )
m_spacing( aFrame, m_spacingLabel, m_spacingCtrl, m_spacingUnits ), m_r( aFrame, m_rLabel, m_rCtrl, m_rUnits ),
m_settings( aSettings ), m_mode( aMeanderType )
{
m_targetDelay.SetUnits( EDA_UNITS::PS );
m_r.SetUnits( EDA_UNITS::PERCENT );
switch( m_mode )
@ -52,7 +53,8 @@ DIALOG_TUNING_PATTERN_PROPERTIES::DIALOG_TUNING_PATTERN_PROPERTIES( PCB_BASE_EDI
case PNS::PNS_MODE_TUNE_DIFF_PAIR_SKEW:
m_legend->SetBitmap( KiBitmapBundle( BITMAPS::tune_diff_pair_skew_legend ) );
m_targetLengthLabel->SetLabel( _( "Target skew: ") );
m_targetLengthLabel->SetLabel( _( "Target Skew: " ) );
m_targetDelayLabel->SetLabel( _( "Target Skew Delay: " ) );
break;
default:
@ -74,22 +76,54 @@ bool DIALOG_TUNING_PATTERN_PROPERTIES::TransferDataToWindow()
{
if( m_mode == PNS::PNS_MODE_TUNE_DIFF_PAIR_SKEW )
{
m_targetLength.SetValue( m_settings.m_targetSkew.Opt() );
if( m_targetLength.GetValue() == PNS::MEANDER_SETTINGS::SKEW_UNCONSTRAINED )
if( m_settings.m_isTimeDomain )
{
m_targetLength.SetValue( wxEmptyString );
m_targetDelay.SetValue( m_settings.m_targetSkewDelay.Opt() );
if( m_targetDelay.GetValue() == PNS::MEANDER_SETTINGS::SKEW_UNCONSTRAINED )
m_targetDelay.SetValue( wxEmptyString );
}
else
{
m_targetDelay.SetValue( wxEmptyString );
m_targetLength.SetValue( m_settings.m_targetSkew.Opt() );
if( m_targetLength.GetValue() == PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
m_targetLength.SetValue( wxEmptyString );
}
}
else
{
m_targetLength.SetValue( m_settings.m_targetLength.Opt() );
if( m_targetLength.GetValue() == PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
if( m_settings.m_isTimeDomain )
{
m_targetLength.SetValue( wxEmptyString );
m_targetDelay.SetValue( m_settings.m_targetLengthDelay.Opt() );
if( m_targetDelay.GetValue() == PNS::MEANDER_SETTINGS::DELAY_UNCONSTRAINED )
m_targetDelay.SetValue( wxEmptyString );
}
else
{
m_targetDelay.SetValue( wxEmptyString );
m_targetLength.SetValue( m_settings.m_targetLength.Opt() );
if( m_targetLength.GetValue() == PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
m_targetLength.SetValue( wxEmptyString );
}
}
m_overrideCustomRules->SetValue( m_settings.m_overrideCustomRules );
m_targetLength.Enable( m_constraint.IsNull() || m_settings.m_overrideCustomRules );
m_targetLength.Enable( ( m_constraint.IsNull() || m_settings.m_overrideCustomRules )
&& !m_settings.m_isTimeDomain );
m_targetDelay.Enable( ( m_constraint.IsNull() || m_settings.m_overrideCustomRules ) && m_settings.m_isTimeDomain );
m_radioBtnLength->Enable( m_constraint.IsNull() || m_settings.m_overrideCustomRules );
m_radioBtnDelay->Enable( m_constraint.IsNull() || m_settings.m_overrideCustomRules );
m_radioBtnLength->SetValue( !m_settings.m_isTimeDomain );
m_radioBtnDelay->SetValue( m_settings.m_isTimeDomain );
if( !m_constraint.IsNull() )
m_sourceInfo->SetLabel( wxString::Format( _( "(from %s)" ), m_constraint.GetName() ) );
@ -122,24 +156,52 @@ bool DIALOG_TUNING_PATTERN_PROPERTIES::TransferDataFromWindow()
m_settings.SetTargetSkew( lastTargetSkew );
else
m_settings.m_targetSkew = m_constraint.GetValue();
if( m_targetDelayCtrl->GetValue().IsEmpty() )
lastTargetSkew = PNS::MEANDER_SETTINGS::SKEW_UNCONSTRAINED;
else
lastTargetSkew = m_targetDelay.GetIntValue();
if( lastTargetSkew != m_constraint.GetValue().Opt() )
m_settings.SetTargetSkewDelay( lastTargetSkew );
else
m_settings.SetTargetSkewDelay( m_constraint.GetValue() );
}
else
{
long long int lastTargetLength = PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED;
long long int lastTarget = PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED;
if( m_targetLengthCtrl->GetValue().IsEmpty() )
lastTargetLength = PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED;
lastTarget = PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED;
else
lastTargetLength = m_targetLength.GetIntValue();
lastTarget = m_targetLength.GetIntValue();
if( lastTargetLength != m_constraint.GetValue().Opt() )
m_settings.SetTargetLength( lastTargetLength );
if( lastTarget != m_constraint.GetValue().Opt() )
m_settings.SetTargetLength( lastTarget );
else
m_settings.SetTargetLength( m_constraint.GetValue() );
if( m_targetDelayCtrl->GetValue().IsEmpty() )
lastTarget = PNS::MEANDER_SETTINGS::DELAY_UNCONSTRAINED;
else
lastTarget = m_targetDelay.GetIntValue();
if( lastTarget != m_constraint.GetValue().Opt() )
m_settings.SetTargetLengthDelay( lastTarget );
else
m_settings.SetTargetLengthDelay( m_constraint.GetValue() );
}
m_settings.m_overrideCustomRules = m_overrideCustomRules->GetValue();
if( m_radioBtnLength->IsEnabled() )
{
if( m_radioBtnLength->GetValue() )
m_settings.m_isTimeDomain = false;
else
m_settings.m_isTimeDomain = true;
}
m_settings.m_minAmplitude = m_minA.GetIntValue();
m_settings.m_maxAmplitude = m_maxA.GetIntValue();
m_settings.m_spacing = m_spacing.GetIntValue();
@ -154,11 +216,24 @@ bool DIALOG_TUNING_PATTERN_PROPERTIES::TransferDataFromWindow()
void DIALOG_TUNING_PATTERN_PROPERTIES::onOverrideCustomRules( wxCommandEvent& event )
{
m_targetLength.Enable( event.IsChecked() || m_constraint.IsNull() );
m_targetLength.Enable( ( event.IsChecked() || m_constraint.IsNull() ) && !m_settings.m_isTimeDomain );
m_targetDelay.Enable( ( event.IsChecked() || m_constraint.IsNull() ) && m_settings.m_isTimeDomain );
m_radioBtnLength->Enable( event.IsChecked() || m_constraint.IsNull() );
m_radioBtnDelay->Enable( event.IsChecked() || m_constraint.IsNull() );
if( !event.IsChecked() && !m_constraint.IsNull() )
{
m_targetLength.SetValue( m_constraint.GetValue().Opt() );
if( m_constraint.GetOption( DRC_CONSTRAINT::OPTIONS::SPACE_DOMAIN ) )
{
m_targetLength.SetValue( m_constraint.GetValue().Opt() );
m_targetDelay.SetValue( wxEmptyString );
}
else
{
m_targetLength.SetValue( wxEmptyString );
m_targetDelay.SetValue( m_constraint.GetValue().Opt() );
}
m_sourceInfo->Show( true );
}
else
@ -166,3 +241,23 @@ void DIALOG_TUNING_PATTERN_PROPERTIES::onOverrideCustomRules( wxCommandEvent& ev
m_sourceInfo->Show( false );
}
}
void DIALOG_TUNING_PATTERN_PROPERTIES::onRadioBtnTargetLengthClick( wxCommandEvent& event )
{
if( event.IsChecked() )
{
m_targetLength.Enable( true );
m_targetDelay.Enable( false );
}
}
void DIALOG_TUNING_PATTERN_PROPERTIES::onRadioBtnTargetDelayClick( wxCommandEvent& event )
{
if( event.IsChecked() )
{
m_targetLength.Enable( false );
m_targetDelay.Enable( true );
}
}

View File

@ -49,11 +49,14 @@ private:
bool TransferDataFromWindow() override;
void onOverrideCustomRules( wxCommandEvent& event ) override;
void onRadioBtnTargetLengthClick( wxCommandEvent& event ) override;
void onRadioBtnTargetDelayClick( wxCommandEvent& event ) override;
private:
const DRC_CONSTRAINT& m_constraint;
UNIT_BINDER m_targetLength;
UNIT_BINDER m_targetDelay;
UNIT_BINDER m_minA;
UNIT_BINDER m_maxA;
UNIT_BINDER m_spacing;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -28,9 +28,19 @@ DIALOG_TUNING_PATTERN_PROPERTIES_BASE::DIALOG_TUNING_PATTERN_PROPERTIES_BASE( wx
gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
gbSizer1->SetEmptyCellSize( wxSize( 10,8 ) );
m_targetLengthLabel = new wxStaticText( this, wxID_ANY, _("Target length:"), wxDefaultPosition, wxDefaultSize, 0 );
wxBoxSizer* bSizer3;
bSizer3 = new wxBoxSizer( wxHORIZONTAL );
m_radioBtnLength = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_radioBtnLength->SetValue( true );
bSizer3->Add( m_radioBtnLength, 0, wxALL, 5 );
m_targetLengthLabel = new wxStaticText( this, wxID_ANY, _("Target Length:"), wxDefaultPosition, wxDefaultSize, 0 );
m_targetLengthLabel->Wrap( -1 );
gbSizer1->Add( m_targetLengthLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
bSizer3->Add( m_targetLengthLabel, 0, wxALL, 5 );
gbSizer1->Add( bSizer3, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), 0, 5 );
m_targetLengthCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_targetLengthCtrl, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
@ -39,75 +49,95 @@ DIALOG_TUNING_PATTERN_PROPERTIES_BASE::DIALOG_TUNING_PATTERN_PROPERTIES_BASE( wx
m_targetLengthUnits->Wrap( -1 );
gbSizer1->Add( m_targetLengthUnits, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
wxBoxSizer* bSizer31;
bSizer31 = new wxBoxSizer( wxHORIZONTAL );
m_radioBtnDelay = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
bSizer31->Add( m_radioBtnDelay, 0, wxALL, 5 );
m_targetDelayLabel = new wxStaticText( this, wxID_ANY, _("Target Delay:"), wxDefaultPosition, wxDefaultSize, 0 );
m_targetDelayLabel->Wrap( -1 );
bSizer31->Add( m_targetDelayLabel, 0, wxALL, 5 );
gbSizer1->Add( bSizer31, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), 0, 5 );
m_targetDelayCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_targetDelayCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
m_targetDelayUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_targetDelayUnits->Wrap( -1 );
gbSizer1->Add( m_targetDelayUnits, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
m_overrideCustomRules = new wxCheckBox( this, wxID_ANY, _("Override custom rules"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_overrideCustomRules, wxGBPosition( 0, 4 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL, 5 );
m_sourceInfo = new wxStaticText( this, wxID_ANY, _("(from 'rule name')"), wxDefaultPosition, wxDefaultSize, 0 );
m_sourceInfo->Wrap( -1 );
gbSizer1->Add( m_sourceInfo, wxGBPosition( 1, 1 ), wxGBSpan( 1, 6 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_sourceInfo, wxGBPosition( 2, 1 ), wxGBSpan( 1, 6 ), wxALIGN_CENTER_VERTICAL, 5 );
m_track_minALabel = new wxStaticText( this, wxID_ANY, _("Minimum amplitude (A):"), wxDefaultPosition, wxDefaultSize, 0 );
m_track_minALabel->Wrap( -1 );
gbSizer1->Add( m_track_minALabel, wxGBPosition( 4, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 1 );
gbSizer1->Add( m_track_minALabel, wxGBPosition( 5, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 1 );
m_minACtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_minACtrl, wxGBPosition( 4, 1 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
gbSizer1->Add( m_minACtrl, wxGBPosition( 5, 1 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
m_minAUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_minAUnits->Wrap( -1 );
gbSizer1->Add( m_minAUnits, wxGBPosition( 4, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_minAUnits, wxGBPosition( 5, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
m_maxALabel = new wxStaticText( this, wxID_ANY, _("Maximum amplitude (A):"), wxDefaultPosition, wxDefaultSize, 0 );
m_maxALabel->Wrap( -1 );
gbSizer1->Add( m_maxALabel, wxGBPosition( 4, 4 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_maxALabel, wxGBPosition( 5, 4 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
m_maxACtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_maxACtrl, wxGBPosition( 4, 5 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
gbSizer1->Add( m_maxACtrl, wxGBPosition( 5, 5 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
m_maxAUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_maxAUnits->Wrap( -1 );
gbSizer1->Add( m_maxAUnits, wxGBPosition( 4, 6 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_maxAUnits, wxGBPosition( 5, 6 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
m_spacingLabel = new wxStaticText( this, wxID_ANY, _("Spacing (s):"), wxDefaultPosition, wxDefaultSize, 0 );
m_spacingLabel->Wrap( -1 );
gbSizer1->Add( m_spacingLabel, wxGBPosition( 5, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 1 );
gbSizer1->Add( m_spacingLabel, wxGBPosition( 6, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 1 );
m_spacingCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_spacingCtrl->SetToolTip( _("Minimum spacing between adjacent tuning segments. The resulting spacing may be greater based on design rules.") );
gbSizer1->Add( m_spacingCtrl, wxGBPosition( 5, 1 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
gbSizer1->Add( m_spacingCtrl, wxGBPosition( 6, 1 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
m_spacingUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_spacingUnits->Wrap( -1 );
gbSizer1->Add( m_spacingUnits, wxGBPosition( 5, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_spacingUnits, wxGBPosition( 6, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
m_cornerLabel = new wxStaticText( this, wxID_ANY, _("Corner style:"), wxDefaultPosition, wxDefaultSize, 0 );
m_cornerLabel->Wrap( -1 );
gbSizer1->Add( m_cornerLabel, wxGBPosition( 7, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 1 );
gbSizer1->Add( m_cornerLabel, wxGBPosition( 8, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 1 );
wxString m_cornerCtrlChoices[] = { _("Chamfer"), _("Fillet") };
int m_cornerCtrlNChoices = sizeof( m_cornerCtrlChoices ) / sizeof( wxString );
m_cornerCtrl = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_cornerCtrlNChoices, m_cornerCtrlChoices, 0 );
m_cornerCtrl->SetSelection( 0 );
gbSizer1->Add( m_cornerCtrl, wxGBPosition( 7, 1 ), wxGBSpan( 1, 2 ), wxEXPAND, 5 );
gbSizer1->Add( m_cornerCtrl, wxGBPosition( 8, 1 ), wxGBSpan( 1, 2 ), wxEXPAND, 5 );
m_rLabel = new wxStaticText( this, wxID_ANY, _("Radius (r):"), wxDefaultPosition, wxDefaultSize, 0 );
m_rLabel->Wrap( -1 );
gbSizer1->Add( m_rLabel, wxGBPosition( 7, 4 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_rLabel, wxGBPosition( 8, 4 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
m_rCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_rCtrl, wxGBPosition( 7, 5 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
gbSizer1->Add( m_rCtrl, wxGBPosition( 8, 5 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
m_rUnits = new wxStaticText( this, wxID_ANY, _("%"), wxDefaultPosition, wxDefaultSize, 0 );
m_rUnits->Wrap( -1 );
gbSizer1->Add( m_rUnits, wxGBPosition( 7, 6 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_rUnits, wxGBPosition( 8, 6 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
m_singleSided = new wxCheckBox( this, wxID_ANY, _("Single-sided"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_singleSided, wxGBPosition( 8, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_singleSided, wxGBPosition( 9, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->AddGrowableCol( 1 );
gbSizer1->AddGrowableCol( 4 );
gbSizer1->AddGrowableCol( 5 );
singleTrackSizer->Add( gbSizer1, 1, wxEXPAND, 5 );
@ -129,12 +159,16 @@ DIALOG_TUNING_PATTERN_PROPERTIES_BASE::DIALOG_TUNING_PATTERN_PROPERTIES_BASE( wx
bMainSizer->Fit( this );
// Connect Events
m_radioBtnLength->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_TUNING_PATTERN_PROPERTIES_BASE::onRadioBtnTargetLengthClick ), NULL, this );
m_radioBtnDelay->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_TUNING_PATTERN_PROPERTIES_BASE::onRadioBtnTargetDelayClick ), NULL, this );
m_overrideCustomRules->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_TUNING_PATTERN_PROPERTIES_BASE::onOverrideCustomRules ), NULL, this );
}
DIALOG_TUNING_PATTERN_PROPERTIES_BASE::~DIALOG_TUNING_PATTERN_PROPERTIES_BASE()
{
// Disconnect Events
m_radioBtnLength->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_TUNING_PATTERN_PROPERTIES_BASE::onRadioBtnTargetLengthClick ), NULL, this );
m_radioBtnDelay->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_TUNING_PATTERN_PROPERTIES_BASE::onRadioBtnTargetDelayClick ), NULL, this );
m_overrideCustomRules->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_TUNING_PATTERN_PROPERTIES_BASE::onOverrideCustomRules ), NULL, this );
}

View File

@ -1,34 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="17"/>
<FileVersion major="1" minor="18"/>
<object class="Project" expanded="true">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="cpp_class_decoration"></property>
<property name="cpp_disconnect_events">1</property>
<property name="cpp_event_generation">connect</property>
<property name="cpp_help_provider">none</property>
<property name="cpp_namespace"></property>
<property name="cpp_precompiled_header"></property>
<property name="cpp_use_array_enum">0</property>
<property name="cpp_use_enum">0</property>
<property name="embedded_files_path"></property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">dialog_tuning_pattern_properties_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="lua_skip_events">1</property>
<property name="lua_ui_table">UI</property>
<property name="name">DIALOG_TUNING_PATTERN_PROPERTIES_BASE</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="php_disconnect_events">0</property>
<property name="php_disconnect_mode">source_name</property>
<property name="php_skip_events">1</property>
<property name="python_disconnect_events">0</property>
<property name="python_disconnect_mode">source_name</property>
<property name="python_image_path_wrapper_function_name"></property>
<property name="python_indent_with_spaces"></property>
<property name="python_skip_events">1</property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<property name="use_native_eol">0</property>
<object class="Dialog" expanded="true">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
@ -80,10 +82,10 @@
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap">Load From Resource; </property>
@ -137,7 +139,7 @@
<object class="wxGridBagSizer" expanded="true">
<property name="empty_cell_size">10,8</property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1,4</property>
<property name="growablecols">1,5</property>
<property name="growablerows"></property>
<property name="hgap">4</property>
<property name="minimum_size"></property>
@ -149,65 +151,142 @@
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="flag"></property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Target length:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_targetLengthLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
<property name="name">bSizer3</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label"></property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_radioBtnLength</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">1</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnRadioButton">onRadioBtnTargetLengthClick</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Target Length:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_targetLengthLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</object>
</object>
<object class="gbsizeritem" expanded="true">
@ -222,10 +301,10 @@
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -249,7 +328,7 @@
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
@ -290,10 +369,10 @@
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -343,6 +422,281 @@
<property name="wrap">-1</property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag"></property>
<property name="row">1</property>
<property name="rowspan">1</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bSizer31</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label"></property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_radioBtnDelay</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnRadioButton">onRadioBtnTargetDelayClick</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Target Delay:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_targetDelayLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxEXPAND</property>
<property name="row">1</property>
<property name="rowspan">1</property>
<object class="wxTextCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_targetDelayCtrl</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">2</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">1</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">unit</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_targetDelayUnits</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">3</property>
@ -355,10 +709,10 @@
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -417,17 +771,17 @@
<property name="colspan">6</property>
<property name="column">1</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">1</property>
<property name="row">2</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -482,17 +836,17 @@
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
<property name="row">4</property>
<property name="row">5</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -547,17 +901,17 @@
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxEXPAND</property>
<property name="row">4</property>
<property name="row">5</property>
<property name="rowspan">1</property>
<object class="wxTextCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -581,7 +935,7 @@
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
@ -615,17 +969,17 @@
<property name="colspan">1</property>
<property name="column">2</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">4</property>
<property name="row">5</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -680,17 +1034,17 @@
<property name="colspan">1</property>
<property name="column">4</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">4</property>
<property name="row">5</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -745,17 +1099,17 @@
<property name="colspan">1</property>
<property name="column">5</property>
<property name="flag">wxEXPAND</property>
<property name="row">4</property>
<property name="row">5</property>
<property name="rowspan">1</property>
<object class="wxTextCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -779,7 +1133,7 @@
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
@ -813,17 +1167,17 @@
<property name="colspan">1</property>
<property name="column">6</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">4</property>
<property name="row">5</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -878,17 +1232,17 @@
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
<property name="row">5</property>
<property name="row">6</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -943,17 +1297,17 @@
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxEXPAND</property>
<property name="row">5</property>
<property name="row">6</property>
<property name="rowspan">1</property>
<object class="wxTextCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -977,7 +1331,7 @@
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
@ -1011,17 +1365,17 @@
<property name="colspan">1</property>
<property name="column">2</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">5</property>
<property name="row">6</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -1076,17 +1430,17 @@
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
<property name="row">7</property>
<property name="row">8</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -1141,17 +1495,17 @@
<property name="colspan">2</property>
<property name="column">1</property>
<property name="flag">wxEXPAND</property>
<property name="row">7</property>
<property name="row">8</property>
<property name="rowspan">1</property>
<object class="wxChoice" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -1209,17 +1563,17 @@
<property name="colspan">1</property>
<property name="column">4</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">7</property>
<property name="row">8</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -1274,17 +1628,17 @@
<property name="colspan">1</property>
<property name="column">5</property>
<property name="flag">wxEXPAND</property>
<property name="row">7</property>
<property name="row">8</property>
<property name="rowspan">1</property>
<object class="wxTextCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -1308,7 +1662,7 @@
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
@ -1342,17 +1696,17 @@
<property name="colspan">1</property>
<property name="column">6</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">7</property>
<property name="row">8</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
@ -1407,17 +1761,17 @@
<property name="colspan">2</property>
<property name="column">1</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">8</property>
<property name="row">9</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -20,18 +20,18 @@
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/radiobut.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <wx/textctrl.h>
#include <wx/checkbox.h>
#include <wx/choice.h>
#include <wx/gbsizer.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_TUNING_PATTERN_PROPERTIES_BASE
///////////////////////////////////////////////////////////////////////////////
@ -41,9 +41,14 @@ class DIALOG_TUNING_PATTERN_PROPERTIES_BASE : public DIALOG_SHIM
protected:
wxStaticBitmap* m_legend;
wxRadioButton* m_radioBtnLength;
wxStaticText* m_targetLengthLabel;
wxTextCtrl* m_targetLengthCtrl;
wxStaticText* m_targetLengthUnits;
wxRadioButton* m_radioBtnDelay;
wxStaticText* m_targetDelayLabel;
wxTextCtrl* m_targetDelayCtrl;
wxStaticText* m_targetDelayUnits;
wxCheckBox* m_overrideCustomRules;
wxStaticText* m_sourceInfo;
wxStaticText* m_track_minALabel;
@ -66,6 +71,8 @@ class DIALOG_TUNING_PATTERN_PROPERTIES_BASE : public DIALOG_SHIM
wxButton* m_stdButtonsCancel;
// Virtual event handlers, override them in your derived class
virtual void onRadioBtnTargetLengthClick( wxCommandEvent& event ) { event.Skip(); }
virtual void onRadioBtnTargetDelayClick( wxCommandEvent& event ) { event.Skip(); }
virtual void onOverrideCustomRules( wxCommandEvent& event ) { event.Skip(); }

View File

@ -0,0 +1,634 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program 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.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <widgets/wx_panel.h>
#include <widgets/std_bitmap_button.h>
#include <bitmaps.h>
#include <dialogs/panel_setup_time_domain_parameters.h>
#include <pcb_edit_frame.h>
#include <grid_tricks.h>
#include <layer_ids.h>
#include <pgm_base.h>
#include <widgets/grid_icon_text_helpers.h>
#include <widgets/paged_dialog.h>
PANEL_SETUP_TIME_DOMAIN_PARAMETERS::PANEL_SETUP_TIME_DOMAIN_PARAMETERS(
wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame, BOARD* aBoard,
std::shared_ptr<TIME_DOMAIN_PARAMETERS> aTimeDomainParameters ) :
PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE( aParentWindow ),
m_timeDomainParameters( std::move( aTimeDomainParameters ) ), m_frame( aFrame ), m_board( aFrame->GetBoard() )
{
m_timeDomainParametersPane->SetBorders( true, false, false, false );
// Set up units
m_unitsProvider = std::make_unique<UNITS_PROVIDER>( pcbIUScale, m_frame->GetUserUnits() );
m_tracePropagationGrid->SetUnitsProvider( m_unitsProvider.get() );
m_viaPropagationGrid->SetUnitsProvider( m_unitsProvider.get() );
Freeze();
m_splitter->SetMinimumPaneSize( FromDIP( m_splitter->GetMinimumPaneSize() ) );
// Set up the tuning profiles grid
m_tracePropagationGrid->BeginBatch();
m_tracePropagationGrid->SetUseNativeColLabels();
m_tracePropagationGrid->EnsureColLabelsVisible();
m_tracePropagationGrid->SetDefaultRowSize( m_tracePropagationGrid->GetDefaultRowSize() + 4 );
m_tracePropagationGrid->PushEventHandler( new GRID_TRICKS( m_tracePropagationGrid ) );
m_tracePropagationGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
m_addDelayProfileButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
m_removeDelayProfileButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
m_tracePropagationGrid->EndBatch();
m_tracePropagationGrid->Connect(
wxEVT_GRID_CELL_CHANGING,
wxGridEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnDelayProfileGridCellChanging ), nullptr, this );
// Set up the via override grid
m_viaPropagationGrid->BeginBatch();
m_viaPropagationGrid->SetUseNativeColLabels();
m_viaPropagationGrid->EnsureColLabelsVisible();
m_viaPropagationGrid->SetDefaultRowSize( m_viaPropagationGrid->GetDefaultRowSize() + 4 );
m_viaPropagationGrid->PushEventHandler( new GRID_TRICKS( m_viaPropagationGrid ) );
m_viaPropagationGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
std::vector<int> viaColIds;
m_viaPropagationGrid->SetAutoEvalColUnits( VIA_GRID_DELAY,
m_unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::TIME ) );
viaColIds.push_back( VIA_GRID_DELAY );
m_viaPropagationGrid->SetAutoEvalCols( viaColIds );
m_viaPropagationGrid->EndBatch();
m_addViaOverrideButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
m_removeViaOverrideButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
setColumnWidths();
Thaw();
}
PANEL_SETUP_TIME_DOMAIN_PARAMETERS::~PANEL_SETUP_TIME_DOMAIN_PARAMETERS()
{
// Delete the GRID_TRICKS
m_tracePropagationGrid->PopEventHandler( true );
m_viaPropagationGrid->PopEventHandler( true );
m_tracePropagationGrid->Disconnect(
wxEVT_GRID_CELL_CHANGING,
wxGridEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnDelayProfileGridCellChanging ), nullptr, this );
}
bool PANEL_SETUP_TIME_DOMAIN_PARAMETERS::TransferDataToWindow()
{
m_tracePropagationGrid->ClearRows();
m_viaPropagationGrid->ClearRows();
const std::vector<TIME_DOMAIN_TUNING_PROFILE>& delayProfiles = m_timeDomainParameters->GetDelayProfiles();
SyncCopperLayers( m_board->GetCopperLayerCount() );
for( const TIME_DOMAIN_TUNING_PROFILE& profile : delayProfiles )
{
addProfileRow( profile );
for( const TUNING_PROFILE_VIA_OVERRIDE_ENTRY& viaOverride : profile.m_ViaOverrides )
addViaRow( profile.m_ProfileName, viaOverride );
}
updateViaProfileNamesEditor();
return true;
}
bool PANEL_SETUP_TIME_DOMAIN_PARAMETERS::TransferDataFromWindow()
{
if( !Validate() )
return false;
m_timeDomainParameters->ClearDelayProfiles();
for( int i = 0; i < m_tracePropagationGrid->GetNumberRows(); ++i )
{
TIME_DOMAIN_TUNING_PROFILE profile = getProfileRow( i );
wxString profileName = profile.m_ProfileName;
for( int j = 0; j < m_viaPropagationGrid->GetNumberRows(); ++j )
{
if( m_viaPropagationGrid->GetCellValue( j, VIA_GRID_PROFILE_NAME ) == profileName )
profile.m_ViaOverrides.emplace_back( getViaRow( j ) );
}
m_timeDomainParameters->AddDelayProfile( std::move( profile ) );
}
return true;
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::addProfileRow( const TIME_DOMAIN_TUNING_PROFILE& aDelayProfile )
{
const int rowId = m_tracePropagationGrid->GetNumberRows();
m_tracePropagationGrid->AppendRows();
m_tracePropagationGrid->SetCellValue( rowId, PROFILE_GRID_PROFILE_NAME, aDelayProfile.m_ProfileName );
m_tracePropagationGrid->SetUnitValue( rowId, PROFILE_GRID_VIA_PROP_DELAY, aDelayProfile.m_ViaPropagationDelay );
for( const auto& [layerId, velocity] : aDelayProfile.m_LayerPropagationDelays )
{
if( !m_copperLayerIdsToColumns.contains( layerId ) )
continue;
int col = m_copperLayerIdsToColumns[layerId];
if( col < m_tracePropagationGrid->GetNumberCols() )
{
m_tracePropagationGrid->SetUnitValue( rowId, col, velocity );
}
}
}
TIME_DOMAIN_TUNING_PROFILE PANEL_SETUP_TIME_DOMAIN_PARAMETERS::getProfileRow( const int aRow )
{
TIME_DOMAIN_TUNING_PROFILE entry;
entry.m_ProfileName = m_tracePropagationGrid->GetCellValue( aRow, PROFILE_GRID_PROFILE_NAME );
entry.m_ViaPropagationDelay = m_tracePropagationGrid->GetUnitValue( aRow, PROFILE_GRID_VIA_PROP_DELAY );
std::map<PCB_LAYER_ID, int> propDelays;
for( const auto& [layer, col] : m_copperLayerIdsToColumns )
propDelays[layer] = m_tracePropagationGrid->GetUnitValue( aRow, col );
entry.m_LayerPropagationDelays = std::move( propDelays );
return entry;
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::addViaRow( const wxString& aProfileName,
const TUNING_PROFILE_VIA_OVERRIDE_ENTRY& aViaOverrideEntry ) const
{
const int rowId = m_viaPropagationGrid->GetNumberRows();
m_viaPropagationGrid->AppendRows();
m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_PROFILE_NAME, aProfileName );
m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_SIGNAL_LAYER_FROM,
m_board->GetLayerName( aViaOverrideEntry.m_SignalLayerFrom ) );
m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_SIGNAL_LAYER_TO,
m_board->GetLayerName( aViaOverrideEntry.m_SignalLayerTo ) );
m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_VIA_LAYER_FROM,
m_board->GetLayerName( aViaOverrideEntry.m_ViaLayerFrom ) );
m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_VIA_LAYER_TO,
m_board->GetLayerName( aViaOverrideEntry.m_ViaLayerTo ) );
m_viaPropagationGrid->SetUnitValue( rowId, VIA_GRID_DELAY, aViaOverrideEntry.m_Delay );
}
TUNING_PROFILE_VIA_OVERRIDE_ENTRY PANEL_SETUP_TIME_DOMAIN_PARAMETERS::getViaRow( const int aRow )
{
// Get layer info
const wxString signalLayerFrom = m_viaPropagationGrid->GetCellValue( aRow, VIA_GRID_SIGNAL_LAYER_FROM );
const wxString signalLayerTo = m_viaPropagationGrid->GetCellValue( aRow, VIA_GRID_SIGNAL_LAYER_TO );
const wxString viaLayerFrom = m_viaPropagationGrid->GetCellValue( aRow, VIA_GRID_VIA_LAYER_FROM );
const wxString viaLayerTo = m_viaPropagationGrid->GetCellValue( aRow, VIA_GRID_VIA_LAYER_TO );
PCB_LAYER_ID signalLayerIdFrom = m_layerNamesToIDs[signalLayerFrom];
PCB_LAYER_ID signalLayerIdTo = m_layerNamesToIDs[signalLayerTo];
PCB_LAYER_ID viaLayerIdFrom = m_layerNamesToIDs[viaLayerFrom];
PCB_LAYER_ID viaLayerIdTo = m_layerNamesToIDs[viaLayerTo];
// Order layers in stackup order (from F_Cu first)
if( signalLayerIdTo != B_Cu && ( signalLayerIdTo < signalLayerIdFrom || signalLayerIdFrom == B_Cu ) )
std::swap( signalLayerIdFrom, signalLayerIdTo );
if( viaLayerIdTo != B_Cu && ( viaLayerIdTo < viaLayerIdFrom || viaLayerIdFrom == B_Cu ) )
std::swap( viaLayerIdFrom, viaLayerIdTo );
const TUNING_PROFILE_VIA_OVERRIDE_ENTRY entry{ signalLayerIdFrom, signalLayerIdTo, viaLayerIdFrom, viaLayerIdTo,
m_viaPropagationGrid->GetUnitValue( aRow, VIA_GRID_DELAY ) };
return entry;
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::SyncCopperLayers( int aNumCopperLayers )
{
m_prevLayerNamesToIDs = m_layerNamesToIDs;
m_copperLayerIdsToColumns.clear();
m_copperColumnsToLayerId.clear();
m_layerNames.clear();
m_layerNamesToIDs.clear();
int colIdx = PROFILE_GRID_NUM_REQUIRED_COLS;
for( const auto& layer : LSET::AllCuMask( aNumCopperLayers ).CuStack() )
{
wxString layerName = m_board->GetLayerName( layer );
m_layerNames.emplace_back( layerName );
m_layerNamesToIDs[layerName] = layer;
m_copperLayerIdsToColumns[layer] = colIdx;
m_copperColumnsToLayerId[colIdx] = layer;
++colIdx;
}
updateProfileGridColumns();
updateViaGridColumns();
setColumnWidths();
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::setColumnWidths()
{
const int minValueWidth = m_tracePropagationGrid->GetTextExtent( wxT( "000.00 ps/mm" ) ).x;
const int minNameWidth = m_tracePropagationGrid->GetTextExtent( wxT( "MMMMMMMMMMMM" ) ).x;
for( int i = 0; i < m_tracePropagationGrid->GetNumberCols(); ++i )
{
const int titleSize = m_tracePropagationGrid->GetTextExtent( m_tracePropagationGrid->GetColLabelValue( i ) ).x;
if( i == PROFILE_GRID_PROFILE_NAME )
m_tracePropagationGrid->SetColSize( i, std::max( titleSize, minNameWidth ) );
else
m_tracePropagationGrid->SetColSize( i, std::max( titleSize, minValueWidth ) );
}
for( int i = 0; i < m_viaPropagationGrid->GetNumberCols(); ++i )
{
const int titleSize = GetTextExtent( m_viaPropagationGrid->GetColLabelValue( i ) ).x;
if( i == VIA_GRID_PROFILE_NAME )
m_viaPropagationGrid->SetColSize( i, std::max( titleSize, minNameWidth ) );
else
m_viaPropagationGrid->SetColSize( i, titleSize + 30 );
}
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::updateProfileGridColumns()
{
const int newCopperLayers = static_cast<int>( m_copperLayerIdsToColumns.size() );
const int curCopperLayers = m_tracePropagationGrid->GetNumberCols() - PROFILE_GRID_NUM_REQUIRED_COLS;
if( newCopperLayers < curCopperLayers )
{
// TODO: WARN OF DELETING DATA?
m_tracePropagationGrid->DeleteCols( curCopperLayers - newCopperLayers + PROFILE_GRID_NUM_REQUIRED_COLS,
curCopperLayers - newCopperLayers );
}
else if( newCopperLayers > curCopperLayers )
{
m_tracePropagationGrid->AppendCols( newCopperLayers - curCopperLayers );
}
std::vector<int> copperColIds;
m_tracePropagationGrid->SetAutoEvalColUnits( PROFILE_GRID_VIA_PROP_DELAY,
m_unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::LENGTH_DELAY ) );
copperColIds.push_back( PROFILE_GRID_VIA_PROP_DELAY );
for( const auto& [colIdx, layerId] : m_copperColumnsToLayerId )
{
m_tracePropagationGrid->SetColLabelValue( colIdx, m_board->GetLayerName( layerId ) );
m_tracePropagationGrid->SetAutoEvalColUnits( colIdx,
m_unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::LENGTH_DELAY ) );
copperColIds.push_back( colIdx );
}
m_tracePropagationGrid->SetAutoEvalCols( copperColIds );
m_tracePropagationGrid->EnsureColLabelsVisible();
m_tracePropagationGrid->Refresh();
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::updateViaGridColumns()
{
wxArrayString layerNames;
std::ranges::for_each( m_layerNames,
[&layerNames]( const wxString& aLayerName )
{
layerNames.push_back( aLayerName );
} );
// Save the current data
std::vector<wxString> currentSignalLayersFrom;
std::vector<wxString> currentSignalLayersTo;
std::vector<wxString> currentViaLayersFrom;
std::vector<wxString> currentViaLayersTo;
for( int row = 0; row < m_viaPropagationGrid->GetNumberRows(); ++row )
{
currentSignalLayersFrom.emplace_back( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM ) );
currentSignalLayersTo.emplace_back( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO ) );
currentViaLayersFrom.emplace_back( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_VIA_LAYER_FROM ) );
currentViaLayersTo.emplace_back( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_VIA_LAYER_TO ) );
}
// Reset the via layers lists
wxGridCellAttr* attr = new wxGridCellAttr;
attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) );
m_viaPropagationGrid->SetColAttr( VIA_GRID_SIGNAL_LAYER_FROM, attr );
attr = new wxGridCellAttr;
attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) );
m_viaPropagationGrid->SetColAttr( VIA_GRID_SIGNAL_LAYER_TO, attr );
attr = new wxGridCellAttr;
attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) );
m_viaPropagationGrid->SetColAttr( VIA_GRID_VIA_LAYER_FROM, attr );
attr = new wxGridCellAttr;
attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) );
m_viaPropagationGrid->SetColAttr( VIA_GRID_VIA_LAYER_TO, attr );
// Restore the data, changing or resetting layer names if required
for( int row = 0; row < m_viaPropagationGrid->GetNumberRows(); ++row )
{
const PCB_LAYER_ID lastSignalFromId = m_prevLayerNamesToIDs[currentSignalLayersFrom[row]];
if( m_copperLayerIdsToColumns.contains( lastSignalFromId ) )
m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM,
m_board->GetLayerName( lastSignalFromId ) );
else
m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM, m_layerNames.front() );
const PCB_LAYER_ID lastSignalToId = m_prevLayerNamesToIDs[currentSignalLayersTo[row]];
if( m_copperLayerIdsToColumns.contains( lastSignalToId ) )
m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO,
m_board->GetLayerName( lastSignalToId ) );
else
m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO, m_layerNames.back() );
const PCB_LAYER_ID lastViaFromId = m_prevLayerNamesToIDs[currentViaLayersFrom[row]];
if( m_copperLayerIdsToColumns.contains( lastViaFromId ) )
m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_FROM, m_board->GetLayerName( lastViaFromId ) );
else
m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_FROM, m_layerNames.front() );
const PCB_LAYER_ID lastViaToId = m_prevLayerNamesToIDs[currentViaLayersTo[row]];
if( m_copperLayerIdsToColumns.contains( lastViaToId ) )
m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_TO, m_board->GetLayerName( lastViaToId ) );
else
m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_TO, m_layerNames.back() );
}
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnAddDelayProfileClick( wxCommandEvent& event )
{
if( !m_tracePropagationGrid->CommitPendingChanges() )
return;
const int rowId = m_tracePropagationGrid->GetNumberRows();
m_tracePropagationGrid->AppendRows();
m_tracePropagationGrid->SetCellValue( rowId, PROFILE_GRID_PROFILE_NAME, "" );
for( int i = PROFILE_GRID_VIA_PROP_DELAY; i < m_tracePropagationGrid->GetNumberCols(); ++i )
m_tracePropagationGrid->SetUnitValue( rowId, i, 0 );
const int newRow = m_tracePropagationGrid->GetNumberRows() - 1;
m_tracePropagationGrid->MakeCellVisible( newRow, PROFILE_GRID_PROFILE_NAME );
m_tracePropagationGrid->SetGridCursor( newRow, PROFILE_GRID_PROFILE_NAME );
m_tracePropagationGrid->EnableCellEditControl( true );
m_tracePropagationGrid->ShowCellEditControl();
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnRemoveDelayProfileClick( wxCommandEvent& event )
{
if( !m_tracePropagationGrid->CommitPendingChanges() )
return;
const int curRow = m_tracePropagationGrid->GetGridCursorRow();
if( curRow < 0 )
return;
wxString profileName = m_tracePropagationGrid->GetCellValue( curRow, PROFILE_GRID_PROFILE_NAME );
profileName.Trim( true );
profileName.Trim( false );
// Delete associated via overrides
for( int viaRow = m_viaPropagationGrid->GetNumberRows() - 1; viaRow >= 0; --viaRow )
{
if( m_viaPropagationGrid->GetCellValue( viaRow, VIA_GRID_PROFILE_NAME ) == profileName )
m_viaPropagationGrid->DeleteRows( viaRow, 1 );
}
// Delete tuning profile
m_tracePropagationGrid->DeleteRows( curRow, 1 );
m_tracePropagationGrid->MakeCellVisible( std::max( 0, curRow - 1 ),
m_tracePropagationGrid->GetGridCursorCol() );
m_tracePropagationGrid->SetGridCursor( std::max( 0, curRow - 1 ),
m_tracePropagationGrid->GetGridCursorCol() );
updateViaProfileNamesEditor();
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnAddViaOverrideClick( wxCommandEvent& event )
{
if( !m_viaPropagationGrid->CommitPendingChanges() )
return;
const int rowId = m_viaPropagationGrid->GetNumberRows();
m_viaPropagationGrid->AppendRows();
m_viaPropagationGrid->SetCellValue( rowId, PROFILE_GRID_PROFILE_NAME, "" );
m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_SIGNAL_LAYER_FROM, m_layerNames.front() );
m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_SIGNAL_LAYER_TO, m_layerNames.back() );
m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_VIA_LAYER_FROM, m_layerNames.front() );
m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_VIA_LAYER_TO, m_layerNames.back() );
m_viaPropagationGrid->SetUnitValue( rowId, VIA_GRID_DELAY, 0 );
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnRemoveViaOverrideClick( wxCommandEvent& event )
{
if( !m_viaPropagationGrid->CommitPendingChanges() )
return;
int curRow = m_viaPropagationGrid->GetGridCursorRow();
if( curRow < 0 )
return;
m_viaPropagationGrid->DeleteRows( curRow, 1 );
m_viaPropagationGrid->MakeCellVisible( std::max( 0, curRow - 1 ), m_viaPropagationGrid->GetGridCursorCol() );
m_viaPropagationGrid->SetGridCursor( std::max( 0, curRow - 1 ), m_viaPropagationGrid->GetGridCursorCol() );
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnDelayProfileGridCellChanging( wxGridEvent& event )
{
if( event.GetCol() == PROFILE_GRID_PROFILE_NAME )
{
if( validateDelayProfileName( event.GetRow(), event.GetString() ) )
{
const wxString oldName = m_tracePropagationGrid->GetCellValue( event.GetRow(), PROFILE_GRID_PROFILE_NAME );
const wxString newName = event.GetString();
if( !oldName.IsEmpty() )
{
m_viaPropagationGrid->Freeze();
updateViaProfileNamesEditor( oldName, newName );
// Update changed profile names
for( int row = 0; row < m_viaPropagationGrid->GetNumberRows(); ++row )
{
if( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_PROFILE_NAME ) == oldName )
m_viaPropagationGrid->SetCellValue( row, VIA_GRID_PROFILE_NAME, newName );
}
m_viaPropagationGrid->Thaw();
}
else
{
updateViaProfileNamesEditor( oldName, newName );
}
}
else
{
event.Veto();
}
}
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::updateViaProfileNamesEditor( const wxString& aOldName,
const wxString& aNewName ) const
{
wxArrayString profileNames;
for( int i = 0; i < m_tracePropagationGrid->GetNumberRows(); ++i )
{
wxString profileName = m_tracePropagationGrid->GetCellValue( i, PROFILE_GRID_PROFILE_NAME );
if( profileName == aOldName )
profileName = aNewName;
profileNames.push_back( profileName );
}
std::ranges::sort( profileNames,
[]( const wxString& a, const wxString& b )
{
return a.CmpNoCase( b ) < 0;
} );
wxGridCellAttr* attr = new wxGridCellAttr;
attr->SetEditor( new wxGridCellChoiceEditor( profileNames, false ) );
m_viaPropagationGrid->SetColAttr( VIA_GRID_PROFILE_NAME, attr );
}
bool PANEL_SETUP_TIME_DOMAIN_PARAMETERS::validateDelayProfileName( int aRow, const wxString& aName, bool focusFirst )
{
wxString tmp = aName;
tmp.Trim( true );
tmp.Trim( false );
if( tmp.IsEmpty() )
{
const wxString msg = _( "Tuning profile must have a name." );
PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_tracePropagationGrid, aRow, PROFILE_GRID_PROFILE_NAME );
return false;
}
for( int ii = 0; ii < m_tracePropagationGrid->GetNumberRows(); ii++ )
{
if( ii != aRow && m_tracePropagationGrid->GetCellValue( ii, PROFILE_GRID_PROFILE_NAME ).CmpNoCase( tmp ) == 0 )
{
const wxString msg = _( "Tuning profile name already in use." );
PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_tracePropagationGrid, focusFirst ? aRow : ii,
PROFILE_GRID_PROFILE_NAME );
return false;
}
}
return true;
}
bool PANEL_SETUP_TIME_DOMAIN_PARAMETERS::Validate()
{
if( !m_tracePropagationGrid->CommitPendingChanges() || !m_viaPropagationGrid->CommitPendingChanges() )
return false;
// Test net class parameters.
for( int row = 0; row < m_tracePropagationGrid->GetNumberRows(); row++ )
{
wxString profileName = m_tracePropagationGrid->GetCellValue( row, PROFILE_GRID_PROFILE_NAME );
profileName.Trim( true );
profileName.Trim( false );
if( !validateDelayProfileName( row, profileName, false ) )
return false;
}
return true;
}
std::vector<wxString> PANEL_SETUP_TIME_DOMAIN_PARAMETERS::GetDelayProfileNames() const
{
std::vector<wxString> profileNames;
for( int i = 0; i < m_tracePropagationGrid->GetNumberRows(); i++ )
profileNames.emplace_back( m_tracePropagationGrid->GetCellValue( i, PROFILE_GRID_PROFILE_NAME ) );
std::ranges::sort( profileNames,
[]( const wxString& a, const wxString& b )
{
return a.CmpNoCase( b ) < 0;
} );
return profileNames;
}
void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::ImportSettingsFrom(
const std::shared_ptr<TIME_DOMAIN_PARAMETERS>& aOtherParameters )
{
std::shared_ptr<TIME_DOMAIN_PARAMETERS> savedParameters = m_timeDomainParameters;
m_timeDomainParameters = aOtherParameters;
TransferDataToWindow();
updateViaProfileNamesEditor();
m_viaPropagationGrid->ForceRefresh();
m_timeDomainParameters = std::move( savedParameters );
}

View File

@ -0,0 +1,150 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program 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.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PANEL_SETUP_TIME_DOMAIN_PARAMETERS_H
#define PANEL_SETUP_TIME_DOMAIN_PARAMETERS_H
#include <utility>
#include <board.h>
#include <dialogs/panel_setup_time_domain_parameters_base.h>
#include <project/time_domain_parameters.h>
class NET_SETTINGS;
class PANEL_SETUP_TIME_DOMAIN_PARAMETERS : public PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE
{
public:
PANEL_SETUP_TIME_DOMAIN_PARAMETERS(
wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame, BOARD* aBoard,
std::shared_ptr<TIME_DOMAIN_PARAMETERS> aTimeDomainParameters );
~PANEL_SETUP_TIME_DOMAIN_PARAMETERS() override;
/**
* Called when switching to this tab to make sure that any changes to the copper layer count
* made on the physical stackup page are reflected here
* @param aNumCopperLayers is the number of copper layers in the board
*/
void SyncCopperLayers( int aNumCopperLayers );
/// Load parameter data from the settings object
bool TransferDataToWindow() override;
/// Save parameter data to the settings object
bool TransferDataFromWindow() override;
/// Returns all configured tuning profile names. Used by the netclass setup panel
std::vector<wxString> GetDelayProfileNames() const;
/// Load configuration from the given settings object
void ImportSettingsFrom( const std::shared_ptr<TIME_DOMAIN_PARAMETERS>& aOtherParameters );
private:
enum PROFILE_GRID_REQUIRED_COLS
{
PROFILE_GRID_PROFILE_NAME = 0,
PROFILE_GRID_VIA_PROP_DELAY,
PROFILE_GRID_NUM_REQUIRED_COLS
};
enum VIA_GRID_REQUIRED_COLS
{
VIA_GRID_PROFILE_NAME = 0,
VIA_GRID_SIGNAL_LAYER_FROM,
VIA_GRID_SIGNAL_LAYER_TO,
VIA_GRID_VIA_LAYER_FROM,
VIA_GRID_VIA_LAYER_TO,
VIA_GRID_DELAY
};
/// Optimise grid columns to fit titles and content
void setColumnWidths();
/// Updates the via override tuning profile name dropdown lists
/// Updates entries if aOldName and aNewName are passed
void updateViaProfileNamesEditor( const wxString& aOldName = wxEmptyString,
const wxString& aNewName = wxEmptyString ) const;
/// Update the dynamic (per-layer) columns in the tuning profiles grid
void updateProfileGridColumns();
/// Update the dynamic (per-layer) columns in the via overrides grid
void updateViaGridColumns();
/// Adds a new tuning profile entry to the tuning profile grid
void OnAddDelayProfileClick( wxCommandEvent& event ) override;
/// Removes a tuning profile entry from the tuning profile grid
void OnRemoveDelayProfileClick( wxCommandEvent& event ) override;
/// Adds a new via override profile entry to the via overrides grid
void OnAddViaOverrideClick( wxCommandEvent& event ) override;
/// Removes a via override profile entry from the via overrides grid
void OnRemoveViaOverrideClick( wxCommandEvent& event ) override;
/// Validates a tuning profile row data
void OnDelayProfileGridCellChanging( wxGridEvent& event );
/// Validates a tuning profile name (checks for not empty and not duplicated)
bool validateDelayProfileName( int aRow, const wxString& aName, bool focusFirst = true );
/// Validates all data
bool Validate() override;
/// Adds a tuning profile row with the given persisted parameters
void addProfileRow( const TIME_DOMAIN_TUNING_PROFILE& aDelayProfile );
/// Gets a tuning profile row as a set of persistable parameters
TIME_DOMAIN_TUNING_PROFILE getProfileRow( int aRow );
/// Adds a via override row with the given persisted parameters
void addViaRow( const wxString& aProfileName, const TUNING_PROFILE_VIA_OVERRIDE_ENTRY& aViaOverrideEntry ) const;
/// Gets a via override row as a set of persistable parameters
TUNING_PROFILE_VIA_OVERRIDE_ENTRY getViaRow( int aRow );
/// The parameters object to load / save data from / to
std::shared_ptr<TIME_DOMAIN_PARAMETERS> m_timeDomainParameters;
/// The active edit frame
PCB_EDIT_FRAME* m_frame;
/// The current board
BOARD* m_board;
std::unique_ptr<UNITS_PROVIDER> m_unitsProvider;
// Layer / column lookups
std::map<PCB_LAYER_ID, int> m_copperLayerIdsToColumns;
std::map<int, PCB_LAYER_ID> m_copperColumnsToLayerId;
std::vector<wxString> m_layerNames;
// We cache these in case the names change on the layers panel
std::map<wxString, PCB_LAYER_ID> m_layerNamesToIDs;
std::map<wxString, PCB_LAYER_ID> m_prevLayerNamesToIDs;
};
#endif // PANEL_SETUP_TIME_DOMAIN_PARAMETERS_H

View File

@ -0,0 +1,185 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "widgets/std_bitmap_button.h"
#include "widgets/wx_grid.h"
#include "widgets/wx_panel.h"
#include "panel_setup_time_domain_parameters_base.h"
///////////////////////////////////////////////////////////////////////////
PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
wxBoxSizer* bpanelTomeDomainSizer;
bpanelTomeDomainSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bMargins;
bMargins = new wxBoxSizer( wxVERTICAL );
m_splitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH|wxSP_LIVE_UPDATE|wxSP_NO_XP_THEME );
m_splitter->SetMinimumPaneSize( 160 );
m_timeDomainParametersPane = new WX_PANEL( m_splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bUpperSizer;
bUpperSizer = new wxBoxSizer( wxVERTICAL );
m_staticText3 = new wxStaticText( m_timeDomainParametersPane, wxID_ANY, _("Delay Profiles"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText3->Wrap( -1 );
bUpperSizer->Add( m_staticText3, 0, wxTOP|wxLEFT|wxEXPAND, 8 );
bUpperSizer->Add( 0, 3, 0, wxEXPAND, 5 );
m_tracePropagationGrid = new WX_GRID( m_timeDomainParametersPane, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL );
// Grid
m_tracePropagationGrid->CreateGrid( 0, 2 );
m_tracePropagationGrid->EnableEditing( true );
m_tracePropagationGrid->EnableGridLines( true );
m_tracePropagationGrid->EnableDragGridSize( false );
m_tracePropagationGrid->SetMargins( 0, 0 );
// Columns
m_tracePropagationGrid->EnableDragColMove( false );
m_tracePropagationGrid->EnableDragColSize( true );
m_tracePropagationGrid->SetColLabelValue( 0, _("Profile Name") );
m_tracePropagationGrid->SetColLabelValue( 1, _("Vias") );
m_tracePropagationGrid->SetColLabelSize( wxGRID_AUTOSIZE );
m_tracePropagationGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Rows
m_tracePropagationGrid->EnableDragRowSize( true );
m_tracePropagationGrid->SetRowLabelSize( 0 );
m_tracePropagationGrid->SetRowLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTER );
// Label Appearance
// Cell Defaults
m_tracePropagationGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTER );
bUpperSizer->Add( m_tracePropagationGrid, 1, wxEXPAND|wxFIXED_MINSIZE|wxLEFT|wxRIGHT|wxTOP, 5 );
wxBoxSizer* buttonBoxSizer;
buttonBoxSizer = new wxBoxSizer( wxHORIZONTAL );
m_addDelayProfileButton = new STD_BITMAP_BUTTON( m_timeDomainParametersPane, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
buttonBoxSizer->Add( m_addDelayProfileButton, 0, wxLEFT, 2 );
buttonBoxSizer->Add( 20, 0, 0, wxEXPAND, 5 );
m_removeDelayProfileButton = new STD_BITMAP_BUTTON( m_timeDomainParametersPane, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
buttonBoxSizer->Add( m_removeDelayProfileButton, 0, wxBOTTOM|wxLEFT, 5 );
buttonBoxSizer->Add( 20, 0, 0, wxEXPAND, 5 );
bUpperSizer->Add( buttonBoxSizer, 0, wxEXPAND|wxLEFT|wxTOP, 5 );
m_timeDomainParametersPane->SetSizer( bUpperSizer );
m_timeDomainParametersPane->Layout();
bUpperSizer->Fit( m_timeDomainParametersPane );
m_timeDomainParametersPane1 = new WX_PANEL( m_splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bUpperSizer1;
bUpperSizer1 = new wxBoxSizer( wxVERTICAL );
m_staticText31 = new wxStaticText( m_timeDomainParametersPane1, wxID_ANY, _("Via Delay Overrides"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText31->Wrap( -1 );
bUpperSizer1->Add( m_staticText31, 0, wxTOP|wxLEFT|wxEXPAND, 8 );
bUpperSizer1->Add( 0, 3, 0, wxEXPAND, 5 );
m_viaPropagationGrid = new WX_GRID( m_timeDomainParametersPane1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL );
// Grid
m_viaPropagationGrid->CreateGrid( 0, 6 );
m_viaPropagationGrid->EnableEditing( true );
m_viaPropagationGrid->EnableGridLines( true );
m_viaPropagationGrid->EnableDragGridSize( false );
m_viaPropagationGrid->SetMargins( 0, 0 );
// Columns
m_viaPropagationGrid->EnableDragColMove( false );
m_viaPropagationGrid->EnableDragColSize( true );
m_viaPropagationGrid->SetColLabelValue( 0, _("Profile Name") );
m_viaPropagationGrid->SetColLabelValue( 1, _("Signal Layer From") );
m_viaPropagationGrid->SetColLabelValue( 2, _("Signal Layer To") );
m_viaPropagationGrid->SetColLabelValue( 3, _("Via Layer From") );
m_viaPropagationGrid->SetColLabelValue( 4, _("Via Layer To") );
m_viaPropagationGrid->SetColLabelValue( 5, _("Delay") );
m_viaPropagationGrid->SetColLabelSize( wxGRID_AUTOSIZE );
m_viaPropagationGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Rows
m_viaPropagationGrid->EnableDragRowSize( true );
m_viaPropagationGrid->SetRowLabelSize( 0 );
m_viaPropagationGrid->SetRowLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTER );
// Label Appearance
// Cell Defaults
m_viaPropagationGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTER );
bUpperSizer1->Add( m_viaPropagationGrid, 1, wxEXPAND|wxFIXED_MINSIZE|wxLEFT|wxRIGHT|wxTOP, 5 );
wxBoxSizer* buttonBoxSizer1;
buttonBoxSizer1 = new wxBoxSizer( wxHORIZONTAL );
m_addViaOverrideButton = new STD_BITMAP_BUTTON( m_timeDomainParametersPane1, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
buttonBoxSizer1->Add( m_addViaOverrideButton, 0, wxLEFT, 2 );
buttonBoxSizer1->Add( 20, 0, 0, wxEXPAND, 5 );
m_removeViaOverrideButton = new STD_BITMAP_BUTTON( m_timeDomainParametersPane1, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
buttonBoxSizer1->Add( m_removeViaOverrideButton, 0, wxBOTTOM|wxLEFT, 5 );
buttonBoxSizer1->Add( 20, 0, 0, wxEXPAND, 5 );
bUpperSizer1->Add( buttonBoxSizer1, 0, wxEXPAND|wxLEFT|wxTOP, 5 );
m_timeDomainParametersPane1->SetSizer( bUpperSizer1 );
m_timeDomainParametersPane1->Layout();
bUpperSizer1->Fit( m_timeDomainParametersPane1 );
m_splitter->SplitHorizontally( m_timeDomainParametersPane, m_timeDomainParametersPane1, -1 );
bMargins->Add( m_splitter, 1, wxEXPAND, 10 );
bpanelTomeDomainSizer->Add( bMargins, 1, wxEXPAND|wxTOP, 2 );
this->SetSizer( bpanelTomeDomainSizer );
this->Layout();
bpanelTomeDomainSizer->Fit( this );
// Connect Events
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnUpdateUI ) );
m_tracePropagationGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnSizeTraceParametersGrid ), NULL, this );
m_addDelayProfileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnAddDelayProfileClick ), NULL, this );
m_removeDelayProfileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnRemoveDelayProfileClick ), NULL, this );
m_viaPropagationGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnSizeTraceParametersGrid ), NULL, this );
m_addViaOverrideButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnAddViaOverrideClick ), NULL, this );
m_removeViaOverrideButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnRemoveViaOverrideClick ), NULL, this );
}
PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::~PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnUpdateUI ) );
m_tracePropagationGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnSizeTraceParametersGrid ), NULL, this );
m_addDelayProfileButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnAddDelayProfileClick ), NULL, this );
m_removeDelayProfileButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnRemoveDelayProfileClick ), NULL, this );
m_viaPropagationGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnSizeTraceParametersGrid ), NULL, this );
m_addViaOverrideButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnAddViaOverrideClick ), NULL, this );
m_removeViaOverrideButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnRemoveViaOverrideClick ), NULL, this );
}

View File

@ -0,0 +1,950 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="18"/>
<object class="Project" expanded="true">
<property name="code_generation">C++</property>
<property name="cpp_class_decoration"></property>
<property name="cpp_disconnect_events">1</property>
<property name="cpp_event_generation">connect</property>
<property name="cpp_help_provider">none</property>
<property name="cpp_namespace"></property>
<property name="cpp_precompiled_header"></property>
<property name="cpp_use_array_enum">0</property>
<property name="cpp_use_enum">1</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="file">panel_setup_time_domain_parameters_base</property>
<property name="first_id">1000</property>
<property name="internationalize">1</property>
<property name="lua_skip_events">1</property>
<property name="lua_ui_table">UI</property>
<property name="name">panel_setup_time_domain_parameters_base</property>
<property name="path">.</property>
<property name="php_disconnect_events">0</property>
<property name="php_disconnect_mode">source_name</property>
<property name="php_skip_events">1</property>
<property name="python_disconnect_events">0</property>
<property name="python_disconnect_mode">source_name</property>
<property name="python_image_path_wrapper_function_name"></property>
<property name="python_indent_with_spaces"></property>
<property name="python_skip_events">1</property>
<property name="relative_path">1</property>
<property name="use_microsoft_bom">0</property>
<property name="use_native_eol">0</property>
<object class="Panel" expanded="true">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">-1,-1</property>
<property name="name">PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="subclass">; forward_declare</property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<event name="OnUpdateUI">OnUpdateUI</event>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bpanelTomeDomainSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">2</property>
<property name="flag">wxEXPAND|wxTOP</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bMargins</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">10</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxSplitterWindow" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_pane_size">160</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_splitter</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="sashgravity">0.0</property>
<property name="sashpos">-1</property>
<property name="sashsize">-1</property>
<property name="show">1</property>
<property name="size"></property>
<property name="splitmode">wxSPLIT_HORIZONTAL</property>
<property name="style">wxSP_3DSASH|wxSP_LIVE_UPDATE|wxSP_NO_XP_THEME</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="splitteritem" expanded="true">
<object class="wxPanel" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_timeDomainParametersPane</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">WX_PANEL; widgets/wx_panel.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="false">
<property name="minimum_size"></property>
<property name="name">bUpperSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="false">
<property name="border">8</property>
<property name="flag">wxTOP|wxLEFT|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Delay Profiles</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText3</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="false">
<property name="height">3</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxFIXED_MINSIZE|wxLEFT|wxRIGHT|wxTOP</property>
<property name="proportion">1</property>
<object class="wxGrid" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="autosize_cols">0</property>
<property name="autosize_rows">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="cell_bg"></property>
<property name="cell_font"></property>
<property name="cell_horiz_alignment">wxALIGN_LEFT</property>
<property name="cell_text"></property>
<property name="cell_vert_alignment">wxALIGN_CENTER</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
<property name="col_label_size">wxGRID_AUTOSIZE</property>
<property name="col_label_values">&quot;Profile Name&quot; &quot;Vias&quot;</property>
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
<property name="cols">2</property>
<property name="column_sizes"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="drag_col_move">0</property>
<property name="drag_col_size">1</property>
<property name="drag_grid_size">0</property>
<property name="drag_row_size">1</property>
<property name="editing">1</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="grid_line_color"></property>
<property name="grid_lines">1</property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label_bg"></property>
<property name="label_font"></property>
<property name="label_text"></property>
<property name="margin_height">0</property>
<property name="margin_width">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_tracePropagationGrid</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="row_label_horiz_alignment">wxALIGN_LEFT</property>
<property name="row_label_size">0</property>
<property name="row_label_values"></property>
<property name="row_label_vert_alignment">wxALIGN_CENTER</property>
<property name="row_sizes"></property>
<property name="rows">0</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL</property>
<event name="OnSize">OnSizeTraceParametersGrid</event>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxLEFT|wxTOP</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="false">
<property name="minimum_size"></property>
<property name="name">buttonBoxSizer</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="false">
<property name="border">2</property>
<property name="flag">wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Add Parameter</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_addDelayProfileButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size">-1,-1</property>
<property name="style"></property>
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnAddDelayProfileClick</event>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="false">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">20</property>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Delete Parameter</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_removeDelayProfileButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size">-1,-1</property>
<property name="style"></property>
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnRemoveDelayProfileClick</event>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="false">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">20</property>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
<object class="splitteritem" expanded="true">
<object class="wxPanel" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_timeDomainParametersPane1</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">WX_PANEL; widgets/wx_panel.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bUpperSizer1</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">8</property>
<property name="flag">wxTOP|wxLEFT|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Via Delay Overrides</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText31</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="true">
<property name="height">3</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxFIXED_MINSIZE|wxLEFT|wxRIGHT|wxTOP</property>
<property name="proportion">1</property>
<object class="wxGrid" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="autosize_cols">0</property>
<property name="autosize_rows">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="cell_bg"></property>
<property name="cell_font"></property>
<property name="cell_horiz_alignment">wxALIGN_LEFT</property>
<property name="cell_text"></property>
<property name="cell_vert_alignment">wxALIGN_CENTER</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
<property name="col_label_size">wxGRID_AUTOSIZE</property>
<property name="col_label_values">&quot;Profile Name&quot; &quot;Signal Layer From&quot; &quot;Signal Layer To&quot; &quot;Via Layer From&quot; &quot;Via Layer To&quot; &quot;Delay&quot;</property>
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
<property name="cols">6</property>
<property name="column_sizes"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="drag_col_move">0</property>
<property name="drag_col_size">1</property>
<property name="drag_grid_size">0</property>
<property name="drag_row_size">1</property>
<property name="editing">1</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="grid_line_color"></property>
<property name="grid_lines">1</property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label_bg"></property>
<property name="label_font"></property>
<property name="label_text"></property>
<property name="margin_height">0</property>
<property name="margin_width">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_viaPropagationGrid</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="row_label_horiz_alignment">wxALIGN_LEFT</property>
<property name="row_label_size">0</property>
<property name="row_label_values"></property>
<property name="row_label_vert_alignment">wxALIGN_CENTER</property>
<property name="row_sizes"></property>
<property name="rows">0</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL</property>
<event name="OnSize">OnSizeTraceParametersGrid</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxLEFT|wxTOP</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">buttonBoxSizer1</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">2</property>
<property name="flag">wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Add Parameter</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_addViaOverrideButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size">-1,-1</property>
<property name="style"></property>
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnAddViaOverrideClick</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="true">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">20</property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Delete Parameter</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_removeViaOverrideButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size">-1,-1</property>
<property name="style"></property>
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnRemoveViaOverrideClick</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="true">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">20</property>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -0,0 +1,71 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
class STD_BITMAP_BUTTON;
class WX_GRID;
class WX_PANEL;
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/grid.h>
#include <wx/bmpbuttn.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/splitter.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE
///////////////////////////////////////////////////////////////////////////////
class PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE : public wxPanel
{
private:
protected:
wxSplitterWindow* m_splitter;
WX_PANEL* m_timeDomainParametersPane;
wxStaticText* m_staticText3;
WX_GRID* m_tracePropagationGrid;
STD_BITMAP_BUTTON* m_addDelayProfileButton;
STD_BITMAP_BUTTON* m_removeDelayProfileButton;
WX_PANEL* m_timeDomainParametersPane1;
wxStaticText* m_staticText31;
WX_GRID* m_viaPropagationGrid;
STD_BITMAP_BUTTON* m_addViaOverrideButton;
STD_BITMAP_BUTTON* m_removeViaOverrideButton;
// Virtual event handlers, override them in your derived class
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnSizeTraceParametersGrid( wxSizeEvent& event ) { event.Skip(); }
virtual void OnAddDelayProfileClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRemoveDelayProfileClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnAddViaOverrideClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRemoveViaOverrideClick( wxCommandEvent& event ) { event.Skip(); }
public:
PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
~PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE();
};

View File

@ -775,6 +775,8 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
constraint.m_ZoneConnection = c->constraint.m_ZoneConnection;
constraint.SetParentRule( c->constraint.GetParentRule() );
constraint.SetOptionsFromOther( c->constraint );
};
const FOOTPRINT* footprints[2] = {a ? a->GetParentFootprint() : nullptr,

View File

@ -40,9 +40,13 @@ public:
std::set<BOARD_CONNECTED_ITEM*> items;
int viaCount;
double totalRoute;
double totalRouteDelay;
int totalVia;
int64_t totalViaDelay;
int totalPadToDie;
int64_t totalPadToDieDelay;
double total;
double totalDelay;
};
DRC_LENGTH_REPORT()

View File

@ -141,7 +141,12 @@ public:
enum class OPTIONS : std::size_t
{
SKEW_WITHIN_DIFF_PAIRS = 0
SKEW_WITHIN_DIFF_PAIRS = 0,
SPACE_DOMAIN,
TIME_DOMAIN,
// Keep this last value - used to statically size the options bitset
NUM_OPTIONS
};
bool IsNull() const
@ -180,11 +185,15 @@ public:
void SetOption( OPTIONS option ) { m_options.set( static_cast<std::size_t>( option ), true ); }
void ClearOption( OPTIONS option ) { m_options.set( static_cast<std::size_t>( option ), false ); }
bool GetOption( OPTIONS option ) const
{
return m_options.test( static_cast<std::size_t>( option ) );
}
void SetOptionsFromOther( const DRC_CONSTRAINT& aOther ) { m_options = aOther.m_options; }
public:
DRC_CONSTRAINT_T m_Type;
MINOPTMAX<int> m_Value;
@ -196,8 +205,8 @@ public:
private:
wxString m_name; // For just-in-time constraints
DRC_RULE* m_parentRule; // For constraints found in rules
std::bitset<1> m_options; // Constraint-specific option bits
// (indexed from DRC_CONSTRAINT::OPTIONS)
std::bitset<static_cast<int>( OPTIONS::NUM_OPTIONS )> m_options; // Constraint-specific option bits
// (indexed from DRC_CONSTRAINT::OPTIONS)
};

View File

@ -420,7 +420,41 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
{
DRC_CONSTRAINT c;
int value;
EDA_UNITS units = EDA_UNITS::UNSCALED;
EDA_DATA_TYPE unitsType = EDA_DATA_TYPE::UNITLESS;
wxString msg;
bool allowsTimeDomain = false;
auto validateAndSetValueWithUnits =
[this, &allowsTimeDomain, &unitsType, &c]( int aValue, const EDA_UNITS aUnits, auto aSetter )
{
const EDA_DATA_TYPE unitsTypeTmp = UNITS_PROVIDER::GetTypeFromUnits( aUnits );
if( !allowsTimeDomain && unitsTypeTmp == EDA_DATA_TYPE::TIME )
reportError( _( "Time based units not allowed for constraint type." ) );
if( ( c.m_Value.HasMin() || c.m_Value.HasMax() || c.m_Value.HasOpt() ) && unitsType != unitsTypeTmp )
{
reportError( _( "Mixed units for constraint values." ) );
}
unitsType = unitsTypeTmp;
aSetter( aValue );
if( allowsTimeDomain )
{
if( unitsType == EDA_DATA_TYPE::TIME )
{
c.SetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN );
c.ClearOption( DRC_CONSTRAINT::OPTIONS::SPACE_DOMAIN );
}
else
{
c.SetOption( DRC_CONSTRAINT::OPTIONS::SPACE_DOMAIN );
c.ClearOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN );
}
}
};
T token = NextTok();
@ -504,6 +538,8 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|| c.m_Type == MIN_RESOLVED_SPOKES_CONSTRAINT
|| c.m_Type == TRACK_ANGLE_CONSTRAINT;
allowsTimeDomain = c.m_Type == LENGTH_CONSTRAINT || c.m_Type == SKEW_CONSTRAINT;
if( c.m_Type == DISALLOW_CONSTRAINT )
{
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
@ -661,8 +697,12 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
break;
}
parseValueWithUnits( FromUTF8(), value, unitless );
c.m_Value.SetMin( value );
parseValueWithUnits( FromUTF8(), value, units, unitless );
validateAndSetValueWithUnits( value, units,
[&c]( const int aValue )
{
c.m_Value.SetMin( aValue );
} );
if( (int) NextTok() != DSN_RIGHT )
{
@ -681,9 +721,12 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
break;
}
parseValueWithUnits( FromUTF8(), value, unitless );
c.m_Value.SetMax( value );
parseValueWithUnits( FromUTF8(), value, units, unitless );
validateAndSetValueWithUnits( value, units,
[&c]( const int aValue )
{
c.m_Value.SetMax( aValue );
} );
if( (int) NextTok() != DSN_RIGHT )
{
@ -702,8 +745,12 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
break;
}
parseValueWithUnits( FromUTF8(), value, unitless );
c.m_Value.SetOpt( value );
parseValueWithUnits( FromUTF8(), value, units, unitless );
validateAndSetValueWithUnits( value, units,
[&c]( const int aValue )
{
c.m_Value.SetOpt( aValue );
} );
if( (int) NextTok() != DSN_RIGHT )
{
@ -733,8 +780,11 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
}
void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult, bool aUnitless )
void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult, EDA_UNITS& aUnits, bool aUnitless )
{
aResult = 0.0;
aUnits = EDA_UNITS::UNSCALED;
auto errorHandler = [&]( const wxString& aMessage, int aOffset )
{
wxString rest;
@ -760,8 +810,11 @@ void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult,
: (LIBEVAL::UNIT_RESOLVER*) new PCBEXPR_UNIT_RESOLVER() );
evaluator.SetErrorCallback( errorHandler );
evaluator.Evaluate( aExpr );
aResult = evaluator.Result();
if( evaluator.Evaluate( aExpr ) )
{
aResult = evaluator.Result();
aUnits = evaluator.Units();
}
}

View File

@ -55,7 +55,7 @@ private:
std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE> parseComponentClassAssignment();
void parseConstraint( DRC_RULE* aRule );
void parseValueWithUnits( const wxString& aExpr, int& aResult, bool aUnitless = false );
void parseValueWithUnits( const wxString& aExpr, int& aResult, EDA_UNITS& aUnits, bool aUnitless = false );
LSET parseLayer( wxString* aSource );
SEVERITY parseSeverity();
void parseUnknown();

View File

@ -373,17 +373,17 @@ bool DRC_TEST_PROVIDER::isInvisibleText( const BOARD_ITEM* aItem ) const
}
wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource,
double aConstraint, double aActual )
wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource, double aConstraint,
double aActual, EDA_DATA_TYPE aType )
{
wxString constraint_str = MessageTextFromValue( aConstraint );
wxString actual_str = MessageTextFromValue( aActual );
wxString constraint_str = MessageTextFromValue( aConstraint, true, aType );
wxString actual_str = MessageTextFromValue( aActual, true, aType );
if( constraint_str == actual_str )
{
// Use more precise formatting if the message-text strings were equal.
constraint_str = StringFromValue( aConstraint, true );
actual_str = StringFromValue( aActual, true );
constraint_str = StringFromValue( aConstraint, true, aType );
actual_str = StringFromValue( aActual, true, aType );
}
return wxString::Format( aFormatString, aSource, constraint_str, actual_str );

View File

@ -122,8 +122,8 @@ protected:
bool isInvisibleText( const BOARD_ITEM* aItem ) const;
wxString formatMsg( const wxString& aFormatString, const wxString& aSource, double aConstraint,
double aActual );
wxString formatMsg( const wxString& aFormatString, const wxString& aSource, double aConstraint, double aActual,
EDA_DATA_TYPE aDataType = EDA_DATA_TYPE::DISTANCE );
wxString formatMsg( const wxString& aFormatString, const wxString& aSource,
const EDA_ANGLE& aConstraint, const EDA_ANGLE& aActual );

View File

@ -93,15 +93,34 @@ void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkLengths( const DRC_CONSTRAINT& aCons
int minLen = 0;
int maxLen = 0;
if( aConstraint.GetValue().HasMin() && ent.total < aConstraint.GetValue().Min() )
const bool isTimeDomain = aConstraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN );
const EDA_DATA_TYPE dataType = isTimeDomain ? EDA_DATA_TYPE::TIME : EDA_DATA_TYPE::DISTANCE;
if( !isTimeDomain )
{
minViolation = true;
minLen = aConstraint.GetValue().Min();
if( aConstraint.GetValue().HasMin() && ent.total < aConstraint.GetValue().Min() )
{
minViolation = true;
minLen = aConstraint.GetValue().Min();
}
else if( aConstraint.GetValue().HasMax() && ent.total > aConstraint.GetValue().Max() )
{
maxViolation = true;
maxLen = aConstraint.GetValue().Max();
}
}
else if( aConstraint.GetValue().HasMax() && ent.total > aConstraint.GetValue().Max() )
else
{
maxViolation = true;
maxLen = aConstraint.GetValue().Max();
if( aConstraint.GetValue().HasMin() && ent.totalDelay < aConstraint.GetValue().Min() )
{
minViolation = true;
minLen = aConstraint.GetValue().Min();
}
else if( aConstraint.GetValue().HasMax() && ent.totalDelay > aConstraint.GetValue().Max() )
{
maxViolation = true;
maxLen = aConstraint.GetValue().Max();
}
}
if( ( minViolation || maxViolation ) )
@ -111,17 +130,29 @@ void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkLengths( const DRC_CONSTRAINT& aCons
if( minViolation )
{
msg = formatMsg( _( "(%s min length %s; actual %s)" ),
aConstraint.GetName(),
minLen,
ent.total );
if( aConstraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN ) )
{
msg = formatMsg( _( "(%s min length %s; actual %s)" ), aConstraint.GetName(), minLen,
ent.totalDelay, dataType );
}
else
{
msg = formatMsg( _( "(%s min length %s; actual %s)" ), aConstraint.GetName(), minLen, ent.total,
dataType );
}
}
else if( maxViolation )
{
msg = formatMsg( _( "(%s max length %s; actual %s)" ),
aConstraint.GetName(),
maxLen,
ent.total );
if( aConstraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN ) )
{
msg = formatMsg( _( "(%s max length %s; actual %s)" ), aConstraint.GetName(), maxLen,
ent.totalDelay, dataType );
}
else
{
msg = formatMsg( _( "(%s max length %s; actual %s)" ), aConstraint.GetName(), maxLen, ent.total,
dataType );
}
}
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
@ -142,21 +173,44 @@ void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkSkews( const DRC_CONSTRAINT& aConstr
{
auto checkSkewsImpl = [this, &aConstraint]( const std::vector<CONNECTION>& connections )
{
const bool isTimeDomain = aConstraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN );
const EDA_DATA_TYPE dataType = isTimeDomain ? EDA_DATA_TYPE::TIME : EDA_DATA_TYPE::DISTANCE;
double maxLength = 0;
wxString maxNetname;
for( const DRC_LENGTH_REPORT::ENTRY& ent : connections )
if( !isTimeDomain )
{
if( ent.total > maxLength )
for( const DRC_LENGTH_REPORT::ENTRY& ent : connections )
{
maxLength = ent.total;
maxNetname = ent.netname;
if( ent.total > maxLength )
{
maxLength = ent.total;
maxNetname = ent.netname;
}
}
}
else
{
for( const DRC_LENGTH_REPORT::ENTRY& ent : connections )
{
if( ent.totalDelay > maxLength )
{
maxLength = ent.totalDelay;
maxNetname = ent.netname;
}
}
}
for( const auto& ent : connections )
{
int skew = KiROUND( ent.total - maxLength );
int skew = 0;
if( isTimeDomain )
skew = KiROUND( ent.totalDelay - maxLength );
else
skew = KiROUND( ent.total - maxLength );
bool fail_min = false;
bool fail_max = false;
@ -170,23 +224,27 @@ void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkSkews( const DRC_CONSTRAINT& aConstr
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_SKEW_OUT_OF_RANGE );
wxString msg;
double reportTotal = isTimeDomain ? ent.totalDelay : ent.total;
if( fail_min )
{
msg.Printf( _( "(%s min skew %s; actual %s; target net length %s (from %s); "
"actual %s)" ),
aConstraint.GetName(),
MessageTextFromValue( aConstraint.GetValue().Min() ),
MessageTextFromValue( skew ), MessageTextFromValue( maxLength ),
maxNetname, MessageTextFromValue( ent.total ) );
MessageTextFromValue( aConstraint.GetValue().Min(), true, dataType ),
MessageTextFromValue( skew, true, dataType ),
MessageTextFromValue( maxLength, true, dataType ), maxNetname,
MessageTextFromValue( reportTotal, true, dataType ) );
}
else
{
msg.Printf( _( "(%s max skew %s; actual %s; target net length %s (from %s); "
"actual %s)" ),
aConstraint.GetName(),
MessageTextFromValue( aConstraint.GetValue().Max() ),
MessageTextFromValue( skew ), MessageTextFromValue( maxLength ),
maxNetname, MessageTextFromValue( ent.total ) );
MessageTextFromValue( aConstraint.GetValue().Max(), true, dataType ),
MessageTextFromValue( skew, true, dataType ),
MessageTextFromValue( maxLength, true, dataType ), maxNetname,
MessageTextFromValue( reportTotal, true, dataType ) );
}
drcItem->SetErrorMessage( drcItem->GetErrorText() + " " + msg );
@ -345,7 +403,7 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
return true;
} );
LENGTH_CALCULATION* calc = m_board->GetLengthCalculation();
LENGTH_DELAY_CALCULATION* calc = m_board->GetLengthCalculation();
std::map< DRC_RULE*, std::vector<CONNECTION> > matches;
@ -358,7 +416,7 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
for( const auto& [netCode, netItems] : netMap )
{
std::vector<LENGTH_CALCULATION_ITEM> lengthItems;
std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems;
lengthItems.reserve( netItems.size() );
CONNECTION ent;
@ -376,21 +434,28 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
for( BOARD_CONNECTED_ITEM* item : netItems )
{
LENGTH_CALCULATION_ITEM lengthItem = calc->GetLengthCalculationItem( item );
LENGTH_DELAY_CALCULATION_ITEM lengthItem = calc->GetLengthCalculationItem( item );
if( lengthItem.Type() != LENGTH_CALCULATION_ITEM::TYPE::UNKNOWN )
if( lengthItem.Type() != LENGTH_DELAY_CALCULATION_ITEM::TYPE::UNKNOWN )
lengthItems.emplace_back( lengthItem );
}
constexpr PATH_OPTIMISATIONS opts = {
.OptimiseViaLayers = true, .MergeTracks = true, .OptimiseTracesInPads = true, .InferViaInPad = false
};
LENGTH_DETAILS details = calc->CalculateLengthDetails( lengthItems, opts );
LENGTH_DELAY_STATS details = calc->CalculateLengthDetails( lengthItems, opts, nullptr, nullptr,
LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL,
LENGTH_DELAY_DOMAIN_OPT::WITH_DELAY_DETAIL );
ent.viaCount = details.NumVias;
ent.totalVia = details.ViaLength;
ent.totalViaDelay = details.ViaDelay;
ent.totalRoute = static_cast<double>( details.TrackLength );
ent.totalRouteDelay = static_cast<double>( details.TrackDelay );
ent.totalPadToDie = details.PadToDieLength;
ent.totalPadToDieDelay = details.PadToDieDelay;
ent.total = ent.totalRoute + ent.totalVia + ent.totalPadToDie;
ent.totalDelay = ent.totalRouteDelay + static_cast<double>( ent.totalViaDelay )
+ static_cast<double>( ent.totalPadToDieDelay );
ent.matchingRule = rule;
// fixme: doesn't seem to work ;-)

View File

@ -82,11 +82,8 @@ class TUNING_STATUS_VIEW_ITEM : public EDA_ITEM
{
public:
TUNING_STATUS_VIEW_ITEM( PCB_BASE_EDIT_FRAME* aFrame ) :
EDA_ITEM( NOT_USED ), // Never added to anything - just a preview
m_frame( aFrame ),
m_min( 0.0 ),
m_max( 0.0 ),
m_current( 0.0 )
EDA_ITEM( NOT_USED ), // Never added to anything - just a preview
m_frame( aFrame ), m_min( 0.0 ), m_max( 0.0 ), m_current( 0.0 ), m_isTimeDomain( false )
{ }
wxString GetClass() const override { return wxT( "TUNING_STATUS" ); }
@ -98,12 +95,14 @@ public:
VECTOR2I GetPosition() const override { return m_pos; }
void SetPosition( const VECTOR2I& aPos ) override { m_pos = aPos; };
void SetMinMax( double aMin, double aMax )
void SetMinMax( const double aMin, const double aMax )
{
const EDA_DATA_TYPE unitType = m_isTimeDomain ? EDA_DATA_TYPE::TIME : EDA_DATA_TYPE::DISTANCE;
m_min = aMin;
m_minText = m_frame->MessageTextFromValue( m_min, false );
m_minText = m_frame->MessageTextFromValue( m_min, false, unitType );
m_max = aMax;
m_maxText = m_frame->MessageTextFromValue( m_max, false );
m_maxText = m_frame->MessageTextFromValue( m_max, false, unitType );
}
void ClearMinMax()
@ -114,13 +113,17 @@ public:
m_maxText = wxT( "---" );
}
void SetCurrent( double aCurrent, const wxString& aLabel )
void SetCurrent( const double aCurrent, const wxString& aLabel )
{
const EDA_DATA_TYPE unitType = m_isTimeDomain ? EDA_DATA_TYPE::TIME : EDA_DATA_TYPE::DISTANCE;
m_current = aCurrent;
m_currentText = m_frame->MessageTextFromValue( aCurrent );
m_currentText = m_frame->MessageTextFromValue( aCurrent, true, unitType );
m_currentLabel = aLabel;
}
void SetIsTimeDomain( const bool aIsTimeDomain ) { m_isTimeDomain = aIsTimeDomain; }
const BOX2I ViewBBox() const override
{
BOX2I tmp;
@ -237,6 +240,7 @@ protected:
wxString m_currentText;
wxString m_minText;
wxString m_maxText;
bool m_isTimeDomain;
};
@ -450,15 +454,38 @@ public:
void SetTargetLength( std::optional<int> aValue )
{
m_settings.m_isTimeDomain = false;
if( aValue.has_value() )
m_settings.SetTargetLength( aValue.value() );
else
m_settings.SetTargetLength( PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED );
}
std::optional<int> GetTargetDelay() const
{
if( m_settings.m_targetLengthDelay.Opt() == PNS::MEANDER_SETTINGS::DELAY_UNCONSTRAINED )
return std::optional<int>();
else
return m_settings.m_targetLengthDelay.Opt();
}
void SetTargetDelay( std::optional<int> aValue )
{
m_settings.m_isTimeDomain = true;
if( aValue.has_value() )
m_settings.SetTargetLengthDelay( aValue.value() );
else
m_settings.SetTargetLengthDelay( PNS::MEANDER_SETTINGS::DELAY_UNCONSTRAINED );
}
int GetTargetSkew() const { return m_settings.m_targetSkew.Opt(); }
void SetTargetSkew( int aValue ) { m_settings.SetTargetSkew( aValue ); }
int GetTargetSkewDelay() const { return m_settings.m_targetSkewDelay.Opt(); }
void SetTargetSkewDelay( int aValue ) { m_settings.SetTargetSkewDelay( aValue ); }
bool GetOverrideCustomRules() const { return m_settings.m_overrideCustomRules; }
void SetOverrideCustomRules( bool aOverride ) { m_settings.m_overrideCustomRules = aOverride; }
@ -745,17 +772,49 @@ PCB_TUNING_PATTERN* PCB_TUNING_PATTERN::CreateNew( GENERATOR_TOOL* aTool,
case DIFF_PAIR_SKEW: pattern->m_settings = bds.m_SkewMeanderSettings; break;
}
constraint = bds.m_DRCEngine->EvalRules( LENGTH_CONSTRAINT, aStartItem, nullptr, layer );
if( !constraint.IsNull() )
if( aMode == SINGLE || aMode == DIFF_PAIR )
{
if( aMode == DIFF_PAIR_SKEW )
pattern->m_settings.SetTargetSkew( constraint.GetValue() );
else
pattern->m_settings.SetTargetLength( constraint.GetValue() );
constraint = bds.m_DRCEngine->EvalRules( LENGTH_CONSTRAINT, aStartItem, nullptr, layer );
if( !constraint.IsNull() )
{
if( constraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN ) )
{
pattern->m_settings.SetTargetLengthDelay( constraint.GetValue() );
pattern->m_settings.SetTargetLength( MINOPTMAX<int>() );
pattern->m_settings.m_isTimeDomain = true;
}
else
{
pattern->m_settings.SetTargetLengthDelay( MINOPTMAX<int>() );
pattern->m_settings.SetTargetLength( constraint.GetValue() );
pattern->m_settings.m_isTimeDomain = false;
}
}
}
else
{
constraint = bds.m_DRCEngine->EvalRules( SKEW_CONSTRAINT, aStartItem, nullptr, layer );
if( !constraint.IsNull() )
{
if( constraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN ) )
{
pattern->m_settings.SetTargetSkew( MINOPTMAX<int>() );
pattern->m_settings.SetTargetLengthDelay( constraint.GetValue() );
pattern->m_settings.m_isTimeDomain = true;
}
else
{
pattern->m_settings.SetTargetSkew( constraint.GetValue() );
pattern->m_settings.SetTargetSkewDelay( MINOPTMAX<int>() );
pattern->m_settings.m_isTimeDomain = true;
}
}
}
pattern->SetFlags( IS_NEW );
pattern->m_settings.m_netClass = aStartItem->GetEffectiveNetClass();
return pattern;
}
@ -814,14 +873,15 @@ void PCB_TUNING_PATTERN::EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_
m_updateSideFromEnd = false;
}
PCB_TRACK* track = nullptr;
m_origin = snapToNearestTrack( m_origin, aBoard, nullptr, &track );
wxCHECK( track, /* void */ );
m_settings.m_netClass = track->GetEffectiveNetClass();
if( !m_settings.m_overrideCustomRules )
{
PCB_TRACK* track = nullptr;
PNS::SEGMENT pnsItem;
m_origin = snapToNearestTrack( m_origin, aBoard, nullptr, &track );
wxCHECK( track, /* void */ );
PNS::SEGMENT pnsItem;
NETINFO_ITEM* net = track->GetNet();
pnsItem.SetParent( track );
@ -832,7 +892,18 @@ void PCB_TUNING_PATTERN::EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_
if( resolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_LENGTH,
&pnsItem, nullptr, layer, &constraint ) )
{
m_settings.SetTargetLength( constraint.m_Value );
if( constraint.m_IsTimeDomain )
{
m_settings.SetTargetLengthDelay( constraint.m_Value );
m_settings.SetTargetLength( MINOPTMAX<int>() );
}
else
{
m_settings.SetTargetLengthDelay( MINOPTMAX<int>() );
m_settings.SetTargetLength( constraint.m_Value );
}
m_settings.m_isTimeDomain = constraint.m_IsTimeDomain;
aTool->GetManager()->PostEvent( EVENTS::SelectedItemsModified );
}
}
@ -853,7 +924,18 @@ void PCB_TUNING_PATTERN::EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_
if( resolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_LENGTH,
&pnsItem, &pnsCoupledItem, layer, &constraint ) )
{
m_settings.SetTargetLength( constraint.m_Value );
if( constraint.m_IsTimeDomain )
{
m_settings.SetTargetLengthDelay( constraint.m_Value );
m_settings.SetTargetLength( MINOPTMAX<int>() );
}
else
{
m_settings.SetTargetLengthDelay( MINOPTMAX<int>() );
m_settings.SetTargetLength( constraint.m_Value );
}
m_settings.m_isTimeDomain = constraint.m_IsTimeDomain;
aTool->GetManager()->PostEvent( EVENTS::SelectedItemsModified );
}
}
@ -862,7 +944,18 @@ void PCB_TUNING_PATTERN::EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_
if( resolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_SKEW,
&pnsItem, &pnsCoupledItem, layer, &constraint ) )
{
m_settings.m_targetSkew = constraint.m_Value;
if( constraint.m_IsTimeDomain )
{
m_settings.SetTargetSkewDelay( constraint.m_Value );
m_settings.SetTargetSkew( MINOPTMAX<int>() );
}
else
{
m_settings.SetTargetSkewDelay( MINOPTMAX<int>() );
m_settings.SetTargetSkew( constraint.m_Value );
}
m_settings.m_isTimeDomain = constraint.m_IsTimeDomain;
aTool->GetManager()->PostEvent( EVENTS::SelectedItemsModified );
}
}
@ -1473,8 +1566,16 @@ bool PCB_TUNING_PATTERN::Update( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COM
if( aTool->GetManager()->GetSettings() )
userUnits = static_cast<EDA_UNITS>( aTool->GetManager()->GetSettings()->m_System.units );
result = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, userUnits,
(double) placer->TuningResult() );
if( m_settings.m_isTimeDomain )
{
result = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, EDA_UNITS::PS,
(double) placer->TuningLengthResult() );
}
else
{
result = EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, userUnits,
(double) placer->TuningLengthResult() );
}
m_tuningInfo.Printf( wxS( "%s (%s)" ), result, statusMessage );
@ -1900,6 +2001,7 @@ const STRING_ANY_MAP PCB_TUNING_PATTERN::GetProperties() const
props.set( "tuning_mode", tuningToString( m_tuningMode ) );
props.set( "initial_side", sideToString( m_settings.m_initialSide ) );
props.set( "last_status", statusToString( m_tuningStatus ) );
props.set( "is_time_domain", m_settings.m_isTimeDomain );
props.set( "end", m_end );
props.set( "corner_radius_percent", m_settings.m_cornerRadiusPercentage );
@ -1912,6 +2014,9 @@ const STRING_ANY_MAP PCB_TUNING_PATTERN::GetProperties() const
props.set_iu( "target_length_min", m_settings.m_targetLength.Min() );
props.set_iu( "target_length", m_settings.m_targetLength.Opt() );
props.set_iu( "target_length_max", m_settings.m_targetLength.Max() );
props.set_iu( "target_delay_min", m_settings.m_targetLengthDelay.Min() );
props.set_iu( "target_delay", m_settings.m_targetLengthDelay.Opt() );
props.set_iu( "target_delay_max", m_settings.m_targetLengthDelay.Max() );
props.set_iu( "target_skew_min", m_settings.m_targetSkew.Min() );
props.set_iu( "target_skew", m_settings.m_targetSkew.Opt() );
props.set_iu( "target_skew_max", m_settings.m_targetSkew.Max() );
@ -1948,6 +2053,8 @@ void PCB_TUNING_PATTERN::SetProperties( const STRING_ANY_MAP& aProps )
aProps.get_to( "last_status", status );
m_tuningStatus = statusFromString( status.utf8_string() );
aProps.get_to( "is_time_domain", m_settings.m_isTimeDomain );
aProps.get_to( "end", m_end );
aProps.get_to( "corner_radius_percent", m_settings.m_cornerRadiusPercentage );
aProps.get_to( "single_sided", m_settings.m_singleSided );
@ -1968,6 +2075,15 @@ void PCB_TUNING_PATTERN::SetProperties( const STRING_ANY_MAP& aProps )
if( aProps.get_to_iu( "target_length_max", val ) )
m_settings.m_targetLength.SetMax( val );
aProps.get_to_iu( "target_delay", val );
m_settings.SetTargetLengthDelay( val );
if( aProps.get_to_iu( "target_delay_min", val ) )
m_settings.m_targetLengthDelay.SetMin( val );
if( aProps.get_to_iu( "target_delay_max", val ) )
m_settings.m_targetLengthDelay.SetMax( val );
int int_val;
aProps.get_to_iu( "target_skew", int_val );
@ -2007,10 +2123,46 @@ void PCB_TUNING_PATTERN::ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame )
BOARD_ITEM* startItem = static_cast<BOARD_ITEM*>( *m_items.begin() );
std::shared_ptr<DRC_ENGINE>& drcEngine = GetBoard()->GetDesignSettings().m_DRCEngine;
constraint = drcEngine->EvalRules( LENGTH_CONSTRAINT, startItem, nullptr, GetLayer() );
if( m_tuningMode == DIFF_PAIR_SKEW )
{
constraint = drcEngine->EvalRules( SKEW_CONSTRAINT, startItem, nullptr, GetLayer() );
if( !constraint.IsNull() && !settings.m_overrideCustomRules )
settings.SetTargetLength( constraint.GetValue() );
if( !constraint.IsNull() && !settings.m_overrideCustomRules )
{
if( constraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN ) )
{
settings.SetTargetLengthDelay( constraint.GetValue() );
settings.SetTargetLength( MINOPTMAX<int>() );
settings.m_isTimeDomain = true;
}
else
{
settings.SetTargetLengthDelay( MINOPTMAX<int>() );
settings.SetTargetLength( constraint.GetValue() );
settings.m_isTimeDomain = false;
}
}
}
else
{
constraint = drcEngine->EvalRules( LENGTH_CONSTRAINT, startItem, nullptr, GetLayer() );
if( !constraint.IsNull() && !settings.m_overrideCustomRules )
{
if( constraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN ) )
{
settings.SetTargetLengthDelay( constraint.GetValue() );
settings.SetTargetLength( MINOPTMAX<int>() );
settings.m_isTimeDomain = true;
}
else
{
settings.SetTargetLengthDelay( MINOPTMAX<int>() );
settings.SetTargetLength( constraint.GetValue() );
settings.m_isTimeDomain = false;
}
}
}
}
DIALOG_TUNING_PATTERN_PROPERTIES dlg( aEditFrame, settings, GetPNSMode(), constraint );
@ -2052,25 +2204,55 @@ std::vector<EDA_ITEM*> PCB_TUNING_PATTERN::GetPreviewItems( GENERATOR_TOOL* aToo
if( m_tuningMode == DIFF_PAIR_SKEW )
{
statusItem->SetMinMax( m_settings.m_targetSkew.Min(), m_settings.m_targetSkew.Max() );
if( m_settings.m_isTimeDomain )
statusItem->SetMinMax( m_settings.m_targetSkewDelay.Min(), m_settings.m_targetSkewDelay.Max() );
else
statusItem->SetMinMax( m_settings.m_targetSkew.Min(), m_settings.m_targetSkew.Max() );
}
else
{
if( m_settings.m_targetLength.Opt() == PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
if( m_settings.m_isTimeDomain )
{
statusItem->ClearMinMax();
if( m_settings.m_targetLengthDelay.Opt() == PNS::MEANDER_SETTINGS::DELAY_UNCONSTRAINED )
{
statusItem->ClearMinMax();
}
else
{
statusItem->SetMinMax( static_cast<double>( m_settings.m_targetLengthDelay.Min() ),
static_cast<double>( m_settings.m_targetLengthDelay.Max() ) );
}
}
else
{
statusItem->SetMinMax( (double) m_settings.m_targetLength.Min(),
(double) m_settings.m_targetLength.Max() );
if( m_settings.m_targetLengthDelay.Opt() == PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
{
statusItem->ClearMinMax();
}
else
{
statusItem->SetMinMax( static_cast<double>( m_settings.m_targetLength.Min() ),
static_cast<double>( m_settings.m_targetLength.Max() ) );
}
}
}
statusItem->SetIsTimeDomain( m_settings.m_isTimeDomain );
if( m_tuningMode == DIFF_PAIR_SKEW )
statusItem->SetCurrent( (double) placer->TuningResult(), _( "current skew" ) );
{
if( m_settings.m_isTimeDomain )
statusItem->SetCurrent( static_cast<double>( placer->TuningDelayResult() ), _( "current skew" ) );
else
statusItem->SetCurrent( static_cast<double>( placer->TuningLengthResult() ), _( "current skew" ) );
}
else
statusItem->SetCurrent( (double) placer->TuningResult(), _( "current length" ) );
{
if( m_settings.m_isTimeDomain )
statusItem->SetCurrent( static_cast<double>( placer->TuningDelayResult() ), _( "current delay" ) );
else
statusItem->SetCurrent( static_cast<double>( placer->TuningLengthResult() ), _( "current length" ) );
}
statusItem->SetPosition( aFrame->GetToolManager()->GetMousePosition() );
previewItems.push_back( statusItem );
@ -2092,6 +2274,8 @@ void PCB_TUNING_PATTERN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
int width = 0;
bool mixedWidth = false;
EDA_DATA_TYPE unitType = m_settings.m_isTimeDomain ? EDA_DATA_TYPE::TIME : EDA_DATA_TYPE::DISTANCE;
aList.emplace_back( _( "Type" ), GetFriendlyName() );
for( EDA_ITEM* member : GetItems() )
@ -2146,27 +2330,51 @@ void PCB_TUNING_PATTERN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
// Display full track length (in Pcbnew)
if( board && primaryItem && primaryItem->GetNetCode() > 0 )
{
int count;
double trackLen;
double lenPadToDie;
int count = 0;
double trackLen = 0.0;
double lenPadToDie = 0.0;
double trackDelay = 0.0;
double delayPadToDie = 0.0;
std::tie( count, trackLen, lenPadToDie ) = board->GetTrackLength( *primaryItem );
std::tie( count, trackLen, lenPadToDie, trackDelay, delayPadToDie ) = board->GetTrackLength( *primaryItem );
if( coupledItem && coupledItem->GetNetCode() > 0 )
{
double coupledLen;
std::tie( count, coupledLen, lenPadToDie ) = board->GetTrackLength( *coupledItem );
double coupledLen = 0.0;
double coupledLenPadToDie = 0.0;
double coupledTrackDelay = 0.0;
double doubledDelayPadToDie = 0.0;
aList.emplace_back( _( "Routed Lengths" ), aFrame->MessageTextFromValue( trackLen )
+ wxS( ", " )
+ aFrame->MessageTextFromValue( coupledLen ) );
std::tie( count, coupledLen, coupledLenPadToDie, coupledTrackDelay, doubledDelayPadToDie ) =
board->GetTrackLength( *coupledItem );
if( trackDelay == 0.0 || coupledTrackDelay == 0.0 )
{
aList.emplace_back( _( "Routed Lengths" ), aFrame->MessageTextFromValue( trackLen ) + wxS( ", " )
+ aFrame->MessageTextFromValue( coupledLen ) );
}
else
{
aList.emplace_back(
_( "Routed Delays" ),
aFrame->MessageTextFromValue( trackDelay, true, EDA_DATA_TYPE::TIME ) + wxS( ", " )
+ aFrame->MessageTextFromValue( coupledTrackDelay, true, EDA_DATA_TYPE::TIME ) );
}
}
else
{
aList.emplace_back( _( "Routed Length" ), aFrame->MessageTextFromValue( trackLen ) );
if( trackDelay == 0.0 )
{
aList.emplace_back( _( "Routed Length" ), aFrame->MessageTextFromValue( trackLen ) );
}
else
{
aList.emplace_back( _( "Routed Delay" ),
aFrame->MessageTextFromValue( trackDelay, true, EDA_DATA_TYPE::TIME ) );
}
}
if( lenPadToDie != 0 )
if( lenPadToDie != 0 && delayPadToDie == 0.0 )
{
msg = aFrame->MessageTextFromValue( lenPadToDie );
aList.emplace_back( _( "Pad To Die Length" ), msg );
@ -2174,6 +2382,14 @@ void PCB_TUNING_PATTERN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
msg = aFrame->MessageTextFromValue( trackLen + lenPadToDie );
aList.emplace_back( _( "Full Length" ), msg );
}
else if( delayPadToDie > 0.0 )
{
msg = aFrame->MessageTextFromValue( delayPadToDie, true, EDA_DATA_TYPE::TIME );
aList.emplace_back( _( "Pad To Die Delay" ), msg );
msg = aFrame->MessageTextFromValue( trackDelay + delayPadToDie, true, EDA_DATA_TYPE::TIME );
aList.emplace_back( _( "Full Delay" ), msg );
}
}
if( m_tuningMode == DIFF_PAIR_SKEW )
@ -2204,18 +2420,32 @@ void PCB_TUNING_PATTERN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
if( constraint.IsNull() || m_settings.m_overrideCustomRules )
{
msg = aFrame->MessageTextFromValue( (double) m_settings.m_targetLength.Opt() );
wxString caption;
aList.emplace_back( wxString::Format( _( "Target Length: %s" ), msg ),
if( m_settings.m_isTimeDomain )
{
caption = _( "Target Delay: %s" );
msg = aFrame->MessageTextFromValue( static_cast<double>( m_settings.m_targetLengthDelay.Opt() ), true,
EDA_DATA_TYPE::TIME );
}
else
{
caption = _( "Target Length: %s" );
msg = aFrame->MessageTextFromValue( static_cast<double>( m_settings.m_targetLength.Opt() ) );
}
aList.emplace_back( wxString::Format( caption, msg ),
wxString::Format( _( "(from tuning pattern properties)" ) ) );
}
else
{
msg = aFrame->MessageTextFromMinOptMax( constraint.GetValue() );
msg = aFrame->MessageTextFromMinOptMax( constraint.GetValue(), unitType );
wxString caption = m_settings.m_isTimeDomain ? _( "Delay Constraints: %s" ) : _( "Length Constraints: %s" );
if( !msg.IsEmpty() )
{
aList.emplace_back( wxString::Format( _( "Length Constraints: %s" ), msg ),
aList.emplace_back( wxString::Format( caption, msg ),
wxString::Format( _( "(from %s)" ), constraint.GetName() ) );
}
}
@ -2673,28 +2903,61 @@ static struct PCB_TUNING_PATTERN_DESC
return false;
};
auto notIsSkew =
[&]( INSPECTABLE* aItem ) -> bool
{
return !isSkew( aItem );
};
auto isTimeDomain = []( INSPECTABLE* aItem ) -> bool
{
if( PCB_TUNING_PATTERN* pattern = dynamic_cast<PCB_TUNING_PATTERN*>( aItem ) )
return pattern->GetSettings().m_isTimeDomain;
return false;
};
auto isLengthIsSpaceDomain = [&]( INSPECTABLE* aItem ) -> bool
{
return !isSkew( aItem ) && !isTimeDomain( aItem );
};
auto isLengthIsTimeDomain = [&]( INSPECTABLE* aItem ) -> bool
{
return !isSkew( aItem ) && isTimeDomain( aItem );
};
auto isSkewIsSpaceDomain = [&]( INSPECTABLE* aItem ) -> bool
{
return isSkew( aItem ) && !isTimeDomain( aItem );
};
auto isSkewIsTimeDomain = [&]( INSPECTABLE* aItem ) -> bool
{
return isSkew( aItem ) && isTimeDomain( aItem );
};
propMgr.AddProperty( new PROPERTY<PCB_TUNING_PATTERN, std::optional<int>>(
_HKI( "Target Length" ),
&PCB_TUNING_PATTERN::SetTargetLength,
&PCB_TUNING_PATTERN::GetTargetLength,
PROPERTY_DISPLAY::PT_SIZE, ORIGIN_TRANSFORMS::ABS_X_COORD ),
_HKI( "Target Length" ), &PCB_TUNING_PATTERN::SetTargetLength,
&PCB_TUNING_PATTERN::GetTargetLength, PROPERTY_DISPLAY::PT_SIZE,
ORIGIN_TRANSFORMS::ABS_X_COORD ),
groupTab )
.SetAvailableFunc( notIsSkew );
.SetAvailableFunc( isLengthIsSpaceDomain );
propMgr.AddProperty( new PROPERTY<PCB_TUNING_PATTERN, std::optional<int>>(
_HKI( "Target Delay" ), &PCB_TUNING_PATTERN::SetTargetDelay,
&PCB_TUNING_PATTERN::GetTargetDelay, PROPERTY_DISPLAY::PT_TIME,
ORIGIN_TRANSFORMS::NOT_A_COORD ),
groupTab )
.SetAvailableFunc( isLengthIsTimeDomain );
propMgr.AddProperty( new PROPERTY<PCB_TUNING_PATTERN, int>(
_HKI( "Target Skew" ), &PCB_TUNING_PATTERN::SetTargetSkew,
&PCB_TUNING_PATTERN::GetTargetSkew,
PROPERTY_DISPLAY::PT_SIZE, ORIGIN_TRANSFORMS::ABS_X_COORD ),
&PCB_TUNING_PATTERN::GetTargetSkew, PROPERTY_DISPLAY::PT_SIZE,
ORIGIN_TRANSFORMS::ABS_X_COORD ),
groupTab )
.SetAvailableFunc( isSkew );
.SetAvailableFunc( isSkewIsSpaceDomain );
propMgr.AddProperty( new PROPERTY<PCB_TUNING_PATTERN, int>(
_HKI( "Target Skew Delay" ), &PCB_TUNING_PATTERN::SetTargetSkewDelay,
&PCB_TUNING_PATTERN::GetTargetSkewDelay, PROPERTY_DISPLAY::PT_TIME,
ORIGIN_TRANSFORMS::NOT_A_COORD ),
groupTab )
.SetAvailableFunc( isSkewIsTimeDomain );
propMgr.AddProperty( new PROPERTY<PCB_TUNING_PATTERN, bool>(
_HKI( "Override Custom Rules" ),

View File

@ -1,288 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program 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.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PCBNEW_LENGTH_CALCULATION_H
#define PCBNEW_LENGTH_CALCULATION_H
#include <board_design_settings.h>
#include <geometry/shape_line_chain.h>
#include <pad.h>
#include <pcb_track.h>
#include <layer_ids.h>
#include <unordered_set>
#include <connectivity/connectivity_data.h>
class BOARD;
/**
* Lightweight class which holds a pad, via, or a routed trace outline. Proxied objects passed by pointer are not
* owned by this container.
*/
class LENGTH_CALCULATION_ITEM
{
public:
/// The type of routing object this item proxies
enum class TYPE
{
UNKNOWN,
PAD,
LINE,
VIA
};
/// Whether this item is UNMERGED, it has been merged and should be used (MERGED_IN_USE), or it has been merged
/// and has been retired from use (MERGED_RETIRED). MERGED_RETIRED essentially means the object has been merged
/// in to a MERGED_IN_USE item.
enum class MERGE_STATUS
{
UNMERGED,
MERGED_IN_USE,
MERGED_RETIRED
};
/// Gets the routing item type
TYPE Type() const { return m_type; };
/// Sets the parent PAD associated with this item
void SetPad( PAD* aPad )
{
m_type = TYPE::PAD;
m_pad = aPad;
}
/// Gets the parent PAD associated with this item
PAD* GetPad() const { return m_pad; }
/// Sets the source SHAPE_LINE_CHAIN of this item
void SetLine( const SHAPE_LINE_CHAIN& aLine )
{
m_type = TYPE::LINE;
m_line = aLine;
}
/// Gets the SHAPE_LINE_CHAIN associated with this item
SHAPE_LINE_CHAIN& GetLine() const { return m_line; }
/// Sets the VIA associated with this item
void SetVia( PCB_VIA* aVia )
{
m_type = TYPE::VIA;
m_via = aVia;
}
/// Gets the VIA associated with this item
PCB_VIA* GetVia() const { return m_via; }
/// Sets the first and last layers associated with this item
void SetLayers( const PCB_LAYER_ID aStart, const PCB_LAYER_ID aEnd = PCB_LAYER_ID::UNDEFINED_LAYER )
{
m_layerStart = aStart;
m_layerEnd = aEnd;
}
/// Sets the MERGE_STATUS of this item. MERGED_RETIRED essentially means the object has been merged
/// in to a MERGED_IN_USE item.
void SetMergeStatus( const MERGE_STATUS aStatus ) { m_mergeStatus = aStatus; }
/// Gets the MERGE_STATUS of this item
MERGE_STATUS GetMergeStatus() const { return m_mergeStatus; }
/// Gets the upper and lower layers for the proxied item
std::tuple<PCB_LAYER_ID, PCB_LAYER_ID> GetLayers() const { return { m_layerStart, m_layerEnd }; }
/// Gets the start board layer for the proxied item
PCB_LAYER_ID GetStartLayer() const { return m_layerStart; }
/// Gets the end board layer for the proxied item.
PCB_LAYER_ID GetEndLayer() const { return m_layerEnd; }
/// Calculates active via payers for a proxied VIA object
void CalculateViaLayers( const BOARD* aBoard );
protected:
/// A proxied PAD object. Set to nullptr if not proxying a PAD.
PAD* m_pad{ nullptr };
/// A proxied SHAPE_LINE_CHAIN object. Line is empty if not proxying a SHAPE_LINE_CHAIN.
mutable SHAPE_LINE_CHAIN m_line;
/// A proxied PVIAAD object. Set to nullptr if not proxying a VIA.
PCB_VIA* m_via{ nullptr };
/// The start board layer for the proxied object
PCB_LAYER_ID m_layerStart{ PCB_LAYER_ID::UNDEFINED_LAYER };
/// The end board layer for the proxied object
PCB_LAYER_ID m_layerEnd{ PCB_LAYER_ID::UNDEFINED_LAYER };
/// Flags whether this item has already been merged with another
MERGE_STATUS m_mergeStatus{ MERGE_STATUS::UNMERGED };
/// The routing object type of the proxied parent
TYPE m_type{ TYPE::UNKNOWN };
};
/**
* Holds length measurement result details and statistics
*/
struct LENGTH_DETAILS
{
int NumPads{ 0 };
int NumVias{ 0 };
int ViaLength{ 0 };
int64_t TrackLength{ 0 };
int PadToDieLength{ 0 };
std::unique_ptr<std::map<PCB_LAYER_ID, int64_t>> LayerLengths;
int64_t TotalLength() const { return ViaLength + TrackLength + PadToDieLength; }
};
/**
* Struct to control which optimisations the length calculation code runs on
* the given path objects. This is required as some call sites (e.g. PNS) run
* their own path optimisation, whereas others (e.g. Net Inspector) do not.
*/
struct PATH_OPTIMISATIONS
{
/// Optimise via layers for height calculations, ensuring only the distance
/// between routed segments is considered
bool OptimiseViaLayers = false;
/// Merges all contiguous (end-to-end, same layer) tracks
bool MergeTracks = false;
/// Optimises the electrical length of tracks within pads. Note that the track
/// must terminate at the trace anchor point to be considered for
/// optimisation. Will require MergeTracks if used with a non-contiguous item
/// set.
bool OptimiseTracesInPads = false;
/// Determines if there is a via-in-pad present on the board but not in the
/// item set. This condition can arise from the PNS meander placer.
/// TODO (JJ): This can be fixed in the router
bool InferViaInPad = false;
};
/**
* Class which calculates lengths (and associated routing statistics) in a BOARD context
*/
class LENGTH_CALCULATION
{
public:
/// Construct the calculator in the given BOARD context
explicit LENGTH_CALCULATION( BOARD* aBoard ) : m_board( aBoard ) {}
/**
* @brief Calculates the electrical length of the given items
* @param aItems is the vector of items making up the route
* @param aPathType indicates whether this is an ordered route, or an unordered collection
* @param aOptimised indicates whether this has been optimised for electrical length (e.g. clipping within pads)
* @param aStartPad is the starting pad of the route
* @param aEndPad is the ending pad of the route
*/
int64_t CalculateLength( std::vector<LENGTH_CALCULATION_ITEM>& aItems, PATH_OPTIMISATIONS aOptimisations,
const PAD* aStartPad = nullptr, const PAD* aEndPad = nullptr ) const;
/**
* @brief Calculates the electrical length of the given items
* @param aItems is the vector of items making up the route
* @param aPathType indicates whether this is an ordered route, or an unordered collection
* @param aOptimised indicates whether this has been optimised for electrical length (e.g. clipping within pads)
* @param aStartPad is the starting pad of the route
* @param aEndPad is the ending pad of the route
* @param aWithLayerLengths indicates whether the layer length structure should be populated
*/
LENGTH_DETAILS CalculateLengthDetails( std::vector<LENGTH_CALCULATION_ITEM>& aItems,
PATH_OPTIMISATIONS aOptimisations, const PAD* aStartPad = nullptr,
const PAD* aEndPad = nullptr, bool aWithLayerLengths = false ) const;
/// Optimises the given trace / line to minimise the electrical path length within the given pad
static void OptimiseTraceInPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad, PCB_LAYER_ID aPcbLayer );
/// Return a LENGTH_CALCULATION_ITEM constructed from the given BOARD_CONNECTED_ITEM
LENGTH_CALCULATION_ITEM GetLengthCalculationItem( BOARD_CONNECTED_ITEM* aBoardItem ) const;
protected:
/// The parent board for all items
BOARD* m_board;
/// Enum to describe whether track merging is attempted from the start or end of a track segment
enum class MERGE_POINT
{
START,
END
};
/**
* Returns the stackup distance between the two given layers.
*
* Note: Can return 0 if the board design settings disallow stackup height calculations
*/
int stackupHeight( PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer ) const;
/**
* Optimises the given set of items to minimise the electrical path length. At the moment
* only optimises lines attached to pads, future work could optimise paths through pads
*
* Assumes that any polylines are only connected at either end, and not at midpoints
*/
static void optimiseTracesInPads( const std::vector<LENGTH_CALCULATION_ITEM*>& aPads,
const std::vector<LENGTH_CALCULATION_ITEM*>& aLines );
/// Clips the given line to the minimal direct electrical length within the pad
static void clipLineToPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad, PCB_LAYER_ID aLayer, bool aForward = true );
/**
* Optimises the via layers. Ensures that vias that are routed through only on one layer do not count towards total
* length calculations.
*/
static void
optimiseViaLayers( const std::vector<LENGTH_CALCULATION_ITEM*>& aVias,
std::vector<LENGTH_CALCULATION_ITEM*>& aLines,
std::map<VECTOR2I, std::unordered_set<LENGTH_CALCULATION_ITEM*>>& aLinesPositionMap,
const std::map<VECTOR2I, std::unordered_set<LENGTH_CALCULATION_ITEM*>>& aPadsPositionMap );
/**
* Merges any lines (traces) that are contiguous, on one layer, and with no junctions
*/
static void mergeLines( std::vector<LENGTH_CALCULATION_ITEM*>& aLines,
std::map<VECTOR2I, std::unordered_set<LENGTH_CALCULATION_ITEM*>>& aLinesPositionMap );
/**
* Merges two SHAPE_LINE_CHAINs where there is a shared endpoing.
*
* aSecondary is merged in to aPrimary
*/
static void mergeShapeLineChains( SHAPE_LINE_CHAIN& aPrimary, const SHAPE_LINE_CHAIN& aSecondary,
MERGE_POINT aMergePoint );
/**
* Infers if there is a via in the given pad. Adds via details to the length details data structure if found.
*/
void inferViaInPad( const PAD* aPad, const LENGTH_CALCULATION_ITEM& aItem, LENGTH_DETAILS& aDetails ) const;
};
#endif //PCBNEW_LENGTH_CALCULATION_H

View File

@ -21,14 +21,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <length_calculation.h>
#include <length_delay_calculation/length_delay_calculation.h>
#include <board.h>
#include <board_design_settings.h>
#include <geometry/geometry_utils.h>
void LENGTH_CALCULATION_ITEM::CalculateViaLayers( const BOARD* aBoard )
void LENGTH_DELAY_CALCULATION_ITEM::CalculateViaLayers( const BOARD* aBoard )
{
static std::initializer_list<KICAD_T> traceAndPadTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T };
@ -53,11 +53,12 @@ void LENGTH_CALCULATION_ITEM::CalculateViaLayers( const BOARD* aBoard )
if( bottom_layer == UNDEFINED_LAYER )
bottom_layer = m_via->BottomLayer();
SetLayers( bottom_layer, top_layer );
SetLayers( top_layer, bottom_layer );
}
void LENGTH_CALCULATION::clipLineToPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad, PCB_LAYER_ID aLayer, bool aForward )
void LENGTH_DELAY_CALCULATION::clipLineToPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad, PCB_LAYER_ID aLayer,
bool aForward )
{
const int start = aForward ? 0 : aLine.PointCount() - 1;
const int delta = aForward ? 1 : -1;
@ -106,36 +107,37 @@ void LENGTH_CALCULATION::clipLineToPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad
}
LENGTH_DETAILS LENGTH_CALCULATION::CalculateLengthDetails( std::vector<LENGTH_CALCULATION_ITEM>& aItems,
const PATH_OPTIMISATIONS aOptimisations,
const PAD* aStartPad, const PAD* aEndPad,
const bool aWithLayerLengths ) const
LENGTH_DELAY_STATS LENGTH_DELAY_CALCULATION::CalculateLengthDetails( std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems,
const PATH_OPTIMISATIONS aOptimisations,
const PAD* aStartPad, const PAD* aEndPad,
const LENGTH_DELAY_LAYER_OPT aLayerOpt,
const LENGTH_DELAY_DOMAIN_OPT aDomain ) const
{
// If this set of items has not been optimised, optimise for shortest electrical path
if( aOptimisations.OptimiseViaLayers || aOptimisations.MergeTracks || aOptimisations.MergeTracks )
{
std::vector<LENGTH_CALCULATION_ITEM*> pads;
std::vector<LENGTH_CALCULATION_ITEM*> lines;
std::vector<LENGTH_CALCULATION_ITEM*> vias;
std::vector<LENGTH_DELAY_CALCULATION_ITEM*> pads;
std::vector<LENGTH_DELAY_CALCULATION_ITEM*> lines;
std::vector<LENGTH_DELAY_CALCULATION_ITEM*> vias;
// Map of line endpoints to line objects
std::map<VECTOR2I, std::unordered_set<LENGTH_CALCULATION_ITEM*>> linesPositionMap;
std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>> linesPositionMap;
// Map of pad positions to pad objects
std::map<VECTOR2I, std::unordered_set<LENGTH_CALCULATION_ITEM*>> padsPositionMap;
std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>> padsPositionMap;
for( LENGTH_CALCULATION_ITEM& item : aItems )
for( LENGTH_DELAY_CALCULATION_ITEM& item : aItems )
{
if( item.Type() == LENGTH_CALCULATION_ITEM::TYPE::PAD )
if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
{
pads.emplace_back( &item );
padsPositionMap[item.GetPad()->GetPosition()].insert( &item );
}
else if( item.Type() == LENGTH_CALCULATION_ITEM::TYPE::VIA )
else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA )
{
vias.emplace_back( &item );
}
else if( item.Type() == LENGTH_CALCULATION_ITEM::TYPE::LINE )
else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
{
lines.emplace_back( &item );
linesPositionMap[item.GetLine().CPoint( 0 )].insert( &item );
@ -153,11 +155,17 @@ LENGTH_DETAILS LENGTH_CALCULATION::CalculateLengthDetails( std::vector<LENGTH_CA
optimiseTracesInPads( pads, lines );
}
LENGTH_DETAILS details;
LENGTH_DELAY_STATS details;
if( aWithLayerLengths )
// Create the layer detail maps if required
if( aLayerOpt == LENGTH_DELAY_LAYER_OPT::WITH_LAYER_DETAIL )
{
details.LayerLengths = std::make_unique<std::map<PCB_LAYER_ID, int64_t>>();
if( aDomain == LENGTH_DELAY_DOMAIN_OPT::WITH_DELAY_DETAIL )
details.LayerDelays = std::make_unique<std::map<PCB_LAYER_ID, int64_t>>();
}
const bool useHeight = m_board->GetDesignSettings().m_UseHeightForLengthCalcs;
// If this is a contiguous set of items, check if we have an inferred fanout via at either end. Note that this
@ -170,16 +178,17 @@ LENGTH_DETAILS LENGTH_CALCULATION::CalculateLengthDetails( std::vector<LENGTH_CA
}
// Add stats for each item
for( const LENGTH_CALCULATION_ITEM& item : aItems )
for( const LENGTH_DELAY_CALCULATION_ITEM& item : aItems )
{
// Don't include merged items
if( item.GetMergeStatus() == LENGTH_CALCULATION_ITEM::MERGE_STATUS::MERGED_RETIRED
|| item.Type() == LENGTH_CALCULATION_ITEM::TYPE::UNKNOWN )
if( item.GetMergeStatus() == LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::MERGED_RETIRED
|| item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::UNKNOWN )
{
continue;
}
if( item.Type() == LENGTH_CALCULATION_ITEM::TYPE::LINE )
// Calculate the space domain statistics
if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
{
const int64_t length = item.GetLine().Length();
@ -188,27 +197,60 @@ LENGTH_DETAILS LENGTH_CALCULATION::CalculateLengthDetails( std::vector<LENGTH_CA
if( details.LayerLengths )
( *details.LayerLengths )[item.GetStartLayer()] += length;
}
else if( item.Type() == LENGTH_CALCULATION_ITEM::TYPE::VIA && useHeight )
else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA && useHeight )
{
const auto [layerStart, layerEnd] = item.GetLayers();
details.ViaLength += stackupHeight( layerStart, layerEnd );
details.ViaLength += StackupHeight( layerStart, layerEnd );
details.NumVias += 1;
}
else if( item.Type() == LENGTH_CALCULATION_ITEM::TYPE::PAD )
else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
{
details.PadToDieLength += item.GetPad()->GetPadToDieLength();
details.NumPads += 1;
}
}
// Calculate the time domain statistics if required
if( aDomain == LENGTH_DELAY_DOMAIN_OPT::WITH_DELAY_DETAIL )
{
// TODO(JJ): Populate this
TIME_DOMAIN_GEOMETRY_CONTEXT ctx;
ctx.NetClass = aItems.front().GetEffectiveNetClass(); // We don't care if this is merged for net class lookup
const std::vector<int64_t> itemDelays = m_timeDomainParameters->GetPropagationDelays( aItems, ctx );
wxASSERT( itemDelays.size() == aItems.size() );
for( size_t i = 0; i < aItems.size(); ++i )
{
const LENGTH_DELAY_CALCULATION_ITEM& item = aItems[i];
if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
{
details.TrackDelay += itemDelays[i];
if( details.LayerDelays )
( *details.LayerDelays )[item.GetStartLayer()] += itemDelays[i];
}
else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA && useHeight )
{
details.ViaDelay += itemDelays[i];
}
else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
{
details.PadToDieDelay += itemDelays[i];
}
}
}
return details;
}
void LENGTH_CALCULATION::inferViaInPad( const PAD* aPad, const LENGTH_CALCULATION_ITEM& aItem,
LENGTH_DETAILS& aDetails ) const
void LENGTH_DELAY_CALCULATION::inferViaInPad( const PAD* aPad, const LENGTH_DELAY_CALCULATION_ITEM& aItem,
LENGTH_DELAY_STATS& aDetails ) const
{
if( aPad && aItem.Type() == LENGTH_CALCULATION_ITEM::TYPE::LINE )
if( aPad && aItem.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
{
const PCB_LAYER_ID startBottomLayer = aItem.GetStartLayer();
const LSET padLayers = aPad->Padstack().LayerSet();
@ -219,21 +261,31 @@ void LENGTH_CALCULATION::inferViaInPad( const PAD* aPad, const LENGTH_CALCULATIO
const PCB_LAYER_ID padLayer = padLayers.Contains( F_Cu ) ? F_Cu : B_Cu;
aDetails.NumVias += 1;
aDetails.ViaLength += stackupHeight( startBottomLayer, padLayer );
aDetails.ViaLength += StackupHeight( startBottomLayer, padLayer );
}
}
}
int64_t LENGTH_CALCULATION::CalculateLength( std::vector<LENGTH_CALCULATION_ITEM>& aItems,
const PATH_OPTIMISATIONS aOptimisations, const PAD* aStartPad,
const PAD* aEndPad ) const
int64_t LENGTH_DELAY_CALCULATION::CalculateLength( std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems,
const PATH_OPTIMISATIONS aOptimisations, const PAD* aStartPad,
const PAD* aEndPad ) const
{
return CalculateLengthDetails( aItems, aOptimisations, aStartPad, aEndPad ).TotalLength();
}
int LENGTH_CALCULATION::stackupHeight( const PCB_LAYER_ID aFirstLayer, const PCB_LAYER_ID aSecondLayer ) const
int64_t LENGTH_DELAY_CALCULATION::CalculateDelay( std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems,
const PATH_OPTIMISATIONS aOptimisations, const PAD* aStartPad,
const PAD* aEndPad ) const
{
return CalculateLengthDetails( aItems, aOptimisations, aStartPad, aEndPad, LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL,
LENGTH_DELAY_DOMAIN_OPT::WITH_DELAY_DETAIL )
.TotalDelay();
}
int LENGTH_DELAY_CALCULATION::StackupHeight( const PCB_LAYER_ID aFirstLayer, const PCB_LAYER_ID aSecondLayer ) const
{
if( !m_board || !m_board->GetDesignSettings().m_UseHeightForLengthCalcs )
return 0;
@ -252,23 +304,23 @@ int LENGTH_CALCULATION::stackupHeight( const PCB_LAYER_ID aFirstLayer, const PCB
}
void LENGTH_CALCULATION::mergeLines(
std::vector<LENGTH_CALCULATION_ITEM*>& aLines,
std::map<VECTOR2I, std::unordered_set<LENGTH_CALCULATION_ITEM*>>& aLinesPositionMap )
void LENGTH_DELAY_CALCULATION::mergeLines(
std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines,
std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aLinesPositionMap )
{
// Vector of pads, and an associated flag to indicate whether they have been visited by the clustering algorithm
std::vector<LENGTH_CALCULATION_ITEM*> pads;
std::vector<LENGTH_DELAY_CALCULATION_ITEM*> pads;
auto removeFromPositionMap = [&aLinesPositionMap]( LENGTH_CALCULATION_ITEM* line )
auto removeFromPositionMap = [&aLinesPositionMap]( LENGTH_DELAY_CALCULATION_ITEM* line )
{
aLinesPositionMap[line->GetLine().CPoint( 0 )].erase( line );
aLinesPositionMap[line->GetLine().CLastPoint()].erase( line );
};
// Attempts to merge unmerged lines in to aPrimaryLine
auto tryMerge = [&removeFromPositionMap, &aLinesPositionMap]( const MERGE_POINT aMergePoint,
const VECTOR2I& aMergePos,
const LENGTH_CALCULATION_ITEM* aPrimaryItem,
auto tryMerge = [&removeFromPositionMap, &aLinesPositionMap]( const MERGE_POINT aMergePoint,
const VECTOR2I& aMergePos,
const LENGTH_DELAY_CALCULATION_ITEM* aPrimaryItem,
SHAPE_LINE_CHAIN& aPrimaryLine, bool* aDidMerge )
{
const auto startItr = aLinesPositionMap.find( aMergePos );
@ -276,12 +328,12 @@ void LENGTH_CALCULATION::mergeLines(
if( startItr == aLinesPositionMap.end() )
return;
std::unordered_set<LENGTH_CALCULATION_ITEM*>& startItems = startItr->second;
std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>& startItems = startItr->second;
if( startItems.size() != 1 )
return;
LENGTH_CALCULATION_ITEM* lineToMerge = *startItems.begin();
LENGTH_DELAY_CALCULATION_ITEM* lineToMerge = *startItems.begin();
// Don't merge if line is an arc
if( !lineToMerge->GetLine().CArcs().empty() )
@ -292,17 +344,17 @@ void LENGTH_CALCULATION::mergeLines(
return;
// Merge the lines
lineToMerge->SetMergeStatus( LENGTH_CALCULATION_ITEM::MERGE_STATUS::MERGED_RETIRED );
lineToMerge->SetMergeStatus( LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::MERGED_RETIRED );
mergeShapeLineChains( aPrimaryLine, lineToMerge->GetLine(), aMergePoint );
removeFromPositionMap( lineToMerge );
*aDidMerge = true;
};
// Cluster all lines in to contiguous entities
for( LENGTH_CALCULATION_ITEM* primaryItem : aLines )
for( LENGTH_DELAY_CALCULATION_ITEM* primaryItem : aLines )
{
// Don't start with an already merged line
if( primaryItem->GetMergeStatus() != LENGTH_CALCULATION_ITEM::MERGE_STATUS::UNMERGED )
if( primaryItem->GetMergeStatus() != LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::UNMERGED )
continue;
// Remove starting line from the position map
@ -311,7 +363,7 @@ void LENGTH_CALCULATION::mergeLines(
SHAPE_LINE_CHAIN& primaryLine = primaryItem->GetLine();
// Merge all endpoints
primaryItem->SetMergeStatus( LENGTH_CALCULATION_ITEM::MERGE_STATUS::MERGED_IN_USE );
primaryItem->SetMergeStatus( LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::MERGED_IN_USE );
bool mergeComplete = false;
while( !mergeComplete )
@ -331,8 +383,8 @@ void LENGTH_CALCULATION::mergeLines(
}
void LENGTH_CALCULATION::mergeShapeLineChains( SHAPE_LINE_CHAIN& aPrimary, const SHAPE_LINE_CHAIN& aSecondary,
const MERGE_POINT aMergePoint )
void LENGTH_DELAY_CALCULATION::mergeShapeLineChains( SHAPE_LINE_CHAIN& aPrimary, const SHAPE_LINE_CHAIN& aSecondary,
const MERGE_POINT aMergePoint )
{
if( aMergePoint == MERGE_POINT::START )
{
@ -367,17 +419,17 @@ void LENGTH_CALCULATION::mergeShapeLineChains( SHAPE_LINE_CHAIN& aPrimary, const
}
void LENGTH_CALCULATION::optimiseTracesInPads( const std::vector<LENGTH_CALCULATION_ITEM*>& aPads,
const std::vector<LENGTH_CALCULATION_ITEM*>& aLines )
void LENGTH_DELAY_CALCULATION::optimiseTracesInPads( const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aPads,
const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines )
{
for( LENGTH_CALCULATION_ITEM* padItem : aPads )
for( LENGTH_DELAY_CALCULATION_ITEM* padItem : aPads )
{
PAD* pad = padItem->GetPad();
const PAD* pad = padItem->GetPad();
for( LENGTH_CALCULATION_ITEM* lineItem : aLines )
for( LENGTH_DELAY_CALCULATION_ITEM* lineItem : aLines )
{
// Ignore merged lines
if( lineItem->GetMergeStatus() != LENGTH_CALCULATION_ITEM::MERGE_STATUS::MERGED_IN_USE )
if( lineItem->GetMergeStatus() != LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::MERGED_IN_USE )
continue;
const PCB_LAYER_ID pcbLayer = lineItem->GetStartLayer();
@ -389,19 +441,19 @@ void LENGTH_CALCULATION::optimiseTracesInPads( const std::vector<LENGTH_CALCULAT
}
void LENGTH_CALCULATION::optimiseViaLayers(
const std::vector<LENGTH_CALCULATION_ITEM*>& aVias, std::vector<LENGTH_CALCULATION_ITEM*>& aLines,
std::map<VECTOR2I, std::unordered_set<LENGTH_CALCULATION_ITEM*>>& aLinesPositionMap,
const std::map<VECTOR2I, std::unordered_set<LENGTH_CALCULATION_ITEM*>>& aPadsPositionMap )
void LENGTH_DELAY_CALCULATION::optimiseViaLayers(
const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aVias, std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines,
std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aLinesPositionMap,
const std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aPadsPositionMap )
{
for( LENGTH_CALCULATION_ITEM* via : aVias )
for( LENGTH_DELAY_CALCULATION_ITEM* via : aVias )
{
auto lineItr = aLinesPositionMap.find( via->GetVia()->GetPosition() );
if( lineItr == aLinesPositionMap.end() )
continue;
std::unordered_set<LENGTH_CALCULATION_ITEM*>& connectedLines = lineItr->second;
std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>& connectedLines = lineItr->second;
if( connectedLines.empty() )
{
@ -419,11 +471,11 @@ void LENGTH_CALCULATION::optimiseViaLayers(
if( padItr != aPadsPositionMap.end() )
{
// This could be a via-in-pad - check for overlapping pads which are not on the line layer
const std::unordered_set<LENGTH_CALCULATION_ITEM*>& pads = padItr->second;
const std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>& pads = padItr->second;
if( pads.size() == 1 )
{
const LENGTH_CALCULATION_ITEM* padItem = *pads.begin();
const LENGTH_DELAY_CALCULATION_ITEM* padItem = *pads.begin();
if( !padItem->GetPad()->Padstack().LayerSet().Contains( lineLayer ) )
{
@ -446,7 +498,7 @@ void LENGTH_CALCULATION::optimiseViaLayers(
// than the overall via span)
LSET layers;
for( const LENGTH_CALCULATION_ITEM* lineItem : connectedLines )
for( const LENGTH_DELAY_CALCULATION_ITEM* lineItem : connectedLines )
layers.set( lineItem->GetStartLayer() );
LSEQ cuStack = layers.CuStack();
@ -471,7 +523,8 @@ void LENGTH_CALCULATION::optimiseViaLayers(
}
void LENGTH_CALCULATION::OptimiseTraceInPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad, const PCB_LAYER_ID aPcbLayer )
void LENGTH_DELAY_CALCULATION::OptimiseTraceInPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad,
const PCB_LAYER_ID aPcbLayer )
{
// Only consider lines which terminate in the pad
if( aLine.CPoint( 0 ) != aPad->GetPosition() && aLine.CLastPoint() != aPad->GetPosition() )
@ -489,31 +542,34 @@ void LENGTH_CALCULATION::OptimiseTraceInPad( SHAPE_LINE_CHAIN& aLine, const PAD*
}
LENGTH_CALCULATION_ITEM LENGTH_CALCULATION::GetLengthCalculationItem( BOARD_CONNECTED_ITEM* aBoardItem ) const
LENGTH_DELAY_CALCULATION_ITEM
LENGTH_DELAY_CALCULATION::GetLengthCalculationItem( const BOARD_CONNECTED_ITEM* aBoardItem ) const
{
if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( aBoardItem ) )
if( const PCB_TRACK* track = dynamic_cast<const PCB_TRACK*>( aBoardItem ) )
{
if( track->Type() == PCB_VIA_T )
{
PCB_VIA* via = static_cast<PCB_VIA*>( track );
const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
LENGTH_CALCULATION_ITEM item;
LENGTH_DELAY_CALCULATION_ITEM item;
item.SetVia( via );
item.CalculateViaLayers( m_board );
item.SetEffectiveNetClass( via->GetEffectiveNetClass() );
return item;
}
if( track->Type() == PCB_ARC_T )
{
PCB_ARC* arcParent = static_cast<PCB_ARC*>( track );
const PCB_ARC* arcParent = static_cast<const PCB_ARC*>( track );
SHAPE_ARC shapeArc( arcParent->GetStart(), arcParent->GetMid(), arcParent->GetEnd(),
arcParent->GetWidth() );
SHAPE_LINE_CHAIN chainArc( shapeArc );
LENGTH_CALCULATION_ITEM item;
LENGTH_DELAY_CALCULATION_ITEM item;
item.SetLine( chainArc );
item.SetLayers( track->GetLayer() );
item.SetEffectiveNetClass( arcParent->GetEffectiveNetClass() );
return item;
}
@ -523,19 +579,20 @@ LENGTH_CALCULATION_ITEM LENGTH_CALCULATION::GetLengthCalculationItem( BOARD_CONN
std::vector<VECTOR2I> points{ track->GetStart(), track->GetEnd() };
SHAPE_LINE_CHAIN shape( points );
LENGTH_CALCULATION_ITEM item;
LENGTH_DELAY_CALCULATION_ITEM item;
item.SetLine( shape );
item.SetLayers( track->GetLayer() );
item.SetEffectiveNetClass( track->GetEffectiveNetClass() );
return item;
}
}
else if( PAD* pad = dynamic_cast<PAD*>( aBoardItem ) )
else if( const PAD* pad = dynamic_cast<const PAD*>( aBoardItem ) )
{
LENGTH_CALCULATION_ITEM item;
LENGTH_DELAY_CALCULATION_ITEM item;
item.SetPad( pad );
LSET& layers = pad->Padstack().LayerSet();
const LSET& layers = pad->Padstack().LayerSet();
PCB_LAYER_ID firstLayer = UNDEFINED_LAYER;
PCB_LAYER_ID secondLayer = UNDEFINED_LAYER;
@ -548,9 +605,38 @@ LENGTH_CALCULATION_ITEM LENGTH_CALCULATION::GetLengthCalculationItem( BOARD_CONN
}
item.SetLayers( firstLayer, secondLayer );
item.SetEffectiveNetClass( pad->GetEffectiveNetClass() );
return item;
}
return {};
}
void LENGTH_DELAY_CALCULATION::SetTimeDomainParametersProvider(
std::unique_ptr<TIME_DOMAIN_PARAMETERS_IFACE>&& aProvider )
{
m_timeDomainParameters = std::move( aProvider );
}
void LENGTH_DELAY_CALCULATION::SynchronizeTimeDomainProperties() const
{
m_timeDomainParameters->OnSettingsChanged();
}
int64_t LENGTH_DELAY_CALCULATION::CalculateLengthForDelay( const int64_t aDesiredDelay,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const
{
return m_timeDomainParameters->GetTrackLengthForPropagationDelay( aDesiredDelay, aCtx );
}
int64_t
LENGTH_DELAY_CALCULATION::CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const
{
return m_timeDomainParameters->CalculatePropagationDelayForShapeLineChain( aShape, aCtx );
}

View File

@ -0,0 +1,266 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program 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.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PCBNEW_LENGTH_DELAY_CALCULATION_H
#define PCBNEW_LENGTH_DELAY_CALCULATION_H
#include "time_domain_parameters_iface.h"
#include "time_domain_parameters_user_defined.h"
#include <board_design_settings.h>
#include <connectivity/connectivity_data.h>
#include <length_delay_calculation/length_delay_calculation_item.h>
#include <unordered_set>
class BOARD;
/**
* Holds length measurement result details and statistics
*/
struct LENGTH_DELAY_STATS
{
// Generic statistics
int NumPads{ 0 };
int NumVias{ 0 };
// Space domain statistics
int ViaLength{ 0 };
int64_t TrackLength{ 0 };
int PadToDieLength{ 0 };
std::unique_ptr<std::map<PCB_LAYER_ID, int64_t>> LayerLengths;
/// Calculates the total electrical length for this set of statistics
int64_t TotalLength() const { return ViaLength + TrackLength + PadToDieLength; }
// Time domain statistics
int64_t ViaDelay{ 0 };
int64_t TrackDelay{ 0 };
int64_t PadToDieDelay{ 0 };
std::unique_ptr<std::map<PCB_LAYER_ID, int64_t>> LayerDelays;
/// Calculates the total electrical propagation delay for this set of statistics
int64_t TotalDelay() const { return ViaDelay + TrackDelay + PadToDieDelay; }
};
/**
* Struct to control which optimisations the length calculation code runs on
* the given path objects. This is required as some call sites (e.g. PNS) run
* their own path optimisation, whereas others (e.g. Net Inspector) do not.
*/
struct PATH_OPTIMISATIONS
{
/// Optimise via layers for height calculations, ensuring only the distance
/// between routed segments is considered
bool OptimiseViaLayers = false;
/// Merges all contiguous (end-to-end, same layer) tracks
bool MergeTracks = false;
/// Optimises the electrical length of tracks within pads. Note that the track
/// must terminate at the trace anchor point to be considered for
/// optimisation. Will require MergeTracks if used with a non-contiguous item
/// set.
bool OptimiseTracesInPads = false;
/// Determines if there is a via-in-pad present on the board but not in the
/// item set. This condition can arise from the PNS meander placer.
/// TODO (JJ): This can be fixed in the router
bool InferViaInPad = false;
};
/**
* Enum which controls the level of detail returned by the length / delay calculation methods.
*
* NO_LAYER_DETAIL: Only returns totals, without populating the layer length / delay detail maps
* WITH_LAYER_DETAIL: Populates the layer lengths / delay detail maps
*/
enum class LENGTH_DELAY_LAYER_OPT
{
NO_LAYER_DETAIL,
WITH_LAYER_DETAIL
};
/**
* Enum which controls the calculation domain of the length / delay calculation methods.
*
* NO_DELAY_DETAIL: Only calculates space domain (e.g. length) details
* WITH_DELAY_DETAIL: Calculates space and time domain (e.g. length and delay) details
*/
enum class LENGTH_DELAY_DOMAIN_OPT
{
NO_DELAY_DETAIL,
WITH_DELAY_DETAIL
};
/**
* Class which calculates lengths (and associated routing statistics) in a BOARD context
*/
class LENGTH_DELAY_CALCULATION
{
public:
/**
* Construct the calculator in the given BOARD context. Also constructs a default user-defined time domain
* parameters provider
*/
explicit LENGTH_DELAY_CALCULATION( BOARD* aBoard ) :
m_board( aBoard ),
m_timeDomainParameters( std::make_unique<TIME_DOMAIN_PARAMETERS_USER_DEFINED>( aBoard, this ) )
{
}
/**
* @brief Calculates the electrical length of the given items
*
* @param aItems is the vector of items making up the route
* @param aOptimisations details the electrical path optimisations that should be applied to the board items
* @param aStartPad is the starting pad of the route
* @param aEndPad is the ending pad of the route
*/
int64_t CalculateLength( std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems, PATH_OPTIMISATIONS aOptimisations,
const PAD* aStartPad = nullptr, const PAD* aEndPad = nullptr ) const;
/**
* @brief Calculates the electrical propagation delay of the given items
*
* @param aItems is the vector of items making up the route
* @param aOptimisations details the electrical path optimisations that should be applied to the board items
* @param aStartPad is the starting pad of the route
* @param aEndPad is the ending pad of the route
*/
int64_t CalculateDelay( std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems, PATH_OPTIMISATIONS aOptimisations,
const PAD* aStartPad = nullptr, const PAD* aEndPad = nullptr ) const;
/**
* @brief Calculates the electrical length of the given items
*
* @param aItems is the vector of items making up the route
* @param aOptimisations details the electrical path optimisations that should be applied to the board items
* @param aStartPad is the starting pad of the route
* @param aEndPad is the ending pad of the route
* @param aLayerOpt determines whether the layer details map is populated
* @param aDomain determines whether calculations include time domain (delay) details
*/
LENGTH_DELAY_STATS
CalculateLengthDetails( std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems, PATH_OPTIMISATIONS aOptimisations,
const PAD* aStartPad = nullptr, const PAD* aEndPad = nullptr,
LENGTH_DELAY_LAYER_OPT aLayerOpt = LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL,
LENGTH_DELAY_DOMAIN_OPT aDomain = LENGTH_DELAY_DOMAIN_OPT::NO_DELAY_DETAIL ) const;
/**
* Gets the propagation delay for the given shape line chain
*
* @param aShape is the shape to calculate delay for
* @param aCtx is the geometry context for which to query to propagation delay
*/
int64_t CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const;
/**
* @brief Calculates the length of track required for the given delay in a specific geometry context
*
* @param aDesiredDelay is the desired track delay (in IU)
* @param aCtx is the track geometry context to calculate propagation velocitiy against
*/
int64_t CalculateLengthForDelay( int64_t aDesiredDelay, const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const;
/// Optimises the given trace / line to minimise the electrical path length within the given pad
static void OptimiseTraceInPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad, PCB_LAYER_ID aPcbLayer );
/// Return a LENGTH_CALCULATION_ITEM constructed from the given BOARD_CONNECTED_ITEM
LENGTH_DELAY_CALCULATION_ITEM GetLengthCalculationItem( const BOARD_CONNECTED_ITEM* aBoardItem ) const;
/// Sets the provider for time domain parameter resolution
void SetTimeDomainParametersProvider( std::unique_ptr<TIME_DOMAIN_PARAMETERS_IFACE>&& aProvider );
/// Ensure time domain properties provider is synced with board / project settings if required
void SynchronizeTimeDomainProperties() const;
/**
* Returns the stackup distance between the two given layers.
*
* Note: Can return 0 if the board design settings disallow stackup height calculations
*/
int StackupHeight( PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer ) const;
protected:
/// The parent board for all items
BOARD* m_board;
/// The active provider of time domain parameters
std::unique_ptr<TIME_DOMAIN_PARAMETERS_IFACE> m_timeDomainParameters;
/// Enum to describe whether track merging is attempted from the start or end of a track segment
enum class MERGE_POINT
{
START,
END
};
/**
* Optimises the given set of items to minimise the electrical path length. At the moment
* only optimises lines attached to pads, future work could optimise paths through pads
*
* Assumes that any polylines are only connected at either end, and not at midpoints
*/
static void optimiseTracesInPads( const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aPads,
const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines );
/// Clips the given line to the minimal direct electrical length within the pad
static void clipLineToPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad, PCB_LAYER_ID aLayer, bool aForward = true );
/**
* Optimises the via layers. Ensures that vias that are routed through only on one layer do not count towards total
* length calculations.
*/
static void
optimiseViaLayers( const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aVias,
std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines,
std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aLinesPositionMap,
const std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aPadsPositionMap );
/**
* Merges any lines (traces) that are contiguous, on one layer, and with no junctions
*/
static void mergeLines( std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines,
std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aLinesPositionMap );
/**
* Merges two SHAPE_LINE_CHAINs where there is a shared endpoing.
*
* aSecondary is merged in to aPrimary
*/
static void mergeShapeLineChains( SHAPE_LINE_CHAIN& aPrimary, const SHAPE_LINE_CHAIN& aSecondary,
MERGE_POINT aMergePoint );
/**
* Infers if there is a via in the given pad. Adds via details to the length details data structure if found.
*/
void inferViaInPad( const PAD* aPad, const LENGTH_DELAY_CALCULATION_ITEM& aItem,
LENGTH_DELAY_STATS& aDetails ) const;
};
#endif //PCBNEW_LENGTH_DELAY_CALCULATION_H

View File

@ -0,0 +1,55 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program 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.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <length_delay_calculation/length_delay_calculation_item.h>
#include <board.h>
void LENGTH_DELAY_CALCULATION_ITEM::CalculateViaLayers( const BOARD* aBoard )
{
static std::initializer_list<KICAD_T> traceAndPadTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T };
PCB_LAYER_ID top_layer = UNDEFINED_LAYER;
PCB_LAYER_ID bottom_layer = UNDEFINED_LAYER;
const LSET layers = aBoard->GetDesignSettings().GetEnabledLayers();
for( auto layer_it = layers.copper_layers_begin(); layer_it != layers.copper_layers_end(); ++layer_it )
{
if( aBoard->GetConnectivity()->IsConnectedOnLayer( m_via, *layer_it, traceAndPadTypes ) )
{
if( top_layer == UNDEFINED_LAYER )
top_layer = *layer_it;
else
bottom_layer = *layer_it;
}
}
if( top_layer == UNDEFINED_LAYER )
top_layer = m_via->TopLayer();
if( bottom_layer == UNDEFINED_LAYER )
bottom_layer = m_via->BottomLayer();
SetLayers( bottom_layer, top_layer );
}

View File

@ -0,0 +1,158 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program 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.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PCBNEW_LENGTH_DELAY_CALCULATION_ITEM_H
#define PCBNEW_LENGTH_DELAY_CALCULATION_ITEM_H
#include <geometry/shape_line_chain.h>
#include <layer_ids.h>
#include <pad.h>
#include <pcb_track.h>
/**
* Lightweight class which holds a pad, via, or a routed trace outline. Proxied objects passed by pointer are not
* owned by this container.
*/
class LENGTH_DELAY_CALCULATION_ITEM
{
public:
/// The type of routing object this item proxies
enum class TYPE
{
UNKNOWN,
PAD,
LINE,
VIA
};
/// Whether this item is UNMERGED, it has been merged and should be used (MERGED_IN_USE), or it has been merged
/// and has been retired from use (MERGED_RETIRED). MERGED_RETIRED essentially means the object has been merged
/// in to a MERGED_IN_USE item.
enum class MERGE_STATUS
{
UNMERGED,
MERGED_IN_USE,
MERGED_RETIRED
};
/// Gets the routing item type
TYPE Type() const { return m_type; };
/// Sets the parent PAD associated with this item
void SetPad( const PAD* aPad )
{
m_type = TYPE::PAD;
m_pad = aPad;
}
/// Gets the parent PAD associated with this item
const PAD* GetPad() const { return m_pad; }
/// Sets the source SHAPE_LINE_CHAIN of this item
void SetLine( const SHAPE_LINE_CHAIN& aLine )
{
m_type = TYPE::LINE;
m_line = aLine;
}
/// Gets the SHAPE_LINE_CHAIN associated with this item
SHAPE_LINE_CHAIN& GetLine() const { return m_line; }
/// Sets the VIA associated with this item
void SetVia( const PCB_VIA* aVia )
{
m_type = TYPE::VIA;
m_via = aVia;
}
/// Gets the VIA associated with this item
const PCB_VIA* GetVia() const { return m_via; }
/// Sets the first and last layers associated with this item. Always stores in copper layer order
/// (F_Cu to B_Cu)
void SetLayers( const PCB_LAYER_ID aStart, const PCB_LAYER_ID aEnd = PCB_LAYER_ID::UNDEFINED_LAYER )
{
if( aEnd != UNDEFINED_LAYER && IsCopperLayerLowerThan( aStart, aEnd ) )
{
m_layerStart = aEnd;
m_layerEnd = aStart;
}
else
{
m_layerStart = aStart;
m_layerEnd = aEnd;
}
}
/// Sets the MERGE_STATUS of this item. MERGED_RETIRED essentially means the object has been merged
/// in to a MERGED_IN_USE item.
void SetMergeStatus( const MERGE_STATUS aStatus ) { m_mergeStatus = aStatus; }
/// Gets the MERGE_STATUS of this item
MERGE_STATUS GetMergeStatus() const { return m_mergeStatus; }
/// Gets the upper and lower layers for the proxied item
std::tuple<PCB_LAYER_ID, PCB_LAYER_ID> GetLayers() const { return { m_layerStart, m_layerEnd }; }
/// Gets the start board layer for the proxied item
PCB_LAYER_ID GetStartLayer() const { return m_layerStart; }
/// Gets the end board layer for the proxied item.
PCB_LAYER_ID GetEndLayer() const { return m_layerEnd; }
/// Calculates active via payers for a proxied VIA object
void CalculateViaLayers( const BOARD* aBoard );
/// Sets the effective net class for the item
void SetEffectiveNetClass( const NETCLASS* aNetClass ) { m_netClass = aNetClass; }
/// Returns the effective net class for the item
const NETCLASS* GetEffectiveNetClass() const { return m_netClass; }
protected:
/// A proxied PAD object. Set to nullptr if not proxying a PAD.
const PAD* m_pad{ nullptr };
/// A proxied SHAPE_LINE_CHAIN object. Line is empty if not proxying a SHAPE_LINE_CHAIN.
mutable SHAPE_LINE_CHAIN m_line;
/// A proxied PCB_VIA object. Set to nullptr if not proxying a VIA.
const PCB_VIA* m_via{ nullptr };
/// The start board layer for the proxied object
PCB_LAYER_ID m_layerStart{ PCB_LAYER_ID::UNDEFINED_LAYER };
/// The end board layer for the proxied object
PCB_LAYER_ID m_layerEnd{ PCB_LAYER_ID::UNDEFINED_LAYER };
/// Flags whether this item has already been merged with another
MERGE_STATUS m_mergeStatus{ MERGE_STATUS::UNMERGED };
/// The routing object type of the proxied parent
TYPE m_type{ TYPE::UNKNOWN };
/// The net class of the object
const NETCLASS* m_netClass{ nullptr };
};
#endif //PCBNEW_LENGTH_DELAY_CALCULATION_ITEM_H

View File

@ -0,0 +1,126 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program 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.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PCBNEW_TIME_DOMAIN_PARAMETERS_INTERFACE_H
#define PCBNEW_TIME_DOMAIN_PARAMETERS_INTERFACE_H
#include <length_delay_calculation/length_delay_calculation_item.h>
#include <netclass.h>
class LENGTH_DELAY_CALCULATION;
/**
* A data structure to contain basic geometry data which can affect signal propagation calculations.
*/
struct TIME_DOMAIN_GEOMETRY_CONTEXT
{
/// The net class this track belongs to
const NETCLASS* NetClass;
/// The layer this track is on
PCB_LAYER_ID Layer;
/// The width (in internal units) of the track
int64_t Width;
/// Whether this track or via is a member of a coupled differential pair
bool IsDiffPairCoupled{ false };
/// The gap between coupled tracks
int64_t DiffPairCouplingGap{ 0 };
};
/**
* Interface for providers of time domain parameter information. This interface is consumed by the
* LENGTH_TIME_CALCULATOR object to convert space-domain physical layout informaton (e.g. track lengths) in to
* time-domain propagation information.
*/
class TIME_DOMAIN_PARAMETERS_IFACE
{
public:
explicit TIME_DOMAIN_PARAMETERS_IFACE( BOARD* aBoard, LENGTH_DELAY_CALCULATION* aCalculation ) :
m_board{ aBoard }, m_lengthCalculation{ aCalculation }
{
}
virtual ~TIME_DOMAIN_PARAMETERS_IFACE() = default;
/**
* Event called by the length and time calculation architecture if the board stackup has changed. This can be used
* to invalidate any calculation / simulation caches.
*/
virtual void OnStackupChanged() {};
/**
* Event called by the length and time calculation architecture if netclass definitions have changed. This can be
* used to invalidate any calculation / simulation caches.
*/
virtual void OnSettingsChanged() {};
/**
* Gets the propagation delays (in internal units) for the given items in the given geometry context
*
* @param aItems the board items to query propagation delay for
* @param aContext the geometry context in which to query to propagation delay
*/
virtual std::vector<int64_t> GetPropagationDelays( const std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) = 0;
/**
* Gets the propagation delay (in internal units) for the given item in the given geometry context
*
* @param aItem the board item to query propagation delay for
* @param aContext is the geometry context in which to query to propagation delay
*/
virtual int64_t GetPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) = 0;
/**
* Gets the track length (in internal distance units) required for the given propagation delay (in internal time
* units). The track length should be calculated with the given geometry context.
*
* @param aContext the geometry context in which to query to propagation delay
* @param aDelay the propagation delay for which a length should be calculated
*/
virtual int64_t GetTrackLengthForPropagationDelay( int64_t aDelay,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) = 0;
/**
* Gets the propagation delay for the given shape line chain
*
* @param aShape is the shape to calculate delay for
* @param aContext is the geometry context for which to query to propagation delay
*/
virtual int64_t CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) = 0;
protected:
/// The board all calculations are for
BOARD* m_board;
/// The parent length / delay calculation object
LENGTH_DELAY_CALCULATION* m_lengthCalculation;
};
#endif //PCBNEW_TIME_DOMAIN_PARAMETERS_INTERFACE_H

View File

@ -0,0 +1,190 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program 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.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <board.h>
#include <length_delay_calculation/time_domain_parameters_user_defined.h>
#include <project/project_file.h>
void TIME_DOMAIN_PARAMETERS_USER_DEFINED::OnSettingsChanged()
{
rebuildCaches();
}
std::vector<int64_t>
TIME_DOMAIN_PARAMETERS_USER_DEFINED::GetPropagationDelays( const std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext )
{
if( aItems.empty() )
return {};
const wxString tuningProfileName = aItems.front().GetEffectiveNetClass()->GetTuningProfile();
const TIME_DOMAIN_TUNING_PROFILE* tuningProfile = getTuningProfile( tuningProfileName );
if( !tuningProfile )
return std::vector<int64_t>( aItems.size(), 0 );
std::vector<int64_t> propagationDelays;
propagationDelays.reserve( aItems.size() );
for( const LENGTH_DELAY_CALCULATION_ITEM& item : aItems )
propagationDelays.emplace_back( getPropagationDelay( item, aContext, tuningProfile ) );
return propagationDelays;
}
int64_t TIME_DOMAIN_PARAMETERS_USER_DEFINED::GetPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext )
{
if( aItem.GetMergeStatus() == LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::MERGED_RETIRED )
return 0;
const wxString tuningProfileName = aItem.GetEffectiveNetClass()->GetTuningProfile();
const TIME_DOMAIN_TUNING_PROFILE* tuningProfile = getTuningProfile( tuningProfileName );
if( !tuningProfile )
return 0;
return getPropagationDelay( aItem, aContext, tuningProfile );
}
int64_t
TIME_DOMAIN_PARAMETERS_USER_DEFINED::getPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext,
const TIME_DOMAIN_TUNING_PROFILE* aTuningProfile ) const
{
if( aItem.GetMergeStatus() == LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::MERGED_RETIRED )
return 0;
const LENGTH_DELAY_CALCULATION_ITEM::TYPE itemType = aItem.Type();
if( itemType == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
{
const double delayUnit = aTuningProfile->m_LayerPropagationDelays.at( aItem.GetStartLayer() );
return static_cast<int64_t>( delayUnit * ( static_cast<double>( aItem.GetLine().Length() ) / PCB_IU_PER_MM ) );
}
if( itemType == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA )
{
const PCB_LAYER_ID signalStartLayer = aItem.GetStartLayer();
const PCB_LAYER_ID signalEndLayer = aItem.GetEndLayer();
const PCB_LAYER_ID viaStartLayer = aItem.GetVia()->Padstack().StartLayer();
const PCB_LAYER_ID viaEndLayer = aItem.GetVia()->Padstack().EndLayer();
// First check for a layer-to-layer override - this assumes that the layers are already in CuStack() order
auto& viaOverrides = m_viaOverridesCache.at( aTuningProfile->m_ProfileName );
const auto viaItr = viaOverrides.find(
VIA_OVERRIDE_CACHE_KEY{ signalStartLayer, signalEndLayer, viaStartLayer, viaEndLayer } );
if( viaItr != viaOverrides.end() )
return viaItr->second;
// Otherwise, return the tuning profile default
const double distance = m_lengthCalculation->StackupHeight( signalStartLayer, signalEndLayer );
return static_cast<int64_t>( aTuningProfile->m_ViaPropagationDelay * ( distance / PCB_IU_PER_MM ) );
}
if( itemType == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
{
return aItem.GetPad()->GetPadToDieDelay();
}
return 0;
}
const TIME_DOMAIN_TUNING_PROFILE*
TIME_DOMAIN_PARAMETERS_USER_DEFINED::getTuningProfile( const wxString& aTuningProfileName )
{
if( !m_cachesInitialised ) [[unlikely]]
rebuildCaches();
auto itr = m_tuningProfilesCache.find( aTuningProfileName );
if( itr != m_tuningProfilesCache.end() )
return itr->second;
return nullptr;
}
int64_t
TIME_DOMAIN_PARAMETERS_USER_DEFINED::GetTrackLengthForPropagationDelay( int64_t aDelay,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext )
{
const wxString tuningProfileName = aContext.NetClass->GetTuningProfile();
const TIME_DOMAIN_TUNING_PROFILE* profile = getTuningProfile( tuningProfileName );
if( !profile )
return 0;
const double delayUnit = profile->m_LayerPropagationDelays.at( aContext.Layer ); // Time IU / MM
const double lengthInMM = static_cast<double>( aDelay ) / delayUnit; // MM
return static_cast<int64_t>( lengthInMM * PCB_IU_PER_MM ); // Length IU
}
int64_t TIME_DOMAIN_PARAMETERS_USER_DEFINED::CalculatePropagationDelayForShapeLineChain(
const SHAPE_LINE_CHAIN& aShape, const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext )
{
const wxString tuningProfileName = aContext.NetClass->GetTuningProfile();
const TIME_DOMAIN_TUNING_PROFILE* profile = getTuningProfile( tuningProfileName );
if( !profile )
return 0;
const double delayUnit = profile->m_LayerPropagationDelays.at( aContext.Layer );
return static_cast<int64_t>( delayUnit * ( static_cast<double>( aShape.Length() ) / PCB_IU_PER_MM ) );
}
void TIME_DOMAIN_PARAMETERS_USER_DEFINED::rebuildCaches()
{
m_tuningProfilesCache.clear();
m_viaOverridesCache.clear();
if( const PROJECT* project = m_board->GetProject() )
{
TIME_DOMAIN_PARAMETERS* params = project->GetProjectFile().TimeDomainParameters().get();
for( const TIME_DOMAIN_TUNING_PROFILE& profile : params->GetDelayProfiles() )
{
m_tuningProfilesCache[profile.m_ProfileName] = &profile;
std::map<VIA_OVERRIDE_CACHE_KEY, int64_t>& viaOverrides = m_viaOverridesCache[profile.m_ProfileName];
for( const TUNING_PROFILE_VIA_OVERRIDE_ENTRY& viaOverride : profile.m_ViaOverrides )
{
viaOverrides[VIA_OVERRIDE_CACHE_KEY{ viaOverride.m_SignalLayerFrom, viaOverride.m_SignalLayerTo,
viaOverride.m_ViaLayerFrom, viaOverride.m_ViaLayerTo }] =
viaOverride.m_Delay;
}
}
}
m_cachesInitialised = true;
}

View File

@ -0,0 +1,145 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program 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.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PCB_NEW_TIME_DOMAIN_PARAMETERS_USER_DEFINED_H
#define PCB_NEW_TIME_DOMAIN_PARAMETERS_USER_DEFINED_H
#include <length_delay_calculation/time_domain_parameters_iface.h>
#include <project/time_domain_parameters.h>
class TIME_DOMAIN_PARAMETERS_USER_DEFINED final : public TIME_DOMAIN_PARAMETERS_IFACE
{
public:
explicit TIME_DOMAIN_PARAMETERS_USER_DEFINED( BOARD* aBoard, LENGTH_DELAY_CALCULATION* aCalculation ) :
TIME_DOMAIN_PARAMETERS_IFACE( aBoard, aCalculation )
{
}
/**
* Event called by the length and time calculation architecture if netclass definitions have changed. This can be
* used to invalidate any calculation / simulation caches.
*/
void OnSettingsChanged() override;
/**
* Gets the propagation delays (in internal units) for the given items in the given geometry context.
* This assumes that all items are in the same netclass
*
* @param aItems the board items to query propagation delay for
* @param aContext the geometry context in which to query to propagation delay
*/
std::vector<int64_t> GetPropagationDelays( const std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) override;
/**
* Gets the propagation delay (in internal units) for the given item in the given geometry context
*
* @param aItem the board item to query propagation delay for
* @param aContext the geometry context in which to query to propagation delay
*/
int64_t GetPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) override;
/**
* Gets the track length (in internal distance units) required for the given propagation delay (in internal time
* units). The track length should be calculated with the given geometry context.
*
* @param aContext the geometry context in which to query to propagation delay
* @param aDelay the propagation delay for which a length should be calculated
*/
int64_t GetTrackLengthForPropagationDelay( int64_t aDelay, const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) override;
/**
* Gets the propagation delay for the given shape line chain
*
* @param aShape is the shape to calculate delay for
* @param aContext is the geometry context for which to query to propagation delay
*/
int64_t CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) override;
private:
void rebuildCaches();
/// Cache key for use with std::map
struct VIA_OVERRIDE_CACHE_KEY
{
PCB_LAYER_ID SignalStart;
PCB_LAYER_ID SignalEnd;
PCB_LAYER_ID ViaStart;
PCB_LAYER_ID ViaEnd;
bool operator<( const VIA_OVERRIDE_CACHE_KEY& aOther ) const
{
if( SignalStart < aOther.SignalStart )
return true;
if( aOther.SignalStart < SignalStart )
return false;
if( SignalEnd < aOther.SignalEnd )
return true;
if( aOther.SignalEnd < SignalEnd )
return false;
if( ViaStart < aOther.ViaStart )
return true;
if( aOther.ViaStart < ViaStart )
return false;
return ViaEnd < aOther.ViaEnd;
}
};
/**
* Gets the propagation delay (in internal units) for the given item in the given geometry context,
* for items in the pre-found net class.
*
* Preconditions:
* - aNetClass must not be null
* - Calculation caches must be valid
*
* @param aItem the board item to query propagation delay for
* @param aContext the geometry context in which to query to propagation delay
* @param aTuningProfile the time domain tuning profile for the given item
*/
int64_t getPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem,
const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext,
const TIME_DOMAIN_TUNING_PROFILE* aTuningProfile ) const;
/**
* Gets the tuning profile pointer for the given tuning profile name
*
* @param aTuningProfileName the tuning profile name to return
* @returns Valid pointer to a tuning profile, or nullptr if no profile found
*/
const TIME_DOMAIN_TUNING_PROFILE* getTuningProfile( const wxString& aTuningProfileName );
/// Cached map of tuning profile names to per-layer time domain parameters
std::map<wxString, const TIME_DOMAIN_TUNING_PROFILE*> m_tuningProfilesCache;
/// Cached per-tuning profile via overrides
std::map<wxString, std::map<VIA_OVERRIDE_CACHE_KEY, int64_t>> m_viaOverridesCache;
/// Used to ensure caches are valid when board first loaded
bool m_cachesInitialised{ false };
};
#endif //PCB_NEW_TIME_DOMAIN_PARAMETERS_USER_DEFINED_H

View File

@ -125,20 +125,39 @@ void NETINFO_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANE
if( startTrack )
{
double lengthNet = 0.0; // This is the length of tracks on pcb
double lengthPadToDie = 0.0; // this is the length of internal ICs connections
double lengthNet = 0.0; // This is the length of tracks / vias on the pcb
double lengthPadToDie = 0.0; // This is the length of internal IC connections
double delayNet = 0.0; // This is the delay of tracks / vias on the pcb
double delayPadToDie = 0.0; // This is the delay of internal IC connections
std::tie( count, lengthNet, lengthPadToDie ) = board->GetTrackLength( *startTrack );
std::tie( count, lengthNet, lengthPadToDie, delayNet, delayPadToDie ) =
board->GetTrackLength( *startTrack );
// Displays the full net length (tracks on pcb + internal ICs connections ):
aList.emplace_back( _( "Net Length" ),
aFrame->MessageTextFromValue( lengthNet + lengthPadToDie ) );
if( delayNet == 0.0 )
{
// Displays the full net length (tracks on pcb + internal ICs connections ):
aList.emplace_back( _( "Net Length" ), aFrame->MessageTextFromValue( lengthNet + lengthPadToDie ) );
// Displays the net length of tracks only:
aList.emplace_back( _( "On Board" ), aFrame->MessageTextFromValue( lengthNet ) );
// Displays the net length of tracks only:
aList.emplace_back( _( "On Board" ), aFrame->MessageTextFromValue( lengthNet ) );
// Displays the net length of internal ICs connections (wires inside ICs):
aList.emplace_back( _( "In Package" ), aFrame->MessageTextFromValue( lengthPadToDie ) );
// Displays the net length of internal ICs connections (wires inside ICs):
aList.emplace_back( _( "In Package" ), aFrame->MessageTextFromValue( lengthPadToDie ) );
}
else
{
// Displays the full net length (tracks on pcb + internal ICs connections ):
aList.emplace_back( _( "Net Delay" ), aFrame->MessageTextFromValue( delayNet + delayPadToDie, true,
EDA_DATA_TYPE::TIME ) );
// Displays the net length of tracks only:
aList.emplace_back( _( "On Board" ),
aFrame->MessageTextFromValue( delayNet, true, EDA_DATA_TYPE::TIME ) );
// Displays the net length of internal ICs connections (wires inside ICs):
aList.emplace_back( _( "In Package" ),
aFrame->MessageTextFromValue( delayPadToDie, true, EDA_DATA_TYPE::TIME ) );
}
}
}
}

View File

@ -81,6 +81,7 @@ PAD::PAD( FOOTPRINT* parent ) :
PADSTACK::ALL_LAYERS );
drill.x = drill.y = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 30 ); // Default drill size 30 mils.
m_lengthPadToDie = 0;
m_delayPadToDie = 0;
if( m_parent && m_parent->Type() == PCB_FOOTPRINT_T )
m_pos = GetParent()->GetPosition();
@ -130,6 +131,7 @@ PAD& PAD::operator=( const PAD &aOther )
ImportSettingsFrom( aOther );
SetPadToDieLength( aOther.GetPadToDieLength() );
SetPadToDieDelay( aOther.GetPadToDieDelay() );
SetPosition( aOther.GetPosition() );
SetNumber( aOther.GetNumber() );
SetPinType( aOther.GetPinType() );
@ -1887,6 +1889,7 @@ void PAD::ImportSettingsFrom( const PAD& aMasterPad )
// really specific to a given pad (JPC).
#if 0
SetPadToDieLength( aMasterPad.GetPadToDieLength() );
SetPadToDieDelay( aMasterPad.GetPadToDieDelay() );
#endif
// The pad orientation, for historical reasons is the pad rotation + parent rotation.
@ -2885,6 +2888,11 @@ static struct PAD_DESC
padToDie->SetAvailableFunc( isCopperPad );
propMgr.AddProperty( padToDie, groupPad );
auto padToDieDelay = new PROPERTY<PAD, int>( _HKI( "Pad To Die Delay" ), &PAD::SetPadToDieDelay,
&PAD::GetPadToDieDelay, PROPERTY_DISPLAY::PT_TIME );
padToDieDelay->SetAvailableFunc( isCopperPad );
propMgr.AddProperty( padToDieDelay, groupPad );
const wxString groupOverrides = _HKI( "Overrides" );
propMgr.AddProperty( new PROPERTY<PAD, std::optional<int>>(

View File

@ -452,6 +452,9 @@ public:
void SetPadToDieLength( int aLength ) { m_lengthPadToDie = aLength; }
int GetPadToDieLength() const { return m_lengthPadToDie; }
void SetPadToDieDelay( int aDelay ) { m_delayPadToDie = aDelay; }
int GetPadToDieDelay() const { return m_delayPadToDie; }
std::optional<int> GetLocalClearance() const override { return m_padStack.Clearance(); }
void SetLocalClearance( std::optional<int> aClearance ) { m_padStack.Clearance() = aClearance; }
@ -959,7 +962,8 @@ private:
PAD_PROP m_property; // Property in fab files (BGA, FIDUCIAL, TESTPOINT, etc.)
int m_lengthPadToDie; // Length net from pad to die, inside the package
int m_lengthPadToDie; // Length net from pad to die, inside the package
int m_delayPadToDie; // Propagation delay from pad to die
mutable std::mutex m_zoneLayerOverridesMutex;
std::map<PCB_LAYER_ID, ZONE_LAYER_OVERRIDE> m_zoneLayerOverrides;

View File

@ -1403,6 +1403,8 @@ void PCB_EDIT_FRAME::ShowBoardSetupDialog( const wxString& aInitialPage )
wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::GENERIC );
}
GetBoard()->SynchronizeTimeDomainProperties();
// We don't know if anything was modified, so err on the side of requiring a save
OnModify();

View File

@ -1696,6 +1696,11 @@ void PCB_IO_KICAD_SEXPR::format( const PAD* aPad ) const
formatInternalUnits( aPad->GetPadToDieLength() ).c_str() );
}
if( aPad->GetPadToDieDelay() != 0 )
{
m_out->Print( "(die_delay %s)", formatInternalUnits( aPad->GetPadToDieDelay() ).c_str() );
}
if( aPad->GetLocalSolderMaskMargin().has_value() )
{
m_out->Print( "(solder_mask_margin %s)",

View File

@ -181,7 +181,8 @@ class PCB_IO_KICAD_SEXPR; // forward decl
//#define SEXPR_BOARD_FILE_VERSION 20250228 // ipc-4761 via protection features
//#define SEXPR_BOARD_FILE_VERSION 20250302 // Zone Hatching Offsets
//#define SEXPR_BOARD_FILE_VERSION 20250309 // Component class dynamic assignment rules
#define SEXPR_BOARD_FILE_VERSION 20250324 // Jumper pads
//#define SEXPR_BOARD_FILE_VERSION 20250324 // Jumper pads
#define SEXPR_BOARD_FILE_VERSION 20250401 // Time domain length tuning
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting

View File

@ -5370,6 +5370,11 @@ PAD* PCB_IO_KICAD_SEXPR_PARSER::parsePAD( FOOTPRINT* aParent )
NeedRIGHT();
break;
case T_die_delay:
pad->SetPadToDieDelay( parseBoardUnits( T_die_delay ) );
NeedRIGHT();
break;
case T_solder_mask_margin:
pad->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) );
NeedRIGHT();

View File

@ -773,6 +773,24 @@ double PCB_TRACK::GetLength() const
}
double PCB_TRACK::GetDelay() const
{
const BOARD* board = GetBoard();
if( !board )
return 0.0;
const LENGTH_DELAY_CALCULATION* calc = board->GetLengthCalculation();
const LENGTH_DELAY_CALCULATION_ITEM calcItem = calc->GetLengthCalculationItem( this );
std::vector<LENGTH_DELAY_CALCULATION_ITEM> items{ calcItem };
constexpr PATH_OPTIMISATIONS opts = {
.OptimiseViaLayers = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = false
};
return calc->CalculateDelay( items, opts );
}
void PCB_TRACK::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
{
RotatePoint( m_Start, aRotCentre, aAngle );
@ -1761,26 +1779,56 @@ void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
aList.emplace_back( _( "Radius" ), aFrame->MessageTextFromValue( radius ) );
}
aList.emplace_back( _( "Segment Length" ), aFrame->MessageTextFromValue( GetLength() ) );
double segmentLength = GetLength();
double segmentDelay = GetDelay();
if( segmentDelay == 0.0 )
{
aList.emplace_back( _( "Segment Length" ), aFrame->MessageTextFromValue( segmentLength ) );
}
else
{
aList.emplace_back( _( "Segment Delay" ),
aFrame->MessageTextFromValue( segmentDelay, true, EDA_DATA_TYPE::TIME ) );
}
// Display full track length (in Pcbnew)
if( board && GetNetCode() > 0 )
{
int count;
double trackLen;
double lenPadToDie;
int count = 0;
double trackLen = 0.0;
double lenPadToDie = 0.0;
double trackDelay = 0.0;
double delayPadToDie = 0.0;
std::tie( count, trackLen, lenPadToDie ) = board->GetTrackLength( *this );
std::tie( count, trackLen, lenPadToDie, trackDelay, delayPadToDie ) = board->GetTrackLength( *this );
aList.emplace_back( _( "Routed Length" ), aFrame->MessageTextFromValue( trackLen ) );
if( lenPadToDie != 0 )
if( trackDelay == 0.0 )
{
msg = aFrame->MessageTextFromValue( lenPadToDie );
aList.emplace_back( _( "Pad To Die Length" ), msg );
aList.emplace_back( _( "Routed Length" ), aFrame->MessageTextFromValue( trackLen ) );
msg = aFrame->MessageTextFromValue( trackLen + lenPadToDie );
aList.emplace_back( _( "Full Length" ), msg );
if( lenPadToDie != 0 )
{
msg = aFrame->MessageTextFromValue( lenPadToDie );
aList.emplace_back( _( "Pad To Die Length" ), msg );
msg = aFrame->MessageTextFromValue( trackLen + lenPadToDie );
aList.emplace_back( _( "Full Length" ), msg );
}
}
else
{
aList.emplace_back( _( "Routed Delay" ),
aFrame->MessageTextFromValue( trackDelay, true, EDA_DATA_TYPE::TIME ) );
if( delayPadToDie != 0.0 )
{
msg = aFrame->MessageTextFromValue( delayPadToDie, true, EDA_DATA_TYPE::TIME );
aList.emplace_back( _( "Pad To Die Delay" ), msg );
msg = aFrame->MessageTextFromValue( trackDelay + delayPadToDie, true, EDA_DATA_TYPE::TIME );
aList.emplace_back( _( "Full Delay" ), msg );
}
}
}

View File

@ -191,10 +191,17 @@ public:
/**
* Get the length of the track using the hypotenuse calculation.
*
* @return the length of the track.
* @return the length of the track
*/
virtual double GetLength() const;
/**
* Get the time delay of the track
*
* @return the delay of the track
*/
virtual double GetDelay() const;
/**
* Convert the track shape to a closed polygon.
*

View File

@ -603,7 +603,8 @@ BOARD* PCBEXPR_CONTEXT::GetBoard() const
const std::vector<wxString>& PCBEXPR_UNIT_RESOLVER::GetSupportedUnits() const
{
static const std::vector<wxString> pcbUnits = { wxT( "mil" ), wxT( "mm" ), wxT( "in" ),
wxT( "deg" ) };
wxT( "deg" ), wxT( "fs" ), wxT( "ps" ) };
return pcbUnits;
}
@ -611,7 +612,16 @@ const std::vector<wxString>& PCBEXPR_UNIT_RESOLVER::GetSupportedUnits() const
wxString PCBEXPR_UNIT_RESOLVER::GetSupportedUnitsMessage() const
{
return _( "must be mm, in, mil, or deg" );
return _( "must be mm, in, mil, deg, fs, or ps" );
}
const std::vector<EDA_UNITS>& PCBEXPR_UNIT_RESOLVER::GetSupportedUnitsTypes() const
{
static const std::vector<EDA_UNITS> pcbUnits = { EDA_UNITS::MILS, EDA_UNITS::MM, EDA_UNITS::INCH,
EDA_UNITS::DEGREES, EDA_UNITS::FS, EDA_UNITS::PS };
return pcbUnits;
}
@ -624,6 +634,9 @@ double PCBEXPR_UNIT_RESOLVER::Convert( const wxString& aString, int unitId ) con
case 0: return EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::MILS, aString );
case 1: return EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::MM, aString );
case 2: return EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::INCH, aString );
case 3: return v;
case 4: return EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::FS, aString );
case 5: return EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::PS, aString );
default: return v;
}
};
@ -637,6 +650,14 @@ const std::vector<wxString>& PCBEXPR_UNITLESS_RESOLVER::GetSupportedUnits() cons
}
const std::vector<EDA_UNITS>& PCBEXPR_UNITLESS_RESOLVER::GetSupportedUnitsTypes() const
{
static const std::vector<EDA_UNITS> emptyUnits;
return emptyUnits;
}
double PCBEXPR_UNITLESS_RESOLVER::Convert( const wxString& aString, int unitId ) const
{
return wxAtof( aString );
@ -679,7 +700,10 @@ bool PCBEXPR_EVALUATOR::Evaluate( const wxString& aExpr )
LIBEVAL::VALUE* result = ucode.Run( &evaluationContext );
if( result->GetType() == LIBEVAL::VT_NUMERIC )
{
m_result = KiROUND( result->AsDouble() );
m_units = result->GetUnits();
}
return true;
}

View File

@ -213,6 +213,7 @@ class PCBEXPR_UNIT_RESOLVER : public LIBEVAL::UNIT_RESOLVER
{
public:
const std::vector<wxString>& GetSupportedUnits() const override;
const std::vector<EDA_UNITS>& GetSupportedUnitsTypes() const override;
wxString GetSupportedUnitsMessage() const override;
@ -224,6 +225,7 @@ class PCBEXPR_UNITLESS_RESOLVER : public LIBEVAL::UNIT_RESOLVER
{
public:
const std::vector<wxString>& GetSupportedUnits() const override;
const std::vector<EDA_UNITS>& GetSupportedUnitsTypes() const override;
double Convert( const wxString& aString, int unitId ) const override;
};
@ -244,6 +246,7 @@ public:
bool Evaluate( const wxString& aExpr );
int Result() const { return m_result; }
EDA_UNITS Units() const { return m_units; }
void SetErrorCallback( std::function<void( const wxString& aMessage, int aOffset )> aCallback )
{
@ -255,6 +258,7 @@ public:
private:
int m_result;
EDA_UNITS m_units;
PCBEXPR_COMPILER m_compiler;
PCBEXPR_UCODE m_ucode;

View File

@ -37,13 +37,19 @@ DP_MEANDER_PLACER::DP_MEANDER_PLACER( ROUTER* aRouter ) :
m_world = nullptr;
m_currentNode = nullptr;
m_padToDieP = 0;
m_padToDieN = 0;
m_padToDieLengthP = 0;
m_padToDieLengthN = 0;
m_padToDieDelayP = 0;
m_padToDieDelayN = 0;
// Init temporary variables (do not leave uninitialized members)
m_initialSegment = nullptr;
m_lastLength = 0;
m_lastDelay = 0;
m_lastStatus = TOO_SHORT;
m_netClass = nullptr;
}
@ -107,30 +113,49 @@ bool DP_MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
m_tunedPathP = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.PLine().GetLink( 0 ), &m_startPad_p,
&m_endPad_p );
m_padToDieP = 0;
m_padToDieLengthP = 0;
m_padToDieDelayP = 0;
if( m_startPad_p )
m_padToDieP += m_startPad_p->GetPadToDie();
{
m_padToDieLengthP += m_startPad_p->GetPadToDie();
m_padToDieDelayP += m_startPad_p->GetPadToDieDelay();
}
if( m_endPad_p )
m_padToDieP += m_endPad_p->GetPadToDie();
{
m_padToDieLengthP += m_endPad_p->GetPadToDie();
m_padToDieDelayP += m_endPad_p->GetPadToDieDelay();
}
m_tunedPathN = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.NLine().GetLink( 0 ), &m_startPad_n,
&m_endPad_n );
m_padToDieN = 0;
m_padToDieLengthN = 0;
m_padToDieDelayN = 0;
if( m_startPad_n )
m_padToDieN += m_startPad_n->GetPadToDie();
{
m_padToDieLengthN += m_startPad_n->GetPadToDie();
m_padToDieDelayN += m_startPad_n->GetPadToDieDelay();
}
if( m_endPad_n )
m_padToDieN += m_endPad_n->GetPadToDie();
{
m_padToDieLengthN += m_endPad_n->GetPadToDie();
m_padToDieDelayN += m_endPad_n->GetPadToDieDelay();
}
m_world->Remove( m_originPair.PLine() );
m_world->Remove( m_originPair.NLine() );
m_currentWidth = m_originPair.Width();
const BOARD_CONNECTED_ITEM* conItem = static_cast<BOARD_CONNECTED_ITEM*>( aStartItem->GetSourceItem() );
m_netClass = conItem->GetEffectiveNetClass();
calculateTimeDomainTargets();
return true;
}
@ -142,8 +167,16 @@ void DP_MEANDER_PLACER::release()
long long int DP_MEANDER_PLACER::origPathLength() const
{
long long int totalP = m_padToDieP + lineLength( m_tunedPathP, m_startPad_p, m_endPad_p );
long long int totalN = m_padToDieN + lineLength( m_tunedPathN, m_startPad_n, m_endPad_n );
long long int totalP = m_padToDieLengthP + lineLength( m_tunedPathP, m_startPad_p, m_endPad_p );
long long int totalN = m_padToDieLengthN + lineLength( m_tunedPathN, m_startPad_n, m_endPad_n );
return std::max( totalP, totalN );
}
int64_t DP_MEANDER_PLACER::origPathDelay() const
{
const int64_t totalP = m_padToDieDelayP + lineDelay( m_tunedPathP, m_startPad_p, m_endPad_p );
const int64_t totalN = m_padToDieDelayP + lineDelay( m_tunedPathN, m_startPad_n, m_endPad_n );
return std::max( totalP, totalN );
}
@ -169,6 +202,8 @@ bool DP_MEANDER_PLACER::pairOrientation( const DIFF_PAIR::COUPLED_SEGMENTS& aPai
bool DP_MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
{
calculateTimeDomainTargets();
if( m_currentStart == aP )
return false;
@ -329,6 +364,7 @@ bool DP_MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
m_result.AddCorner( tunedP.CPoint( -1 ), tunedN.CPoint( -1 ) );
long long int dpLen = origPathLength();
int64_t dpDelay = origPathDelay();
m_lastStatus = TUNED;
@ -336,10 +372,24 @@ bool DP_MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
{
m_lastStatus = TOO_LONG;
m_lastLength = dpLen;
m_lastDelay = dpDelay;
}
else
{
m_lastLength = dpLen - std::max( tunedP.Length(), tunedN.Length() );
if( m_settings.m_isTimeDomain )
{
int64_t tunedPDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
tunedP, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
m_netClass );
int64_t tunedNDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
tunedN, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
m_netClass );
m_lastDelay = dpDelay - std::max( tunedPDelay, tunedNDelay );
}
tuneLineLength( m_result, m_settings.m_targetLength.Opt() - dpLen );
}
@ -358,6 +408,19 @@ bool DP_MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
}
m_lastLength += std::max( tunedP.Length(), tunedN.Length() );
if( m_settings.m_isTimeDomain )
{
int64_t tunedPDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
tunedP, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
m_netClass );
int64_t tunedNDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
tunedN, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
m_netClass );
m_lastDelay += std::max( tunedPDelay, tunedNDelay );
}
updateStatus();
}
@ -500,7 +563,7 @@ int DP_MEANDER_PLACER::CurrentLayer() const
}
long long int DP_MEANDER_PLACER::TuningResult() const
long long int DP_MEANDER_PLACER::TuningLengthResult() const
{
if( m_lastLength )
return m_lastLength;
@ -509,6 +572,15 @@ long long int DP_MEANDER_PLACER::TuningResult() const
}
int64_t DP_MEANDER_PLACER::TuningDelayResult() const
{
if( m_lastDelay )
return m_lastDelay;
else
return origPathDelay();
}
DP_MEANDER_PLACER::TUNING_STATUS DP_MEANDER_PLACER::TuningStatus() const
{
return m_lastStatus;
@ -523,4 +595,36 @@ const std::vector<NET_HANDLE> DP_MEANDER_PLACER::CurrentNets() const
return rv;
}
void DP_MEANDER_PLACER::calculateTimeDomainTargets()
{
// If this is a time domain tuning, calculate the target length for the desired total delay
if( m_settings.m_isTimeDomain )
{
const int64_t curDelay = origPathDelay();
const int64_t desiredDelayMin = m_settings.m_targetLengthDelay.Min();
const int64_t desiredDelayOpt = m_settings.m_targetLengthDelay.Opt();
const int64_t desiredDelayMax = m_settings.m_targetLengthDelay.Max();
const int64_t delayDifferenceOpt = desiredDelayOpt - curDelay;
const int64_t curLength = origPathLength();
const int64_t lengthDiffMin = m_router->GetInterface()->CalculateLengthForDelay(
desiredDelayOpt - desiredDelayMin, GetOriginPair().Width(), true, GetOriginPair().Gap(),
m_router->GetCurrentLayer(), m_netClass );
int64_t lengthDiffOpt = m_router->GetInterface()->CalculateLengthForDelay(
std::abs( delayDifferenceOpt ), GetOriginPair().Width(), true, GetOriginPair().Gap(),
m_router->GetCurrentLayer(), m_netClass );
const int64_t lengthDiffMax = m_router->GetInterface()->CalculateLengthForDelay(
desiredDelayMax - desiredDelayOpt, GetOriginPair().Width(), true, GetOriginPair().Gap(),
m_router->GetCurrentLayer(), m_netClass );
lengthDiffOpt = delayDifferenceOpt > 0 ? lengthDiffOpt : -lengthDiffOpt;
m_settings.m_targetLength.SetMin( curLength + lengthDiffOpt - lengthDiffMin );
m_settings.m_targetLength.SetOpt( curLength + lengthDiffOpt );
m_settings.m_targetLength.SetMax( curLength + lengthDiffOpt + lengthDiffMax );
}
}
}

View File

@ -108,7 +108,11 @@ public:
long long int totalLength();
long long int TuningResult() const override;
long long int TuningLengthResult() const override;
/// @copydoc MEANDER_PLACER_BASE::TuningDelayResult()
int64_t TuningDelayResult() const override;
TUNING_STATUS TuningStatus() const override;
bool CheckFit( MEANDER_SHAPE* aShape ) override;
@ -130,6 +134,10 @@ private:
long long int origPathLength() const;
int64_t origPathDelay() const;
void calculateTimeDomainTargets();
///< Current routing start point (end of tail, beginning of head).
VECTOR2I m_currentStart;
@ -147,9 +155,14 @@ private:
LINKED_ITEM* m_initialSegment;
long long int m_lastLength;
int m_padToDieP;
int m_padToDieN;
int64_t m_lastDelay;
int m_padToDieLengthP;
int m_padToDieLengthN;
int64_t m_padToDieDelayP;
int64_t m_padToDieDelayN;
TUNING_STATUS m_lastStatus;
NETCLASS* m_netClass;
};
}

View File

@ -443,6 +443,7 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
aConstraint->m_Value = hostConstraint.GetValue();
aConstraint->m_RuleName = hostConstraint.GetName();
aConstraint->m_Type = aType;
aConstraint->m_IsTimeDomain = hostConstraint.GetOption( DRC_CONSTRAINT::OPTIONS::TIME_DOMAIN );
return true;
default:
@ -1193,6 +1194,7 @@ std::vector<std::unique_ptr<PNS::SOLID>> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPa
solid->SetNet( aPad->GetNet() );
solid->SetParent( aPad );
solid->SetPadToDie( aPad->GetPadToDieLength() );
solid->SetPadToDieDelay( aPad->GetPadToDieDelay() );
solid->SetOrientation( aPad->GetOrientation() );
if( aPad->IsFreePad() )
@ -2325,40 +2327,9 @@ PNS_LAYER_RANGE PNS_KICAD_IFACE_BASE::SetLayersFromPCBNew( PCB_LAYER_ID aStartLa
long long int PNS_KICAD_IFACE_BASE::CalculateRoutedPathLength( const PNS::ITEM_SET& aLine, const PNS::SOLID* aStartPad,
const PNS::SOLID* aEndPad )
const PNS::SOLID* aEndPad, const NETCLASS* aNetClass )
{
std::vector<LENGTH_CALCULATION_ITEM> lengthItems;
for( int idx = 0; idx < aLine.Size(); idx++ )
{
const PNS::ITEM* lineItem = aLine[idx];
if( const PNS::LINE* l = dyn_cast<const PNS::LINE*>( lineItem ) )
{
LENGTH_CALCULATION_ITEM item;
item.SetLine( l->CLine() );
const PCB_LAYER_ID layer = GetBoardLayerFromPNSLayer( lineItem->Layer() );
item.SetLayers( layer );
lengthItems.emplace_back( std::move( item ) );
}
else if( lineItem->OfKind( PNS::ITEM::VIA_T ) && idx > 0 && idx < aLine.Size() - 1 )
{
const int layerPrev = aLine[idx - 1]->Layer();
const int layerNext = aLine[idx + 1]->Layer();
const PCB_LAYER_ID pcbLayerPrev = GetBoardLayerFromPNSLayer( layerPrev );
const PCB_LAYER_ID pcbLayerNext = GetBoardLayerFromPNSLayer( layerNext );
if( layerPrev != layerNext )
{
LENGTH_CALCULATION_ITEM item;
item.SetVia( static_cast<PCB_VIA*>( lineItem->GetSourceItem() ) );
item.SetLayers( pcbLayerPrev, pcbLayerNext );
lengthItems.emplace_back( std::move( item ) );
}
}
}
std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems = getLengthDelayCalculationItems( aLine, aNetClass );
const PAD* startPad = nullptr;
const PAD* endPad = nullptr;
@ -2375,3 +2346,99 @@ long long int PNS_KICAD_IFACE_BASE::CalculateRoutedPathLength( const PNS::ITEM_S
const BOARD* board = GetBoard();
return board->GetLengthCalculation()->CalculateLength( lengthItems, opts, startPad, endPad );
}
int64_t PNS_KICAD_IFACE_BASE::CalculateRoutedPathDelay( const PNS::ITEM_SET& aLine, const PNS::SOLID* aStartPad,
const PNS::SOLID* aEndPad, const NETCLASS* aNetClass )
{
std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems = getLengthDelayCalculationItems( aLine, aNetClass );
const PAD* startPad = nullptr;
const PAD* endPad = nullptr;
if( aStartPad )
startPad = static_cast<PAD*>( aStartPad->Parent() );
if( aEndPad )
endPad = static_cast<PAD*>( aEndPad->Parent() );
constexpr PATH_OPTIMISATIONS opts = {
.OptimiseViaLayers = false, .MergeTracks = false, .OptimiseTracesInPads = false, .InferViaInPad = true
};
const BOARD* board = GetBoard();
return board->GetLengthCalculation()->CalculateDelay( lengthItems, opts, startPad, endPad );
}
int64_t PNS_KICAD_IFACE_BASE::CalculateLengthForDelay( int64_t aDesiredDelay, const int aWidth,
const bool aIsDiffPairCoupled, const int aDiffPairCouplingGap,
const int aPNSLayer, const NETCLASS* aNetClass )
{
TIME_DOMAIN_GEOMETRY_CONTEXT ctx;
ctx.NetClass = aNetClass;
ctx.Width = aWidth;
ctx.IsDiffPairCoupled = aIsDiffPairCoupled;
ctx.DiffPairCouplingGap = aDiffPairCouplingGap;
ctx.Layer = GetBoardLayerFromPNSLayer( aPNSLayer );
const BOARD* board = GetBoard();
return board->GetLengthCalculation()->CalculateLengthForDelay( aDesiredDelay, ctx );
}
int64_t PNS_KICAD_IFACE_BASE::CalculateDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, int aWidth,
bool aIsDiffPairCoupled, int aDiffPairCouplingGap,
int aPNSLayer, const NETCLASS* aNetClass )
{
TIME_DOMAIN_GEOMETRY_CONTEXT ctx;
ctx.NetClass = aNetClass;
ctx.Width = aWidth;
ctx.IsDiffPairCoupled = aIsDiffPairCoupled;
ctx.DiffPairCouplingGap = aDiffPairCouplingGap;
ctx.Layer = GetBoardLayerFromPNSLayer( aPNSLayer );
const BOARD* board = GetBoard();
return board->GetLengthCalculation()->CalculatePropagationDelayForShapeLineChain( aShape, ctx );
}
std::vector<LENGTH_DELAY_CALCULATION_ITEM>
PNS_KICAD_IFACE_BASE::getLengthDelayCalculationItems( const PNS::ITEM_SET& aLine, const NETCLASS* aNetClass ) const
{
std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems;
for( int idx = 0; idx < aLine.Size(); idx++ )
{
const PNS::ITEM* lineItem = aLine[idx];
if( const PNS::LINE* l = dyn_cast<const PNS::LINE*>( lineItem ) )
{
LENGTH_DELAY_CALCULATION_ITEM item;
item.SetLine( l->CLine() );
const PCB_LAYER_ID layer = GetBoardLayerFromPNSLayer( lineItem->Layer() );
item.SetLayers( layer );
item.SetEffectiveNetClass( aNetClass );
lengthItems.emplace_back( std::move( item ) );
}
else if( lineItem->OfKind( PNS::ITEM::VIA_T ) && idx > 0 && idx < aLine.Size() - 1 )
{
const int layerPrev = aLine[idx - 1]->Layer();
const int layerNext = aLine[idx + 1]->Layer();
const PCB_LAYER_ID pcbLayerPrev = GetBoardLayerFromPNSLayer( layerPrev );
const PCB_LAYER_ID pcbLayerNext = GetBoardLayerFromPNSLayer( layerNext );
if( layerPrev != layerNext )
{
LENGTH_DELAY_CALCULATION_ITEM item;
item.SetVia( static_cast<PCB_VIA*>( lineItem->GetSourceItem() ) );
item.SetLayers( pcbLayerPrev, pcbLayerNext ); // TODO: BUG IS HERE!!!
item.SetEffectiveNetClass( aNetClass );
lengthItems.emplace_back( std::move( item ) );
}
}
}
return lengthItems;
}

View File

@ -37,6 +37,7 @@ class PCB_TOOL_BASE;
class FOOTPRINT;
class PAD;
class EDA_TEXT;
class LENGTH_DELAY_CALCULATION_ITEM;
namespace PNS
{
@ -84,7 +85,15 @@ public:
void SetDebugDecorator( PNS::DEBUG_DECORATOR* aDec );
long long int CalculateRoutedPathLength( const PNS::ITEM_SET& aLine, const PNS::SOLID* aStartPad,
const PNS::SOLID* aEndPad ) override;
const PNS::SOLID* aEndPad, const NETCLASS* aNetClass ) override;
int64_t CalculateRoutedPathDelay( const PNS::ITEM_SET& aLine, const PNS::SOLID* aStartPad,
const PNS::SOLID* aEndPad, const NETCLASS* aNetClass ) override;
int64_t CalculateLengthForDelay( int64_t aDesiredDelay, int aWidth, bool aIsDiffPairCoupled,
int aDiffPairCouplingGap, int aPNSLayer, const NETCLASS* aNetClass ) override;
int64_t CalculateDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, int aWidth, bool aIsDiffPairCoupled,
int aDiffPairCouplingGap, int aPNSLayer,
const NETCLASS* aNetClass ) override;
PCB_LAYER_ID GetBoardLayerFromPNSLayer( int aLayer ) const override;
int GetPNSLayerFromBoardLayer( PCB_LAYER_ID aLayer ) const override;
@ -114,6 +123,8 @@ protected:
bool syncGraphicalItem( PNS::NODE* aWorld, PCB_SHAPE* aItem );
bool syncZone( PNS::NODE* aWorld, ZONE* aZone, SHAPE_POLY_SET* aBoardOutline );
bool inheritTrackWidth( PNS::ITEM* aItem, int* aInheritedWidth );
std::vector<LENGTH_DELAY_CALCULATION_ITEM> getLengthDelayCalculationItems( const PNS::ITEM_SET& aLine,
const NETCLASS* aNetClass ) const;
protected:
PNS::NODE* m_world;

View File

@ -28,8 +28,12 @@
namespace PNS {
const long long int MEANDER_SETTINGS::DEFAULT_TOLERANCE( pcbIUScale.mmToIU( 0.1 ) );
const long long int MEANDER_SETTINGS::DEFAULT_LENGTH_TOLERANCE( pcbIUScale.mmToIU( 0.1 ) );
const long long int MEANDER_SETTINGS::LENGTH_UNCONSTRAINED( 1000000 * pcbIUScale.IU_PER_MM );
const long long int MEANDER_SETTINGS::DEFAULT_DELAY_TOLERANCE( 0.1 * pcbIUScale.IU_PER_PS );
const long long int MEANDER_SETTINGS::DELAY_UNCONSTRAINED( 1000000 * pcbIUScale.IU_PER_PS );
const int MEANDER_SETTINGS::SKEW_UNCONSTRAINED( std::numeric_limits<int>::max() );
@ -41,7 +45,9 @@ MEANDER_SETTINGS::MEANDER_SETTINGS()
m_lenPadToDie = 0;
m_spacing = 600000;
SetTargetLength( LENGTH_UNCONSTRAINED );
SetTargetLengthDelay( DELAY_UNCONSTRAINED );
SetTargetSkew( 0 );
SetTargetSkewDelay( 0 );
m_overrideCustomRules = false;
m_cornerStyle = MEANDER_STYLE_ROUND;
m_cornerRadiusPercentage = 80;
@ -49,6 +55,7 @@ MEANDER_SETTINGS::MEANDER_SETTINGS()
m_initialSide = MEANDER_SIDE_LEFT;
m_lengthTolerance = 0;
m_keepEndpoints = false;
m_isTimeDomain = false;
}
@ -63,8 +70,8 @@ void MEANDER_SETTINGS::SetTargetLength( long long int aOpt )
}
else
{
m_targetLength.SetMin( aOpt - DEFAULT_TOLERANCE );
m_targetLength.SetMax( aOpt + DEFAULT_TOLERANCE );
m_targetLength.SetMin( aOpt - DEFAULT_LENGTH_TOLERANCE );
m_targetLength.SetMax( aOpt + DEFAULT_LENGTH_TOLERANCE );
}
}
@ -81,6 +88,35 @@ void MEANDER_SETTINGS::SetTargetLength( const MINOPTMAX<int>& aConstraint )
}
void MEANDER_SETTINGS::SetTargetLengthDelay( long long int aOpt )
{
m_targetLengthDelay.SetOpt( aOpt );
if( aOpt == PNS::MEANDER_SETTINGS::DELAY_UNCONSTRAINED )
{
m_targetLengthDelay.SetMin( 0 );
m_targetLengthDelay.SetMax( aOpt );
}
else
{
m_targetLengthDelay.SetMin( aOpt - DEFAULT_DELAY_TOLERANCE );
m_targetLengthDelay.SetMax( aOpt + DEFAULT_DELAY_TOLERANCE );
}
}
void MEANDER_SETTINGS::SetTargetLengthDelay( const MINOPTMAX<int>& aConstraint )
{
SetTargetLengthDelay( aConstraint.Opt() );
if( aConstraint.HasMin() )
m_targetLengthDelay.SetMin( aConstraint.Min() );
if( aConstraint.HasMax() )
m_targetLengthDelay.SetMax( aConstraint.Max() );
}
void MEANDER_SETTINGS::SetTargetSkew( int aOpt )
{
m_targetSkew.SetOpt( aOpt );
@ -92,8 +128,8 @@ void MEANDER_SETTINGS::SetTargetSkew( int aOpt )
}
else
{
m_targetSkew.SetMin( aOpt - DEFAULT_TOLERANCE );
m_targetSkew.SetMax( aOpt + DEFAULT_TOLERANCE );
m_targetSkew.SetMin( aOpt - DEFAULT_LENGTH_TOLERANCE );
m_targetSkew.SetMax( aOpt + DEFAULT_LENGTH_TOLERANCE );
}
}
@ -110,6 +146,35 @@ void MEANDER_SETTINGS::SetTargetSkew( const MINOPTMAX<int>& aConstraint )
}
void MEANDER_SETTINGS::SetTargetSkewDelay( int aOpt )
{
m_targetSkewDelay.SetOpt( aOpt );
if( aOpt == PNS::MEANDER_SETTINGS::SKEW_UNCONSTRAINED )
{
m_targetSkewDelay.SetMin( 0 );
m_targetSkewDelay.SetMax( aOpt );
}
else
{
m_targetSkewDelay.SetMin( aOpt - DEFAULT_LENGTH_TOLERANCE );
m_targetSkewDelay.SetMax( aOpt + DEFAULT_LENGTH_TOLERANCE );
}
}
void MEANDER_SETTINGS::SetTargetSkewDelay( const MINOPTMAX<int>& aConstraint )
{
SetTargetSkewDelay( aConstraint.Opt() );
if( aConstraint.HasMin() )
m_targetSkewDelay.SetMin( aConstraint.Min() );
if( aConstraint.HasMax() )
m_targetSkewDelay.SetMax( aConstraint.Max() );
}
const MEANDER_SETTINGS& MEANDER_SHAPE::Settings() const
{
return m_placer->MeanderSettings();

View File

@ -67,8 +67,12 @@ enum MEANDER_SIDE
class MEANDER_SETTINGS
{
public:
static const long long int DEFAULT_TOLERANCE;
static const long long int DEFAULT_LENGTH_TOLERANCE;
static const long long int LENGTH_UNCONSTRAINED;
static const long long int DEFAULT_DELAY_TOLERANCE;
static const long long int DELAY_UNCONSTRAINED;
static const int SKEW_UNCONSTRAINED;
MEANDER_SETTINGS();
@ -76,9 +80,15 @@ public:
void SetTargetLength( long long int aOpt );
void SetTargetLength( const MINOPTMAX<int>& aConstraint );
void SetTargetLengthDelay( long long int aOpt );
void SetTargetLengthDelay( const MINOPTMAX<int>& aConstraint );
void SetTargetSkew( int aOpt );
void SetTargetSkew( const MINOPTMAX<int>& aConstraint );
void SetTargetSkewDelay( int aOpt );
void SetTargetSkewDelay( const MINOPTMAX<int>& aConstraint );
///< Minimum meandering amplitude.
int m_minAmplitude;
@ -97,9 +107,15 @@ public:
///< Desired length of the tuned line/diff pair (this is in nm, so allow more than board width).
MINOPTMAX<long long int> m_targetLength;
///< Desired propagation delay of the tuned line
MINOPTMAX<long long int> m_targetLengthDelay;
///< Target skew value for diff pair de-skewing.
MINOPTMAX<int> m_targetSkew;
///< Target skew value for diff pair de-skewing.
MINOPTMAX<int> m_targetSkewDelay;
bool m_overrideCustomRules;
///< Type of corners for the meandered line.
@ -119,6 +135,12 @@ public:
///< Keep vertices between pre, tuned and post parts of the line.
bool m_keepEndpoints;
///< Calculate tuning in the time domain
bool m_isTimeDomain;
///< The net class this meander pattern belongs to
NETCLASS* m_netClass;
};
/**

View File

@ -27,6 +27,8 @@
#include "pns_solid.h"
#include "pns_topology.h"
#include <length_delay_calculation/time_domain_parameters_iface.h>
namespace PNS {
MEANDER_PLACER::MEANDER_PLACER( ROUTER* aRouter ) :
@ -37,8 +39,11 @@ MEANDER_PLACER::MEANDER_PLACER( ROUTER* aRouter ) :
// Init temporary variables (do not leave uninitialized members)
m_initialSegment = nullptr;
m_lastLength = 0;
m_lastDelay = 0;
m_lastStatus = TOO_SHORT;
m_padToDieLength = 0;
m_padToDieDelay = 0;
m_netClass = nullptr;
}
@ -75,18 +80,30 @@ bool MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
m_tunedPath = topo.AssembleTuningPath( Router()->GetInterface(), m_initialSegment, &m_startPad_n, &m_endPad_n );
m_padToDieLength = 0;
m_padToDieDelay = 0;
if( m_startPad_n )
{
m_padToDieLength += m_startPad_n->GetPadToDie();
m_padToDieDelay += m_startPad_n->GetPadToDieDelay();
}
if( m_endPad_n )
{
m_padToDieLength += m_endPad_n->GetPadToDie();
m_padToDieDelay += m_endPad_n->GetPadToDieDelay();
}
m_world->Remove( m_originLine );
m_currentWidth = m_originLine.Width();
m_currentEnd = VECTOR2I( 0, 0 );
const BOARD_CONNECTED_ITEM* conItem = static_cast<BOARD_CONNECTED_ITEM*>( aStartItem->GetSourceItem() );
m_netClass = conItem->GetEffectiveNetClass();
calculateTimeDomainTargets();
return true;
}
@ -97,8 +114,49 @@ long long int MEANDER_PLACER::origPathLength() const
}
int64_t MEANDER_PLACER::origPathDelay() const
{
return m_padToDieDelay + lineDelay( m_tunedPath, m_startPad_n, m_endPad_n );
}
void MEANDER_PLACER::calculateTimeDomainTargets()
{
// If this is a time domain tuning, calculate the target length for the desired total delay
if( m_settings.m_isTimeDomain )
{
const int64_t curDelay = origPathDelay();
const int64_t desiredDelayMin = m_settings.m_targetLengthDelay.Min();
const int64_t desiredDelayOpt = m_settings.m_targetLengthDelay.Opt();
const int64_t desiredDelayMax = m_settings.m_targetLengthDelay.Max();
const int64_t delayDifferenceOpt = desiredDelayOpt - curDelay;
const int64_t curLength = origPathLength();
const int64_t lengthDiffMin = m_router->GetInterface()->CalculateLengthForDelay(
desiredDelayOpt - desiredDelayMin, m_currentWidth, false, m_router->Sizes().DiffPairGap(),
m_router->GetCurrentLayer(), m_netClass );
int64_t lengthDiffOpt = m_router->GetInterface()->CalculateLengthForDelay(
std::abs( delayDifferenceOpt ), m_currentWidth, false, m_router->Sizes().DiffPairGap(),
m_router->GetCurrentLayer(), m_netClass );
const int64_t lengthDiffMax = m_router->GetInterface()->CalculateLengthForDelay(
desiredDelayMax - desiredDelayOpt, m_currentWidth, false, m_router->Sizes().DiffPairGap(),
m_router->GetCurrentLayer(), m_netClass );
lengthDiffOpt = delayDifferenceOpt > 0 ? lengthDiffOpt : -lengthDiffOpt;
m_settings.m_targetLength.SetMin( curLength + lengthDiffOpt - lengthDiffMin );
m_settings.m_targetLength.SetOpt( curLength + lengthDiffOpt );
m_settings.m_targetLength.SetMax( curLength + lengthDiffOpt + lengthDiffMax );
}
}
bool MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
{
calculateTimeDomainTargets();
return doMove( aP, aEndItem, m_settings.m_targetLength.Opt(), m_settings.m_targetLength.Min(),
m_settings.m_targetLength.Max() );
}
@ -152,8 +210,10 @@ bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, long long int a
}
long long int lineLen = origPathLength();
int64_t lineDelay = origPathDelay();
m_lastLength = lineLen;
m_lastDelay = lineDelay;
m_lastStatus = TUNED;
if( lineLen > m_settings.m_targetLength.Max() )
@ -163,6 +223,15 @@ bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, long long int a
else
{
m_lastLength = lineLen - tuned.Length();
if( m_settings.m_isTimeDomain )
{
m_lastDelay = lineDelay
- m_router->GetInterface()->CalculateDelayForShapeLineChain(
tuned, m_currentWidth, false, m_router->Sizes().DiffPairGap(),
m_router->GetCurrentLayer(), m_netClass );
}
tuneLineLength( m_result, aTargetLength - lineLen );
}
@ -190,6 +259,13 @@ bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, long long int a
m_lastLength += tuned.Length();
if( m_settings.m_isTimeDomain )
{
m_lastDelay += m_router->GetInterface()->CalculateDelayForShapeLineChain(
tuned, m_currentWidth, false, m_router->Sizes().DiffPairGap(), m_router->GetCurrentLayer(),
m_netClass );
}
if( m_lastLength > aTargetMax )
m_lastStatus = TOO_LONG;
else if( m_lastLength < aTargetMin )
@ -299,7 +375,7 @@ int MEANDER_PLACER::CurrentLayer() const
}
long long int MEANDER_PLACER::TuningResult() const
long long int MEANDER_PLACER::TuningLengthResult() const
{
if( m_lastLength )
return m_lastLength;
@ -308,6 +384,15 @@ long long int MEANDER_PLACER::TuningResult() const
}
int64_t MEANDER_PLACER::TuningDelayResult() const
{
if( m_lastDelay )
return m_lastDelay;
else
return origPathDelay();
}
MEANDER_PLACER::TUNING_STATUS MEANDER_PLACER::TuningStatus() const
{
return m_lastStatus;

View File

@ -91,8 +91,11 @@ public:
/// @copydoc PLACEMENT_ALGO::CurrentLayer()
int CurrentLayer() const override;
/// @copydoc MEANDER_PLACER_BASE::TuningResult()
long long int TuningResult() const override;
/// @copydoc MEANDER_PLACER_BASE::TuningLengthResult()
long long int TuningLengthResult() const override;
/// @copydoc MEANDER_PLACER_BASE::TuningDelayResult()
int64_t TuningDelayResult() const override;
/// @copydoc MEANDER_PLACER_BASE::TuningStatus()
TUNING_STATUS TuningStatus() const override;
@ -106,6 +109,10 @@ protected:
virtual long long int origPathLength() const;
virtual int64_t origPathDelay() const;
virtual void calculateTimeDomainTargets();
///< current routing start point (end of tail, beginning of head)
VECTOR2I m_currentStart;
@ -123,7 +130,14 @@ protected:
///< Total length added by pad to die size.
int m_padToDieLength;
///< Total length added by pad to die size.
int m_padToDieDelay;
///< The netclass for the placed segments
NETCLASS* m_netClass;
long long int m_lastLength;
int64_t m_lastDelay;
TUNING_STATUS m_lastStatus;
};

View File

@ -251,44 +251,6 @@ void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, long long int
}
int MEANDER_PLACER_BASE::GetTotalPadToDieLength( const LINE& aLine ) const
{
int length = 0;
JOINT start;
JOINT end;
m_world->FindLineEnds( aLine, start, end );
// Extract the length of the pad to die for start and end pads
for( auto& link : start.LinkList() )
{
if( const SOLID* solid = dyn_cast<const SOLID*>( link ) )
{
// If there are overlapping pads, choose the first with a non-zero length
if( solid->GetPadToDie() > 0 )
{
length += solid->GetPadToDie();
break;
}
}
}
for( auto& link : end.LinkList() )
{
if( const SOLID* solid = dyn_cast<const SOLID*>( link ) )
{
if( solid->GetPadToDie() > 0 )
{
length += solid->GetPadToDie();
break;
}
}
}
return length;
}
const MEANDER_SETTINGS& MEANDER_PLACER_BASE::MeanderSettings() const
{
return m_settings;
@ -325,6 +287,16 @@ long long int MEANDER_PLACER_BASE::lineLength( const ITEM_SET& aLine, const SOLI
return 0;
ROUTER_IFACE* iface = Router()->GetInterface();
return iface->CalculateRoutedPathLength( aLine, aStartPad, aEndPad );
return iface->CalculateRoutedPathLength( aLine, aStartPad, aEndPad, m_settings.m_netClass );
}
int64_t MEANDER_PLACER_BASE::lineDelay( const ITEM_SET& aLine, const SOLID* aStartPad, const SOLID* aEndPad ) const
{
if( aLine.Empty() )
return 0;
ROUTER_IFACE* iface = Router()->GetInterface();
return iface->CalculateRoutedPathDelay( aLine, aStartPad, aEndPad, m_settings.m_netClass );
}
}

View File

@ -58,7 +58,12 @@ public:
/**
* Return the resultant length or skew of the tuned traces.
*/
virtual long long int TuningResult() const = 0;
virtual long long int TuningLengthResult() const = 0;
/**
* Return the resultant delay or skew of the tuned traces.
*/
virtual int64_t TuningDelayResult() const { return 0; };
/**
* Return the tuning status (too short, too long, etc.) of the trace(s) being tuned.
@ -112,8 +117,6 @@ public:
return false;
}
int GetTotalPadToDieLength( const LINE& aLine ) const;
virtual const ITEM_SET TunedPath() = 0;
protected:
@ -132,6 +135,13 @@ protected:
*/
long long int lineLength( const ITEM_SET& aLine, const SOLID* aStartPad, const SOLID* aEndPad ) const;
/**
* Calculate the total delay of the line represented by an item set (tracks and vias)
* @param aLine
* @return
*/
int64_t lineDelay( const ITEM_SET& aLine, const SOLID* aStartPad, const SOLID* aEndPad ) const;
///< Pointer to world to search colliding items.
NODE* m_world;

View File

@ -35,8 +35,11 @@ MEANDER_SKEW_PLACER::MEANDER_SKEW_PLACER ( ROUTER* aRouter ) :
{
// Init temporary variables (do not leave uninitialized members)
m_coupledLength = 0;
m_padToDieN = 0;
m_padToDieP = 0;
m_coupledDelay = 0;
m_padToDieLengthN = 0;
m_padToDieLengthP = 0;
m_padToDieDelayN = 0;
m_padToDieDelayP = 0;
}
@ -81,43 +84,71 @@ bool MEANDER_SKEW_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
m_tunedPathP = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.PLine().GetLink( 0 ), &m_startPad_p,
&m_endPad_p );
m_padToDieP = 0;
m_padToDieLengthP = 0;
m_padToDieDelayP = 0;
if( m_startPad_p )
m_padToDieP += m_startPad_p->GetPadToDie();
{
m_padToDieLengthP += m_startPad_p->GetPadToDie();
m_padToDieDelayP += m_startPad_p->GetPadToDieDelay();
}
if( m_endPad_p )
m_padToDieP += m_endPad_p->GetPadToDie();
{
m_padToDieLengthP += m_endPad_p->GetPadToDie();
m_padToDieDelayP += m_endPad_p->GetPadToDieDelay();
}
m_tunedPathN = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.NLine().GetLink( 0 ), &m_startPad_n,
&m_endPad_n );
m_padToDieN = 0;
m_padToDieLengthN = 0;
m_padToDieDelayN = 0;
if( m_startPad_n )
m_padToDieN += m_startPad_n->GetPadToDie();
{
m_padToDieLengthN += m_startPad_n->GetPadToDie();
m_padToDieDelayN += m_startPad_n->GetPadToDieDelay();
}
if( m_endPad_n )
m_padToDieN += m_endPad_n->GetPadToDie();
{
m_padToDieLengthN += m_endPad_n->GetPadToDie();
m_padToDieDelayN += m_endPad_n->GetPadToDieDelay();
}
m_world->Remove( m_originLine );
m_currentWidth = m_originLine.Width();
m_currentEnd = VECTOR2I( 0, 0 );
const BOARD_CONNECTED_ITEM* conItem = static_cast<BOARD_CONNECTED_ITEM*>( aStartItem->GetSourceItem() );
m_netClass = conItem->GetEffectiveNetClass();
m_settings.m_netClass = m_netClass;
if ( m_originPair.NetP() == m_originLine.Net() )
{
m_coupledLength = m_padToDieN + lineLength( m_tunedPathN, m_startPad_n, m_endPad_n );
m_lastLength = m_padToDieP + lineLength( m_tunedPathP, m_startPad_p, m_endPad_p );
m_coupledLength = m_padToDieLengthN + lineLength( m_tunedPathN, m_startPad_n, m_endPad_n );
m_lastLength = m_padToDieLengthP + lineLength( m_tunedPathP, m_startPad_p, m_endPad_p );
m_coupledDelay = m_padToDieDelayN + lineDelay( m_tunedPathN, m_startPad_p, m_endPad_p );
m_lastDelay = m_padToDieDelayP + lineDelay( m_tunedPathP, m_startPad_p, m_endPad_p );
m_tunedPath = m_tunedPathP;
}
else
{
m_coupledLength = m_padToDieP + lineLength( m_tunedPathP, m_startPad_p, m_endPad_p );
m_lastLength = m_padToDieN + lineLength( m_tunedPathN, m_startPad_n, m_endPad_n );
m_coupledLength = m_padToDieLengthP + lineLength( m_tunedPathP, m_startPad_p, m_endPad_p );
m_lastLength = m_padToDieLengthN + lineLength( m_tunedPathN, m_startPad_n, m_endPad_n );
m_coupledDelay = m_padToDieDelayP + lineDelay( m_tunedPathP, m_startPad_p, m_endPad_p );
m_lastDelay = m_padToDieDelayN + lineDelay( m_tunedPathN, m_startPad_p, m_endPad_p );
m_tunedPath = m_tunedPathN;
}
calculateTimeDomainTargets();
return true;
}
@ -125,10 +156,18 @@ bool MEANDER_SKEW_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
long long int MEANDER_SKEW_PLACER::origPathLength() const
{
if ( m_originPair.NetP() == m_originLine.Net() )
return m_padToDieP + lineLength( m_tunedPath, m_startPad_p, m_endPad_p );
return m_padToDieLengthP + lineLength( m_tunedPath, m_startPad_p, m_endPad_p );
return m_padToDieN + lineLength( m_tunedPath, m_startPad_n, m_endPad_n );
return m_padToDieLengthN + lineLength( m_tunedPath, m_startPad_n, m_endPad_n );
}
int64_t MEANDER_SKEW_PLACER::origPathDelay() const
{
if( m_originPair.NetP() == m_originLine.Net() )
return m_padToDieDelayP + lineDelay( m_tunedPath, m_startPad_p, m_endPad_p );
return m_padToDieDelayN + lineDelay( m_tunedPath, m_startPad_n, m_endPad_n );
}
@ -140,6 +179,8 @@ long long int MEANDER_SKEW_PLACER::CurrentSkew() const
bool MEANDER_SKEW_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
{
calculateTimeDomainTargets();
bool isPositive = m_originPair.NetP() == m_originLine.Net();
for( const ITEM* item : m_tunedPathP.CItems() )
@ -168,9 +209,37 @@ bool MEANDER_SKEW_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
}
long long int MEANDER_SKEW_PLACER::TuningResult() const
long long int MEANDER_SKEW_PLACER::TuningLengthResult() const
{
return m_lastLength - m_coupledLength;
}
int64_t MEANDER_SKEW_PLACER::TuningDelayResult() const
{
return m_lastDelay - m_coupledDelay;
}
void MEANDER_SKEW_PLACER::calculateTimeDomainTargets()
{
if( m_settings.m_isTimeDomain )
{
const int64_t minSkew = m_router->GetInterface()->CalculateLengthForDelay(
m_settings.m_targetSkewDelay.Min(), m_originPair.Width(), true, m_originPair.Gap(),
m_router->GetCurrentLayer(), m_netClass );
const int64_t optSkew = m_router->GetInterface()->CalculateLengthForDelay(
m_settings.m_targetSkewDelay.Opt(), m_originPair.Width(), true, m_originPair.Gap(),
m_router->GetCurrentLayer(), m_netClass );
const int64_t maxSkew = m_router->GetInterface()->CalculateLengthForDelay(
m_settings.m_targetSkewDelay.Max(), m_originPair.Width(), true, m_originPair.Gap(),
m_router->GetCurrentLayer(), m_netClass );
m_settings.m_targetSkew.SetMin( static_cast<int>( minSkew ) );
m_settings.m_targetSkew.SetOpt( static_cast<int>( optSkew ) );
m_settings.m_targetSkew.SetMax( static_cast<int>( maxSkew ) );
}
}
}

View File

@ -48,20 +48,30 @@ public:
/// @copydoc PLACEMENT_ALGO::Move()
bool Move( const VECTOR2I& aP, ITEM* aEndItem ) override;
/// @copydoc MEANDER_PLACER_BASE::TuningResult()
long long int TuningResult() const override;
/// @copydoc MEANDER_PLACER_BASE::TuningLengthResult()
long long int TuningLengthResult() const override;
/// @copydoc MEANDER_PLACER_BASE::TuningDelayResult()
int64_t TuningDelayResult() const override;
long long int CurrentSkew() const;
private:
long long int origPathLength() const override;
int64_t origPathDelay() const override;
void calculateTimeDomainTargets() override;
DIFF_PAIR m_originPair;
ITEM_SET m_tunedPathP, m_tunedPathN;
long long int m_coupledLength;
int m_padToDieP;
int m_padToDieN;
int64_t m_coupledDelay;
int m_padToDieLengthP;
int m_padToDieLengthN;
int64_t m_padToDieDelayP;
int64_t m_padToDieDelayN;
};
}

View File

@ -77,6 +77,7 @@ struct CONSTRAINT
wxString m_RuleName;
wxString m_FromName;
wxString m_ToName;
bool m_IsTimeDomain;
};

View File

@ -118,7 +118,14 @@ enum DRAG_MODE
virtual DEBUG_DECORATOR* GetDebugDecorator() = 0;
virtual long long int CalculateRoutedPathLength( const ITEM_SET& aLine, const SOLID* aStartPad,
const SOLID* aEndPad ) = 0;
const SOLID* aEndPad, const NETCLASS* aNetClass ) = 0;
virtual int64_t CalculateRoutedPathDelay( const ITEM_SET& aLine, const SOLID* aStartPad, const SOLID* aEndPad,
const NETCLASS* aNetClass ) = 0;
virtual int64_t CalculateLengthForDelay( int64_t aDesiredDelay, int aWidth, bool aIsDiffPairCoupled,
int aDiffPairCouplingGap, int aPNSLayer, const NETCLASS* aNetClass ) = 0;
virtual int64_t CalculateDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, int aWidth,
bool aIsDiffPairCoupled, int aDiffPairCouplingGap, int aPNSLayer,
const NETCLASS* aNetClass ) = 0;
virtual PCB_LAYER_ID GetBoardLayerFromPNSLayer( int aLayer ) const = 0;
virtual int GetPNSLayerFromBoardLayer( PCB_LAYER_ID aLayer ) const = 0;
};

Some files were not shown because too many files have changed in this diff Show More