tableMapping

List of all pip packages imported

  1"""
  2List of all pip packages imported
  3"""
  4
  5import difflib
  6import itertools
  7import json
  8import logging
  9import os
 10import re
 11import sys
 12
 13import jellyfish
 14import numpy as np
 15import pandas as pd
 16import yaml
 17from tabulate import tabulate
 18
 19# ===========================================================================================
 20# ======================================= Begin Class =======================================
 21# ===========================================================================================
 22
 23
 24class TableMapping:
 25    """
 26    Generates a golden model for a particular SRAM memory table map config
 27    using a respective TCAM memory table map and configs.
 28    """
 29
 30    # * ----------------------------------------------------------------- Variables
 31    def __init__(self):
 32        """
 33        Constructor: Initializes all the class variables
 34
 35        **Public Variables:**
 36        :param str prjWorkDir:                  current project working dir
 37        :param str sramTableDir:                abs path of SRAM table map folder
 38        :param str tcamTableConfigsFilePath:    abs path of TCAM table map config file
 39        :param str tcamTableConfigsFileName:    TCAM table map config file name
 40        :param str tcamTableXlsxFilePath:       abs path of TCAM table map XLSX file
 41        :param str tcamTableXlsxFileName:       TCAM table map XLSX file name
 42        :param str sramTableXlsxFilePath:       abs path of generated SRAM table map XLSX file
 43        :param str sramTableXlsxFileName:       SRAM table map XLSX file name
 44        :param str sramTableHtmlFilePath:       abs path of generated SRAM table map HTML file
 45        :param str sramTableHtmlFileName:       SRAM table map HTML file name
 46        :param str sramTableJsonFilePath:       abs path of generated SRAM table map JSON file
 47        :param str sramTableJsonFileName:       SRAM table map JSON file name
 48        :param str sramTableTxtFilePath:        abs path of generated SRAM table map TXT file
 49        :param str sramTableTxtFileName:        SRAM table map TXT file name
 50
 51        **Protected Variables:**
 52        :param dict _tcamTableConfigs:      TCAM table map configs
 53        :param DataFrame _tcamTable:        TCAM table map
 54        :param DataFrame _sramTable:        SRAM table map
 55        :param DataFrame _tcamQSAddrTable:  TCAM table map query addr sub str
 56        :param DataFrame _sramQSAddrTable:  SRAM table map query addr sub str
 57
 58        **Private Variables:**
 59        :param int __tcamQueryStrLen:   `queryStrLen` of a particular TCAM table config
 60        :param int __tcamSubStrLen:     `subStrLen` of a particular TCAM table config
 61        :param int __tcamTotalSubStr:   `totalSubStr` of a particular TCAM table config
 62        :param int __tcamPotMatchAddr:  `potMatchAddr` of a particular TCAM table config
 63        :param int __sramTableRows:     SRAM table map row count
 64        :param int __sramTableCols:     SRAM table map col count
 65        :param list __tcamRows:         TCAM table map row count vector
 66        :param list __tcamCols:         TCAM table map col count vector
 67        :param list __tcamColVec:       TCAM table map sub string address col count vector
 68        :param list __sramRows:         SRAM table map row count vector
 69        :param list __sramRowVec:       SRAM table map sub string address row count vector
 70        :param list __sramCols:         SRAM table map col count vector
 71        """
 72        # * ------------------- public vars
 73        self.prjWorkDir = ""
 74        self.sramTableDir = ""
 75        self.tcamTableConfigsFilePath = ""
 76        self.tcamTableConfigsFileName = ""
 77        self.tcamTableXlsxFilePath = ""
 78        self.tcamTableXlsxFileName = ""
 79        self.sramTableXlsxFilePath = ""
 80        self.sramTableXlsxFileName = ""
 81        self.sramTableHtmlFilePath = ""
 82        self.sramTableHtmlFileName = ""
 83        self.sramTableJsonFilePath = ""
 84        self.sramTableJsonFileName = ""
 85        self.sramTableTxtFilePath = ""
 86        self.sramTableTxtFileName = ""
 87        # * ------------------- protected vars
 88        self._tcamTableConfigs = {}
 89        self._tcamTable = pd.DataFrame
 90        self._sramTable = pd.DataFrame
 91        self._tcamQSAddrTable = pd.DataFrame
 92        self._sramQSAddrTable = pd.DataFrame
 93        # * ------------------- private vars
 94        self.__tcamQueryStrLen = 0
 95        self.__tcamSubStrLen = 0
 96        self.__tcamTotalSubStr = 0
 97        self.__tcamPotMatchAddr = 0
 98        self.__sramTableRows = 0
 99        self.__sramTableCols = 0
