test: add cocotb LDPC basic decode test with firmware
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,3 +5,4 @@ from user_proj_tests.counter_la.counter_la import counter_la
|
|||||||
from user_proj_tests.counter_la_reset.counter_la_reset import counter_la_reset
|
from user_proj_tests.counter_la_reset.counter_la_reset import counter_la_reset
|
||||||
from user_proj_tests.counter_la_clk.counter_la_clk import counter_la_clk
|
from user_proj_tests.counter_la_clk.counter_la_clk import counter_la_clk
|
||||||
from gpio_test.gpio_test import gpio_test
|
from gpio_test.gpio_test import gpio_test
|
||||||
|
from ldpc_tests.ldpc_basic.ldpc_basic import ldpc_basic
|
||||||
|
|||||||
140
verilog/dv/cocotb/ldpc_tests/ldpc_basic/ldpc_basic.c
Normal file
140
verilog/dv/cocotb/ldpc_tests/ldpc_basic/ldpc_basic.c
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 LDPC Optical Project
|
||||||
|
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LDPC Basic Decode Test Firmware
|
||||||
|
*
|
||||||
|
* Runs on PicoRV32 inside Caravel. Exercises the LDPC decoder via Wishbone:
|
||||||
|
* 1. Checks VERSION register
|
||||||
|
* 2. Writes all-zero-codeword LLRs (all +31)
|
||||||
|
* 3. Starts decode with early termination
|
||||||
|
* 4. Polls until done
|
||||||
|
* 5. Checks convergence, syndrome weight, and decoded bits
|
||||||
|
* 6. Signals pass (0xAB) or fail (0xFF) on GPIO[7:0]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <firmware_apis.h>
|
||||||
|
|
||||||
|
// LDPC register word offsets (byte_addr / 4)
|
||||||
|
#define LDPC_CTRL 0 // 0x00
|
||||||
|
#define LDPC_STATUS 1 // 0x04
|
||||||
|
#define LDPC_LLR_BASE 4 // 0x10
|
||||||
|
#define LDPC_DECODED 20 // 0x50
|
||||||
|
#define LDPC_VERSION 21 // 0x54
|
||||||
|
|
||||||
|
#define LLR_WORD_COUNT 52 // 260 LLRs / 5 per word, rounded up
|
||||||
|
|
||||||
|
// CTRL register fields
|
||||||
|
#define CTRL_START (1 << 0)
|
||||||
|
#define CTRL_EARLY_TERM (1 << 1)
|
||||||
|
#define CTRL_MAX_ITER(n) (((n) & 0x1F) << 8)
|
||||||
|
|
||||||
|
// STATUS register fields
|
||||||
|
#define STATUS_BUSY (1 << 0)
|
||||||
|
#define STATUS_CONVERGED (1 << 1)
|
||||||
|
#define STATUS_ITER_MASK (0x1F << 8)
|
||||||
|
#define STATUS_SYN_MASK (0xFF << 16)
|
||||||
|
|
||||||
|
// Expected values
|
||||||
|
#define EXPECTED_VERSION 0x1D010001
|
||||||
|
#define PASS_SIGNATURE 0xAB
|
||||||
|
#define FAIL_SIGNATURE 0xFF
|
||||||
|
|
||||||
|
// All-zero codeword: every LLR = +31 (6'b011111 = 0x1F)
|
||||||
|
// Pack 5x 0x1F per word:
|
||||||
|
// (0x1F << 0) | (0x1F << 6) | (0x1F << 12) | (0x1F << 18) | (0x1F << 24)
|
||||||
|
// = 0x1F | 0x7C0 | 0x1F000 | 0x7C0000 | 0x1F000000
|
||||||
|
// = 0x1F7DF7DF
|
||||||
|
#define ALL_ZERO_LLR_WORD 0x1F7DF7DF
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
unsigned int status;
|
||||||
|
unsigned int decoded;
|
||||||
|
unsigned int version;
|
||||||
|
int pass = 1;
|
||||||
|
|
||||||
|
// --- Setup management GPIO for synchronization ---
|
||||||
|
ManagmentGpio_outputEnable();
|
||||||
|
ManagmentGpio_write(0);
|
||||||
|
enableHkSpi(0);
|
||||||
|
|
||||||
|
// Configure all GPIOs as management standard output (driven by firmware)
|
||||||
|
GPIOs_configureAll(GPIO_MODE_MGMT_STD_OUTPUT);
|
||||||
|
GPIOs_loadConfigs();
|
||||||
|
|
||||||
|
// Clear GPIO output
|
||||||
|
GPIOs_writeLow(0x00000000);
|
||||||
|
|
||||||
|
// Enable Wishbone interface to user project
|
||||||
|
User_enableIF();
|
||||||
|
|
||||||
|
// Signal firmware ready
|
||||||
|
ManagmentGpio_write(1);
|
||||||
|
|
||||||
|
// --- Step 1: Read and verify VERSION register ---
|
||||||
|
version = USER_readWord(LDPC_VERSION);
|
||||||
|
if (version != EXPECTED_VERSION) {
|
||||||
|
pass = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Step 2: Write all-zero-codeword LLRs ---
|
||||||
|
// All 256 LLRs = +31 (strong confidence in bit=0)
|
||||||
|
// Last word (index 51) has only 1 LLR, upper bits zero
|
||||||
|
for (int i = 0; i < LLR_WORD_COUNT - 1; i++) {
|
||||||
|
USER_writeWord(ALL_ZERO_LLR_WORD, LDPC_LLR_BASE + i);
|
||||||
|
}
|
||||||
|
// Last word: only LLR[255] = +31, remaining slots zero
|
||||||
|
// bits[5:0] = 0x1F, bits[29:6] = 0
|
||||||
|
USER_writeWord(0x0000001F, LDPC_LLR_BASE + LLR_WORD_COUNT - 1);
|
||||||
|
|
||||||
|
// --- Step 3: Start decode ---
|
||||||
|
// start=1, early_term_en=1, max_iter=30
|
||||||
|
USER_writeWord(CTRL_START | CTRL_EARLY_TERM | CTRL_MAX_ITER(30), LDPC_CTRL);
|
||||||
|
|
||||||
|
// --- Step 4: Poll STATUS until not busy ---
|
||||||
|
do {
|
||||||
|
status = USER_readWord(LDPC_STATUS);
|
||||||
|
} while (status & STATUS_BUSY);
|
||||||
|
|
||||||
|
// --- Step 5: Check results ---
|
||||||
|
// Check converged (bit 1)
|
||||||
|
if (!(status & STATUS_CONVERGED)) {
|
||||||
|
pass = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check syndrome weight = 0 (bits [23:16])
|
||||||
|
if ((status & STATUS_SYN_MASK) != 0) {
|
||||||
|
pass = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read decoded info bits (should be all zero for all-zero codeword)
|
||||||
|
decoded = USER_readWord(LDPC_DECODED);
|
||||||
|
if (decoded != 0x00000000) {
|
||||||
|
pass = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Step 6: Signal result via GPIO[7:0] ---
|
||||||
|
if (pass) {
|
||||||
|
GPIOs_writeLow(PASS_SIGNATURE); // 0xAB = pass
|
||||||
|
} else {
|
||||||
|
GPIOs_writeLow(FAIL_SIGNATURE); // 0xFF = fail
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal test complete via management GPIO
|
||||||
|
ManagmentGpio_write(0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
82
verilog/dv/cocotb/ldpc_tests/ldpc_basic/ldpc_basic.py
Normal file
82
verilog/dv/cocotb/ldpc_tests/ldpc_basic/ldpc_basic.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2024 LDPC Optical Project
|
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
"""
|
||||||
|
LDPC Basic Decode Test - cocotb Monitor
|
||||||
|
|
||||||
|
Tests the LDPC decoder via Wishbone by running firmware on PicoRV32 that:
|
||||||
|
1. Verifies the VERSION register
|
||||||
|
2. Loads all-zero-codeword LLRs
|
||||||
|
3. Runs a decode
|
||||||
|
4. Checks convergence, syndrome weight, and decoded bits
|
||||||
|
5. Signals pass (0xAB) or fail (0xFF) on GPIO[7:0]
|
||||||
|
|
||||||
|
The cocotb monitor waits for the management GPIO to signal firmware ready,
|
||||||
|
then waits for the management GPIO to drop (test complete), and reads
|
||||||
|
GPIO[7:0] for the pass/fail result.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from caravel_cocotb.caravel_interfaces import test_configure
|
||||||
|
from caravel_cocotb.caravel_interfaces import report_test
|
||||||
|
import cocotb
|
||||||
|
|
||||||
|
PASS_SIGNATURE = 0xAB
|
||||||
|
FAIL_SIGNATURE = 0xFF
|
||||||
|
|
||||||
|
|
||||||
|
@cocotb.test()
|
||||||
|
@report_test
|
||||||
|
async def ldpc_basic(dut):
|
||||||
|
caravelEnv = await test_configure(dut, timeout_cycles=300000)
|
||||||
|
|
||||||
|
cocotb.log.info("[TEST] Starting LDPC basic decode test")
|
||||||
|
|
||||||
|
# Release CSB to allow GPIO to function
|
||||||
|
await caravelEnv.release_csb()
|
||||||
|
|
||||||
|
# Wait for firmware to signal ready (mgmt_gpio = 1)
|
||||||
|
cocotb.log.info("[TEST] Waiting for firmware ready (mgmt_gpio=1)...")
|
||||||
|
await caravelEnv.wait_mgmt_gpio(1)
|
||||||
|
cocotb.log.info("[TEST] Firmware ready, decode in progress...")
|
||||||
|
|
||||||
|
# Wait for firmware to signal test complete (mgmt_gpio = 0)
|
||||||
|
await caravelEnv.wait_mgmt_gpio(0)
|
||||||
|
cocotb.log.info("[TEST] Firmware signaled test complete")
|
||||||
|
|
||||||
|
# Read GPIO[7:0] for pass/fail result
|
||||||
|
gpio_val = caravelEnv.monitor_gpio(7, 0)
|
||||||
|
|
||||||
|
if not gpio_val.is_resolvable:
|
||||||
|
cocotb.log.error(
|
||||||
|
f"[TEST] FAIL - GPIO[7:0] is unresolvable: {gpio_val.binstr}"
|
||||||
|
)
|
||||||
|
assert False, "GPIO[7:0] has X/Z values"
|
||||||
|
|
||||||
|
result = gpio_val.integer
|
||||||
|
cocotb.log.info(f"[TEST] GPIO[7:0] = 0x{result:02X}")
|
||||||
|
|
||||||
|
if result == PASS_SIGNATURE:
|
||||||
|
cocotb.log.info("[TEST] PASS - Firmware reported decode success (0xAB)")
|
||||||
|
elif result == FAIL_SIGNATURE:
|
||||||
|
cocotb.log.error(
|
||||||
|
"[TEST] FAIL - Firmware reported decode failure (0xFF)"
|
||||||
|
)
|
||||||
|
assert False, "Firmware reported LDPC decode failure"
|
||||||
|
else:
|
||||||
|
cocotb.log.error(
|
||||||
|
f"[TEST] FAIL - Unexpected GPIO value: 0x{result:02X}"
|
||||||
|
)
|
||||||
|
assert False, f"Unexpected GPIO result: 0x{result:02X}"
|
||||||
19
verilog/dv/cocotb/ldpc_tests/ldpc_basic/ldpc_basic.yaml
Normal file
19
verilog/dv/cocotb/ldpc_tests/ldpc_basic/ldpc_basic.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
# SPDX-FileCopyrightText: 2024 LDPC Optical Project
|
||||||
|
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
Tests:
|
||||||
|
- {name: ldpc_basic, sim: RTL}
|
||||||
Reference in New Issue
Block a user