Skip to content

Commit

Permalink
[WIP] eeschema/erc: add hierarchical pins connections check
Browse files Browse the repository at this point in the history
  • Loading branch information
mplucinski committed Apr 16, 2024
1 parent 5d7e968 commit ba40178
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 0 deletions.
122 changes: 122 additions & 0 deletions eeschema/erc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,123 @@ int ERC_TESTER::TestPinToPin()
return errors;
}

// TODO: remove?
int ERC_TESTER::TestSheetPinToSheetPin()
{
ERC_SETTINGS& settings = m_schematic->ErcSettings();
const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();

int errors = 0;

for( const std::pair<NET_NAME_CODE_CACHE_KEY, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
{
struct ERC_SCH_SHEET_PIN_CONTEXT {
// TODO: elsewhere?
SCH_SHEET_PIN *pin;
SCH_SHEET_PATH path;
};

std::vector<ERC_SCH_SHEET_PIN_CONTEXT> sheetPins;
std::unordered_map<EDA_ITEM*, SCH_SCREEN*> sheetPinToScreenMap;

for( CONNECTION_SUBGRAPH* subgraph: net.second )
{
for( SCH_ITEM* item : subgraph->GetItems() )
{
#if 0 // TODO: probably not needed?
if( item->Type() == SCH_HIER_LABEL_T) // this is a label *inside* a hierarchical sheet
{
SCH_HIERLABEL *label = static_cast<SCH_HIERLABEL*>(item);

std::cerr << "hierarchical label in the net "
<< net.first.Name << ": "
<< label->GetShownText(false) << " (extra text: "
<< label->GetShownText(true) << ")" << std::endl;
}
#endif
if (item->Type() == SCH_SHEET_PIN_T) // this is a pin *outside* a hierarchical sheet (on the "frame" of the sub-sheet in the parent sheet)
{
auto pin = static_cast<SCH_SHEET_PIN*>(item);

std::cerr << "net " << net.first.Name << " (" << subgraph->GetNetName() << "), "
<< "subgraph on sheet " << subgraph->GetSheet().PathAsString() << ": "
<< "found pin: " << pin->GetShownText(false) << " (extra text: " << pin->GetShownText(true) << ")"
<< std::endl;

sheetPins.emplace_back( pin, subgraph->GetSheet() );
sheetPinToScreenMap[item] = subgraph->GetSheet().LastScreen();
}
}
}

// TODO: elsewhere?
auto toElectricalPinType = [](LABEL_FLAG_SHAPE flag)->ELECTRICAL_PINTYPE
{
std::cerr << "converting flag " << std::hex << flag << " to electrical pin type" << std::endl;
if (flag == L_INPUT) return ELECTRICAL_PINTYPE::PT_INPUT;
if (flag == L_OUTPUT) return ELECTRICAL_PINTYPE::PT_OUTPUT;
if (flag == L_BIDI) return ELECTRICAL_PINTYPE::PT_BIDI;
if (flag == L_TRISTATE) return ELECTRICAL_PINTYPE::PT_TRISTATE;
if (flag == L_UNSPECIFIED) return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
// TODO: what's a proper way of printing warnings in KiCad?
std::cerr << "Could not convert label flag shape " << std::hex << flag << " to electrical pin type" << std::endl;
return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
};

for (auto refIt = sheetPins.begin(); refIt != sheetPins.end(); ++refIt)
{
auto refType = toElectricalPinType(refIt->pin->GetShape());

for (auto testIt = refIt + 1; testIt != sheetPins.end(); ++testIt)
{
std::cerr << "checking " << refIt->pin->GetShownText(&refIt->path, true) << " of " << refIt->pin->GetParent()->GetShownName( true ) << " "
<< "against " << testIt->pin->GetShownText(&testIt->path, true) << " of " << testIt->pin->GetParent()->GetShownName( true )
<< std::endl;

auto testType = toElectricalPinType(testIt->pin->GetShape());
auto erc = settings.GetPinMapValue(refType, testType);

if (erc != PIN_ERROR::OK /*TODO: && settings.isTestEnabled(..SHEET_PIN_TO_SHEET_PIN..*/)
{
// TODO: hijacking PIN_TO_PIN stuff here but should probably have its only types
auto ercItem = ERC_ITEM::Create( erc == PIN_ERROR::WARNING ? ERCE_PIN_TO_PIN_WARNING :
ERCE_PIN_TO_PIN_ERROR );
ercItem->SetItems(refIt->pin, testIt->pin);
ercItem->SetSheetSpecificPath( refIt->path );
ercItem->SetItemsSheetPaths( refIt->path, testIt->path );
ercItem->SetErrorMessage(
wxString::Format( _("Sheet pins of type %s and %s are connected"),
ElectricalPinTypeGetText(refType),
ElectricalPinTypeGetText(testType)
)
);

auto marker = new SCH_MARKER(ercItem, refIt->pin->GetPosition());
sheetPinToScreenMap[refIt->pin]->Append( marker );
errors++;
}
}

// TODO: TestPinToPin does some magic to "upgrade to a ""better"" pin". I'm leaving it
// for later
if (DrivenPinTypes.count (refType))
{
// TODO: check settings
// TODO: a new error code?
auto ercItem = ERC_ITEM::Create (ERCE_PIN_NOT_DRIVEN);
ercItem->SetItems( refIt->pin );
ercItem->SetSheetSpecificPath( refIt->path );
ercItem->SetItemsSheetPaths( refIt->path );

auto marker = new SCH_MARKER(ercItem, refIt->pin->GetPosition());
sheetPinToScreenMap[refIt->pin]->Append( marker );
errors++;
}
}
}

return errors;
}

int ERC_TESTER::TestMultUnitPinConflicts()
{
Expand Down Expand Up @@ -1307,6 +1424,11 @@ void ERC_TESTER::RunTests( DS_PROXY_VIEW_ITEM* aDrawingSheet, SCH_EDIT_FRAME* aE
TestPinToPin();
}

// TODO: a new setting for this test?
TestSheetPinToSheetPin();

// TODO: cross test with regular pins? SheetPin against [Regular]Pin ?

// Test similar labels (i;e. labels which are identical when
// using case insensitive comparisons)
if( settings.IsTestEnabled( ERCE_SIMILAR_LABELS ) )
Expand Down
6 changes: 6 additions & 0 deletions eeschema/erc.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ class ERC_TESTER
*/
int TestPinToPin();

/**
* Checks the hierarchical labels of sub sheets against the pin-to-pin connectivity requirements
* @return the error count
*/
int TestSheetPinToSheetPin();

/**
* Checks if shared pins on multi-unit symbols have been connected to different nets
* @return the error count
Expand Down

0 comments on commit ba40178

Please sign in to comment.