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>
56 lines
2.0 KiB
C++
56 lines
2.0 KiB
C++
#ifndef _PIN_MODEL_HPP_
|
|
#define _PIN_MODEL_HPP_
|
|
|
|
#include "pin_spec.hpp"
|
|
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
class Part;
|
|
|
|
// A source of *expected* pin attributes for a part — a connector layout, a BSDL
|
|
// device, (later) a SPICE/Modelica model. Both of today's sources implement this
|
|
// interface and feed the single `apply_model()`, so `verify` stays agnostic of
|
|
// where a pin's spec came from.
|
|
struct PinModel {
|
|
virtual ~PinModel() = default;
|
|
|
|
// Expected spec for the pin identified by `pin_name` — its logical name, and
|
|
// for models that index physical pads, its package ball too. Returns a
|
|
// default PinSpec (source == None) when the model has nothing to say.
|
|
virtual PinSpec spec_for(const std::string &pin_name) const = 0;
|
|
|
|
// Canonical full pin-name list, used to materialise pins absent from the
|
|
// imported netlist. Empty means the model does not drive materialisation.
|
|
virtual std::vector<std::string> layout() const = 0;
|
|
|
|
// Which source this model represents (recorded in each spec it sets).
|
|
virtual SpecSource source() const = 0;
|
|
};
|
|
|
|
struct ApplyReport {
|
|
int pins_total = 0; ///< pins on the part after materialisation
|
|
int set = 0; ///< pins whose spec the model set
|
|
int materialised = 0; ///< pins created from layout()
|
|
};
|
|
|
|
// Materialise the layout pins missing from the part, then set each pin's `spec`
|
|
// from the model — only where the model actually speaks for that pin
|
|
// (`spec.source != None`), so a model never wipes another source's spec.
|
|
ApplyReport apply_model(Part *part, const PinModel &model);
|
|
|
|
// Connector-layout model: wraps `pin_role(kind, name)` / `pin_layout(kind)`.
|
|
class ConnectorModel : public PinModel {
|
|
public:
|
|
explicit ConnectorModel(std::string kind) : kind_(std::move(kind)) {}
|
|
PinSpec spec_for(const std::string &pin_name) const override;
|
|
std::vector<std::string> layout() const override;
|
|
SpecSource source() const override { return SpecSource::ConnectorModel; }
|
|
|
|
private:
|
|
std::string kind_;
|
|
};
|
|
|
|
#endif // _PIN_MODEL_HPP_
|