100        self.__tcamRows = []
101        self.__tcamCols = []
102        self.__tcamColVec = []
103        self.__sramRows = []
104        self.__sramRowVec = []
105        self.__sramCols = []
106        # * logging config
107        logging.basicConfig(
108            level=logging.DEBUG,
109            filename="./logs/tableMapping.log",
110            format="%(asctime)s | %(filename)s | %(funcName)s | %(levelname)s | %(lineno)d | %(message)s",
111        )
112
113    # * ----------------------------------------------------------------- Functions
114    def getPrjDir(self, verbose):
115        """
116        Obtain the absolute path of the current working directory.
117
118        :param int verbose: print information in verbose mode.
119        :return str: absolute path of the current project working directory.
120        """
121        self.prjWorkDir = os.getcwd()
122        logging.info("Project working dir: %s", self.prjWorkDir)
123        printVerbose(verbose, f"Project working dir: {self.prjWorkDir}")
124        return self.prjWorkDir
125
126    def getYAMLFilePath(self, verbose):
127        """
128        Obtain the absolute path of file tcamTables.yaml.
129
130        :param int verbose: print information in verbose mode.
131        :return str: absolute path of the current project working directory.
132        """
133        # * get tcamTables config file path
134        tempPath = os.path.join(self.prjWorkDir, "compiler/configs/tcamTables.yaml")
135        if os.path.isfile(tempPath) is True:
136            self.tcamTableConfigsFilePath = tempPath
137            self.tcamTableConfigsFileName = os.path.basename(tempPath)
138            logging.info('"FOUND": TCAM table config file path: %s', self.tcamTableConfigsFilePath)
139            printVerbose(verbose, f'"FOUND": TCAM table config file path: {self.tcamTableConfigsFilePath}')
140            return self.tcamTableConfigsFilePath
141        logging.error('"NOT FOUND": TCAM table config file path: %s', self.tcamTableConfigsFilePath)
142        sys.exit(f'"NOT FOUND": TCAM table config file path: {self.tcamTableConfigsFilePath}')
143
144    def readYAML(self, filePath, verbose):
145        """
146        Read a particular YAML config file
147
148        :param str filePath: absolute path of file tcamTables.yaml.
149        :param int verbose: print information in verbose mode.
150        :return dict: dictionary containing all the TCAM table configs.
151        """
152        with open(filePath, encoding="utf-8") as file:
153            self._tcamTableConfigs = yaml.full_load(file)
154        # print(json.dumps(self._tcamTableConfigs,indent=4))
155        # print(yaml.dump(self._tcamTableConfigs,sort_keys=False,default_flow_style=False))
156        logging.info("Read TCAM table config file: %s", self.tcamTableConfigsFilePath)
157        printVerbose(verbose, f"Read TCAM table config file: {self.tcamTableConfigsFilePath}")
158        return self._tcamTableConfigs
159
160    def printYAML(self, debug):
161        """
162        Print all present configs of a YAML file either in JSON or YAML style.
163
164        :param int debug: print information in debug mode.
165        """
166        printDebug(debug, "Printing TCAM table configs")
167        print(json.dumps(self._tcamTableConfigs, indent=4))
168        # print(yaml.dump(self._tcamTableConfigs,sort_keys=False,default_flow_style=False))
169        logging.info("Printed TCAM table configs")
170
171    def getTCAMConfig(self, tcamConfig):
172        """
173        Check if a particular tcamTable config exists in file tcamTables.yaml. If found store the config params in vars.
174        - **__tcamQueryStrLen:**    saves `queryStrLen`
175        - **__tcamSubStrLen:**      saves `subStrLen`
176        - **__tcamTotalSubStr:**    saves `totalSubStr`
177        - **__tcamPotMatchAddr:**   saves `potMatchAddr`
178
179        :param str tcamConfig: TCAM table config name e.g. tcamTableX
180        :return dict: dictionary containing the respective table map config.
181        """
182        # * look for specific tcam config in compiler/configs/tcamTables.yaml
183        if tcamConfig in self._tcamTableConfigs.keys():
184            tempConfig = self._tcamTableConfigs[tcamConfig]
185            # * save tcam config vars
186            self.__tcamQueryStrLen = tempConfig["queryStrLen"]
187            self.__tcamSubStrLen = tempConfig["subStrLen"]
188            self.__tcamTotalSubStr = tempConfig["totalSubStr"]
189            self.__tcamPotMatchAddr = tempConfig["potMatchAddr"]
190            # * print specific tcam config
191            # print(type(tempConfig))
192            logging.info('"FOUND" Required TCAM Config [%s]', tcamConfig)
193            print('"FOUND" Required TCAM Config [%s]', tcamConfig)
194            logging.info("TCAM Config Data [%s] = %s", tcamConfig, tempConfig)
195            return tempConfig
196        logging.error('"NOT FOUND": TCAM Config [%s]', tcamConfig)
197        sys.exit(f'"NOT FOUND": Required TCAM table config [{tcamConfig}]')
198
199    def getTCAMTableFilePath(self, tcamConfig, verbose):
200        """
201        Obtain the absolute path of file **tcamTableX.xlsx** which represents the TCAM memory table map.
202
203        :param str tcamConfig: TCAM table config name e.g. tcamTableX
204        :param int verbose: print information in verbose mode.
205        :return str: absolute path of the TCAM table mapping file.
206        """
207        # * find the specific tcam table map in compiler/lib/
208        tempPath = os.path.join(self.prjWorkDir, "compiler/lib/" + tcamConfig + ".xlsx")
209        if os.path.isfile(tempPath) is True:
210            self.tcamTableXlsxFilePath = tempPath
211            self.tcamTableXlsxFileName = os.path.basename(tempPath)
212            logging.info('"FOUND" TCAM table map XLSX file path: %s', self.tcamTableXlsxFilePath)
213            printVerbose(verbose, f'"FOUND" TCAM table map XLSX file path: {self.tcamTableXlsxFilePath}')
214            return self.tcamTableXlsxFilePath
215        logging.error('"NOT FOUND": TCAM table map XLSX file path: %s', self.tcamTableXlsxFilePath)
216        sys.exit(f'"NOT FOUND": TCAM table map XLSX file path {self.tcamTableXlsxFilePath}')
217
218    def printDF(self, dataFrame, heading):
219        """
220        Display the contents of a particular data frame.
221
222        :param DataFrame dataFrame: particular data frame object.
223        :param str heading: Title above data frame.
224        """
225        print("\n")
226        print("Printing dataframe: %s", heading)
227        print(tabulate(dataFrame, headers="keys", showindex=True, disable_numparse=True, tablefmt="github"), "\n")
228        logging.info("Printing dataframe: %s", str(heading))
229
230    def getTcamTableMap(self):
231        """
232        Getter function for the TCAM table map
233
234        :return DataFrame: TCAM table map dataframe object
235        """
236        return self._tcamTable
237
238    def getSramTableMap(self):
239        """
240        Getter function for the SRAM table map
241
242        :return DataFrame: SRAM table map dataframe object
243        """
244        return self._sramTable
245
246    def readTCAMTable(self, verbose):
247        """
248        Read the contents of a **tcamTableX.xlsx** TCAM memory table map as a data frame.
249
250        :param int verbose: print information in verbose mode.
251        :return int: list containing dimensions of TCAM table memory map.
252        """
253        # * store tcam table in dataframe
254        self._tcamTable = pd.read_excel(self.tcamTableXlsxFilePath, skiprows=2, index_col=None, engine="openpyxl")
255        # * get num of rows and col from tcam table
256        tcamTableRows = self._tcamTable.shape[0]
257        tcamTableCols = self._tcamTable.shape[1]
258        # * compare row/col of tcam table with respective yaml config
259        if tcamTableRows == self.__tcamPotMatchAddr and tcamTableCols - 1 == self.__tcamQueryStrLen:
260            logging.info('"MATCH FOUND": TCAM table map rows == TCAM table YAML config potMatchAddr')
261            printVerbose(verbose, '"MATCH FOUND": TCAM table map rows == TCAM table YAML config potMatchAddr')
262            logging.info('"MATCH FOUND": TCAM table map cols == TCAM table YAML config queryStrLen')
263            printVerbose(verbose, '"MATCH FOUND": TCAM table map cols == TCAM table YAML config queryStrLen')
264            return [tcamTableRows, tcamTableCols]
265        logging.error('"MATCH NOT FOUND": TCAM table map rows != TCAM table YAML config potMatchAddr')
266        logging.error('"MATCH NOT FOUND": TCAM table map cols != TCAM table YAML config queryStrLen')
267        sys.exit('"MATCH NOT FOUND": MISMATCH in TCAM table map and YAML config rows/cols')
268
269    def getSRAMTableDim(self, verbose):
270        """
271        Generate the dimensions of the SRAM table map data frame using TCAM table map configs.
272
273        :param int verbose: print information in verbose mode.
274        :return int: list containing dimensions of SRAM table memory map.
275        """
276        self.__sramTableRows = self.__tcamTotalSubStr * pow(2, self.__tcamSubStrLen)
277        self.__sramTableCols = self.__tcamPotMatchAddr
278        logging.info("SRAM table rows [{%4d}] cols [{%4d}]", self.__sramTableRows, self.__sramTableCols)
279        printVerbose(verbose, f"SRAM table rows [{self.__sramTableRows}] cols [{self.__sramTableCols}]")
280        return [self.__sramTableRows, self.__sramTableCols]
281
282    def genSRAMTable(self, verbose):
283        """
284        Create an empty SRAM table map data frame containing respective row addresses and column headings.
285
286        :param int verbose: print information in verbose mode.
287        """
288        # * create temp vars
289        sramTableAddrList = []
290        sramColHeadings = []
291        # * create row address
292        for i in range(self.__tcamTotalSubStr):
293            for j in range(2**self.__tcamSubStrLen):
294                padding = "0" + str(self.__tcamSubStrLen) + "b"
295                # sramTableAddrList.append(format(j, '#012b'))  # with 0b prefix
296                sramTableAddrList.append(format(j, padding))  # without 0b prefix
297            logging.info("Created [{%4d}] SRAM addresses from search query [{%4d}]", j + 1, i)
298            printVerbose(verbose, f"Created [{j+1}] SRAM addresses from search query [{i}]")
299        # * create col headings
300        for k in reversed(range(self.__tcamPotMatchAddr)):
301            heading = "D" + str(k)
302            sramColHeadings.append(heading)
303            logging.info("Created column heading %s", heading)
304        # * gen empty m*n sram table
305        self._sramTable = pd.DataFrame(index=np.arange(self.__sramTableRows), columns=np.arange(self.__sramTableCols))
306        # * rename column headings
307        self._sramTable.columns = sramColHeadings
308        # * insert addr col at position 0
309        self._sramTable.insert(0, "Addresses", sramTableAddrList, allow_duplicates=True)
310        logging.info("Created empty [%d x %d] SRAM table", self._sramTable.shape[0], self._sramTable.shape[1])
311        printVerbose(verbose, f"Created empty [{self._sramTable.shape[0]} x {self._sramTable.shape[1]}] SRAM table")
312
313    def createSRAMTableDir(self, verbose):
314        """
315        Create a directory to store SRAM table maps in various formats.
316
317        :param int verbose: print information in verbose mode.
318        :return str: absolute path of the SRAM table map directory.
319        """
320        # * create sramTables dir if it doesn't exist
321        self.sramTableDir = os.path.join(self.prjWorkDir, "sramTables")
322        if os.path.exists(self.sramTableDir) is False:
323            os.makedirs("sramTables")
324            logging.info("Created sramTables dir: %s", self.sramTableDir)
325            printVerbose(verbose, f"Created sramTables dir: {self.sramTableDir}")
326        return self.sramTableDir
327
328    def splitRowsAndCols(self, debug):
329        """
330        Create TCAM and SRAM table map row and column vectors based on TCAM table config parameters.
331
332        :param int debug: print information in debug mode.
333        :return list: list containing TCAM and SRAM row and column vectors.
334        """
335        # * store tcam and sram table in temp vars
336        tcamDF = self._tcamTable
337        sramDF = self._sramTable
338        logging.info("TCAM table (r*c): %s", tuple(tcamDF.shape))
339        logging.info("SRAM table (r*c): %s", tuple(sramDF.shape))
340        # * create tcamRows vector
341        self.__tcamRows = np.arange(0, self.__tcamPotMatchAddr, 1).tolist()
342        logging.info("TCAM table row vector: %s", list(self.__tcamRows))
343        printDebug(debug, f"TCAM table row vector: {*self.__tcamRows,}")
344        # * create tcamCols vector
345        self.__tcamCols = np.arange(1, self.__tcamQueryStrLen + 1, 1).tolist()
346        logging.info("TCAM table col vector: %s", list(self.__tcamCols))
347        printDebug(debug, f"TCAM table col vector: {*self.__tcamCols,}")
348        # * create tcamColVec vector and split in equal pieces
349        self.__tcamColVec = np.array_split(self.__tcamCols, self.__tcamTotalSubStr)
350        for i in range(len(self.__tcamColVec)):
351            self.__tcamColVec[i] = self.__tcamColVec[i].tolist()
352            logging.info("TCAM table col split vector [%d]: %s", i, list(self.__tcamColVec[i]))
353            printDebug(debug, f"TCAM table col split vector [{i}]: {self.__tcamColVec[i]}")
354        # * create sramRows vector
355        self.__sramRows = np.arange(0, self.__tcamTotalSubStr * 2**self.__tcamSubStrLen, 1).tolist()
356        logging.info("SRAM table row vector: %s", list(self.__sramRows))
357        printDebug(debug, f"SRAM table row vector: {self.__sramRows}")
358        # * create sramRowVec vector and split in equal pieces
359        self.__sramRowVec = np.array_split(self.__sramRows, self.__tcamTotalSubStr)
360        for i in range(len(self.__sramRowVec)):
361            self.__sramRowVec[i] = self.__sramRowVec[i].tolist()
362            logging.info("SRAM table row split vector [%d]: %s", i, list(self.__sramRowVec[i]))
363            printDebug(debug, f"SRAM table row split vector [{i}]: {self.__sramRowVec[i]}")
364        # * create sramCols vector
365        self.__sramCols = np.arange(0, self.__tcamPotMatchAddr + 1, 1).tolist()
366        logging.info("SRAM table col vector: %s", list(self.__sramCols))
367        printDebug(debug, f"SRAM table col vector: {self.__sramCols}")
368        return [self.__tcamRows, self.__tcamColVec, self.__sramRowVec, self.__sramCols]
369
370    def isolateTCAMSearchQueries(self, verbose, debug):
371        """
372        Create a data frame containing all the sub strings in original format from all the TCAM table search queries.
373
374        :param int verbose: print information in verbose mode.
375        :param int debug: print information in debug mode.
376        """
377        tcamDF = self._tcamTable
378        count1 = 0
379        self._tcamQSAddrTable = pd.DataFrame(columns=["TCAM Query Str Addr", "PMA", "QS col"])
380
381        # * ----- add all original search queries in dataframe
382        # * iterate through tcam table rows
383        for row in range(len(tcamDF)):
384            # * iterate through tcam table cols
385            for col in range(len(self.__tcamColVec)):
386                # * search and concat search query string address in tcam table
387                tempAddr = [str(c) for c in list(tcamDF.iloc[row, self.__tcamColVec[col]])]
388                tempAddr = "".join(tempAddr)
389                # * append row in sqSubStrAddrDf data frame
390                tempRow = [tempAddr, row, col]
391                self._tcamQSAddrTable.loc[count1] = tempRow
392                count1 += 1
393                logging.info("TCAM Search Queries Table | Addr: %s | TCAM Row: %5d | Sub String Col: %5d |", tempAddr, row, col)
394                printDebug(debug, f"TCAM Search Queries Table | Addr: {tempAddr} | TCAM Row: {row} | Sub String Col: {col} |")
395        if verbose:
396            self.printDF(self._tcamQSAddrTable, "Original TCAM Search Query Address Table")
397
398    def generateSRAMSubStr(self, verbose, debug):
399        """
400        Generate all possible combinations of all sub strings from the original TCAM table search queries.
401
402        :param int verbose: print information in verbose mode.
403        :param int debug: print information in debug mode.
404        """
405        count2 = 0
406        self._sramQSAddrTable = pd.DataFrame(columns=["SRAM Query Str Addr", "PMA", "QS col"])
407
408        # * ----- find all possible alternatives for X based addr
409        # * create array of N bit bin addresses
410        queryStrBinAddrList = np.arange(2**self.__tcamSubStrLen).tolist()
411        padding = "0" + str(self.__tcamSubStrLen) + "b"
412        for item in queryStrBinAddrList:
413            dec2Bin = format(item, padding)
414            queryStrBinAddrList = queryStrBinAddrList[:item] + [dec2Bin] + queryStrBinAddrList[item + 1 :]
415        logging.info("N bit bin addr list: %s", list(queryStrBinAddrList))
416        logging.info("N bit bin addr list len: %d", len(queryStrBinAddrList))
417        if verbose or debug:
418            print("N bit bin addr list: %s", list(queryStrBinAddrList))
419            print("N bit bin addr list len: %d", len(queryStrBinAddrList))
420
421        # * get origSQ addr
422        tempQSAddrList = self._tcamQSAddrTable["TCAM Query Str Addr"].to_list()
423        tempQSPmaList = self._tcamQSAddrTable["PMA"].to_list()
424        tempQSColList = self._tcamQSAddrTable["QS col"].to_list()
425
426        printDebug(debug, f"Search Query addr list: {tempQSAddrList}")
427        printDebug(debug, f"Search Query addr list len: {len(tempQSAddrList)}\n")
428        # * map the 'bX in search queries to 0 and 1
429        for (oldAddr, pma, qscol) in zip(tempQSAddrList, tempQSPmaList, tempQSColList):
430            # * if 'bX in search query then find all possible alternatives and add in table
431            if "x" in oldAddr:
432                for newAddr in queryStrBinAddrList:
433                    matching = jellyfish.damerau_levenshtein_distance(oldAddr, newAddr)
434                    if matching == len(re.findall("x", oldAddr)):
435                        printVerbose(
436                            verbose,
437                            f"count = {count2} | orig Search Query = {oldAddr} | " f"new Search Query = {newAddr} | matching ratio = {matching} |",
438                        )
439                        logging.info(
440                            "count = %d | orig Search Query = %s | new Search Query = %s | matching ratio = %f |", count2, oldAddr, newAddr, matching
441                        )
442                        self._sramQSAddrTable.loc[count2] = [newAddr, pma, qscol]
443                        count2 += 1
444            # * else simply add search query in table as is
445            else:
446                printVerbose(verbose, f"count = {count2} | orig Search Query = {oldAddr} | new Search Query = {oldAddr} | matching ratio = {0} |")
447                logging.info("count = %d | orig Search Query = %s | new Search Query = %s | matching ratio = %f |", count2, oldAddr, oldAddr, 0)
448                self._sramQSAddrTable.loc[count2] = [oldAddr, pma, qscol]
449                count2 += 1
450
451        if verbose:
452            self.printDF(self._sramQSAddrTable, "Original SRAM Search Query Address Table")
453
454    def mapTCAMtoSRAM(self, verbose, debug):
455        """
456        Map all possible combinations of TCAM table map sub strings to SRAM table map sub strings.
457
458        :param int verbose: print information in verbose mode.
459        :param int debug: print information in debug mode.
460        """
461        sramDF = self._sramTable
462        sramAddrList = self._sramQSAddrTable["SRAM Query Str Addr"].to_list()
463        tcamRowList = self._sramQSAddrTable["PMA"].to_list()
464        sramColList = self._sramQSAddrTable["QS col"].to_list()
465
466        if len(tcamRowList) == len(sramColList):
467            for (queryStr, pma, qsCol) in itertools.zip_longest(sramAddrList, tcamRowList, sramColList):
468                # * create sram table subsections based on query str
469                tempSRAMTable = sramDF.iloc[self.__sramRowVec[qsCol], self.__sramCols]
470                logging.info("Search Query mapping portion: %d", qsCol)
471                printDebug(debug, f"Search Query mapping portion: {qsCol}")
472                # print(tabulate(tempSRAMTable,headers='keys',tablefmt='github'),'\n')
473                # * find specific mapping cell in sram table
474                rowIndex = tempSRAMTable.index[tempSRAMTable["Addresses"] == queryStr].to_list()[0]
475                colIndex = len(self.__sramCols) - pma - 1
476                # print('sram rowIndex: ',rowIndex,type(rowIndex))
477                # print('sram colIndex: ',colIndex,type(colIndex))
478                # * find specific entry
479                oldSramTableEntry = sramDF.iloc[rowIndex, colIndex]
480                # print(sramDF.iloc[rowIndex,colIndex])
481                # * replace specific entry
482                sramDF.iat[rowIndex, colIndex] = 1
483                # * print before and after
484                if verbose or debug:
485                    logging.info("SRAM table cell [%d, %d] | Value = %s -> %s", rowIndex, colIndex, oldSramTableEntry, sramDF.iat[rowIndex, colIndex])
486                    printDebug(debug, f"SRAM table cell [{rowIndex}, {colIndex}] | Value = {oldSramTableEntry} -> {sramDF.iat[rowIndex,colIndex]}")
487            # * add zeros in empty cells
488            sramDF = sramDF.fillna(0)
489            self._sramTable = sramDF
490        else:
491            logging.error('"MATCH NOT FOUND": TCAM table rows != SRAM table cols config potMatchAddr')
492            sys.exit('"MATCH NOT FOUND": MISMATCH in TCAM table map and YAML config rows/cols')
493
494    def writeSRAMtoXlsx(self):
495        """
496        Generates an SRAM table map in XLSX format.
497
498        :return str: absolute path of the SRAM table map `.xlsx` file.
499        """
500        # * create sram table file path and name
501        self.sramTableXlsxFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram"))
502        self.sramTableXlsxFilePath = os.path.join(self.sramTableDir, self.sramTableXlsxFileName)
503        # * create excel file in dir sramTables
504        # writer = pd.ExcelWriter(self.sramTableXlsxFilePath,engine='xlsxwriter')
505        # writer.save()
506        # * apply formatting to dataframe
507        self._sramTable.style.applymap(highlightCell).to_excel(
508            excel_writer=self.sramTableXlsxFilePath, sheet_name=self.sramTableXlsxFileName, na_rep="", header=True, index=True, engine="openpyxl"
509        )
510        logging.info("Created SRAM table XLSX file: %s", self.sramTableXlsxFilePath)
511        print("Created SRAM table XLSX file: %s", self.sramTableXlsxFilePath)
512        return self.sramTableXlsxFilePath
513
514    def writeSRAMtoHtml(self):
515        """
516        Generates an SRAM table map in HTML format.
517
518        :return str: absolute path of the SRAM table map `.html` file.
519        """
520        # * create sram table file path and name
521        self.sramTableHtmlFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram").replace(".xlsx", ".html"))
522        self.sramTableHtmlFilePath = os.path.join(self.sramTableDir, self.sramTableHtmlFileName)
523        # * create html file in dir sramTables
524        self._sramTable.to_html(self.sramTableHtmlFilePath, index=True, header=True, justify="center", classes="table table-stripped")
525        logging.info("Created SRAM table HTML file: %s", self.sramTableHtmlFilePath)
526        print("Created SRAM table HTML file: %s", self.sramTableHtmlFilePath)
527        return self.sramTableHtmlFilePath
528
529    def writeSRAMtoJson(self):
530        """
531        Generates an SRAM table map in JSON format.
532
533        :return str: absolute path of the SRAM table map `.json` file.
534        """
535        # * create sram table file path and name
536        self.sramTableJsonFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram").replace(".xlsx", ".json"))
537        self.sramTableJsonFilePath = os.path.join(self.sramTableDir, self.sramTableJsonFileName)
538        # * create json file in dir sramTables
539        self._sramTable.to_json(self.sramTableJsonFilePath, orient="index", indent=4)
540        logging.info("Created SRAM table JSON file: %s", self.sramTableJsonFilePath)
541        print("Created SRAM table JSON file: %s", self.sramTableJsonFilePath)
542        return self.sramTableJsonFilePath
543
544    def writeSRAMtoTxt(self):
545        """
546        Generates an SRAM table map in TXT format.
547
548        :return str: absolute path of the SRAM table map `.txt` file.
549        """
550        # * create sram table file path and name
551        self.sramTableTxtFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram").replace(".xlsx", ".txt"))
552        self.sramTableTxtFilePath = os.path.join(self.sramTableDir, self.sramTableTxtFileName)
553        # * create txt file in dir sramTables
554        myTable = tabulate(self._sramTable, headers="keys", showindex=True, disable_numparse=True, tablefmt="github")
555        with open(self.sramTableTxtFilePath, "w", encoding="utf-8") as file:
556            file.write(myTable)
557        logging.info("Created SRAM table Txt file:  %s", self.sramTableTxtFilePath)
558        print("Created SRAM table Txt file:  %s", self.sramTableTxtFilePath)
559        return self.sramTableTxtFilePath
560
561
562# ===========================================================================================
563# ======================================== End Class ========================================
564# ===========================================================================================
565
566
567def printVerbose(verbose, msg):
568    """
569    Prints a string if verbose flag is active.
570
571    :param int verbose: print information in verbose mode.
572    :param str msg: Message to be printed in verbose mode.
573    """
574    if verbose:
575        print(str(msg))
576
577
578def printDebug(debug, msg):
579    """
580    Prints a string if debug flag is active.
581
582    :param int debug: print information in debug mode.
583    :param str msg: Message to be printed in debug mode.
584    """
585    if debug:
586        print(str(msg))
587
588
589def highlightCell(val):
590    """
591    Colors SRAM table map cells in XLSX file depending upon their value.
592
593    :param int val: numerical value of a particular cell.
594    :return str: cell background color code as a hex RBG value.
595    """
596    if val == 1:
597        color = "#E5961A"
598    elif val == 0:
599        color = "#E4EA15"
600    else:
601        color = "#D8C05A"
602    return f"background-color: {color}"
class TableMapping:
 25class TableMapping:
 26    """
 27    Generates a golden model for a particular SRAM memory table map config
 28    using a respective TCAM memory table map and configs.
 29    """
 30
 31    # * ----------------------------------------------------------------- Variables
 32    def __init__(self):
 33        """
 34        Constructor: Initializes all the class variables
 35
 36        **Public Variables:**
 37        :param str prjWorkDir:                  current project working dir
 38        :param str sramTableDir:                abs path of SRAM table map folder
 39        :param str tcamTableConfigsFilePath:    abs path of TCAM table map config file
 40        :param str tcamTableConfigsFileName:    TCAM table map config file name
 41        :param str tcamTableXlsxFilePath:       abs path of TCAM table map XLSX file
 42        :param str tcamTableXlsxFileName:       TCAM table map XLSX file name
 43        :param str sramTableXlsxFilePath:       abs path of generated SRAM table map XLSX file
 44        :param str sramTableXlsxFileName:       SRAM table map XLSX file name
 45        :param str sramTableHtmlFilePath:       abs path of generated SRAM table map HTML file
 46        :param str sramTableHtmlFileName:       SRAM table map HTML file name
 47        :param str sramTableJsonFilePath:       abs path of generated SRAM table map JSON file
 48        :param str sramTableJsonFileName:       SRAM table map JSON file name
 49        :param str sramTableTxtFilePath:        abs path of generated SRAM table map TXT file
 50        :param str sramTableTxtFileName:        SRAM table map TXT file name
 51
 52        **Protected Variables:**
 53        :param dict _tcamTableConfigs:      TCAM table map configs
 54        :param DataFrame _tcamTable:        TCAM table map
 55        :param DataFrame _sramTable:        SRAM table map
 56        :param DataFrame _tcamQSAddrTable:  TCAM table map query addr sub str
 57        :param DataFrame _sramQSAddrTable:  SRAM table map query addr sub str
 58
 59        **Private Variables:**
 60        :param int __tcamQueryStrLen:   `queryStrLen` of a particular TCAM table config
 61        :param int __tcamSubStrLen:     `subStrLen` of a particular TCAM table config
 62        :param int __tcamTotalSubStr:   `totalSubStr` of a particular TCAM table config
 63        :param int __tcamPotMatchAddr:  `potMatchAddr` of a particular TCAM table config
 64        :param int __sramTableRows:     SRAM table map row count
 65        :param int __sramTableCols:     SRAM table map col count
 66        :param list __tcamRows:         TCAM table map row count vector
 67        :param list __tcamCols:         TCAM table map col count vector
 68        :param list __tcamColVec:       TCAM table map sub string address col count vector
 69        :param list __sramRows:         SRAM table map row count vector
 70        :param list __sramRowVec:       SRAM table map sub string address row count vector
 71        :param list __sramCols:         SRAM table map col count vector
 72        """
 73        # * ------------------- public vars
 74        self.prjWorkDir = ""
 75        self.sramTableDir = ""
 76        self.tcamTableConfigsFilePath = ""
 77        self.tcamTableConfigsFileName = ""
 78        self.tcamTableXlsxFilePath = ""
 79        self.tcamTableXlsxFileName = ""
 80        self.sramTableXlsxFilePath = ""
 81        self.sramTableXlsxFileName = ""
 82        self.sramTableHtmlFilePath = ""
 83        self.sramTableHtmlFileName = ""
 84        self.sramTableJsonFilePath = ""
 85        self.sramTableJsonFileName = ""
 86        self.sramTableTxtFilePath = ""
 87        self.sramTableTxtFileName = ""
 88        # * ------------------- protected vars
 89        self._tcamTableConfigs = {}
 90        self._tcamTable = pd.DataFrame
 91        self._sramTable = pd.DataFrame
 92        self._tcamQSAddrTable = pd.DataFrame
 93        self._sramQSAddrTable = pd.DataFrame
 94        # * ------------------- private vars
 95        self.__tcamQueryStrLen = 0
 96        self.__tcamSubStrLen = 0
 97        self.__tcamTotalSubStr = 0
 98        self.__tcamPotMatchAddr = 0
 99        self.__sramTableRows = 0
