Files
essim/tests/test_pin_model.cpp
François cb61e9b084 P3: unify connector layout + BSDL behind one PinModel provider
New PinModel interface (spec_for / layout / source) + a single apply_model(
Part*, const PinModel&) that materialises missing layout pins and sets each
pin's spec only where the model speaks (spec.source != None), so one source
never clobbers another's. ConnectorModel wraps pin_role/pin_layout;
BsdlPinModel wraps a parsed BsdlModel (indexed by port name and physical pad).
set-connector-type and screen_settype now use ConnectorModel + apply_model;
attach-bsdl and the restore re-apply keep calling apply_bsdl, now a thin
adapter over apply_model. Behaviour-preserving: unit tests (73 cases) green and
the real 8-card system re-runs identically (1517/1517 bound, same JTAG
findings). Covered by test_pin_model.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 16:02:39 +02:00

71 lines
2.2 KiB
C++

#include <doctest/doctest.h>
#include "system/parts.hpp"
#include "system/pin_model.hpp"
#include "system/pin_spec.hpp"
#include "system/pins.hpp"
#include <string>
#include <vector>
namespace {
// A stand-in PinModel: knows VCC (power) and CLK (clock input), has a 3-pin
// canonical layout, and says nothing about anything else.
struct FakeModel : PinModel {
PinSpec spec_for(const std::string &name) const override {
PinSpec s;
if (name == "VCC") {
s.function = PinFunction::Power;
s.direction = PinDirection::Power;
s.source = SpecSource::Bsdl;
} else if (name == "CLK") {
s.function = PinFunction::Clock;
s.direction = PinDirection::In;
s.source = SpecSource::Bsdl;
}
return s; // else default: source == None
}
std::vector<std::string> layout() const override {
return {"VCC", "CLK", "GND"};
}
SpecSource source() const override { return SpecSource::Bsdl; }
};
} // namespace
TEST_CASE("apply_model materialises layout pins and sets specs where the model speaks") {
Part part("U1");
part.add(new Pin("VCC")); // already present; CLK and GND are not
FakeModel m;
ApplyReport r = apply_model(&part, m);
// CLK and GND materialised from layout(); VCC was already there.
CHECK(r.materialised == 2);
CHECK(part.exists("CLK"));
CHECK(part.exists("GND"));
CHECK(r.pins_total == 3);
// Specs set only where the model speaks (VCC, CLK), not GND.
CHECK(part.get("VCC")->spec.function == PinFunction::Power);
CHECK(part.get("VCC")->spec.source == SpecSource::Bsdl);
CHECK(part.get("CLK")->spec.function == PinFunction::Clock);
CHECK(part.get("GND")->spec.source == SpecSource::None);
CHECK(r.set == 2);
}
TEST_CASE("apply_model does not overwrite a spec the model is silent about") {
Part part("U2");
Pin *p = new Pin("DATA");
p->spec.function = PinFunction::Signal;
p->spec.source = SpecSource::Bsdl; // a prior model wrote this
part.add(p);
FakeModel m; // says nothing about DATA
apply_model(&part, m);
CHECK(part.get("DATA")->spec.function == PinFunction::Signal);
CHECK(part.get("DATA")->spec.source == SpecSource::Bsdl);
}