Skip to content

✨ Foundation for Phase 0 Added - #98

Open
FeldmeierMichael wants to merge 15 commits into
mainfrom
phase-0-foundation-v2
Open

✨ Foundation for Phase 0 Added#98
FeldmeierMichael wants to merge 15 commits into
mainfrom
phase-0-foundation-v2

Conversation

@FeldmeierMichael

@FeldmeierMichael FeldmeierMichael commented Sep 3, 2026

Copy link
Copy Markdown

🤖 AI text below 🤖

Description

This pull request implements phase 0 of the FridgeCAD port: the repository structure and the data model, with no domain logic. It also brings in the architecture document, the data-model and pipeline documents, and the eight decision records that this code relies on.

  • Eight per-module CMake targets replace the flat mqt-scpd target. cmake/AddMQTScpdLibrary.cmake, adapted from MQT Core's AddMQTCoreLibrary.cmake, declares mqt-scpd-<module> with the alias MQT::Scpd<Module>, a FILE_SET HEADERS under include/mqt-scpd/<module>/, and an export header. A module without source files is an interface library until its first source file arrives. cmake/CompilerWarnings.cmake is adopted from MQT Core. The dependency direction of ARCHITECTURE.md is encoded in the module CMakeLists.txt files, and each module owns a test directory under test/<module>/.
  • FlatBuffers schemas in schemas/ define the data model: geometry, the design (ports, the two role enums, design rules, couplers, bridges), the run configuration with detection and start_component for phase 1, the six stage artifacts behind one Artifact root, and the DRC report. Each schema has its own namespace, mqt.scpd.flatbuffers.<schema>. The schemas hold what phases 0 and 1 read; later stages append their tables and fields when they arrive. Every field that the in-memory model holds by value is marked required, so the verifier rejects a buffer that omits it instead of unpacking it to a default.- Generated code is committed: one C++ header per schema under include/mqt-scpd/flatbuffers/ in the namespace mqt::scpd::flatbuffers::<schema>, and one Python subpackage per schema under python/mqt/scpd/flatbuffers/ with one module per type. Python code is generated for the schemas Python reads or writes itself; drc.json is read as JSON, so drc.fbs has no Python module. No .pyi stubs are committed; the modules keep their inline annotations.
  • nox -s schemas regenerates the committed code. It builds flatc from the FlatBuffers source that the C++ build fetches (MQT_SCPD_BUILD_FLATC, off by default and never part of a wheel build), so the generator and the runtime cannot disagree on their version. nox -s schemas -- --check fails on stale output.
  • CI gains a schemas job that runs this check as one of the required checks. cpp-linter now walks the repository instead of fetching the pull request diff, because GitHub refuses diffs above 20,000 lines. Codecov ignores the generated headers, and .gitignore covers the cmake_test_discovery_*.json files that gtest_discover_tests writes into the source tree.
  • Tests: 29 GoogleTests cover the generated data model: round trips through buffers, the enum values as the wire format, the artifact identifier, the configuration defaults, and verifier rejection of foreign, truncated and incomplete buffers, including an artifact without its producer. Eight Python tests cover the generated subpackages and the package import. The add placeholder from the repository template is removed.
  • Documentation: ARCHITECTURE.md and docs/design/data-model.md describe the module declaration, the schema files, the namespaces and the regeneration flow. The generated code is excluded from the Doxygen and autoapi builds.
    Two details are worth knowing:
  • flatc 25.12.19's Python generator has two defects: --gen-onefile omits the imports of object-API types from included schemas, and --no-python-gen-numpy places EndVector() inside the loop (fixed upstream in Fix indention level for --no-python-gen-numpy google/flatbuffers#9049 after the release). The session therefore generates one Python module per type and keeps numpy optional.
  • The generated code must stay byte-identical to the flatc output, which the CI job checks. The end-of-file-fixer and trailing-whitespace hooks therefore exclude the two generated directories; ruff, ty, typos and the license tool already skip them through their own configuration.
    Dependencies: flatbuffers from PyPI is a new runtime dependency (the runtime of the generated Python) and is also listed in the test group. FlatBuffers 25.12.19 is fetched through FetchContent for the header-only C++ runtime. The branch is based on main after ⬆️🐍 Adopt nanobind 3 split-mode wheels #96, so it builds with nanobind 3.
    Verified locally: cmake --preset release and ctest --preset release (29 tests, no compiler warnings), uvx nox -s tests-3.13, uvx nox -s lint, uvx nox -s stubs (no change), uvx nox -s schemas -- --check on a committed snapshot, and uvx nox -s docs.