100        self.__sramTableCols = 0
101        self.__tcamRows = []
102        self.__tcamCols = []
103        self.__tcamColVec = []
104        self.__sramRows = []
105        self.__sramRowVec = []
106        self.__sramCols = []
107        # * logging config
108        logging.basicConfig(
109            level=logging.DEBUG,
110            filename="./logs/tableMapping.log",
111            format="%(asctime)s | %(filename)s | %(funcName)s | %(levelname)s | %(lineno)d | %(message)s",
112        )
113
114    # * ----------------------------------------------------------------- Functions
115    def getPrjDir(self, verbose):
116        """
117        Obtain the absolute path of the current working directory.
118
119        :param int verbose: print information in verbose mode.
120        :return str: absolute path of the current project working directory.
121        """
122        self.prjWorkDir = os.getcwd()
123        logging.info("Project working dir: %s", self.prjWorkDir)
124        printVerbose(verbose, f"Project working dir: {self.prjWorkDir}")
125        return self.prjWorkDir
126
127    def getYAMLFilePath(self, verbose):
128        """
129        Obtain the absolute path of file tcamTables.yaml.
130
131        :param int verbose: print information in verbose mode.
132        :return str: absolute path of the current project working directory.
133        """
134        # * get tcamTables config file path
135        tempPath = os.path.join(self.prjWorkDir, "compiler/configs/tcamTables.yaml")
136        if os.path.isfile(tempPath) is True:
137            self.tcamTableConfigsFilePath = tempPath
138            self.tcamTableConfigsFileName = os.path.basename(tempPath)
139            logging.info('"FOUND": TCAM table config file path: %s', self.tcamTableConfigsFilePath)
140            printVerbose(verbose, f'"FOUND": TCAM table config file path: {self.tcamTableConfigsFilePath}')
141            return self.tcamTableConfigsFilePath
142        logging.error('"NOT FOUND": TCAM table config file path: %s', self.tcamTableConfigsFilePath)
143        sys.exit(f'"NOT FOUND": TCAM table config file path: {self.tcamTableConfigsFilePath}')
144
145    def readYAML(self, filePath, verbose):
146        """
147        Read a particular YAML config file
148
149        :param str filePath: absolute path of file tcamTables.yaml.
150        :param int verbose: print information in verbose mode.
151        :return dict: dictionary containing all the TCAM table configs.
152        """
153        with open(filePath, encoding="utf-8") as file:
154            self._tcamTableConfigs = yaml.full_load(file)
155        # print(json.dumps(self._tcamTableConfigs,indent=4))
156        # print(yaml.dump(self._tcamTableConfigs,sort_keys=False,default_flow_style=False))
157        logging.info("Read TCAM table config file: %s", self.tcamTableConfigsFilePath)
158        printVerbose(verbose, f"Read TCAM table config file: {self.tcamTableConfigsFilePath}")
159        return self._tcamTableConfigs
160
161    def printYAML(self, debug):
162        """
163        Print all present configs of a YAML file either in JSON or YAML style.
164
165        :param int debug: print information in debug mode.
166        """
167        printDebug(debug, "Printing TCAM table configs")
168        print(json.dumps(self._tcamTableConfigs, indent=4))
169        # print(yaml.dump(self._tcamTableConfigs,sort_keys=False,default_flow_style=False))
170        logging.info("Printed TCAM table configs")
171
172    def getTCAMConfig(self, tcamConfig):
173        """
174        Check if a particular tcamTable config exists in file tcamTables.yaml. If found store the config params in vars.
175        - **__tcamQueryStrLen:**    saves `queryStrLen`
176        - **__tcamSubStrLen:**      saves `subStrLen`
177        - **__tcamTotalSubStr:**    saves `totalSubStr`
178        - **__tcamPotMatchAddr:**   saves `potMatchAddr`
179
180        :param str tcamConfig: TCAM table config name e.g. tcamTableX
181        :return dict: dictionary containing the respective table map config.
182        """
183        # * look for specific tcam config in compiler/configs/tcamTables.yaml
184        if tcamConfig in self._tcamTableConfigs.keys():
185            tempConfig = self._tcamTableConfigs[tcamConfig]
186            # * save tcam config vars
187            self.__tcamQueryStrLen = tempConfig["queryStrLen"]
188            self.__tcamSubStrLen = tempConfig["subStrLen"]
189            self.__tcamTotalSubStr = tempConfig["totalSubStr"]
190            self.__tcamPotMatchAddr = tempConfig["potMatchAddr"]
191            # * print specific tcam config
192            # print(type(tempConfig))
193            logging.info('"FOUND" Required TCAM Config [%s]', tcamConfig)
194            print('"FOUND" Required TCAM Config [%s]', tcamConfig)
195            logging.info("TCAM Config Data [%s] = %s", tcamConfig, tempConfig)
196            return tempConfig
197        logging.error('"NOT FOUND": TCAM Config [%s]', tcamConfig)
198        sys.exit(f'"NOT FOUND": Required TCAM table config [{tcamConfig}]')
199
200    def getTCAMTableFilePath(self, tcamConfig, verbose):
201        """
202        Obtain the absolute path of file **tcamTableX.xlsx** which represents the TCAM memory table map.
203
204        :param str tcamConfig: TCAM table config name e.g. tcamTableX
205        :param int verbose: print information in verbose mode.
206        :return str: absolute path of the TCAM table mapping file.
207        """
208        # * find the specific tcam table map in compiler/lib/
209        tempPath = os.path.join(self.prjWorkDir, "compiler/lib/" + tcamConfig + ".xlsx")
210        if os.path.isfile(tempPath) is True:
211            self.tcamTableXlsxFilePath = tempPath
212            self.tcamTableXlsxFileName = os.path.basename(tempPath)
213            logging.info('"FOUND" TCAM table map XLSX file path: %s', self.tcamTableXlsxFilePath)
214            printVerbose(verbose, f'"FOUND" TCAM table map XLSX file path: {self.tcamTableXlsxFilePath}')
215            return self.tcamTableXlsxFilePath
216        logging.error('"NOT FOUND": TCAM table map XLSX file path: %s', self.tcamTableXlsxFilePath)
217        sys.exit(f'"NOT FOUND": TCAM table map XLSX file path {self.tcamTableXlsxFilePath}')
218
219    def printDF(self, dataFrame, heading):
220        """
221        Display the contents of a particular data frame.
222
223        :param DataFrame dataFrame: particular data frame object.
224        :param str heading: Title above data frame.
225        """
226        print("\n")
227        print("Printing dataframe: %s", heading)
228        print(tabulate(dataFrame, headers="keys", showindex=True, disable_numparse=True, tablefmt="github"), "\n")
229        logging.info("Printing dataframe: %s", str(heading))
230
231    def getTcamTableMap(self):
232        """
233        Getter function for the TCAM table map
234
235        :return DataFrame: TCAM table map dataframe object
236        """
237        return self._tcamTable
238
239    def getSramTableMap(self):
240        """
241        Getter function for the SRAM table map
242
243        :return DataFrame: SRAM table map dataframe object
244        """
245        return self._sramTable
246
247    def readTCAMTable(self, verbose):
248        """
249        Read the contents of a **tcamTableX.xlsx** TCAM memory table map as a data frame.
250
251        :param int verbose: print information in verbose mode.
252        :return int: list containing dimensions of TCAM table memory map.
253        """
254        # * store tcam table in dataframe
255        self._tcamTable = pd.read_excel(self.tcamTableXlsxFilePath, skiprows=2, index_col=None, engine="openpyxl")
256        # * get num of rows and col from tcam table
257        tcamTableRows = self._tcamTable.shape[0]
258        tcamTableCols = self._tcamTable.shape[1]
259        # * compare row/col of tcam table with respective yaml config
260        if tcamTableRows == self.__tcamPotMatchAddr and tcamTableCols - 1 == self.__tcamQueryStrLen:
261            logging.info('"MATCH FOUND": TCAM table map rows == TCAM table YAML config potMatchAddr')
262            printVerbose(verbose, '"MATCH FOUND": TCAM table map rows == TCAM table YAML config potMatchAddr')
263            logging.info('"MATCH FOUND": TCAM table map cols == TCAM table YAML config queryStrLen')
264            printVerbose(verbose, '"MATCH FOUND": TCAM table map cols == TCAM table YAML config queryStrLen')
265            return [tcamTableRows, tcamTableCols]
266        logging.error('"MATCH NOT FOUND": TCAM table map rows != TCAM table YAML config potMatchAddr')
267        logging.error('"MATCH NOT FOUND": TCAM table map cols != TCAM table YAML config queryStrLen')
268        sys.exit('"MATCH NOT FOUND": MISMATCH in TCAM table map and YAML config rows/cols')
269
270    def getSRAMTableDim(self, verbose):
271        """
272        Generate the dimensions of the SRAM table map data frame using TCAM table map configs.
273
274        :param int verbose: print information in verbose mode.
275        :return int: list containing dimensions of SRAM table memory map.
276        """
277        self.__sramTableRows = self.__tcamTotalSubStr * pow(2, self.__tcamSubStrLen)
278        self.__sramTableCols = self.__tcamPotMatchAddr
279        logging.info("SRAM table rows [{%4d}] cols [{%4d}]", self.__sramTableRows, self.__sramTableCols)
280        printVerbose(verbose, f"SRAM table rows [{self.__sramTableRows}] cols [{self.__sramTableCols}]")
281        return [self.__sramTableRows, self.__sramTableCols]
282
283    def genSRAMTable(self, verbose):
284        """
285        Create an empty SRAM table map data frame containing respective row addresses and column headings.
286
287        :param int verbose: print information in verbose mode.
288        """
289        # * create temp vars
290        sramTableAddrList = []
291        sramColHeadings = []
292        # * create row address
293        for i in range(self.__tcamTotalSubStr):
294            for j in range(2**self.__tcamSubStrLen):
295                padding = "0" + str(self.__tcamSubStrLen) + "b"
296                # sramTableAddrList.append(format(j, '#012b'))  # with 0b prefix
297                sramTableAddrList.append(format(j, padding))  # without 0b prefix
298            logging.info("Created [{%4d}] SRAM addresses from search query [{%4d}]", j + 1, i)
299            printVerbose(verbose, f"Created [{j+1}] SRAM addresses from search query [{i}]")
300        # * create col headings
301        for k in reversed(range(self.__tcamPotMatchAddr)):
302            heading = "D" + str(k)
303            sramColHeadings.append(heading)
304            logging.info("Created column heading %s", heading)
305        # * gen empty m*n sram table
306        self._sramTable = pd.DataFrame(index=np.arange(self.__sramTableRows), columns=np.arange(self.__sramTableCols))
307        # * rename column headings
308        self._sramTable.columns = sramColHeadings
309        # * insert addr col at position 0
310        self._sramTable.insert(0, "Addresses", sramTableAddrList, allow_duplicates=True)
311        logging.info("Created empty [%d x %d] SRAM table", self._sramTable.shape[0], self._sramTable.shape[1])
312        printVerbose(verbose, f"Created empty [{self._sramTable.shape[0]} x {self._sramTable.shape[1]}] SRAM table")
313
314    def createSRAMTableDir(self, verbose):
315        """
316        Create a directory to store SRAM table maps in various formats.
317
318        :param int verbose: print information in verbose mode.
319        :return str: absolute path of the SRAM table map directory.
320        """
321        # * create sramTables dir if it doesn't exist
322        self.sramTableDir = os.path.join(self.prjWorkDir, "sramTables")
323        if os.path.exists(self.sramTableDir) is False:
324            os.makedirs("sramTables")
325            logging.info("Created sramTables dir: %s", self.sramTableDir)
326            printVerbose(verbose, f"Created sramTables dir: {self.sramTableDir}")
327        return self.sramTableDir
328
329    def splitRowsAndCols(self, debug):
330        """
331        Create TCAM and SRAM table map row and column vectors based on TCAM table config parameters.
332
333        :param int debug: print information in debug mode.
334        :return list: list containing TCAM and SRAM row and column vectors.
335        """
336        # * store tcam and sram table in temp vars
337        tcamDF = self._tcamTable
338        sramDF = self._sramTable
339        logging.info("TCAM table (r*c): %s", tuple(tcamDF.shape))
340        logging.info("SRAM table (r*c): %s", tuple(sramDF.shape))
341        # * create tcamRows vector
342        self.__tcamRows = np.arange(0, self.__tcamPotMatchAddr, 1).tolist()
343        logging.info("TCAM table row vector: %s", list(self.__tcamRows))
344        printDebug(debug, f"TCAM table row vector: {*self.__tcamRows,}")
345        # * create tcamCols vector
346        self.__tcamCols = np.arange(1, self.__tcamQueryStrLen + 1, 1).tolist()
347        logging.info("TCAM table col vector: %s", list(self.__tcamCols))
348        printDebug(debug, f"TCAM table col vector: {*self.__tcamCols,}")
349        # * create tcamColVec vector and split in equal pieces
350        self.__tcamColVec = np.array_split(self.__tcamCols, self.__tcamTotalSubStr)
351        for i in range(len(self.__tcamColVec)):
352            self.__tcamColVec[i] = self.__tcamColVec[i].tolist()
353            logging.info("TCAM table col split vector [%d]: %s", i, list(self.__tcamColVec[i]))
354            printDebug(debug, f"TCAM table col split vector [{i}]: {self.__tcamColVec[i]}")
355        # * create sramRows vector
356        self.__sramRows = np.arange(0, self.__tcamTotalSubStr * 2**self.__tcamSubStrLen, 1).tolist()
357        logging.info("SRAM table row vector: %s", list(self.__sramRows))
358        printDebug(debug, f"SRAM table row vector: {self.__sramRows}")
359        # * create sramRowVec vector and split in equal pieces
360        self.__sramRowVec = np.array_split(self.__sramRows, self.__tcamTotalSubStr)
361        for i in range(len(self.__sramRowVec)):
362            self.__sramRowVec[i] = self.__sramRowVec[i].tolist()
363            logging.info("SRAM table row split vector [%d]: %s", i, list(self.__sramRowVec[i]))
364            printDebug(debug, f"SRAM table row split vector [{i}]: {self.__sramRowVec[i]}")
365        # * create sramCols vector
366        self.__sramCols = np.arange(0, self.__tcamPotMatchAddr + 1, 1).tolist()
367        logging.info("SRAM table col vector: %s", list(self.__sramCols))
368        printDebug(debug, f"SRAM table col vector: {self.__sramCols}")
369        return [self.__tcamRows, self.__tcamColVec, self.__sramRowVec, self.__sramCols]
370
371    def isolateTCAMSearchQueries(self, verbose, debug):
372        """
373        Create a data frame containing all the sub strings in original format from all the TCAM table search queries.
374
375        :param int verbose: print information in verbose mode.
376        :param int debug: print information in debug mode.
377        """
378        tcamDF = self._tcamTable
379        count1 = 0
380        self._tcamQSAddrTable = pd.DataFrame(columns=["TCAM Query Str Addr", "PMA", "QS col"])
381
382        # * ----- add all original search queries in dataframe
383        # * iterate through tcam table rows
384        for row in range(len(tcamDF)):
385            # * iterate through tcam table cols
386            for col in range(len(self.__tcamColVec)):
387                # * search and concat search query string address in tcam table
388                tempAddr = [str(c) for c in list(tcamDF.iloc[row, self.__tcamColVec[col]])]
389                tempAddr = "".join(tempAddr)
390                # * append row in sqSubStrAddrDf data frame
391                tempRow = [tempAddr, row, col]
392                self._tcamQSAddrTable.loc[count1] = tempRow
393                count1 += 1
394                logging.info("TCAM Search Queries Table | Addr: %s | TCAM Row: %5d | Sub String Col: %5d |", tempAddr, row, col)
395                printDebug(debug, f"TCAM Search Queries Table | Addr: {tempAddr} | TCAM Row: {row} | Sub String Col: {col} |")
396        if verbose:
397            self.printDF(self._tcamQSAddrTable, "Original TCAM Search Query Address Table")
398
399    def generateSRAMSubStr(self, verbose, debug):
400        """
401        Generate all possible combinations of all sub strings from the original TCAM table search queries.
402
403        :param int verbose: print information in verbose mode.
404        :param int debug: print information in debug mode.
405        """
406        count2 = 0
407        self._sramQSAddrTable = pd.DataFrame(columns=["SRAM Query Str Addr", "PMA", "QS col"])
408
409        # * ----- find all possible alternatives for X based addr
410        # * create array of N bit bin addresses
411        queryStrBinAddrList = np.arange(2**self.__tcamSubStrLen).tolist()
412        padding = "0" + str(self.__tcamSubStrLen) + "b"
413        for item in queryStrBinAddrList:
414            dec2Bin = format(item, padding)
415            queryStrBinAddrList = queryStrBinAddrList[:item] + [dec2Bin] + queryStrBinAddrList[item + 1 :]
416        logging.info("N bit bin addr list: %s", list(queryStrBinAddrList))
417        logging.info("N bit bin addr list len: %d", len(queryStrBinAddrList))
418        if verbose or debug:
419            print("N bit bin addr list: %s", list(queryStrBinAddrList))
420            print("N bit bin addr list len: %d", len(queryStrBinAddrList))
421
422        # * get origSQ addr
423        tempQSAddrList = self._tcamQSAddrTable["TCAM Query Str Addr"].to_list()
424        tempQSPmaList = self._tcamQSAddrTable["PMA"].to_list()
425        tempQSColList = self._tcamQSAddrTable["QS col"].to_list()
426
427        printDebug(debug, f"Search Query addr list: {tempQSAddrList}")
428        printDebug(debug, f"Search Query addr list len: {len(tempQSAddrList)}\n")
429        # * map the 'bX in search queries to 0 and 1
430        for (oldAddr, pma, qscol) in zip(tempQSAddrList, tempQSPmaList, tempQSColList):
431            # * if 'bX in search query then find all possible alternatives and add in table
432            if "x" in oldAddr:
433                for newAddr in queryStrBinAddrList:
434                    matching = jellyfish.damerau_levenshtein_distance(oldAddr, newAddr)
435                    if matching == len(re.findall("x", oldAddr)):
436                        printVerbose(
437                            verbose,
438                            f"count = {count2} | orig Search Query = {oldAddr} | " f"new Search Query = {newAddr} | matching ratio = {matching} |",
439                        )
440                        logging.info(
441                            "count = %d | orig Search Query = %s | new Search Query = %s | matching ratio = %f |", count2, oldAddr, newAddr, matching
442                        )
443                        self._sramQSAddrTable.loc[count2] = [newAddr, pma, qscol]
444                        count2 += 1
445            # * else simply add search query in table as is
446            else:
447                printVerbose(verbose, f"count = {count2} | orig Search Query = {oldAddr} | new Search Query = {oldAddr} | matching ratio = {0} |")
448                logging.info("count = %d | orig Search Query = %s | new Search Query = %s | matching ratio = %f |", count2, oldAddr, oldAddr, 0)
449                self._sramQSAddrTable.loc[count2] = [oldAddr, pma, qscol]
450                count2 += 1
451
452        if verbose:
453            self.printDF(self._sramQSAddrTable, "Original SRAM Search Query Address Table")
454
455    def mapTCAMtoSRAM(self, verbose, debug):
456        """
457        Map all possible combinations of TCAM table map sub strings to SRAM table map sub strings.
458
459        :param int verbose: print information in verbose mode.
460        :param int debug: print information in debug mode.
461        """
462        sramDF = self._sramTable
463        sramAddrList = self._sramQSAddrTable["SRAM Query Str Addr"].to_list()
464        tcamRowList = self._sramQSAddrTable["PMA"].to_list()
465        sramColList = self._sramQSAddrTable["QS col"].to_list()
466
467        if len(tcamRowList) == len(sramColList):
468            for (queryStr, pma, qsCol) in itertools.zip_longest(sramAddrList, tcamRowList, sramColList):
469                # * create sram table subsections based on query str
470                tempSRAMTable = sramDF.iloc[self.__sramRowVec[qsCol], self.__sramCols]
471                logging.info("Search Query mapping portion: %d", qsCol)
472                printDebug(debug, f"Search Query mapping portion: {qsCol}")
473                # print(tabulate(tempSRAMTable,headers='keys',tablefmt='github'),'\n')
474                # * find specific mapping cell in sram table
475                rowIndex = tempSRAMTable.index[tempSRAMTable["Addresses"] == queryStr].to_list()[0]
476                colIndex = len(self.__sramCols) - pma - 1
477                # print('sram rowIndex: ',rowIndex,type(rowIndex))
478                # print('sram colIndex: ',colIndex,type(colIndex))
479                # * find specific entry
480                oldSramTableEntry = sramDF.iloc[rowIndex, colIndex]
481                # print(sramDF.iloc[rowIndex,colIndex])
482                # * replace specific entry
483                sramDF.iat[rowIndex, colIndex] = 1
484                # * print before and after
485                if verbose or debug:
486                    logging.info("SRAM table cell [%d, %d] | Value = %s -> %s", rowIndex, colIndex, oldSramTableEntry, sramDF.iat[rowIndex, colIndex])
487                    printDebug(debug, f"SRAM table cell [{rowIndex}, {colIndex}] | Value = {oldSramTableEntry} -> {sramDF.iat[rowIndex,colIndex]}")
488            # * add zeros in empty cells
489            sramDF = sramDF.fillna(0)
490            self._sramTable = sramDF
491        else:
492            logging.error('"MATCH NOT FOUND": TCAM table rows != SRAM table cols config potMatchAddr')
493            sys.exit('"MATCH NOT FOUND": MISMATCH in TCAM table map and YAML config rows/cols')
494
495    def writeSRAMtoXlsx(self):
496        """
497        Generates an SRAM table map in XLSX format.
498
499        :return str: absolute path of the SRAM table map `.xlsx` file.
500        """
501        # * create sram table file path and name
502        self.sramTableXlsxFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram"))
503        self.sramTableXlsxFilePath = os.path.join(self.sramTableDir, self.sramTableXlsxFileName)
504        # * create excel file in dir sramTables
505        # writer = pd.ExcelWriter(self.sramTableXlsxFilePath,engine='xlsxwriter')
506        # writer.save()
507        # * apply formatting to dataframe
508        self._sramTable.style.applymap(highlightCell).to_excel(
509            excel_writer=self.sramTableXlsxFilePath, sheet_name=self.sramTableXlsxFileName, na_rep="", header=True, index=True, engine="openpyxl"
510        )
511        logging.info("Created SRAM table XLSX file: %s", self.sramTableXlsxFilePath)
512        print("Created SRAM table XLSX file: %s", self.sramTableXlsxFilePath)
513        return self.sramTableXlsxFilePath
514
515    def writeSRAMtoHtml(self):
516        """
517        Generates an SRAM table map in HTML format.
518
519        :return str: absolute path of the SRAM table map `.html` file.
520        """
521        # * create sram table file path and name
522        self.sramTableHtmlFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram").replace(".xlsx", ".html"))
523        self.sramTableHtmlFilePath = os.path.join(self.sramTableDir, self.sramTableHtmlFileName)
524        # * create html file in dir sramTables
525        self._sramTable.to_html(self.sramTableHtmlFilePath, index=True, header=True, justify="center", classes="table table-stripped")
526        logging.info("Created SRAM table HTML file: %s", self.sramTableHtmlFilePath)
527        print("Created SRAM table HTML file: %s", self.sramTableHtmlFilePath)
528        return self.sramTableHtmlFilePath
529
530    def writeSRAMtoJson(self):
531        """
532        Generates an SRAM table map in JSON format.
533
534        :return str: absolute path of the SRAM table map `.json` file.
535        """
536        # * create sram table file path and name
537        self.sramTableJsonFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram").replace(".xlsx", ".json"))
538        self.sramTableJsonFilePath = os.path.join(self.sramTableDir, self.sramTableJsonFileName)
539        # * create json file in dir sramTables
540        self._sramTable.to_json(self.sramTableJsonFilePath, orient="index", indent=4)
541        logging.info("Created SRAM table JSON file: %s", self.sramTableJsonFilePath)
542        print("Created SRAM table JSON file: %s", self.sramTableJsonFilePath)
543        return self.sramTableJsonFilePath
544
545    def writeSRAMtoTxt(self):
546        """
547        Generates an SRAM table map in TXT format.
548
549        :return str: absolute path of the SRAM table map `.txt` file.
550        """
551        # * create sram table file path and name
552        self.sramTableTxtFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram").replace(".xlsx", ".txt"))
553        self.sramTableTxtFilePath = os.path.join(self.sramTableDir, self.sramTableTxtFileName)
554        # * create txt file in dir sramTables
555        myTable = tabulate(self._sramTable, headers="keys", showindex=True, disable_numparse=True, tablefmt="github")
556        with open(self.sramTableTxtFilePath, "w", encoding="utf-8") as file:
557            file.write(myTable)
558        logging.info("Created SRAM table Txt file:  %s", self.sramTableTxtFilePath)
559        print("Created SRAM table Txt file:  %s", self.sramTableTxtFilePath)
560        return self.sramTableTxtFilePath

