KiCad PCB EDA Suite
Loading...
Searching...
No Matches
tuning_profiles.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2020 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Jon Evans <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <lset.h>
23#include <netclass.h>
25
27
28#include <nlohmann/json.hpp>
29#include <settings/parameters.h>
30
31
33
34TUNING_PROFILES::TUNING_PROFILES( JSON_SETTINGS* aParent, const std::string& aPath ) :
35 NESTED_SETTINGS( "tuning_profiles", tuningParametersSchemaVersion, aParent, aPath, false )
36{
37 auto saveViaOverrideConfigurationLine =
38 []( nlohmann::json& json_array, const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& item )
39 {
40 const nlohmann::json item_json = { { "signal_layer_from", LSET::Name( item.m_SignalLayerFrom ) },
41 { "signal_layer_to", LSET::Name( item.m_SignalLayerTo ) },
42 { "via_layer_from", LSET::Name( item.m_ViaLayerFrom ) },
43 { "via_layer_to", LSET::Name( item.m_ViaLayerTo ) },
44 { "delay", item.m_Delay } };
45
46 json_array.push_back( item_json );
47 };
48
49 auto readViaOverrideConfigurationLine = []( const nlohmann::json& entry )
50 {
51 wxString signalLayerFromName = entry["signal_layer_from"];
52 int signalLayerFromId = LSET::NameToLayer( signalLayerFromName );
53
54 wxString signalLayerToName = entry["signal_layer_to"];
55 int signalLayerToId = LSET::NameToLayer( signalLayerToName );
56
57 wxString viaLayerFromName = entry["via_layer_from"];
58 int viaLayerFromId = LSET::NameToLayer( viaLayerFromName );
59
60 wxString viaLayerToName = entry["via_layer_to"];
61 int viaLayerToId = LSET::NameToLayer( viaLayerToName );
62
63 int delay = entry["delay"];
64
65 DELAY_PROFILE_VIA_OVERRIDE_ENTRY item{ static_cast<PCB_LAYER_ID>( signalLayerFromId ),
66 static_cast<PCB_LAYER_ID>( signalLayerToId ),
67 static_cast<PCB_LAYER_ID>( viaLayerFromId ),
68 static_cast<PCB_LAYER_ID>( viaLayerToId ), delay };
69
70 return item;
71 };
72
73 auto saveUserDefinedProfileConfigurationLine =
74 [saveViaOverrideConfigurationLine]( nlohmann::json& json_array, const TUNING_PROFILE& item )
75 {
76 nlohmann::json layer_entries = nlohmann::json::array();
77
78 for( const DELAY_PROFILE_TRACK_PROPAGATION_ENTRY& trackEntry : item.m_TrackPropagationEntries )
79 {
80 nlohmann::json layer_json;
81
82 layer_json["signal_layer"] = LSET::Name( trackEntry.m_signalLayer );
83 layer_json["top_reference_layer"] = LSET::Name( trackEntry.m_topReferenceLayer );
84 layer_json["bottom_reference_layer"] = LSET::Name( trackEntry.m_bottomReferenceLayer );
85 layer_json["width"] = trackEntry.m_width;
86 layer_json["diff_pair_gap"] = trackEntry.m_diffPairGap;
87 layer_json["delay"] = trackEntry.m_delay;
88
89 layer_entries.push_back( layer_json );
90 }
91
92 nlohmann::json via_overrides = nlohmann::json::array();
93
94 for( const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& viaOverride : item.m_ViaOverrides )
95 {
96 saveViaOverrideConfigurationLine( via_overrides, viaOverride );
97 }
98
99 const nlohmann::json item_json = { { "profile_name", item.m_ProfileName.ToUTF8() },
100 { "type", static_cast<int>( item.m_Type ) },
101 { "target_impedance", item.m_TargetImpedance },
102 { "frequency", item.m_Frequency },
103 { "model_solder_mask", item.m_ModelSolderMask },
104 { "enable_time_domain_tuning", item.m_EnableTimeDomainTuning },
105 { "layer_entries", layer_entries },
106 { "via_prop_delay", item.m_ViaPropagationDelay },
107 { "via_overrides", via_overrides },
108 { "net_chain_bridge_prop_delay", item.m_NetChainBridgePropagationDelay } };
109
110 json_array.push_back( item_json );
111 };
112
113 auto readUserDefinedProfileConfigurationLine = [readViaOverrideConfigurationLine]( const nlohmann::json& entry )
114 {
115 const wxString profileName = entry["profile_name"];
116 const TUNING_PROFILE::PROFILE_TYPE profileType = static_cast<TUNING_PROFILE::PROFILE_TYPE>( entry["type"] );
117 const double targetImpedance = entry["target_impedance"];
118 const double frequency = entry["frequency"];
119 const bool modelSolderMask = entry["model_solder_mask"];
120 const bool enableTimeDomainTuning = entry["enable_time_domain_tuning"];
121 const int viaPropDelay = entry["via_prop_delay"];
122 const int netChainBridgePropDelay = entry["net_chain_bridge_prop_delay"];
123 std::vector<DELAY_PROFILE_TRACK_PROPAGATION_ENTRY> trackEntries;
124 std::map<PCB_LAYER_ID, DELAY_PROFILE_TRACK_PROPAGATION_ENTRY> trackEntriesMap;
125
126 for( const nlohmann::json& layerEntry : entry["layer_entries"] )
127 {
128 if( !layerEntry.is_object() )
129 continue;
130
131 wxString signalLayer = layerEntry["signal_layer"];
132 wxString topRefLayer = layerEntry["top_reference_layer"];
133 wxString bottomRefLayer = layerEntry["bottom_reference_layer"];
134 int signalLayerId = LSET::NameToLayer( signalLayer );
135 int topRefLayerId = LSET::NameToLayer( topRefLayer );
136 int bottomRefLayerId = LSET::NameToLayer( bottomRefLayer );
137
139 trackEntry.m_signalLayer = static_cast<PCB_LAYER_ID>( signalLayerId );
140 trackEntry.m_topReferenceLayer = static_cast<PCB_LAYER_ID>( topRefLayerId );
141 trackEntry.m_bottomReferenceLayer = static_cast<PCB_LAYER_ID>( bottomRefLayerId );
142 trackEntry.m_width = layerEntry["width"];
143 trackEntry.m_diffPairGap = layerEntry["diff_pair_gap"];
144 trackEntry.m_delay = layerEntry["delay"];
145 trackEntry.m_enableTimeDomainTuning = enableTimeDomainTuning;
146
147 trackEntries.push_back( trackEntry );
148 trackEntriesMap[static_cast<PCB_LAYER_ID>( signalLayerId )] = trackEntry;
149 }
150
151 std::vector<DELAY_PROFILE_VIA_OVERRIDE_ENTRY> viaOverrides;
152
153 for( const nlohmann::json& viaEntry : entry["via_overrides"] )
154 {
155 if( !viaEntry.is_object() || !viaEntry.contains( "signal_layer_from" ) )
156 continue;
157
158 viaOverrides.push_back( readViaOverrideConfigurationLine( viaEntry ) );
159 }
160
161 TUNING_PROFILE item{ profileName,
162 profileType,
163 targetImpedance,
164 frequency,
165 enableTimeDomainTuning,
166 modelSolderMask,
167 std::move( trackEntries ),
168 viaPropDelay,
169 std::move( viaOverrides ),
170 netChainBridgePropDelay,
171 std::move( trackEntriesMap ) };
172
173 return item;
174 };
175
176 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
177 "tuning_profiles_impedance_geometric",
178 [this, saveUserDefinedProfileConfigurationLine]() -> nlohmann::json
179 {
180 nlohmann::json ret = nlohmann::json::array();
181
182 for( const auto& entry : m_tuningProfiles )
183 saveUserDefinedProfileConfigurationLine( ret, entry );
184
185 return ret;
186 },
187 [this, readUserDefinedProfileConfigurationLine]( const nlohmann::json& aJson )
188 {
189 if( !aJson.is_array() )
190 return;
191
193
194 for( const nlohmann::json& entry : aJson )
195 {
196 if( !entry.is_object() || !entry.contains( "profile_name" ) )
197 continue;
198
199 m_tuningProfiles.emplace_back( readUserDefinedProfileConfigurationLine( entry ) );
200 }
201 },
202 {} ) );
203
204 registerMigration( 0, 1, std::bind( &TUNING_PROFILES::migrateSchema0to1, this ) );
205 registerMigration( 1, 2, std::bind( &TUNING_PROFILES::migrateSchema1to2, this ) );
206}
207
208
210{
211 // Add frequency and model solder mask fields to tuning profiles
212 if( m_internals->contains( "tuning_profiles_impedance_geometric" )
213 && m_internals->At( "tuning_profiles_impedance_geometric" ).is_array() )
214 {
215 for( auto& profile : m_internals->At( "tuning_profiles_impedance_geometric" ).items() )
216 {
217 profile.value()["frequency"] = 1e9;
218 profile.value()["model_solder_mask"] = false;
219 }
220 }
221
222 return true;
223}
224
226{
227 // Add net chain bridge propagation delay entries
228 if( m_internals->contains( "tuning_profiles_impedance_geometric" )
229 && m_internals->At( "tuning_profiles_impedance_geometric" ).is_array() )
230 {
231 for( auto& profile : m_internals->At( "tuning_profiles_impedance_geometric" ).items() )
232 {
233 profile.value()["net_chain_bridge_prop_delay"] = 0;
234 }
235 }
236
237 return true;
238}
239
240
242{
243 // Release early before destroying members
244 if( m_parent )
245 {
246 m_parent->ReleaseNestedSettings( this );
247 m_parent = nullptr;
248 }
249}
250
251
253{
254 auto itr = std::find_if( m_tuningProfiles.begin(), m_tuningProfiles.end(),
255 [&aProfileName]( const TUNING_PROFILE& aProfile )
256 {
257 return aProfile.m_ProfileName == aProfileName;
258 } );
259
260 if( itr == m_tuningProfiles.end() )
261 return m_nullDelayProfile;
262
263 return *itr;
264}
265
266
268{
269 return m_tuningProfiles == aOther.m_tuningProfiles;
270}
Represents a single line in a time domain profile track propagation setup.
PCB_LAYER_ID m_bottomReferenceLayer
int m_delay
PCB_LAYER_ID m_topReferenceLayer
int m_diffPairGap
bool m_enableTimeDomainTuning
int m_width
PCB_LAYER_ID m_signalLayer
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
void registerMigration(int aOldSchemaVersion, int aNewSchemaVersion, std::function< bool(void)> aMigrator)
Registers a migration from one schema version to another.
JSON_SETTINGS(const wxString &aFilename, SETTINGS_LOC aLocation, int aSchemaVersion)
std::unique_ptr< JSON_SETTINGS_INTERNALS > m_internals
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
Definition lset.cpp:113
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition lset.cpp:184
JSON_SETTINGS * m_parent
A pointer to the parent object to load and store from.
NESTED_SETTINGS(const std::string &aName, int aSchemaVersion, JSON_SETTINGS *aParent, const std::string &aPath, bool aLoadFromFile=true)
Like a normal param, but with custom getter and setter functions.
Definition parameters.h:299
TUNING_PROFILE m_nullDelayProfile
TUNING_PROFILE & GetTuningProfile(wxString aProfileName)
std::vector< TUNING_PROFILE > m_tuningProfiles
TUNING_PROFILES(JSON_SETTINGS *aParent, const std::string &aPath)
bool migrateSchema1to2() const
bool migrateSchema0to1() const
bool operator==(const TUNING_PROFILES &aOther) const
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
Represents a single line in the time domain configuration via overrides configuration grid.
Represents a single line in the tuning profile configuration grid.
constexpr int tuningParametersSchemaVersion