Skip to content

Device models, simulator integration and the firmware test harness - #23

Open
pratheesh wants to merge 45 commits into
TexasInstruments:mainfrom
pratheesh:feat/device-models-simulator
Open

pratheesh wants to merge 45 commits into
TexasInstruments:mainfrom
pratheesh:feat/device-models-simulator

Conversation

@pratheesh

@pratheesh pratheesh commented Oct 24, 2026 •

Copy link
Copy Markdown

Stacked pull request. Depends on #22. GitHub cannot base a pull request on another fork branch, so until it merges the diff here also contains its commits. The 16 commits of this pull request alone: feat/block-infrastructure...feat/device-models-simulator. It will be rebased onto main once it merges.

Summary

Builds on the shared-infrastructure pull request. Adds behavioural device models, the Device Model block, device
bindings from SysConfig to TI pru-simulator, the GUI simulator support for attached devices, and the Python harness
that builds a block's macro with clpru and runs the ELF on TI pru-simulator. Most firmware-backed tests for the
allocator and existing-block fixes of the previous pull request live here, because they need this harness.

What changes

  • New Python package pru_device_models/ (repository root): device_model.py (base class), SPI ADC, step/dir driver,
    WS2812 string, MDIO PHY, Hall sensor, dual OSSD emitter, quadrature/index encoder, SSI/EnDat encoder, BiSS line
    model, buscosim.py (independent pin-trace decoders) and waveform_player.py (cycle-keyed GPI stimulus). The name
    is chosen so it does not shadow the pru-simulator checkout's own top-level packages (core, perif, pru_io),
    which the tests import in the same process; tests/test_package_names.py checks both the names and an
    import-model-then-simulator sequence in one interpreter.
  • scripts/sim/: elf_cosim.py (build a block macro or design with clpru, run it on TI pru-simulator in a closed pin
    loop; optional constant-table override and IEP_CONSTANTS for firmware that programs the IEP through c26; optional
    IEP-at-core-clock), device_bindings.py, run_bound_devices.py, extract_device_bindings.py, gui_run.py,
    live_view.py, and node helpers (emit_block_asm.js, crc_dut.js, lut_cycles.js, ...).
    tools/gpi_stimulus_runner.py. Root conftest.py: a missing simulator checkout, or a checkout without a device
    model a test imports, is reported as SKIPPED with the reason.
  • New SysConfig files: utils/device_model_block, common/device_model_table.js, common/pru_ti_run.js (GUI "Run on
    TI pru-simulator"), common/pru_device_bindings.json.xdt, common/simulation/device_bus.js,
    common/simulation/device_models.js; the Device Model block is registered on AM243x, AM64x and AM261x.
  • Changes to TI's existing pru_blocks_static_module.syscfg.js and pru_syscfg.asm.xdt: Simulation Settings device
    fields per GPI pin, the device-binding manifest, reader/register annotation for gmake sim, and the GUI preview
    banner for attached devices. Device-binding errors are logged against the module instance SysConfig passes to
    validate() (SysConfig's report.logError rejects any other object); scripts/sim/test_device_binding_syscfg.js
    covers it (on the commit before the change 14 passed, 1 failed; now 15 passed).
  • Display names follow SysConfig's convention (Title Case, at most 36 characters). The Device Model block takes each
    field's display name from displayTitle() in device_model_table.js; configuration names (the keys saved in
    .syscfg files) are unchanged. scripts/sim/test_device_model_titles.js applies the rule to every field the table
    produces. The "Open Live Web View After Run" option keeps its detail in the long description, so its tooltip stays
    within SysConfig's length limit.
  • Behaviour changes to TI's existing GUI simulator common/simulation/pru_core.js:
    • word registers: Rn.wK is bits 8K+15..8K (shift 8K, was 16K, which made every .w1 access wrong);
    • sub-register writes leave the register as an unsigned 32-bit value;
    • LBCO is executed as LBBO, SBCO as SBBO, with c26 = IEP (0x0002E000) and c28 = 0; LBBO results are
      unsigned;
    • an IEP register model (GLOBAL_CFG, COUNT, CMP_CFG, CMP_STATUS W1C, 64-bit CMPj pairs) at the AM243x offsets;
    • ZERO, FILL, XIN/XOUT for the MAC (signed 32x32) and the scratchpad (bounds-checked); MULL is an error;
    • HALT with devices attached idles the bus until the cycle budget instead of jumping the cycle counter;
    • R30 starts at the bus idle level when devices are attached;
    • MAC, MACU and WBC used as instructions stop the run with an error (main skipped them silently); macro calls
      and directives are still skipped.
      tests/test_gui_simulator_core.py covers the word-register shift, unsigned sub-register writes and the
      MAC/MACU/WBC error: 9 passed on this branch; on main's pru_core.js 8 of 9 fail.
  • tests/fixtures/firmware/ (minimal main.asm that jumps to the generated code and halts at
    sysconfig_generated_end, plus the AM243x PRU0 linker.cmd) so the ELF tests of the allocator fixes run without
    an example project. Its linker.cmd places .udmem and .usmem like the example linker files.
  • Tests (tests/, scripts/sim/): device bindings, models and catalogue, GUI run glue, waveform player, BiSS line,
    crc and access-LUT index scaling, SPI read/transfer zero-extend, loop accumulators, Load Constant width,
    register-pool exhaustion, fan-out register alias, nested hardware LOOP, SPI CS timing, board variant builds,
    elf_cosim constant override, and tests/test_spi_sclk_duty.py: every pru_spi_read / write / transfer controller
    variant (four modes, MSB and LSB first) built with the block's own delay components and run on TI pru-simulator
    against a model peripheral; each SCLK high and low phase must equal the configured width and the word read must
    match. Without the SPI read fix of the previous pull request the MODE1 and MODE3 LSB read cases fail (2 of 24).

How it was tested

Tools: node; SysConfig 1.28 (SYSCFG_PATH); TI PRU CGT 2.3.3 (CGT_TI_PRU_PATH); TI pru-simulator checkout
(PRU_SIMULATOR_PATH, run here against its main branch 544d5ea).

python -m pytest tests scripts/sim -q -p no:cacheprovider
for t in scripts/sim/test_*.js; do node "$t"; done
  • with SysConfig, clpru and PRU_SIMULATOR_PATH: 340 passed, 0 failed, 25 skipped;
  • without PRU_SIMULATOR_PATH: 226 passed, 0 failed, 139 skipped;
  • with PRU_SIMULATOR_PATH, gmake on PATH and a repository-root imports.mak: 366 passed, 0 failed, 18 skipped;
  • the five node test scripts: all pass.

The 25 skips with every tool present: 18 scripts/sim/test_device_bindings.py cases (17 whose device model is not
in pru-simulator main: pru_io.ssi_encoder, quadrature_encoder, endat_encoder, bissc_device_model,
bissline_device_model, sd_modulator_device, uart_device; one declared-sink case); 7 cases of
tests/test_spi_cs_timing_elf.py (4) and tests/test_board_variant_builds.py (3) that need gmake and a
repository-root imports.mak, which is not part of a default checkout. With gmake and an imports.mak they run and
pass; the 18 skips that remain are the device-binding cases.

SysConfig Sanity Tests: the eight contexts of make syscfg-tests-am243x, syscfg-tests-am64x and
syscfg-tests-am261x, each run as the makefile runs it with SysConfig 1.27.0 (the version the workflow installs):
Total 0 error(s) and no "failed" line in every context.

Known limitations

  • The Device Model kinds whose model lives in pru-simulator (ssi, bissc, endat, quadrature, uart,
    sigma_delta, tca9538) need a pru-simulator revision that ships those models; on main they are skipped.
  • The pru_device_models models (SPI ADC, step/dir, WS2812, MDIO PHY) use a tick() contract and are refused by
    pru-simulator's device bus by name; they are used by this repository's closed-loop tests.
  • pru-simulator main maps c26 to 0x00010000 in config/constants_am243x.cfg; tests of IEP-programming blocks pass
    elf_cosim.IEP_CONSTANTS so c26 reaches the simulator's IEP model, as on the device.
  • Nothing here is verified on silicon; all device behaviour is simulated.

🤖 Generated with Claude Code

…module


Register allocator:
- release a block's registers after its last data consumer, including
  values produced outside a loop and read inside it
- keep pre-initialized loop values in their own register and support
  explicit loop accumulator bindings and exported loop results
- route each consumer input from the output port it is wired to and
  refuse connections to ports that own no register
- record register-pool exhaustion per block so validation can name it
- reserve user-typed registers that blocks emit verbatim and report
  overlapping ones
- give multi-result macros one destination register per output
- keep 64-bit (two register) sources and outputs

Static module and templates:
- report allocation failures, pinned-register conflicts, unconnected
  required inputs, invalid port connections, loop/container boundary
  violations and macro arity mismatches at validation time
- program CTPPR0 so c28 points at shared RAM when a block uses c28, and
  drive SPI controller CS pins to their idle level, at every entry into
  generated code
- warn in the GUI when a GPO/GPI pad is shared or a GPO has two drivers
- gate blocks that need a hardware widget on the device capability table
- define TEMP_REG3/TEMP_REG4 (R26/R27) for macros
- expand multi-line instructions in the simulator path

New shared scripts: pru_reserved_names.js (clpru reserved identifiers),
pru_spi_timing.js (SPI delay limits and IRAM budget), pru_device_caps.js
(per-SoC hardware widgets), block_control_flow_data.js.
- CRC16/CRC32: scale the table index to the entry size before the load
  (the byte offset does not fit the LBBO offset operand); 13 cycles
- Access Lookup Table: scale the index for ushort/uint tables (7 cycles)
- PRU GPI: build the bit mask in the result register so pins above 7
  work; 3 cycles, 4-byte output
- PRU SPI Read/Transfer: clear the result register before sampling so
  short packets are zero-extended; reserve the whole register for
  17-24 bit packets; one extra overhead cycle
- PRU SPI Read/Write/Transfer: refuse CS/data delays above 256 cycles,
  warn when the SPI blocks exceed the PRU IRAM budget
- If/Else: an unconnected true/false branch is an error (the generated
  code would reference an undefined label)
- Load Constant: optional explicit output width
- Loop: reject a hardware LOOP nested in a finite loop body; add
  exported result blocks and accumulator bindings
- Delay: document the exact cycle count and the nesting restriction
- Memory Access: warn when two blocks share one auto-created Memory
  Variable
- CRC, Lookup Table, Memory Variable, Group, If/Else: reject symbols that
  clash with clpru reserved identifiers
- PRU GPI/GPO and SPI blocks: declare the pins they use (getPinUsage)
- tests/test_syscfg_add_instance.py: every block module adds an instance
  through the SysConfig CLI (skipped when SysConfig is not installed)
- tests/test_fail_closed_gating.py: the device-capability gate fails
  closed on every degraded path
- tests/test_shared_memvar_rename.py, tests/test_conditional_unconnected_branch.py
- scripts/static_module_validate_runner.js, scripts/block_validate_runner.js,
  scripts/shared_memvar_runner.js: run block validators under node
… test

The register allocator now releases a register once its last reader has run,
so main.asm can no longer rely on a released register still holding its value.
Name the registers once in main.asm, and keep the received frame live on the
receiving core by reading it into an otherwise unused block output.

Add a firmware test that runs the example on the simulator for both boards and
both cores, checking the stored data byte and the CRC match/mismatch result.
The MODE1 LSB loop advanced its bit counter in the low half, where the delay
formulas assume none, so SCLK ran one cycle short high and one cycle long low.
The MODE3 LSB loop sampled a 1 bit one instruction slower than a 0 bit, so
its high half grew by a cycle on every 1. Both variants now count in the half
the MSB variant counts in, and both sample paths take two instructions.
The Memory Variable block reserves buffers in .udmem (data RAM) and .usmem
(shared RAM). With no rule for either section clpru placed them in
instruction RAM after .text. Each example linker file now places .udmem in
the data RAM its .bss uses and .usmem in PRU_SHAREDMEM, and a test checks
every tracked linker file.
Behavioural peripheral models (perif/, core/device_model.py, pru_io/), the
in-tool device bus and device models used by the Simulation Settings GPI
"Attached Device Model" mode and the Device Model block, the device-binding
manifest emitted into pru_syscfg.asm, and the TI pru-simulator run path
(scripts/sim: ELF co-simulation, bound-device runner, Run on TI pru-simulator
launcher). The static module gains the device-mode GPI fields, the device-bus
preview, the pad check between attached devices and PRU outputs, and the
TI pru-simulator result banner.
Tests for the device models and bindings, the Run on TI pru-simulator
launcher, and regression tests of the shared allocator and existing blocks
that run the generated firmware on TI pru-simulator (CRC/LUT index scaling,
SPI zero-extension, loop nesting, register-pool exhaustion, loop-carried
accumulators, load-constant width). A repository-level conftest reports
tests that need a TI pru-simulator checkout as skipped, with the reason,
when none is available.
…hey do not shadow the pru-simulator's; firmware test fixture; GUI simulator register tests; neutral wording
validate() passed a copy of the instance, with the companion pins defaulted
from the bound block, to validateDeviceInput, which logged errors against that
copy. SysConfig's report.logError throws "Unknown instance" for any object it
does not own, so a device-mode GPI with a refused setting aborted validation,
code generation and serialization. The effective pins are now passed
separately and errors are logged against the real instance.
SysConfig display names are Title Case, at most 36 characters. The Device
Model block now takes each field's display name from displayTitle() in the
device model table: an explicit title where the label is a sentence, else the
label converted word by word. The label itself stays the noun used in
messages. The live web view settings get Title Case names and the long
tooltip moves to the long description.
…dths in every mode and bit order

Each read, write and transfer macro variant is built with the block's own
delay components, run on TI pru-simulator against a model peripheral, and
every SCLK phase inside the packet is checked, along with the word read.
@pratheesh-ti

Copy link
Copy Markdown
Collaborator

/agentic_describe

@pratheesh-ti

Copy link
Copy Markdown
Collaborator

/agentic_review

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add device models and firmware-backed PRU simulation

✨ Enhancement 🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Add typed device bindings and closed-loop models to simulate attached hardware.
Diagram

graph TD
  A["SysConfig design"] --> B["Binding manifest"] --> C["Firmware runner"] --> D["TI simulator"] --> E["Device models"]
  D --> F["Pin traces"] --> G["Protocol verdict"]
  E --> G
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use TI simulation exclusively
  • ➕ Avoids maintaining parallel JavaScript device behavior.
  • ➖ Loses the in-tool preview and requires an external simulator for interactive feedback.

Recommendation: Keep TI simulation authoritative for firmware verdicts and JavaScript simulation as a limited preview. Review the stacked infrastructure separately after #22 merges; the current combined diff obscures which changes belong to this branch.

Files changed (145) +22729 / -205

Enhancement (35) +11976 / -21
block_control_flow_data.jsClassify block control flow +33/-0

Classify block control flow

• Provides block classifications for pin-sharing and competing-output checks.

.metadata/sysconfig/.meta/pru_blocks/common/block_control_flow_data.js

device_model_table.jsDefine the typed device catalogue +664/-0

Define the typed device catalogue

• Centralizes device kinds, pin roles, parameter fields, and manifest conversion used by SysConfig.

.metadata/sysconfig/.meta/pru_blocks/common/device_model_table.js

pru_blocks_static_module.syscfg.jsConnect simulation settings to device bindings +1593/-18

Connect simulation settings to device bindings

• Adds device configuration, binding generation, reader resolution, GUI simulation controls, and broader allocation and design validation.

.metadata/sysconfig/.meta/pru_blocks/common/pru_blocks_static_module.syscfg.js

pru_device_bindings.json.xdtEmit device-binding manifest +27/-0

Emit device-binding manifest

• Writes configured bindings and allocator-selected reader registers to a generated JSON file.

.metadata/sysconfig/.meta/pru_blocks/common/pru_device_bindings.json.xdt

pru_device_caps.jsCentralize PRU hardware capabilities +144/-0

Centralize PRU hardware capabilities

• Defines device-family widget availability for validating blocks against supported hardware.

.metadata/sysconfig/.meta/pru_blocks/common/pru_device_caps.js

pru_syscfg.asm.xdtAnnotate generated assembly for simulation +27/-0

Annotate generated assembly for simulation

• Embeds bindings and a design digest, defines temporary registers, and initializes constant-table and SPI state at code entry.

.metadata/sysconfig/.meta/pru_blocks/common/pru_syscfg.asm.xdt

pru_syscfg.inc.xdtExpose two additional temporary registers +2/-0

Expose two additional temporary registers

• Defines TEMP_REG3 and TEMP_REG4 for generated macros.

.metadata/sysconfig/.meta/pru_blocks/common/pru_syscfg.inc.xdt

pru_ti_run.jsAdd SysConfig TI-run integration +287/-0

Add SysConfig TI-run integration

• Computes design digests and interprets launcher results with fail-closed verdict handling.

.metadata/sysconfig/.meta/pru_blocks/common/pru_ti_run.js

device_bus.jsModel bidirectional device pins +192/-0

Model bidirectional device pins

• Resolves PRU and device drives each cycle, including open-drain behavior and contention faults.

.metadata/sysconfig/.meta/pru_blocks/common/simulation/device_bus.js

device_models.jsAdd in-tool behavioral device models +1626/-0

Add in-tool behavioral device models

• Implements JavaScript models and a supported-device catalogue for interactive simulation, with explicit refusal of unsupported models.

.metadata/sysconfig/.meta/pru_blocks/common/simulation/device_models.js

load_constant_block.syscfg.jsAllow explicit constant output widths +37/-3

Allow explicit constant output widths

• Adds an output-width setting and rejects values that cannot fit the selected width.

.metadata/sysconfig/.meta/pru_blocks/data_handling/load_constant_block.syscfg.js

device_model_block.syscfg.jsAdd declarative Device Model block +270/-0

Add declarative Device Model block

• Exposes typed model pins and parameters and contributes bindings without generating firmware.

.metadata/sysconfig/.meta/pru_blocks/utils/device_model_block.syscfg.js

pru_blocks_am243x.syscfg.jsRegister AM243x Device Model block +1/-0

Register AM243x Device Model block

• Makes the new block available in the AM243x catalogue.

.metadata/sysconfig/.meta/soc/pru_blocks_am243x.syscfg.js

pru_blocks_am261x.syscfg.jsRegister AM261x Device Model block +1/-0

Register AM261x Device Model block

• Makes the new block available in the AM261x catalogue.

.metadata/sysconfig/.meta/soc/pru_blocks_am261x.syscfg.js

pru_blocks_am64x.syscfg.jsRegister AM64x Device Model block +1/-0

Register AM64x Device Model block

• Makes the new block available in the AM64x catalogue.

.metadata/sysconfig/.meta/soc/pru_blocks_am64x.syscfg.js

__init__.pyCreate nonconflicting model package +5/-0

Create nonconflicting model package

• Defines the repository-owned Python device-model namespace.

pru_device_models/init.py

bissline_device_model.pyModel a BiSS line encoder +390/-0

Model a BiSS line encoder

• Implements cycle-based BiSS line responses and protocol event and fault reporting.

pru_device_models/bissline_device_model.py

device_model.pyDefine the Python device contract +15/-0

Define the Python device contract

• Provides the shared base interface for cycle-driven device models.

pru_device_models/device_model.py

hall_sensor.pyModel Hall sensor signals +256/-0

Model Hall sensor signals

• Generates Hall sensor pin behavior and observable events.

pru_device_models/hall_sensor.py

mdio_phy_model.pyModel an MDIO PHY +278/-0

Model an MDIO PHY

• Responds to MDIO bus activity and records protocol behavior.

pru_device_models/mdio_phy_model.py

ossd_emitter.pyModel dual OSSD outputs +233/-0

Model dual OSSD outputs

• Emits dual-channel OSSD signals for firmware and decoder tests.

pru_device_models/ossd_emitter.py

quadrature_index_encoder.pyModel quadrature and index signals +120/-0

Model quadrature and index signals

• Produces A/B/index encoder transitions based on cycle and position.

pru_device_models/quadrature_index_encoder.py

spi_adc.pyModel an SPI ADC +140/-0

Model an SPI ADC

• Responds to SPI controller pins and records ADC transactions and faults.

pru_device_models/spi_adc.py

ssi_endat_encoder.pyModel SSI and EnDat encoders +281/-0

Model SSI and EnDat encoders

• Implements clocked absolute-encoder behavior for SSI and EnDat.

pru_device_models/ssi_endat_encoder.py

step_dir_driver.pyObserve step/direction output +99/-0

Observe step/direction output

• Checks PRU-driven step and direction signals as a sink device.

pru_device_models/step_dir_driver.py

waveform_player.pyReplay cycle-keyed GPI stimuli +185/-0

Replay cycle-keyed GPI stimuli

• Provides reusable pin-input waveforms synchronized to simulated cycles.

pru_device_models/waveform_player.py

ws2812_string.pyObserve WS2812 output +138/-0

Observe WS2812 output

• Decodes PRU-driven LED-string signaling as a sink device.

pru_device_models/ws2812_string.py

device_bindings.pyValidate and instantiate device bindings +544/-0

Validate and instantiate device bindings

• Translates manifests into Python models and refuses invalid pin roles, kinds, or parameters.

scripts/sim/device_bindings.py

extract_device_bindings.pyExtract embedded assembly bindings +23/-0

Extract embedded assembly bindings

• Retrieves generated device-binding records for simulation tools.

scripts/sim/extract_device_bindings.py

gui_run.pyBridge GUI runs to built firmware +668/-0

Bridge GUI runs to built firmware

• Regenerates and builds saved designs, rejects stale digests, runs bound models, and returns a structured verdict.

scripts/sim/gui_run.py

gui_run_launcher.jsLaunch firmware simulation from SysConfig +89/-0

Launch firmware simulation from SysConfig

• Connects the GUI command to the Python run wrapper.

scripts/sim/gui_run_launcher.js

live_view.pyExpose a live TI simulator view +467/-0

Expose a live TI simulator view

• Attaches bound devices to the upstream dashboard and adds verdict, waveform, and binding endpoints.

scripts/sim/live_view.py

run_bound_devices.pyJudge firmware against attached devices +415/-0

Judge firmware against attached devices

• Runs a built program with manifest models and distinguishes passing, failing, refused, and unchecked results.

scripts/sim/run_bound_devices.py

simulator.jsAdd scripted JavaScript simulator wrapper +2481/-0

Add scripted JavaScript simulator wrapper

• Loads TI COFF output and supports stepping, watchpoints, and waveform export around the in-tool core.

scripts/simulator.js

gpi_stimulus_runner.pyRun GPI stimulus against firmware +244/-0

Run GPI stimulus against firmware

• Applies configured GPI waveforms while executing a PRU program in simulation.

tools/gpi_stimulus_runner.py

Bug fix (24) +1981 / -183
crc_block.syscfg.jsCorrect CRC lookup addressing +44/-13

Correct CRC lookup addressing

• Scales CRC16/CRC32 table indices to byte offsets and validates assembler-reserved symbols.

.metadata/sysconfig/.meta/pru_blocks/application_specific/crc_block.syscfg.js

pru_reserved_names.jsValidate assembler-reserved names +160/-0

Validate assembler-reserved names

• Shares clpru identifier rules across blocks that emit labels or symbols.

.metadata/sysconfig/.meta/pru_blocks/common/pru_reserved_names.js

pru_spi_timing.jsShare SPI timing conversions +153/-0

Share SPI timing conversions

• Converts configured nanoseconds to PRU cycles and validates delay and instruction-memory limits.

.metadata/sysconfig/.meta/pru_blocks/common/pru_spi_timing.js

pru_register_allocator.jsStrengthen register allocation across blocks +785/-49

Strengthen register allocation across blocks

• Adds lifetime releases, loop accumulator handling, explicit port routing, pinned-register checks, and allocation diagnostics.

.metadata/sysconfig/.meta/pru_blocks/common/register_allocation/pru_register_allocator.js

pru_core.jsExtend JavaScript PRU execution +364/-11

Extend JavaScript PRU execution

• Corrects register-lane handling and adds peripheral, timing, and execution behavior needed by device-aware simulation.

.metadata/sysconfig/.meta/pru_blocks/common/simulation/pru_core.js

arithmetic_block.syscfg.jsAdjust arithmetic block metadata +1/-1

Adjust arithmetic block metadata

• Updates arithmetic block behavior used by shared block infrastructure.

.metadata/sysconfig/.meta/pru_blocks/data_handling/arithmetic_block.syscfg.js

bitwise_block.syscfg.jsAdjust bitwise block metadata +1/-1

Adjust bitwise block metadata

• Updates bitwise block behavior used by shared block infrastructure.

.metadata/sysconfig/.meta/pru_blocks/data_handling/bitwise_block.syscfg.js

conditional_block.syscfg.jsHarden conditional block behavior +11/-4

Harden conditional block behavior

• Adjusts conditional handling for validated control flow and generated firmware.

.metadata/sysconfig/.meta/pru_blocks/program_control/conditional_block.syscfg.js

flow_control_block.syscfg.jsAdjust flow-control metadata +1/-1

Adjust flow-control metadata

• Updates a flow-control declaration for shared infrastructure.

.metadata/sysconfig/.meta/pru_blocks/program_control/flow_control_block.syscfg.js

group_block.syscfg.jsValidate group assembly labels +8/-1

Validate group assembly labels

• Adds checks for names emitted as group labels and related group behavior.

.metadata/sysconfig/.meta/pru_blocks/program_control/group_block.syscfg.js

loop_block.syscfg.jsValidate loop structure and accumulators +142/-6

Validate loop structure and accumulators

• Adds explicit accumulator and exported-result settings and rejects nested hardware loops.

.metadata/sysconfig/.meta/pru_blocks/program_control/loop_block.syscfg.js

pru_gpi_block.syscfg.jsGenerate a full-width GPI read +24/-14

Generate a full-width GPI read

• Clears and masks the destination register explicitly and corrects its declared width and cycle count.

.metadata/sysconfig/.meta/pru_blocks/pru_io_blocks/pru_gpi_block.syscfg.js

pru_gpo_block.syscfg.jsAdjust GPO block behavior +7/-1

Adjust GPO block behavior

• Updates GPO handling for generated output and shared validation.

.metadata/sysconfig/.meta/pru_blocks/pru_io_blocks/pru_gpo_block.syscfg.js

pru_spi_read.syscfg.jsFix SPI read initialization and timing +60/-17

Fix SPI read initialization and timing

• Initializes receive data, reserves full-width results where needed, and applies shared timing validation.

.metadata/sysconfig/.meta/pru_blocks/pru_io_blocks/pru_spi_read.syscfg.js

pru_spi_transfer.syscfg.jsFix SPI transfer receive results +41/-8

Fix SPI transfer receive results

• Initializes receive registers, reserves the required width, and validates configured timings.

.metadata/sysconfig/.meta/pru_blocks/pru_io_blocks/pru_spi_transfer.syscfg.js

pru_spi_write.syscfg.jsValidate SPI write timing +17/-3

Validate SPI write timing

• Applies shared nanosecond-to-cycle timing and instruction-memory checks.

.metadata/sysconfig/.meta/pru_blocks/pru_io_blocks/pru_spi_write.syscfg.js

access_look_up_table.syscfg.jsScale lookup-table indices +34/-8

Scale lookup-table indices

• Converts multibyte entry indices into byte addresses before loading table values.

.metadata/sysconfig/.meta/pru_blocks/utils/access_look_up_table.syscfg.js

delay_block.syscfg.jsCorrect delay behavior and guidance +21/-36

Correct delay behavior and guidance

• Aligns stated cycle costs with emitted instructions and explains hardware-loop nesting restrictions.

.metadata/sysconfig/.meta/pru_blocks/utils/delay_block.syscfg.js

look_up_table.syscfg.jsValidate lookup-table symbols +8/-1

Validate lookup-table symbols

• Checks names emitted as assembler symbols against reserved identifiers.

.metadata/sysconfig/.meta/pru_blocks/utils/look_up_table.syscfg.js

memory_access_block.syscfg.jsWarn about shared memory-variable aliases +55/-0

Warn about shared memory-variable aliases

• Identifies Memory Access blocks that share one variable and documents explicit variable assignment.

.metadata/sysconfig/.meta/pru_blocks/utils/memory_access_block.syscfg.js

memory_variable_block.syscfg.jsValidate memory-variable symbols +7/-0

Validate memory-variable symbols

• Rejects reserved assembler names for emitted memory reservation labels.

.metadata/sysconfig/.meta/pru_blocks/utils/memory_variable_block.syscfg.js

example.syscfgRevise AM243x UART/CRC design +8/-1

Revise AM243x UART/CRC design

• Adjusts block configuration and connections for the UART/CRC firmware example.

examples/uart_crc/firmware/am243x-lp/icss_g0_pru1_fw/example.syscfg

example.syscfgRevise AM261x UART/CRC design +8/-1

Revise AM261x UART/CRC design

• Adjusts block configuration and connections for the UART/CRC firmware example.

examples/uart_crc/firmware/am261x-lp/icss_m1_pru1_fw/example.syscfg

main.asmCorrect UART/CRC example assembly +21/-6

Correct UART/CRC example assembly

• Adjusts the example's generated-code integration and result handling.

examples/uart_crc/firmware/main.asm

Refactor (1) +31 / -0
asm_label.jsShare assembly label parsing +31/-0

Share assembly label parsing

• Provides a common label grammar to the simulator and test harnesses.

scripts/asm_label.js

Tests (34) +6158 / -0
conftest.pySkip unavailable simulator tests explicitly +52/-0

Skip unavailable simulator tests explicitly

• Reports missing TI simulator checkouts or older missing upstream device packages as skipped tests.

conftest.py

test_catalog_completeness.pyCheck device catalogue coverage +81/-0

Check device catalogue coverage

• Verifies that repository device-model classes have corresponding GUI catalogue entries.

scripts/sim/test_catalog_completeness.py

test_device_binding_runtime.jsTest runtime binding integration +312/-0

Test runtime binding integration

• Exercises device-binding behavior across the JavaScript simulation path.

scripts/sim/test_device_binding_runtime.js

test_device_binding_syscfg.jsTest SysConfig binding generation +206/-0

Test SysConfig binding generation

• Checks manifest generation and configured device binding validation.

scripts/sim/test_device_binding_syscfg.js

test_device_bindings.pyTest Python manifest handling +408/-0

Test Python manifest handling

• Covers binding translation, validation, and refusal conditions.

scripts/sim/test_device_bindings.py

test_device_model_titles.jsCheck device-field presentation +76/-0

Check device-field presentation

• Tests device-model catalogue titles shown in SysConfig.

scripts/sim/test_device_model_titles.js

test_device_models.jsTest JavaScript device behavior +369/-0

Test JavaScript device behavior

• Exercises supported in-tool models, including deliberately invalid stimuli.

scripts/sim/test_device_models.js

test_ti_run_gui.jsTest GUI run verdict handling +410/-0

Test GUI run verdict handling

• Checks design-digest and fail-closed launcher-result behavior.

scripts/sim/test_ti_run_gui.js

conftest.pyConfigure firmware test fixtures +7/-0

Configure firmware test fixtures

• Supplies shared setup for repository test cases.

tests/conftest.py

linker.cmdLink firmware test fixtures +55/-0

Link firmware test fixtures

• Defines PRU memory placement for assembled test programs.

tests/fixtures/firmware/linker.cmd

main.asmProvide assembly test fixture +31/-0

Provide assembly test fixture

• Defines reusable PRU assembly for firmware-backed tests.

tests/fixtures/firmware/main.asm

test_access_lut_index_scaling.pyVerify multibyte lookup indices +98/-0

Verify multibyte lookup indices

• Tests assembled lookup-table access using entry-sized address scaling.

tests/test_access_lut_index_scaling.py

test_bissline.pyVerify BiSS line behavior and faults +702/-0

Verify BiSS line behavior and faults

• Pairs legal frames with broken initiators and independent protocol checks.

tests/test_bissline.py

test_board_variant_builds.pyCheck board-specific firmware builds +234/-0

Check board-specific firmware builds

• Exercises generated firmware across supported board and core variants.

tests/test_board_variant_builds.py

test_conditional_unconnected_branch.pyCover unconnected conditional branches +56/-0

Cover unconnected conditional branches

• Checks firmware and validation behavior when a conditional branch is unwired.

tests/test_conditional_unconnected_branch.py

test_crc_lut_index_scaling.pyVerify CRC lookup addressing +276/-0

Verify CRC lookup addressing

• Tests assembled CRC16 and CRC32 lookup offsets against expected results.

tests/test_crc_lut_index_scaling.py

test_elf_cosim_constants.pyCheck simulator constant-table overrides +48/-0

Check simulator constant-table overrides

• Tests firmware co-simulation with configured constant-table and IEP addresses.

tests/test_elf_cosim_constants.py

test_fail_closed_gating.pyTest unsupported-feature refusals +126/-0

Test unsupported-feature refusals

• Checks capability and simulation paths do not silently report success.

tests/test_fail_closed_gating.py

test_fanout_register_alias.pyCover fan-out register lifetimes +330/-0

Cover fan-out register lifetimes

• Tests allocator routing and aliasing when several blocks consume one result.

tests/test_fanout_register_alias.py

test_gui_simulator_core.pyCheck JavaScript core execution +72/-0

Check JavaScript core execution

• Tests core behavior required by the GUI simulator.

tests/test_gui_simulator_core.py

test_hardware_loop_nesting.pyReject nested PRU hardware loops +213/-0

Reject nested PRU hardware loops

• Tests direct and container-mediated nesting restrictions.

tests/test_hardware_loop_nesting.py

test_linker_section_rules.pyCheck linker section placement +41/-0

Check linker section placement

• Verifies local and shared memory sections in firmware linker files.

tests/test_linker_section_rules.py

test_load_constant_width.pyTest constant output widths +175/-0

Test constant output widths

• Checks explicit-width allocation and rejection of undersized constants.

tests/test_load_constant_width.py

test_loop_carried_accumulator.pyTest loop-carried register values +274/-0

Test loop-carried register values

• Checks pre-initialized accumulator bindings and loop result lifetimes.

tests/test_loop_carried_accumulator.py

test_package_names.pyGuard against simulator import collisions +57/-0

Guard against simulator import collisions

• Checks package names and imports repository models before the upstream simulator in one interpreter.

tests/test_package_names.py

test_register_pool_exhaustion.pyTest allocator exhaustion diagnostics +268/-0

Test allocator exhaustion diagnostics

• Checks allocation failures are attributed to blocks and surfaced during validation.

tests/test_register_pool_exhaustion.py

test_shared_memvar_rename.pyTest shared memory-variable warnings +53/-0

Test shared memory-variable warnings

• Exercises aliased variables and their naming behavior.

tests/test_shared_memvar_rename.py

test_spi_cs_timing_elf.pyMeasure assembled SPI chip-select timing +170/-0

Measure assembled SPI chip-select timing

• Checks chip-select setup and hold behavior against compiled firmware.

tests/test_spi_cs_timing_elf.py

test_spi_read_zero_extend.pyTest SPI read result clearing +129/-0

Test SPI read result clearing

• Checks that assembled SPI reads do not retain high bits from earlier values.

tests/test_spi_read_zero_extend.py

test_spi_sclk_duty.pyMeasure assembled SPI clock duty +148/-0

Measure assembled SPI clock duty

• Tests clock pulse timing for SPI macro variants.

tests/test_spi_sclk_duty.py

test_spi_transfer_zero_extend.pyTest SPI transfer receive clearing +168/-0

Test SPI transfer receive clearing

• Checks that assembled full-duplex receives initialize their destination register.

tests/test_spi_transfer_zero_extend.py

test_syscfg_add_instance.pyTest SysConfig instance creation +81/-0

Test SysConfig instance creation

• Exercises scripted block-instance construction and configuration.

tests/test_syscfg_add_instance.py

test_uart_crc_firmware.pyExercise UART/CRC example firmware +160/-0

Exercise UART/CRC example firmware

• Builds and checks the example's firmware behavior.

tests/test_uart_crc_firmware.py

test_waveform_player.pyTest cycle-keyed pin stimuli +272/-0

Test cycle-keyed pin stimuli

• Checks WaveformPlayer timing and generated GPI levels.

tests/test_waveform_player.py

Other (51) +2583 / -1
.gitignoreIgnore simulation artifacts +2/-1

Ignore simulation artifacts

• Adjusts ignore rules for generated simulation and test files.

.gitignore

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/conditional/firmware/am243x-lp/icss_g0_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/conditional/firmware/am261x-lp/icss_m1_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-evm/icss_g0_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-evm/icss_g0_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-evm/icss_g0_rtu_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-evm/icss_g0_rtu_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-evm/icss_g0_tx_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-evm/icss_g0_tx_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-lp/icss_g0_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-lp/icss_g0_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-lp/icss_g0_rtu_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-lp/icss_g0_rtu_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-lp/icss_g0_tx_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am243x-lp/icss_g0_tx_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am261x-lp/icss_m0_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am261x-lp/icss_m0_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am261x-lp/icss_m1_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am261x-lp/icss_m1_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am64x-evm/icss_g0_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am64x-evm/icss_g0_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am64x-evm/icss_g0_rtu_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am64x-evm/icss_g0_rtu_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am64x-evm/icss_g0_tx_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/empty/firmware/am64x-evm/icss_g0_tx_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/gray_encoder_4_bit/firmware/am243x-lp/icss_g0_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/gray_encoder_4_bit/firmware/am261x-lp/icss_m1_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/incremental_spi/firmware/am243x-lp/icss_g0_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/incremental_spi/firmware/am261x-lp/icss_m1_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/spi_10mhz/firmware/am261x-lp/icss_m1_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/spi_10mhz/firmware/am261x-lp/icss_m1_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/spi_loopback/firmware/am243x-lp/icss_g0_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/spi_loopback/firmware/am243x-lp/icss_g0_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/spi_loopback/firmware/am261x-lp/icss_m1_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/spi_loopback/firmware/am261x-lp/icss_m1_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/uart_crc/firmware/am243x-lp/icss_g0_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/uart_crc/firmware/am243x-lp/icss_g0_pru1_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/uart_crc/firmware/am261x-lp/icss_m1_pru0_fw/ti-pru-cgt/linker.cmd

linker.cmdPlace generated memory sections +2/-0

Place generated memory sections

• Maps .udmem and .usmem into PRU local and shared memory.

examples/uart_crc/firmware/am261x-lp/icss_m1_pru1_fw/ti-pru-cgt/linker.cmd

buscosim.pyDecode resolved bus traces independently +474/-0

Decode resolved bus traces independently

• Extracts protocol events from pin traces separately from model state.

pru_device_models/buscosim.py

block_validate_runner.jsRun block validation outside SysConfig +309/-0

Run block validation outside SysConfig

• Adds a Node-based harness for block validation tests.

scripts/block_validate_runner.j

[Comment truncated to fit github's 65,536-char limit.]

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo


Action required

1. Four selectable devices cannot run simulations 🐞
Description
attach_bound_devices() rejects every model without nets, including the repository-native SPI
ADC, step/dir, WS2812 and MDIO models offered in device configuration. Selecting any of these kinds
for a bound-device run raises DeviceRefused before the model is attached, so neither the headless
run nor the live view can simulate it.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Four selectable repository-native device kinds are rejected by the bound-device runner because they implement the `tick()` contract rather than `nets`.
## Fix Focus Areas
- scripts/sim/run_bound_devices.py[174-200]
- scripts/sim/device_bindings.py[178-200]
- pru_device_models/device_model.py[4-15]
## Recommended Fix
Adapt these models to the simulator's pin-bus contract or add an attachment path that drives the bus using their `tick()` interface. Keep the selectable kinds and supported runtime kinds consistent, and test each through the bound-device runner.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗


View medium (7)
Remediation recommended
2. Later BiSS frames fail as overclocking 🐞
Description
BissLineEncoder.tick() increments _clocks_in_burst on every rising edge without resetting it for
a subsequent frame, while _frame_emitted remains set after flush(). A second correctly timed
transaction in the same run exceeds the first frame's clock count, records an overclock fault and
produces no second frame event.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The BiSS line model retains its first frame's clock count and emitted flag, so a second transaction is rejected.
## Fix Focus Areas
- pru_device_models/bissline_device_model.py[258-305]
## Recommended Fix
Detect the inter-frame boundary and reset the per-frame clock, capture, shift and emission state before sampling the next transaction. Add a test that clocks two complete frames with an idle gap.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

3. Line-coded frames accumulate disparity 🐞
Description
encode_8b10b_byte() always combines the fixed negative-disparity table entries and has no
running-disparity state or alternate encoding. With line coding enabled, repeated bytes can
therefore produce successive symbols with the same nonzero disparity instead of a valid balanced
8b/10b stream; the model's inverse table can still decode its own output.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Optional BiSS line coding reuses one fixed codeword per byte rather than maintaining 8b/10b running disparity.
## Fix Focus Areas
- pru_device_models/bissline_device_model.py[42-78]
- pru_device_models/bissline_device_model.py[238-251]
## Recommended Fix
Implement both disparity variants and update running disparity across symbols when constructing a frame. Test emitted wire symbols against independently specified vectors, including repeated bytes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

4. First input sample ignores attached devices 🐞
Description
simulatePruInstructions() initializes R30 to the attached bus's idle output but leaves R31 at zero
until the post-instruction bus settlement. Firmware that reads R31 in its first instruction receives
zero rather than the device-resolved input level at startup, affecting first-cycle samples and
branches.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Attached-device simulation initializes R30 but does not resolve R31 before executing firmware's first instruction.
## Fix Focus Areas
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/pru_core.js[1984-2015]
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/device_bus.js[128-136]
## Recommended Fix
Settle the attached bus at startup with the initial R30 value, assign the resolved level to R31 and initialize its history consistently before instruction dispatch. Test a first-instruction R31 read against an attached device's idle level.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

5. GUI SSI encoder sends wrong data at 32+ bits 🐞
Description
SsiEncoder._fallingEdge builds the frame with 32-bit JS bitwise operations: `(1 << this.bits) -
1, >>> 0, and >> shifts by bits - i`. The Device Model table accepts SSI frame widths up to
64, and the constructor only checks bits >= 1. At the common width of 32, the mask works out to 0,
so the encoder always sends zeros. At widths above 32, the shift counts wrap modulo 32 and the frame
is corrupted.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The GUI SSI encoder model builds frames with 32-bit JS bitwise operations, but the parameter table accepts widths up to 64. At bits=32 the mask becomes 0. Above 32, the shifts wrap.

## Fix Focus Areas
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/device_models.js[276-287]
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/device_models.js[212-214]
- .metadata/sysconfig/.meta/pru_blocks/common/device_model_table.js[67]

## Recommended Fix
Either do the mask, gray-code and bit-extract steps with BigInt (or with Math.pow/Math.floor arithmetic up to 53 bits), or lower the table max and the constructor check to 32 bits.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

6. BiSS model misreads zero bits when master data is high 🐞
Description
BissLineEncoder.tick records each clocked bit as slave_bit | mo, where mo is sampled from the
separate master-data GPO pin. Whenever firmware holds MO high during the reply, every 0 bit the
slave sent is recorded as 1. This corrupts the model's own 8b/10b, Hamming and CRC decode in
_emit_frame, so a correct firmware run can produce false decode faults or a wrong position event.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The BiSS Line model ORs the master MO pin into each captured slave bit, so MO=1 corrupts the decoded frame.

## Fix Focus Areas
- pru_device_models/bissline_device_model.py[258-285]

## Recommended Fix
Append `slave_bit` alone to `_captured_bits`. If MO driving during the reply is meant to represent bus contention, record a fault for it instead of changing the captured value.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

7. Python and GUI encoders count opposite directions 🐞
Description
The Python QuadratureIndexEncoder uses state 2*A+B with forward order 0→1→3→2, so B rises first
on a forward step. The GUI JS model's QUAD_PHASES order is [A,B] 00→10→11→01, so A rises first.
The same 'forward' motion therefore reaches firmware as opposite rotation in the TI-simulator
harness and in the GUI simulator, and a decoder validated against one model counts backwards against
the other.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Python and JS quadrature models disagree about which channel leads on forward motion.

## Fix Focus Areas
- pru_device_models/quadrature_index_encoder.py[24-26]
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/device_models.js[51]

## Recommended Fix
Pick one convention (A leads for CW is the usual one). In Python, change `_FWD` to 0→2→3→1 (state=2A+B), or change the JS table, so both models emit the same A/B sequence for forward motion.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

8. Timed-out GUI runs leave build processes running on Linux 🐞
Description
kill_process_tree only calls proc.kill() on POSIX, and run_logged starts the command without
start_new_session, so gmake's children are never signalled. After a sysconfig, build or simulator
timeout, compiler or simulator descendants keep running and can keep writing generated files.
Meanwhile the log claims the process tree was terminated.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
On POSIX, a timeout kills only the direct child, so gmake's descendants are orphaned.

## Fix Focus Areas
- scripts/sim/gui_run.py[152-179]

## Recommended Fix
Pass `start_new_session=True` to Popen on POSIX. In `kill_process_tree`, call `os.killpg(os.getpgid(proc.pid), signal.SIGKILL)` (catching ProcessLookupError), then `proc.wait()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗


View low (2)
Informational
9. Encoder with zero counts per turn crashes 🐞
Description
The constructor only appends 'cpr must be positive' to the fault list and keeps going. On the first
edge, tick() evaluates self.count % self.cpr. With cpr=0, this raises ZeroDivisionError and
aborts the whole co-simulation instead of reporting the fault the model already recorded.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
With cpr<=0, QuadratureIndexEncoder.tick divides by zero.

## Fix Focus Areas
- pru_device_models/quadrature_index_encoder.py[44-51]
- pru_device_models/quadrature_index_encoder.py[98-100]

## Recommended Fix
Either raise ValueError in the constructor, or skip the index check when `self.cpr <= 0`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

10. Missing simulator gives a traceback, not a refusal 🐞
Description
run_bound_devices.main calls find_pru_simulator() outside any try block. That function raises
SimulatorNotFound, so a missing or invalid checkout ends with an uncaught traceback and exit code
1. The runner's documented REFUSED result and exit code are never produced in that case.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
run_bound_devices.main does not handle SimulatorNotFound.

## Fix Focus Areas
- scripts/sim/run_bound_devices.py[358]

## Recommended Fix
Wrap `find_pru_simulator()` in try/except SimulatorNotFound, print `REFUSED: ...` to stderr and return EXIT_REFUSED.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗


Comment on lines +191 to +197
if getattr(model, "nets", None) is None:
raise DeviceRefused(
f"device kind {entry['kind']!r} "
f"({type(model).__module__}.{type(model).__name__}) uses the "
f"pru_device_models.device_model contract with no `nets`; TI pru-simulator's "
f"device bus cannot attach it, so gmake sim does not support "
f"this kind yet")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Four selectable devices cannot run simulations 🐞 Bug ≡ Correctness

attach_bound_devices() rejects every model without nets, including the repository-native SPI
ADC, step/dir, WS2812 and MDIO models offered in device configuration. Selecting any of these kinds
for a bound-device run raises DeviceRefused before the model is attached, so neither the headless
run nor the live view can simulate it.
Agent Prompt
## Issue description
Four selectable repository-native device kinds are rejected by the bound-device runner because they implement the `tick()` contract rather than `nets`.
## Fix Focus Areas
- scripts/sim/run_bound_devices.py[174-200]
- scripts/sim/device_bindings.py[178-200]
- pru_device_models/device_model.py[4-15]
## Recommended Fix
Adapt these models to the simulator's pin-bus contract or add an attachment path that drives the bus using their `tick()` interface. Keep the selectable kinds and supported runtime kinds consistent, and test each through the bound-device runner.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Left for a follow-up: these four models use the tick() contract, not per-pin nets, so the bound-device runner refuses them by name (scripts/sim/run_bound_devices.py:178-190) rather than attach them wrongly. Running them on the TI simulator needs a bus adapter that states which pins each model drives; that is a design change we have not made yet.

Comment on lines +272 to +275
self._clocks_in_burst += 1

if self._clocks_in_burst > len(self._wire_bits):
if not self._overclock_flagged:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

2. Later biss frames fail as overclocking 🐞 Bug ≡ Correctness

BissLineEncoder.tick() increments _clocks_in_burst on every rising edge without resetting it for
a subsequent frame, while _frame_emitted remains set after flush(). A second correctly timed
transaction in the same run exceeds the first frame's clock count, records an overclock fault and
produces no second frame event.
Agent Prompt
## Issue description
The BiSS line model retains its first frame's clock count and emitted flag, so a second transaction is rejected.
## Fix Focus Areas
- pru_device_models/bissline_device_model.py[258-305]
## Recommended Fix
Detect the inter-frame boundary and reset the per-frame clock, capture, shift and emission state before sampling the next transaction. Add a test that clocks two complete frames with an idle gap.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 2d06275: a clock idle for frame_gap_cycles (default 64) now ends a frame and the next burst starts from clean state, so a second frame is no longer counted as overclocked; overclocking inside one frame is still flagged.

Comment on lines +63 to +69
def _init_8b10b():
for bv in range(256):
c6 = _5B6B_RD_NEG[bv & 0x1F]
c4 = _3B4B_RD_NEG[(bv >> 5) & 0x07]
sym = (c6 << 4) | c4
_8B10B_ENC[bv] = sym
_8B10B_DEC[sym] = bv

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

3. Line-coded frames accumulate disparity 🐞 Bug ≡ Correctness

encode_8b10b_byte() always combines the fixed negative-disparity table entries and has no
running-disparity state or alternate encoding. With line coding enabled, repeated bytes can
therefore produce successive symbols with the same nonzero disparity instead of a valid balanced
8b/10b stream; the model's inverse table can still decode its own output.
Agent Prompt
## Issue description
Optional BiSS line coding reuses one fixed codeword per byte rather than maintaining 8b/10b running disparity.
## Fix Focus Areas
- pru_device_models/bissline_device_model.py[42-78]
- pru_device_models/bissline_device_model.py[238-251]
## Recommended Fix
Implement both disparity variants and update running disparity across symbols when constructing a frame. Test emitted wire symbols against independently specified vectors, including repeated bytes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 2d06275: line coding now tracks running disparity, using the RD- or RD+ code (including the alternate D.x.A7 symbol) per byte; the decoder accepts both. Tests check written-out symbol vectors and repeated bytes.

// present every clocked device with a falling edge the firmware never
// generated. Open-loop runs (no bus) keep the historical zero start.
if (deviceBus) {
pruState.registers[30] = deviceBus.idlePruWord();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

4. First input sample ignores attached devices 🐞 Bug ≡ Correctness

simulatePruInstructions() initializes R30 to the attached bus's idle output but leaves R31 at zero
until the post-instruction bus settlement. Firmware that reads R31 in its first instruction receives
zero rather than the device-resolved input level at startup, affecting first-cycle samples and
branches.
Agent Prompt
## Issue description
Attached-device simulation initializes R30 but does not resolve R31 before executing firmware's first instruction.
## Fix Focus Areas
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/pru_core.js[1984-2015]
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/device_bus.js[128-136]
## Recommended Fix
Settle the attached bus at startup with the initial R30 value, assign the resolved level to R31 and initialize its history consistently before instruction dispatch. Test a first-instruction R31 read against an attached device's idle level.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 7c14f0c: the attached bus is settled once at startup and its result seeds R31 and the R31 history, so a first-instruction R31 read sees the idle level.

Comment on lines +280 to +283
const raw = this.position & ((1 << this.bits) - 1);
this._latched = (this.gray ? toGray(raw) : raw) >>> 0;
this._bitIndex = 1;
this._data = (this._latched >> (this.bits - 1)) & 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

5. Gui ssi encoder sends wrong data at 32+ bits 🐞 Bug ≡ Correctness

SsiEncoder._fallingEdge builds the frame with 32-bit JS bitwise operations: `(1 << this.bits) -
1, >>> 0, and >> shifts by bits - i`. The Device Model table accepts SSI frame widths up to
64, and the constructor only checks bits >= 1. At the common width of 32, the mask works out to 0,
so the encoder always sends zeros. At widths above 32, the shift counts wrap modulo 32 and the frame
is corrupted.
Agent Prompt
## Issue description
The GUI SSI encoder model builds frames with 32-bit JS bitwise operations, but the parameter table accepts widths up to 64. At bits=32 the mask becomes 0. Above 32, the shifts wrap.

## Fix Focus Areas
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/device_models.js[276-287]
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/device_models.js[212-214]
- .metadata/sysconfig/.meta/pru_blocks/common/device_model_table.js[67]

## Recommended Fix
Either do the mask, gray-code and bit-extract steps with BigInt (or with Math.pow/Math.floor arithmetic up to 53 bits), or lower the table max and the constructor check to 32 bits.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 19bff5c: the SSI encoder builds the frame with BigInt, so 32-bit frames are no longer masked to zero and frames up to the table's 64 bits keep every bit.

Comment on lines +282 to +285
self._shift_index = self._clocks_in_burst
driven_val = self._drive()
slave_bit = (driven_val >> self.slo_pin) & 1
self._captured_bits.append(slave_bit | mo)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

6. Biss model misreads zero bits when master data is high 🐞 Bug ≡ Correctness

BissLineEncoder.tick records each clocked bit as slave_bit | mo, where mo is sampled from the
separate master-data GPO pin. Whenever firmware holds MO high during the reply, every 0 bit the
slave sent is recorded as 1. This corrupts the model's own 8b/10b, Hamming and CRC decode in
_emit_frame, so a correct firmware run can produce false decode faults or a wrong position event.
Agent Prompt
## Issue description
The BiSS Line model ORs the master MO pin into each captured slave bit, so MO=1 corrupts the decoded frame.

## Fix Focus Areas
- pru_device_models/bissline_device_model.py[258-285]

## Recommended Fix
Append `slave_bit` alone to `_captured_bits`. If MO driving during the reply is meant to represent bus contention, record a fault for it instead of changing the captured value.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Not changed: BiSS Line shares one line between master and slave, and the model deliberately captures slave_bit | mo so a master that drives the line during the reply corrupts the frame (pru_device_models/bissline_device_model.py tick(); asserted by tests/test_bissline.py TestMasterDataCorruption). Reporting that case as a contention fault instead is a possible refinement we have not made.

Comment on lines +24 to +26
# x4 state table: state = 2*A + B. Forward (CW) order 0,1,3,2,0...
_FWD = {0: 1, 1: 3, 3: 2, 2: 0}
_REV = {v: k for k, v in _FWD.items()}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

7. Python and gui encoders count opposite directions 🐞 Bug ≡ Correctness

The Python QuadratureIndexEncoder uses state 2*A+B with forward order 0→1→3→2, so B rises first
on a forward step. The GUI JS model's QUAD_PHASES order is [A,B] 00→10→11→01, so A rises first.
The same 'forward' motion therefore reaches firmware as opposite rotation in the TI-simulator
harness and in the GUI simulator, and a decoder validated against one model counts backwards against
the other.
Agent Prompt
## Issue description
The Python and JS quadrature models disagree about which channel leads on forward motion.

## Fix Focus Areas
- pru_device_models/quadrature_index_encoder.py[24-26]
- .metadata/sysconfig/.meta/pru_blocks/common/simulation/device_models.js[51]

## Recommended Fix
Pick one convention (A leads for CW is the usual one). In Python, change `_FWD` to 0→2→3→1 (state=2A+B), or change the JS table, so both models emit the same A/B sequence for forward motion.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in a29c4e8: aligned the in-tool simulation model phase table and the Python encoder/decoder models to the PRU firmware's B-leading positive direction convention, so forward motion counts positively in both simulation environments and matches compiled firmware cosimulation.

Comment on lines +98 to +99
if self.count % self.cpr == 0 and self.count != 0:
self._z_high_until = cycle + self.index_width_cycles

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Informational

9. Encoder with zero counts per turn crashes 🐞 Bug ☼ Reliability

The constructor only appends 'cpr must be positive' to the fault list and keeps going. On the first
edge, tick() evaluates self.count % self.cpr. With cpr=0, this raises ZeroDivisionError and
aborts the whole co-simulation instead of reporting the fault the model already recorded.
Agent Prompt
## Issue description
With cpr<=0, QuadratureIndexEncoder.tick divides by zero.

## Fix Focus Areas
- pru_device_models/quadrature_index_encoder.py[44-51]
- pru_device_models/quadrature_index_encoder.py[98-100]

## Recommended Fix
Either raise ValueError in the constructor, or skip the index check when `self.cpr <= 0`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in af07099: with a counts-per-turn of zero the fault is reported as before and the index check no longer divides by it, so the run is not aborted.

Comment thread scripts/sim/gui_run.py Outdated
Comment on lines +176 to +179
subprocess.run(["taskkill", "/F", "/T", "/PID", str(proc.pid)],
capture_output=True, text=True, timeout=30)
else:
proc.kill()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

8. Timed-out gui runs leave build processes running on linux 🐞 Bug ☼ Reliability

kill_process_tree only calls proc.kill() on POSIX, and run_logged starts the command without
start_new_session, so gmake's children are never signalled. After a sysconfig, build or simulator
timeout, compiler or simulator descendants keep running and can keep writing generated files.
Meanwhile the log claims the process tree was terminated.
Agent Prompt
## Issue description
On POSIX, a timeout kills only the direct child, so gmake's descendants are orphaned.

## Fix Focus Areas
- scripts/sim/gui_run.py[152-179]

## Recommended Fix
Pass `start_new_session=True` to Popen on POSIX. In `kill_process_tree`, call `os.killpg(os.getpgid(proc.pid), signal.SIGKILL)` (catching ProcessLookupError), then `proc.wait()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 31e1883: on POSIX commands now run in their own session and a timeout signals the whole process group, then reaps the child.


bindings = manifest.get("bindings", [])
if not bindings:
print("REFUSED: manifest has no device bindings. An empty manifest is REFUSED.", file=sys.stderr)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Informational

10. Missing simulator gives a traceback, not a refusal 🐞 Bug ☼ Reliability

run_bound_devices.main calls find_pru_simulator() outside any try block. That function raises
SimulatorNotFound, so a missing or invalid checkout ends with an uncaught traceback and exit code
1. The runner's documented REFUSED result and exit code are never produced in that case.
Agent Prompt
## Issue description
run_bound_devices.main does not handle SimulatorNotFound.

## Fix Focus Areas
- scripts/sim/run_bound_devices.py[358]

## Recommended Fix
Wrap `find_pru_simulator()` in try/except SimulatorNotFound, print `REFUSED: ...` to stderr and return EXIT_REFUSED.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 2819fa3: a missing simulator checkout now prints a REFUSED diagnostic and exits with the refusal code instead of a traceback.

The option was not recognised in the argument loop, so its name was taken as the
block path or the instance JSON and the file was never read. It is now parsed
with its path, read and parsed with a clear error on failure, and listed in the
usage text.
getDevicePadSharing returned an empty set when the device data had neither a
usable runtime pin interface nor pin common info, which the validator read as
"no pad is shared" and so emitted neither a collision warning nor the
"could not be checked" warning. It now returns null in that case, keeping an
empty set only when available data holds no shared pad.
…ry ports

A multi-output macro reserved the full width for output2 and up but emitted only
the first register of the pair, and consumers wired to such a port read only that
register, so a 64-bit second result lost its upper half. The macro destination and
the consumer's source token now carry both registers, as output1 already did.
TEMP_REG3 and TEMP_REG4 alias R26 and R27, which were still in the allocatable pool,
so a macro writing them could overwrite a live value or its own result. Before
allocation the pool now drops R26 and/or R27 when any block's macro text names
TEMP_REG3 and/or TEMP_REG4; designs that use neither keep the full 28-register
pool. The summary comments list the scratch registers in use and the out-of-registers
error mentions the bytes held for them.
…zero counts-per-turn setting

The Python quadrature encoder and its independent decoder stepped B first on
forward motion, the opposite of the in-tool model, so the same motion counted
in opposite directions in the two simulators. Forward motion now rises A
first in both. A counts-per-turn of zero is recorded as a fault as before,
but the index check no longer divides by it, so the run is not aborted.
… 8b/10b running disparity

A second correctly timed frame in the same run was counted on top of the first
frame's clocks, reported as overclocked and produced no frame event. The model
now treats a clock idle for frame_gap_cycles as the end of a frame, reports it
and starts the next one from clean state.

Line coding always used the negative-disparity code of every byte, so repeated
bytes with unbalanced codes drifted in disparity. The encoder now selects the
RD- or RD+ code, including the alternate D.x.A7 symbol, and carries the running
disparity across the symbols of a frame; the decoder accepts both columns.
…POSIX

The wrapper started its commands in the parent's session and only killed the
direct child on POSIX, so the compiler or simulator started by gmake kept
running after a timeout while the log said the process tree was terminated.
Commands now lead their own session, the group is signalled, and the child is
reaped.
…device runner

main() called the simulator lookup outside its refusal handling, so a missing
checkout ended in an uncaught traceback and exit code 1. It now prints a
REFUSED diagnostic and returns the refusal exit code.
Each symbol was decoded at an offset counted from the start of the file, so
names, values and sizes came from the ELF header and the bytes after it. The
offset now starts at the symbol table section.
The GUI core rounded the count up to whole registers and ignored the byte or
word offset of the operand, so zero &R2.b2, 1 cleared all of R2. The headless
simulator called a register-reference parser it does not define and threw a
TypeError on either instruction. Both now start at the operand's byte, change
exactly the requested number of bytes and stop after R31.
…GUI core

The headless timer recognised count, status and compare at the offsets of an
older timer layout (0x0C, 0x44, 0x48/0x4C), counted unconditionally and reset
on any compare at or above CMP0, so firmware using the generated timer code
(GLOBAL_CFG 0x00, COUNT 0x10/0x14, CMP_CFG 0x70, CMP_STATUS 0x74, CMPj at
0x78 + 8j) read and wrote different registers and saw compare hits it had not
enabled. The map, the 64-bit count, CNT_ENABLE and DEFAULT_INC, CMP_EN,
equality compare and CMP0_RST_CNT_EN now match the GUI core.

LBCO and SBCO also read the register operand through fields the parser does
not return, so register-sourced stores moved no data; they now use the
parsed register number and byte offset.
With devices attached, R30 started at the bus idle word but R31 stayed zero
until the first bus settlement after an instruction, so firmware that read R31
in its first instruction saw zero instead of the level the devices and
pull-ups give the idle outputs. The bus is now settled once at startup and its
result seeds R31 and the R31 history.
The frame mask, Gray conversion and bit extraction used 32-bit JavaScript
bitwise operators, so a 32-bit frame was masked to zero and wider frames
(the table accepts up to 64 bits) had their shift counts wrapped. The
position is now latched and shifted as a BigInt.
buildDeviceBindings wrote the raw clock and index fields, mapping the unset
value to null, while validation, the pin-conflict check and the in-tool
simulator use the pins defaulted from the bound block. A clocked device whose
clock came from its block therefore reached the Python binding without a
clock pin and was refused. The manifest now carries the same effective pins.
The compiled PRU firmware decodes transition 0 -> 1 as forward motion
(B rises before A). The Python encoder and decoder models, along with the
in-tool JavaScript simulation phase table, now consistently follow this
B-leading convention. Forward motion advances positive count across both
simulation environments and agrees with firmware cosimulation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants