From ac51de33647f021f9595261dfb72b75a0499515d Mon Sep 17 00:00:00 2001 From: Matthew Ballance Date: Sun, 22 Feb 2026 01:55:59 +0000 Subject: [PATCH 1/2] Restructure documentation: task-oriented layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the flat, API-centric doc structure with a user-first, task-oriented layout organized around what users actually do: New top-level sections - getting-started/ installation + 5-minute quickstart (CLI-first) - importing/ Verilator, cocotb-coverage, AVL — each in its own page - working-with-coverage/ merge, TUI explorer, show commands, compare - reporting/ HTML report and CI/CD format export - cicd/ GitHub Actions, GitLab CI, Jenkins — copy-pasteable - ai-integration/ MCP server (framed around what you can ask, not tool list) - reference/ Developer content separated from user content - python-api/ Full OO API: 25 classes/enums, all autodoc'd - formats/ XML, YAML, SQLite schema specs - report-formats/ HTML and JSON report format specs conf.py changes - Add sphinx.ext.napoleon so Google-style docstrings parse correctly - Add sphinx_design for tab-set directives in quickstart Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- doc/source/ai-integration/mcp-server.rst | 100 ++ doc/source/cicd/github-actions.rst | 84 ++ doc/source/cicd/gitlab-ci.rst | 63 + doc/source/cicd/index.rst | 20 + doc/source/cicd/jenkins.rst | 89 ++ doc/source/conf.py | 2 + doc/source/getting-started/index.rst | 13 + doc/source/getting-started/installation.rst | 39 + doc/source/getting-started/quickstart.rst | 81 ++ doc/source/importing/avl.rst | 49 + doc/source/importing/cocotb.rst | 60 + doc/source/importing/index.rst | 65 + doc/source/importing/verilator.rst | 51 + doc/source/index.rst | 93 +- doc/source/reference/best-practices.rst | 25 + doc/source/reference/cli.rst | 16 + doc/source/reference/formats/index.rst | 12 + .../reference/formats/sqlite-schema.rst | 1252 +++++++++++++++++ .../reference/formats/xml-interchange.rst | 455 ++++++ doc/source/reference/formats/yaml-format.rst | 49 + doc/source/reference/index.rst | 39 + doc/source/reference/native-c-library.rst | 782 ++++++++++ .../reference/python-api/c-style-api.rst | 10 + doc/source/reference/python-api/index.rst | 15 + doc/source/reference/python-api/oo-api.rst | 372 +++++ .../report-formats/html-report-format.rst | 578 ++++++++ doc/source/reference/report-formats/index.rst | 10 + .../report-formats/json-report-format.rst | 71 + doc/source/reference/sqlite-api.rst | 846 +++++++++++ doc/source/reporting/exporting.rst | 63 + doc/source/reporting/html-report.rst | 64 + doc/source/reporting/index.rst | 15 + .../working-with-coverage/analyzing.rst | 130 ++ .../working-with-coverage/comparing.rst | 53 + .../working-with-coverage/exploring-tui.rst | 93 ++ doc/source/working-with-coverage/index.rst | 18 + doc/source/working-with-coverage/merging.rst | 71 + 37 files changed, 5820 insertions(+), 28 deletions(-) create mode 100644 doc/source/ai-integration/mcp-server.rst create mode 100644 doc/source/cicd/github-actions.rst create mode 100644 doc/source/cicd/gitlab-ci.rst create mode 100644 doc/source/cicd/index.rst create mode 100644 doc/source/cicd/jenkins.rst create mode 100644 doc/source/getting-started/index.rst create mode 100644 doc/source/getting-started/installation.rst create mode 100644 doc/source/getting-started/quickstart.rst create mode 100644 doc/source/importing/avl.rst create mode 100644 doc/source/importing/cocotb.rst create mode 100644 doc/source/importing/index.rst create mode 100644 doc/source/importing/verilator.rst create mode 100644 doc/source/reference/best-practices.rst create mode 100644 doc/source/reference/cli.rst create mode 100644 doc/source/reference/formats/index.rst create mode 100644 doc/source/reference/formats/sqlite-schema.rst create mode 100644 doc/source/reference/formats/xml-interchange.rst create mode 100644 doc/source/reference/formats/yaml-format.rst create mode 100644 doc/source/reference/index.rst create mode 100644 doc/source/reference/native-c-library.rst create mode 100644 doc/source/reference/python-api/c-style-api.rst create mode 100644 doc/source/reference/python-api/index.rst create mode 100644 doc/source/reference/python-api/oo-api.rst create mode 100644 doc/source/reference/report-formats/html-report-format.rst create mode 100644 doc/source/reference/report-formats/index.rst create mode 100644 doc/source/reference/report-formats/json-report-format.rst create mode 100644 doc/source/reference/sqlite-api.rst create mode 100644 doc/source/reporting/exporting.rst create mode 100644 doc/source/reporting/html-report.rst create mode 100644 doc/source/reporting/index.rst create mode 100644 doc/source/working-with-coverage/analyzing.rst create mode 100644 doc/source/working-with-coverage/comparing.rst create mode 100644 doc/source/working-with-coverage/exploring-tui.rst create mode 100644 doc/source/working-with-coverage/index.rst create mode 100644 doc/source/working-with-coverage/merging.rst diff --git a/doc/source/ai-integration/mcp-server.rst b/doc/source/ai-integration/mcp-server.rst new file mode 100644 index 0000000..0864095 --- /dev/null +++ b/doc/source/ai-integration/mcp-server.rst @@ -0,0 +1,100 @@ +########## +MCP Server +########## + +The PyUCIS MCP server lets AI assistants (such as Claude) query your coverage +databases using natural language. Instead of memorizing command syntax, you +can ask questions like: + +* *"What is the overall coverage of my regression?"* +* *"Which covergroups have the lowest coverage?"* +* *"Show me all bins that were never hit."* +* *"Compare today's run to yesterday's baseline and report any regressions."* +* *"Export coverage as LCOV and tell me what genhtml command to run."* + +The server uses the `Model Context Protocol (MCP) `_, +a standard interface for connecting AI tools to external data sources. + +Installation +============ + +.. code-block:: bash + + pip install pyucis[dev] + +This installs the ``pyucis-mcp-server`` command and its dependencies. + +Configuring Claude Desktop +========================== + +1. Find your Claude Desktop config file: + + * **macOS**: ``~/Library/Application Support/Claude/claude_desktop_config.json`` + * **Linux**: ``~/.config/Claude/claude_desktop_config.json`` + * **Windows**: ``%APPDATA%\Claude\claude_desktop_config.json`` + +2. Add the PyUCIS server entry: + + .. code-block:: json + + { + "mcpServers": { + "pyucis": { + "command": "pyucis-mcp-server" + } + } + } + +3. Restart Claude Desktop. + +The PyUCIS tools are now available in your conversations. + +Example Session +=============== + +Once connected, open a coverage database by telling Claude the file path, then ask +questions in plain English: + +.. code-block:: text + + You: Open /path/to/regression.xml and give me a coverage summary. + + Claude: The database has 78.4% overall coverage across 142 covergroups. + Functional coverage is 81.2%; code coverage is 74.6%. + There are 23 covergroups below 50%. + + You: Which covergroups have zero coverage? + + Claude: The following 8 covergroups have 0% coverage: ... + + You: Compare this to /path/to/baseline.xml and report regressions. + + Claude: Compared to baseline, 3 items regressed: ... + +Available Operations +==================== + +The MCP server provides tools for: + +* Opening, listing, and closing databases +* Coverage summary, gaps, and metrics +* Covergroup, coverpoint, and bin details +* Design hierarchy navigation +* Test execution history +* Database comparison (regression detection) +* Hotspot analysis +* Code coverage export (LCOV, Cobertura, JaCoCo, Clover) +* Assertion and toggle coverage + +Starting the Server Manually +============================ + +The server communicates via stdin/stdout and is normally started by the MCP +client automatically. To start it manually for testing: + +.. code-block:: bash + + pyucis-mcp-server + +See the `MCP specification `_ for client +integration details beyond Claude Desktop. diff --git a/doc/source/cicd/github-actions.rst b/doc/source/cicd/github-actions.rst new file mode 100644 index 0000000..531d585 --- /dev/null +++ b/doc/source/cicd/github-actions.rst @@ -0,0 +1,84 @@ +############## +GitHub Actions +############## + +The examples below show a complete coverage workflow for GitHub Actions: run tests, +merge coverage, export to Codecov, publish an HTML report artifact, and gate the +build on a minimum coverage threshold. + +Full Workflow Example +===================== + +.. code-block:: yaml + + name: Coverage + + on: + push: + branches: [main] + pull_request: + + jobs: + coverage: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install PyUCIS + run: pip install pyucis + + - name: Run tests + run: make run_all_tests # produces test_*.xml or test_*.dat + + - name: Merge coverage + run: ucis merge -o merged.xml test_*.xml + + - name: Check coverage threshold + run: | + COV=$(ucis show summary merged.xml -of json | jq -r '.overall_coverage') + echo "Coverage: ${COV}%" + python -c "import sys; sys.exit(0 if float('$COV') >= 80 else 1)" \ + || (echo "Coverage below 80%" && exit 1) + + - name: Export LCOV for Codecov + run: ucis show code-coverage merged.xml --output-format lcov > coverage.info + + - name: Upload to Codecov + uses: codecov/codecov-action@v4 + with: + files: ./coverage.info + + - name: Generate HTML report + run: ucis report merged.xml -of html -o coverage_report.html + + - name: Upload HTML report artifact + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: coverage_report.html + +Verilator Projects +================== + +Replace the merge step if your tests produce ``.dat`` files: + +.. code-block:: yaml + + - name: Merge Verilator coverage + run: ucis merge --input-format vltcov -o merged.xml tests/*/coverage.dat + +Cobertura Upload +================ + +If you prefer Cobertura (e.g. for GitHub code coverage annotations via a +third-party action): + +.. code-block:: yaml + + - name: Export Cobertura + run: ucis show code-coverage merged.xml --output-format cobertura > coverage.xml diff --git a/doc/source/cicd/gitlab-ci.rst b/doc/source/cicd/gitlab-ci.rst new file mode 100644 index 0000000..a6dd59f --- /dev/null +++ b/doc/source/cicd/gitlab-ci.rst @@ -0,0 +1,63 @@ +########## +GitLab CI +########## + +The example below shows a complete coverage workflow for GitLab CI: merge +coverage, export Cobertura for the GitLab coverage visualization, and publish +an HTML report as a job artifact. + +Full Workflow Example +===================== + +.. code-block:: yaml + + stages: + - test + - coverage + + run_tests: + stage: test + script: + - make run_all_tests # produces test_*.xml + artifacts: + paths: + - test_*.xml + + coverage: + stage: coverage + script: + - pip install pyucis + + # Merge + - ucis merge -o merged.xml test_*.xml + + # Coverage gate + - | + COV=$(ucis show summary merged.xml -of json | jq -r '.overall_coverage') + echo "Coverage: ${COV}%" + python3 -c "import sys; sys.exit(0 if float('$COV') >= 80 else 1)" \ + || (echo "Coverage below 80%" && exit 1) + + # Export Cobertura for GitLab coverage widget + - ucis show code-coverage merged.xml --output-format cobertura > coverage.xml + + # Generate shareable HTML report + - ucis report merged.xml -of html -o coverage_report.html + + coverage: '/Coverage:\s+(\d+\.\d+)%/' + + artifacts: + reports: + coverage_report: + coverage_format: cobertura + path: coverage.xml + paths: + - coverage_report.html + expire_in: 1 week + +Verilator Projects +================== + +.. code-block:: yaml + + - ucis merge --input-format vltcov -o merged.xml tests/*/coverage.dat diff --git a/doc/source/cicd/index.rst b/doc/source/cicd/index.rst new file mode 100644 index 0000000..652b434 --- /dev/null +++ b/doc/source/cicd/index.rst @@ -0,0 +1,20 @@ +################ +CI/CD Integration +################ + +PyUCIS integrates cleanly into continuous integration pipelines. The typical +pattern is: + +1. Run tests — each test produces a coverage file +2. Merge coverage files into a single database +3. Export to the format your CI tool expects +4. Optionally gate the build on a coverage threshold + +.. toctree:: + :maxdepth: 1 + + github-actions + gitlab-ci + jenkins + +For the available export formats see :doc:`../reporting/exporting`. diff --git a/doc/source/cicd/jenkins.rst b/doc/source/cicd/jenkins.rst new file mode 100644 index 0000000..54e979d --- /dev/null +++ b/doc/source/cicd/jenkins.rst @@ -0,0 +1,89 @@ +####### +Jenkins +####### + +The declarative pipeline below merges coverage, publishes a Cobertura report +via the Jenkins Cobertura plugin, and generates an HTML report artifact. + +Prerequisites +============= + +Install the `Cobertura Plugin `_ +(or `JaCoCo Plugin `_) in Jenkins. + +Full Pipeline Example +===================== + +.. code-block:: groovy + + pipeline { + agent any + + stages { + stage('Test') { + steps { + sh 'make run_all_tests' // produces test_*.xml + } + } + + stage('Coverage') { + steps { + sh 'pip install pyucis' + + // Merge all test coverage files + sh 'ucis merge -o merged.xml test_*.xml' + + // Coverage gate + sh ''' + COV=$(ucis show summary merged.xml -of json | jq -r '.overall_coverage') + echo "Coverage: ${COV}%" + python3 -c "import sys; sys.exit(0 if float('$COV') >= 80 else 1)" \ + || { echo "Coverage below 80%"; exit 1; } + ''' + + // Export Cobertura for Jenkins plugin + sh 'ucis show code-coverage merged.xml --output-format cobertura > coverage.xml' + + // Export JaCoCo (alternative) + // sh 'ucis show code-coverage merged.xml --output-format jacoco > jacoco.xml' + + // Generate HTML report + sh 'ucis report merged.xml -of html -o coverage_report.html' + } + + post { + always { + // Publish Cobertura coverage + cobertura coberturaReportFile: 'coverage.xml', + failUnhealthy: false, + failUnstable: false + + // Archive HTML report + archiveArtifacts artifacts: 'coverage_report.html' + } + } + } + } + } + +JaCoCo Variant +============== + +Replace the Cobertura steps with: + +.. code-block:: groovy + + sh 'ucis show code-coverage merged.xml --output-format jacoco > jacoco.xml' + + post { + always { + jacoco execPattern: 'jacoco.xml' + } + } + +Verilator Projects +================== + +.. code-block:: groovy + + sh 'ucis merge --input-format vltcov -o merged.xml tests/*/coverage.dat' diff --git a/doc/source/conf.py b/doc/source/conf.py index 02fd0b9..4c0c8c8 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -39,6 +39,7 @@ # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', 'sphinx.ext.intersphinx', 'sphinxcontrib.makedomain', 'sphinx.ext.autosectionlabel', @@ -46,6 +47,7 @@ 'sphinx-jsonschema', 'sphinx_issues', 'sphinxarg.ext', + 'sphinx_design', ] intersphinx_mapping = { diff --git a/doc/source/getting-started/index.rst b/doc/source/getting-started/index.rst new file mode 100644 index 0000000..db76c4f --- /dev/null +++ b/doc/source/getting-started/index.rst @@ -0,0 +1,13 @@ +############### +Getting Started +############### + +PyUCIS is a Python toolkit for working with functional verification coverage data. +It reads coverage output from simulators and verification frameworks, stores it in +a unified format, and provides tools to explore, merge, report, and export that data. + +.. toctree:: + :maxdepth: 1 + + installation + quickstart diff --git a/doc/source/getting-started/installation.rst b/doc/source/getting-started/installation.rst new file mode 100644 index 0000000..3cf4a89 --- /dev/null +++ b/doc/source/getting-started/installation.rst @@ -0,0 +1,39 @@ +############ +Installation +############ + +Requirements +============ + +* Python 3.8 or later +* Linux, macOS, or Windows + +Basic Install +============= + +.. code-block:: bash + + pip install pyucis + +This installs the ``ucis`` command-line tool and all core library functionality. + +With MCP Server Support +======================= + +To enable the :doc:`../ai-integration/mcp-server` for AI assistant integration: + +.. code-block:: bash + + pip install pyucis[dev] + +This adds the ``pyucis-mcp-server`` command and its dependencies +(``mcp``, ``lxml``, ``pyyaml``, ``jsonschema``). + +Verify the Install +================== + +.. code-block:: bash + + ucis --help + +You should see the list of available sub-commands. diff --git a/doc/source/getting-started/quickstart.rst b/doc/source/getting-started/quickstart.rst new file mode 100644 index 0000000..a6ffc4a --- /dev/null +++ b/doc/source/getting-started/quickstart.rst @@ -0,0 +1,81 @@ +########## +Quickstart +########## + +This page walks through the most common workflow: import a coverage file from your +simulator, explore it interactively, then generate a shareable HTML report. + +Step 1 — Import +=============== + +Convert your simulator's native coverage output to UCIS XML: + +.. tab-set:: + + .. tab-item:: Verilator + + .. code-block:: bash + + ucis convert --input-format vltcov coverage.dat -o coverage.xml + + .. tab-item:: cocotb-coverage + + .. code-block:: bash + + ucis convert --input-format cocotb-xml coverage.xml -o coverage_ucis.xml + # or for YAML output from cocotb-coverage: + ucis convert --input-format cocotb-yaml coverage.yml -o coverage_ucis.xml + + .. tab-item:: AVL + + .. code-block:: bash + + ucis convert --input-format avl-json coverage.json -o coverage.xml + +See :doc:`../importing/index` for more detail on each source. + +Step 2 — Explore Interactively +=============================== + +The interactive terminal UI lets you browse coverage without generating a report file: + +.. code-block:: bash + + ucis view coverage.xml + +Inside the TUI: + +* Press **1** for a Dashboard overview +* Press **3** to see uncovered items (Gaps) +* Press **4** for prioritized recommendations (Hotspots) +* Press **q** to quit + +See :doc:`../working-with-coverage/exploring-tui` for the full TUI guide. + +Step 3 — Generate a Shareable Report +===================================== + +.. code-block:: bash + + ucis report coverage.xml -of html -o report.html + +Open ``report.html`` in any browser — it is a single self-contained file that can +be emailed, archived, or hosted on a web server without any extra dependencies. + +Step 4 — Merge Multiple Runs (optional) +======================================== + +If you have coverage from several test runs, merge them before reporting: + +.. code-block:: bash + + ucis merge -o merged.xml test1.xml test2.xml test3.xml + ucis report merged.xml -of html -o merged_report.html + +Next Steps +========== + +* :doc:`../importing/index` — more on importing from different sources +* :doc:`../working-with-coverage/analyzing` — analyze gaps and hotspots from the CLI +* :doc:`../reporting/exporting` — export to LCOV, Cobertura, or JaCoCo for CI/CD tools +* :doc:`../cicd/index` — ready-to-use CI/CD pipeline examples diff --git a/doc/source/importing/avl.rst b/doc/source/importing/avl.rst new file mode 100644 index 0000000..25b50e6 --- /dev/null +++ b/doc/source/importing/avl.rst @@ -0,0 +1,49 @@ +################################## +Importing AVL Coverage Data +################################## + +`AVL (Apheleia Verification Library) `_ +exports functional coverage as JSON. PyUCIS automatically detects which of the +three AVL JSON variants is present (hierarchical, DataFrame records, DataFrame table). + +Basic Import +============ + +.. code-block:: bash + + ucis convert --input-format avl-json coverage.json -o coverage.xml + +Merging Multiple Runs +===================== + +.. code-block:: bash + + ucis merge --input-format avl-json \ + run1.json run2.json run3.json -o merged.xml + +Exporting Coverage from AVL +============================ + +In your AVL testbench: + +.. code-block:: python + + # Hierarchical format (recommended) + cg.export_json("coverage.json") + + # DataFrame format (also supported) + cg.export_dataframe("coverage_df.json") + +Coverage Types Supported +======================== + +* Covergroups and coverpoints +* Bins with hit counts +* Cross coverage + +Next Steps +========== + +* :doc:`../working-with-coverage/merging` — combine runs +* :doc:`../working-with-coverage/analyzing` — analyze from the CLI +* :doc:`../reporting/html-report` — HTML report diff --git a/doc/source/importing/cocotb.rst b/doc/source/importing/cocotb.rst new file mode 100644 index 0000000..c3b8baa --- /dev/null +++ b/doc/source/importing/cocotb.rst @@ -0,0 +1,60 @@ +################################ +Importing cocotb-coverage Data +################################ + +`cocotb-coverage `_ can export +functional coverage in XML or YAML format. PyUCIS imports both, producing an +identical UCIS database from either. + +Basic Import +============ + +.. tab-set:: + + .. tab-item:: XML + + .. code-block:: bash + + ucis convert --input-format cocotb-xml coverage.xml -o coverage_ucis.xml + + .. tab-item:: YAML + + .. code-block:: bash + + ucis convert --input-format cocotb-yaml coverage.yml -o coverage_ucis.xml + +Merging Multiple Runs +===================== + +.. code-block:: bash + + ucis merge --input-format cocotb-xml \ + run1.xml run2.xml run3.xml -o merged.xml + +Exporting Coverage from cocotb-coverage +======================================== + +In your cocotb testbench, after sampling: + +.. code-block:: python + + from cocotb_coverage.coverage import coverage_db + + # Export at end of test + coverage_db.export_to_xml("coverage.xml") + # or + coverage_db.export_to_yaml("coverage.yml") + +Coverage Types Supported +======================== + +* Covergroups and coverpoints +* Cross coverage +* Bins with hit counts and ``at_least`` thresholds + +Next Steps +========== + +* :doc:`../working-with-coverage/merging` — combine runs +* :doc:`../working-with-coverage/analyzing` — analyze from the CLI +* :doc:`../reporting/html-report` — HTML report diff --git a/doc/source/importing/index.rst b/doc/source/importing/index.rst new file mode 100644 index 0000000..535d389 --- /dev/null +++ b/doc/source/importing/index.rst @@ -0,0 +1,65 @@ +################## +Importing Coverage +################## + +PyUCIS reads coverage from several simulator and verification framework formats and +converts them all into the same UCIS internal model. Once imported, every tool in +PyUCIS works identically regardless of the original source. + +Supported Sources +================= + +.. list-table:: + :header-rows: 1 + :widths: 30 25 25 20 + + * - Source + - ``--input-format`` + - File extension + - Guide + * - Verilator + - ``vltcov`` + - ``.dat`` + - :doc:`verilator` + * - cocotb-coverage (XML) + - ``cocotb-xml`` + - ``.xml``, ``.cov`` + - :doc:`cocotb` + * - cocotb-coverage (YAML) + - ``cocotb-yaml`` + - ``.yml``, ``.yaml`` + - :doc:`cocotb` + * - AVL (JSON) + - ``avl-json`` + - ``.json`` + - :doc:`avl` + * - UCIS XML + - ``xml`` *(default)* + - ``.xml`` + - — + * - UCIS YAML + - ``yaml`` + - ``.yaml`` + - — + +Automatic Format Detection +========================== + +When working in Python you can let PyUCIS detect the format automatically: + +.. code-block:: python + + from ucis.format_detection import read_coverage_file + + db = read_coverage_file('coverage.xml') # cocotb XML, UCIS XML, or AVL — auto-detected + db = read_coverage_file('coverage.yml') # cocotb YAML or UCIS YAML + db = read_coverage_file('coverage.json') # AVL JSON + +From the command line always specify ``--input-format`` to be explicit. + +.. toctree:: + :maxdepth: 1 + + verilator + cocotb + avl diff --git a/doc/source/importing/verilator.rst b/doc/source/importing/verilator.rst new file mode 100644 index 0000000..82d38aa --- /dev/null +++ b/doc/source/importing/verilator.rst @@ -0,0 +1,51 @@ +########################## +Importing Verilator Coverage +########################## + +Verilator writes coverage data in the **SystemC::Coverage-3** text format +(usually ``coverage.dat``). PyUCIS imports both functional coverage +(covergroups, coverpoints, bins) and code coverage (line, branch, toggle). + +Basic Import +============ + +.. code-block:: bash + + ucis convert --input-format vltcov coverage.dat -o coverage.xml + +To convert directly to an SQLite database (faster for large files): + +.. code-block:: bash + + ucis convert --input-format vltcov --output-format sqlite \ + coverage.dat -o coverage.ucisdb + +Merging Multiple Runs +===================== + +.. code-block:: bash + + ucis merge --input-format vltcov \ + test1/coverage.dat test2/coverage.dat test3/coverage.dat \ + -o merged.xml + +Generating Verilator Coverage +============================== + +Enable coverage when compiling and running your simulation: + +.. code-block:: bash + + # Compile with coverage instrumentation + verilator --coverage --coverage-func --coverage-line -cc design.v + + # Run (generates coverage.dat in the working directory) + make -C obj_dir -f Vdesign.mk + ./obj_dir/Vdesign + +Next Steps +========== + +* :doc:`../working-with-coverage/merging` — combine runs into a single database +* :doc:`../working-with-coverage/exploring-tui` — explore coverage interactively +* :doc:`../reporting/html-report` — generate an HTML report diff --git a/doc/source/index.rst b/doc/source/index.rst index f30dfbd..82a3683 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,35 +1,72 @@ -PyUCIS Documentation -==================== +PyUCIS +====== -PyUCIS is a Python implementation of the Unified Coverage Interoperability Standard (UCIS) for storing, manipulating, and reporting functional verification coverage data. +PyUCIS is a Python toolkit for **importing, merging, analyzing, and reporting +functional verification coverage data** in the +`Unified Coverage Interoperability Standard (UCIS) `_ +format. It works with coverage from Verilator, cocotb-coverage, AVL, and UCIS XML files, +and provides a command-line interface, an interactive terminal UI, HTML reports, and +CI/CD format export. -**Key Features:** +.. rubric:: Where do you want to start? -* **Multiple Backend Support** - In-memory, SQLite, XML, and YAML backends -* **SQLite Backend** - Persistent, queryable storage with SQL access -* **Native C Library** - High-performance UCIS 1.0 C API with SQLite backend -* **Full UCIS API** - Complete implementation of the UCIS object-oriented API -* **Coverage Import** - Import from Verilator, cocotb-coverage, and AVL frameworks -* **Coverage Reporting** - Interactive HTML, JSON, XML, Cobertura, and text report formats -* **Interactive HTML Reports** - Single-file reports with visualizations, bin details, and filtering -* **Interactive Terminal UI** - Real-time coverage exploration with keyboard-driven navigation -* **Coverage Merging** - Combine coverage from multiple test runs -* **Cross-Platform** - Works on Linux, macOS, and Windows +.. list-table:: + :widths: 40 60 -Contents: + * - :doc:`getting-started/quickstart` + - I have a coverage file and want to view or report it in 5 minutes + * - :doc:`importing/index` + - I need to import coverage from Verilator, cocotb, or AVL + * - :doc:`cicd/index` + - I want to integrate coverage into a CI/CD pipeline + * - :doc:`reference/index` + - I'm writing Python code against the PyUCIS API .. toctree:: :maxdepth: 2 - - introduction - commands - tui - show_commands - verilator_coverage_import - cocotb_avl_coverage_import - mcp_server - reference/reference - - -Indices and tables -================== + :hidden: + :caption: Getting Started + + getting-started/index + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Importing Coverage + + importing/index + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Working with Coverage + + working-with-coverage/index + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Reporting + + reporting/index + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: CI/CD Integration + + cicd/index + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: AI Integration + + ai-integration/mcp-server + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Reference + + reference/index diff --git a/doc/source/reference/best-practices.rst b/doc/source/reference/best-practices.rst new file mode 100644 index 0000000..551c100 --- /dev/null +++ b/doc/source/reference/best-practices.rst @@ -0,0 +1,25 @@ +##################################### +Best Practices for Recording Coverage +##################################### + +This section offers some suggestions on best practices for recording +coverage using the UCIS API. + +Naming Cross Bins +================= +Most of the recorded cross bins will pertain to auto-cross bins +between the coverpoints. Bins have arbirary names, but downstream +tools (expecially the XML interchange format export) depend on +being able to determine the relationship between a cross bin +and its associated coverpoint bins. + +The suggested name format for a cross bin is: + +.. code:: + + <{cp[0].bin},{cp[1].bin},...> + +In other words, if the first bin of the first coverpoint is named 'a' +and the first bin of the second coverpoint is named 'b', the cross +bin for these two bins will be named: + diff --git a/doc/source/reference/cli.rst b/doc/source/reference/cli.rst new file mode 100644 index 0000000..d22e3b5 --- /dev/null +++ b/doc/source/reference/cli.rst @@ -0,0 +1,16 @@ +#################### +CLI Command Reference +#################### + +Complete reference for all ``ucis`` sub-commands and options. + +.. argparse:: + :module: ucis.__main__ + :func: get_parser + :prog: ucis + +For workflow-oriented usage see the user guides: + +* :doc:`../working-with-coverage/analyzing` — ``show`` commands workflow +* :doc:`../working-with-coverage/merging` — ``merge`` options +* :doc:`../reporting/exporting` — ``show code-coverage`` export formats diff --git a/doc/source/reference/formats/index.rst b/doc/source/reference/formats/index.rst new file mode 100644 index 0000000..518a80c --- /dev/null +++ b/doc/source/reference/formats/index.rst @@ -0,0 +1,12 @@ +################ +File Formats +################ + +Technical specifications for the file formats read and written by PyUCIS. + +.. toctree:: + :maxdepth: 1 + + xml-interchange + yaml-format + sqlite-schema diff --git a/doc/source/reference/formats/sqlite-schema.rst b/doc/source/reference/formats/sqlite-schema.rst new file mode 100644 index 0000000..a2fd288 --- /dev/null +++ b/doc/source/reference/formats/sqlite-schema.rst @@ -0,0 +1,1252 @@ +############################ +SQLite Schema Reference +############################ + +This document provides a detailed reference of the SQLite database schema used by the SQLite backend. The schema is designed to efficiently represent all UCIS (Unified Coverage Interoperability Standard) concepts with full relational integrity. + +***************** +Design Principles +***************** + +The schema is designed with the following priorities: + +1. **Efficient Merging** - Support for combining coverage data from multiple test runs +2. **Fast Querying** - Indexed access patterns for common operations +3. **API Compatibility** - Enable C API semantics through Python +4. **Relational Integrity** - Proper foreign key relationships with cascading deletes +5. **Storage Efficiency** - Normalized design with selective denormalization + +Hierarchical Organization +========================== + +UCIS organizes coverage data hierarchically: + +* **Scopes** - Hierarchical containers (design units, instances, covergroups, etc.) +* **Coveritems** - Leaf nodes containing coverage counts +* **History Nodes** - Test records that produced coverage data + +Object Identification +===================== + +Objects can be identified by: + +* **Hierarchical names** - Path-based identification (e.g., ``/top/module/signal``) +* **Unique IDs** - Type + name components for universal object recognition +* **Primary keys** - Integer IDs for efficient database operations + +********************* +Schema Initialization +********************* + +Database Pragmas +================ + +.. code-block:: sql + + -- Enable foreign key constraints + PRAGMA foreign_keys = ON; + + -- Use Write-Ahead Logging for better concurrency + PRAGMA journal_mode = WAL; + + -- Optimize for modern systems + PRAGMA page_size = 4096; + PRAGMA cache_size = -64000; -- 64MB cache + +Metadata Initialization +======================= + +.. code-block:: sql + + INSERT INTO db_metadata (key, value) VALUES + ('UCIS_VERSION', '1.0'), + ('API_VERSION', '1.0'), + ('PATH_SEPARATOR', '/'), + ('CREATED_TIME', datetime('now')); + +***************** +Table Reference +***************** + +1. Database Metadata +==================== + +db_metadata +----------- + +Stores database-level configuration and version information. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE db_metadata ( + key TEXT PRIMARY KEY NOT NULL, + value TEXT + ); + + CREATE INDEX idx_db_metadata_key ON db_metadata(key); + +**Standard Keys:** + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Key + - Description + * - ``DATABASE_TYPE`` + - Database type identifier (always "PYUCIS") + * - ``DATABASE_FORMAT_VERSION`` + - Database format version (current: "1.0") + * - ``UCIS_VERSION`` + - UCIS standard version (e.g., "1.0") + * - ``API_VERSION`` + - Implementation API version + * - ``SCHEMA_VERSION`` + - Database schema version (current: "2.1") + * - ``CREATED_TIME`` + - Database creation timestamp (ISO 8601) + * - ``MODIFIED_TIME`` + - Last modification timestamp + * - ``PATH_SEPARATOR`` + - Character used for path separation (default: '/') + +**Database Identification:** + +The ``DATABASE_TYPE`` key serves as a marker to identify PyUCIS coverage databases. This allows validation that a SQLite file is specifically a PyUCIS database rather than an arbitrary SQLite file. + +**Example:** + +.. code-block:: sql + + SELECT key, value FROM db_metadata; + -- Result: + -- DATABASE_TYPE | PYUCIS + -- DATABASE_FORMAT_VERSION | 1.0 + -- UCIS_VERSION | 1.0 + -- API_VERSION | 1.0 + -- SCHEMA_VERSION | 2.1 + -- CREATED_TIME | 2026-01-12T15:30:00 + +2. File Management +================== + +files +----- + +Tracks source files referenced by coverage objects. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE files ( + file_id INTEGER PRIMARY KEY AUTOINCREMENT, + file_path TEXT NOT NULL UNIQUE, + file_hash TEXT, -- Optional hash for version tracking + file_table_id INTEGER -- For multi-file design units (1-indexed) + ); + + CREATE INDEX idx_files_path ON files(file_path); + CREATE INDEX idx_files_hash ON files(file_hash) WHERE file_hash IS NOT NULL; + +**Columns:** + +.. list-table:: + :header-rows: 1 + :widths: 20 20 60 + + * - Column + - Type + - Description + * - file_id + - INTEGER + - Primary key (auto-increment) + * - file_path + - TEXT + - File path (unique) + * - file_hash + - TEXT + - Optional hash (MD5/SHA) for version tracking + * - file_table_id + - INTEGER + - Multi-file compilation unit ID (1-indexed) + +**Example:** + +.. code-block:: sql + + INSERT INTO files (file_path, file_hash) + VALUES ('/project/rtl/counter.v', 'a1b2c3d4'); + + SELECT file_id, file_path FROM files WHERE file_path LIKE '%.v'; + +3. Scope Hierarchy +================== + +scopes +------ + +Hierarchical coverage containers representing design structure, coverage organization, and functional coverage groups. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE scopes ( + scope_id INTEGER PRIMARY KEY AUTOINCREMENT, + parent_id INTEGER, -- NULL for root scopes + scope_type INTEGER NOT NULL, -- ucisScopeTypeT (bit flags) + scope_name TEXT NOT NULL, + scope_flags INTEGER DEFAULT 0, -- Configuration flags + weight INTEGER DEFAULT 1, -- Coverage weight + goal INTEGER, -- Coverage goal percentage + limit INTEGER, -- Coverage limit + source_file_id INTEGER, -- Source location + source_line INTEGER, + source_token INTEGER, + language_type INTEGER, -- VHDL, Verilog, etc. + + FOREIGN KEY (parent_id) REFERENCES scopes(scope_id) ON DELETE CASCADE, + FOREIGN KEY (source_file_id) REFERENCES files(file_id) ON DELETE SET NULL + ); + + CREATE INDEX idx_scopes_parent ON scopes(parent_id); + CREATE INDEX idx_scopes_parent_type_name ON scopes(parent_id, scope_type, scope_name); + +**Columns:** + +.. list-table:: + :header-rows: 1 + :widths: 20 15 65 + + * - Column + - Type + - Description + * - scope_id + - INTEGER + - Primary key (auto-increment) + * - parent_id + - INTEGER + - Parent scope ID (NULL for root) + * - scope_type + - INTEGER + - Scope type bit flags (see ucisScopeTypeT) + * - scope_name + - TEXT + - Scope name + * - scope_flags + - INTEGER + - Configuration flags (enabled coverage, UOR flags) + * - weight + - INTEGER + - Coverage weight (default: 1) + * - goal + - INTEGER + - Coverage goal percentage + * - limit + - INTEGER + - Coverage limit + * - source_file_id + - INTEGER + - Reference to files table + * - source_line + - INTEGER + - Source line number + * - source_token + - INTEGER + - Source token position + * - language_type + - INTEGER + - Source language (VHDL, Verilog, SV, etc.) + +**Scope Types (ucisScopeTypeT):** + +.. list-table:: + :header-rows: 1 + :widths: 30 15 55 + + * - Type + - Value + - Description + * - UCIS_TOGGLE + - 0x0001 + - Toggle coverage scope + * - UCIS_BRANCH + - 0x0002 + - Branch coverage scope + * - UCIS_EXPR + - 0x0004 + - Expression coverage scope + * - UCIS_COND + - 0x0008 + - Condition coverage scope + * - UCIS_INSTANCE + - 0x0010 + - Design instance + * - UCIS_DU_MODULE + - 0x0020 + - Module design unit + * - UCIS_DU_ARCH + - 0x0040 + - Architecture design unit + * - UCIS_DU_PACKAGE + - 0x0080 + - Package design unit + * - UCIS_DU_PROGRAM + - 0x0100 + - Program design unit + * - UCIS_DU_INTERFACE + - 0x0200 + - Interface design unit + * - UCIS_BLOCK + - 0x0800 + - Block coverage scope + * - UCIS_COVERGROUP + - 0x1000 + - Covergroup type definition + * - UCIS_COVERINSTANCE + - 0x2000 + - Covergroup instance + * - UCIS_COVERPOINT + - 0x4000 + - Coverpoint + * - UCIS_CROSS + - 0x8000 + - Cross coverage + * - UCIS_FSM + - 0x400000 + - Finite state machine + * - UCIS_ASSERT + - 0x800000 + - Assertion/cover directive + +**Scope Flags:** + +.. list-table:: + :header-rows: 1 + :widths: 40 15 45 + + * - Flag + - Value + - Description + * - UCIS_ENABLED_STMT + - 0x01 + - Statement coverage enabled + * - UCIS_ENABLED_BRANCH + - 0x02 + - Branch coverage enabled + * - UCIS_ENABLED_COND + - 0x04 + - Condition coverage enabled + * - UCIS_ENABLED_EXPR + - 0x08 + - Expression coverage enabled + * - UCIS_ENABLED_FSM + - 0x10 + - FSM coverage enabled + * - UCIS_ENABLED_TOGGLE + - 0x20 + - Toggle coverage enabled + * - UCIS_UOR_SAFE_SCOPE + - 0x40 + - Universal Object Recognition safe + * - UCIS_UOR_SAFE_SCOPE_ALLCOVERS + - 0x80 + - All coveritems UOR safe + * - UCIS_INST_ONCE + - 0x100 + - Instance appears once in design + +**Example:** + +.. code-block:: sql + + -- Create top-level instance + INSERT INTO scopes (parent_id, scope_type, scope_name, scope_flags, weight) + VALUES (NULL, 0x10, 'top', 0, 1); + + -- Create child module with toggle coverage enabled + INSERT INTO scopes (parent_id, scope_type, scope_name, scope_flags, weight) + VALUES (1, 0x10, 'dut', 0x20, 1); + + -- Query all instances + SELECT scope_id, scope_name FROM scopes + WHERE scope_type & 0x10 != 0; + +4. Coverage Items +================= + +coveritems +---------- + +Leaf nodes containing actual coverage counts and metadata. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE coveritems ( + cover_id INTEGER PRIMARY KEY AUTOINCREMENT, + scope_id INTEGER NOT NULL, + cover_index INTEGER NOT NULL, -- Index within parent (0-based) + cover_type INTEGER NOT NULL, -- ucisCoverTypeT (bit flags) + cover_name TEXT NOT NULL, + cover_flags INTEGER DEFAULT 0, -- Coverage state flags + cover_data INTEGER DEFAULT 0, -- Primary hit count + cover_data_fec INTEGER DEFAULT 0, -- Functional equivalent count + at_least INTEGER DEFAULT 1, -- Minimum for coverage + weight INTEGER DEFAULT 1, + goal INTEGER, + limit INTEGER, + source_file_id INTEGER, -- Source location + source_line INTEGER, + source_token INTEGER, + + FOREIGN KEY (scope_id) REFERENCES scopes(scope_id) ON DELETE CASCADE, + FOREIGN KEY (source_file_id) REFERENCES files(file_id) ON DELETE SET NULL, + UNIQUE(scope_id, cover_index) + ); + + CREATE INDEX idx_coveritems_scope_index ON coveritems(scope_id, cover_index); + +**Columns:** + +.. list-table:: + :header-rows: 1 + :widths: 20 15 65 + + * - Column + - Type + - Description + * - cover_id + - INTEGER + - Primary key (auto-increment) + * - scope_id + - INTEGER + - Parent scope reference + * - cover_index + - INTEGER + - Index within parent scope (0-based) + * - cover_type + - INTEGER + - Coverage type bit flags + * - cover_name + - TEXT + - Coverage item name + * - cover_flags + - INTEGER + - State flags (covered, excluded, etc.) + * - cover_data + - INTEGER + - Primary hit count + * - cover_data_fec + - INTEGER + - Functional equivalent count + * - at_least + - INTEGER + - Minimum count for coverage (default: 1) + * - weight + - INTEGER + - Coverage weight + * - goal + - INTEGER + - Coverage goal + * - limit + - INTEGER + - Coverage limit + * - source_file_id + - INTEGER + - Reference to files table + * - source_line + - INTEGER + - Source line number + * - source_token + - INTEGER + - Source token position + +**Cover Types (ucisCoverTypeT):** + +.. list-table:: + :header-rows: 1 + :widths: 30 15 55 + + * - Type + - Value + - Description + * - UCIS_CVGBIN + - 0x0001 + - Regular covergroup bin + * - UCIS_STMTBIN + - 0x0002 + - Statement + * - UCIS_BRANCHBIN + - 0x0004 + - Branch (true/false) + * - UCIS_EXPRBIN + - 0x0008 + - Expression term + * - UCIS_CONDBIN + - 0x0010 + - Condition + * - UCIS_TOGGLEBIN + - 0x0200 + - Toggle (0->1 or 1->0) + * - UCIS_ASSERTBIN + - 0x0400 + - Assertion/cover + * - UCIS_FSMBIN + - 0x0800 + - FSM state or transition + * - UCIS_IGNOREBIN + - 0x80000 + - Ignore bin (excluded from coverage) + * - UCIS_ILLEGALBIN + - 0x100000 + - Illegal bin (should not be hit) + * - UCIS_DEFAULTBIN + - 0x200000 + - Default bin + +**Cover Flags:** + +.. list-table:: + :header-rows: 1 + :widths: 40 15 45 + + * - Flag + - Value + - Description + * - UCIS_IS_COVERED + - 0x01 + - Meets coverage goal + * - UCIS_CVG_EXCLUDE + - 0x02 + - Excluded from coverage + * - UCIS_UOR_SAFE_COVERITEM + - 0x04 + - Universal Object Recognition safe + +**Example:** + +.. code-block:: sql + + -- Create toggle coveritems (0->1 and 1->0) + INSERT INTO coveritems (scope_id, cover_index, cover_type, cover_name, cover_data) + VALUES (5, 0, 0x200, '0->1', 157); + + INSERT INTO coveritems (scope_id, cover_index, cover_type, cover_name, cover_data) + VALUES (5, 1, 0x200, '1->0', 156); + + -- Find uncovered items + SELECT c.cover_name, c.cover_data, c.at_least + FROM coveritems c + WHERE c.cover_data < c.at_least; + +5. History Nodes (Test Records) +================================ + +history_nodes +------------- + +Records of test runs, merges, and test plan nodes that contribute coverage data. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE history_nodes ( + history_id INTEGER PRIMARY KEY AUTOINCREMENT, + parent_id INTEGER, -- Hierarchical organization + history_kind INTEGER NOT NULL, -- TEST, MERGE, TESTPLAN + logical_name TEXT NOT NULL, + physical_name TEXT, + test_status INTEGER, -- Pass/fail status + sim_time_low INTEGER, -- 64-bit simulation time + sim_time_high INTEGER, + time_unit INTEGER, -- Time unit scale + cpu_time REAL, -- CPU execution time + seed TEXT, -- Random seed + cmd_line TEXT, -- Command line + compulsory INTEGER DEFAULT 0, -- Is test mandatory + date TEXT, -- Execution date + user_name TEXT, + cost REAL, -- Test cost metric + version TEXT, -- Tool version + + FOREIGN KEY (parent_id) REFERENCES history_nodes(history_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_history_parent ON history_nodes(parent_id); + CREATE INDEX idx_history_kind ON history_nodes(history_kind); + CREATE INDEX idx_history_logical ON history_nodes(logical_name); + CREATE INDEX idx_history_status ON history_nodes(test_status); + CREATE INDEX idx_history_date ON history_nodes(date) WHERE date IS NOT NULL; + +**Columns:** + +.. list-table:: + :header-rows: 1 + :widths: 20 15 65 + + * - Column + - Type + - Description + * - history_id + - INTEGER + - Primary key (auto-increment) + * - parent_id + - INTEGER + - Parent history node (for hierarchical organization) + * - history_kind + - INTEGER + - Node kind (TEST, MERGE, TESTPLAN) + * - logical_name + - TEXT + - Logical test name + * - physical_name + - TEXT + - Physical file path + * - test_status + - INTEGER + - Test execution status + * - sim_time_low + - INTEGER + - Lower 32 bits of simulation time + * - sim_time_high + - INTEGER + - Upper 32 bits of simulation time + * - time_unit + - INTEGER + - Time unit scale factor + * - cpu_time + - REAL + - CPU execution time (seconds) + * - seed + - TEXT + - Random seed value + * - cmd_line + - TEXT + - Command line used + * - compulsory + - INTEGER + - Is test mandatory (boolean) + * - date + - TEXT + - Execution date (ISO 8601) + * - user_name + - TEXT + - User who ran test + * - cost + - REAL + - Test cost metric + * - version + - TEXT + - Tool version + +**History Kinds:** + +.. list-table:: + :header-rows: 1 + :widths: 35 15 50 + + * - Kind + - Value + - Description + * - UCIS_HISTORYNODE_TEST + - 0x01 + - Individual test run + * - UCIS_HISTORYNODE_MERGE + - 0x02 + - Merged coverage from multiple sources + * - UCIS_HISTORYNODE_TESTPLAN + - 0x04 + - Test plan organizational node + +**Test Status:** + +.. list-table:: + :header-rows: 1 + :widths: 35 15 50 + + * - Status + - Value + - Description + * - UCIS_TESTSTATUS_OK + - 0 + - Test passed + * - UCIS_TESTSTATUS_WARNING + - 1 + - Test passed with warnings + * - UCIS_TESTSTATUS_FATAL + - 2 + - Test failed + +**Example:** + +.. code-block:: sql + + -- Create test record + INSERT INTO history_nodes (history_kind, logical_name, physical_name, + test_status, seed, date) + VALUES (0x01, 'test_basic', 'tests/test_basic.sv', 0, '12345', + '2026-01-12T10:30:00'); + + -- Query failed tests + SELECT logical_name, test_status FROM history_nodes + WHERE test_status = 2 AND history_kind = 0x01; + +6. Test-Coverage Associations +============================== + +coveritem_tests +--------------- + +Many-to-many relationship linking coverage items to the tests that hit them. Enables test minimization and impact analysis. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE coveritem_tests ( + cover_id INTEGER NOT NULL, + history_id INTEGER NOT NULL, + count_contribution INTEGER DEFAULT 0, -- Count from this test + + PRIMARY KEY (cover_id, history_id), + FOREIGN KEY (cover_id) REFERENCES coveritems(cover_id) ON DELETE CASCADE, + FOREIGN KEY (history_id) REFERENCES history_nodes(history_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_coveritem_tests_cover ON coveritem_tests(cover_id); + CREATE INDEX idx_coveritem_tests_history ON coveritem_tests(history_id); + +**Use Cases:** + +* Identify which tests hit specific coverage points +* Find tests that uniquely cover certain items +* Rank tests by unique coverage contribution +* Test minimization analysis + +**Example:** + +.. code-block:: sql + + -- Link test to coverage items + INSERT INTO coveritem_tests (cover_id, history_id, count_contribution) + VALUES (42, 1, 15); + + -- Find tests that hit a specific coverage point + SELECT h.logical_name, ct.count_contribution + FROM coveritem_tests ct + JOIN history_nodes h ON ct.history_id = h.history_id + WHERE ct.cover_id = 42; + + -- Find coverage unique to a test + SELECT c.cover_name + FROM coveritems c + JOIN coveritem_tests ct ON c.cover_id = ct.cover_id + WHERE ct.history_id = 1 + AND NOT EXISTS ( + SELECT 1 FROM coveritem_tests ct2 + WHERE ct2.cover_id = c.cover_id AND ct2.history_id != 1 + ); + +7. Properties +============= + +Generic key-value storage for extensible metadata on scopes, coveritems, and history nodes. + +scope_properties +---------------- + +.. code-block:: sql + + CREATE TABLE scope_properties ( + scope_id INTEGER NOT NULL, + property_key INTEGER NOT NULL, -- Property enum + property_type INTEGER NOT NULL, -- INT, REAL, STRING, HANDLE + int_value INTEGER, + real_value REAL, + string_value TEXT, + handle_value INTEGER, -- Reference to another object + + PRIMARY KEY (scope_id, property_key), + FOREIGN KEY (scope_id) REFERENCES scopes(scope_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_scope_props_key ON scope_properties(property_key); + +coveritem_properties +-------------------- + +.. code-block:: sql + + CREATE TABLE coveritem_properties ( + cover_id INTEGER NOT NULL, + property_key INTEGER NOT NULL, + property_type INTEGER NOT NULL, + int_value INTEGER, + real_value REAL, + string_value TEXT, + handle_value INTEGER, + + PRIMARY KEY (cover_id, property_key), + FOREIGN KEY (cover_id) REFERENCES coveritems(cover_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_cover_props_key ON coveritem_properties(property_key); + +history_properties +------------------ + +.. code-block:: sql + + CREATE TABLE history_properties ( + history_id INTEGER NOT NULL, + property_key INTEGER NOT NULL, + property_type INTEGER NOT NULL, + int_value INTEGER, + real_value REAL, + string_value TEXT, + handle_value INTEGER, + + PRIMARY KEY (history_id, property_key), + FOREIGN KEY (history_id) REFERENCES history_nodes(history_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_history_props_key ON history_properties(property_key); + +**Property Types:** + +.. list-table:: + :header-rows: 1 + :widths: 35 65 + + * - Type + - Description + * - UCIS_ATTR_INT (1) + - Integer value + * - UCIS_ATTR_REAL (2) + - Floating point value + * - UCIS_ATTR_STRING (3) + - String value + * - UCIS_ATTR_HANDLE (4) + - Reference to another object + +**Common Property Keys:** + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Key + - Description + * - UCIS_STR_UNIQUE_ID (0x100) + - Unique identifier string + * - UCIS_STR_NAME (0x101) + - Name property + * - UCIS_STR_COMMENT (0x102) + - Comment text + * - UCIS_INT_SCOPE_NUM_COVERS (0x200) + - Number of coveritems + * - UCIS_INT_COVERAGE_COUNT (0x201) + - Total coverage count + * - UCIS_REAL_CVG_INST_AVERAGE (0x300) + - Average coverage percentage + +8. User-Defined Attributes +=========================== + +attributes +---------- + +Flexible user-defined key-value pairs for custom metadata. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE attributes ( + attr_id INTEGER PRIMARY KEY AUTOINCREMENT, + obj_kind INTEGER NOT NULL, -- Scope, coveritem, or history + obj_id INTEGER NOT NULL, + attr_key TEXT NOT NULL, + attr_value TEXT, + + UNIQUE(obj_kind, obj_id, attr_key) + ); + + CREATE INDEX idx_attributes_obj ON attributes(obj_kind, obj_id); + CREATE INDEX idx_attributes_key ON attributes(attr_key); + +**Object Kinds:** + +.. list-table:: + :header-rows: 1 + :widths: 35 15 50 + + * - Kind + - Value + - Description + * - UCIS_OBJ_SCOPE + - 1 + - Attribute on scope + * - UCIS_OBJ_COVER + - 2 + - Attribute on coveritem + * - UCIS_OBJ_HISTORY + - 3 + - Attribute on history node + +9. Tags +======= + +tags / object_tags +------------------ + +Named tags for linking objects to verification plans or categories. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE tags ( + tag_id INTEGER PRIMARY KEY AUTOINCREMENT, + tag_name TEXT NOT NULL UNIQUE + ); + + CREATE INDEX idx_tags_name ON tags(tag_name); + + CREATE TABLE object_tags ( + obj_kind INTEGER NOT NULL, + obj_id INTEGER NOT NULL, + tag_id INTEGER NOT NULL, + + PRIMARY KEY (obj_kind, obj_id, tag_id), + FOREIGN KEY (tag_id) REFERENCES tags(tag_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_object_tags_obj ON object_tags(obj_kind, obj_id); + CREATE INDEX idx_object_tags_tag ON object_tags(tag_id); + +10. Toggle Coverage Details +============================ + +toggle_bits +----------- + +Per-bit toggle information for multi-bit signals. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE toggle_bits ( + toggle_id INTEGER PRIMARY KEY AUTOINCREMENT, + cover_id INTEGER NOT NULL, -- Parent toggle coveritem + bit_index INTEGER NOT NULL, + bit_type INTEGER NOT NULL, -- Bit, enum, others + toggle_01 INTEGER DEFAULT 0, -- 0->1 count + toggle_10 INTEGER DEFAULT 0, -- 1->0 count + + FOREIGN KEY (cover_id) REFERENCES coveritems(cover_id) ON DELETE CASCADE, + UNIQUE(cover_id, bit_index) + ); + + CREATE INDEX idx_toggle_bits_cover ON toggle_bits(cover_id); + +11. FSM Coverage Details +========================= + +fsm_states / fsm_transitions +----------------------------- + +Finite state machine state definitions and transitions. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE fsm_states ( + state_id INTEGER PRIMARY KEY AUTOINCREMENT, + scope_id INTEGER NOT NULL, -- Parent FSM scope + state_name TEXT NOT NULL, + state_index INTEGER NOT NULL, + + FOREIGN KEY (scope_id) REFERENCES scopes(scope_id) ON DELETE CASCADE, + UNIQUE(scope_id, state_index) + ); + + CREATE INDEX idx_fsm_states_scope ON fsm_states(scope_id); + CREATE INDEX idx_fsm_states_name ON fsm_states(state_name); + + CREATE TABLE fsm_transitions ( + cover_id INTEGER NOT NULL, -- Transition coveritem + from_state_id INTEGER NOT NULL, + to_state_id INTEGER NOT NULL, + + PRIMARY KEY (cover_id), + FOREIGN KEY (cover_id) REFERENCES coveritems(cover_id) ON DELETE CASCADE, + FOREIGN KEY (from_state_id) REFERENCES fsm_states(state_id) ON DELETE CASCADE, + FOREIGN KEY (to_state_id) REFERENCES fsm_states(state_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_fsm_trans_from ON fsm_transitions(from_state_id); + CREATE INDEX idx_fsm_trans_to ON fsm_transitions(to_state_id); + +12. Cross Coverage +================== + +cross_coverpoints +----------------- + +Links cross coverage to constituent coverpoints. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE cross_coverpoints ( + cross_scope_id INTEGER NOT NULL, -- UCIS_CROSS scope + coverpoint_scope_id INTEGER NOT NULL, -- UCIS_COVERPOINT scope + cvp_index INTEGER NOT NULL, -- Order in cross + + PRIMARY KEY (cross_scope_id, cvp_index), + FOREIGN KEY (cross_scope_id) REFERENCES scopes(scope_id) ON DELETE CASCADE, + FOREIGN KEY (coverpoint_scope_id) REFERENCES scopes(scope_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_cross_cvps_cross ON cross_coverpoints(cross_scope_id); + CREATE INDEX idx_cross_cvps_cvp ON cross_coverpoints(coverpoint_scope_id); + +13. Formal Verification +======================== + +formal_data / formal_envs +-------------------------- + +Formal verification results and environment settings. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE formal_data ( + cover_id INTEGER PRIMARY KEY, -- Assertion coveritem + formal_status INTEGER, -- Proven, disproven, etc. + formal_radius INTEGER, -- Proof depth + witness_file TEXT, -- Counter-example location + + FOREIGN KEY (cover_id) REFERENCES coveritems(cover_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_formal_status ON formal_data(formal_status); + + CREATE TABLE formal_envs ( + env_id INTEGER PRIMARY KEY AUTOINCREMENT, + history_id INTEGER, -- Associated test/proof + env_type INTEGER NOT NULL, + env_name TEXT, + env_value TEXT, + + FOREIGN KEY (history_id) REFERENCES history_nodes(history_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_formal_envs_history ON formal_envs(history_id); + CREATE INDEX idx_formal_envs_type ON formal_envs(env_type); + +**Formal Status Values:** + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Status + - Description + * - UCIS_FORMAL_VACUOUS (1) + - Vacuously true + * - UCIS_FORMAL_UNREACHABLE (2) + - Unreachable + * - UCIS_FORMAL_DISPROVEN (3) + - Counter-example found + * - UCIS_FORMAL_PROVEN (4) + - Formally proven + * - UCIS_FORMAL_INCONCLUSIVE (5) + - Inconclusive result + +14. Design Unit Management +=========================== + +design_units +------------ + +Tracks design unit definitions and relationships. + +**Schema:** + +.. code-block:: sql + + CREATE TABLE design_units ( + du_id INTEGER PRIMARY KEY AUTOINCREMENT, + du_scope_id INTEGER NOT NULL UNIQUE, -- References scopes table + du_name TEXT NOT NULL, + du_type INTEGER NOT NULL, -- Module, architecture, etc. + + FOREIGN KEY (du_scope_id) REFERENCES scopes(scope_id) ON DELETE CASCADE + ); + + CREATE INDEX idx_design_units_name ON design_units(du_name); + CREATE INDEX idx_design_units_type ON design_units(du_type); + +****************** +Query Examples +****************** + +Hierarchical Path Queries +========================== + +Build full paths using recursive CTEs: + +.. code-block:: sql + + WITH RECURSIVE scope_path AS ( + SELECT scope_id, scope_name, scope_type, parent_id, + scope_name as full_path + FROM scopes + WHERE parent_id IS NULL + + UNION ALL + + SELECT s.scope_id, s.scope_name, s.scope_type, s.parent_id, + sp.full_path || '/' || s.scope_name + FROM scopes s + JOIN scope_path sp ON s.parent_id = sp.scope_id + ) + SELECT full_path, scope_type + FROM scope_path + WHERE scope_name LIKE '%clk%'; + +Coverage Calculation +==================== + +Calculate coverage percentages: + +.. code-block:: sql + + -- Coverpoint coverage + SELECT + s.scope_name, + COUNT(*) as total_bins, + SUM(CASE WHEN c.cover_data >= c.at_least THEN 1 ELSE 0 END) as covered_bins, + (100.0 * SUM(CASE WHEN c.cover_data >= c.at_least THEN 1 ELSE 0 END) / + COUNT(*)) as coverage_pct + FROM scopes s + JOIN coveritems c ON s.scope_id = c.scope_id + WHERE s.scope_type = 0x4000 -- COVERPOINT + GROUP BY s.scope_id; + +Test Unique Coverage +==================== + +Find coverage unique to specific tests: + +.. code-block:: sql + + SELECT + h.logical_name, + COUNT(DISTINCT ct.cover_id) as bins_hit, + COUNT(DISTINCT CASE WHEN unique_hits = 1 THEN ct.cover_id END) as unique_bins + FROM history_nodes h + JOIN coveritem_tests ct ON h.history_id = ct.history_id + LEFT JOIN ( + SELECT cover_id, COUNT(*) as unique_hits + FROM coveritem_tests + GROUP BY cover_id + ) u ON ct.cover_id = u.cover_id + GROUP BY h.history_id; + +Uncovered Items +=============== + +Find items not meeting coverage goals: + +.. code-block:: sql + + SELECT + s.scope_name, + c.cover_name, + c.cover_data as hits, + c.at_least as required + FROM coveritems c + JOIN scopes s ON c.scope_id = s.scope_id + WHERE c.cover_data < c.at_least + AND (c.cover_flags & 0x02) = 0 -- Not excluded + ORDER BY s.scope_name, c.cover_index; + +******************* +Performance Tuning +******************* + +Schema Version +============== + +**Current Version: 2.1** + +The database schema includes a version number stored in the ``db_metadata`` table. Version 2.1 introduces optimizations for merge performance and storage efficiency: + +* **Reduced indexes** - Removed 7 unused indexes that provided no query benefit +* **Merge optimization** - Streamlined bin creation to minimize row growth +* **History tracking** - Optional history squashing for large-scale merges + +Opening a database with a mismatched schema version will raise an error. Databases from older schema versions must be recreated with the current schema. + +Index Optimization +================== + +Version 2.1 includes optimized indexes for common query patterns: + +**Scopes:** + +* ``idx_scopes_parent`` - Parent-child traversal +* ``idx_scopes_parent_type_name`` - Composite lookup by parent, type, and name + +**Coveritems:** + +* ``idx_coveritems_scope_index`` - Lookup by scope and cover index (critical for merge performance) + +**Removed Indexes (v2.1):** + +The following indexes were removed as they provided no measurable performance benefit: + +* ``idx_scopes_type``, ``idx_scopes_name``, ``idx_scopes_parent_name``, ``idx_scopes_source`` +* ``idx_coveritems_scope``, ``idx_coveritems_type``, ``idx_coveritems_name``, ``idx_coveritems_source`` + +This reduces storage overhead by approximately 30-40% with no query performance impact. + +ANALYZE Command +=============== + +Update statistics for query optimization: + +.. code-block:: sql + + ANALYZE; + +Vacuum +====== + +Reclaim space and optimize storage: + +.. code-block:: sql + + VACUUM; + +********** +See Also +********** + +* :doc:`../sqlite-api` - Python API documentation +* :doc:`../native-c-library` - C API documentation +* :doc:`../python-api/oo-api` - General object-oriented API diff --git a/doc/source/reference/formats/xml-interchange.rst b/doc/source/reference/formats/xml-interchange.rst new file mode 100644 index 0000000..189e335 --- /dev/null +++ b/doc/source/reference/formats/xml-interchange.rst @@ -0,0 +1,455 @@ +###################### +XML Interchange Format +###################### + +The Accelera UCIS Standard document specifies an XML interchange format. While the +XML document structure has some similarities with the data model accessed via the +UCIS C API, there are also significant differences. + +The UCIS standards document also has relatively few examples of the XML interchange +format, leaving some things a bit ambiguous. None of the ambiguities are with respect +to the document schema. Rather, they are with respect to how a schema-compliant +XML document is interpreted. + +This section of the PyUCIS documentation describes how PyUCIS interprets a +schema-compliant XML description, and the data it produces. Many of the +details are shaped by how existing tools interpret the XML interchange +format. Because our goal is to maximize interoperability, PyUCIS +deliberately shapes its data output (especially) to maximize interoperability + +Functional Coverage +=================== + +Functional coverage data is stored in `cgInstance` sections within a +`covergroupCoverage` scope. + + +Covergroup instance/type linkage +-------------------------------- +The cgId section inside the cgInstance specifies the associated covergroup type. + +.. code:: + + + + + + + + + +This covergroup instance name is `top.cg_i1`, and is associated with a +covergroup type `top::my_covergroup`. + +Covergroup instance and type data +--------------------------------- +The UCIS data model represents covergroup type coverage (the merge of all +covergroup instances of a given type) as a scope that contains a series +of sub-scopes that hold per-instance coverage data. The XML interchange +format does not provide such a hierarchy. + +When instance coverage is being recorded, all cgInstance sections +associated with a given covergroup type contain instance data. The +reader of XML data is responsible for reconstructing type coverage. + +When instance coverage is not being recorded, only a single cgInstance +section is written. This section contains type data. +This intepretation is backed up bythe spec: a `covergroupCoverage` scope +with a single `cgInstance` entry represents coverage for the covergroup as a whole. +For example, a covergroup with `per_instance` set to false. + +Coverage Instance Options +------------------------- +When reading XML, PyUCIS considers the following coverage options significant: + +- _per_instance_ - Indicates whether per-instance data is recorded +- _merge_instances_ - Specifies whether to produce type coverage from the merge of instance data + +Both of these options are boolean options. PyUCIS accepts `true`, `false`, `0`, and `1`. + +When writing XML, PyUCIS emits `auto_bin_max=0`. This is because PyUCIS represents all coverpoint +bins explicitly. Some consumers of XML interchange format attempt to create auto-bins if this +option is not explicitly set to 0. + +Coverpoint Bins +--------------- + +.. code:: + + + + + + contents coverageCount="1"/> + + + + + +Coverpoint data is stored within a `coverpoint` subsection inside `cgInstance`. PyUCIS +writes the bin type as one of `bins`, `ignore`, `illegal`. + +PyUCIS only interprets and records the following options: +- `weight` +- `at_least` + +PyUCIS does not interpret the value-range data, and records both bounds of the +range as `-1`. This is because UCIS doesn't provide relevant data to record. + + +Cross Bins +---------- +The most common case with cross bins is to record auto-bins resulting from +the cross of the relevant coverpoints. + +.. code:: + + + + cp1 + cp2 + + 0 + 0 + + + + + +Note that the bin-index information is not something that is present in +the UCIS data model. Cross bins, like all other bins, are simply named +counts. PyUCIS attempts to reconstruct the indices by looking for bin +names within the bin name. In the example above, the bin names a[0], +a[0] are both the first bin within their respective coverpoints. +Consequently, bin indices 0,0 are specified. + +In the case of `ignore` or `illegal` bins, all indices are specified +as -1. + +PyUCIS records the bin type only if it is `ignore` or `illegal`. This +improves interoperability with some tools. + +Coverage Options Support +========================= + +PyUCIS fully supports reading and writing coverage options per the UCIS 1.0 specification: + +Supported Options +----------------- + +**Covergroup Options** (``CGINST_OPTIONS``): + - ``weight`` - Relative weight for coverage calculation + - ``goal`` - Coverage goal percentage (default: 100) + - ``at_least`` - Minimum hit count for coverage (default: 1) + - ``per_instance`` - Track per-instance coverage + - ``merge_instances`` - Merge instance coverage into type coverage + - ``get_inst_coverage`` - Enable instance coverage retrieval + - ``auto_bin_max`` - Maximum auto-generated bins (PyUCIS sets to 64) + - ``detect_overlap`` - Detect overlapping bins + - ``strobe`` - Strobe sampling mode + +**Coverpoint Options** (``COVERPOINT_OPTIONS``): + - ``weight`` - Relative weight for coverage calculation + - ``goal`` - Coverage goal percentage (default: 100) + - ``at_least`` - Minimum hit count for coverage (default: 1) + - ``auto_bin_max`` - Maximum auto-generated bins + - ``detect_overlap`` - Detect overlapping bins + +**Cross Options** (``CROSS_OPTIONS``): + - ``weight`` - Relative weight for coverage calculation + - ``goal`` - Coverage goal percentage (default: 100) + - ``at_least`` - Minimum hit count for coverage (default: 1) + - ``cross_num_print_missing`` - Number of missing cross bins to report + +Value Normalization +------------------- + +When writing XML, PyUCIS normalizes certain values to comply with XSD schema constraints: + +- Negative ``goal`` values → 100 (UCIS default) +- Zero or negative ``at_least`` values → 1 (UCIS default) +- Zero or negative ``auto_bin_max`` values → 64 (UCIS default) + +This ensures XML validates against the schema's ``nonNegativeInteger`` requirements. + +Schema Compliance +================= + +PyUCIS implementation follows UCIS 1.0 XML schema (``ucis.xsd``) with the following notable aspects: + +Required Elements +----------------- + +- **sourceFiles** (minOccurs="1") - At least one source file entry required +- **historyNodes** (minOccurs="1") - At least one history node required +- **instanceCoverages** (minOccurs="1") - At least one instance coverage required +- **coverpointBin** (minOccurs="1") - Coverpoints must contain at least one bin + +Optional Elements +----------------- + +- **coverpoint** (minOccurs="0") - Covergroups may be empty (no coverpoints) +- **cross** (minOccurs="0") - Cross coverage is optional +- **crossBin** (minOccurs="0") - Crosses may have no bins + +Code Coverage +============= + +PyUCIS supports reading and writing all major UCIS code coverage types within +``instanceCoverages`` elements. + +Statement Coverage +------------------ + +Statement coverage is stored as ``blockCoverage`` → flat ``statement`` elements: + +.. code:: + + + + + + + +Each ``statement`` records one source location with its hit count. + +Branch Coverage +--------------- + +Branch coverage is stored as ``branchCoverage`` → ``branch`` elements, one per +branching statement (``if``, ``case``, etc.). Each branch has one or more +``branchBin`` arms: + +.. code:: + + + + + + + + + + + + +Toggle Coverage +--------------- + +Toggle coverage is stored as ``toggleCoverage`` → ``toggleObject`` → ``toggleBit`` +elements. Each bit records a 0→1 and a 1→0 transition bin: + +.. code:: + + + + + + + + + + + + + + +FSM Coverage +------------ + +FSM coverage is stored as ``fsmCoverage`` → ``fsm`` elements. State coverage uses +``stateBin`` and transition coverage uses ``transitionBin``: + +.. code:: + + + + + + + + + + IDLE + ACTIVE + + + + + + + +Assertion Coverage +------------------ + +Assertion coverage is stored as ``assertionCoverage`` → ``assertion`` elements. +The ``assertionKind`` attribute is either ``assert`` or ``cover``: + +.. code:: + + + + + + + + + + + + + + + +Supported bin kinds for ``assert``: ``failBin``, ``passBin``, ``vacuousBin``, +``disabledBin``, ``attemptBin``, ``activeBin``, ``peakActiveBin``. + +Supported bin kinds for ``cover``: ``coverBin``, ``failBin``, ``passBin``, +``vacuousBin``, ``disabledBin``, ``attemptBin``, ``activeBin``, ``peakActiveBin``. + +User Attributes +=============== + +PyUCIS supports round-tripping user attributes (set via ``setAttribute`` / +``getAttribute``) through XML ``userAttr`` child elements. These are written as +the last children of each coverage container element: + +.. code:: + + + + my_simulator + 2024.1 + + +User attributes attached to instance scopes are preserved across XML write/read +round-trips. Tags (set via ``addTag``) are not currently serialized to XML. + +History Nodes +============= + +History nodes record the provenance of coverage data (test runs, merges). PyUCIS +preserves the parent/child relationships between history nodes using the ``id`` +and ``parentId`` attributes: + +.. code:: + + + + + + +Known Format Limitations +========================= + +The following limitations are inherent to the UCIS XML interchange format specification: + +Structural Limitations +---------------------- + +1. **Design Unit (DU) Scopes Not Serialized** + + Only instance coverages are written to XML. Design unit definitions and their source information + are not directly preserved. DU information is referenced via the ``moduleName`` attribute in + ``instanceCoverages``. + +2. **Instance Weight Not Supported** + + The ``INSTANCE_COVERAGE`` schema does not include a ``weight`` attribute. Instance-level weighting + must be handled through covergroup weights instead. + +3. **Mandatory Instance Coverage** + + The schema requires at least one ``instanceCoverages`` element. Pure file handle or metadata-only + databases cannot be represented in XML format. + +4. **Coverpoints Require Bins** + + Per the schema, coverpoints must contain at least one bin (``minOccurs="1"`` for ``coverpointBin``). + Empty coverpoints cannot be serialized to XML. + +Feature Support Matrix +---------------------- + +.. list-table:: + :header-rows: 1 + :widths: 40 20 40 + + * - Feature + - Supported + - Notes + * - Covergroup Options + - ✅ Yes + - Full read/write support + * - Coverpoint Options + - ✅ Yes + - Full read/write support + * - Cross Coverage + - ✅ Yes + - Including multi-way crosses + * - Cross Bins + - ✅ Yes + - With index reconstruction + * - Statement Coverage + - ✅ Yes + - Flat statement mode + * - Branch Coverage + - ✅ Yes + - if/case branching statements + * - Toggle Coverage + - ✅ Yes + - Per-bit 0→1 and 1→0 bins + * - FSM Coverage + - ✅ Yes + - State and transition coverage + * - Assertion Coverage + - ✅ Yes + - cover and assert kinds, all bin types + * - User Attributes + - ✅ Yes + - Via ``userAttr`` child elements + * - History Node Hierarchy + - ✅ Yes + - Parent/child via ``parentId`` + * - Condition/Expression Coverage + - ❌ No + - Not in Python DM; writer emits ctx.warn + * - Instance Weights + - ❌ No + - Not in XML schema + * - Empty Coverpoints + - ❌ No + - Schema requires bins + * - DU Source Info + - ⚠️ Partial + - Only via instance references + * - Standalone File Handles + - ❌ No + - Requires instanceCoverages + * - Tags + - ❌ No + - No direct XML representation + +Workarounds +----------- + +**For Empty Coverpoints:** + Add a placeholder bin when writing to XML. The bin can be marked as ``ignore`` type + to indicate it's not a real coverage point. + +**For Instance Weights:** + Use covergroup-level weights instead. Apply instance-specific weights at the covergroup + level for each instance. + +**For File Handle Preservation:** + Include at least one instance coverage element in the XML. File handles are preserved + within the ``sourceFiles`` section and referenced by ``id`` attributes. + +Version Information +=================== + +This documentation applies to PyUCIS implementation of UCIS 1.0 XML interchange format +as specified in the Accelera UCIS Standard (June 2012). + +Schema file: ``src/ucis/xml/schema/ucis.xsd`` + diff --git a/doc/source/reference/formats/yaml-format.rst b/doc/source/reference/formats/yaml-format.rst new file mode 100644 index 0000000..9883fb3 --- /dev/null +++ b/doc/source/reference/formats/yaml-format.rst @@ -0,0 +1,49 @@ +######################### +YAML Coverage Data Format +######################### + +The YAML coverage-data format is used to represent functional coverage +data in a manner that is accurate and relatively easy for humans and +tools to create and process. + + +Format Reference +================ + +.. jsonschema:: ../../../src/ucis/schema/coverage.json + +Every coverage-data document has a `coverage` element as its root. Currently, +the only sub-elements is a list of covergroup types. + +.. jsonschema:: ../../../src/ucis/schema/coverage.json#/defs/covergroupType + +A type covergroup provides data about a covergroup type. All instances +of a covergroup type have the same coverpoints and crosses. All +coverpoints in instances of a covergroup type have the same bins. +Merged type coverage (the union of coverage achieved by all instances) +is derived by PyUCIS from the instance coverage, and is not specified +in the coverage file. + +.. jsonschema:: ../../../src/ucis/schema/coverage.json#/defs/covergroupInstType + +An instance covergroup provides data about a covergroup instance. + + +.. jsonschema:: ../../../src/ucis/schema/coverage.json#/defs/coverpointType + +A coverpoint lists a set of bins that it is monitoring. Each +coverpoint can specify an `atleast` count to specify that a +bin must contain `atleast` hits in order to count as being covered. +By default, `atleast` is 1. + +.. jsonschema:: ../../../src/ucis/schema/coverage.json#/defs/crossType + +A cross lists the set of coverpoints from which it is composed, +and lists its cross bins. Each cross can specify an `atleast` +count to specify that a bin must contain `atleast` hits in +order to count as being covered. By default, `atleast` is 1. + +.. jsonschema:: ../../../src/ucis/schema/coverage.json#/defs/coverBinType + +A coverbin associates a bin name with the number of hits +in that bin. diff --git a/doc/source/reference/index.rst b/doc/source/reference/index.rst new file mode 100644 index 0000000..f27d454 --- /dev/null +++ b/doc/source/reference/index.rst @@ -0,0 +1,39 @@ +################ +Reference +################ + +This section is for **developers and tool integrators** who need: + +* The complete CLI option reference +* Python API documentation (object-oriented and C-style) +* Technical specifications for the supported file formats +* SQLite backend API and schema + +If you are a typical user of the ``ucis`` command-line tool, start with +:doc:`../getting-started/quickstart` instead. + +.. toctree:: + :maxdepth: 1 + + cli + sqlite-api + native-c-library + best-practices + +.. toctree:: + :maxdepth: 2 + :caption: Python API + + python-api/index + +.. toctree:: + :maxdepth: 2 + :caption: File Formats + + formats/index + +.. toctree:: + :maxdepth: 2 + :caption: Report Formats + + report-formats/index diff --git a/doc/source/reference/native-c-library.rst b/doc/source/reference/native-c-library.rst new file mode 100644 index 0000000..0b0dca1 --- /dev/null +++ b/doc/source/reference/native-c-library.rst @@ -0,0 +1,782 @@ +########################## +Native C Library API +########################## + +The PyUCIS Native C Library provides a complete implementation of the UCIS 1.0 C API using SQLite3 as the backend storage. This native library can be used directly from C/C++ applications or through Python's ctypes interface. + +******** +Overview +******** + +Features +======== + +* **UCIS 1.0 Standard Compliant** - Full implementation of the official C API +* **SQLite3 Backend** - Persistent, queryable storage with SQL access +* **High Performance** - Optimized with prepared statements and caching +* **Thread-Safe** - Can be used in multi-threaded applications +* **Cross-Platform** - Builds on Linux, macOS, and Windows +* **Python Integration** - Can be loaded via ctypes from Python + +Architecture +============ + +**Opaque Handles** + All API types are opaque pointers backed by an internal handle table for type safety. + +**Prepared Statements** + Frequently-used SQL queries are prepared once and cached for performance. + +**Foreign Keys** + Referential integrity enforced at the database level. + +**WAL Mode** + Write-Ahead Logging enabled for better concurrency. + +**Handle Caching** + Frequently-accessed data cached in handle entries to minimize database queries. + +************ +Building +************ + +Requirements +============ + +* C compiler (GCC, Clang, or MSVC) +* CMake 3.10 or later +* SQLite3 (included as amalgamation) + +Build Steps +=========== + +.. code-block:: bash + + # Navigate to native directory + cd src/native + + # Build with CMake + mkdir build + cd build + cmake .. + make + + # Or use make directly + cd src/native + make + + # Install library (optional) + sudo make install + +Build Outputs +============= + +* **libucis.so** (Linux) - Shared library +* **libucis.dylib** (macOS) - Shared library +* **ucis.dll** (Windows) - Dynamic link library +* **libucis.a** - Static library (optional) + +Testing +======= + +.. code-block:: bash + + # Run test suite + make test + + # Or run individual tests + cd test + python3 test_basic.py + python3 test_scopes.py + +************* +API Reference +************* + +Database Lifecycle +================== + +ucis_Open +--------- + +.. c:function:: ucisT ucis_Open(const char* name) + + Open or create a UCIS database. + + :param name: File path or NULL for in-memory database + :return: Database handle or NULL on error + + **Example:** + + .. code-block:: c + + ucisT db = ucis_Open("coverage.ucisdb"); + if (!db) { + fprintf(stderr, "Error: %s\n", ucis_GetLastError()); + return 1; + } + +ucis_Close +---------- + +.. c:function:: void ucis_Close(ucisT db) + + Close a UCIS database and free all resources. + + :param db: Database handle + + **Example:** + + .. code-block:: c + + ucis_Close(db); + +ucis_Write +---------- + +.. c:function:: int ucis_Write(ucisT db, const char* name) + + Write database to a file (useful for in-memory databases). + + :param db: Database handle + :param name: Target file path + :return: 0 on success, non-zero on error + + **Example:** + + .. code-block:: c + + if (ucis_Write(db, "output.ucisdb") != 0) { + fprintf(stderr, "Write failed: %s\n", ucis_GetLastError()); + } + +ucis_GetAPIVersion +------------------ + +.. c:function:: const char* ucis_GetAPIVersion(void) + + Get UCIS API version string. + + :return: Version string (e.g., "1.0") + + **Example:** + + .. code-block:: c + + printf("UCIS API Version: %s\n", ucis_GetAPIVersion()); + +ucis_GetLastError +----------------- + +.. c:function:: const char* ucis_GetLastError(void) + + Get the last error message from any UCIS operation. + + :return: Error message string or NULL if no error + + **Example:** + + .. code-block:: c + + if (!db) { + fprintf(stderr, "Error: %s\n", ucis_GetLastError()); + } + +Scope Operations +================ + +ucis_CreateScope +---------------- + +.. c:function:: ucisScopeT ucis_CreateScope(ucisT db, ucisScopeT parent, const char* name, ucisSourceInfoT* source, int weight, ucisSourceT source_type, ucisScopeTypeT type, int flags) + + Create a new scope in the hierarchy. + + :param db: Database handle + :param parent: Parent scope or NULL for root-level scope + :param name: Scope name + :param source: Source location info or NULL + :param weight: Coverage weight (typically 1) + :param source_type: Source type (UCIS_VHDL, UCIS_VLOG, etc.) + :param type: Scope type (UCIS_INSTANCE, UCIS_COVERGROUP, etc.) + :param flags: Scope flags (coverage enables, UOR flags) + :return: New scope handle or NULL on error + + **Example:** + + .. code-block:: c + + // Create top-level instance + ucisScopeT top = ucis_CreateScope( + db, + NULL, // No parent + "top", + NULL, // No source info + 1, // Weight + UCIS_VLOG, + UCIS_INSTANCE, + 0 // No flags + ); + +ucis_CreateInstance +------------------- + +.. c:function:: ucisScopeT ucis_CreateInstance(ucisT db, ucisScopeT parent, const char* name, ucisSourceInfoT* source, int weight, ucisSourceT source_type) + + Create an instance scope (convenience wrapper). + + :param db: Database handle + :param parent: Parent scope + :param name: Instance name + :param source: Source location or NULL + :param weight: Coverage weight + :param source_type: Source type + :return: New instance scope or NULL on error + + **Example:** + + .. code-block:: c + + ucisScopeT dut = ucis_CreateInstance(db, top, "dut", NULL, 1, UCIS_VLOG); + +ucis_GetScopeName +----------------- + +.. c:function:: const char* ucis_GetScopeName(ucisT db, ucisScopeT scope) + + Get the name of a scope. + + :param db: Database handle + :param scope: Scope handle + :return: Scope name or NULL on error + + **Example:** + + .. code-block:: c + + const char* name = ucis_GetScopeName(db, scope); + printf("Scope name: %s\n", name); + +ucis_GetScopeType +----------------- + +.. c:function:: ucisScopeTypeT ucis_GetScopeType(ucisT db, ucisScopeT scope) + + Get the type of a scope. + + :param db: Database handle + :param scope: Scope handle + :return: Scope type flags + + **Example:** + + .. code-block:: c + + ucisScopeTypeT type = ucis_GetScopeType(db, scope); + if (type & UCIS_INSTANCE) { + printf("This is an instance\n"); + } + +ucis_GetParent +-------------- + +.. c:function:: ucisScopeT ucis_GetParent(ucisT db, ucisScopeT scope) + + Get the parent scope. + + :param db: Database handle + :param scope: Scope handle + :return: Parent scope handle or NULL if root + + **Example:** + + .. code-block:: c + + ucisScopeT parent = ucis_GetParent(db, scope); + if (parent) { + printf("Parent: %s\n", ucis_GetScopeName(db, parent)); + } + +ucis_SetScopeWeight +------------------- + +.. c:function:: int ucis_SetScopeWeight(ucisT db, ucisScopeT scope, int weight) + + Set the coverage weight of a scope. + + :param db: Database handle + :param scope: Scope handle + :param weight: New weight value + :return: 0 on success, non-zero on error + +ucis_SetScopeGoal +----------------- + +.. c:function:: int ucis_SetScopeGoal(ucisT db, ucisScopeT scope, int goal) + + Set the coverage goal percentage. + + :param db: Database handle + :param scope: Scope handle + :param goal: Goal percentage (0-100) + :return: 0 on success, non-zero on error + +ucis_SetScopeFlags +------------------ + +.. c:function:: int ucis_SetScopeFlags(ucisT db, ucisScopeT scope, int flags) + + Set scope flags. + + :param db: Database handle + :param scope: Scope handle + :param flags: Flag bits (coverage enables, UOR flags) + :return: 0 on success, non-zero on error + +ucis_ScopeIterate +----------------- + +.. c:function:: int ucis_ScopeIterate(ucisT db, ucisScopeT parent, ucisScopeTypeT type_mask, ucisScopeCBT callback, void* userdata) + + Iterate over child scopes with optional type filtering. + + :param db: Database handle + :param parent: Parent scope or NULL for root-level scopes + :param type_mask: Scope type filter (bitwise OR of types, -1 for all) + :param callback: Callback function called for each scope + :param userdata: User data passed to callback + :return: 0 on success, non-zero on error + + **Callback signature:** + + .. code-block:: c + + typedef int (*ucisScopeCBT)(void* userdata, ucisScopeT scope); + + **Example:** + + .. code-block:: c + + int print_scope(void* userdata, ucisScopeT scope) { + ucisT db = (ucisT)userdata; + printf("Scope: %s\n", ucis_GetScopeName(db, scope)); + return 0; // Continue iteration + } + + // Iterate all child scopes + ucis_ScopeIterate(db, parent, -1, print_scope, db); + + // Iterate only instances + ucis_ScopeIterate(db, parent, UCIS_INSTANCE, print_scope, db); + +Coverage Operations +=================== + +ucis_CreateNextCover +-------------------- + +.. c:function:: ucisCoverT ucis_CreateNextCover(ucisT db, ucisScopeT parent, const char* name, ucisCoverDataT* data, ucisSourceInfoT* source) + + Create the next coverage item in a scope. + + :param db: Database handle + :param parent: Parent scope + :param name: Coverage item name + :param data: Coverage data (type and initial count) + :param source: Source location or NULL + :return: New coverage item handle or NULL on error + + **Example:** + + .. code-block:: c + + ucisCoverDataT data = {0}; + data.type = UCIS_CVGBIN; + data.data = 0; // Initial count + + ucisCoverT bin = ucis_CreateNextCover(db, coverpoint, "low", &data, NULL); + +ucis_GetCoverData +----------------- + +.. c:function:: int ucis_GetCoverData(ucisT db, ucisCoverT cover, ucisCoverDataT* data) + + Get coverage data for an item. + + :param db: Database handle + :param cover: Coverage item handle + :param data: Output parameter for coverage data + :return: 0 on success, non-zero on error + + **Example:** + + .. code-block:: c + + ucisCoverDataT data; + if (ucis_GetCoverData(db, cover, &data) == 0) { + printf("Hit count: %d\n", data.data); + } + +ucis_SetCoverData +----------------- + +.. c:function:: int ucis_SetCoverData(ucisT db, ucisCoverT cover, ucisCoverDataT* data) + + Set coverage data for an item. + + :param db: Database handle + :param cover: Coverage item handle + :param data: New coverage data + :return: 0 on success, non-zero on error + +ucis_IncrementCoverData +------------------------ + +.. c:function:: int ucis_IncrementCoverData(ucisT db, ucisCoverT cover, int amount) + + Increment coverage count. + + :param db: Database handle + :param cover: Coverage item handle + :param amount: Amount to increment (default: 1) + :return: 0 on success, non-zero on error + + **Example:** + + .. code-block:: c + + // Increment by 1 + ucis_IncrementCoverData(db, cover, 1); + +ucis_CoverIterate +----------------- + +.. c:function:: int ucis_CoverIterate(ucisT db, ucisScopeT parent, ucisCoverTypeT type_mask, ucisCoverCBT callback, void* userdata) + + Iterate over coverage items in a scope. + + :param db: Database handle + :param parent: Parent scope + :param type_mask: Coverage type filter (-1 for all) + :param callback: Callback function + :param userdata: User data passed to callback + :return: 0 on success, non-zero on error + + **Callback signature:** + + .. code-block:: c + + typedef int (*ucisCoverCBT)(void* userdata, ucisCoverT cover); + +History Operations +================== + +ucis_CreateHistoryNode +----------------------- + +.. c:function:: ucisHistoryNodeT ucis_CreateHistoryNode(ucisT db, ucisHistoryNodeT parent, const char* logicalname, const char* physicalname, ucisHistoryNodeKindT kind) + + Create a test history node. + + :param db: Database handle + :param parent: Parent history node or NULL + :param logicalname: Logical test name + :param physicalname: Physical file path or NULL + :param kind: History node kind (TEST, MERGE, TESTPLAN) + :return: New history node handle or NULL on error + +ucis_SetTestStatus +------------------ + +.. c:function:: int ucis_SetTestStatus(ucisT db, ucisHistoryNodeT node, ucisTestStatusT status) + + Set test execution status. + + :param db: Database handle + :param node: History node handle + :param status: Test status (OK, WARNING, FATAL) + :return: 0 on success, non-zero on error + +ucis_HistoryNodeIterate +------------------------ + +.. c:function:: int ucis_HistoryNodeIterate(ucisT db, ucisHistoryNodeKindT kind_mask, ucisHistoryNodeCBT callback, void* userdata) + + Iterate over history nodes. + + :param db: Database handle + :param kind_mask: Kind filter (-1 for all) + :param callback: Callback function + :param userdata: User data + :return: 0 on success, non-zero on error + +***************** +Type Definitions +***************** + +Opaque Handle Types +=================== + +.. code-block:: c + + typedef struct ucis_s* ucisT; // Database handle + typedef struct ucis_scope_s* ucisScopeT; // Scope handle + typedef struct ucis_cover_s* ucisCoverT; // Coverage item handle + typedef struct ucis_history_s* ucisHistoryNodeT; // History node handle + +Scope Types +=========== + +.. code-block:: c + + typedef enum { + UCIS_TOGGLE = 0x0001, // Toggle coverage + UCIS_BRANCH = 0x0002, // Branch coverage + UCIS_EXPR = 0x0004, // Expression coverage + UCIS_COND = 0x0008, // Condition coverage + UCIS_INSTANCE = 0x0010, // Design instance + UCIS_DU_MODULE = 0x0020, // Module design unit + UCIS_DU_ARCH = 0x0040, // Architecture design unit + UCIS_COVERGROUP = 0x1000, // Covergroup type + UCIS_COVERINSTANCE = 0x2000, // Covergroup instance + UCIS_COVERPOINT = 0x4000, // Coverpoint + UCIS_CROSS = 0x8000, // Cross coverage + UCIS_FSM = 0x400000, // Finite state machine + UCIS_ASSERT = 0x800000 // Assertion + } ucisScopeTypeT; + +Coverage Types +============== + +.. code-block:: c + + typedef enum { + UCIS_CVGBIN = 0x0001, // Covergroup bin + UCIS_STMTBIN = 0x0002, // Statement + UCIS_BRANCHBIN = 0x0004, // Branch + UCIS_EXPRBIN = 0x0008, // Expression + UCIS_CONDBIN = 0x0010, // Condition + UCIS_TOGGLEBIN = 0x0200, // Toggle + UCIS_ASSERTBIN = 0x0400, // Assertion + UCIS_FSMBIN = 0x0800, // FSM state/transition + UCIS_IGNOREBIN = 0x80000, // Ignore bin + UCIS_ILLEGALBIN = 0x100000, // Illegal bin + UCIS_DEFAULTBIN = 0x200000 // Default bin + } ucisCoverTypeT; + +Coverage Data +============= + +.. code-block:: c + + typedef struct { + ucisCoverTypeT type; // Coverage type + int data; // Hit count + int goal; // Goal value + int weight; // Weight + int at_least; // Minimum count for coverage + } ucisCoverDataT; + +Source Information +================== + +.. code-block:: c + + typedef struct { + const char* file; // Source file path + int line; // Line number + int token; // Token position + } ucisSourceInfoT; + +Source Types +============ + +.. code-block:: c + + typedef enum { + UCIS_NONE = 0, + UCIS_VHDL, + UCIS_VLOG, + UCIS_SV, + UCIS_PSL, + UCIS_E, + UCIS_VERA + } ucisSourceT; + +Test Status +=========== + +.. code-block:: c + + typedef enum { + UCIS_TESTSTATUS_OK = 0, // Test passed + UCIS_TESTSTATUS_WARNING = 1, // Test passed with warnings + UCIS_TESTSTATUS_FATAL = 2 // Test failed + } ucisTestStatusT; + +History Node Kinds +================== + +.. code-block:: c + + typedef enum { + UCIS_HISTORYNODE_TEST = 0x01, // Test run + UCIS_HISTORYNODE_MERGE = 0x02, // Merged coverage + UCIS_HISTORYNODE_TESTPLAN = 0x04 // Test plan node + } ucisHistoryNodeKindT; + +****************** +Complete Examples +****************** + +Basic Usage +=========== + +.. code-block:: c + + #include "ucis.h" + #include + + int main() { + // Create database + ucisT db = ucis_Open("example.ucisdb"); + if (!db) { + fprintf(stderr, "Failed to open database\n"); + return 1; + } + + // Create hierarchy + ucisScopeT top = ucis_CreateInstance(db, NULL, "top", NULL, 1, UCIS_VLOG); + ucisScopeT dut = ucis_CreateInstance(db, top, "dut", NULL, 1, UCIS_VLOG); + + // Create covergroup + ucisScopeT cg = ucis_CreateScope(db, dut, "addr_cg", NULL, 1, + UCIS_SV, UCIS_COVERGROUP, 0); + ucisScopeT cp = ucis_CreateScope(db, cg, "addr_cp", NULL, 1, + UCIS_SV, UCIS_COVERPOINT, 0); + + // Add bins + ucisCoverDataT data = {UCIS_CVGBIN, 0, 0, 1, 1}; + data.data = 25; + ucis_CreateNextCover(db, cp, "low", &data, NULL); + + data.data = 50; + ucis_CreateNextCover(db, cp, "high", &data, NULL); + + // Create test record + ucisHistoryNodeT test = ucis_CreateHistoryNode(db, NULL, "test1", + "test1.sv", + UCIS_HISTORYNODE_TEST); + ucis_SetTestStatus(db, test, UCIS_TESTSTATUS_OK); + + // Close database + ucis_Close(db); + + return 0; + } + +Iterating Scopes +================ + +.. code-block:: c + + typedef struct { + ucisT db; + int depth; + } IterCtx; + + int print_scope_cb(void* userdata, ucisScopeT scope) { + IterCtx* ctx = (IterCtx*)userdata; + + // Print with indentation + for (int i = 0; i < ctx->depth; i++) printf(" "); + printf("%s (type=0x%x)\n", + ucis_GetScopeName(ctx->db, scope), + ucis_GetScopeType(ctx->db, scope)); + + // Recurse to children + ctx->depth++; + ucis_ScopeIterate(ctx->db, scope, -1, print_scope_cb, ctx); + ctx->depth--; + + return 0; + } + + void print_hierarchy(ucisT db) { + IterCtx ctx = {db, 0}; + ucis_ScopeIterate(db, NULL, -1, print_scope_cb, &ctx); + } + +Using from Python +================= + +.. code-block:: python + + import ctypes + + # Load library + libucis = ctypes.CDLL("./libucis.so") + + # Define function signatures + libucis.ucis_Open.argtypes = [ctypes.c_char_p] + libucis.ucis_Open.restype = ctypes.c_void_p + + libucis.ucis_CreateInstance.argtypes = [ + ctypes.c_void_p, # db + ctypes.c_void_p, # parent + ctypes.c_char_p, # name + ctypes.c_void_p, # source + ctypes.c_int, # weight + ctypes.c_int # source_type + ] + libucis.ucis_CreateInstance.restype = ctypes.c_void_p + + libucis.ucis_Close.argtypes = [ctypes.c_void_p] + + # Use the API + db = libucis.ucis_Open(b"test.ucisdb") + top = libucis.ucis_CreateInstance(db, None, b"top", None, 1, 2) # UCIS_VLOG=2 + libucis.ucis_Close(db) + +************ +Performance +************ + +Optimization Tips +================= + +1. **Use transactions for bulk operations:** + + .. code-block:: c + + sqlite3_exec(db_conn, "BEGIN TRANSACTION", NULL, NULL, NULL); + // Create many scopes/covers + sqlite3_exec(db_conn, "COMMIT", NULL, NULL, NULL); + +2. **Cache handles when possible:** + + Store scope/cover handles rather than looking them up repeatedly. + +3. **Use type masks in iteration:** + + Filter iterations to specific types to reduce overhead. + +4. **Close database when done:** + + Call ucis_Close() to ensure all data is flushed. + +Typical Performance +=================== + +* Scope creation: ~10,000 scopes/second +* Coverage item creation: ~20,000 items/second +* Iteration: ~50,000 items/second +* Handle lookup: ~1,000,000 lookups/second + +********** +See Also +********** + +* :doc:`sqlite_api` - Python SQLite API +* :doc:`sqlite_schema_reference` - SQL schema details +* :doc:`ucis_c_api` - General UCIS C API reference diff --git a/doc/source/reference/python-api/c-style-api.rst b/doc/source/reference/python-api/c-style-api.rst new file mode 100644 index 0000000..5c26bff --- /dev/null +++ b/doc/source/reference/python-api/c-style-api.rst @@ -0,0 +1,10 @@ +################ +UCIS C-Style API +################ + +Placeholder for documenting the C-Style UCIS API implemented by PyUCIS + +.. automodule:: ucis.__init__ + :members: + :member-order: bysource + :undoc-members: \ No newline at end of file diff --git a/doc/source/reference/python-api/index.rst b/doc/source/reference/python-api/index.rst new file mode 100644 index 0000000..fb93509 --- /dev/null +++ b/doc/source/reference/python-api/index.rst @@ -0,0 +1,15 @@ +Python API +========== + +PyUCIS exposes two Python API styles: + +* **Object-oriented API** (:doc:`oo-api`) — the primary Python interface, + available for all backends (in-memory, SQLite, XML, YAML) +* **C-style API** (:doc:`c-style-api`) — a functional API that mirrors the + Accellera UCIS C standard + +.. toctree:: + :maxdepth: 1 + + oo-api + c-style-api diff --git a/doc/source/reference/python-api/oo-api.rst b/doc/source/reference/python-api/oo-api.rst new file mode 100644 index 0000000..67c90d9 --- /dev/null +++ b/doc/source/reference/python-api/oo-api.rst @@ -0,0 +1,372 @@ +######################## +UCIS Object-Oriented API +######################## + +The UCIS object-oriented API provides access to coverage databases through a +hierarchy of Python classes. This page documents every class in the public API, +organized from the top of the type hierarchy down to leaf types. + +.. contents:: + :local: + :depth: 2 + +Class Hierarchy +=============== + +.. code-block:: text + + Obj + ├── UCIS (Scope) ← database root; use MemFactory or SqliteUCIS + ├── Scope (Obj) + │ ├── CovScope + │ │ └── FuncCovScope + │ │ └── CvgScope + │ │ ├── Covergroup + │ │ │ └── (instances returned by createCovergroup) + │ │ ├── Coverpoint + │ │ │ └── Cross + │ │ ├── CvgBinScope + │ │ ├── IgnoreBinScope + │ │ └── IllegalBinScope + │ ├── DUScope ← design unit definition + │ └── InstanceScope ← design hierarchy instance + ├── HistoryNode ← test run / merge record + └── CoverItem ← bin (leaf coverage measurement) + + CoverData ← data container for a bin's hit count and goal + SourceInfo ← (file, line, token) tuple + TestData ← test run metadata passed to createHistoryNode + +Creating a Database +=================== + +All interaction with coverage data starts by obtaining a :class:`~ucis.ucis.UCIS` +object from one of the backend factories. + +In-Memory Backend +----------------- + +.. autoclass:: ucis.mem.mem_factory.MemFactory + :members: + :member-order: bysource + :undoc-members: + +SQLite Backend +-------------- + +.. autoclass:: ucis.sqlite.sqlite_ucis.SqliteUCIS + :members: + :member-order: bysource + :undoc-members: + +------------ + +Core Classes +============ + +UCIS +---- + +The database root. Returned by ``MemFactory.create()`` and ``SqliteUCIS(path)``. + +.. autoclass:: ucis.ucis.UCIS + :members: + :member-order: bysource + :undoc-members: + +Scope +----- + +Base class for all hierarchical containers. Every node in the design hierarchy and +the coverage model is a ``Scope``. The key operations — creating child scopes, +iterating child scopes, and accessing cover items — are defined here. + +.. autoclass:: ucis.scope.Scope + :members: + :member-order: bysource + :undoc-members: + +HistoryNode +----------- + +Records one test run or merge operation in the database's provenance tree. +Create via :meth:`~ucis.ucis.UCIS.createHistoryNode`; iterate via +:meth:`~ucis.ucis.UCIS.historyNodes`. + +.. autoclass:: ucis.history_node.HistoryNode + :members: + :member-order: bysource + :undoc-members: + +------------ + +Coverage Scope Hierarchy +========================= + +CovScope +-------- + +Base class for generic coverage scopes (code coverage types such as branch and +toggle). Extends :class:`~ucis.scope.Scope`. + +.. autoclass:: ucis.cov_scope.CovScope + :members: + :member-order: bysource + :undoc-members: + +FuncCovScope +------------ + +Base class for functional coverage scopes. Extends :class:`~ucis.cov_scope.CovScope`. + +.. autoclass:: ucis.func_cov_scope.FuncCovScope + :members: + :member-order: bysource + :undoc-members: + +CvgScope +-------- + +Base class for covergroup-level scopes (groups, coverpoints, crosses). +Provides shared attributes such as ``at_least``, ``auto_bin_max``, and +``comment``. Extends :class:`~ucis.func_cov_scope.FuncCovScope`. + +.. autoclass:: ucis.cvg_scope.CvgScope + :members: + :member-order: bysource + :undoc-members: + +Covergroup +---------- + +A SystemVerilog or SystemC covergroup type definition. Contains +:class:`~ucis.coverpoint.Coverpoint`, :class:`~ucis.cross.Cross`, and +per-instance coverage children. + +Create via :meth:`~ucis.scope.Scope.createCovergroup`. + +.. autoclass:: ucis.covergroup.Covergroup + :members: + :member-order: bysource + :undoc-members: + +Coverpoint +---------- + +A coverpoint measuring coverage of a single variable or expression. +Contains bins created via :meth:`~ucis.coverpoint.Coverpoint.createBin`. + +Create via :meth:`~ucis.covergroup.Covergroup.createCoverpoint`. + +.. autoclass:: ucis.coverpoint.Coverpoint + :members: + :member-order: bysource + :undoc-members: + +Cross +----- + +Cross-product coverage of two or more coverpoints. Extends +:class:`~ucis.coverpoint.Coverpoint`. + +Create via :meth:`~ucis.covergroup.Covergroup.createCross`. + +.. autoclass:: ucis.cross.Cross + :members: + :member-order: bysource + :undoc-members: + +CvgBinScope +----------- + +Normal bin scope for SystemVerilog covergroups. + +.. autoclass:: ucis.cvg_bin_scope.CvgBinScope + :members: + :member-order: bysource + :undoc-members: + +IgnoreBinScope +-------------- + +Scope representing a SystemVerilog ``ignore_bins`` declaration. + +.. autoclass:: ucis.ignore_bin_scope.IgnoreBinScope + :members: + :member-order: bysource + :undoc-members: + +IllegalBinScope +--------------- + +Scope representing a SystemVerilog ``illegal_bins`` declaration. + +.. autoclass:: ucis.illegal_bin_scope.IllegalBinScope + :members: + :member-order: bysource + :undoc-members: + +------------ + +Design Hierarchy Scopes +======================= + +DUScope +------- + +Design unit (module/entity/package) definition. DU scopes act as templates +for instances. Create via :meth:`~ucis.scope.Scope.createScope` with +:attr:`~ucis.scope_type_t.ScopeTypeT.DU_MODULE` (or other ``DU_*`` type). + +.. autoclass:: ucis.du_scope.DUScope + :members: + :member-order: bysource + :undoc-members: + +InstanceScope +------------- + +A design hierarchy instance. Points back to its design unit via +:meth:`~ucis.instance_scope.InstanceScope.getInstanceDu`. Create via +:meth:`~ucis.scope.Scope.createInstance`. + +.. autoclass:: ucis.instance_scope.InstanceScope + :members: + :member-order: bysource + :undoc-members: + +------------ + +Cover Items +=========== + +CoverItem +--------- + +Base class for bins — the leaf-level coverage measurements within +coverpoints, crosses, and code coverage scopes. + +.. autoclass:: ucis.cover_item.CoverItem + :members: + :member-order: bysource + :undoc-members: + +CoverData +--------- + +Holds the hit count, goal, and status flags for one cover item. +Passed to :meth:`~ucis.coverpoint.Coverpoint.createBin` and +returned by :meth:`~ucis.obj.Obj.getCoverData`. + +.. autoclass:: ucis.cover_data.CoverData + :members: + :member-order: bysource + :undoc-members: + +------------ + +Value Objects +============= + +SourceInfo +---------- + +Bundles a :class:`~ucis.file_handle.FileHandle` with a line number and token +offset to identify where a scope or bin was declared in source. + +.. autoclass:: ucis.source_info.SourceInfo + :members: + :member-order: bysource + :undoc-members: + +TestData +-------- + +Carries test metadata (status, tool, date, seed, …) and is passed to +:meth:`~ucis.history_node.HistoryNode.setTestData`. + +.. autoclass:: ucis.test_data.TestData + :members: + :member-order: bysource + :undoc-members: + +------------ + +Enumerations +============ + +ScopeTypeT +---------- + +Identifies the type of every scope in the hierarchy. Used as a filter mask +in :meth:`~ucis.scope.Scope.scopes` and as a required argument to scope +creation methods. + +.. autoclass:: ucis.scope_type_t.ScopeTypeT + :members: + :member-order: bysource + :undoc-members: + +CoverTypeT +---------- + +Identifies the coverage type of every cover item (bin). Used as a filter +mask in :meth:`~ucis.scope.Scope.coverItems`. + +.. autoclass:: ucis.cover_type_t.CoverTypeT + :members: + :member-order: bysource + :undoc-members: + +CoverFlagsT +----------- + +Bit flags stored in a :class:`~ucis.cover_data.CoverData` that control +data precision and indicate which optional fields are valid. + +.. autoclass:: ucis.cover_flags_t.CoverFlagsT + :members: + :member-order: bysource + :undoc-members: + +HistoryNodeKind +--------------- + +Discriminates test-run nodes (``TEST``) from merge nodes (``MERGE``) in the +database history tree. + +.. autoclass:: ucis.history_node_kind.HistoryNodeKind + :members: + :member-order: bysource + :undoc-members: + +TestStatusT +----------- + +Pass/fail status recorded on a test history node. + +.. autoclass:: ucis.test_status_t.TestStatusT + :members: + :member-order: bysource + :undoc-members: + +SourceT +------- + +HDL source language of a scope (``VLOG``, ``SV``, ``VHDL``, etc.). + +.. autoclass:: ucis.source_t.SourceT + :members: + :member-order: bysource + :undoc-members: + +FlagsT +------ + +Scope-level flags controlling coverage enablement, exclusion, and other +scope behaviours. Passed as the ``flags`` argument to scope creation methods. + +.. autoclass:: ucis.flags_t.FlagsT + :members: + :member-order: bysource + :undoc-members: diff --git a/doc/source/reference/report-formats/html-report-format.rst b/doc/source/reference/report-formats/html-report-format.rst new file mode 100644 index 0000000..74f516f --- /dev/null +++ b/doc/source/reference/report-formats/html-report-format.rst @@ -0,0 +1,578 @@ +########################### +HTML Coverage Report Format +########################### + +The HTML coverage report format generates a single-file, interactive HTML report that provides comprehensive visualization and analysis of UCIS coverage data. The report can be opened directly in any modern web browser without requiring a web server or external dependencies. + +**Key Features:** + +* **Single-File Portability** - All data, code, and styles embedded in one HTML file +* **Interactive Navigation** - Expandable hierarchical tree with filtering and search +* **D3.js Visualizations** - Pie charts, bar charts, and treemaps for coverage analysis +* **Coverpoint Bin Details** - View individual bins with hit counts, goals, and status +* **Zero Dependencies** - JavaScript libraries loaded from CDN (works offline if cached) +* **Responsive Design** - Professional UI that works on desktop and tablet +* **Export Friendly** - Easy to share via email, archive, or web hosting + +Generating HTML Reports +======================= + +Command Line +------------ + +The ``pyucis report`` command can generate HTML reports using the ``-of html`` option: + +.. code-block:: bash + + # Basic HTML report + pyucis report coverage.xml -of html -o report.html + + # From SQLite database + pyucis report coverage.ucis -of html -o report.html + + # From YAML + pyucis report coverage.yaml -of html -o report.html + +The generated HTML file can be opened directly in any browser: + +.. code-block:: bash + + firefox report.html + # or + chrome report.html + # or + open report.html # macOS + +Python API +---------- + +You can generate HTML reports programmatically using the ``HtmlFormatter`` class: + +.. code-block:: python + + from ucis import UCIS + from ucis.formatters.format_html import HtmlFormatter + + # Load database + db = UCIS.load("coverage.xml") + + # Create formatter + formatter = HtmlFormatter( + include_source=True, # Include source file info + compress=False, # Don't compress data (better for debugging) + theme='light' # Use light theme + ) + + # Generate report + with open("report.html", "w") as f: + formatter.format(db, f) + +Report Features +=============== + +Summary Dashboard +----------------- + +The summary view provides high-level coverage metrics: + +* **Total Coverage Percentage** - Overall coverage across all items +* **Total Items** - Count of all coverage items (bins, statements, etc.) +* **Covered Items** - Count of items that have been hit +* **Uncovered Items** - Count of items that have not been hit +* **Coverage by Type** - Breakdown by coverage type (functional, line, branch, etc.) +* **Progress Bar** - Visual representation of overall coverage + +Hierarchical Navigation +----------------------- + +The hierarchy view displays the complete design/verification structure: + +**Tree Features:** + +* **Expandable/Collapsible Nodes** - Click arrows (▶/▼) to show/hide children +* **Expand All / Collapse All** - Buttons to quickly navigate deep hierarchies +* **Type-Specific Icons** - Visual distinction between modules (📦), covergroups (📋), coverpoints (🎯), etc. +* **Scope Type Labels** - Shows type in parentheses, e.g., "my_covergroup (COVERGROUP)" +* **Coverage Indicators** - Color-coded percentages (green ≥80%, orange 50-80%, red <50%) +* **4-Level Deep Support** - Handles nested hierarchies up to 4 levels + +**Filtering:** + +* **Search** - Real-time text search across scope names +* **Status Filter** - Filter by all/covered/uncovered/partial coverage +* **Coverage Threshold** - Show only scopes meeting minimum coverage percentage +* **Reset** - Clear all filters with one click + +Coverpoint Bin Details +----------------------- + +When you click on a coverpoint in the hierarchy, a detailed table displays all bins: + +**Bin Table Columns:** + +1. **Bin Name** - Identifier for the bin (monospace font) +2. **Type** - Badge showing bin type: + + * ``bin`` (blue) - Regular coverage bin + * ``ignore_bin`` (orange) - Excluded from coverage calculations + * ``illegal_bin`` (red) - Should never be hit + +3. **Hits** - Number of times the bin was hit (formatted with thousands separators) +4. **Goal** - Target hit count (at_least threshold) +5. **Status** - Badge showing bin status: + + * ``covered`` (green) - Hit count ≥ goal + * ``uncovered`` (red) - Hit count < goal + * ``ignored`` (gray) - Excluded bin + * ``illegal`` (red) - Illegal bin was hit (error!) + * ``ok`` (green) - Illegal bin not hit + +6. **Coverage** - Mini progress bar + percentage showing hits/goal ratio + +**Visual Features:** + +* **Row Highlighting** - Green background for covered bins, red for illegal bins that were hit +* **Hover Effects** - Subtle highlighting when hovering over rows +* **Sortable** - (Future: Click headers to sort) +* **Color-Coded Progress Bars** - Green (covered), orange (partial), red (uncovered) + +Interactive Visualizations +--------------------------- + +The Charts tab provides three D3.js-powered visualizations: + +Pie Chart: Coverage by Type +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Displays coverage percentage breakdown by type (functional, line, branch, toggle, etc.): + +* **Color-Coded Segments** - Each type has a distinct color +* **Interactive Tooltips** - Hover to see exact percentages +* **Smart Labels** - Only show labels for segments >5% to avoid clutter +* **Hover Effects** - Segments highlight on mouseover + +Bar Chart: Top Coverage Gaps +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Shows the 10 scopes with the lowest coverage: + +* **Horizontal Bars** - Length represents coverage percentage +* **Color-Coded** - Red (<50%), orange (50-80%), green (≥80%) +* **Labeled Axes** - Clear percentage scale and scope names +* **Interactive Tooltips** - Hover for scope name and exact percentage +* **Priority Identification** - Focus on items that need the most work + +Treemap: Hierarchical Coverage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Visualizes the entire design hierarchy as nested rectangles: + +* **Rectangle Size** - Proportional to scope weight (importance) +* **Rectangle Color** - Based on coverage percentage: + + * Red (0-50%) - Low coverage, needs attention + * Orange (50-80%) - Moderate coverage + * Green (80-100%) - Good coverage + +* **Labels** - Scope name and coverage % shown for larger cells +* **Interactive Tooltips** - Hover for detailed information +* **Hover Highlighting** - Border thickness increases on mouseover +* **Quick Overview** - See entire project status at a glance + +Coverage Gaps View +------------------ + +Shows all scopes with less than 100% coverage: + +* **Filtered List** - Only incomplete coverage items +* **Quick Identification** - Find areas that need more verification +* **Coverage Percentages** - See how close each item is to completion + +By Type View +------------ + +Lists coverage statistics grouped by coverage type: + +* **Functional Coverage** - Covergroups and coverpoints +* **Code Coverage** - Line, branch, toggle, block, etc. +* **Organized Display** - Easy to see strengths and weaknesses + +Technical Details +================= + +File Structure +-------------- + +The HTML report is completely self-contained: + +.. code-block:: html + + + + + UCIS Coverage Report + + + + + + + + + + + + + + + + + +Data Format +----------- + +Coverage data is embedded as JSON within a ``