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;
201 for(
const std::reference_wrapper<const SIM_MODEL_PIN>&
pin : aBaseModel.
GetPins() )
203 wxString name( pin.get().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." ),
318 for(
const UNIT_INFO& unit : units )
320 if( !mapsNonShared( unit ) )
324 instance.unit = unit.unit;
326 for(
const wxString& basePin : basePinOrder )
328 if( sharedSet.count( basePin ) )
330 instance.nodes.push_back( sharedNode.at( basePin ) );
332 else if(
auto it = unit.modelToSymbol.find( basePin ); it != unit.modelToSymbol.end() )
334 instance.nodes.push_back(
nodeName( it->second ) );
339 instance.nodes.push_back( wxString::Format( wxS(
"nc_%zu_%s" ),
345 m_instances.push_back( std::move( instance ) );
348 if( m_instances.empty() )
349 THROW_IO_ERROR(
_(
"Repeat-per-unit decomposition produced no instances." ) );
354 std::set<wxString> addedNodes;
357 [&](
const wxString& aNode,
const wxString& aSymbolPin )
359 if( addedNodes.insert( aNode ).second )
360 AddPin( { aNode.ToStdString(), aSymbolPin } );
363 for(
const UNIT_INFO& unit : units )
365 if( !mapsNonShared( unit ) )
368 for(
const wxString& basePin : basePinOrder )
370 if( sharedSet.count( basePin ) )
373 if(
auto it = unit.modelToSymbol.find( basePin ); it != unit.modelToSymbol.end() )
374 addOuterPin(
nodeName( it->second ), it->second );
378 for(
const wxString& basePin : basePinOrder )
380 if( !sharedSet.count( basePin ) )
383 for(
const UNIT_INFO& unit : units )
385 if(
auto it = unit.modelToSymbol.find( basePin ); it != unit.modelToSymbol.end() )
387 addOuterPin( sharedNode.at( basePin ), it->second );
393 m_signature = computeSignature();
wxString result
Test unit parsing edge cases and error handling.