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 )
109 THROW_IO_ERRORF(
_(
"Symbol '%s' has a malformed Sim.Pins entry '%s'." ), aRef, token );
111 wxString symbolPin = token.Left( pos );
112 wxString modelPin = token.Mid( pos + 1 );
114 auto [it, inserted] = seen.try_emplace( symbolPin, modelPin );
118 if( it->second != modelPin )
130 pairs.emplace_back( symbolPin, modelPin );
182 const std::vector<UNIT_PIN_MAP>& aUnitMaps,
183 const std::vector<wxString>& aSharedModelPins ) :
193 THROW_IO_ERRORF(
_(
"Repeat-per-unit decomposition does not support model '%s' because it has "
194 "subcircuit parameters." ), aBaseModelName );
198 std::vector<wxString> basePinOrder;
199 std::set<wxString> basePinSet;
203 wxString name( pin.modelPinName );
204 basePinOrder.push_back( name );
205 basePinSet.insert( name );
208 std::set<wxString> sharedSet;
210 for(
const wxString& shared : aSharedModelPins )
212 if( !basePinSet.count( shared ) )
213 THROW_IO_ERRORF( _(
"Shared pin '%s' is not a pin of model '%s'." ), shared, aBaseModelName );
215 sharedSet.insert( shared );
222 std::map<wxString, wxString> modelToSymbol;
225 std::vector<UNIT_INFO> units;
230 info.unit = unitMap.unit;
232 for( const auto& [symbolPin, modelPin] : unitMap.pins )
236 if( !basePinSet.count( modelPin ) )
238 THROW_IO_ERRORF( _(
"Unit %d maps to unknown pin '%s' of model '%s'." ),
244 auto [it, inserted] = info.modelToSymbol.emplace( modelPin, symbolPin );
246 if( !inserted && it->second != symbolPin )
248 THROW_IO_ERRORF( _(
"Unit %d maps model pin '%s' to both symbol pins '%s' and '%s'." ),
256 units.push_back( std::move(
info ) );
260 [&](
const UNIT_INFO& aUnit )
262 for(
const auto& [modelPin, symbolPin] : aUnit.modelToSymbol )
264 if( !sharedSet.count( modelPin ) )
272 std::map<wxString, wxString> sharedNode;
274 for(
const wxString& shared : aSharedModelPins )
276 std::set<wxString> symbolPins;
278 for(
const UNIT_INFO& unit : units )
280 if(
auto it = unit.modelToSymbol.find( shared ); it != unit.modelToSymbol.end() )
281 symbolPins.insert( it->second );
284 if( symbolPins.empty() )
285 THROW_IO_ERRORF(
_(
"Shared pin '%s' is not connected on any unit." ), shared );
287 if( symbolPins.size() > 1 )
288 THROW_IO_ERRORF(
_(
"Shared pin '%s' resolves to more than one net." ), shared );
290 sharedNode[shared] =
nodeName( *symbolPins.begin() );
295 for(
const wxString& basePin : basePinOrder )
297 if( sharedSet.count( basePin ) )
302 for(
const UNIT_INFO& unit : units )
304 if( unit.modelToSymbol.count( basePin ) )
310 THROW_IO_ERRORF(
_(
"Model '%s' pin '%s' is neither shared nor assigned to any unit." ),
311 aBaseModelName, basePin );
317 for(
const UNIT_INFO& unit : units )
319 if( !mapsNonShared( unit ) )
323 instance.unit = unit.unit;
325 for(
const wxString& basePin : basePinOrder )
327 if( sharedSet.count( basePin ) )
329 instance.nodes.push_back( sharedNode.at( basePin ) );
331 else if(
auto it = unit.modelToSymbol.find( basePin ); it != unit.modelToSymbol.end() )
333 instance.nodes.push_back(
nodeName( it->second ) );
338 instance.nodes.push_back( wxString::Format( wxS(
"nc_%zu_%s" ), m_instances.size(),
343 m_instances.push_back( std::move( instance ) );
346 if( m_instances.empty() )
347 THROW_IO_ERROR(
_(
"Repeat-per-unit decomposition produced no instances." ) );
352 std::set<wxString> addedNodes;
355 [&](
const wxString& aNode,
const wxString& aSymbolPin )
357 if( addedNodes.insert( aNode ).second )
358 AddPin( { aNode.ToStdString(), aSymbolPin } );
361 for(
const UNIT_INFO& unit : units )
363 if( !mapsNonShared( unit ) )
366 for(
const wxString& basePin : basePinOrder )
368 if( sharedSet.count( basePin ) )
371 if(
auto it = unit.modelToSymbol.find( basePin ); it != unit.modelToSymbol.end() )
372 addOuterPin(
nodeName( it->second ), it->second );
376 for(
const wxString& basePin : basePinOrder )
378 if( !sharedSet.count( basePin ) )
381 for(
const UNIT_INFO& unit : units )
383 if(
auto it = unit.modelToSymbol.find( basePin ); it != unit.modelToSymbol.end() )
385 addOuterPin( sharedNode.at( basePin ), it->second );
391 m_signature = computeSignature();
wxString result
Test unit parsing edge cases and error handling.