Generates a golden model for a particular SRAM memory table map config using a respective TCAM memory table map and configs.

TableMapping()
 32    def __init__(self):
 33        """
 34        Constructor: Initializes all the class variables
 35
 36        **Public Variables:**
 37        :param str prjWorkDir:                  current project working dir
 38        :param str sramTableDir:                abs path of SRAM table map folder
 39        :param str tcamTableConfigsFilePath:    abs path of TCAM table map config file
 40        :param str tcamTableConfigsFileName:    TCAM table map config file name
 41        :param str tcamTableXlsxFilePath:       abs path of TCAM table map XLSX file
 42        :param str tcamTableXlsxFileName:       TCAM table map XLSX file name
 43        :param str sramTableXlsxFilePath:       abs path of generated SRAM table map XLSX file
 44        :param str sramTableXlsxFileName:       SRAM table map XLSX file name
 45        :param str sramTableHtmlFilePath:       abs path of generated SRAM table map HTML file
 46        :param str sramTableHtmlFileName:       SRAM table map HTML file name
 47        :param str sramTableJsonFilePath:       abs path of generated SRAM table map JSON file
 48        :param str sramTableJsonFileName:       SRAM table map JSON file name
 49        :param str sramTableTxtFilePath:        abs path of generated SRAM table map TXT file
 50        :param str sramTableTxtFileName:        SRAM table map TXT file name
 51
 52        **Protected Variables:**
 53        :param dict _tcamTableConfigs:      TCAM table map configs
 54        :param DataFrame _tcamTable:        TCAM table map
 55        :param DataFrame _sramTable:        SRAM table map
 56        :param DataFrame _tcamQSAddrTable:  TCAM table map query addr sub str
 57        :param DataFrame _sramQSAddrTable:  SRAM table map query addr sub str
 58
 59        **Private Variables:**
 60        :param int __tcamQueryStrLen:   `queryStrLen` of a particular TCAM table config
 61        :param int __tcamSubStrLen:     `subStrLen` of a particular TCAM table config
 62        :param int __tcamTotalSubStr:   `totalSubStr` of a particular TCAM table config
 63        :param int __tcamPotMatchAddr:  `potMatchAddr` of a particular TCAM table config
 64        :param int __sramTableRows:     SRAM table map row count
 65        :param int __sramTableCols:     SRAM table map col count
 66        :param list __tcamRows:         TCAM table map row count vector
 67        :param list __tcamCols:         TCAM table map col count vector
 68        :param list __tcamColVec:       TCAM table map sub string address col count vector
 69        :param list __sramRows:         SRAM table map row count vector
 70        :param list __sramRowVec:       SRAM table map sub string address row count vector
 71        :param list __sramCols:         SRAM table map col count vector
 72        """
 73        # * ------------------- public vars
 74        self.prjWorkDir = ""
 75        self.sramTableDir = ""
 76        self.tcamTableConfigsFilePath = ""
 77        self.tcamTableConfigsFileName = ""
 78        self.tcamTableXlsxFilePath = ""
 79        self.tcamTableXlsxFileName = ""
 80        self.sramTableXlsxFilePath = ""
 81        self.sramTableXlsxFileName = ""
 82        self.sramTableHtmlFilePath = ""
 83        self.sramTableHtmlFileName = ""
 84        self.sramTableJsonFilePath = ""
 85        self.sramTableJsonFileName = ""
 86        self.sramTableTxtFilePath = ""
 87        self.sramTableTxtFileName = ""
 88        # * ------------------- protected vars
 89        self._tcamTableConfigs = {}
 90        self._tcamTable = pd.DataFrame
 91        self._sramTable = pd.DataFrame
 92        self._tcamQSAddrTable = pd.DataFrame
 93        self._sramQSAddrTable = pd.DataFrame
 94        # * ------------------- private vars
 95        self.__tcamQueryStrLen = 0
 96        self.__tcamSubStrLen = 0
 97        self.__tcamTotalSubStr = 0
 98        self.__tcamPotMatchAddr = 0
 99        self.__sramTableRows = 0
