Source code for FABulous.fabric_generator.gen_fabric.gen_helper

"""Helper functions for FPGA fabric generation.

This module provides utility functions that assist in various aspects of FPGA fabric
generation, including switch matrix bootstrapping, signal ordering, and file generation
utilities. These functions support the main fabric generation workflow by providing
common operations needed across multiple generation stages.
"""

import csv
import re
from pathlib import Path

from loguru import logger

from FABulous.fabric_definition.define import Direction
from FABulous.fabric_definition.Tile import Tile
from FABulous.fabric_generator.parser.parse_switchmatrix import parseList


[docs] def bootstrapSwitchMatrix(tile: Tile, outputDir: Path) -> None: """Generate a blank switch matrix CSV file for the given tile. The top left corner will contain the name of the tile. Columns are the source signals and rows are the destination signals. The order of the signal will be: - standard wire - BEL signal with prefix - GEN_IO signals with prefix - jump wire The order is important as this order will be used during switch matrix generation. Parameters ---------- tile : Tile The tile to generate the switch matrix for outputDir : str The output directory to write the switch matrix to """ logger.info(f"Generate matrix csv for {tile.name} # filename: {outputDir}") with outputDir.open("w") as f: writer = csv.writer(f) sourceName, destName = [], [] # normal wire for i in tile.portsInfo: if i.wireDirection != Direction.JUMP: portInput, portOutput = i.expandPortInfo("AutoSwitchMatrix") sourceName += portInput destName += portOutput # bel wire for b in tile.bels: for p in b.inputs: sourceName.append(f"{p}") for p in b.outputs + b.externalOutput: destName.append(f"{p}") # jump wire for i in tile.portsInfo: if i.wireDirection == Direction.JUMP: portInput, portOutput = i.expandPortInfo("AutoSwitchMatrix") sourceName += portInput destName += portOutput sourceName = list(dict.fromkeys(sourceName)) destName = list(dict.fromkeys(destName)) writer.writerow([tile.name] + destName) for p in sourceName: writer.writerow([p] + [0] * len(destName))
[docs] def list2CSV(InFileName: Path, OutFileName: Path) -> None: """Export a list file into its equivalent CSV switch matrix representation. A comment will be appended to the end of the column and row of the matrix, which will indicate the number of signals in a given row. Parameters ---------- InFileName : str The input file name of the list file OutFileName : str The directory of the CSV file to be written Raises ------ ValueError If the list file contains signals that are not in the matrix file """ logger.info(f"Adding {InFileName} to {OutFileName}") connectionPair = parseList(InFileName) with Path(OutFileName).open() as f: file = f.read() file = re.sub(r"#.*", "", file) file = file.split("\n") col = len(file[0].split(",")) rows = len(file) # create a 0 zero matrix as initialization matrix = [[0 for _ in range(col)] for _ in range(rows)] # load the data from the original csv into the matrix for i in range(1, len(file)): for j in range(1, len(file[i].split(","))): value = file[i].split(",")[j] if value == "": continue matrix[i - 1][j - 1] = int(value) # get source and destination list in the csv destination = file[0].strip("\n").split(",")[1:] source = [file[i].split(",")[0] for i in range(1, len(file))] # set the matrix value with the provided connection pair for s, d in connectionPair: try: s_index = source.index(s) except ValueError: logger.critical(f"{s} is not in the source column of the matrix csv file") exit(-1) try: d_index = destination.index(d) except ValueError: logger.critical(f"{d} is not in the destination row of the matrix csv file") exit(-1) if matrix[s_index][d_index] != 0: logger.warning( f"Connection ({s}, {d}) already exists in the original matrix" ) matrix[s_index][d_index] = 1 # writing the matrix back to the given out file with Path(OutFileName).open("w") as f: f.write(file[0] + "\n") for i in range(len(source)): f.write(f"{source[i]},") for j in range(len(destination)): f.write(str(matrix[i][j])) if j != len(destination) - 1: f.write(",") else: f.write(f",#,{matrix[i].count(1)}") f.write("\n") colCount = [] for j in range(col): count = 0 for i in range(rows): if matrix[i][j] == 1: count += 1 colCount.append(str(count)) f.write(f"#,{','.join(colCount)}")
[docs] def CSV2list(InFileName: str, OutFileName: str) -> None: """Export a CSV switch matrix description into its equivalent list representation. Parameters ---------- InFileName : str The input file name of the CSV file OutFileName : str The directory of the list file to be written """ with Path(InFileName).open() as f: inFile = f.readlines() InFile = [i.strip("\n").split(",") for i in inFile] with Path(OutFileName).open("w") as f: # get the number of tiles in horizontal direction cols = len(InFile[0]) # top-left should be the name _ = f.write(f"# {InFile[0][0]}\n") # switch matrix inputs inputs = [] for item in InFile[0][1:]: inputs.append(item) # beginning from the second line, write out the list for line in InFile[1:]: for i in range(1, cols): if line[i] != "0": # it is [i-1] because the beginning of the line is the # destination port _ = f.write(f"{line[0]},{inputs[i - 1]}")