|
CocoTB Framework · Verification Infrastructure for RTL Testing GitHub · Documentation Index · MIT License |
apb_gaxi_scoreboard.py¶
APB-GAXI bridge scoreboard implementation for verifying protocol conversion between APB and GAXI protocols. This module provides specialized verification for APB-GAXI bridge systems with comprehensive transaction matching and response validation.
Overview¶
The APB-GAXI scoreboard system provides: - Three-Phase Transaction Matching: APB transaction → GAXI command → GAXI response - Protocol-Aware Verification: Understands both APB and GAXI protocol semantics - Response Handling: Proper matching of both read and write responses - Enhanced Error Classification: Detailed error categorization and field-level analysis - Timeout-Based Matching: Robust verification with configurable timeouts
Classes¶
APBGAXIScoreboard¶
Comprehensive APB-GAXI bridge verification with three-queue transaction matching.
Parameters:
- name: Scoreboard name for identification
- log: Logger instance for detailed reporting
Key Features: - Separate transaction queues for APB, GAXI commands, and GAXI responses - Automatic timeout-based transaction matching - Comprehensive statistics tracking - Enhanced error reporting with field extraction
Transaction Queues:
- apb_queue: APB transactions from master/slave interface
- gaxi_cmd_queue: GAXI command transactions
- gaxi_rsp_queue: GAXI response transactions
Core Methods¶
Transaction Management¶
add_apb_transaction(transaction)¶
Add APB transaction to the scoreboard for verification.
Parameters:
- transaction: APB transaction to be matched
Behavior:
- Extracts APB transaction fields using APBTransactionExtractor
- Stores transaction with timestamp for timeout management
- Increments APB transaction counter
- Triggers automatic matching attempt
# Add APB transaction
apb_transaction = create_apb_write(addr=0x1000, data=0xDEADBEEF)
scoreboard.add_apb_transaction(apb_transaction)
add_gaxi_command(transaction)¶
Add GAXI command transaction for bridge verification.
Parameters:
- transaction: GAXI command transaction
Behavior: - Extracts command fields (address, data, operation type) - Stores in GAXI command queue with timestamp - Updates command transaction statistics - Attempts transaction matching
# Add GAXI command
gaxi_command = create_gaxi_command(addr=0x1000, data=0xDEADBEEF, cmd=1)
scoreboard.add_gaxi_command(gaxi_command)
add_gaxi_response(transaction)¶
Add GAXI response transaction for completion verification.
Parameters:
- transaction: GAXI response transaction
Behavior: - Extracts response fields (data, status, error indicators) - Stores in GAXI response queue with timestamp - Tracks error transactions based on response status - Triggers comprehensive matching
# Add GAXI response
gaxi_response = create_gaxi_response(data=0xDEADBEEF, status='OKAY')
scoreboard.add_gaxi_response(gaxi_response)
Transaction Matching¶
_match_transactions()¶
Core matching algorithm for three-phase transaction verification.
Matching Logic: 1. APB-GAXI Command Matching: Matches APB transactions with corresponding GAXI commands based on address and operation type 2. Command-Response Pairing: Links GAXI commands with their responses using transaction identifiers 3. End-to-End Verification: Ensures complete APB→GAXI→Response flow integrity
Timeout Handling:
- Configurable timeout (match_timeout_ns) for transaction completion
- Automatic cleanup of expired transactions
- Timeout error reporting and statistics
Field Extraction and Formatting¶
The scoreboard uses APBTransactionExtractor for robust field extraction:
APB Transaction Fields¶
- Command Fields: Address, data, write enable, strobe
- Response Fields: Read data, error status, completion status
- Timing Fields: Start time, end time, duration
GAXI Transaction Fields¶
- Command Fields: Address, data, command type, strobe
- Response Fields: Response data, status codes, error indicators
# Example field extraction
apb_fields = APBTransactionExtractor.extract_command_fields(apb_transaction)
# Returns: {'addr': 0x1000, 'data': 0xDEADBEEF, 'is_write': True, 'strb': 0xF}
gaxi_fields = APBTransactionExtractor.extract_response_fields(gaxi_response)
# Returns: {'data': 0xDEADBEEF, 'has_error': False, 'status': 'OKAY'}
Statistics and Reporting¶
Comprehensive Statistics Tracking¶
The scoreboard maintains detailed statistics:
stats = {
'apb_transactions': 0, # Total APB transactions
'gaxi_cmd_transactions': 0, # Total GAXI commands
'gaxi_rsp_transactions': 0, # Total GAXI responses
'matched_pairs': 0, # Successfully matched complete flows
'matched_write_responses': 0, # Matched write responses
'matched_read_responses': 0, # Matched read responses
'unmatched_apb': 0, # Unmatched APB transactions
'unmatched_gaxi_cmd': 0, # Unmatched GAXI commands
'unmatched_gaxi_rsp': 0, # Unmatched GAXI responses
'error_transactions': 0, # Transactions with errors
'field_extraction_errors': 0, # Field extraction failures
'transaction_type_errors': 0 # Invalid transaction types
}
Reporting Methods¶
report()¶
Generate comprehensive scoreboard report.
Returns:
- str: Detailed report with all statistics and analysis
Report Contents: - Transaction counts for all three phases - Match success rates for reads and writes - Error analysis and unmatched transaction counts - Field extraction and type error statistics
print(scoreboard.report())
# Output:
# === APB-GAXI Scoreboard Report (BridgeTest) ===
# APB Transactions: 150
# GAXI Commands: 148
# GAXI Responses: 147
# Matched Pairs: 145
# - Write Responses: 85
# - Read Responses: 60
# Error Transactions: 2
# Unmatched APB: 5
# Unmatched GAXI CMD: 3
# Unmatched GAXI RSP: 2
get_stats()¶
Get detailed statistics dictionary for programmatic analysis.
Returns:
- dict: Complete statistics dictionary
stats = scoreboard.get_stats()
success_rate = stats['matched_pairs'] / stats['apb_transactions'] * 100
print(f"Bridge success rate: {success_rate:.2f}%")
Utility Methods¶
clear()¶
Reset scoreboard state for new test phase.
Behavior: - Clears all transaction queues - Resets all statistics counters - Preserves configuration settings
Usage Examples¶
Basic APB-GAXI Bridge Verification¶
from CocoTBFramework.scoreboards.apb_gaxi_scoreboard import APBGAXIScoreboard
from CocoTBFramework.components.apb.apb_packet import APBPacket
from CocoTBFramework.components.gaxi.gaxi_packet import GAXIPacket
# Create bridge scoreboard
scoreboard = APBGAXIScoreboard("APB_GAXI_Bridge", log=logger)
# Configure timeout for bridge latency
scoreboard.match_timeout_ns = 1000 # 1μs timeout
# Test write transaction flow
apb_write = APBPacket()
apb_write.direction = 'WRITE'
apb_write.paddr = 0x2000
apb_write.pwdata = 0x12345678
apb_write.pstrb = 0xF
gaxi_cmd = GAXIPacket(field_config)
gaxi_cmd.fields['addr'] = 0x2000
gaxi_cmd.fields['data'] = 0x12345678
gaxi_cmd.fields['cmd'] = 1 # Write
gaxi_cmd.fields['strb'] = 0xF
gaxi_rsp = GAXIPacket(field_config)
gaxi_rsp.fields['data'] = 0x0 # Write response (no data)
gaxi_rsp.fields['status'] = 0 # OKAY
# Add transactions in sequence
scoreboard.add_apb_transaction(apb_write)
scoreboard.add_gaxi_command(gaxi_cmd)
scoreboard.add_gaxi_response(gaxi_rsp)
# Verify bridge operation
report = scoreboard.report()
print(report)
# Check success rate
stats = scoreboard.get_stats()
if stats['matched_pairs'] == stats['apb_transactions']:
print("Bridge verification: PASS")
else:
print(f"Bridge verification: FAIL ({stats['matched_pairs']}/{stats['apb_transactions']} matched)")
Read Transaction Verification¶
# Test read transaction flow
async def test_bridge_read_flow():
scoreboard = APBGAXIScoreboard("Read_Bridge", log=logger)
# APB read request
apb_read = APBPacket()
apb_read.direction = 'READ'
apb_read.paddr = 0x3000
apb_read.prdata = 0xABCDEF00 # Expected read data
# Corresponding GAXI command
gaxi_cmd = GAXIPacket(field_config)
gaxi_cmd.fields['addr'] = 0x3000
gaxi_cmd.fields['cmd'] = 0 # Read
# GAXI response with read data
gaxi_rsp = GAXIPacket(field_config)
gaxi_rsp.fields['data'] = 0xABCDEF00
gaxi_rsp.fields['status'] = 0 # OKAY
# Simulate bridge operation timing
scoreboard.add_apb_transaction(apb_read)
await Timer(100, units='ns') # Bridge processing delay
scoreboard.add_gaxi_command(gaxi_cmd)
await Timer(50, units='ns') # Memory access delay
scoreboard.add_gaxi_response(gaxi_rsp)
# Verify read flow
stats = scoreboard.get_stats()
assert stats['matched_read_responses'] == 1, "Read response not matched"
assert stats['error_transactions'] == 0, "Unexpected errors detected"
print("Read bridge verification: PASS")
High-Throughput Bridge Testing¶
# Test bridge with multiple concurrent transactions
async def test_high_throughput_bridge():
scoreboard = APBGAXIScoreboard("HighThroughput", log=logger)
scoreboard.match_timeout_ns = 10000 # 10μs for high throughput
# Generate transaction patterns
num_transactions = 100
transaction_pairs = []
for i in range(num_transactions):
# Alternating read/write pattern
is_write = (i % 2 == 0)
addr = 0x10000 + (i * 4)
data = 0xDEAD0000 + i
# APB transaction
apb_tx = APBPacket()
apb_tx.direction = 'WRITE' if is_write else 'READ'
apb_tx.paddr = addr
if is_write:
apb_tx.pwdata = data
apb_tx.pstrb = 0xF
else:
apb_tx.prdata = data
# GAXI command
gaxi_cmd = GAXIPacket(field_config)
gaxi_cmd.fields['addr'] = addr
gaxi_cmd.fields['cmd'] = 1 if is_write else 0
if is_write:
gaxi_cmd.fields['data'] = data
gaxi_cmd.fields['strb'] = 0xF
# GAXI response
gaxi_rsp = GAXIPacket(field_config)
gaxi_rsp.fields['data'] = data if not is_write else 0
gaxi_rsp.fields['status'] = 0 # OKAY
transaction_pairs.append((apb_tx, gaxi_cmd, gaxi_rsp))
# Simulate concurrent bridge operation
for apb_tx, gaxi_cmd, gaxi_rsp in transaction_pairs:
scoreboard.add_apb_transaction(apb_tx)
# Small delay for bridge processing
await Timer(10, units='ns')
scoreboard.add_gaxi_command(gaxi_cmd)
# Memory response delay
await Timer(5, units='ns')
scoreboard.add_gaxi_response(gaxi_rsp)
# Wait for all matching to complete
await Timer(1000, units='ns')
# Analyze results
stats = scoreboard.get_stats()
print(f"High-throughput test results:")
print(f" APB transactions: {stats['apb_transactions']}")
print(f" Matched pairs: {stats['matched_pairs']}")
print(f" Success rate: {stats['matched_pairs']/stats['apb_transactions']*100:.1f}%")
print(f" Write responses: {stats['matched_write_responses']}")
print(f" Read responses: {stats['matched_read_responses']}")
# Verify performance
assert stats['matched_pairs'] >= num_transactions * 0.95, "Insufficient match rate"
assert stats['error_transactions'] == 0, "Unexpected error transactions"
print("High-throughput bridge verification: PASS")
Error Injection and Recovery Testing¶
# Test bridge error handling
async def test_bridge_error_handling():
scoreboard = APBGAXIScoreboard("ErrorTest", log=logger)
# Normal transaction
normal_apb = create_apb_write(addr=0x1000, data=0x11111111)
normal_cmd = create_gaxi_command(addr=0x1000, data=0x11111111, cmd=1)
normal_rsp = create_gaxi_response(status='OKAY')
# Error transaction
error_apb = create_apb_write(addr=0x2000, data=0x22222222)
error_cmd = create_gaxi_command(addr=0x2000, data=0x22222222, cmd=1)
error_rsp = create_gaxi_response(status='SLVERR') # Slave error
# Timeout transaction (no response)
timeout_apb = create_apb_write(addr=0x3000, data=0x33333333)
timeout_cmd = create_gaxi_command(addr=0x3000, data=0x33333333, cmd=1)
# No response - will timeout
# Add transactions
scoreboard.add_apb_transaction(normal_apb)
scoreboard.add_gaxi_command(normal_cmd)
scoreboard.add_gaxi_response(normal_rsp)
scoreboard.add_apb_transaction(error_apb)
scoreboard.add_gaxi_command(error_cmd)
scoreboard.add_gaxi_response(error_rsp)
scoreboard.add_apb_transaction(timeout_apb)
scoreboard.add_gaxi_command(timeout_cmd)
# No response added
# Wait for timeout
await Timer(scoreboard.match_timeout_ns + 1000, units='ns')
# Analyze error handling
stats = scoreboard.get_stats()
print("Error handling test results:")
print(f" Total APB transactions: {stats['apb_transactions']}")
print(f" Matched pairs: {stats['matched_pairs']}")
print(f" Error transactions: {stats['error_transactions']}")
print(f" Unmatched responses: {stats['unmatched_gaxi_rsp']}")
# Verify error detection
assert stats['error_transactions'] >= 1, "Error transaction not detected"
assert stats['unmatched_gaxi_rsp'] >= 1, "Timeout not detected"
print("Error handling verification: PASS")
Multi-Bridge System Verification¶
# Test system with multiple APB-GAXI bridges
class MultiBridgeTestEnvironment:
def __init__(self, num_bridges):
self.scoreboards = {}
for i in range(num_bridges):
self.scoreboards[i] = APBGAXIScoreboard(f"Bridge_{i}", log=logger)
def add_bridge_transaction(self, bridge_id, apb_tx, gaxi_cmd, gaxi_rsp):
if bridge_id in self.scoreboards:
sb = self.scoreboards[bridge_id]
sb.add_apb_transaction(apb_tx)
sb.add_gaxi_command(gaxi_cmd)
sb.add_gaxi_response(gaxi_rsp)
def generate_comprehensive_report(self):
total_stats = {
'apb_transactions': 0,
'matched_pairs': 0,
'error_transactions': 0
}
print("=== Multi-Bridge System Report ===")
for bridge_id, scoreboard in self.scoreboards.items():
stats = scoreboard.get_stats()
total_stats['apb_transactions'] += stats['apb_transactions']
total_stats['matched_pairs'] += stats['matched_pairs']
total_stats['error_transactions'] += stats['error_transactions']
success_rate = stats['matched_pairs'] / stats['apb_transactions'] * 100 if stats['apb_transactions'] > 0 else 0
print(f"Bridge {bridge_id}: {stats['matched_pairs']}/{stats['apb_transactions']} ({success_rate:.1f}%)")
overall_success = total_stats['matched_pairs'] / total_stats['apb_transactions'] * 100 if total_stats['apb_transactions'] > 0 else 0
print(f"Overall System: {total_stats['matched_pairs']}/{total_stats['apb_transactions']} ({overall_success:.1f}%)")
print(f"Total Errors: {total_stats['error_transactions']}")
return total_stats
# Usage
async def test_multi_bridge_system():
test_env = MultiBridgeTestEnvironment(num_bridges=4)
# Generate transactions for each bridge
for bridge_id in range(4):
for addr_offset in range(10):
addr = 0x10000 + (bridge_id * 0x1000) + (addr_offset * 4)
data = 0xB0000000 + (bridge_id << 16) + addr_offset
apb_tx = create_apb_write(addr=addr, data=data)
gaxi_cmd = create_gaxi_command(addr=addr, data=data, cmd=1)
gaxi_rsp = create_gaxi_response(status='OKAY')
test_env.add_bridge_transaction(bridge_id, apb_tx, gaxi_cmd, gaxi_rsp)
await Timer(50, units='ns')
# Generate system report
system_stats = test_env.generate_comprehensive_report()
# Verify system performance
assert system_stats['error_transactions'] == 0, "System errors detected"
assert system_stats['matched_pairs'] == system_stats['apb_transactions'], "Incomplete transaction matching"
print("Multi-bridge system verification: PASS")
Best Practices¶
Timeout Configuration¶
- Configure appropriate timeouts based on bridge latency characteristics
- Use shorter timeouts for low-latency bridges
- Account for memory access delays in timeout calculations
Transaction Ordering¶
- Add transactions in realistic temporal order
- Ensure APB transactions are added before corresponding GAXI commands
- Add GAXI responses promptly after commands for timing accuracy
Error Analysis¶
- Enable detailed logging for field extraction debugging
- Monitor timeout statistics for performance analysis
- Use error classification for systematic debugging
Performance Optimization¶
- Clear scoreboards between major test phases
- Monitor queue sizes in high-throughput scenarios
- Use appropriate timeout values to balance accuracy and performance
Integration Points¶
Monitor Integration¶
# Connect monitors to scoreboard
def on_apb_transaction(packet):
scoreboard.add_apb_transaction(packet)
def on_gaxi_command(packet):
scoreboard.add_gaxi_command(packet)
def on_gaxi_response(packet):
scoreboard.add_gaxi_response(packet)
apb_monitor.add_callback(on_apb_transaction)
gaxi_cmd_monitor.add_callback(on_gaxi_command)
gaxi_rsp_monitor.add_callback(on_gaxi_response)
Test Environment Integration¶
# Complete bridge test environment
class APBGAXIBridgeTestEnv:
def __init__(self, dut, clock):
self.scoreboard = APBGAXIScoreboard("BridgeEnv", log=logger)
# Connect monitors
self.apb_monitor = APBMonitor(dut.apb, clock)
self.gaxi_cmd_monitor = GAXIMonitor(dut.gaxi_cmd, clock)
self.gaxi_rsp_monitor = GAXIMonitor(dut.gaxi_rsp, clock)
# Connect callbacks
self.apb_monitor.add_callback(self.scoreboard.add_apb_transaction)
self.gaxi_cmd_monitor.add_callback(self.scoreboard.add_gaxi_command)
self.gaxi_rsp_monitor.add_callback(self.scoreboard.add_gaxi_response)
def get_verification_results(self):
return {
'report': self.scoreboard.report(),
'stats': self.scoreboard.get_stats()
}
The APB-GAXI scoreboard provides comprehensive verification for protocol bridge systems with robust transaction matching, detailed error analysis, and extensive configuration options for complex multi-bridge verification scenarios.