100        self.__sramTableCols = 0
101        self.__tcamRows = []
102        self.__tcamCols = []
103        self.__tcamColVec = []
104        self.__sramRows = []
105        self.__sramRowVec = []
106        self.__sramCols = []
107        # * logging config
108        logging.basicConfig(
109            level=logging.DEBUG,
110            filename="./logs/tableMapping.log",
111            format="%(asctime)s | %(filename)s | %(funcName)s | %(levelname)s | %(lineno)d | %(message)s",
112        )

Constructor: Initializes all the class variables

Public Variables:

Parameters
  • str prjWorkDir: current project working dir
  • str sramTableDir: abs path of SRAM table map folder
  • str tcamTableConfigsFilePath: abs path of TCAM table map config file
  • str tcamTableConfigsFileName: TCAM table map config file name
  • str tcamTableXlsxFilePath: abs path of TCAM table map XLSX file
  • str tcamTableXlsxFileName: TCAM table map XLSX file name
  • str sramTableXlsxFilePath: abs path of generated SRAM table map XLSX file
  • str sramTableXlsxFileName: SRAM table map XLSX file name
  • str sramTableHtmlFilePath: abs path of generated SRAM table map HTML file
  • str sramTableHtmlFileName: SRAM table map HTML file name
  • str sramTableJsonFilePath: abs path of generated SRAM table map JSON file
  • str sramTableJsonFileName: SRAM table map JSON file name
  • str sramTableTxtFilePath: abs path of generated SRAM table map TXT file
  • str sramTableTxtFileName: SRAM table map TXT file name

