Skip to content

Cleaning up#70

Draft
kikkiakki wants to merge 3 commits intotenstorrent:mainfrom
kikkiakki:reorganize-flash
Draft

Cleaning up#70
kikkiakki wants to merge 3 commits intotenstorrent:mainfrom
kikkiakki:reorganize-flash

Conversation

@kikkiakki
Copy link
Contributor

Trying to move things out of flash.py and compartmentalize code by functionality a bit more.

Major changes:

  • Move live_countdown to utility.py as it's a CLI display util
  • Improve the readability of flash_chip_stage1 by pulling out the FW version compatibility check and the FlashWrite building functionality.
  • Created wormhole.py to put all the tag handlers used to build the flash data. Although the wormhole.py tag handlers are not necessarily Wormhole-specific and work for Grayskull as well, Wormhole will be the only non-deprecated chip that uses them.
  • Formatted all the files with black.

In an attempt to categorize some of the code in flash.py and separate it
out where possible, move live_countdown to utility.py as a command line
utility.

Signed-off-by: Petra Alexson <palexson@tenstorrent.com>
During flash stage 1, there is a FW compatability check that gatekeeps
whether a chip should be flashed or not. Move all this logic into its
own function.

Signed-off-by: Petra Alexson <palexson@tenstorrent.com>
- Create wormhole.py for symmetry with blackhole.py, handles the legacy
SPI format
- Split out functions that create FlashWrite data for WH and BH into
their own files (wormhole.py and blackhole.py respectively).
- Skip flashing Grayskull/any other chips if they are detected.
- Format edited files with black

Signed-off-by: Petra Alexson <palexson@tenstorrent.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the codebase to improve organization and readability by compartmentalizing code by functionality. The main changes include moving utility functions to appropriate modules, extracting complex logic into separate functions, and creating a new module for tag handlers.

  • Extracted live_countdown CLI utility function to utility.py
  • Refactored flash_chip_stage1 by extracting firmware version compatibility checking logic into a separate function
  • Created wormhole.py module to consolidate tag handlers and flash write building functionality
  • Applied black formatting across all modified files

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 16 comments.

File Description
tt_flash/wormhole.py New module containing tag handlers and build_flash_writes_wh function for building flash write data structures
tt_flash/utility.py Added live_countdown function moved from flash.py for CLI display functionality
tt_flash/flash.py Refactored to extract firmware version checking logic, updated imports, and applied formatting
tt_flash/blackhole.py Added build_flash_writes_bh function to encapsulate flash write building logic for Blackhole chips

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

version = tt_flash.__version__

version_parts = version.split(".")
for _ in range(version_parts.__len__(), 4):
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

Incorrect usage of __len__() method. Use the built-in len() function instead: for _ in range(len(version_parts), 4):. The __len__() method is a dunder method that should not be called directly.

Suggested change
for _ in range(version_parts.__len__(), 4):
for _ in range(len(version_parts), 4):

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +26


@dataclass
class FlashWrite:
offset: int
write: bytearray


def rmw_param(
chip: TTChip, data: bytearray, spi_addr: int, data_addr: int, len: int
) -> bytearray:
# Read the existing data
existing_data = chip.spi_read(spi_addr, len)

Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

The FlashWrite dataclass is duplicated across multiple files (defined in both tt_flash/wormhole.py and tt_flash/blackhole.py). This creates maintenance issues and potential inconsistencies. Consider defining FlashWrite once in a shared module (e.g., a common types module) and importing it in both files.

Suggested change
@dataclass
class FlashWrite:
offset: int
write: bytearray
def rmw_param(
chip: TTChip, data: bytearray, spi_addr: int, data_addr: int, len: int
) -> bytearray:
# Read the existing data
existing_data = chip.spi_read(spi_addr, len)
from tt_flash.types import FlashWrite

Copilot uses AI. Check for mistakes.
print(f"{CConfig.COLOR.GREEN}Stage:{CConfig.COLOR.ENDC} RESET")

m3_delay = 20 # M3 takes 20 seconds to boot and be ready after a reset
m3_delay = 20 # M3 takes 20 seconds to boot and be ready after a reset
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

Inconsistent use of constants. The inline comment states "M3 takes 20 seconds to boot" which duplicates the comment for M3_DELAY_NORMAL at line 36. Instead of the magic number 20, use the constant: m3_delay = M3_DELAY_NORMAL.

Suggested change
m3_delay = 20 # M3 takes 20 seconds to boot and be ready after a reset
m3_delay = M3_DELAY_NORMAL # M3 takes 20 seconds to boot and be ready after a reset

Copilot uses AI. Check for mistakes.
force: bool,
allow_major_downgrades: bool,
skip_missing_fw: bool = False,
) -> tuple[bool, str]:
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

The return type annotation is incorrect. This function should return FlashStageResult, not tuple[bool, str]. The function body returns FlashStageResult objects (lines 247-249), which is inconsistent with the type annotation.

