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>
This commit is contained in:
55
src/system/pin_model.hpp
Normal file
55
src/system/pin_model.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#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_
|
||||
Reference in New Issue
Block a user