Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/link_check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2026 Texas Instruments Incorporated - http://www.ti.com/
#
# Link Check CI — checks for broken relative links and image references in all
# markdown files across the repository. Catches missing images, wrong paths, and
# stale cross-references before they land in main.

name: Link Check

on:
push:
branches: [ main, master ]
paths:
- '**/*.md'
- '**/images/**'
pull_request:
branches: [ "**" ]
paths:
- '**/*.md'
- '**/images/**'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
link-check:
name: Check Links in Markdown Files
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Run lychee link checker
uses: lycheeverse/lychee-action@v2
with:
# Check all markdown files in the repo
args: >-
--verbose
--no-progress
--include-fragments
--accept 200..=429
--root-dir ${{ github.workspace }}
'./**/*.md'
# Fail the workflow if any broken links are found
fail: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34 changes: 34 additions & 0 deletions .metadata/sysconfig/.meta/pru_blocks.syscfg.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,27 @@ exports = {
side: "right",
multipleConnections: true,
},
// Typed data ports — width-enforced connections
{
type: "input32",
side: "left",
multipleConnections: false,
},
{
type: "output32",
side: "right",
multipleConnections: true,
},
{
type: "input64",
side: "left",
multipleConnections: false,
},
{
type: "output64",
side: "right",
multipleConnections: true,
},
{
type: "CONDITIONAL_NEXT",
side: "right",
Expand Down Expand Up @@ -77,6 +98,19 @@ exports = {
type: "data",
displayName: "dataflow",
},
// Typed width-enforced data connections
{
start: "output32",
end: "input32",
type: "data",
displayName: "dataflow32",
},
{
start: "output64",
end: "input64",
type: "data",
displayName: "dataflow64",
},
{
start: "CONDITIONAL_NEXT",
end: "PREV",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -603,14 +603,14 @@ exports = {
ports: (inst) => {
let ports = [];

ports.push({ name: "input1", displayName:"init", type: "input" })
ports.push({ name: "input2", displayName:"data", type: "input" })
ports.push({ name: "input1", displayName:"init", type: "input32" })
ports.push({ name: "input2", displayName:"data", type: "input32" })
ports.push({ name: "prev", type: "PREV" })
ports.push({ name: "next", type: "NEXT"})

for(let iterator = 1; iterator <= inst["numOfOutputPorts"]; iterator++)
{
ports.push({ name: "output"+iterator.toString(), type: "output"})
ports.push({ name: "output"+iterator.toString(), type: "output32"})
}

return ports
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,23 @@
% pins.push({ pin: inst["SDO Signal"], func: "SDO", dir: `${PRU_USED}_GPO` });
% pins.push({ pin: inst["CS Signal"], func: "CS", dir: isCtrl ? `${PRU_USED}_GPO` : `${PRU_USED}_GPI` });
% }
% // UART TX block - uses ENDAT peripheral with fixed pins per channel
% else if (modulePath.includes("uart_tx")) {
% const ch = inst.channel;
% // Channel 0: GPO0 (clock), GPO1 (data out), GPO2 (out enable)
% // Channel 1: GPO3, GPO4, GPO5
% // Channel 2: GPO6, GPO7, GPO8
% const basePin = ch * 3;
% pins.push({ pin: basePin, func: "PERIF" + ch + "_CLK", dir: `${PRU_USED}_GPO` });
% pins.push({ pin: basePin + 1, func: "PERIF" + ch + "_DOUT", dir: `${PRU_USED}_GPO` });
% pins.push({ pin: basePin + 2, func: "PERIF" + ch + "_OE", dir: `${PRU_USED}_GPO` });
% }
% // UART RX block - uses ENDAT peripheral with fixed pins per channel
% else if (modulePath.includes("uart_rx")) {
% const ch = inst.channel;
% // Channel 0: GPI9 (perif_data_in)
% // Channel 1: GPI10
% // Channel 2: GPI11
% const rxPin = 9 + ch;
% pins.push({ pin: rxPin, func: "PERIF" + ch + "_DIN", dir: `${PRU_USED}_GPI` });
% // UART Config block - covers pins for all enabled TX/RX channels
% // TX op and RX op blocks share the same pins — only uart_config is the source of truth
% else if (modulePath.includes("uart_config")) {
% if (inst.enableTX) {
% const ch = inst.txChannel;
% const basePin = ch * 3;
% pins.push({ pin: basePin, func: "PERIF" + ch + "_CLK", dir: `${PRU_USED}_GPO` });
% pins.push({ pin: basePin + 1, func: "PERIF" + ch + "_DOUT", dir: `${PRU_USED}_GPO` });
% pins.push({ pin: basePin + 2, func: "PERIF" + ch + "_OE", dir: `${PRU_USED}_GPO` });
% }
% if (inst.enableRX) {
% const ch = inst.rxChannel;
% const rxPin = 9 + ch;
% pins.push({ pin: rxPin, func: "PERIF" + ch + "_DIN", dir: `${PRU_USED}_GPI` });
% }
% }
% // UART TX Op / UART RX Op — pins already covered by the paired uart_config instance above
% return pins;
%}
%
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,10 +549,16 @@ function pushInstruction(instance, parentInstance) {
maxBytesUsed = noOfBytesUsedByInput > maxBytesUsed ? noOfBytesUsedByInput : maxBytesUsed;

// Get register notation for this input's output
inputValues = inputValues + getPruRegister(
moduleInstanceRegisterMap[inputInstanceName].byteOffsetOfOutput1,
moduleInstanceRegisterMap[inputInstanceName].numOfBytesReqByOutput1
) + " , ";
const _srcByteOffset = moduleInstanceRegisterMap[inputInstanceName].byteOffsetOfOutput1;
const _srcNumBytes = moduleInstanceRegisterMap[inputInstanceName].numOfBytesReqByOutput1;
if (_srcNumBytes > 4) {
// 64-bit source: emit two consecutive registers (lo, hi)
const _loReg = getPruRegister(_srcByteOffset, 4);
const _hiReg = getPruRegister(_srcByteOffset + 4, 4);
inputValues = inputValues + _loReg + " , " + _hiReg + " , ";
} else {
inputValues = inputValues + getPruRegister(_srcByteOffset, _srcNumBytes) + " , ";
}
}
}

Expand Down Expand Up @@ -728,7 +734,15 @@ function pushInstruction(instance, parentInstance) {
moduleInstanceRegisterMap[instanceName].numOfBytesReqByOutput1 = maxBytesUsed;

// Get output register notation
const outputRegister = getPruRegister(byteOffset, maxBytesUsed);
// For 64-bit outputs (>4 bytes), emit two consecutive registers (lo, hi)
let outputRegister;
if (maxBytesUsed > 4) {
const _outLoReg = getPruRegister(byteOffset, 4);
const _outHiReg = getPruRegister(byteOffset + 4, 4);
outputRegister = `${_outLoReg}, ${_outHiReg}`;
} else {
outputRegister = getPruRegister(byteOffset, maxBytesUsed);
}

// Clean up input values string (remove trailing comma and space)
if (inputValues.endsWith(" , ")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,11 @@ exports = {
let ports = [];
for(let iterator = 1; iterator <= inst["numOfInputPorts"]; iterator++)
{
ports.push({ name: "input"+iterator.toString(), type: "input" })
ports.push({ name: "input"+iterator.toString(), type: "input32" })
}
for(let iterator = 1; iterator <= inst["numOfOutputPorts"]; iterator++)
{
ports.push({ name: "output"+iterator.toString(), type: "output"})
ports.push({ name: "output"+iterator.toString(), type: "output32"})
}
ports.push({ name: "prev", type: "PREV" })
ports.push({ name: "next", type: "NEXT"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,11 @@ exports = {
let ports = [];
for(let iterator = 1; iterator <= inst["numOfInputPorts"]; iterator++)
{
ports.push({ name: "input"+iterator.toString(), type: "input" })
ports.push({ name: "input"+iterator.toString(), type: "input32" })
}
for(let iterator = 1; iterator <= inst["numOfOutputPorts"]; iterator++)
{
ports.push({ name: "output"+iterator.toString(), type: "output"})
ports.push({ name: "output"+iterator.toString(), type: "output32"})
}
ports.push({ name: "prev", type: "PREV" })
ports.push({ name: "next", type: "NEXT"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,11 @@ exports = {
let ports = [];
for(let iterator = 1; iterator <= inst["numOfInputPorts"]; iterator++)
{
ports.push({ name: "input"+iterator.toString(), type: "input" })
ports.push({ name: "input"+iterator.toString(), type: "input32" })
}
for(let iterator = 1; iterator <= inst["numOfOutputPorts"]; iterator++)
{
ports.push({ name: "output"+iterator.toString(), type: "output"})
ports.push({ name: "output"+iterator.toString(), type: "output32"})
}
ports.push({ name: "prev", type: "PREV" })
ports.push({ name: "next", type: "NEXT"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ scripting.connect(prev_block, "next", if_else1, "prev");
4. **Single Cycle**: Comparison and branch decision execute in 1 PRU cycle.

5. **Port Names**: True path uses "T" port, False path uses "F" port (displayed as t_next/f_next).

6. **Terminate Each Branch with a Flow Control Block**: The code generator places the FALSE path immediately after the branch instruction, with the TRUE path at the branch target label. If the FALSE path has no explicit terminator, execution falls through into the TRUE path — causing both branches to execute regardless of the condition. Always end each branch (T and F) with a Flow Control block (HALT or END) to prevent this fall-through.
`;
}

Expand Down Expand Up @@ -168,6 +170,7 @@ Implements conditional logic (IF/ELSE statements) to control program flow based
- The conditional check happens instantly (1 cycle)
- Code on both branches is generated, only one path executes at runtime
- This block does not produce an output value - it only controls flow
- **Always terminate each branch (T and F) with a Flow Control block**: The FALSE path falls through to the TRUE path in the generated assembly unless explicitly stopped. Without a terminator on the FALSE branch, both branches execute sequentially regardless of the condition result.

### Terminology
- **Conditional branching**: Changing program flow based on a condition
Expand Down Expand Up @@ -292,7 +295,7 @@ exports = {
let ports = [];
for(let iterator = 1; iterator <= inst["numOfInputPorts"]; iterator++)
{
ports.push({ name: "input"+iterator.toString(), type: "input" })
ports.push({ name: "input"+iterator.toString(), type: "input32" })
}
ports.push({ name: "T",displayName: "t_next", type: "CONDITIONAL_NEXT"})
ports.push({ name: "F",displayName: "f_next", type: "CONDITIONAL_NEXT"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,11 @@ exports = {
let ports = [];
for(let iterator = 1; iterator <= inst["numOfInputPorts"]; iterator++)
{
ports.push({ name: "input"+iterator.toString(), type: "input" })
ports.push({ name: "input"+iterator.toString(), type: "input32" })
}
for(let iterator = 1; iterator <= inst["numOfOutputPorts"]; iterator++)
{
ports.push({ name: "output"+iterator.toString(), type: "output"})
ports.push({ name: "output"+iterator.toString(), type: "output32"})
}
ports.push({ name: "prev", type: "IO_PREV" })
ports.push({ name: "next", type: "IO_NEXT" })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,11 +352,11 @@ exports = {
let ports = [];
for(let iterator = 1; iterator <= inst["numOfInputPorts"]; iterator++)
{
ports.push({ name: "input"+iterator.toString(), type: "input" })
ports.push({ name: "input"+iterator.toString(), type: "input32" })
}
for(let iterator = 1; iterator <= inst["numOfOutputPorts"]; iterator++)
{
ports.push({ name: "output"+iterator.toString(), type: "output"})
ports.push({ name: "output"+iterator.toString(), type: "output32"})
}
ports.push({ name: "prev", type: "IO_PREV" })
ports.push({ name: "next", type: "IO_NEXT" })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1393,11 +1393,11 @@ exports = {
let ports = [];
for(let iterator = 1; iterator <= inst["numOfInputPorts"]; iterator++)
{
ports.push({ name: "input"+iterator.toString(), type: "input" })
ports.push({ name: "input"+iterator.toString(), type: "input32" })
}
for(let iterator = 1; iterator <= inst["numOfOutputPorts"]; iterator++)
{
ports.push({ name: "output"+iterator.toString(), type: "output"})
ports.push({ name: "output"+iterator.toString(), type: "output32"})
}
ports.push({ name: "prev", type: "PREV" })
ports.push({ name: "next", type: "NEXT"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1653,11 +1653,11 @@ exports = {
let ports = [];
for(let iterator = 1; iterator <= inst["numOfInputPorts"]; iterator++)
{
ports.push({ name: "input"+iterator.toString(), type: "input" })
ports.push({ name: "input"+iterator.toString(), type: "input32" })
}
for(let iterator = 1; iterator <= inst["numOfOutputPorts"]; iterator++)
{
ports.push({ name: "output"+iterator.toString(), type: "output"})
ports.push({ name: "output"+iterator.toString(), type: "output32"})
}
ports.push({ name: "prev", type: "PREV" })
ports.push({ name: "next", type: "NEXT"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1421,11 +1421,11 @@ exports = {
let ports = [];
for(let iterator = 1; iterator <= inst["numOfInputPorts"]; iterator++)
{
ports.push({ name: "input"+iterator.toString(), type: "input" })
ports.push({ name: "input"+iterator.toString(), type: "input32" })
}
for(let iterator = 1; iterator <= inst["numOfOutputPorts"]; iterator++)
{
ports.push({ name: "output"+iterator.toString(), type: "output"})
ports.push({ name: "output"+iterator.toString(), type: "output32"})
}
ports.push({ name: "prev", type: "PREV" })
ports.push({ name: "next", type: "NEXT"})
Expand Down
Loading
Loading