Protected Variables:

  • dict _tcamTableConfigs: TCAM table map configs
  • DataFrame _tcamTable: TCAM table map
  • DataFrame _sramTable: SRAM table map
  • DataFrame _tcamQSAddrTable: TCAM table map query addr sub str
  • DataFrame _sramQSAddrTable: SRAM table map query addr sub str

Private Variables:

  • int __tcamQueryStrLen: queryStrLen of a particular TCAM table config
  • int __tcamSubStrLen: subStrLen of a particular TCAM table config
  • int __tcamTotalSubStr: totalSubStr of a particular TCAM table config
  • int __tcamPotMatchAddr: potMatchAddr of a particular TCAM table config
  • int __sramTableRows: SRAM table map row count
  • int __sramTableCols: SRAM table map col count
  • list __tcamRows: TCAM table map row count vector
  • list __tcamCols: TCAM table map col count vector
  • list __tcamColVec: TCAM table map sub string address col count vector
  • list __sramRows: SRAM table map row count vector
  • list __sramRowVec: SRAM table map sub string address row count vector
  • list __sramCols: SRAM table map col count vector
def getPrjDir(self, verbose):
115    def getPrjDir(self, verbose):
116        """
117        Obtain the absolute path of the current working directory.
118
119        :param int verbose: print information in verbose mode.
120        :return str: absolute path of the current project working directory.
121        """
122        self.prjWorkDir = os.getcwd()
123        logging.info("Project working dir: %s", self.prjWorkDir)
124        printVerbose(verbose, f"Project working dir: {self.prjWorkDir}")
125        return self.prjWorkDir

Obtain the absolute path of the current working directory.

Parameters
  • int verbose: print information in verbose mode.
Returns

absolute path of the current project working directory.

def getYAMLFilePath(self, verbose):
127    def getYAMLFilePath(self, verbose):
128        """
129        Obtain the absolute path of file tcamTables.yaml.
130
131        :param int verbose: print information in verbose mode.
132        :return str: absolute path of the current project working directory.
133        """
134        # * get tcamTables config file path
135        tempPath = os.path.join(self.prjWorkDir, "compiler/configs/tcamTables.yaml")
136        if os.path.isfile(tempPath) is True:
137            self.tcamTableConfigsFilePath = tempPath
138            self.tcamTableConfigsFileName = os.path.basename(tempPath)
139            logging.info('"FOUND": TCAM table config file path: %s', self.tcamTableConfigsFilePath)
140            printVerbose(verbose, f'"FOUND": TCAM table config file path: {self.tcamTableConfigsFilePath}')
141            return self.tcamTableConfigsFilePath
142        logging.error('"NOT FOUND": TCAM table config file path: %s', self.tcamTableConfigsFilePath)
143        sys.exit(f'"NOT FOUND": TCAM table config file path: {self.tcamTableConfigsFilePath}')

Obtain the absolute path of file tcamTables.yaml.

Parameters
  • int verbose: print information in verbose mode.
Returns

absolute path of the current project working directory.

def readYAML(self, filePath, verbose):
145    def readYAML(self, filePath, verbose):
146        """
147        Read a particular YAML config file
148
149        :param str filePath: absolute path of file tcamTables.yaml.
150        :param int verbose: print information in verbose mode.
151        :return dict: dictionary containing all the TCAM table configs.
152        """
153        with open(filePath, encoding="utf-8") as file:
154            self._tcamTableConfigs = yaml.full_load(file)
155        # print(json.dumps(self._tcamTableConfigs,indent=4))
156        # print(yaml.dump(self._tcamTableConfigs,sort_keys=False,default_flow_style=False))
157        logging.info("Read TCAM table config file: %s", self.tcamTableConfigsFilePath)
158        printVerbose(verbose, f"Read TCAM table config file: {self.tcamTableConfigsFilePath}")
159        return self._tcamTableConfigs

Read a particular YAML config file

Parameters
  • str filePath: absolute path of file tcamTables.yaml.
  • int verbose: print information in verbose mode.
Returns

dictionary containing all the TCAM table configs.

def printYAML(self, debug):
161    def printYAML(self, debug):
162        """
163        Print all present configs of a YAML file either in JSON or YAML style.
164
165        :param int debug: print information in debug mode.
166        """
167        printDebug(debug, "Printing TCAM table configs")
168        print(json.dumps(self._tcamTableConfigs, indent=4))
169        # print(yaml.dump(self._tcamTableConfigs,sort_keys=False,default_flow_style=False))
170        logging.info("Printed TCAM table configs")

Print all present configs of a YAML file either in JSON or YAML style.

Parameters
  • int debug: print information in debug mode.
def getTCAMConfig(self, tcamConfig):
172    def getTCAMConfig(self, tcamConfig):
173        """
174        Check if a particular tcamTable config exists in file tcamTables.yaml. If found store the config params in vars.
175        - **__tcamQueryStrLen:**    saves `queryStrLen`
176        - **__tcamSubStrLen:**      saves `subStrLen`
177        - **__tcamTotalSubStr:**    saves `totalSubStr`
178        - **__tcamPotMatchAddr:**   saves `potMatchAddr`
179
180        :param str tcamConfig: TCAM table config name e.g. tcamTableX
181        :return dict: dictionary containing the respective table map config.
182        """
183        # * look for specific tcam config in compiler/configs/tcamTables.yaml
184        if tcamConfig in self._tcamTableConfigs.keys():
185            tempConfig = self._tcamTableConfigs[tcamConfig]
186            # * save tcam config vars
187            self.__tcamQueryStrLen = tempConfig["queryStrLen"]
188            self.__tcamSubStrLen = tempConfig["subStrLen"]
189            self.__tcamTotalSubStr = tempConfig["totalSubStr"]
190            self.__tcamPotMatchAddr = tempConfig["potMatchAddr"]
191            # * print specific tcam config
192            # print(type(tempConfig))
193            logging.info('"FOUND" Required TCAM Config [%s]', tcamConfig)
194            print('"FOUND" Required TCAM Config [%s]', tcamConfig)
195            logging.info("TCAM Config Data [%s] = %s", tcamConfig, tempConfig)
196            return tempConfig
197        logging.error('"NOT FOUND": TCAM Config [%s]', tcamConfig)
198        sys.exit(f'"NOT FOUND": Required TCAM table config [{tcamConfig}]')

Check if a particular tcamTable config exists in file tcamTables.yaml. If found store the config params in vars.

  • __tcamQueryStrLen: saves queryStrLen
  • __tcamSubStrLen: saves subStrLen
  • __tcamTotalSubStr: saves totalSubStr
  • __tcamPotMatchAddr: saves potMatchAddr
Parameters
  • str tcamConfig: TCAM table config name e.g. tcamTableX
Returns

dictionary containing the respective table map config.

def getTCAMTableFilePath(self, tcamConfig, verbose):
200    def getTCAMTableFilePath(self, tcamConfig, verbose):
201        """
202        Obtain the absolute path of file **tcamTableX.xlsx** which represents the TCAM memory table map.
203
204        :param str tcamConfig: TCAM table config name e.g. tcamTableX
205        :param int verbose: print information in verbose mode.
206        :return str: absolute path of the TCAM table mapping file.
207        """
208        # * find the specific tcam table map in compiler/lib/
209        tempPath = os.path.join(self.prjWorkDir, "compiler/lib/" + tcamConfig + ".xlsx")
210        if os.path.isfile(tempPath) is True:
211            self.tcamTableXlsxFilePath = tempPath
212            self.tcamTableXlsxFileName = os.path.basename(tempPath)
213            logging.info('"FOUND" TCAM table map XLSX file path: %s', self.tcamTableXlsxFilePath)
214            printVerbose(verbose, f'"FOUND" TCAM table map XLSX file path: {self.tcamTableXlsxFilePath}')
215            return self.tcamTableXlsxFilePath
216        logging.error('"NOT FOUND": TCAM table map XLSX file path: %s', self.tcamTableXlsxFilePath)
217        sys.exit(f'"NOT FOUND": TCAM table map XLSX file path {self.tcamTableXlsxFilePath}')

Obtain the absolute path of file tcamTableX.xlsx which represents the TCAM memory table map.

Parameters
  • str tcamConfig: TCAM table config name e.g. tcamTableX
  • int verbose: print information in verbose mode.
Returns

absolute path of the TCAM table mapping file.

def printDF(self, dataFrame, heading):
219    def printDF(self, dataFrame, heading):
220        """
221        Display the contents of a particular data frame.
222
223        :param DataFrame dataFrame: particular data frame object.
224        :param str heading: Title above data frame.
225        """
226        print("\n")
227        print("Printing dataframe: %s", heading)
228        print(tabulate(dataFrame, headers="keys", showindex=True, disable_numparse=True, tablefmt="github"), "\n")
229        logging.info("Printing dataframe: %s", str(heading))

Display the contents of a particular data frame.

Parameters
  • DataFrame dataFrame: particular data frame object.
  • str heading: Title above data frame.
def getTcamTableMap(self):
231    def getTcamTableMap(self):
232        """
233        Getter function for the TCAM table map
234
235        :return DataFrame: TCAM table map dataframe object
236        """
237        return self._tcamTable

Getter function for the TCAM table map

Returns

TCAM table map dataframe object

def getSramTableMap(self):
239    def getSramTableMap(self):
240        """
241        Getter function for the SRAM table map
242
243        :return DataFrame: SRAM table map dataframe object
244        """
245        return self._sramTable

Getter function for the SRAM table map

Returns

SRAM table map dataframe object

def readTCAMTable(self, verbose):
247    def readTCAMTable(self, verbose):
248        """
249        Read the contents of a **tcamTableX.xlsx** TCAM memory table map as a data frame.
250
251        :param int verbose: print information in verbose mode.
252        :return int: list containing dimensions of TCAM table memory map.
253        """
254        # * store tcam table in dataframe
255        self._tcamTable = pd.read_excel(self.tcamTableXlsxFilePath, skiprows=2, index_col=None, engine="openpyxl")
256        # * get num of rows and col from tcam table
257        tcamTableRows = self._tcamTable.shape[0]
258        tcamTableCols = self._tcamTable.shape[1]
259        # * compare row/col of tcam table with respective yaml config
260        if tcamTableRows == self.__tcamPotMatchAddr and tcamTableCols - 1 == self.__tcamQueryStrLen:
261            logging.info('"MATCH FOUND": TCAM table map rows == TCAM table YAML config potMatchAddr')
262            printVerbose(verbose, '"MATCH FOUND": TCAM table map rows == TCAM table YAML config potMatchAddr')
263            logging.info('"MATCH FOUND": TCAM table map cols == TCAM table YAML config queryStrLen')
264            printVerbose(verbose, '"MATCH FOUND": TCAM table map cols == TCAM table YAML config queryStrLen')
265            return [tcamTableRows, tcamTableCols]
266        logging.error('"MATCH NOT FOUND": TCAM table map rows != TCAM table YAML config potMatchAddr')
267        logging.error('"MATCH NOT FOUND": TCAM table map cols != TCAM table YAML config queryStrLen')
268        sys.exit('"MATCH NOT FOUND": MISMATCH in TCAM table map and YAML config rows/cols')

Read the contents of a tcamTableX.xlsx TCAM memory table map as a data frame.

Parameters
  • int verbose: print information in verbose mode.
Returns

list containing dimensions of TCAM table memory map.

def getSRAMTableDim(self, verbose):
270    def getSRAMTableDim(self, verbose):
271        """
272        Generate the dimensions of the SRAM table map data frame using TCAM table map configs.
273
274        :param int verbose: print information in verbose mode.
275        :return int: list containing dimensions of SRAM table memory map.
276        """
277        self.__sramTableRows = self.__tcamTotalSubStr * pow(2, self.__tcamSubStrLen)
278        self.__sramTableCols = self.__tcamPotMatchAddr
279        logging.info("SRAM table rows [{%4d}] cols [{%4d}]", self.__sramTableRows, self.__sramTableCols)
280        printVerbose(verbose, f"SRAM table rows [{self.__sramTableRows}] cols [{self.__sramTableCols}]")
281        return [self.__sramTableRows, self.__sramTableCols]

Generate the dimensions of the SRAM table map data frame using TCAM table map configs.

Parameters
  • int verbose: print information in verbose mode.
Returns

list containing dimensions of SRAM table memory map.

def genSRAMTable(self, verbose):
283    def genSRAMTable(self, verbose):
284        """
285        Create an empty SRAM table map data frame containing respective row addresses and column headings.
286
287        :param int verbose: print information in verbose mode.
288        """
289        # * create temp vars
290        sramTableAddrList = []
291        sramColHeadings = []
292        # * create row address
293        for i in range(self.__tcamTotalSubStr):
294            for j in range(2**self.__tcamSubStrLen):
295                padding = "0" + str(self.__tcamSubStrLen) + "b"
296                # sramTableAddrList.append(format(j, '#012b'))  # with 0b prefix
297                sramTableAddrList.append(format(j, padding))  # without 0b prefix
298            logging.info("Created [{%4d}] SRAM addresses from search query [{%4d}]", j + 1, i)
299            printVerbose(verbose, f"Created [{j+1}] SRAM addresses from search query [{i}]")
300        # * create col headings
301        for k in reversed(range(self.__tcamPotMatchAddr)):
302            heading = "D" + str(k)
303            sramColHeadings.append(heading)
304            logging.info("Created column heading %s", heading)
305        # * gen empty m*n sram table
306        self._sramTable = pd.DataFrame(index=np.arange(self.__sramTableRows), columns=np.arange(self.__sramTableCols))
307        # * rename column headings
308        self._sramTable.columns = sramColHeadings
309        # * insert addr col at position 0
310        self._sramTable.insert(0, "Addresses", sramTableAddrList, allow_duplicates=True)
311        logging.info("Created empty [%d x %d] SRAM table", self._sramTable.shape[0], self._sramTable.shape[1])
312        printVerbose(verbose, f"Created empty [{self._sramTable.shape[0]} x {self._sramTable.shape[1]}] SRAM table")

Create an empty SRAM table map data frame containing respective row addresses and column headings.

Parameters
  • int verbose: print information in verbose mode.
def createSRAMTableDir(self, verbose):
314    def createSRAMTableDir(self, verbose):
315        """
316        Create a directory to store SRAM table maps in various formats.
317
318        :param int verbose: print information in verbose mode.
319        :return str: absolute path of the SRAM table map directory.
320        """
321        # * create sramTables dir if it doesn't exist
322        self.sramTableDir = os.path.join(self.prjWorkDir, "sramTables")
323        if os.path.exists(self.sramTableDir) is False:
324            os.makedirs("sramTables")
325            logging.info("Created sramTables dir: %s", self.sramTableDir)
326            printVerbose(verbose, f"Created sramTables dir: {self.sramTableDir}")
327        return self.sramTableDir

Create a directory to store SRAM table maps in various formats.

Parameters
  • int verbose: print information in verbose mode.
Returns

absolute path of the SRAM table map directory.

def splitRowsAndCols(self, debug):
329    def splitRowsAndCols(self, debug):
330        """
331        Create TCAM and SRAM table map row and column vectors based on TCAM table config parameters.
332
333        :param int debug: print information in debug mode.
334        :return list: list containing TCAM and SRAM row and column vectors.
335        """
336        # * store tcam and sram table in temp vars
337        tcamDF = self._tcamTable
338        sramDF = self._sramTable
339        logging.info("TCAM table (r*c): %s", tuple(tcamDF.shape))
340        logging.info("SRAM table (r*c): %s", tuple(sramDF.shape))
341        # * create tcamRows vector
342        self.__tcamRows = np.arange(0, self.__tcamPotMatchAddr, 1).tolist()
343        logging.info("TCAM table row vector: %s", list(self.__tcamRows))
344        printDebug(debug, f"TCAM table row vector: {*self.__tcamRows,}")
345        # * create tcamCols vector
346        self.__tcamCols = np.arange(1, self.__tcamQueryStrLen + 1, 1).tolist()
347        logging.info("TCAM table col vector: %s", list(self.__tcamCols))
348        printDebug(debug, f"TCAM table col vector: {*self.__tcamCols,}")
349        # * create tcamColVec vector and split in equal pieces
350        self.__tcamColVec = np.array_split(self.__tcamCols, self.__tcamTotalSubStr)
351        for i in range(len(self.__tcamColVec)):
352            self.__tcamColVec[i] = self.__tcamColVec[i].tolist()
353            logging.info("TCAM table col split vector [%d]: %s", i, list(self.__tcamColVec[i]))
354            printDebug(debug, f"TCAM table col split vector [{i}]: {self.__tcamColVec[i]}")
355        # * create sramRows vector
356        self.__sramRows = np.arange(0, self.__tcamTotalSubStr * 2**self.__tcamSubStrLen, 1).tolist()
357        logging.info("SRAM table row vector: %s", list(self.__sramRows))
358        printDebug(debug, f"SRAM table row vector: {self.__sramRows}")
359        # * create sramRowVec vector and split in equal pieces
360        self.__sramRowVec = np.array_split(self.__sramRows, self.__tcamTotalSubStr)
361        for i in range(len(self.__sramRowVec)):
362            self.__sramRowVec[i] = self.__sramRowVec[i].tolist()
363            logging.info("SRAM table row split vector [%d]: %s", i, list(self.__sramRowVec[i]))
364            printDebug(debug, f"SRAM table row split vector [{i}]: {self.__sramRowVec[i]}")
365        # * create sramCols vector
366        self.__sramCols = np.arange(0, self.__tcamPotMatchAddr + 1, 1).tolist()
367        logging.info("SRAM table col vector: %s", list(self.__sramCols))
368        printDebug(debug, f"SRAM table col vector: {self.__sramCols}")
369        return [self.__tcamRows, self.__tcamColVec, self.__sramRowVec, self.__sramCols]

Create TCAM and SRAM table map row and column vectors based on TCAM table config parameters.

Parameters
  • int debug: print information in debug mode.
Returns

list containing TCAM and SRAM row and column vectors.

def isolateTCAMSearchQueries(self, verbose, debug):
371    def isolateTCAMSearchQueries(self, verbose, debug):
372        """
373        Create a data frame containing all the sub strings in original format from all the TCAM table search queries.
374
375        :param int verbose: print information in verbose mode.
376        :param int debug: print information in debug mode.
377        """
378        tcamDF = self._tcamTable
379        count1 = 0
380        self._tcamQSAddrTable = pd.DataFrame(columns=["TCAM Query Str Addr", "PMA", "QS col"])
381
382        # * ----- add all original search queries in dataframe
383        # * iterate through tcam table rows
384        for row in range(len(tcamDF)):
385            # * iterate through tcam table cols
386            for col in range(len(self.__tcamColVec)):
387                # * search and concat search query string address in tcam table
388                tempAddr = [str(c) for c in list(tcamDF.iloc[row, self.__tcamColVec[col]])]
389                tempAddr = "".join(tempAddr)
390                # * append row in sqSubStrAddrDf data frame
391                tempRow = [tempAddr, row, col]
392                self._tcamQSAddrTable.loc[count1] = tempRow
393                count1 += 1
394                logging.info("TCAM Search Queries Table | Addr: %s | TCAM Row: %5d | Sub String Col: %5d |", tempAddr, row, col)
395                printDebug(debug, f"TCAM Search Queries Table | Addr: {tempAddr} | TCAM Row: {row} | Sub String Col: {col} |")
396        if verbose:
397            self.printDF(self._tcamQSAddrTable, "Original TCAM Search Query Address Table")

Create a data frame containing all the sub strings in original format from all the TCAM table search queries.

Parameters
  • int verbose: print information in verbose mode.
  • int debug: print information in debug mode.
def generateSRAMSubStr(self, verbose, debug):
399    def generateSRAMSubStr(self, verbose, debug):
400        """
401        Generate all possible combinations of all sub strings from the original TCAM table search queries.
402
403        :param int verbose: print information in verbose mode.
404        :param int debug: print information in debug mode.
405        """
406        count2 = 0
407        self._sramQSAddrTable = pd.DataFrame(columns=["SRAM Query Str Addr", "PMA", "QS col"])
408
409        # * ----- find all possible alternatives for X based addr
410        # * create array of N bit bin addresses
411        queryStrBinAddrList = np.arange(2**self.__tcamSubStrLen).tolist()
412        padding = "0" + str(self.__tcamSubStrLen) + "b"
413        for item in queryStrBinAddrList:
414            dec2Bin = format(item, padding)
415            queryStrBinAddrList = queryStrBinAddrList[:item] + [dec2Bin] + queryStrBinAddrList[item + 1 :]
416        logging.info("N bit bin addr list: %s", list(queryStrBinAddrList))
417        logging.info("N bit bin addr list len: %d", len(queryStrBinAddrList))
418        if verbose or debug:
419            print("N bit bin addr list: %s", list(queryStrBinAddrList))
420            print("N bit bin addr list len: %d", len(queryStrBinAddrList))
421
422        # * get origSQ addr
423        tempQSAddrList = self._tcamQSAddrTable["TCAM Query Str Addr"].to_list()
424        tempQSPmaList = self._tcamQSAddrTable["PMA"].to_list()
425        tempQSColList = self._tcamQSAddrTable["QS col"].to_list()
426
427        printDebug(debug, f"Search Query addr list: {tempQSAddrList}")
428        printDebug(debug, f"Search Query addr list len: {len(tempQSAddrList)}\n")
429        # * map the 'bX in search queries to 0 and 1
430        for (oldAddr, pma, qscol) in zip(tempQSAddrList, tempQSPmaList, tempQSColList):
431            # * if 'bX in search query then find all possible alternatives and add in table
432            if "x" in oldAddr:
433                for newAddr in queryStrBinAddrList:
434                    matching = jellyfish.damerau_levenshtein_distance(oldAddr, newAddr)
435                    if matching == len(re.findall("x", oldAddr)):
436                        printVerbose(
437                            verbose,
438                            f"count = {count2} | orig Search Query = {oldAddr} | " f"new Search Query = {newAddr} | matching ratio = {matching} |",
439                        )
440                        logging.info(
441                            "count = %d | orig Search Query = %s | new Search Query = %s | matching ratio = %f |", count2, oldAddr, newAddr, matching
442                        )
443                        self._sramQSAddrTable.loc[count2] = [newAddr, pma, qscol]
444                        count2 += 1
445            # * else simply add search query in table as is
446            else:
447                printVerbose(verbose, f"count = {count2} | orig Search Query = {oldAddr} | new Search Query = {oldAddr} | matching ratio = {0} |")
448                logging.info("count = %d | orig Search Query = %s | new Search Query = %s | matching ratio = %f |", count2, oldAddr, oldAddr, 0)
449                self._sramQSAddrTable.loc[count2] = [oldAddr, pma, qscol]
450                count2 += 1
451
452        if verbose:
453            self.printDF(self._sramQSAddrTable, "Original SRAM Search Query Address Table")

Generate all possible combinations of all sub strings from the original TCAM table search queries.

Parameters
  • int verbose: print information in verbose mode.
  • int debug: print information in debug mode.
def mapTCAMtoSRAM(self, verbose, debug):
455    def mapTCAMtoSRAM(self, verbose, debug):
456        """
457        Map all possible combinations of TCAM table map sub strings to SRAM table map sub strings.
458
459        :param int verbose: print information in verbose mode.
460        :param int debug: print information in debug mode.
461        """
462        sramDF = self._sramTable
463        sramAddrList = self._sramQSAddrTable["SRAM Query Str Addr"].to_list()
464        tcamRowList = self._sramQSAddrTable["PMA"].to_list()
465        sramColList = self._sramQSAddrTable["QS col"].to_list()
466
467        if len(tcamRowList) == len(sramColList):
468            for (queryStr, pma, qsCol) in itertools.zip_longest(sramAddrList, tcamRowList, sramColList):
469                # * create sram table subsections based on query str
470                tempSRAMTable = sramDF.iloc[self.__sramRowVec[qsCol], self.__sramCols]
471                logging.info("Search Query mapping portion: %d", qsCol)
472                printDebug(debug, f"Search Query mapping portion: {qsCol}")
473                # print(tabulate(tempSRAMTable,headers='keys',tablefmt='github'),'\n')
474                # * find specific mapping cell in sram table
475                rowIndex = tempSRAMTable.index[tempSRAMTable["Addresses"] == queryStr].to_list()[0]
476                colIndex = len(self.__sramCols) - pma - 1
477                # print('sram rowIndex: ',rowIndex,type(rowIndex))
478                # print('sram colIndex: ',colIndex,type(colIndex))
479                # * find specific entry
480                oldSramTableEntry = sramDF.iloc[rowIndex, colIndex]
481                # print(sramDF.iloc[rowIndex,colIndex])
482                # * replace specific entry
483                sramDF.iat[rowIndex, colIndex] = 1
484                # * print before and after
485                if verbose or debug:
486                    logging.info("SRAM table cell [%d, %d] | Value = %s -> %s", rowIndex, colIndex, oldSramTableEntry, sramDF.iat[rowIndex, colIndex])
487                    printDebug(debug, f"SRAM table cell [{rowIndex}, {colIndex}] | Value = {oldSramTableEntry} -> {sramDF.iat[rowIndex,colIndex]}")
488            # * add zeros in empty cells
489            sramDF = sramDF.fillna(0)
490            self._sramTable = sramDF
491        else:
492            logging.error('"MATCH NOT FOUND": TCAM table rows != SRAM table cols config potMatchAddr')
493            sys.exit('"MATCH NOT FOUND": MISMATCH in TCAM table map and YAML config rows/cols')

Map all possible combinations of TCAM table map sub strings to SRAM table map sub strings.

Parameters
  • int verbose: print information in verbose mode.
  • int debug: print information in debug mode.
def writeSRAMtoXlsx(self):
495    def writeSRAMtoXlsx(self):
496        """
497        Generates an SRAM table map in XLSX format.
498
499        :return str: absolute path of the SRAM table map `.xlsx` file.
500        """
501        # * create sram table file path and name
502        self.sramTableXlsxFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram"))
503        self.sramTableXlsxFilePath = os.path.join(self.sramTableDir, self.sramTableXlsxFileName)
504        # * create excel file in dir sramTables
505        # writer = pd.ExcelWriter(self.sramTableXlsxFilePath,engine='xlsxwriter')
506        # writer.save()
507        # * apply formatting to dataframe
508        self._sramTable.style.applymap(highlightCell).to_excel(
509            excel_writer=self.sramTableXlsxFilePath, sheet_name=self.sramTableXlsxFileName, na_rep="", header=True, index=True, engine="openpyxl"
510        )
511        logging.info("Created SRAM table XLSX file: %s", self.sramTableXlsxFilePath)
512        print("Created SRAM table XLSX file: %s", self.sramTableXlsxFilePath)
513        return self.sramTableXlsxFilePath

Generates an SRAM table map in XLSX format.

Returns

absolute path of the SRAM table map .xlsx file.

def writeSRAMtoHtml(self):
515    def writeSRAMtoHtml(self):
516        """
517        Generates an SRAM table map in HTML format.
518
519        :return str: absolute path of the SRAM table map `.html` file.
520        """
521        # * create sram table file path and name
522        self.sramTableHtmlFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram").replace(".xlsx", ".html"))
523        self.sramTableHtmlFilePath = os.path.join(self.sramTableDir, self.sramTableHtmlFileName)
524        # * create html file in dir sramTables
525        self._sramTable.to_html(self.sramTableHtmlFilePath, index=True, header=True, justify="center", classes="table table-stripped")
526        logging.info("Created SRAM table HTML file: %s", self.sramTableHtmlFilePath)
527        print("Created SRAM table HTML file: %s", self.sramTableHtmlFilePath)
528        return self.sramTableHtmlFilePath

Generates an SRAM table map in HTML format.

Returns

absolute path of the SRAM table map .html file.

def writeSRAMtoJson(self):
530    def writeSRAMtoJson(self):
531        """
532        Generates an SRAM table map in JSON format.
533
534        :return str: absolute path of the SRAM table map `.json` file.
535        """
536        # * create sram table file path and name
537        self.sramTableJsonFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram").replace(".xlsx", ".json"))
538        self.sramTableJsonFilePath = os.path.join(self.sramTableDir, self.sramTableJsonFileName)
539        # * create json file in dir sramTables
540        self._sramTable.to_json(self.sramTableJsonFilePath, orient="index", indent=4)
541        logging.info("Created SRAM table JSON file: %s", self.sramTableJsonFilePath)
542        print("Created SRAM table JSON file: %s", self.sramTableJsonFilePath)
543        return self.sramTableJsonFilePath

Generates an SRAM table map in JSON format.

Returns

absolute path of the SRAM table map .json file.

def writeSRAMtoTxt(self):
545    def writeSRAMtoTxt(self):
546        """
547        Generates an SRAM table map in TXT format.
548
549        :return str: absolute path of the SRAM table map `.txt` file.
550        """
551        # * create sram table file path and name
552        self.sramTableTxtFileName = os.path.basename(self.tcamTableXlsxFileName.replace("tcam", "sram").replace(".xlsx", ".txt"))
553        self.sramTableTxtFilePath = os.path.join(self.sramTableDir, self.sramTableTxtFileName)
554        # * create txt file in dir sramTables
555        myTable = tabulate(self._sramTable, headers="keys", showindex=True, disable_numparse=True, tablefmt="github")
556        with open(self.sramTableTxtFilePath, "w", encoding="utf-8") as file:
557            file.write(myTable)
558        logging.info("Created SRAM table Txt file:  %s", self.sramTableTxtFilePath)
559        print("Created SRAM table Txt file:  %s", self.sramTableTxtFilePath)
560        return self.sramTableTxtFilePath

Generates an SRAM table map in TXT format.

Returns

absolute path of the SRAM table map .txt file.

def printVerbose(verbose, msg):
568def printVerbose(verbose, msg):
569    """
570    Prints a string if verbose flag is active.
571
572    :param int verbose: print information in verbose mode.
573    :param str msg: Message to be printed in verbose mode.
574    """
575    if verbose:
576        print(str(msg))

Prints a string if verbose flag is active.

Parameters
  • int verbose: print information in verbose mode.
  • str msg: Message to be printed in verbose mode.
def printDebug(debug, msg):
579def printDebug(debug, msg):
580    """
581    Prints a string if debug flag is active.
582
583    :param int debug: print information in debug mode.
584    :param str msg: Message to be printed in debug mode.
585    """
586    if debug:
587        print(str(msg))

Prints a string if debug flag is active.

Parameters
  • int debug: print information in debug mode.
  • str msg: Message to be printed in debug mode.
def highlightCell(val):
590def highlightCell(val):
591    """
592    Colors SRAM table map cells in XLSX file depending upon their value.
593
594    :param int val: numerical value of a particular cell.
595    :return str: cell background color code as a hex RBG value.
596    """
597    if val == 1:
598        color = "#E5961A"
599    elif val == 0:
600        color = "#E4EA15"
601    else:
602        color = "#D8C05A"
603    return f"background-color: {color}"

Colors SRAM table map cells in XLSX file depending upon their value.

Parameters
  • int val: numerical value of a particular cell.
Returns

cell background color code as a hex RBG value.