Skip to content

Commit

Permalink
add more schematic checks
Browse files Browse the repository at this point in the history
 - one-label nets
 - unconnected pins
 - unconnected ports
  • Loading branch information
carrotIndustries committed Jan 14, 2022
1 parent bc78ec2 commit fa257a5
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 9 deletions.
50 changes: 41 additions & 9 deletions src/imp/rules/rule_editor_connectivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,46 @@ void RuleEditorConnectivity::populate()
{
rule2 = &dynamic_cast<RuleConnectivity &>(rule);

Gtk::CheckButton *editor = Gtk::manage(new Gtk::CheckButton("Include unnamed nets"));
editor->set_valign(Gtk::ALIGN_START);
pack_start(*editor, true, true, 0);
editor->set_active(rule2->include_unnamed);
editor->signal_toggled().connect([this, editor] {
rule2->include_unnamed = editor->get_active();
s_signal_updated.emit();
});
editor->show();
auto box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
box->set_margin_start(20);
box->set_margin_end(20);
box->set_margin_bottom(20);
{
auto la = Gtk::manage(new Gtk::Label("• One-pin nets"));
la->set_halign(Gtk::ALIGN_START);
box->pack_start(*la, true, true, 0);
}
{
Gtk::CheckButton *editor = Gtk::manage(new Gtk::CheckButton("Include unnamed nets"));
editor->set_halign(Gtk::ALIGN_START);
editor->set_margin_start(10);
box->pack_start(*editor, true, true, 0);
editor->set_active(rule2->include_unnamed);
editor->signal_toggled().connect([this, editor] {
rule2->include_unnamed = editor->get_active();
s_signal_updated.emit();
});
}
{
auto la = Gtk::manage(new Gtk::Label("• One-label nets"));
la->set_margin_top(5);
la->set_halign(Gtk::ALIGN_START);
box->pack_start(*la, true, true, 0);
}
{
auto la = Gtk::manage(new Gtk::Label("• Unconnected pins"));
la->set_margin_top(5);
la->set_halign(Gtk::ALIGN_START);
box->pack_start(*la, true, true, 0);
}
{
auto la = Gtk::manage(new Gtk::Label("• Unconnected ports"));
la->set_margin_top(5);
la->set_halign(Gtk::ALIGN_START);
box->pack_start(*la, true, true, 0);
}

box->show_all();
pack_start(*box, false, false, 0);
}
} // namespace horizon
131 changes: 131 additions & 0 deletions src/schematic/schematic_rules_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,137 @@ RulesCheckResult SchematicRules::check_connectivity(const BlocksSchematic &block
}
}
}
const auto all_sheets = blocks.get_top_block_item().schematic.get_all_sheets();


for (const auto &[uu_block, block_item] : blocks.blocks) {
std::map<UUID, std::set<UUID>> net_segments_with_labels;
for (const auto &[uu_sheet, sheet] : block_item.schematic.sheets) {
auto net_segments = sheet.analyze_net_segments();
for (const auto &[ns, nsinfo] : net_segments) {
if (nsinfo.really_has_label()) {
if (!nsinfo.net->is_port)
net_segments_with_labels[nsinfo.net->uuid].insert(ns);
}
}
}
for (const auto &[net, net_segments] : net_segments_with_labels) {
if (net_segments.size() == 1) {
const auto seg = *net_segments.begin();
r.errors.emplace_back(RulesCheckErrorLevel::WARN);
auto &x = r.errors.back();
x.comment = "Net \"" + block_item.block.get_net_name(net) + "\" only has one net segment with a label";
// find sheet the only label is on
bool found = false;
for (const auto &[uu_sheet, sheet] : block_item.schematic.sheets) {
for (const auto &[uu_label, label] : sheet.net_labels) {
if (label.junction->net->uuid == net && label.junction->net_segment == seg) {
// find first sheet to place warning on
for (const auto &it : all_sheets) {
if (it.schematic.block->uuid == uu_block && it.sheet.uuid == uu_sheet) {
x.has_location = true;
if (it.instance_path.size())
x.comment += " (Only shown in first instance)";
x.instance_path = it.instance_path;
x.sheet = it.sheet.uuid;
x.location = label.junction->position;
break;
}
}

found = true;
break;
}
}
if (found)
break;
}
}
}
}