@FeldmeierMichael FeldmeierMichael self-assigned this Sep 3, 2026
@FeldmeierMichael FeldmeierMichael added documentation Improvements or additions to documentation feature New feature or request python Python related changes labels Sep 3, 2026
@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

@FeldmeierMichael

FeldmeierMichael commented Sep 3, 2026

Copy link
Copy Markdown
Author

Had to change files-changed-only: true to files-changed-only: false in ci.yml as the PR also includes the docs for the rewriting plan -> files-changed-only: true crashes if more than 20000 lines changed. I will revert it back in the next PR

@marcelwa marcelwa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks for getting this started. It goes in the right direction, we just need to get a few high-level things out of the way before we focus more on the details. Expect a few review rounds and don't get discouraged 😉

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove all plans from this branch that are not directly related to the current phase.

"testsuite": [
{
"name": "PortDetectionDefaultsToManual",
"file": "\/Users\/michaelfeldmeier\/Documents\/GitHub\/scpd\/test\/design\/test_config_schema.cpp",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should never be file paths to your personal machine anywhere in a PR

Comment thread pyproject.toml Outdated
Comment on lines +230 to +231
ein = "ein"
als = "als"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be no need for German spelling anywhere in the repo

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's maybe rename the folder to flatbuffers and also drop the _generated postfix. That makes the point clearer and improves readability.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: let's rename the folder to flatbuffers.

Additionally, is there any way to group the generated Python files into submodules by association to give more meaning to an otherwise flat directory?

@marcelwa

marcelwa commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Currently, your PR description still carries a

Hier die aktualisierte PR-Beschreibung für den neuen Branch. Gegenüber der ersten Fassung ist der Abschnitt zu den Lint-Hooks neu, und die Verifikation nennt den Stand mit nanobind 3.

Titel: 🏗️ Implement phase 0: module targets, FlatBuffers schemas, schema check

that should be removed. Also, the manual line breaks in the PR description should be eliminated.

@marcelwa marcelwa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description still contains manual line breaks and outdated information like the referenced generated/ folder or the number of GoogleTests.

I noticed that the code uses British English spelling. I believe the rest of the MQT uses American English. Maybe @denialhaag could comment on whether there is a constraint to use one spelling over the other. Especially for coding symbols, that matters.

Comment thread CHANGELOG.md Outdated
Comment on lines +15 to +21
- 👷 Fail CI when the committed schema-generated code is stale ([#97])
([**@FeldmeierMichael**])
- ✨ Add the FlatBuffers schemas of the data model, the committed C++ and Python
code generated from them, and the `nox -s schemas` session ([#97])
([**@FeldmeierMichael**])
- 🏗️ Split the core into the eight per-module CMake targets of the architecture
([#97]) ([**@FeldmeierMichael**])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is PR #98, not #97

Comment thread schemas/geometry.fbs
Comment on lines +29 to +41
table Line {
start: Point (native_inline);
end: Point (native_inline);
}

/// A circular arc in layout space with an exact centre and radius. Angles are
/// radians; a positive sweep runs counter-clockwise.
table Arc {
centre: Point (native_inline);
radius: double;
start_angle: double;
sweep: double;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line.start and .end as well as Arc.centre are mandatory according to the model but optional on the wire.

Edit: also applies to

  • Connection.target
  • CpwCoupler.port and CpwCoupler.centre
  • Bridge.centre
  • probably DrcFinding.location

Comment thread schemas/artifacts.fbs Outdated
/// The root of every stage artifact.
table Artifact {
/// The mqt-scpd version that wrote the artifact, for provenance.
producer: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema says producer records the version that wrote the artifact, but the field is optional, and producers that are omitted pass verification. Please mark it required if it is required, and test that the verifier rejects an artifact without it.

If not, nothing to do here.

@denialhaag

Copy link
Copy Markdown
Member

I noticed that the code uses British English spelling. I believe the rest of the MQT uses American English. Maybe @denialhaag could comment on whether there is a constraint to use one spelling over the other. Especially for coding symbols, that matters.

Without a terribly deep reason, I would generally prefer to keep everything in American English. 🙂

@marcelwa marcelwa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI text below 🤖

Requesting changes for six data-model, serialization, and build-system issues. The blocking issues are the unpersisted coupler-created port and Python's ability to write artifacts that the C++ verifier rejects.

Comment thread schemas/design.fbs Outdated
/// Final stage at exact physical dimensions in layout units.
table CpwCoupler {
/// The ResonatorSource port the coupler carries.
port: PortRef (required, native_inline);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI text below 🤖

[P1] Persist the coupler-created port in a stage output. CpwCoupler.port is a PortRef into Chip.ports, but Final receives an immutable Chip and returns only FinalRouting. Neither FinalRouting nor the stored 00-chip.json contains the appended port or the updated connection whose source was absent during Assignment. The reference therefore cannot remain valid after reload, which breaks resume, plotting, and DRC. Please persist the new port and its connection mapping in the stage output, or return and store an updated chip.

def test_final_routing_keeps_scalar_vectors() -> None:
"""A vector of indices survives packing with zero, one and several elements."""
for unresolved in ([], [7], [2, 5, 11]):
artifact = ArtifactT(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI text below 🤖

[P1] Do not treat this artifact as valid without producer. The generated Python End methods do not call Builder.Required, and the Python FlatBuffers runtime has no structural verifier. With FlatBuffers 25.12.19, I reproduced a 16-byte artifact with producer=None and output=None that Python writes and reads successfully, while C++ VerifyArtifactBuffer rejects it. Because Python is expected to write the stage artifacts, add a checked, non-generated serialization and read layer, make missing required fields fail, and include producer in valid round-trip tests.

Comment thread schemas/design.fbs
/// carries the ResonatorSource role.
source: PortRef;
target: PortRef (required, native_inline);
source_role: AssignedRole;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI text below 🤖

[P2] Distinguish missing roles from FeedlineSource. FlatBuffers scalar fields are not required here: when either role is absent, the generated accessor returns enum value 0 and the verifier still succeeds. I reproduced a serialized connection with both role offsets absent that decoded as (FeedlineSource, FeedlineSource). The same silent-default problem affects Port.role, Wire.connection, dimensions, and design-rule values. Please use invalid enum sentinels or optional scalars where absence matters, and add semantic validation after structural verification.

Comment thread schemas/drc.fbs Outdated
feedlines_skipped: uint32;
}

root_type DrcReport;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI text below 🤖

[P2] Add a root that can represent the complete drc.json. DrcReport contains one stage, and this declaration makes one report the JSON root, while the pipeline contract says the Final and Finalize reports both go into the same file. A top-level JSON array around two reports would no longer conform to this root schema. Please add a container with a vector of reports, or redesign the root around per-stage groups.

Comment thread src/CMakeLists.txt
target_link_libraries(${PROJECT_NAME} PRIVATE MQT::ProjectOptions)

# add MQT alias
add_library(MQT::SCPD ALIAS ${PROJECT_NAME})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI text below 🤖

[P2] Preserve or document the removal of the public MQT::SCPD target. Existing downstream CMake consumers that link this alias stop configuring after this change. The changelog currently lists only additions, and UPGRADING.md has no migration entry. Please keep a compatibility umbrella target that links the appropriate module, or record the breaking change and its replacement targets in both places.

Comment thread cmake/AddMQTScpdLibrary.cmake Outdated
set(alias MQT::Scpd${ARG_ALIAS_NAME})

# collect headers and source files
file(GLOB_RECURSE headers ${MQT_SCPD_INCLUDE_BUILD_DIR}/mqt-scpd/${module}/*.hpp)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI text below 🤖

[P2] Make additions to these globs trigger CMake regeneration. Without CONFIGURE_DEPENDS, adding the first .cpp to a module does not cause an existing build tree to reconfigure, so the target remains an interface library and the new implementation is not compiled. The per-module test globs have the same problem. Please list sources explicitly or use CONFIGURE_DEPENDS for both source and test discovery.

Comment thread .gitignore Outdated
Comment on lines +142 to +143
# CMake writes these into the working directory of gtest_discover_tests
cmake_test_discovery_*.json

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With #103, SCPD is now using a templated .gitignore. When resolving the merge conflict, you can just pick the version on main. 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation feature New feature or request python Python related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants