96 const wxString& aRef )
98 std::vector<std::pair<wxString, wxString>> pairs;
99 std::map<wxString, wxString> seen;
101 wxStringTokenizer tokenizer( aPins, wxS(
" \t\r\n" ), wxTOKEN_STRTOK );
103 while( tokenizer.HasMoreTokens() )
105 wxString token = tokenizer.GetNextToken();
106 int pos = token.Find( wxS(
'=' ) );
108 if( pos == wxNOT_FOUND || pos == 0 || pos == (
int) token.length() - 1 )
111 _(
"Symbol '%s' has a malformed Sim.Pins entry '%s'." ), aRef, token ) );
114 wxString symbolPin = token.Left( pos );
115 wxString modelPin = token.Mid( pos + 1 );
117 auto [it, inserted] = seen.try_emplace( symbolPin, modelPin );
121 if( it->second != modelPin )
124 _(
"Symbol '%s' maps pin '%s' to both '%s' and '%s'." ),
125 aRef, symbolPin, it->second, modelPin ) );
131 pairs.emplace_back( symbolPin, modelPin );
183 const std::vector<UNIT_PIN_MAP>& aUnitMaps,
184 const std::vector<wxString>& aSharedModelPins ) :
195 _(
"Repeat-per-unit decomposition does not support model '%s' because it has "
196 "subcircuit parameters." ),
201 std::vector<wxString> basePinOrder;
202 std::set<wxString> basePinSet;
206 wxString name( pin.modelPinName );
207 basePinOrder.push_back( name );
208 basePinSet.insert( name );
211 std::set<wxString> sharedSet;
213 for(
const wxString& shared : aSharedModelPins )
215 if( !basePinSet.count( shared ) )
217 THROW_IO_ERROR( wxString::Format(
218 _(
"Shared pin '%s' is not a pin of model '%s'." ), shared, aBaseModelName ) );
221 sharedSet.insert( shared );
228 std::map<wxString, wxString> modelToSymbol;
231 std::vector<UNIT_INFO> units;
236 info.unit = unitMap.unit;
238 for(
const auto& [symbolPin, modelPin] : unitMap.pins )
242 if( !basePinSet.count( modelPin ) )
245 _(
"Unit %d maps to unknown pin '%s' of model '%s'." ), unitMap.unit,
246 modelPin, aBaseModelName ) );
249 auto [it, inserted] =
info.modelToSymbol.emplace( modelPin, symbolPin );
251 if( !inserted && it->second != symbolPin )
254 _(
"Unit %d maps model pin '%s' to both symbol pins '%s' and '%s'." ),
255 unitMap.unit, modelPin, it->second, symbolPin ) );
259 units.push_back( std::move(
info ) );
263 [&](
const UNIT_INFO& aUnit )
265 for(
const auto& [modelPin, symbolPin] : aUnit.modelToSymbol )
267 if( !sharedSet.count( modelPin ) )
275 std::map<wxString, wxString> sharedNode;
277 for(
const wxString& shared : aSharedModelPins )
279 std::set<wxString> symbolPins;
281 for(
const UNIT_INFO& unit : units )
283 if(
auto it = unit.modelToSymbol.find( shared ); it != unit.modelToSymbol.end() )
284 symbolPins.insert( it->second );
287 if( symbolPins.empty() )
290 _(
"Shared pin '%s' is not connected on any unit." ), shared ) );
293 if( symbolPins.size() > 1 )
296 _(
"Shared pin '%s' resolves to more than one net." ), shared ) );
299 sharedNode[shared] =
nodeName( *symbolPins.begin() );
304 for(
const wxString& basePin : basePinOrder )
306 if( sharedSet.count( basePin ) )
311 for(
const UNIT_INFO& unit : units )
313 if( unit.modelToSymbol.count( basePin ) )
320 _(
"Model '%s' pin '%s' is neither shared nor assigned to any unit." ),
321 aBaseModelName, basePin ) );
327 for(
const UNIT_INFO& unit : units )
329 if( !mapsNonShared( unit ) )
333 instance.unit = unit.unit;
335 for(
const wxString& basePin : basePinOrder )
337 if( sharedSet.count( basePin ) )
339 instance.nodes.push_back( sharedNode.at( basePin ) );
341 else if(
auto it = unit.modelToSymbol.find( basePin ); it != unit.modelToSymbol.end() )
343 instance.nodes.push_back(
nodeName( it->second ) );
348 instance.nodes.push_back( wxString::Format( wxS(
"nc_%zu_%s" ), m_instances.size(),
353 m_instances.push_back( std::move( instance ) );
356 if( m_instances.empty() )
357 THROW_IO_ERROR(
_(
"Repeat-per-unit decomposition produced no instances." ) );
362 std::set<wxString> addedNodes;
365 [&](
const wxString& aNode,
const wxString& aSymbolPin )
367 if( addedNodes.insert( aNode ).second )
368 AddPin( { aNode.ToStdString(), aSymbolPin } );
371 for(
const UNIT_INFO& unit : units )
373 if( !mapsNonShared( unit ) )
376 for(
const wxString& basePin : basePinOrder )
378 if( sharedSet.count( basePin ) )
381 if(
auto it = unit.modelToSymbol.find( basePin ); it != unit.modelToSymbol.end() )
382 addOuterPin(
nodeName( it->second ), it->second );
386 for(
const wxString& basePin : basePinOrder )
388 if( !sharedSet.count( basePin ) )
391 for(
const UNIT_INFO& unit : units )
393 if(
auto it = unit.modelToSymbol.find( basePin ); it != unit.modelToSymbol.end() )
395 addOuterPin( sharedNode.at( basePin ), it->second );
401 m_signature = computeSignature();
wxString result
Test unit parsing edge cases and error handling.