for (const auto &[uu_block, block_item] : blocks.blocks) {
for (const auto &[uu_comp, comp] : block_item.block.components) {
std::set<UUIDPath<2>> pins;
for (const auto &[uu_gate, gate] : comp.entity->gates) {
for (const auto &[uu_pin, pin] : gate.unit->pins) {
pins.emplace(uu_gate, uu_pin);
}
}
for (const auto &[path, net] : comp.connections)
pins.erase(path);

for (const auto &pin_path : pins) {
r.errors.emplace_back(RulesCheckErrorLevel::FAIL);
auto &x = r.errors.back();
const auto &gate = comp.entity->gates.at(pin_path.at(0));
x.comment = "Pin " + comp.refdes + gate.suffix + "." + gate.unit->pins.at(pin_path.at(1)).primary_name
+ " is not connected (not found in schematic)";
bool found = false;
for (const auto &it : all_sheets) {
for (const auto &[uu_sym, sym] : it.sheet.symbols) {
if (sym.component->uuid == uu_comp && sym.gate->uuid == pin_path.at(0)) {
x.comment = "Pin "
+ blocks.get_top_block_item()
.block.get_component_info(comp, it.instance_path)
.refdes
+ sym.gate->suffix + "." + sym.gate->unit->pins.at(pin_path.at(1)).primary_name
+ " is not connected";
x.has_location = true;
if (it.instance_path.size())
x.comment += " (Only shown in first instance)";
x.instance_path = it.instance_path;
x.sheet = it.sheet.uuid;
x.location = sym.placement.transform(sym.symbol.pins.at(pin_path.at(1)).position);
found = true;
break;
}
}
if (found)
break;
}
}
}
}

for (const auto &[uu_block, block_item] : blocks.blocks) {
for (const auto &[uu_inst, inst] : block_item.block.block_instances) {
std::set<UUID> ports;
for (const auto &[uu_net, net] : inst.block->nets) {
if (net.is_port)
ports.insert(uu_net);
}
for (const auto &[uu_port, conn] : inst.connections)
ports.erase(uu_port);

for (const auto &uu_port : ports) {
r.errors.emplace_back(RulesCheckErrorLevel::FAIL);
auto &x = r.errors.back();
x.comment = "Port " + inst.refdes + "." + inst.block->nets.at(uu_port).name + " is not connected";
bool found = false;
for (const auto &it : all_sheets) {
for (const auto &[uu_sym, sym] : it.sheet.block_symbols) {
if (sym.block_instance->uuid == uu_inst) {
x.has_location = true;
if (it.instance_path.size())
x.comment += " (Only shown in first instance)";
x.instance_path = it.instance_path;
x.sheet = it.sheet.uuid;
x.location = sym.placement.transform(
sym.symbol.ports.at(BlockSymbolPort::get_uuid_for_net(uu_port)).position);
found = true;
break;
}
}
if (found)
break;
}
if (!found)
x.comment += " (Not found on schematic)";
}
}
}

r.update();
return r;
}
Expand Down
6 changes: 6 additions & 0 deletions src/schematic/sheet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,11 @@ bool NetSegmentInfo::is_bus() const
return false;
}

bool NetSegmentInfo::really_has_label() const
{
return has_label && !has_power_sym && !has_bus_ripper;
}

std::map<UUID, NetSegmentInfo> Sheet::analyze_net_segments() const
{
std::map<UUID, NetSegmentInfo> net_segments;
Expand All @@ -551,6 +556,7 @@ std::map<UUID, NetSegmentInfo> Sheet::analyze_net_segments() const
for (const auto &it : bus_rippers) {
if (net_segments.count(it.second.net_segment)) {
net_segments.at(it.second.net_segment).has_label = true;
net_segments.at(it.second.net_segment).has_bus_ripper = true;
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/schematic/sheet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class NetSegmentInfo {
NetSegmentInfo(const SchematicJunction *ju);
bool has_label = false;
bool has_power_sym = false;
bool has_bus_ripper = false;
bool really_has_label() const;
Coordi position;
Net *net = nullptr;
Bus *bus = nullptr;
Expand Down

0 comments on commit fa257a5

Please sign in to comment.