python pandas + named_bitfield => карта памяти для встроенной системы - PullRequest
1 голос
/ 24 февраля 2020
  1. Pandas обладает большой гибкостью для обработки больших данных.
  2. Named_bitfield (https://github.com/not-napoleon/named_bitfield/blob/master/named_bitfield.py) имеет возможность обрабатывать поля уровня битов.

Объединение Pandas с named_bitfield создает мощное решение для карты памяти некоторых встроенных систем. Например, Raspberry Pi 4 / Nvidia JETSON TX2 может иметь 4 ГБ памяти и может использовать эту функцию для связи с ИС с большой гибкостью. Приведенный ниже код демонстрирует способ объединения полей Pandas и named_bit для создания тестовой карты памяти из файла csv.

import pandas as pd
from io import StringIO
import ast
from functools import partial
from named_bitfield import named_bitfield

# define register offset as regOffset, name as regName, bit fields ad regFields
# define register default value as regDefault, mode as regMode, description as regDescription
memorymapFile = '''
regOffset,regName,regFields,regDefault,regMode,regDescription
0,test_regin1,"('bit7_4', 4), ('bit3_2', 2), ('bit1_0',2)",0x0,R/W,Test input register 1
1,test_regin2,"('bit7_1',7), ('bit_0',0)",0x0,R/W,Test input register 2
'''

def _bitFields(bitFields, value, bitwidth):
    """ format the regFields content to be used in the named_bitbitFields
        :param bitFields: the coloumn in the regMap contains the bit bitFields definition
        :param value: the default value for this register
        :param bitwidth: 8/16/32 bits in a register if bitFields is empty,
        :return named_bitbitFields with the default value
    """
    if pd.isna(bitFields):
        bitFields = [('rsvd', bitwidth)]
    else:
        bitFields = ast.literal_eval(bitFields)   # convert string to list
    namedbf = named_bitfield('nbf', bitFields, mutable=True)
    return pd.Series(namedbf.fromint(value))

def readRegMapFile(csvfile, index_col='regName', reg_bitFields='regFields', reg_default='regDefault', bitwidth=8):
    regPd = pd.read_csv(csvfile, index_col=index_col, converters={reg_default: partial(int, base=16)})
    regPd['content'] = regPd.apply(lambda x: _bitFields(bitFields=x[reg_bitFields],
                                                        value=x[reg_default], bitwidth=bitwidth), axis=1)
    return regPd

if __name__ == '__main__':
    baseAddr = 0   # memory map defines offset, assume baseAddr is 0
    testMemMapPd = (readRegMapFile(StringIO(memorymapFile)).assign(regAddr = lambda x: x['regOffset'] + baseAddr))
    for column in testMemMapPd.columns:    # print all the properties associated with a register
        print(f"{column}: {testMemMapPd.loc['test_regin1', column]}")
    # use register name as index to address each register
    testMemMapPd.loc['test_regin1', 'content'].bit7_4 = 0xF     # assigned 15 to bit7_4
    print(testMemMapPd.loc['test_regin1'].content)              # print 240
    testMemMapPd.loc['test_regin1', 'content'].bit1_0 = 0x3     # assigned 3 to bit1_0
    print(testMemMapPd.loc['test_regin1'].content)              # print 243
    testMemMapPd.loc['test_regin1', 'content'] = testMemMapPd.loc['test_regin1'].content.fromint(155)
    print(testMemMapPd.loc['test_regin1'].content)              # print 155, 0x9B, 10011011
    print(testMemMapPd.loc['test_regin1'].content.bit7_4)       # print 9
    print(testMemMapPd.loc['test_regin1'].content.bit3_2)       # print 2
    print(testMemMapPd.loc['test_regin1'].content.bit1_0)       # print 3
...