From f18c72b9b255e6511cb7eff5081a9fce4df6daa6 Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Sat, 15 Apr 2023 14:59:48 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=F0=9F=90=9B=20fix:=20remove=20`self.=5Ff?= =?UTF-8?q?ixed=5Fcore=5Fcoord`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paitest/paitest.py | 259 +++++++++++++++++++++++++++++++------------- paitest/paitest.pyi | 41 ++++--- 2 files changed, 206 insertions(+), 94 deletions(-) diff --git a/paitest/paitest.py b/paitest/paitest.py index 91bcb44..4ffe878 100644 --- a/paitest/paitest.py +++ b/paitest/paitest.py @@ -7,62 +7,69 @@ from .log import logger -__all__ = [ - "paitest" -] +__all__ = ["paitest"] class paitest: def __init__(self, - direction: Literal["EAST", "SOUTH", "WEST", "NORTH"], - core_coord: Tuple[int, int] = (0, 0) + direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] = "EAST", + fixed_chip_coord: Tuple[int, int] = (0, 0) ) -> None: + ''' + :param direction: The direction relative to the PAICORE. Default is 'EAST'. + :param fixed_chip_coord: The chip address of the PAICORE under test. Default is (0, 0). + ''' self._work_dir: Union[Path, None] = None self._fc: io.BufferedWriter self._fi: io.BufferedWriter self._fo: io.BufferedWriter - self._groups: int = 1 self._verbose: bool = True - self._fixed_chip_coord: Coord = Coord(0, 0) - self._fixed_core_coord: Coord = Coord(core_coord) + self._fixed_chip_coord: Coord = Coord(fixed_chip_coord) self._masked_core_coord: Coord self._fixed_core_star_coord: Coord = Coord(0, 0) self._test_chip_coord: Coord self._ensure_direction(direction) - def GetRandomCasesForNCores(self, - N: int, - *, - save_dir: Optional[Union[str, Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: + def Get1GroupForNCoresWithNParams(self, + N: int, + *, + save_dir: Optional[Union[str, + Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None + ) -> Tuple[Tuple[int, ...], ...]: ''' - Generate 1 group case for 'N' cores coordinates with 'N' different parameters. + Generate 1 group(case) for 'N' cores coordinates with 'N' different parameters. - 1. save_dir: Where to save the frames file - 2. direction: Test chip direction relative to the location of the core - 3. N: How many groups of configuration-test frames to be generated - 4. masked_core_coord: to avoid genif save_dir: - 5. verbose: Display the logs + - `N`: How many cores coordinates under test. + - `save_dir`: Where to save the frames files. + - `masked_core_coord`: to avoid generating the specific core coordinate. + + :return: Three tuples including config, testin & testout tuples. 3*N frames in config & testout tuple and N frames in testin tuple. ''' - self._ensure_groups(N) + self._ensure_cores(N) if save_dir: self._ensure_dir(save_dir) else: self._work_dir = None - test_chip_coord: Coord = self._direction.value + self._fixed_core_coord - params = self._GetNParameters(N, False) + # 1. Get the test chip coordinate. + test_chip_coord: Coord = self._direction.value + self._fixed_chip_coord - _masked_core_coord = Coord(masked_core_coord) if isinstance( - masked_core_coord, Tuple) else None + # 2. Get N core coordinates list. + if isinstance(masked_core_coord, Tuple): + _masked_core_coord = Coord(masked_core_coord) + else: + _masked_core_coord = None - core_coord_list = self._GetNCoresCoord(N, _masked_core_coord) + core_coords = self._GetNCoresCoord(N, _masked_core_coord) + + # 3. Get N parameters reg. + params = self._GetNParams(N, core_coords, False) cf_list: List[int] = [] ti_list: List[int] = [] @@ -74,8 +81,8 @@ def GetRandomCasesForNCores(self, self._fo = open(self._work_dir / "testout.bin", "wb") for i in range(N): - logger.info(f"Generating group #{i+1}/{N}...") - core_coord = core_coord_list[i] + logger.info(f"Generating test group #{i+1}/{N}...") + core_coord = core_coords[i] param = params[i] for j in range(3): @@ -114,32 +121,42 @@ def GetRandomCasesForNCores(self, return tuple(cf_list), tuple(ti_list), tuple(to_list) - def Get1CaseForNCores(self, - N: int, - *, - save_dir: Optional[Union[str, Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: + def Get1GroupForNCoresWith1Param(self, + N: int, + *, + save_dir: Optional[Union[str, + Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None + ) -> Tuple[Tuple[int, ...], ...]: ''' - Generate 1 group case for 'N' random cores coordinates with the same parameters. - - Always return 3 tuples including 'N' tuples. + Generate 1 group(case) for 'N' random cores coordinates with the same parameters. + + - `N`: How many cores coordinates under test. + - `save_dir`: Where to save the frames files. + - `masked_core_coord`: to avoid generating the specific core coordinate. + + :return: Three tuples including config, testin & testout tuples. 3*N frames in config & testout tuple and N frames in testin tuple. ''' - self._ensure_groups(N) + self._ensure_cores(N) if save_dir: self._ensure_dir(save_dir) else: self._work_dir = None - test_chip_coord = self._direction.value + self._fixed_core_coord - param = self._Get1Parameter(False) + # 1. Get the test chip coordinate. + test_chip_coord = self._direction.value + self._fixed_chip_coord - _masked_core_coord = Coord(masked_core_coord) if isinstance( - masked_core_coord, Tuple) else None + # 2. Get the core coordinates list. + if isinstance(masked_core_coord, Tuple): + _masked_core_coord = Coord(masked_core_coord) + else: + _masked_core_coord = None + + core_coords = self._GetNCoresCoord(N, _masked_core_coord) - core_coord_list = self._GetNCoresCoord( - N, masked_coord=_masked_core_coord) + # 3. Get the parameters reg. + param: List[int] = self._Get1Param(core_coords, False) cf_list: List[int] = [] ti_list: List[int] = [] @@ -151,8 +168,89 @@ def Get1CaseForNCores(self, self._fo = open(self._work_dir / "testout.bin", "wb") for i in range(N): - logger.info(f"Generating group #{i+1}/{N}...") - core_coord = core_coord_list[i] + logger.info(f"Generating test group #{i+1}/{N}...") + core_coord = core_coords[i] + + for j in range(3): + config_frame = FrameGen.GenConfigFrame( + FST.CONFIG_TYPE2, self._fixed_chip_coord, core_coord, self._fixed_core_star_coord, param[j]) + cf_list.append(config_frame) + logger.info("Config frame #%d/3: 0x%x in group #%d/%d" % + (j+1, config_frame, i+1, N)) + + testout_frame = FrameGen.GenTest2OutFrame( + test_chip_coord, core_coord, self._fixed_core_star_coord, param[j]) + to_list.append(testout_frame) + logger.info("Test out frame #%d/3: 0x%x in group #%d/%d" % + (j+1, testout_frame, i+1, N)) + + if self._work_dir: + self._fc.write(config_frame.to_bytes( + length=8, byteorder="big")) + self._fo.write(testout_frame.to_bytes( + length=8, byteorder="big")) + + testin_frame = FrameGen.GenTest2InFrame( + test_chip_coord, core_coord, self._fixed_core_star_coord) + ti_list.append(testin_frame) + logger.info("Test in frame #1/1: 0x%x in group #%d/%d" % + (testin_frame, i+1, N)) + + if self._work_dir: + self._fi.write(testin_frame.to_bytes( + length=8, byteorder="big")) + + return tuple(cf_list), tuple(ti_list), tuple(to_list) + + def GetNGroupsFor1CoreWithNParams(self, + N: int, + *, + save_dir: Optional[Union[str, + Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None + ) -> Tuple[Tuple[int, ...], ...]: + ''' + Generate 'N' groups(cases) for 1 random core coordinate with 'N' different parameters. + + - `N`: How many test groups(cases) of 1 core will be generated. + - `save_dir`: Where to save the frames files. + - `masked_core_coord`: to avoid generating the specific core coordinate. + + :return: Three tuples including config, testin & testout tuples. 3*N frames in config & testout tuple and N frames in testin tuple. + ''' + self._ensure_cores(N) + + if save_dir: + self._ensure_dir(save_dir) + else: + self._work_dir = None + + # 1. Get the test chip coordinate. + test_chip_coord = self._direction.value + self._fixed_chip_coord + + # 2. Get the core coordinates list. + if isinstance(masked_core_coord, Tuple): + _masked_core_coord = Coord(masked_core_coord) + else: + _masked_core_coord = None + + core_coord = self._Get1CoreCoord(_masked_core_coord) + + # 3. Get the parameters reg. + params = self._GetNParams(N, core_coord, False) + + cf_list: List[int] = [] + ti_list: List[int] = [] + to_list: List[int] = [] + + if self._work_dir: + self._fc = open(self._work_dir / "config.bin", "wb") + self._fi = open(self._work_dir / "testin.bin", "wb") + self._fo = open(self._work_dir / "testout.bin", "wb") + + for i in range(N): + logger.info(f"Generating test group #{i+1}/{N}...") + param = params[i] for j in range(3): config_frame = FrameGen.GenConfigFrame( @@ -235,7 +333,7 @@ def _Get1CoreCoord(self, masked_coord: Optional[Coord] = None) -> Coord: return self._GetNCoresCoord(N=1, masked_coord=masked_coord)[0] def _GetNCoresCoord(self, - N: Optional[int] = None, + N: int, masked_coord: Optional[Coord] = None ) -> List[Coord]: ''' @@ -255,51 +353,54 @@ def _CoordGenerator(): coordinates.add((x, y)) yield Coord(x, y) - if not isinstance(N, int): - N = self._groups - - if isinstance(masked_coord, Tuple): + if isinstance(masked_coord, Coord): self._ensure_coord(masked_coord) - - if N == 1008 and isinstance(masked_coord, Tuple): - N = 1007 + if N > 1007: + raise ValueError("When choose to mask a core, \ + the max value of cores to be generated is 1007") generator = _CoordGenerator() core_addr_list = [next(generator) for _ in range(N)] return core_addr_list - def _Get1Parameter(self, is_legal: bool = False) -> List[int]: + def _Get1Param(self, + core_coords: Union[List[Coord], Coord], + is_legal: bool = False + ) -> List[int]: '''Generate one group parameter for parameter register''' - return self._GetNParameters(1, is_legal)[0] + return self._GetNParams(1, core_coords, is_legal)[0] - def _GetNParameters(self, - N: Optional[int] = None, - is_legal: bool = False, - ) -> List[List[int]]: + def _GetNParams(self, + N: int, + core_coords: Union[List[Coord], Coord], + is_legal: bool = False, + ) -> List[List[int]]: ''' - Generate 'N' groups parameter for parameter register. + Generate 'N' parameters reg for parameter register. is_legal: whether to generate legal parameters for every core ''' def _ParamGenerator(): - test_chip_coord: Coord = self._direction.value + self._fixed_core_coord + test_chip_coord: Coord = self._direction.value + self._fixed_chip_coord while True: - - if is_legal: - # TODO: Do legal generation here, including direction config - param = [0, 0, 0] - pass - else: - param = FrameGen.GenConfigGroup( - FST.CONFIG_TYPE2, self._fixed_chip_coord, self._fixed_core_coord, - self._fixed_core_star_coord, test_chip_coord) - - yield param - - if not isinstance(N, int): - N = self._groups + for core_coord in _core_coords: + if is_legal: + # TODO: Do legal generation here, including direction config + param = [0, 0, 0] + pass + else: + param = FrameGen.GenConfigGroup( + FST.CONFIG_TYPE2, self._fixed_chip_coord, core_coord, + self._fixed_core_star_coord, test_chip_coord) + + yield param + + if isinstance(core_coords, Coord): + _core_coords = [core_coords] + else: + _core_coords = core_coords generator = _ParamGenerator() parameters = [next(generator) for _ in range(N)] @@ -355,10 +456,12 @@ def _ensure_groups(self, groups: int) -> None: if groups > 1024 - 16: raise ValueError("Value of groups is no more than 1008") - self._groups = groups - logger.info(f"{groups} groups cases will be generated...") + def _ensure_cores(self, Ncores: int) -> None: + if Ncores > 1024 - 16: + raise ValueError("Value of cores is no more than 1008") + def _ensure_direction(self, direction: Literal["EAST", "SOUTH", "WEST", "NORTH"]) -> None: self._direction = Direction[direction.upper()] diff --git a/paitest/paitest.pyi b/paitest/paitest.pyi index 5dd3cf0..8f1dcaf 100644 --- a/paitest/paitest.pyi +++ b/paitest/paitest.pyi @@ -1,27 +1,36 @@ from typing import Literal, Tuple, List, Optional, Union, overload from pathlib import Path -from .frames.frame import Coord class paitest: def __init__(self, - direction: Literal["EAST", "SOUTH", "WEST", "NORTH"], - core_coord: Tuple[int, int] = (0, 0) + direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] = "EAST", + fixed_chip_coord: Tuple[int, int] = (0, 0) ) -> None: ... - def GetRandomCasesForNCores(self, - N: int, - *, - save_dir: Optional[Union[str, Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: ... - - def Get1CaseForNCores(self, - N: int, - *, - save_dir: Optional[Union[str, Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: ... + def Get1GroupForNCoresWithNParams(self, + N: int, + *, + save_dir: Optional[Union[str, + Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None + ) -> Tuple[Tuple[int, ...], ...]: ... + + def Get1GroupForNCoresWith1Param(self, + N: int, + *, + save_dir: Optional[Union[str, + Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None + ) -> Tuple[Tuple[int, ...], ...]: ... + + def GetNGroupsFor1CoreWithNParams(self, + N: int, + *, + save_dir: Optional[Union[str, + Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None + ) -> Tuple[Tuple[int, ...], ...]: ... @overload def ReplaceCoreCoord(self, frames: int) -> int: ... From acf7b1986f473e873ef03b896b28957f80de0725 Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Sat, 15 Apr 2023 15:00:45 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=F0=9F=8E=A8=20chore:=20using=20Black=20f?= =?UTF-8?q?ormatter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paitest/frames/__init__.py | 17 +- paitest/frames/frame.py | 326 ++++++++++++++++--------------- paitest/frames/frame_params.py | 121 ++++++------ paitest/log.py | 12 +- paitest/paitest.py | 344 +++++++++++++++++++-------------- paitest/paitest.pyi | 75 ++++--- 6 files changed, 481 insertions(+), 414 deletions(-) diff --git a/paitest/frames/__init__.py b/paitest/frames/__init__.py index aae05ed..8a6421f 100644 --- a/paitest/frames/__init__.py +++ b/paitest/frames/__init__.py @@ -1,8 +1,9 @@ -from .frame import \ - Addr2Coord as Addr2Coord, \ - Coord2Addr as Coord2Addr, \ - FrameGen as FrameGen, \ - Coord as Coord, \ - Direction as Direction, \ - FrameMask as FrameMask, \ - FrameSubType as FrameSubType +from .frame import ( + Addr2Coord as Addr2Coord, + Coord2Addr as Coord2Addr, + FrameGen as FrameGen, + Coord as Coord, + Direction as Direction, + FrameMask as FrameMask, + FrameSubType as FrameSubType, +) diff --git a/paitest/frames/frame.py b/paitest/frames/frame.py index af8cd80..1d44751 100644 --- a/paitest/frames/frame.py +++ b/paitest/frames/frame.py @@ -1,19 +1,15 @@ -from .frame_params import \ - FrameType as FT, \ - FrameSubType as FST, \ - FrameMask as FM, \ - ConfigFrameMask as CFM +from .frame_params import ( + FrameType as FT, + FrameSubType as FST, + FrameMask as FM, + ConfigFrameMask as CFM, +) from .frame_params import * from typing import List, Tuple, Union, Dict, Optional import random -__all__ = [ - "Addr2Coord", - "Coord2Addr", - "FrameGen", - "Coord" -] +__all__ = ["Addr2Coord", "Coord2Addr", "FrameGen", "Coord"] def Addr2Coord(addr: int) -> Coord: @@ -27,7 +23,8 @@ def Coord2Addr(coord: Coord) -> int: def test_chip_coord_split(coord: Coord) -> Tuple[int, int]: addr = Coord2Addr(coord) high3 = ( - addr >> CFM.TEST_CHIP_ADDR_COMBINATION_OFFSET) & CFM.TEST_CHIP_ADDR_HIGH3_MASK + addr >> CFM.TEST_CHIP_ADDR_COMBINATION_OFFSET + ) & CFM.TEST_CHIP_ADDR_HIGH3_MASK low7 = addr & CFM.TEST_CHIP_ADDR_LOW7_MASK return high3, low7 @@ -43,77 +40,79 @@ def test_chip_addr_combine(high3: int, low7: int) -> Coord: class FrameGen: - @staticmethod - def _GenFrame(header: int, - chip_addr: int, - core_addr: int, - core_star_addr: int, - payload: int - ) -> int: + def _GenFrame( + header: int, chip_addr: int, core_addr: int, core_star_addr: int, payload: int + ) -> int: header = header & FM.GENERAL_HEADER_MASK chip_addr = chip_addr & FM.GENERAL_CHIP_ADDR_MASK core_addr = core_addr & FM.GENERAL_CORE_ADDR_MASK core_star_addr = core_star_addr & FM.GENERAL_CORE_STAR_ADDR_MASK payload = payload & FM.GENERAL_PAYLOAD_MASK - return (header << FM.GENERAL_HEADER_OFFSET) | \ - (chip_addr << FM.GENERAL_CHIP_ADDR_OFFSET) | \ - (core_addr << FM.GENERAL_CORE_ADDR_OFFSET) | \ - (core_star_addr << FM.GENERAL_CORE_STAR_ADDR_OFFSET) | \ - (payload << FM.GENERAL_PAYLOAD_OFFSET) + return ( + (header << FM.GENERAL_HEADER_OFFSET) + | (chip_addr << FM.GENERAL_CHIP_ADDR_OFFSET) + | (core_addr << FM.GENERAL_CORE_ADDR_OFFSET) + | (core_star_addr << FM.GENERAL_CORE_STAR_ADDR_OFFSET) + | (payload << FM.GENERAL_PAYLOAD_OFFSET) + ) @staticmethod - def GenConfigFrame(header: FST, - chip_coord: Coord, - core_coord: Coord, - core_star_coord: Coord, - payload: int - ) -> int: - + def GenConfigFrame( + header: FST, + chip_coord: Coord, + core_coord: Coord, + core_star_coord: Coord, + payload: int, + ) -> int: chip_addr = Coord2Addr(chip_coord) core_addr = Coord2Addr(core_coord) core_star_addr = Coord2Addr(core_star_coord) - return FrameGen._GenFrame(header.value, chip_addr, core_addr, core_star_addr, payload) + return FrameGen._GenFrame( + header.value, chip_addr, core_addr, core_star_addr, payload + ) @staticmethod - def GenConfigGroup(header: FST, - chip_coord: Coord, - core_coord: Coord, - core_star_coord: Coord, - test_chip_coord: Coord - ) -> List[int]: - + def GenConfigGroup( + header: FST, + chip_coord: Coord, + core_coord: Coord, + core_star_coord: Coord, + test_chip_coord: Coord, + ) -> List[int]: ConfigFrameGroup: List[int] = [] param_reg = FrameGen._GenParamReg(test_chip_coord) for i in range(3): ConfigFrameGroup.append( - FrameGen.GenConfigFrame(header, chip_coord, core_coord, core_star_coord, param_reg[i])) + FrameGen.GenConfigFrame( + header, chip_coord, core_coord, core_star_coord, param_reg[i] + ) + ) return ConfigFrameGroup @staticmethod - def _GenParamReg(test_chip_coord: Coord, - *, - is_random: bool = True, - is_legal: bool = False, - weight_width_type: Optional[WeightPrecisionType] = None, - lcn_type: Optional[LCNTypes] = None, - input_width_type: Optional[InputWidthType] = None, - spike_width_type: Optional[SpikeWidthType] = None, - neuron_num: Optional[int] = None, - pool_max_en: Optional[bool] = None, - tick_wait_start: Optional[int] = None, - tick_wait_end: Optional[int] = None, - snn_en: Optional[bool] = None, - target_lcn: Optional[int] = None, - ) -> List[int]: - - high3, low7 = test_chip_coord_split( - test_chip_coord) + def _GenParamReg( + test_chip_coord: Coord, + *, + is_random: bool = True, + is_legal: bool = False, + weight_width_type: Optional[WeightPrecisionType] = None, + lcn_type: Optional[LCNTypes] = None, + input_width_type: Optional[InputWidthType] = None, + spike_width_type: Optional[SpikeWidthType] = None, + neuron_num: Optional[int] = None, + pool_max_en: Optional[bool] = None, + tick_wait_start: Optional[int] = None, + tick_wait_end: Optional[int] = None, + snn_en: Optional[bool] = None, + target_lcn: Optional[int] = None, + ) -> List[int]: + high3, low7 = test_chip_coord_split(test_chip_coord) param_reg: List[int] = [] @@ -121,11 +120,9 @@ def _GenParamReg(test_chip_coord: Coord, if not is_legal: # Don't care 'tick_wait_start' split in #1 and #2 for _ in range(2): - param_reg.append(random.randint( - 0, FM.GENERAL_PAYLOAD_MASK)) + param_reg.append(random.randint(0, FM.GENERAL_PAYLOAD_MASK)) - param_reg[1] = (param_reg[1] & ( - ~CFM.TEST_CHIP_ADDR_HIGH3_MASK)) | high3 + param_reg[1] = (param_reg[1] & (~CFM.TEST_CHIP_ADDR_HIGH3_MASK)) | high3 param_reg.append(low7 << CFM.TEST_CHIP_ADDR_LOW7_OFFSET) else: # Do legal geenration @@ -135,56 +132,66 @@ def _GenParamReg(test_chip_coord: Coord, return param_reg - '''Functions of Test Frames Generation''' - @staticmethod - def _GenTestFrame(header: FST, - chip_coord: Coord, - core_coord: Coord, - core_star_coord: Coord, - payload: int = 0 - ) -> int: + """Functions of Test Frames Generation""" + @staticmethod + def _GenTestFrame( + header: FST, + chip_coord: Coord, + core_coord: Coord, + core_star_coord: Coord, + payload: int = 0, + ) -> int: chip_addr = Coord2Addr(chip_coord) core_addr = Coord2Addr(core_coord) core_star_addr = Coord2Addr(core_star_coord) - return FrameGen._GenFrame(header.value, chip_addr, core_addr, core_star_addr, payload) + return FrameGen._GenFrame( + header.value, chip_addr, core_addr, core_star_addr, payload + ) @staticmethod - def GenTest1InFrame(chip_coord: Coord, - core_coord: Coord, - core_star_coord: Coord - ) -> int: - return FrameGen._GenTestFrame(FST.TEST_TYPE1, chip_coord, core_coord, core_star_coord) + def GenTest1InFrame( + chip_coord: Coord, core_coord: Coord, core_star_coord: Coord + ) -> int: + return FrameGen._GenTestFrame( + FST.TEST_TYPE1, chip_coord, core_coord, core_star_coord + ) @staticmethod - def GenTest1OutFrame(test_chip_coord: Coord, - core_coord: Coord, - core_star_coord: Coord, - random_seed: int - ) -> int: - return FrameGen._GenTestFrame(FST.TEST_TYPE1, test_chip_coord, core_coord, core_star_coord, random_seed) + def GenTest1OutFrame( + test_chip_coord: Coord, + core_coord: Coord, + core_star_coord: Coord, + random_seed: int, + ) -> int: + return FrameGen._GenTestFrame( + FST.TEST_TYPE1, test_chip_coord, core_coord, core_star_coord, random_seed + ) @staticmethod - def GenTest2InFrame(chip_coord: Coord, - core_coord: Coord, - core_star_coord: Coord - ) -> int: - return FrameGen._GenTestFrame(FST.TEST_TYPE2, chip_coord, core_coord, core_star_coord) + def GenTest2InFrame( + chip_coord: Coord, core_coord: Coord, core_star_coord: Coord + ) -> int: + return FrameGen._GenTestFrame( + FST.TEST_TYPE2, chip_coord, core_coord, core_star_coord + ) @staticmethod - def GenTest2OutFrame(test_chip_coord: Coord, - core_coord: Coord, - core_star_coord: Coord, - param_reg: int - ) -> int: - return FrameGen._GenTestFrame(FST.TEST_TYPE2, test_chip_coord, core_coord, core_star_coord, param_reg) + def GenTest2OutFrame( + test_chip_coord: Coord, + core_coord: Coord, + core_star_coord: Coord, + param_reg: int, + ) -> int: + return FrameGen._GenTestFrame( + FST.TEST_TYPE2, test_chip_coord, core_coord, core_star_coord, param_reg + ) class FrameDecoder: - def __init__(self): - self._len: int + self.groups_len: int self._frame: int self._frames_group: Tuple[int, ...] @@ -200,21 +207,21 @@ def __init__(self): "tick_wait_end": 0, "SNN_EN": 0, "target_LCN": 0, - "test_chip_coord": Coord(0, 0) + "test_chip_coord": Coord(0, 0), } def decode(self, frames: Union[int, List[int], Tuple[int, ...]]) -> None: - ''' - Call for decoding a frame or a valid group of frames. + """ + Call for decoding a frame or a valid group of frames. - Support single frame decoding & a group of 3 frames only. - ''' + Support single frame decoding & a group of 3 frames only. + """ if isinstance(frames, int): - self._len = 1 + self.groups_len = 1 self._frame = frames else: assert len(frames) == 3 - self._len = len(frames) + self.groups_len = len(frames) self._frame = frames[0] self._frames_group = tuple(frames) @@ -222,7 +229,8 @@ def decode(self, frames: Union[int, List[int], Tuple[int, ...]]) -> None: def _get_subtype(self) -> FST: _header: int = ( - self._frame >> FM.GENERAL_HEADER_OFFSET) & FM.GENERAL_HEADER_MASK + self._frame >> FM.GENERAL_HEADER_OFFSET + ) & FM.GENERAL_HEADER_MASK try: _subtype = FrameSubType(_header) return _subtype @@ -245,31 +253,36 @@ def _get_type(self) -> FT: def _get_chip_coord(self) -> Coord: _chip_addr: int = ( - self._frame >> FM.GENERAL_CHIP_ADDR_OFFSET) & FM.GENERAL_CHIP_ADDR_MASK + self._frame >> FM.GENERAL_CHIP_ADDR_OFFSET + ) & FM.GENERAL_CHIP_ADDR_MASK return Addr2Coord(_chip_addr) def _get_core_coord(self) -> Coord: _core_addr: int = ( - self._frame >> FM.GENERAL_CORE_ADDR_OFFSET) & FM.GENERAL_CORE_ADDR_MASK + self._frame >> FM.GENERAL_CORE_ADDR_OFFSET + ) & FM.GENERAL_CORE_ADDR_MASK return Addr2Coord(_core_addr) def _get_core_star_coord(self) -> Coord: _core_star_addr: int = ( - self._frame >> FM.GENERAL_CORE_STAR_ADDR_OFFSET) & FM.GENERAL_CORE_STAR_ADDR_MASK + self._frame >> FM.GENERAL_CORE_STAR_ADDR_OFFSET + ) & FM.GENERAL_CORE_STAR_ADDR_MASK return Addr2Coord(_core_star_addr) def _get_payload(self) -> Union[List[int], int]: - if self._len == 1: - _payload = (self._frame >> - FM.GENERAL_PAYLOAD_OFFSET) & FM.GENERAL_PAYLOAD_MASK + if self.groups_len == 1: + _payload = ( + self._frame >> FM.GENERAL_PAYLOAD_OFFSET + ) & FM.GENERAL_PAYLOAD_MASK else: _payload = [] for frame in self._frames_group: - _payload.append((frame >> FM.GENERAL_PAYLOAD_OFFSET) - & FM.GENERAL_PAYLOAD_MASK) + _payload.append( + (frame >> FM.GENERAL_PAYLOAD_OFFSET) & FM.GENERAL_PAYLOAD_MASK + ) self._payload = _payload @@ -316,80 +329,91 @@ def _general_info(self) -> None: print("#1 Frame type: %s" % self._get_subtype()) chip_coord = self._get_chip_coord() - print("#2 Chip address: [0x%02x | 0x%02x]" % ( - chip_coord.x, chip_coord.y)) + print( + "#2 Chip address: [0x%02x | 0x%02x]" % (chip_coord.x, chip_coord.y) + ) core_coord = self._get_core_coord() - print("#3 Core address: [0x%02x | 0x%02x]" % ( - core_coord.x, core_coord.y)) + print( + "#3 Core address: [0x%02x | 0x%02x]" % (core_coord.x, core_coord.y) + ) core_star_coord = self._get_core_star_coord() - print("#4 Core* address: [0x%02x | 0x%02x]" % - (core_star_coord.x, core_star_coord.y)) + print( + "#4 Core* address: [0x%02x | 0x%02x]" + % (core_star_coord.x, core_star_coord.y) + ) def _config2_info(self) -> None: print("Info of parameter registers") - print("#1 Weight width: 0x%x" % - self._param_reg_dict["weight_width"]) + print("#1 Weight width: 0x%x" % self._param_reg_dict["weight_width"]) print("#2 LCN: 0x%x" % self._param_reg_dict["LCN"]) - print("#3 Input width: 0x%x" % - self._param_reg_dict["input_width"]) - print("#4 Spike width: 0x%x" % - self._param_reg_dict["spike_width"]) - print("#5 Neuron num: %d" % - self._param_reg_dict["neuron_num"]) + print("#3 Input width: 0x%x" % self._param_reg_dict["input_width"]) + print("#4 Spike width: 0x%x" % self._param_reg_dict["spike_width"]) + print("#5 Neuron num: %d" % self._param_reg_dict["neuron_num"]) print("#6 Pool max enable: %d" % self._param_reg_dict["pool_max"]) - print("#7 Tick wait start: 0x%x" % - self._param_reg_dict["tick_wait_start"]) - print("#8 Tick wait end: 0x%x" % - self._param_reg_dict["tick_wait_end"]) + print("#7 Tick wait start: 0x%x" % self._param_reg_dict["tick_wait_start"]) + print("#8 Tick wait end: 0x%x" % self._param_reg_dict["tick_wait_end"]) print("#9 SNN enable: %d" % self._param_reg_dict["SNN_EN"]) - print("#10 Target LCN: 0x%x" % - self._param_reg_dict["target_LCN"]) + print("#10 Target LCN: 0x%x" % self._param_reg_dict["target_LCN"]) - test_chip_coord: Coord = self._param_reg_dict["test_chip_coord"] # type: ignore - print("#11 Test chip coord: [0x%02x | 0x%02x]" % ( - test_chip_coord.x, test_chip_coord.y)) + test_chip_coord: Coord = self._param_reg_dict["test_chip_coord"] # type: ignore + print( + "#11 Test chip coord: [0x%02x | 0x%02x]" + % (test_chip_coord.x, test_chip_coord.y) + ) def _test2_info(self) -> None: pass def _param_reg_parse(self) -> None: self._param_reg_dict["weight_width"] = ( - self._frames_group[0] >> CFM.WEIGHT_WIDTH_OFFSET) & CFM.WEIGHT_WIDTH_MASK + self._frames_group[0] >> CFM.WEIGHT_WIDTH_OFFSET + ) & CFM.WEIGHT_WIDTH_MASK self._param_reg_dict["LCN"] = ( - self._frames_group[0] >> CFM.LCN_OFFSET) & CFM.LCN_MASK + self._frames_group[0] >> CFM.LCN_OFFSET + ) & CFM.LCN_MASK self._param_reg_dict["input_width"] = ( - self._frames_group[0] >> CFM.INPUT_WIDTH_OFFSET) & CFM.INPUT_WIDTH_MASK + self._frames_group[0] >> CFM.INPUT_WIDTH_OFFSET + ) & CFM.INPUT_WIDTH_MASK self._param_reg_dict["spike_width"] = ( - self._frames_group[0] >> CFM.SPIKE_WIDTH_OFFSET) & CFM.SPIKE_WIDTH_MASK + self._frames_group[0] >> CFM.SPIKE_WIDTH_OFFSET + ) & CFM.SPIKE_WIDTH_MASK self._param_reg_dict["neuron_num"] = ( - self._frames_group[0] >> CFM.NEURON_NUM_OFFSET) & CFM.NEURON_NUM_MASK + self._frames_group[0] >> CFM.NEURON_NUM_OFFSET + ) & CFM.NEURON_NUM_MASK self._param_reg_dict["pool_max"] = ( - self._frames_group[0] >> CFM.POOL_MAX_OFFSET) & CFM.POOL_MAX_MASK + self._frames_group[0] >> CFM.POOL_MAX_OFFSET + ) & CFM.POOL_MAX_MASK tick_wait_high8 = ( - self._frames_group[0] >> CFM.TICK_WAIT_START_HIGH8_OFFSET) & CFM.TICK_WAIT_START_HIGH8_MASK + self._frames_group[0] >> CFM.TICK_WAIT_START_HIGH8_OFFSET + ) & CFM.TICK_WAIT_START_HIGH8_MASK tick_wait_low7 = ( - self._frames_group[1] >> CFM.TICK_WAIT_START_LOW7_OFFSET) & CFM.TICK_WAIT_START_LOW7_MASK - self._param_reg_dict["tick_wait_start"] = \ - (tick_wait_high8 << CFM.TICK_WAIT_START_COMBINATION_OFFSET) | tick_wait_low7 + self._frames_group[1] >> CFM.TICK_WAIT_START_LOW7_OFFSET + ) & CFM.TICK_WAIT_START_LOW7_MASK + self._param_reg_dict["tick_wait_start"] = ( + tick_wait_high8 << CFM.TICK_WAIT_START_COMBINATION_OFFSET + ) | tick_wait_low7 self._param_reg_dict["tick_wait_end"] = ( - self._frames_group[1] >> CFM.TICK_WAIT_END_OFFSET) & CFM.TICK_WAIT_END_MASK + self._frames_group[1] >> CFM.TICK_WAIT_END_OFFSET + ) & CFM.TICK_WAIT_END_MASK self._param_reg_dict["SNN_EN"] = ( - self._frames_group[1] >> CFM.SNN_EN_OFFSET) & CFM.SNN_EN_MASK + self._frames_group[1] >> CFM.SNN_EN_OFFSET + ) & CFM.SNN_EN_MASK self._param_reg_dict["target_LCN"] = ( - self._frames_group[1] >> CFM.TARGET_LCN_OFFSET) & CFM.TARGET_LCN_MASK + self._frames_group[1] >> CFM.TARGET_LCN_OFFSET + ) & CFM.TARGET_LCN_MASK high3 = self._frames_group[1] >> CFM.TEST_CHIP_ADDR_HIGH3_OFFSET low7 = self._frames_group[2] >> CFM.TEST_CHIP_ADDR_LOW7_OFFSET - self._param_reg_dict["test_chip_coord"] = test_chip_addr_combine( - high3, low7) + self._param_reg_dict["test_chip_coord"] = test_chip_addr_combine(high3, low7) def _decode_direction(self) -> Direction: - offset: CoordOffset = self._param_reg_dict["test_chip_coord"] - \ - self.chip_coord # type: ignore + offset: CoordOffset = ( + self._param_reg_dict["test_chip_coord"] - self.chip_coord + ) # type: ignore try: direction = Direction(offset) diff --git a/paitest/frames/frame_params.py b/paitest/frames/frame_params.py index 2327399..2b80d62 100644 --- a/paitest/frames/frame_params.py +++ b/paitest/frames/frame_params.py @@ -11,7 +11,8 @@ class CoreType(Enum): @unique class FrameType(Enum): - '''Types of Frames''' + """Types of Frames""" + FRAME_CONFIG = 0 FRAME_TEST = 0x1 FRAME_WORK = 0x2 @@ -20,19 +21,20 @@ class FrameType(Enum): @unique class FrameSubType(Flag): - '''Sub-types of Configuration Frames''' + """Sub-types of Configuration Frames""" + CONFIG_TYPE1 = 0b0000 CONFIG_TYPE2 = 0b0001 CONFIG_TYPE3 = 0b0010 CONFIG_TYPE4 = 0b0011 - '''Sub-types of Test Frames''' + """Sub-types of Test Frames""" TEST_TYPE1 = 0b0100 TEST_TYPE2 = 0b0101 TEST_TYPE3 = 0b0110 TEST_TYPE4 = 0b0111 - '''Sub-types of Work Frames''' + """Sub-types of Work Frames""" WORK_TYPE1 = 0b1000 WORK_TYPE2 = 0b1001 WORK_TYPE3 = 0b1010 @@ -41,83 +43,84 @@ class FrameSubType(Flag): @dataclass class FrameMask: - ''' - Format of data package or single frame for general usages: - ''' - '''Format of single frame''' + """ + Format of data package or single frame for general usages: + """ + + """Format of single frame""" # General mask - GENERAL_MASK = ((1 << 64) - 1) + GENERAL_MASK = (1 << 64) - 1 # Header GENERAL_HEADER_OFFSET = 60 - GENERAL_HEADER_MASK = ((1 << 4) - 1) + GENERAL_HEADER_MASK = (1 << 4) - 1 GENERAL_FRAME_TYPE_OFFSET = GENERAL_HEADER_OFFSET GENERAL_FRAME_TYPE_MASK = GENERAL_HEADER_MASK # Chip address GENERAL_CHIP_ADDR_OFFSET = 50 - GENERAL_CHIP_ADDR_MASK = ((1 << 10) - 1) + GENERAL_CHIP_ADDR_MASK = (1 << 10) - 1 # Chip X/Y address GENERAL_CHIP_ADDR_X_OFFSET = 55 - GENERAL_CHIP_ADDR_X_MASK = ((1 << 5) - 1) + GENERAL_CHIP_ADDR_X_MASK = (1 << 5) - 1 GENERAL_CHIP_ADDR_Y_OFFSET = GENERAL_CHIP_ADDR_OFFSET - GENERAL_CHIP_ADDR_Y_MASK = ((1 << 5) - 1) + GENERAL_CHIP_ADDR_Y_MASK = (1 << 5) - 1 # Core address GENERAL_CORE_ADDR_OFFSET = 40 - GENERAL_CORE_ADDR_MASK = ((1 << 10) - 1) + GENERAL_CORE_ADDR_MASK = (1 << 10) - 1 # Core X/Y address GENERAL_CORE_ADDR_X_OFFSET = 45 - GENERAL_CORE_ADDR_X_MASK = ((1 << 5) - 1) + GENERAL_CORE_ADDR_X_MASK = (1 << 5) - 1 GENERAL_CORE_ADDR_Y_OFFSET = GENERAL_CORE_ADDR_OFFSET - GENERAL_CORE_ADDR_Y_MASK = ((1 << 5) - 1) + GENERAL_CORE_ADDR_Y_MASK = (1 << 5) - 1 # Core* address GENERAL_CORE_STAR_ADDR_OFFSET = 30 - GENERAL_CORE_STAR_ADDR_MASK = ((1 << 10) - 1) + GENERAL_CORE_STAR_ADDR_MASK = (1 << 10) - 1 # Core* X/Y address GENERAL_CORE_STAR_ADDR_X_OFFSET = 35 - GENERAL_CORE_STAR_ADDR_X_MASK = ((1 << 5) - 1) + GENERAL_CORE_STAR_ADDR_X_MASK = (1 << 5) - 1 GENERAL_CORE_STAR_ADDR_Y_OFFSET = GENERAL_CORE_STAR_ADDR_OFFSET - GENERAL_CORE_STAR_ADDR_Y_MASK = ((1 << 5) - 1) + GENERAL_CORE_STAR_ADDR_Y_MASK = (1 << 5) - 1 # Global core = Chip address + core address GENERAL_CORE_GLOBAL_ADDR_OFFSET = GENERAL_CORE_ADDR_OFFSET - GENERAL_CORE_GLOBAL_ADDR_MASK = ((1 << 20) - 1) + GENERAL_CORE_GLOBAL_ADDR_MASK = (1 << 20) - 1 # Payload GENERAL_PAYLOAD_OFFSET = 0 - GENERAL_PAYLOAD_MASK = ((1 << 30) - 1) - GENERAL_PAYLOAD_FILLED_MASK = ((1 << 4) - 1) + GENERAL_PAYLOAD_MASK = (1 << 30) - 1 + GENERAL_PAYLOAD_FILLED_MASK = (1 << 4) - 1 - '''Format of startup frame of data package''' + """Format of startup frame of data package""" GENERAL_PACKAGE_OFFSET = 0 - GENERAL_PACKAGE_MASK = ((1 << 20) - 1) + GENERAL_PACKAGE_MASK = (1 << 20) - 1 GENERAL_PACKAGE_SRAM_START_ADDR_OFFSET = 20 - GENERAL_PACKAGE_SRAM_START_ADDR_MASK = ((1 << 10) - 1) + GENERAL_PACKAGE_SRAM_START_ADDR_MASK = (1 << 10) - 1 GENERAL_PACKAGE_TYPE_OFFSET = 19 GENERAL_PACKAGE_TYPE_MASK = 0x1 GENERAL_PACKAGE_COUNT_OFFSET = GENERAL_PACKAGE_OFFSET - GENERAL_PACKAGE_COUNT_MASK = ((1 << 19) - 1) + GENERAL_PACKAGE_COUNT_MASK = (1 << 19) - 1 @dataclass class ConfigFrameMask(FrameMask): - '''Specific for Conguration Frame Type II''' + """Specific for Conguration Frame Type II""" - '''General''' + """General""" TOTAL_BITS = 57 - '''Frame #1''' + """Frame #1""" WEIGHT_WIDTH_OFFSET = 28 - WEIGHT_WIDTH_MASK = ((1 << 2) - 1) + WEIGHT_WIDTH_MASK = (1 << 2) - 1 LCN_OFFSET = 24 - LCN_MASK = ((1 << 4) - 1) + LCN_MASK = (1 << 4) - 1 INPUT_WIDTH_OFFSET = 23 INPUT_WIDTH_MASK = 1 @@ -126,40 +129,41 @@ class ConfigFrameMask(FrameMask): SPIKE_WIDTH_MASK = 1 NEURON_NUM_OFFSET = 9 - NEURON_NUM_MASK = ((1 << 13) - 1) + NEURON_NUM_MASK = (1 << 13) - 1 POOL_MAX_OFFSET = 8 POOL_MAX_MASK = 1 TICK_WAIT_START_HIGH8_OFFSET = 0 TICK_WAIT_START_COMBINATION_OFFSET = 7 - TICK_WAIT_START_HIGH8_MASK = ((1 << 8) - 1) + TICK_WAIT_START_HIGH8_MASK = (1 << 8) - 1 - '''Frame #2''' + """Frame #2""" TICK_WAIT_START_LOW7_OFFSET = 23 - TICK_WAIT_START_LOW7_MASK = ((1 << 7) - 1) + TICK_WAIT_START_LOW7_MASK = (1 << 7) - 1 TICK_WAIT_END_OFFSET = 8 - TICK_WAIT_END_MASK = ((1 << 15) - 1) + TICK_WAIT_END_MASK = (1 << 15) - 1 SNN_EN_OFFSET = 7 SNN_EN_MASK = 1 TARGET_LCN_OFFSET = 3 - TARGET_LCN_MASK = ((1 << 4) - 1) + TARGET_LCN_MASK = (1 << 4) - 1 TEST_CHIP_ADDR_HIGH3_OFFSET = 0 TEST_CHIP_ADDR_COMBINATION_OFFSET = 7 - TEST_CHIP_ADDR_HIGH3_MASK = ((1 << 3) - 1) + TEST_CHIP_ADDR_HIGH3_MASK = (1 << 3) - 1 - '''Frame #3''' + """Frame #3""" TEST_CHIP_ADDR_LOW7_OFFSET = 23 - TEST_CHIP_ADDR_LOW7_MASK = ((1 << 7) - 1) + TEST_CHIP_ADDR_LOW7_MASK = (1 << 7) - 1 @unique class WeightPrecisionType(Enum): - '''Wight precision of crossbar''' + """Wight precision of crossbar""" + WEIGHT_WIDTH_1BIT = 0 WEIGHT_WIDTH_2BIT = 1 WEIGHT_WIDTH_4BIT = 2 @@ -168,7 +172,8 @@ class WeightPrecisionType(Enum): @unique class LCNTypes(Enum): - '''Scale of Fan-in extension''' + """Scale of Fan-in extension""" + LCN_1X = 0 LCN_2X = 1 LCN_4X = 2 @@ -180,20 +185,22 @@ class LCNTypes(Enum): @unique class InputWidthType(Enum): - '''Format of Input Spike''' + """Format of Input Spike""" + INPUT_WIDTH_1BIT = 0 INPUT_WIDTH_8BIT = 1 @unique class SpikeWidthType(Enum): - '''Format of Output Spike''' + """Format of Output Spike""" + SPIKE_WIDTH_1BIT = 0 SPIKE_WIDTH_8BIT = 1 class Coord: - '''Unchangeable coordinate''' + """Unchangeable coordinate""" def __init__(self, _x: Union[Tuple[int, int], int], _y: Optional[int] = None): if isinstance(_x, Tuple): @@ -221,14 +228,16 @@ def __ne__(self, other) -> bool: return self.x != other.x or self.y != other.y def __lt__(self, other) -> bool: - '''Whether on the left or below''' + """Whether on the left or below""" return not (self.x > other.x and self.y > other.y) def __gt__(self, other) -> bool: - '''Whether on the right and above''' - return (self.x > other.x and self.y > other.y) or \ - (self.x == other.x and self.y > other.y) or \ - (self.x > other.x and self.y == other.y) + """Whether on the right and above""" + return ( + (self.x > other.x and self.y > other.y) + or (self.x == other.x and self.y > other.y) + or (self.x > other.x and self.y == other.y) + ) def __le__(self, other) -> bool: return self.__lt__(other) or self.__eq__(other) @@ -243,7 +252,6 @@ def __str__(self) -> str: class CoordOffset(Coord): - def __init__(self, _x: int, _y: int): if not (-32 < _x < 32 and -32 < _y < 32): raise ValueError(f"-32 < x < 32, -32 < y < 32: ({_x}, {_y})") @@ -265,11 +273,12 @@ def __sub__(self, other): @unique class Direction(Enum): - ''' - For [x, y] - Left to right: +x - Top to bottom: +y - ''' + """ + For [x, y] + Left to right: +x + Top to bottom: +y + """ + EAST = CoordOffset(1, 0) SOUTH = CoordOffset(0, 1) WEST = CoordOffset(-1, 0) diff --git a/paitest/log.py b/paitest/log.py index e7125a7..3ee5cae 100644 --- a/paitest/log.py +++ b/paitest/log.py @@ -1,12 +1,8 @@ import logging -default_format: str = ( - "%(asctime)s " - "[%(levelname)s] " - "%(module)s | " - "%(message)s" -) +default_format: str = "%(asctime)s " "[%(levelname)s] " "%(module)s | " "%(message)s" -logging.basicConfig(level=logging.INFO, format=default_format, - datefmt="%Y-%m-%d %H:%M:%S") +logging.basicConfig( + level=logging.INFO, format=default_format, datefmt="%Y-%m-%d %H:%M:%S" +) logger = logging.getLogger() diff --git a/paitest/paitest.py b/paitest/paitest.py index 4ffe878..7c492f3 100644 --- a/paitest/paitest.py +++ b/paitest/paitest.py @@ -1,5 +1,12 @@ -from .frames import Addr2Coord, Coord2Addr, Coord, FrameGen, \ - Direction, FrameMask as FM, FrameSubType as FST +from .frames import ( + Addr2Coord, + Coord2Addr, + Coord, + FrameGen, + Direction, + FrameMask as FM, + FrameSubType as FST, +) from pathlib import Path from typing import List, Union, Literal, Tuple, Optional import random @@ -11,15 +18,15 @@ class paitest: - - def __init__(self, - direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] = "EAST", - fixed_chip_coord: Tuple[int, int] = (0, 0) - ) -> None: - ''' + def __init__( + self, + direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] = "EAST", + fixed_chip_coord: Tuple[int, int] = (0, 0), + ) -> None: + """ :param direction: The direction relative to the PAICORE. Default is 'EAST'. :param fixed_chip_coord: The chip address of the PAICORE under test. Default is (0, 0). - ''' + """ self._work_dir: Union[Path, None] = None self._fc: io.BufferedWriter @@ -34,22 +41,22 @@ def __init__(self, self._ensure_direction(direction) - def Get1GroupForNCoresWithNParams(self, - N: int, - *, - save_dir: Optional[Union[str, - Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: - ''' + def Get1GroupForNCoresWithNParams( + self, + N: int, + *, + save_dir: Optional[Union[str, Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None, + ) -> Tuple[Tuple[int, ...], ...]: + """ Generate 1 group(case) for 'N' cores coordinates with 'N' different parameters. - `N`: How many cores coordinates under test. - `save_dir`: Where to save the frames files. - `masked_core_coord`: to avoid generating the specific core coordinate. - + :return: Three tuples including config, testin & testout tuples. 3*N frames in config & testout tuple and N frames in testin tuple. - ''' + """ self._ensure_cores(N) if save_dir: @@ -87,32 +94,41 @@ def Get1GroupForNCoresWithNParams(self, for j in range(3): config_frame = FrameGen.GenConfigFrame( - FST.CONFIG_TYPE2, self._fixed_chip_coord, core_coord, self._fixed_core_star_coord, param[j]) + FST.CONFIG_TYPE2, + self._fixed_chip_coord, + core_coord, + self._fixed_core_star_coord, + param[j], + ) cf_list.append(config_frame) - logger.info("Config frame #%d/3: 0x%x in group #%d/%d" % - (j+1, config_frame, i+1, N)) + logger.info( + "Config frame #%d/3: 0x%x in group #%d/%d" + % (j + 1, config_frame, i + 1, N) + ) testout_frame = FrameGen.GenTest2OutFrame( - test_chip_coord, core_coord, self._fixed_core_star_coord, param[j]) + test_chip_coord, core_coord, self._fixed_core_star_coord, param[j] + ) to_list.append(testout_frame) - logger.info("Test out frame #%d/3: 0x%x in group #%d/%d" % - (j+1, testout_frame, i+1, N)) + logger.info( + "Test out frame #%d/3: 0x%x in group #%d/%d" + % (j + 1, testout_frame, i + 1, N) + ) if self._work_dir: - self._fc.write(config_frame.to_bytes( - length=8, byteorder="big")) - self._fo.write(testout_frame.to_bytes( - length=8, byteorder="big")) + self._fc.write(config_frame.to_bytes(length=8, byteorder="big")) + self._fo.write(testout_frame.to_bytes(length=8, byteorder="big")) testin_frame = FrameGen.GenTest2InFrame( - test_chip_coord, core_coord, self._fixed_core_star_coord) + test_chip_coord, core_coord, self._fixed_core_star_coord + ) ti_list.append(testin_frame) - logger.info("Test in frame #1/1: 0x%x in group #%d/%d" % - (testin_frame, i+1, N)) + logger.info( + "Test in frame #1/1: 0x%x in group #%d/%d" % (testin_frame, i + 1, N) + ) if self._work_dir: - self._fi.write(testin_frame.to_bytes( - length=8, byteorder="big")) + self._fi.write(testin_frame.to_bytes(length=8, byteorder="big")) if self._work_dir: self._fc.close() @@ -121,22 +137,22 @@ def Get1GroupForNCoresWithNParams(self, return tuple(cf_list), tuple(ti_list), tuple(to_list) - def Get1GroupForNCoresWith1Param(self, - N: int, - *, - save_dir: Optional[Union[str, - Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: - ''' + def Get1GroupForNCoresWith1Param( + self, + N: int, + *, + save_dir: Optional[Union[str, Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None, + ) -> Tuple[Tuple[int, ...], ...]: + """ Generate 1 group(case) for 'N' random cores coordinates with the same parameters. - + - `N`: How many cores coordinates under test. - `save_dir`: Where to save the frames files. - `masked_core_coord`: to avoid generating the specific core coordinate. - + :return: Three tuples including config, testin & testout tuples. 3*N frames in config & testout tuple and N frames in testin tuple. - ''' + """ self._ensure_cores(N) if save_dir: @@ -173,58 +189,67 @@ def Get1GroupForNCoresWith1Param(self, for j in range(3): config_frame = FrameGen.GenConfigFrame( - FST.CONFIG_TYPE2, self._fixed_chip_coord, core_coord, self._fixed_core_star_coord, param[j]) + FST.CONFIG_TYPE2, + self._fixed_chip_coord, + core_coord, + self._fixed_core_star_coord, + param[j], + ) cf_list.append(config_frame) - logger.info("Config frame #%d/3: 0x%x in group #%d/%d" % - (j+1, config_frame, i+1, N)) + logger.info( + "Config frame #%d/3: 0x%x in group #%d/%d" + % (j + 1, config_frame, i + 1, N) + ) testout_frame = FrameGen.GenTest2OutFrame( - test_chip_coord, core_coord, self._fixed_core_star_coord, param[j]) + test_chip_coord, core_coord, self._fixed_core_star_coord, param[j] + ) to_list.append(testout_frame) - logger.info("Test out frame #%d/3: 0x%x in group #%d/%d" % - (j+1, testout_frame, i+1, N)) + logger.info( + "Test out frame #%d/3: 0x%x in group #%d/%d" + % (j + 1, testout_frame, i + 1, N) + ) if self._work_dir: - self._fc.write(config_frame.to_bytes( - length=8, byteorder="big")) - self._fo.write(testout_frame.to_bytes( - length=8, byteorder="big")) + self._fc.write(config_frame.to_bytes(length=8, byteorder="big")) + self._fo.write(testout_frame.to_bytes(length=8, byteorder="big")) testin_frame = FrameGen.GenTest2InFrame( - test_chip_coord, core_coord, self._fixed_core_star_coord) + test_chip_coord, core_coord, self._fixed_core_star_coord + ) ti_list.append(testin_frame) - logger.info("Test in frame #1/1: 0x%x in group #%d/%d" % - (testin_frame, i+1, N)) + logger.info( + "Test in frame #1/1: 0x%x in group #%d/%d" % (testin_frame, i + 1, N) + ) if self._work_dir: - self._fi.write(testin_frame.to_bytes( - length=8, byteorder="big")) + self._fi.write(testin_frame.to_bytes(length=8, byteorder="big")) return tuple(cf_list), tuple(ti_list), tuple(to_list) - def GetNGroupsFor1CoreWithNParams(self, - N: int, - *, - save_dir: Optional[Union[str, - Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: - ''' + def GetNGroupsFor1CoreWithNParams( + self, + N: int, + *, + save_dir: Optional[Union[str, Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None, + ) -> Tuple[Tuple[int, ...], ...]: + """ Generate 'N' groups(cases) for 1 random core coordinate with 'N' different parameters. - + - `N`: How many test groups(cases) of 1 core will be generated. - `save_dir`: Where to save the frames files. - `masked_core_coord`: to avoid generating the specific core coordinate. - + :return: Three tuples including config, testin & testout tuples. 3*N frames in config & testout tuple and N frames in testin tuple. - ''' + """ self._ensure_cores(N) - + if save_dir: self._ensure_dir(save_dir) else: self._work_dir = None - + # 1. Get the test chip coordinate. test_chip_coord = self._direction.value + self._fixed_chip_coord @@ -235,10 +260,10 @@ def GetNGroupsFor1CoreWithNParams(self, _masked_core_coord = None core_coord = self._Get1CoreCoord(_masked_core_coord) - + # 3. Get the parameters reg. params = self._GetNParams(N, core_coord, False) - + cf_list: List[int] = [] ti_list: List[int] = [] to_list: List[int] = [] @@ -254,40 +279,49 @@ def GetNGroupsFor1CoreWithNParams(self, for j in range(3): config_frame = FrameGen.GenConfigFrame( - FST.CONFIG_TYPE2, self._fixed_chip_coord, core_coord, self._fixed_core_star_coord, param[j]) + FST.CONFIG_TYPE2, + self._fixed_chip_coord, + core_coord, + self._fixed_core_star_coord, + param[j], + ) cf_list.append(config_frame) - logger.info("Config frame #%d/3: 0x%x in group #%d/%d" % - (j+1, config_frame, i+1, N)) + logger.info( + "Config frame #%d/3: 0x%x in group #%d/%d" + % (j + 1, config_frame, i + 1, N) + ) testout_frame = FrameGen.GenTest2OutFrame( - test_chip_coord, core_coord, self._fixed_core_star_coord, param[j]) + test_chip_coord, core_coord, self._fixed_core_star_coord, param[j] + ) to_list.append(testout_frame) - logger.info("Test out frame #%d/3: 0x%x in group #%d/%d" % - (j+1, testout_frame, i+1, N)) + logger.info( + "Test out frame #%d/3: 0x%x in group #%d/%d" + % (j + 1, testout_frame, i + 1, N) + ) if self._work_dir: - self._fc.write(config_frame.to_bytes( - length=8, byteorder="big")) - self._fo.write(testout_frame.to_bytes( - length=8, byteorder="big")) + self._fc.write(config_frame.to_bytes(length=8, byteorder="big")) + self._fo.write(testout_frame.to_bytes(length=8, byteorder="big")) testin_frame = FrameGen.GenTest2InFrame( - test_chip_coord, core_coord, self._fixed_core_star_coord) + test_chip_coord, core_coord, self._fixed_core_star_coord + ) ti_list.append(testin_frame) - logger.info("Test in frame #1/1: 0x%x in group #%d/%d" % - (testin_frame, i+1, N)) + logger.info( + "Test in frame #1/1: 0x%x in group #%d/%d" % (testin_frame, i + 1, N) + ) if self._work_dir: - self._fi.write(testin_frame.to_bytes( - length=8, byteorder="big")) + self._fi.write(testin_frame.to_bytes(length=8, byteorder="big")) return tuple(cf_list), tuple(ti_list), tuple(to_list) - def ReplaceCoreCoord(self, - frames: Union[int, List[int], Tuple[int, ...]], - new_core_coord: Optional[Tuple[int, int]] = None, - ) -> Union[int, Tuple[int, ...]]: - + def ReplaceCoreCoord( + self, + frames: Union[int, List[int], Tuple[int, ...]], + new_core_coord: Optional[Tuple[int, int]] = None, + ) -> Union[int, Tuple[int, ...]]: if isinstance(frames, int): _frame = frames else: @@ -298,7 +332,8 @@ def ReplaceCoreCoord(self, else: # Auto mask the old core coordinate then random pick one old_core_addr = ( - _frame >> FM.GENERAL_CORE_ADDR_OFFSET) & FM.GENERAL_CORE_ADDR_MASK + _frame >> FM.GENERAL_CORE_ADDR_OFFSET + ) & FM.GENERAL_CORE_ADDR_MASK old_core_coord = Addr2Coord(old_core_addr) _new_core_coord = self._Get1CoreCoord(old_core_coord) @@ -309,10 +344,10 @@ def ReplaceCoreCoord(self, return self._ReplaceCoreCoordInNFrames(_frames, _new_core_coord) @staticmethod - def SaveFrames(save_path: Union[str, Path], - frames: Union[int, List[int], Tuple[int, ...]] - ) -> None: - '''Write frames into specific binary file. Must be '.bin' suffix.''' + def SaveFrames( + save_path: Union[str, Path], frames: Union[int, List[int], Tuple[int, ...]] + ) -> None: + """Write frames into specific binary file. Must be '.bin' suffix.""" _path = Path(save_path) @@ -327,18 +362,18 @@ def SaveFrames(save_path: Union[str, Path], f.write(frame.to_bytes(8, "big")) def _Get1CoreCoord(self, masked_coord: Optional[Coord] = None) -> Coord: - ''' - Generate a random core coordinate. Indicate the masked one to avoid generating the same one - ''' + """ + Generate a random core coordinate. Indicate the masked one to avoid generating the same one + """ return self._GetNCoresCoord(N=1, masked_coord=masked_coord)[0] - def _GetNCoresCoord(self, - N: int, - masked_coord: Optional[Coord] = None - ) -> List[Coord]: - ''' - Generate 'N' unique cores coordinates. Optional for excluding one masked core address - ''' + def _GetNCoresCoord( + self, N: int, masked_coord: Optional[Coord] = None + ) -> List[Coord]: + """ + Generate 'N' unique cores coordinates. Optional for excluding one masked core address + """ + def _CoordGenerator(): coordinates = set() @@ -356,31 +391,34 @@ def _CoordGenerator(): if isinstance(masked_coord, Coord): self._ensure_coord(masked_coord) if N > 1007: - raise ValueError("When choose to mask a core, \ - the max value of cores to be generated is 1007") + raise ValueError( + "When choose to mask a core, \ + the max value of cores to be generated is 1007" + ) generator = _CoordGenerator() core_addr_list = [next(generator) for _ in range(N)] return core_addr_list - def _Get1Param(self, - core_coords: Union[List[Coord], Coord], - is_legal: bool = False - ) -> List[int]: - '''Generate one group parameter for parameter register''' + def _Get1Param( + self, core_coords: Union[List[Coord], Coord], is_legal: bool = False + ) -> List[int]: + """Generate one group parameter for parameter register""" return self._GetNParams(1, core_coords, is_legal)[0] - def _GetNParams(self, - N: int, - core_coords: Union[List[Coord], Coord], - is_legal: bool = False, - ) -> List[List[int]]: - ''' - Generate 'N' parameters reg for parameter register. + def _GetNParams( + self, + N: int, + core_coords: Union[List[Coord], Coord], + is_legal: bool = False, + ) -> List[List[int]]: + """ + Generate 'N' parameters reg for parameter register. + + is_legal: whether to generate legal parameters for every core + """ - is_legal: whether to generate legal parameters for every core - ''' def _ParamGenerator(): test_chip_coord: Coord = self._direction.value + self._fixed_chip_coord @@ -392,11 +430,15 @@ def _ParamGenerator(): pass else: param = FrameGen.GenConfigGroup( - FST.CONFIG_TYPE2, self._fixed_chip_coord, core_coord, - self._fixed_core_star_coord, test_chip_coord) + FST.CONFIG_TYPE2, + self._fixed_chip_coord, + core_coord, + self._fixed_core_star_coord, + test_chip_coord, + ) yield param - + if isinstance(core_coords, Coord): _core_coords = [core_coords] else: @@ -408,38 +450,39 @@ def _ParamGenerator(): return parameters def _ReplaceCoreCoordIn1Frame(self, frame: int, new_core_coord: Coord) -> int: - '''Replace the original core coordinate of a frame with a new one.''' - mask = FM.GENERAL_MASK & \ - (~(FM.GENERAL_CORE_ADDR_MASK << FM.GENERAL_CORE_ADDR_OFFSET)) + """Replace the original core coordinate of a frame with a new one.""" + mask = FM.GENERAL_MASK & ( + ~(FM.GENERAL_CORE_ADDR_MASK << FM.GENERAL_CORE_ADDR_OFFSET) + ) new_core_addr = Coord2Addr(new_core_coord) return (frame & mask) | (new_core_addr << FM.GENERAL_CORE_ADDR_OFFSET) - def _ReplaceCoreCoordInNFrames(self, - frames: List[int], - new_core_coord: Coord, - ) -> Tuple[int, ...]: - ''' - Replace the core coordinate of frames with a specific or random one. + def _ReplaceCoreCoordInNFrames( + self, + frames: List[int], + new_core_coord: Coord, + ) -> Tuple[int, ...]: + """ + Replace the core coordinate of frames with a specific or random one. - Indicate the core coordinate to specify it. Keep the parameters still. - ''' - mask = FM.GENERAL_MASK & \ - (~(FM.GENERAL_CORE_ADDR_MASK << FM.GENERAL_CORE_ADDR_OFFSET)) + Indicate the core coordinate to specify it. Keep the parameters still. + """ + mask = FM.GENERAL_MASK & ( + ~(FM.GENERAL_CORE_ADDR_MASK << FM.GENERAL_CORE_ADDR_OFFSET) + ) new_core_addr = Coord2Addr(new_core_coord) for frame in frames: - frame = (frame & mask) | ( - new_core_addr << FM.GENERAL_CORE_ADDR_OFFSET) + frame = (frame & mask) | (new_core_addr << FM.GENERAL_CORE_ADDR_OFFSET) return tuple(frames) def _ReplaceHeader(self, frame: int, header: FST) -> int: - '''Replace the header of a frame with the new one.''' - mask = FM.GENERAL_MASK & \ - (~(FM.GENERAL_HEADER_MASK << FM.GENERAL_HEADER_OFFSET)) + """Replace the header of a frame with the new one.""" + mask = FM.GENERAL_MASK & (~(FM.GENERAL_HEADER_MASK << FM.GENERAL_HEADER_OFFSET)) return (frame & mask) | (header.value << FM.GENERAL_HEADER_OFFSET) @@ -462,12 +505,13 @@ def _ensure_cores(self, Ncores: int) -> None: if Ncores > 1024 - 16: raise ValueError("Value of cores is no more than 1008") - def _ensure_direction(self, direction: Literal["EAST", "SOUTH", "WEST", "NORTH"]) -> None: + def _ensure_direction( + self, direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] + ) -> None: self._direction = Direction[direction.upper()] def _ensure_coord(self, coord: Coord) -> None: if coord >= Coord(0b11100, 0b11100): - raise ValueError( - "Address coordinate must: 0 <= x < 28 or 0 <= y < 28") + raise ValueError("Address coordinate must: 0 <= x < 28 or 0 <= y < 28") self._masked_core_coord = coord diff --git a/paitest/paitest.pyi b/paitest/paitest.pyi index 8f1dcaf..832f135 100644 --- a/paitest/paitest.pyi +++ b/paitest/paitest.pyi @@ -1,57 +1,50 @@ from typing import Literal, Tuple, List, Optional, Union, overload from pathlib import Path - class paitest: - def __init__(self, - direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] = "EAST", - fixed_chip_coord: Tuple[int, int] = (0, 0) - ) -> None: ... - - def Get1GroupForNCoresWithNParams(self, - N: int, - *, - save_dir: Optional[Union[str, - Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: ... - - def Get1GroupForNCoresWith1Param(self, - N: int, - *, - save_dir: Optional[Union[str, - Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: ... - - def GetNGroupsFor1CoreWithNParams(self, - N: int, - *, - save_dir: Optional[Union[str, - Path]] = None, - masked_core_coord: Optional[Tuple[int, int]] = None - ) -> Tuple[Tuple[int, ...], ...]: ... - + def __init__( + self, + direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] = "EAST", + fixed_chip_coord: Tuple[int, int] = (0, 0), + ) -> None: ... + def Get1GroupForNCoresWithNParams( + self, + N: int, + *, + save_dir: Optional[Union[str, Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None + ) -> Tuple[Tuple[int, ...], ...]: ... + def Get1GroupForNCoresWith1Param( + self, + N: int, + *, + save_dir: Optional[Union[str, Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None + ) -> Tuple[Tuple[int, ...], ...]: ... + def GetNGroupsFor1CoreWithNParams( + self, + N: int, + *, + save_dir: Optional[Union[str, Path]] = None, + masked_core_coord: Optional[Tuple[int, int]] = None + ) -> Tuple[Tuple[int, ...], ...]: ... @overload def ReplaceCoreCoord(self, frames: int) -> int: ... @overload def ReplaceCoreCoord(self, frames: List[int]) -> Tuple[int, ...]: ... @overload def ReplaceCoreCoord(self, frames: Tuple[int, ...]) -> Tuple[int, ...]: ... - @overload - def ReplaceCoreCoord( - self, frames: int, new_core_coord: Tuple[int, int]) -> int: ... - + def ReplaceCoreCoord(self, frames: int, new_core_coord: Tuple[int, int]) -> int: ... @overload def ReplaceCoreCoord( - self, frames: List[int], new_core_coord: Tuple[int, int]) -> Tuple[int, ...]: ... - + self, frames: List[int], new_core_coord: Tuple[int, int] + ) -> Tuple[int, ...]: ... @overload def ReplaceCoreCoord( - self, frames: Tuple[int, ...], new_core_coord: Tuple[int, int]) -> Tuple[int, ...]: ... - + self, frames: Tuple[int, ...], new_core_coord: Tuple[int, int] + ) -> Tuple[int, ...]: ... @staticmethod - def SaveFrames(save_path: Union[str, Path], - frames: Union[int, List[int], Tuple[int, ...]] - ) -> None: ... + def SaveFrames( + save_path: Union[str, Path], frames: Union[int, List[int], Tuple[int, ...]] + ) -> None: ... From 97c29592b7605186c80177f23cdf08c26cc19893 Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Sat, 15 Apr 2023 15:02:20 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=F0=9F=A4=96=20chore:=20add=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/poetry-publish.yml | 33 +++++++++++++++++++++++++++ .github/workflows/release-drafter.yml | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/poetry-publish.yml diff --git a/.github/workflows/poetry-publish.yml b/.github/workflows/poetry-publish.yml new file mode 100644 index 0000000..f44967f --- /dev/null +++ b/.github/workflows/poetry-publish.yml @@ -0,0 +1,33 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Upload Python Package + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + publish: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ env.TAG_NAME }} + + - name: Publish python poetry package + uses: JRubics/poetry-publish@v1.16 + with: + python_version: "3.10" + pypi_token: ${{ secrets.PYPI_API_TOKEN }} + build_format: "wheel" + ignore_dev_requirements: "yes" \ No newline at end of file diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index e0b4cb3..2da1537 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -37,4 +37,4 @@ jobs: tag: ${{ env.TAG_NAME }} publish: true env: - GITHUB_TOKEN: ${{ secrets.REPO_TOKEN }} + GITHUB_TOKEN: ${{ secrets.ORG_TOKEN }} From 1929cafde33a3082872301ecbe4619f7a0554a49 Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Sat, 15 Apr 2023 21:06:28 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=F0=9F=9A=80=20enhancement:=20simplify=20?= =?UTF-8?q?check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paitest/frames/__init__.py | 1 + paitest/frames/frame.py | 38 ++++++++++++++++++++++------------ paitest/frames/frame_params.py | 4 ++-- paitest/paitest.py | 25 +++++++--------------- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/paitest/frames/__init__.py b/paitest/frames/__init__.py index 8a6421f..fb9b0da 100644 --- a/paitest/frames/__init__.py +++ b/paitest/frames/__init__.py @@ -6,4 +6,5 @@ Direction as Direction, FrameMask as FrameMask, FrameSubType as FrameSubType, + FrameDecoder as FrameDecoder ) diff --git a/paitest/frames/frame.py b/paitest/frames/frame.py index 1d44751..3601d29 100644 --- a/paitest/frames/frame.py +++ b/paitest/frames/frame.py @@ -5,13 +5,10 @@ ConfigFrameMask as CFM, ) from .frame_params import * -from typing import List, Tuple, Union, Dict, Optional +from typing import List, Tuple, Union, Dict, Optional, Any import random -__all__ = ["Addr2Coord", "Coord2Addr", "FrameGen", "Coord"] - - def Addr2Coord(addr: int) -> Coord: return Coord(addr >> 5, addr & ((1 << 5) - 1)) @@ -194,8 +191,19 @@ def __init__(self): self.groups_len: int self._frame: int self._frames_group: Tuple[int, ...] + + # Total attributes dictionary + self._attr_dict: Dict[str, Any] = {} + + # For general attributes: + self._general_attr: Dict[str, Union[FST, Coord]] = { + "sub_type": FST.CONFIG_TYPE2, + "chip_coord": Coord(0, 0), + "core_coord": Coord(0, 0), + "core_star_coord": Coord(0, 0) + } - # For type II + # For type II attributes self._param_reg_dict: Dict[str, Union[int, bool, Coord]] = { "weight_width": 0, "LCN": 0, @@ -210,7 +218,7 @@ def __init__(self): "test_chip_coord": Coord(0, 0), } - def decode(self, frames: Union[int, List[int], Tuple[int, ...]]) -> None: + def decode(self, frames: Union[int, List[int], Tuple[int, ...]]) -> Dict[str, Any]: """ Call for decoding a frame or a valid group of frames. @@ -226,6 +234,7 @@ def decode(self, frames: Union[int, List[int], Tuple[int, ...]]) -> None: self._frames_group = tuple(frames) self._decode() + return self._attr_dict def _get_subtype(self) -> FST: _header: int = ( @@ -290,9 +299,14 @@ def _get_payload(self) -> Union[List[int], int]: def _decode(self) -> None: subtype = self._get_subtype() + self._general_attr["sub_type"] = subtype + self._general_attr["chip_coord"] = self._get_chip_coord() + self._general_attr["core_coord"] = self._get_core_coord() + self._general_attr["core_star_coord"] = self._get_core_star_coord() if subtype == FST.CONFIG_TYPE2: self._decode_config2() + self._attr_dict = {**self._general_attr, **self._param_reg_dict} else: raise NotImplementedError @@ -301,7 +315,7 @@ def _decode(self) -> None: def _decode_config1(self): pass - def _decode_config2(self): + def _decode_config2(self) -> None: self._param_reg_parse() def _decode_testout1(self): @@ -411,13 +425,11 @@ def _param_reg_parse(self) -> None: self._param_reg_dict["test_chip_coord"] = test_chip_addr_combine(high3, low7) def _decode_direction(self) -> Direction: - offset: CoordOffset = ( - self._param_reg_dict["test_chip_coord"] - self.chip_coord - ) # type: ignore + test_chip_coord: Coord = self._param_reg_dict["test_chip_coord"] # type: ignore + offset = test_chip_coord - self._get_chip_coord() try: direction = Direction(offset) return direction - except ValueError: - print("Offset is invalid, return the default direction: EAST") - return Direction("EAST") + except: + raise ValueError("Offset is invalid. Check the parameters.") diff --git a/paitest/frames/frame_params.py b/paitest/frames/frame_params.py index 2b80d62..557012c 100644 --- a/paitest/frames/frame_params.py +++ b/paitest/frames/frame_params.py @@ -200,7 +200,7 @@ class SpikeWidthType(Enum): class Coord: - """Unchangeable coordinate""" + """Coordinate class""" def __init__(self, _x: Union[Tuple[int, int], int], _y: Optional[int] = None): if isinstance(_x, Tuple): @@ -229,7 +229,7 @@ def __ne__(self, other) -> bool: def __lt__(self, other) -> bool: """Whether on the left or below""" - return not (self.x > other.x and self.y > other.y) + return (self.x < other.x or self.y < other.y) def __gt__(self, other) -> bool: """Whether on the right and above""" diff --git a/paitest/paitest.py b/paitest/paitest.py index 7c492f3..f4d72ef 100644 --- a/paitest/paitest.py +++ b/paitest/paitest.py @@ -49,7 +49,7 @@ def Get1GroupForNCoresWithNParams( masked_core_coord: Optional[Tuple[int, int]] = None, ) -> Tuple[Tuple[int, ...], ...]: """ - Generate 1 group(case) for 'N' cores coordinates with 'N' different parameters. + Generate 1 group(case) for 'N' random cores coordinates with 'N' different parameters. - `N`: How many cores coordinates under test. - `save_dir`: Where to save the frames files. @@ -163,7 +163,7 @@ def Get1GroupForNCoresWith1Param( # 1. Get the test chip coordinate. test_chip_coord = self._direction.value + self._fixed_chip_coord - # 2. Get the core coordinates list. + # 2. Get N core coordinates list. if isinstance(masked_core_coord, Tuple): _masked_core_coord = Coord(masked_core_coord) else: @@ -392,14 +392,13 @@ def _CoordGenerator(): self._ensure_coord(masked_coord) if N > 1007: raise ValueError( - "When choose to mask a core, \ - the max value of cores to be generated is 1007" + "When choose to mask a core, the max value of cores to be generated is 1007" ) generator = _CoordGenerator() - core_addr_list = [next(generator) for _ in range(N)] + core_coord_list = [next(generator) for _ in range(N)] - return core_addr_list + return core_coord_list def _Get1Param( self, core_coords: Union[List[Coord], Coord], is_legal: bool = False @@ -415,8 +414,7 @@ def _GetNParams( ) -> List[List[int]]: """ Generate 'N' parameters reg for parameter register. - - is_legal: whether to generate legal parameters for every core + - `is_legal`: whether to generate legal parameters for every core """ def _ParamGenerator(): @@ -466,7 +464,6 @@ def _ReplaceCoreCoordInNFrames( ) -> Tuple[int, ...]: """ Replace the core coordinate of frames with a specific or random one. - Indicate the core coordinate to specify it. Keep the parameters still. """ mask = FM.GENERAL_MASK & ( @@ -495,15 +492,9 @@ def _ensure_dir(self, user_dir: Union[str, Path]) -> None: self._work_dir = _user_dir - def _ensure_groups(self, groups: int) -> None: - if groups > 1024 - 16: - raise ValueError("Value of groups is no more than 1008") - - logger.info(f"{groups} groups cases will be generated...") - def _ensure_cores(self, Ncores: int) -> None: - if Ncores > 1024 - 16: - raise ValueError("Value of cores is no more than 1008") + if Ncores > 1024 - 16 or Ncores < 1: + raise ValueError("Range of Ncores is 0 < N < 1008") def _ensure_direction( self, direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] From 6965cc56e14950b230313f6000446f4b399e7e7c Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Sat, 15 Apr 2023 23:55:51 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E2=AC=87=EF=B8=8F=20enhancement:=20downg?= =?UTF-8?q?rade=20Python=20to=20`^3.6`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paitest/frames/frame_params.py | 5 +---- paitest/paitest.py | 23 +++++++++++++++++------ paitest/paitest.pyi | 23 +++++++++++++++++------ pyproject.toml | 2 +- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/paitest/frames/frame_params.py b/paitest/frames/frame_params.py index 557012c..8ce71dc 100644 --- a/paitest/frames/frame_params.py +++ b/paitest/frames/frame_params.py @@ -1,4 +1,3 @@ -from dataclasses import dataclass from enum import Flag, Enum, unique from typing import Tuple, Union, Optional @@ -41,7 +40,6 @@ class FrameSubType(Flag): WORK_TYPE4 = 0b1011 -@dataclass class FrameMask: """ Format of data package or single frame for general usages: @@ -108,7 +106,6 @@ class FrameMask: GENERAL_PACKAGE_COUNT_MASK = (1 << 19) - 1 -@dataclass class ConfigFrameMask(FrameMask): """Specific for Conguration Frame Type II""" @@ -229,7 +226,7 @@ def __ne__(self, other) -> bool: def __lt__(self, other) -> bool: """Whether on the left or below""" - return (self.x < other.x or self.y < other.y) + return self.x < other.x or self.y < other.y def __gt__(self, other) -> bool: """Whether on the right and above""" diff --git a/paitest/paitest.py b/paitest/paitest.py index f4d72ef..a164533 100644 --- a/paitest/paitest.py +++ b/paitest/paitest.py @@ -8,11 +8,15 @@ FrameSubType as FST, ) from pathlib import Path -from typing import List, Union, Literal, Tuple, Optional +from typing import List, Union, Tuple, Optional import random import io +import sys from .log import logger +if sys.version_info >= (3, 8): + from typing import Literal + __all__ = ["paitest"] @@ -20,7 +24,7 @@ class paitest: def __init__( self, - direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] = "EAST", + direction="EAST", fixed_chip_coord: Tuple[int, int] = (0, 0), ) -> None: """ @@ -496,10 +500,17 @@ def _ensure_cores(self, Ncores: int) -> None: if Ncores > 1024 - 16 or Ncores < 1: raise ValueError("Range of Ncores is 0 < N < 1008") - def _ensure_direction( - self, direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] - ) -> None: - self._direction = Direction[direction.upper()] + if sys.version_info >= (3, 8): + + def _ensure_direction( + self, direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] + ) -> None: + self._direction = Direction[direction.upper()] + + else: + + def _ensure_direction(self, direction: str) -> None: + self._direction = Direction[direction.upper()] def _ensure_coord(self, coord: Coord) -> None: if coord >= Coord(0b11100, 0b11100): diff --git a/paitest/paitest.pyi b/paitest/paitest.pyi index 832f135..bc08623 100644 --- a/paitest/paitest.pyi +++ b/paitest/paitest.pyi @@ -1,12 +1,23 @@ -from typing import Literal, Tuple, List, Optional, Union, overload +from typing import Tuple, List, Optional, Union, overload +import sys +if sys.version_info >= (3, 8): + from typing import Literal from pathlib import Path class paitest: - def __init__( - self, - direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] = "EAST", - fixed_chip_coord: Tuple[int, int] = (0, 0), - ) -> None: ... + if sys.version_info >= (3, 8): + def __init__( + self, + direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] = "EAST", + fixed_chip_coord: Tuple[int, int] = (0, 0), + ) -> None: ... + else: + def __init__( + self, + direction: str = "EAST", + fixed_chip_coord: Tuple[int, int] = (0, 0), + ) -> None: ... + def Get1GroupForNCoresWithNParams( self, N: int, diff --git a/pyproject.toml b/pyproject.toml index a29240b..42a803c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ keywords = ["PAICookers", "PAITest", "PAICORE"] include = ["./paitest"] [tool.poetry.dependencies] -python = "^3.8" +python = "^3.6" [tool.poetry.group.dev.dependencies] autopep8 = "^2.0.2" From cf1e3e29481d524d19aa3277a9b6a24cb8268711 Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Sun, 16 Apr 2023 12:14:04 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E2=9C=A8=20feature:=20add=20function=20`?= =?UTF-8?q?ReplaceCoreCoord`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paitest/frames/frame.py | 14 +++--- paitest/paitest.py | 109 ++++++++++++++++++---------------------- 2 files changed, 58 insertions(+), 65 deletions(-) diff --git a/paitest/frames/frame.py b/paitest/frames/frame.py index 3601d29..38ec4a5 100644 --- a/paitest/frames/frame.py +++ b/paitest/frames/frame.py @@ -187,20 +187,22 @@ def GenTest2OutFrame( class FrameDecoder: + """Frame decoder""" + def __init__(self): self.groups_len: int self._frame: int self._frames_group: Tuple[int, ...] - + # Total attributes dictionary self._attr_dict: Dict[str, Any] = {} - + # For general attributes: self._general_attr: Dict[str, Union[FST, Coord]] = { "sub_type": FST.CONFIG_TYPE2, "chip_coord": Coord(0, 0), "core_coord": Coord(0, 0), - "core_star_coord": Coord(0, 0) + "core_star_coord": Coord(0, 0), } # For type II attributes @@ -344,17 +346,17 @@ def _general_info(self) -> None: chip_coord = self._get_chip_coord() print( - "#2 Chip address: [0x%02x | 0x%02x]" % (chip_coord.x, chip_coord.y) + "#2 Chip coordinate: [0x%02x | 0x%02x]" % (chip_coord.x, chip_coord.y) ) core_coord = self._get_core_coord() print( - "#3 Core address: [0x%02x | 0x%02x]" % (core_coord.x, core_coord.y) + "#3 Core coordinate: [0x%02x | 0x%02x]" % (core_coord.x, core_coord.y) ) core_star_coord = self._get_core_star_coord() print( - "#4 Core* address: [0x%02x | 0x%02x]" + "#4 Core* coordinate: [0x%02x | 0x%02x]" % (core_star_coord.x, core_star_coord.y) ) diff --git a/paitest/paitest.py b/paitest/paitest.py index a164533..6d309ae 100644 --- a/paitest/paitest.py +++ b/paitest/paitest.py @@ -10,7 +10,6 @@ from pathlib import Path from typing import List, Union, Tuple, Optional import random -import io import sys from .log import logger @@ -31,12 +30,6 @@ def __init__( :param direction: The direction relative to the PAICORE. Default is 'EAST'. :param fixed_chip_coord: The chip address of the PAICORE under test. Default is (0, 0). """ - - self._work_dir: Union[Path, None] = None - self._fc: io.BufferedWriter - self._fi: io.BufferedWriter - self._fo: io.BufferedWriter - self._verbose: bool = True self._fixed_chip_coord: Coord = Coord(fixed_chip_coord) self._masked_core_coord: Coord @@ -64,9 +57,9 @@ def Get1GroupForNCoresWithNParams( self._ensure_cores(N) if save_dir: - self._ensure_dir(save_dir) + work_dir = self._ensure_dir(save_dir) else: - self._work_dir = None + work_dir = None # 1. Get the test chip coordinate. test_chip_coord: Coord = self._direction.value + self._fixed_chip_coord @@ -86,11 +79,6 @@ def Get1GroupForNCoresWithNParams( ti_list: List[int] = [] to_list: List[int] = [] - if self._work_dir: - self._fc = open(self._work_dir / "config.bin", "wb") - self._fi = open(self._work_dir / "testin.bin", "wb") - self._fo = open(self._work_dir / "testout.bin", "wb") - for i in range(N): logger.info(f"Generating test group #{i+1}/{N}...") core_coord = core_coords[i] @@ -119,10 +107,6 @@ def Get1GroupForNCoresWithNParams( % (j + 1, testout_frame, i + 1, N) ) - if self._work_dir: - self._fc.write(config_frame.to_bytes(length=8, byteorder="big")) - self._fo.write(testout_frame.to_bytes(length=8, byteorder="big")) - testin_frame = FrameGen.GenTest2InFrame( test_chip_coord, core_coord, self._fixed_core_star_coord ) @@ -131,13 +115,14 @@ def Get1GroupForNCoresWithNParams( "Test in frame #1/1: 0x%x in group #%d/%d" % (testin_frame, i + 1, N) ) - if self._work_dir: - self._fi.write(testin_frame.to_bytes(length=8, byteorder="big")) - - if self._work_dir: - self._fc.close() - self._fi.close() - self._fo.close() + if isinstance(work_dir, Path): + with open(work_dir / "config.bin", "wb") as fc, open( + work_dir / "testin.bin", "wb" + ) as fi, open(work_dir / "testout.bin", "wb") as fo: + for cf_frame, to_frame, ti_frame in zip(cf_list, to_list, ti_list): + fc.write(cf_frame.to_bytes(length=8, byteorder="big")) + fo.write(to_frame.to_bytes(length=8, byteorder="big")) + fi.write(ti_frame.to_bytes(length=8, byteorder="big")) return tuple(cf_list), tuple(ti_list), tuple(to_list) @@ -160,9 +145,9 @@ def Get1GroupForNCoresWith1Param( self._ensure_cores(N) if save_dir: - self._ensure_dir(save_dir) + work_dir = self._ensure_dir(save_dir) else: - self._work_dir = None + work_dir = None # 1. Get the test chip coordinate. test_chip_coord = self._direction.value + self._fixed_chip_coord @@ -182,11 +167,6 @@ def Get1GroupForNCoresWith1Param( ti_list: List[int] = [] to_list: List[int] = [] - if self._work_dir: - self._fc = open(self._work_dir / "config.bin", "wb") - self._fi = open(self._work_dir / "testin.bin", "wb") - self._fo = open(self._work_dir / "testout.bin", "wb") - for i in range(N): logger.info(f"Generating test group #{i+1}/{N}...") core_coord = core_coords[i] @@ -214,10 +194,6 @@ def Get1GroupForNCoresWith1Param( % (j + 1, testout_frame, i + 1, N) ) - if self._work_dir: - self._fc.write(config_frame.to_bytes(length=8, byteorder="big")) - self._fo.write(testout_frame.to_bytes(length=8, byteorder="big")) - testin_frame = FrameGen.GenTest2InFrame( test_chip_coord, core_coord, self._fixed_core_star_coord ) @@ -226,8 +202,14 @@ def Get1GroupForNCoresWith1Param( "Test in frame #1/1: 0x%x in group #%d/%d" % (testin_frame, i + 1, N) ) - if self._work_dir: - self._fi.write(testin_frame.to_bytes(length=8, byteorder="big")) + if isinstance(work_dir, Path): + with open(work_dir / "config.bin", "wb") as fc, open( + work_dir / "testin.bin", "wb" + ) as fi, open(work_dir / "testout.bin", "wb") as fo: + for cf_frame, to_frame, ti_frame in zip(cf_list, to_list, ti_list): + fc.write(cf_frame.to_bytes(length=8, byteorder="big")) + fo.write(to_frame.to_bytes(length=8, byteorder="big")) + fi.write(ti_frame.to_bytes(length=8, byteorder="big")) return tuple(cf_list), tuple(ti_list), tuple(to_list) @@ -250,9 +232,9 @@ def GetNGroupsFor1CoreWithNParams( self._ensure_cores(N) if save_dir: - self._ensure_dir(save_dir) + work_dir = self._ensure_dir(save_dir) else: - self._work_dir = None + work_dir = None # 1. Get the test chip coordinate. test_chip_coord = self._direction.value + self._fixed_chip_coord @@ -272,11 +254,6 @@ def GetNGroupsFor1CoreWithNParams( ti_list: List[int] = [] to_list: List[int] = [] - if self._work_dir: - self._fc = open(self._work_dir / "config.bin", "wb") - self._fi = open(self._work_dir / "testin.bin", "wb") - self._fo = open(self._work_dir / "testout.bin", "wb") - for i in range(N): logger.info(f"Generating test group #{i+1}/{N}...") param = params[i] @@ -304,10 +281,6 @@ def GetNGroupsFor1CoreWithNParams( % (j + 1, testout_frame, i + 1, N) ) - if self._work_dir: - self._fc.write(config_frame.to_bytes(length=8, byteorder="big")) - self._fo.write(testout_frame.to_bytes(length=8, byteorder="big")) - testin_frame = FrameGen.GenTest2InFrame( test_chip_coord, core_coord, self._fixed_core_star_coord ) @@ -316,8 +289,14 @@ def GetNGroupsFor1CoreWithNParams( "Test in frame #1/1: 0x%x in group #%d/%d" % (testin_frame, i + 1, N) ) - if self._work_dir: - self._fi.write(testin_frame.to_bytes(length=8, byteorder="big")) + if isinstance(work_dir, Path): + with open(work_dir / "config.bin", "wb") as fc, open( + work_dir / "testin.bin", "wb" + ) as fi, open(work_dir / "testout.bin", "wb") as fo: + for cf_frame, to_frame, ti_frame in zip(cf_list, to_list, ti_list): + fc.write(cf_frame.to_bytes(length=8, byteorder="big")) + fo.write(to_frame.to_bytes(length=8, byteorder="big")) + fi.write(ti_frame.to_bytes(length=8, byteorder="big")) return tuple(cf_list), tuple(ti_list), tuple(to_list) @@ -326,6 +305,12 @@ def ReplaceCoreCoord( frames: Union[int, List[int], Tuple[int, ...]], new_core_coord: Optional[Tuple[int, int]] = None, ) -> Union[int, Tuple[int, ...]]: + """ + Replace the core coordinate with the new one. + + - frames: of which the core coordinate you want to replace. It can be a single frame, or a list or tuple. + - new_core_coord: The new core coordinate. If not specified, it will generate one randomly. + """ if isinstance(frames, int): _frame = frames else: @@ -333,6 +318,7 @@ def ReplaceCoreCoord( if isinstance(new_core_coord, Tuple): _new_core_coord = Coord(new_core_coord) + self._ensure_coord(_new_core_coord) else: # Auto mask the old core coordinate then random pick one old_core_addr = ( @@ -467,8 +453,7 @@ def _ReplaceCoreCoordInNFrames( new_core_coord: Coord, ) -> Tuple[int, ...]: """ - Replace the core coordinate of frames with a specific or random one. - Indicate the core coordinate to specify it. Keep the parameters still. + Replace the core coordinate of frames with a specific or random one. Keep the parameters still. """ mask = FM.GENERAL_MASK & ( ~(FM.GENERAL_CORE_ADDR_MASK << FM.GENERAL_CORE_ADDR_OFFSET) @@ -476,8 +461,8 @@ def _ReplaceCoreCoordInNFrames( new_core_addr = Coord2Addr(new_core_coord) - for frame in frames: - frame = (frame & mask) | (new_core_addr << FM.GENERAL_CORE_ADDR_OFFSET) + for i, frame in enumerate(frames): + frames[i] = (frame & mask) | (new_core_addr << FM.GENERAL_CORE_ADDR_OFFSET) return tuple(frames) @@ -487,14 +472,14 @@ def _ReplaceHeader(self, frame: int, header: FST) -> int: return (frame & mask) | (header.value << FM.GENERAL_HEADER_OFFSET) - def _ensure_dir(self, user_dir: Union[str, Path]) -> None: + def _ensure_dir(self, user_dir: Union[str, Path]) -> Path: _user_dir: Path = Path(user_dir) if not _user_dir.exists(): logger.warning(f"Creating directory {_user_dir}...") _user_dir.mkdir(parents=True, exist_ok=True) - self._work_dir = _user_dir + return _user_dir def _ensure_cores(self, Ncores: int) -> None: if Ncores > 1024 - 16 or Ncores < 1: @@ -505,12 +490,18 @@ def _ensure_cores(self, Ncores: int) -> None: def _ensure_direction( self, direction: Literal["EAST", "SOUTH", "WEST", "NORTH"] ) -> None: - self._direction = Direction[direction.upper()] + try: + self._direction = Direction[direction.upper()] + except KeyError: + raise KeyError(f"{direction} is an illegal direction!") else: def _ensure_direction(self, direction: str) -> None: - self._direction = Direction[direction.upper()] + try: + self._direction = Direction[direction.upper()] + except KeyError: + raise KeyError(f"{direction} is an illegal direction!") def _ensure_coord(self, coord: Coord) -> None: if coord >= Coord(0b11100, 0b11100): From db72cb9da83b206ad3a70ca449c2383d369eac13 Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Sun, 16 Apr 2023 13:00:20 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=F0=9F=90=9B=20fix:=20frames=20saving=20i?= =?UTF-8?q?nto=20`.bin`=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paitest/paitest.py | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/paitest/paitest.py b/paitest/paitest.py index 6d309ae..d4c524f 100644 --- a/paitest/paitest.py +++ b/paitest/paitest.py @@ -36,7 +36,7 @@ def __init__( self._fixed_core_star_coord: Coord = Coord(0, 0) self._test_chip_coord: Coord - self._ensure_direction(direction) + self._ensure_direction(direction) # type: ignore def Get1GroupForNCoresWithNParams( self, @@ -116,13 +116,9 @@ def Get1GroupForNCoresWithNParams( ) if isinstance(work_dir, Path): - with open(work_dir / "config.bin", "wb") as fc, open( - work_dir / "testin.bin", "wb" - ) as fi, open(work_dir / "testout.bin", "wb") as fo: - for cf_frame, to_frame, ti_frame in zip(cf_list, to_list, ti_list): - fc.write(cf_frame.to_bytes(length=8, byteorder="big")) - fo.write(to_frame.to_bytes(length=8, byteorder="big")) - fi.write(ti_frame.to_bytes(length=8, byteorder="big")) + self.SaveFrames(work_dir / "config.bin", cf_list) + self.SaveFrames(work_dir / "testin.bin", ti_list) + self.SaveFrames(work_dir / "testout.bin", to_list) return tuple(cf_list), tuple(ti_list), tuple(to_list) @@ -203,13 +199,9 @@ def Get1GroupForNCoresWith1Param( ) if isinstance(work_dir, Path): - with open(work_dir / "config.bin", "wb") as fc, open( - work_dir / "testin.bin", "wb" - ) as fi, open(work_dir / "testout.bin", "wb") as fo: - for cf_frame, to_frame, ti_frame in zip(cf_list, to_list, ti_list): - fc.write(cf_frame.to_bytes(length=8, byteorder="big")) - fo.write(to_frame.to_bytes(length=8, byteorder="big")) - fi.write(ti_frame.to_bytes(length=8, byteorder="big")) + self.SaveFrames(work_dir / "config.bin", cf_list) + self.SaveFrames(work_dir / "testin.bin", ti_list) + self.SaveFrames(work_dir / "testout.bin", to_list) return tuple(cf_list), tuple(ti_list), tuple(to_list) @@ -290,13 +282,9 @@ def GetNGroupsFor1CoreWithNParams( ) if isinstance(work_dir, Path): - with open(work_dir / "config.bin", "wb") as fc, open( - work_dir / "testin.bin", "wb" - ) as fi, open(work_dir / "testout.bin", "wb") as fo: - for cf_frame, to_frame, ti_frame in zip(cf_list, to_list, ti_list): - fc.write(cf_frame.to_bytes(length=8, byteorder="big")) - fo.write(to_frame.to_bytes(length=8, byteorder="big")) - fi.write(ti_frame.to_bytes(length=8, byteorder="big")) + self.SaveFrames(work_dir / "config.bin", cf_list) + self.SaveFrames(work_dir / "testin.bin", ti_list) + self.SaveFrames(work_dir / "testout.bin", to_list) return tuple(cf_list), tuple(ti_list), tuple(to_list) From c2710c9e518efc303aade3397582e528c29c481d Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Mon, 17 Apr 2023 10:45:37 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=F0=9F=8E=A8=20enhancement:=20add=20`coor?= =?UTF-8?q?d.pyi`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paitest/frames/__init__.py | 4 +- paitest/frames/coord.py | 83 ++++++++++++++++++++++++++++++++++ paitest/frames/coord.pyi | 25 ++++++++++ paitest/frames/frame.py | 13 +++--- paitest/frames/frame_params.py | 74 +----------------------------- paitest/paitest.py | 5 +- paitest/paitest.pyi | 3 +- 7 files changed, 124 insertions(+), 83 deletions(-) create mode 100644 paitest/frames/coord.py create mode 100644 paitest/frames/coord.pyi diff --git a/paitest/frames/__init__.py b/paitest/frames/__init__.py index fb9b0da..6e1bda6 100644 --- a/paitest/frames/__init__.py +++ b/paitest/frames/__init__.py @@ -2,9 +2,9 @@ Addr2Coord as Addr2Coord, Coord2Addr as Coord2Addr, FrameGen as FrameGen, - Coord as Coord, Direction as Direction, FrameMask as FrameMask, FrameSubType as FrameSubType, - FrameDecoder as FrameDecoder + FrameDecoder as FrameDecoder, ) +from .coord import Coord as Coord diff --git a/paitest/frames/coord.py b/paitest/frames/coord.py new file mode 100644 index 0000000..7318ba8 --- /dev/null +++ b/paitest/frames/coord.py @@ -0,0 +1,83 @@ +from typing import Tuple, Union, Optional + + +class Coord: + """Coordinate class""" + + def __init__( + self, _x: Union[Tuple[int, int], int], _y: Optional[int] = None + ) -> None: + if isinstance(_x, Tuple): + x, y = _x[0], _x[1] + if isinstance(_y, int): + raise ValueError(f"Wrong Argument: {_y}") + elif isinstance(_x, int): + if isinstance(_y, int): + x, y = _x, _y + else: + raise ValueError("Missing Argument: y") + else: + raise ValueError("Wrong Argument") + + if not (0 <= x < 32 and 0 <= y < 32): + raise ValueError(f"0 <= x < 32, 0 <= y < 32: ({x}, {y})") + + self.x, self.y = x, y + + def __add__(self, other) -> "Coord": + return Coord(self.x + other.x, self.y + other.y) + + def __sub__(self, other) -> "CoordOffset": + return CoordOffset(self.x - other.x, self.y - other.y) + + def __eq__(self, other) -> bool: + if isinstance(other, Tuple): + return (self.x, self.y) == other + + return self.x == other.x and self.y == other.y + + def __ne__(self, other) -> bool: + return self.x != other.x or self.y != other.y + + def __lt__(self, other) -> bool: + """Whether on the left or below""" + return self.x < other.x or self.y < other.y + + def __gt__(self, other) -> bool: + """Whether on the right and above""" + return ( + (self.x > other.x and self.y > other.y) + or (self.x == other.x and self.y > other.y) + or (self.x > other.x and self.y == other.y) + ) + + def __le__(self, other) -> bool: + return self.__lt__(other) or self.__eq__(other) + + def __ge__(self, other) -> bool: + return self.__gt__(other) or self.__eq__(other) + + def __str__(self) -> str: + return f"({self.x}, {self.y})" + + +class CoordOffset(Coord): + """Coordinate offset class""" + + def __init__(self, _x: int, _y: int) -> None: + if not (-32 < _x < 32 and -32 < _y < 32): + raise ValueError(f"-32 < x < 32, -32 < y < 32: ({_x}, {_y})") + + self.x, self.y = _x, _y + + def __add__(self, other): + if isinstance(other, CoordOffset): + return CoordOffset(self.x + other.x, self.y + other.y) + else: + return Coord(self.x + other.x, self.y + other.y) + + def __sub__(self, other) -> "CoordOffset": + if isinstance(other, Coord): + raise TypeError("A CoordOffset cannot substract a Coord") + + return CoordOffset(self.x - other.x, self.y - other.y) diff --git a/paitest/frames/coord.pyi b/paitest/frames/coord.pyi new file mode 100644 index 0000000..7f7f348 --- /dev/null +++ b/paitest/frames/coord.pyi @@ -0,0 +1,25 @@ +from typing import overload, Tuple + +class Coord: + x: int = ... + y: int = ... + @overload + def __init__(self, _x: Tuple[int, int]) -> None: ... + @overload + def __init__(self, _x: int, _y: int) -> None: ... + def __add__(self, other) -> Coord: ... + def __sub__(self, other) -> CoordOffset: ... + def __eq__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... + def __lt__(self, other) -> bool: ... + def __gt__(self, other) -> bool: ... + def __le__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... + def __str__(self) -> str: ... + + __repr__ = __str__ + +class CoordOffset(Coord): + def __init__(self, _x: int, _y: int) -> None: ... + def __add__(self, other) -> CoordOffset | Coord: ... + def __sub__(self, other) -> CoordOffset: ... diff --git a/paitest/frames/frame.py b/paitest/frames/frame.py index 38ec4a5..7d21c89 100644 --- a/paitest/frames/frame.py +++ b/paitest/frames/frame.py @@ -5,6 +5,7 @@ ConfigFrameMask as CFM, ) from .frame_params import * +from .coord import Coord from typing import List, Tuple, Union, Dict, Optional, Any import random @@ -243,7 +244,7 @@ def _get_subtype(self) -> FST: self._frame >> FM.GENERAL_HEADER_OFFSET ) & FM.GENERAL_HEADER_MASK try: - _subtype = FrameSubType(_header) + _subtype = FST(_header) return _subtype except: raise TypeError(f"Frame header {_header} is illigal!") @@ -314,22 +315,22 @@ def _decode(self) -> None: self._info(subtype) - def _decode_config1(self): + def _decode_config1(self) -> None: pass def _decode_config2(self) -> None: self._param_reg_parse() - def _decode_testout1(self): + def _decode_testout1(self) -> None: pass - def _decode_testout2(self): + def _decode_testout2(self) -> None: pass - def _decode_testin1(self): + def _decode_testin1(self) -> None: pass - def _decode_testin2(self): + def _decode_testin2(self) -> None: pass def _info(self, subtype: FST) -> None: diff --git a/paitest/frames/frame_params.py b/paitest/frames/frame_params.py index 8ce71dc..a7b09fa 100644 --- a/paitest/frames/frame_params.py +++ b/paitest/frames/frame_params.py @@ -1,5 +1,5 @@ from enum import Flag, Enum, unique -from typing import Tuple, Union, Optional +from .coord import CoordOffset @unique @@ -196,78 +196,6 @@ class SpikeWidthType(Enum): SPIKE_WIDTH_8BIT = 1 -class Coord: - """Coordinate class""" - - def __init__(self, _x: Union[Tuple[int, int], int], _y: Optional[int] = None): - if isinstance(_x, Tuple): - x, y = _x[0], _x[1] - elif isinstance(_y, int): - x, y = _x, _y - else: - raise ValueError("Coordinate Y is missing!") - - if not (0 <= x < 32 and 0 <= y < 32): - raise ValueError(f"0 <= x < 32, 0 <= y < 32: ({x}, {y})") - - self.x, self.y = x, y - - def __add__(self, other): - return Coord(self.x + other.x, self.y + other.y) - - def __sub__(self, other): - return CoordOffset(self.x - other.x, self.y - other.y) - - def __eq__(self, other) -> bool: - return self.x == other.x and self.y == other.y - - def __ne__(self, other) -> bool: - return self.x != other.x or self.y != other.y - - def __lt__(self, other) -> bool: - """Whether on the left or below""" - return self.x < other.x or self.y < other.y - - def __gt__(self, other) -> bool: - """Whether on the right and above""" - return ( - (self.x > other.x and self.y > other.y) - or (self.x == other.x and self.y > other.y) - or (self.x > other.x and self.y == other.y) - ) - - def __le__(self, other) -> bool: - return self.__lt__(other) or self.__eq__(other) - - def __ge__(self, other) -> bool: - return self.__gt__(other) or self.__eq__(other) - - def __str__(self) -> str: - return f"({self.x}, {self.y})" - - __repr__ = __str__ - - -class CoordOffset(Coord): - def __init__(self, _x: int, _y: int): - if not (-32 < _x < 32 and -32 < _y < 32): - raise ValueError(f"-32 < x < 32, -32 < y < 32: ({_x}, {_y})") - - self.x, self.y = _x, _y - - def __add__(self, other): - if isinstance(other, CoordOffset): - return CoordOffset(self.x + other.x, self.y + other.y) - else: - return Coord(self.x + other.x, self.y + other.y) - - def __sub__(self, other): - if isinstance(other, Coord): - raise TypeError("A CoordOffset cannot substract a Coord") - - return CoordOffset(self.x - other.x, self.y - other.y) - - @unique class Direction(Enum): """ diff --git a/paitest/paitest.py b/paitest/paitest.py index d4c524f..06c26bf 100644 --- a/paitest/paitest.py +++ b/paitest/paitest.py @@ -291,7 +291,7 @@ def GetNGroupsFor1CoreWithNParams( def ReplaceCoreCoord( self, frames: Union[int, List[int], Tuple[int, ...]], - new_core_coord: Optional[Tuple[int, int]] = None, + new_core_coord: Optional[Union[Tuple[int, int], Coord]] = None, ) -> Union[int, Tuple[int, ...]]: """ Replace the core coordinate with the new one. @@ -307,6 +307,9 @@ def ReplaceCoreCoord( if isinstance(new_core_coord, Tuple): _new_core_coord = Coord(new_core_coord) self._ensure_coord(_new_core_coord) + elif isinstance(new_core_coord, Coord): + _new_core_coord = new_core_coord + self._ensure_coord(_new_core_coord) else: # Auto mask the old core coordinate then random pick one old_core_addr = ( diff --git a/paitest/paitest.pyi b/paitest/paitest.pyi index bc08623..13d1d8d 100644 --- a/paitest/paitest.pyi +++ b/paitest/paitest.pyi @@ -1,5 +1,6 @@ from typing import Tuple, List, Optional, Union, overload import sys + if sys.version_info >= (3, 8): from typing import Literal from pathlib import Path @@ -17,7 +18,7 @@ class paitest: direction: str = "EAST", fixed_chip_coord: Tuple[int, int] = (0, 0), ) -> None: ... - + def Get1GroupForNCoresWithNParams( self, N: int, From 1c08055bfdf08bb0639e69e597d5a59edbf69f4b Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Mon, 17 Apr 2023 10:46:03 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=F0=9F=9A=80=20enhancement:=20add=20examp?= =?UTF-8?q?les?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 example.py diff --git a/example.py b/example.py new file mode 100644 index 0000000..4625d10 --- /dev/null +++ b/example.py @@ -0,0 +1,43 @@ +from paitest import paitest +from paitest.frames import FrameDecoder + + +if __name__ == "__main__": + """Here are simple exmaples""" + + # Path to store the config, test input and output frames + save_path = "./test" + + # N groups + groups = 1 + + # PAITest instance + PAITestManager = paitest("EAST") + + # 1. Generate 1 group for N cores with N parameters reg. + a_cf, a_ti, a_to = PAITestManager.Get1GroupForNCoresWithNParams( + 3, save_dir="./test" + ) + print(a_cf, a_ti, a_to) + + # 2. Generate 1 group for N cores with the same 1 parameter reg. + a_cf, a_ti, a_to = PAITestManager.Get1GroupForNCoresWith1Param(1, save_dir="./test") + print(a_cf, a_ti, a_to) + + # 3. Generate N groups for 1 core with N parameters reg. + a_cf, a_fi, a_fo = PAITestManager.GetNGroupsFor1CoreWithNParams( + 3, save_dir="./test1" + ) + + # 3. Replace the core coordinate with (9, 9) then save in test/config_r.bin + a_cf_replaced = PAITestManager.ReplaceCoreCoord(a_cf[:3], (9, 9)) + PAITestManager.SaveFrames("./test/config_r.bin", a_cf_replaced) + print(f"a_cf_replaced: {a_cf_replaced}") + + # Then, decode the replaced frames to check whether the replacement is OK + decoder = FrameDecoder() + attr = decoder.decode(a_cf_replaced) + + replaced_coord = attr.get("core_coord") + if replaced_coord == (9, 9): + print("Replacement OK") From 670aa9450cf6b24a0da06d49c3f2a310453e3d4c Mon Sep 17 00:00:00 2001 From: KafCoppelia Date: Mon, 17 Apr 2023 10:46:09 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=F0=9F=94=96=20v0.0.11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 77 +++++++++++++++++++++++++++++++++----------------- poetry.lock | 60 ++------------------------------------- pyproject.toml | 6 +--- 3 files changed, 55 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 83890da..c42acfd 100644 --- a/README.md +++ b/README.md @@ -6,41 +6,66 @@ ## 📦 版本 -[v0.0.10 Prerelease](https://github.com/PAICookers/PAITest/releases/tag/v0.0.10) +[v0.0.11 Prerelease](https://github.com/PAICookers/PAITest/releases/tag/v0.0.11) -## 🛠️ 使用 +## 🛠️ 使用生成 -生成配置帧及对应测试输入帧,以实现硬件通路的简单测试,后续将芯片实际测试输出帧与预期结果进行对比即可。由于配置帧/测试帧I型需要配合UART配置使用,因此目前仅采用**配置/测试帧II型**方案,且 `chip_addr` 与 `core*_addr` 均固定为 `(0, 0)`。 +配置帧及对应测试输入帧,以实现硬件通路的简单测试,后续将芯片实际测试输出帧与预期结果进行对比即可。 -```python -from paitest import paitest +⚠️ 由于配置帧/测试帧I型需要配合串口配置使用,因此目前仅采用**配置/测试帧II型**方案,且 `CHIP_ADDR` 与 `CORE*_ADDR` 均固定为 `(0, 0)`。 -'''Path to store the config & test frames''' -save_path = Path.cwd() / "test" -'''N groups''' -groups = 1 -'''PAITest instance''' -PAITestManager = paitest("EAST") +1. 实例化 `PAITest` -# Random test 'groups' cores with 'groups' different parameters -paitest.GetRandomCasesForNCores(groups, save_path) + ```python + from paitest import paitest -# Random test 10 cores but don't use core (6, 6) -config_frames, testin_frames, testout_frames = \ - PAITestManager.Get1CaseForNCores(10, save_dir=save_path, masked_core_coord=(6, 6)) + # Define the direction of test chip + PAITestManager = paitest("EAST") + ``` -# Save frames in .bin file -PAITestManager.SaveFrames("./test/config_1.bin", config_frames) -``` +2. `Get1GroupForNCoresWithNParams`,产生一组针对 `N` 个核的配置-测试帧,每个核配置不同参数。可以指定单个需要**屏蔽**的核坐标 -生成的 `N` 组配置帧II型、测试输入帧II型及参考测试输出帧II型在 `save_path` 下: + ```python + groups = 10 # Generate 10 groups + save_to_dir="./test" # Save frames into ./test directory -```python -save_path -├ config.bin -├ testin.bin -└ testout.bin -``` + # Generate configuration frames, testin & testout frames + cf, ti, to = PAITestManager.Get1GroupForNCoresWithNParams(groups, save_dir=save_to_dir) + + # Mask a cord coordinate so that avoid generating the same coordinate. + cf, ti, to = PAITestManager.Get1GroupForNCoresWithNParams(groups, + save_dir=save_to_dir, masked_core_coord=(12, 16)) + ``` + +3. `Get1GroupForNCoresWith1Param`,产生1组针对 `N` 个核的配置-测试帧,每个核配置相同参数。可以指定单个需要**屏蔽**的核坐标 + + ```python + # Same as Get1GroupForNCoresWithNParams + cf, ti, to = PAITestManager.Get1GroupForNCoresWith1Param(10, save_dir="./test") + ``` + +4. `GetNGroupsFor1CoreWithNParams`,产生 `N` 组针对1个核的配置-测试帧,每个核配置不同参数。可以指定单个需要**屏蔽**的核坐标 + + ```python + # Same as Get1GroupForNCoresWithNParams + cf, ti, to = PAITestManager.GetNGroupsFor1CoreWithNParams(1, save_dir="./test") + ``` + +5. `ReplaceCoreCoord`,替换单个或**一组**帧中的 `CORE_ADDR` 为指定坐标。 + + ```python + # Replaced core coordinate with (9, 9) + replaced = PAITestManager.ReplaceCoreCoord(original_frames, (9, 9)) + ``` + + ⚠️ 一组指一组完整的配置帧,包含3帧。对于测试输入帧,即为单帧。 + +6. `SaveFrames`,保存帧数据至 `.bin` 文件 + + ```python + # Save into ./test/config.bin + PAITestManager.SaveFrames("./test/config.bin", replaced) + ``` ## 🗓️ TODO diff --git a/poetry.lock b/poetry.lock index 61f4819..f5a6bc6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,61 +1,7 @@ # This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. - -[[package]] -name = "autopep8" -version = "2.0.2" -description = "A tool that automatically formats Python code to conform to the PEP 8 style guide" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "autopep8-2.0.2-py2.py3-none-any.whl", hash = "sha256:86e9303b5e5c8160872b2f5ef611161b2893e9bfe8ccc7e2f76385947d57a2f1"}, - {file = "autopep8-2.0.2.tar.gz", hash = "sha256:f9849cdd62108cb739dbcdbfb7fdcc9a30d1b63c4cc3e1c1f893b5360941b61c"}, -] - -[package.dependencies] -pycodestyle = ">=2.10.0" -tomli = {version = "*", markers = "python_version < \"3.11\""} - -[package.source] -type = "legacy" -url = "https://pypi.tuna.tsinghua.edu.cn/simple" -reference = "tsinghua" - -[[package]] -name = "pycodestyle" -version = "2.10.0" -description = "Python style guide checker" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"}, - {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"}, -] - -[package.source] -type = "legacy" -url = "https://pypi.tuna.tsinghua.edu.cn/simple" -reference = "tsinghua" - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[package.source] -type = "legacy" -url = "https://pypi.tuna.tsinghua.edu.cn/simple" -reference = "tsinghua" +package = [] [metadata] lock-version = "2.0" -python-versions = "^3.8" -content-hash = "008198bc4ef082f43b4b6dc4ac1f372b61d357da5234803ca2936d43264003a6" +python-versions = "^3.6" +content-hash = "9a9f29c88735611eb476259f44cf1e4f8afa55ee41f4f8bde2845f685545eef5" diff --git a/pyproject.toml b/pyproject.toml index 42a803c..8a0a913 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "PAITest" -version = "0.0.10" +version = "0.0.11" description = "Test module for PAICORE 2.0" authors = ["KafCoppelia "] license = "AGPL v3.0" @@ -14,10 +14,6 @@ include = ["./paitest"] [tool.poetry.dependencies] python = "^3.6" -[tool.poetry.group.dev.dependencies] -autopep8 = "^2.0.2" - - [[tool.poetry.source]] name = "tsinghua" url = "https://pypi.tuna.tsinghua.edu.cn/simple"