Suggested change
) -> tuple[bool, str]:
) -> FlashStageResult:

Copilot uses AI. Check for mistakes.


def build_flash_writes_bh(
chip: BhChip, image: BufferedReader, mask: dict, boardname_to_display: str
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

The parameter type annotation is incorrect. The image parameter is typed as BufferedReader but is actually used as bytes (see line 98 where image.decode("utf-8") is called). The parameter should be typed as bytes instead.

Suggested change
chip: BhChip, image: BufferedReader, mask: dict, boardname_to_display: str
chip: BhChip, image: bytes, mask: dict, boardname_to_display: str

Copilot uses AI. Check for mistakes.
pass

# Check if we can flash based on current version and version to flash
should_flash, reason_message = check_fw_version_compatability(
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

Typo in function name: 'compatability' should be 'compatibility'. This should match the corrected function name at line 90.

Suggested change
should_flash, reason_message = check_fw_version_compatability(
should_flash, reason_message = check_fw_version_compatibility(

Copilot uses AI. Check for mistakes.
Comment on lines +103 to +105
for _ in range(__SEMANTIC_BUNDLE_VERSION.__len__(), 4):
__SEMANTIC_BUNDLE_VERSION.append(0)
version_parts = __SEMANTIC_BUNDLE_VERSION[:4]
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

The function modifies the global list __SEMANTIC_BUNDLE_VERSION in place by appending elements (line 104). This can lead to unexpected behavior if the function is called multiple times, as the list will continue to grow beyond 4 elements. Consider creating a copy of the list or resetting it before modification: version_parts = __SEMANTIC_BUNDLE_VERSION.copy() followed by extending it to length 4.

Suggested change
for _ in range(__SEMANTIC_BUNDLE_VERSION.__len__(), 4):
__SEMANTIC_BUNDLE_VERSION.append(0)
version_parts = __SEMANTIC_BUNDLE_VERSION[:4]
version_parts = __SEMANTIC_BUNDLE_VERSION.copy()
for _ in range(len(version_parts), 4):
version_parts.insert(0, 0)
version_parts = version_parts[:4]

Copilot uses AI. Check for mistakes.
) -> bytearray:
global __SEMANTIC_BUNDLE_VERSION

for _ in range(__SEMANTIC_BUNDLE_VERSION.__len__(), 4):
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

Incorrect usage of __len__() method. Use the built-in len() function instead: for _ in range(len(__SEMANTIC_BUNDLE_VERSION), 4):. The __len__() method is a dunder method that should not be called directly.

Suggested change
for _ in range(__SEMANTIC_BUNDLE_VERSION.__len__(), 4):
for _ in range(len(__SEMANTIC_BUNDLE_VERSION), 4):

Copilot uses AI. Check for mistakes.
Comment on lines +90 to +96
def check_fw_version_compatability(
chip: TTChip, manifest: Manifest, force: bool, allow_major_downgrades: bool
) -> tuple[bool, str]:
"""
This function is used in Flash Stage 1 to perform the following:
1. Read the fw_bundle_version from the chip. If any errors are encountered, only proceed if we detect that exceptions are allowed (e.g. in the case of very old GS or WH firmware)
2. Check major version compatability between a chip's currently running FW and the FW we want to update to. Typically disallow major downgrades and only allow upgrades across one major version boundary.
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

Typo in function name: 'compatability' should be 'compatibility'. The correct spelling is 'compatibility' throughout the codebase.

Suggested change
def check_fw_version_compatability(
chip: TTChip, manifest: Manifest, force: bool, allow_major_downgrades: bool
) -> tuple[bool, str]:
"""
This function is used in Flash Stage 1 to perform the following:
1. Read the fw_bundle_version from the chip. If any errors are encountered, only proceed if we detect that exceptions are allowed (e.g. in the case of very old GS or WH firmware)
2. Check major version compatability between a chip's currently running FW and the FW we want to update to. Typically disallow major downgrades and only allow upgrades across one major version boundary.
def check_fw_version_compatibility(
chip: TTChip, manifest: Manifest, force: bool, allow_major_downgrades: bool
) -> tuple[bool, str]:
"""
This function is used in Flash Stage 1 to perform the following:
1. Read the fw_bundle_version from the chip. If any errors are encountered, only proceed if we detect that exceptions are allowed (e.g. in the case of very old GS or WH firmware)
2. Check major version compatibility between a chip's currently running FW and the FW we want to update to. Typically disallow major downgrades and only allow upgrades across one major version boundary.

Copilot uses AI. Check for mistakes.
Comment on lines +192 to 196
return (
False,
"ROM does not need to be updated, cannot detect the running FW version but the SPI is ahead of the firmware you are attempting to flash. "
"You can load the newer firmware after a reset. Or skip this check with --force.",
)
Copy link

Copilot AI Nov 15, 2025

Choose a reason for hiding this comment

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

This statement is unreachable.

Copilot uses AI. Check for mistakes.
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.

1 participant