Tool to migrate cocotb 1.x tests to cocotb 2.x style
Project description
cocotb2-migrator
A comprehensive tool for migrating cocotb 1.x testbenches to cocotb 2.x with async/await syntax and modern Python practices.
Overview
cocotb2-migrator automates the migration of cocotb testbenches from version 1.x to 2.x by applying a series of code transformations. The tool handles the most common migration patterns including coroutine decorators, fork operations, handle access patterns, binary value usage, deprecated imports, and many other cocotb-specific transformations.
Features
- Coroutine to Async/Await: Converts
@cocotb.coroutinedecorated functions toasync def - Fork to Start Soon: Transforms
cocotb.fork()calls tococotb.start_soon() - Handle Access Modernization: Updates deprecated handle value access patterns
- Binary Value Updates: Migrates
BinaryValuetoLogicArraywith appropriate method calls - Clock Transformations: Updates Clock API usage and removes deprecated parameters
- Environment Variables: Updates deprecated environment variable names to cocotb 2.x conventions
- Join Operations: Simplifies Join operations for direct awaiting
- LogicArray Modernization: Updates LogicArray API usage and imports
- Task Management: Updates Task API methods and imports
- Import Cleanup: Removes or updates deprecated import statements
- Comprehensive Reporting: Generates detailed migration reports in JSON or console format
- In-place Transformation: Safely updates files with syntax highlighting and diff display
Installation
From PyPI (Recommended)
pip install cocotb2-migrator
From Source
git clone https://github.com/aayush598/cocotb2-migrator.git
cd cocotb2-migrator
pip install -e .
Usage
Command Line Interface
# Basic usage - migrate all Python files in a directory
cocotb2-migrator /path/to/your/cocotb/project
# Generate a migration report
cocotb2-migrator /path/to/project --report migration_report.json
# Example with real path
cocotb2-migrator ./testbenches --report ./reports/migration.json
Python API
from cocotb2_migrator.main import main
from cocotb2_migrator.migrator import migrate_directory
from cocotb2_migrator.report import MigrationReport
# Using the API directly
report = MigrationReport()
migrate_directory('/path/to/project', report)
report.print() # Display in console
report.save('migration_report.json') # Save to file
Migration Transformations
1. Coroutine to Async/Await
Converts legacy coroutine syntax to modern async/await:
Before:
@cocotb.coroutine
def my_test_function(dut):
yield Timer(10)
yield RisingEdge(dut.clk)
After:
async def my_test_function(dut):
await Timer(10)
await RisingEdge(dut.clk)
2. Fork to Start Soon
Updates concurrent execution syntax:
Before:
handle = cocotb.fork(my_background_task())
After:
handle = cocotb.start_soon(my_background_task())
3. Handle Value Access
Modernizes signal value access patterns:
Before:
val = dut.signal.value.get_value()
integer_val = dut.signal.value.integer
binary_str = dut.signal.value.binstr
raw_val = dut.signal.value.raw_value
After:
val = dut.signal.value
integer_val = int(dut.signal.value)
binary_str = format(dut.signal.value, 'b')
raw_val = dut.signal.value
4. Binary Value Updates
Transforms BinaryValue usage to LogicArray with appropriate constructor methods:
Before:
# Basic string conversion
val = BinaryValue('1010')
# Integer with bit width
val = BinaryValue(42, 8)
# Signed representation
val = BinaryValue(42, 8, binaryRepresentation=BinaryRepresentation.SIGNED)
# Bytes with endianness
val = BinaryValue(b"\xAA", bigEndian=True)
val = BinaryValue(b"\xBB", bigEndian=False)
# String treated as bytes with endianness
val = BinaryValue('1010', bigEndian=True)
# Property access
x = val.integer
y = val.signed_integer
z = val.binstr
w = val.buff
After:
# Basic string conversion
val = LogicArray('1010')
# Integer with bit width
val = LogicArray.from_unsigned(42, 8)
# Signed representation
val = LogicArray.from_signed(42, 8)
# Bytes with endianness
val = LogicArray.from_bytes(b"\xAA", byteorder="big")
val = LogicArray.from_bytes(b"\xBB", byteorder="little")
# String treated as bytes with endianness
val = LogicArray.from_bytes('1010', byteorder="big")
# Property access
x = val.to_unsigned()
y = val.to_signed()
z = str(val)
w = val.to_bytes(byteorder="big")
Import transformations:
# Before
from cocotb.binary import BinaryValue
# After
from cocotb.types import LogicArray
Module path transformations:
# Before
val = cocotb.binary.BinaryValue('1010')
val = cocotb.BinaryValue('1010')
# After
val = cocotb.types.LogicArray('1010')
val = LogicArray('1010') # If LogicArray is imported
Special cases handled:
- SIGNED_MAGNITUDE representation: Creates a basic LogicArray with warning comment (no direct equivalent in LogicArray)
- Complex constructor patterns: Automatically determines the appropriate
from_*method based on argument types - Endianness handling: Converts
bigEndian=True/Falsetobyteorder="big"/"little"
5. Clock API Updates
Modernizes Clock usage and removes deprecated parameters:
Before:
clock = Clock(dut.clk, 10, units="ns")
cocotb.start_soon(clock.start())
clk.start(cycles=100)
After:
clock = Clock(dut.clk, 10, unit="ns")
clock.start()
clk.start()
6. Environment Variables
Updates deprecated environment variable names:
Before:
module = os.environ["MODULE"]
toplevel = os.environ["TOPLEVEL"]
testcase = os.getenv("TESTCASE")
After:
module = os.environ["COCOTB_TEST_MODULES"]
toplevel = os.environ["COCOTB_TOPLEVEL"]
testcase = os.getenv("COCOTB_TESTCASE")
7. Join Operations
Simplifies Join operations for direct awaiting:
Before:
from cocotb.triggers import Join
await Join(task)
await task.join()
After:
# Join import removed
await task
await task
8. LogicArray Modernization
Updates LogicArray API usage:
Before:
arr = LogicArray(42)
val = arr.integer
signed_val = arr.signed_integer
binary_str = arr.binstr
bytes_val = arr.buff
After:
arr = LogicArray.from_unsigned(42)
val = arr.to_unsigned()
signed_val = arr.to_signed()
binary_str = str(arr)
bytes_val = arr.to_bytes()
9. Task Management
Updates Task API methods:
Before:
task.kill()
has_started = task.has_started()
raise TestSuccess()
After:
task.cancel()
# task.has_started() removed - manual intervention needed
cocotb.pass_test()
10. Deprecated Imports
Removes or updates deprecated import statements:
Before:
from cocotb.decorators import coroutine
from cocotb.result import TestFailure
from cocotb.regression import TestFactory
After:
from cocotb import coroutine
from cocotb import TestFailure
# cocotb.regression import removed (no longer needed)
Architecture
Core Components
1. Parser (parser.py)
- TransformerPipeline: Orchestrates the application of multiple transformers
- File Operations: Handles reading, writing, and backup of source files
- Syntax Highlighting: Provides rich console output with code highlighting
2. Transformers (transformers/)
All transformers inherit from BaseCocotbTransformer and implement specific migration patterns:
CoroutineToAsyncTransformer: Handles@cocotb.coroutine→async defForkTransformer: Convertscocotb.fork()→cocotb.start_soon()HandleTransformer: Updates signal value access patternsBinaryValueTransformer: MigratesBinaryValuetoLogicArraywith appropriate methodsClockTransformer: Updates Clock API usage and parametersEnvironmentTransformer: Updates environment variable namesJoinTransformer: Simplifies Join operationsLogicArrayTransformer: Modernizes LogicArray APITaskTransformer: Updates Task management methodsDeprecatedImportsTransformer: Cleans up deprecated imports
3. Migration Engine (migrator.py)
- File Discovery: Recursively finds Python files in target directories
- Transformation Application: Applies all transformers to discovered files
- Progress Tracking: Monitors and reports transformation progress
4. Reporting (report.py)
- Console Output: Rich table format with color-coded results
- JSON Export: Structured data for integration with other tools
- Statistics: Comprehensive migration statistics and summaries
Technical Details
LibCST Integration
The tool uses LibCST (Concrete Syntax Tree) for parsing and transforming Python code, ensuring:
- Preservation of Formatting: Comments, whitespace, and code style are maintained
- Accurate Transformations: Syntactically correct transformations
- Error Handling: Robust parsing with detailed error reporting
Transformer Pipeline
ALL_TRANSFORMERS = [
CoroutineToAsyncTransformer,
ForkTransformer,
BinaryValueTransformer,
ClockTransformer,
EnvironmentTransformer,
JoinTransformer,
LogicArrayTransformer,
TaskTransformer,
HandleTransformer,
DeprecatedImportsTransformer,
]
Transformers are applied in sequence, with each transformer:
- Parsing the current AST state
- Applying its specific transformations
- Returning the modified AST
- Tracking whether modifications were made
Requirements
- Python: 3.8 or higher
- Dependencies:
libcst >= 1.0.1: For parsing and transforming Python codeclick: Command-line interface frameworktermcolor: Terminal color outputrich: Enhanced console output with syntax highlighting
Development
Project Structure
cocotb2_migrator/
├── __init__.py
├── main.py # Entry point and CLI coordination
├── cli.py # Command-line argument parsing
├── migrator.py # Core migration logic
├── parser.py # File parsing and transformation pipeline
├── report.py # Migration reporting and statistics
└── transformers/
├── __init__.py
├── base.py # Base transformer class
├── coroutine_transformer.py # Coroutine → async/await
├── fork_transformer.py # Fork → start_soon
├── handle_transformer.py # Handle access patterns
├── binaryvalue_transformer.py # BinaryValue → LogicArray
├── clock_transformer.py # Clock API updates
├── environment_transformer.py # Environment variables
├── join_transformer.py # Join operations
├── logicarray_transformer.py # LogicArray modernization
├── task_transformer.py # Task management
└── deprecated_imports_transformer.py # Import cleanup
Adding New Transformers
- Create a new transformer class inheriting from
BaseCocotbTransformer:
from cocotb2_migrator.transformers.base import BaseCocotbTransformer
import libcst as cst
class MyCustomTransformer(BaseCocotbTransformer):
name = "MyCustomTransformer"
def leave_FunctionDef(self, original_node: cst.FunctionDef, updated_node: cst.FunctionDef) -> cst.FunctionDef:
# Your transformation logic here
if self.should_transform(original_node):
self.mark_modified()
return self.transform_node(updated_node)
return updated_node
- Add the transformer to
ALL_TRANSFORMERSinmigrator.py:
ALL_TRANSFORMERS = [
CoroutineToAsyncTransformer,
ForkTransformer,
BinaryValueTransformer,
ClockTransformer,
EnvironmentTransformer,
JoinTransformer,
LogicArrayTransformer,
TaskTransformer,
HandleTransformer,
DeprecatedImportsTransformer,
MyCustomTransformer, # Add your transformer here
]
Testing
The project includes example files for testing transformations:
examples/legacy_tb.py: Legacy cocotb 1.x testbenchexamples/test_example.py: Comprehensive test cases for all transformers
Run migrations on test files:
python -m cocotb2_migrator examples/ --report test_report.json
Migration Notes
Manual Interventions Required
Some transformations require manual intervention after running the migrator:
- Clock.frequency: This attribute was removed in cocotb 2.x with no direct replacement
- Task.has_started(): This method was removed and needs manual handling
- SIGNED_MAGNITUDE representation: Has no direct LogicArray equivalent - creates basic LogicArray with warning
- Complex environment variable usage: Some complex patterns may need manual review
- Custom coroutine patterns: Advanced coroutine usage may need manual adjustment
Best Practices
- Backup your code: Always backup your codebase before running the migrator
- Run tests: Execute your test suite after migration to ensure functionality
- Review changes: Manually review the generated changes, especially for complex patterns
- Incremental migration: Consider migrating smaller sections first to validate the process
Contributing
Contributions are welcome! Please feel free to submit pull requests or open issues for bugs, feature requests, or improvements.
📬 Author & Support
Author: Aayush Gid
Email: aayushgid598@gmail.com
PyPI Package: cocotb2-migrator on PyPI
GitHub: github.com/aayush598
If you find this project helpful, feel free to ⭐️ the repository and share feedback!
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cocotb2_migrator-0.2.1.tar.gz.
File metadata
- Download URL: cocotb2_migrator-0.2.1.tar.gz
- Upload date:
- Size: 23.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
153a2e8c5a7e5b9516d09c4b31e9d3c7e3cbba58c2ba0502d65d3a185328a671
|
|
| MD5 |
3a92dbc9a3f71168e5c69138a7cc50c9
|
|
| BLAKE2b-256 |
c95cfa18e8a6f5c578af8995be2de0be6c4356c2e114f740c8412cbaf153052f
|
File details
Details for the file cocotb2_migrator-0.2.1-py3-none-any.whl.
File metadata
- Download URL: cocotb2_migrator-0.2.1-py3-none-any.whl
- Upload date:
- Size: 30.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7579b94d02b9e5da44a75eae0b521cc31cc3b3c2fbf4421e0d154f88c32fee59
|
|
| MD5 |
0c871d6d88f67806a06ae22c77a26300
|
|
| BLAKE2b-256 |
d701f15e67e6d4f9aacb299b75d033f26f0a6701aebd45335446dd9c5070f0ff
|