Source code for util.initial_placement

"""
====================
OpenFPGA Floorplaner
====================

This is dedicated OpenFPGA floorplaner which shape tiles in traditional structure
as shown below. This placement class is not dependent iupon the architecture and always
applied to homogeneous structure.

There are total two ways

.. toctree::
   :maxdepth: 2

   self

Paramater Based (*Preferred*):
------------------------------

Following figure details the various paramteres referred in this type of floorplanning

.. rst-class:: ascii

::


                  |<---------  GRID_X  --------->|
                  |                              |
        ┌───────────┐┌─────────────┐┌──────────────┐┌─────────────┐┌───────────┐  ∧
        │           ││   CBX_TOP   ││              ││             ││           │  |
        │           ││   _WIDTH    ││              ││             ││           │  | CBX_TOP_HEIGHT
        │        ┌──┘└─────────────┘└──┐        ┌──┘└─────────────┘└──┐        │  ⩒ 
        │        │┌───────────────────┐│        │┌───────────────────┐│        │
        └────────┘│   GRID_CLB_RATIO  │└────────┘│                   │└────────┘
        ┌────────┐│       W/H         │┌────────┐│                   │┌────────┐
        │        ││                   ││        ││                   ││        │
        │  CBY_  ││                   ││   CB_  ││                   ││  CBY_  │
        │  LEFT_ ││                   ││ HEIGHT ││                   ││ RIGHT_ │
        │ HEIGHT ││                   ││ _RATIO ││                   ││ HEIGHT │
        │        ││                   ││        ││                   ││        │
        └────────┘│                   │└────────┘│                   │└────────┘
        ┌────────┐│                   │┌────────┐│                   │┌────────┐
    ↑   │        │└───────────────────┘│        │└───────────────────┘│        │
    |   │        └──┐┌─────────────┐┌──┘        └──┐┌─────────────┐┌──┘        │
    |   │           ││  CB_WIDTH_  ││              ││             ││           │  FPGA_SIZE[0],y
    |   │           ││    RATIO    ││              ││             ││           │
    G   │        ┌──┘└─────────────┘└──┐        ┌──┘└─────────────┘└──┐        │
    R   │        │┌───────────────────┐│        │┌───────────────────┐│        │
    I   └────────┘│                   │└────────┘│                   │└────────┘
    D   ┌────────┐│                   │┌────────┐│                   │┌────────┐
    _   │        ││                   ││        ││                   ││        │
    Y   │        ││                   ││        ││                   ││        │
    |   │        ││                   ││        ││                   ││        │
    |   │        ││                   ││        ││                   ││        │
    |   │        ││                   ││        ││                   ││        │
    |   └────────┘│                   │└────────┘│                   │└────────┘
    |   ┌────────┐│                   │┌────────┐│                   │┌────────┐
    ↓   │        │└───────────────────┘│        │└───────────────────┘│        │
        │        └──┐┌─────────────┐┌──┘        └──┐┌─────────────┐┌──┘        │  ∧
        │           ││ CBX_BOTTOM_ ││              ││             ││           │  |
        │           ││   _WIDTH    ││              ││             ││           │  | CBX_BOTTOM_HEIGHT
        └───────────┘└─────────────┘└──────────────┘└─────────────┘└───────────┘  ⩒
        <----------->                                               <--------->
        CBY_LEFT_WIDTH                                           CBY_RIGHT_WIDTH


**Area Based**:

- ``OVERALL_UTILIZATION``
- ``GRID_CLB_UTILIZATION``
- ``SB_UTILIZATION``


**Common Parameters** (All of them are absolute numbers in multiple of *SC_HEIGHT* or *CPP*)

- ``GRID_CLB_CHAN_X`` and ``GRID_CLB_CHAN_Y``: Grid CLB margins
- ``CBx_CHAN_X`` and ``CBx_CHAN_Y`` : Connection box X margins
- ``CBy_CHAN_X`` and ``CBy_CHAN_Y`` : Connection box Y margins
- ``GPIO_CHAN_X`` and ``GPIO_CHAN_Y``: GPIO cell margins


**Absolute Numbers** (In multiple of *SC_HEIGHT* or *CPP*)

* ``GRID_X``
* ``GRID_Y``
* ``CLB_W``
* ``CLB_H``
* ``CBX_WIDTH``
* ``CBY_HEIGHT``
* ``LEFT_CBY_WIDTH``
* ``LEFT_CBY_HEIGHT``
* ``RIGHT_CBY_WIDTH``
* ``RIGHT_CBY_HEIGHT``
* ``TOP_CBX_WIDTH``
* ``TOP_CBX_HEIGHT``
* ``BOTTOM_CBX_WIDTH``
* ``BOTTOM_CBX_HEIGHT``


Utilization Based
-----------------

**Ideas**:

* Optionally provide a method to apply shaping and placement to the netlist elements

"""


import logging
import math
import os
import json
import pandas as pd
from pprint import pformat, pprint
from spydrnet_physical.util.shell import launch_shell

import yaml
from spydrnet_physical.util import OpenFPGA_Placement_Generator, FPGAGridGen

logger = logging.getLogger('spydrnet_logs')

AREA, WIDTH, HEIGHT = 0, 1, 2
CPP = 4
SCALE = 100
SC_HEIGHT = 4


[docs]class initial_placement(OpenFPGA_Placement_Generator): CPP = 2 """int: ``Contated-poly-pitch`` (`default`=2) """ SC_HEIGHT = 10 """int: ``Standard cell height`` (`default`=10) """ SCALE = 100 """int: Module level variable documented inline. (`default`=100) """ # TODO: Check if its correct PlacementDB = [] """list: Stores list of modules i uppose""" # TODO: Store paramters for each module PlacementDBKey = {} """dict: Module level variable documented inline. (`default`=100) """
[docs] def __init__(self, grid, netlist, fpga_grid: FPGAGridGen, debug=False, areaFile=None, padFile=None, gridIO=False, shapingConf=None): super().__init__(grid, netlist, None) self.sizeX = grid[0] self.sizeY = grid[1] self.GPIOPlacmentKey = [] self.fpga_grid = fpga_grid self.debug = debug self.get_default_configuration() self.areaFile = areaFile self.padFile = padFile self.gridIO = gridIO self.PadNames = {} self.skipChannels = False # Color Setting self.CLB_COLOR = "#f4f0e6" self.CBX_COLOR = "#d9d9f3" self.CBY_COLOR = "#a8d0db" self.SB_COLOR = "#ceefe4" self.PAD_COLOR = "#204969" self.GRID_IO_COLOR = "#ff8000" # Pads Related self.pad_w = 80 self.pad_h = 10 self.SC_GRID = self.SC_HEIGHT*self.CPP if shapingConf: self.update_configuration(shapingConf)
[docs] def create_placement(self): """ Overrides the base method to create placement information """ if not self.PlacementDB: self.ComputeGrid(skipChannels=False) self.CreateDatabase() visited = [] for instance_name, instance_info in self.PlacementDBKey.items(): bbox = instance_info["bbox"] try: instance = next(self._top_module.get_instances(instance_name)) except StopIteration: logger.warning(instance_name + " not found") continue module = instance.reference if len(instance_info["shape"]) == 1: if not module.name in visited: llx, lly, w, h = instance_info["shape"][0] module.properties["SHAPE"] = "rect" module.properties["WIDTH"] = float(w)*CPP module.properties["HEIGHT"] = float(h)*SC_HEIGHT instance.properties["LOC_X"] = bbox[0]*CPP instance.properties["LOC_Y"] = bbox[1]*SC_HEIGHT elif len(instance_info["shape"]) == 2: if not module.name in visited: module.properties["SHAPE"] = "cross" list_a = instance_info["dims"] list_b = [SC_HEIGHT, CPP, SC_HEIGHT, CPP, CPP, SC_HEIGHT] module.properties["POINTS"] = \ [a*b for a, b in zip(list_a, list_b)] instance.properties["LOC_X"] = bbox[0]*CPP instance.properties["LOC_Y"] = bbox[1]*SC_HEIGHT else: if not module.name in visited: w, h = bbox[2]-bbox[0], bbox[3]-bbox[1] module.properties["WIDTH"] = float(w)*CPP module.properties["HEIGHT"] = float(h)*SC_HEIGHT instance.properties["LOC_X"] = bbox[0]*CPP instance.properties["LOC_Y"] = bbox[1]*SC_HEIGHT self._top_module.properties["WIDTH"] = 500*CPP self._top_module.properties["HEIGHT"] = 500*SC_HEIGHT
[docs] def update_configuration(self, shapingConf): ''' Overwrite default configuration variables ''' new_values = None if isinstance(shapingConf, dict): new_values = shapingConf elif isinstance(shapingConf, str): if ".yml" in shapingConf: with open(shapingConf, "r") as file: new_values = yaml.load( file, Loader=yaml.FullLoader).items() elif ".json" in shapingConf: with open(shapingConf, "r") as file: new_values = json.load(file).items() if not new_values: Exception("wrogn shaping configuration") for eachKey, eachValue in new_values: setattr(self, eachKey, eachValue) logger.debug(f"Updated {eachKey} -> {eachValue}")
def get_default_configuration(self): # Grid clb shape self.SC_RATIO = 1 # This is SC_HEIGHT/CPP of stadard cell self.GRID_CLB_RATIO = 1 # This is actual dimension of the CLB unit width/height # Connection box size self.GRID_RATIO_X, self.GRID_RATIO_Y = 1.5, 1.5 self.CBX_WIDTH_RATIO, self.CBY_HEIGHT_RATIO = 0.75, 0.75 # Channel spacing between blocks self.CLB_CHAN_T, self.CLB_CHAN_B = 0, 0 self.CLB_CHAN_L, self.CLB_CHAN_R = 0, 0 self.CBX_CHAN_T, self.CBX_CHAN_B = 0, 0 self.CBX_CHAN_L, self.CBX_CHAN_R = 0, 0 self.CBY_CHAN_T, self.CBY_CHAN_B = 0, 0 self.CBY_CHAN_L, self.CBY_CHAN_R = 0, 0 self.gridIO_MT, self.gridIO_MB = 1, 1 self.gridIO_ML, self.gridIO_MR = 2, 2 self.gridIO_HT, self.gridIO_HB = 10, 10 self.gridIO_WL, self.gridIO_WR = 10, 10 self.GRID_IOV_H_RATIO = 1 self.GRID_IOH_W_RATIO = 1 # TODO: Deprecate this self.GPIO_CHAN_X, self.GPIO_CHAN_Y = 0, 0 self.GPIO_WIDTH, self.GPIO_HEIGHT = 40, 8 def get_variables(self): return { "CLB_COLOR": self.CLB_COLOR, "CBX_COLOR": self.CBX_COLOR, "CBY_COLOR": self.CBY_COLOR, "SB_COLOR": self.SB_COLOR, "PAD_COLOR": self.PAD_COLOR, "GRID_IO_COLOR": self.GRID_IO_COLOR, "CORE_BBOX": (0, 0, int(self.CLB_GRID_X*(self.sizeX+1)), int(self.CLB_GRID_Y*(self.sizeY+1))) } def figSize(self): size = (4+(1*self.sizeX), 4+(1*self.sizeY)) if self.sizeX < 16: dpi = 300 elif self.sizeX < 64: dpi = 100 else: dpi = 50 return {"size": size, "dpi": dpi} def snapDims(self, num, dim=2): return int(math.ceil(num/dim)*dim) def ComputeGrid(self, skipChannels=False): self.skipChannels = skipChannels self.CLB_DIM = [2500, 24*8, 24] self.CB_DIM = [2500*0.6, 0, 0] if self.areaFile: if isinstance(self.areaFile, str): BlockArea = {} for eachLine in open(self.areaFile, "r"): module, dims = eachLine.split(" ", 1) BlockArea[module] = list(map(float, list(dims.split()))) if isinstance(self.areaFile, dict): BlockArea = self.areaFile self.CLB_DIM = BlockArea["grid_clb"] self.CB_DIM = BlockArea["cbx_1__1_"] # Snap CLB Height and Width to next Multiple of 2 self.CLB_UNIT = math.sqrt( self.CLB_DIM[AREA]/(self.GRID_CLB_RATIO*self.SC_RATIO)) self.CLB_H = self.snapDims(self.CLB_UNIT, 2) self.CLB_W = self.snapDims(self.CLB_DIM[AREA]/self.CLB_H, 2) self.CLB_GRID_X = self.snapDims(self.CLB_W*self.GRID_RATIO_X, 2) self.CLB_GRID_Y = self.snapDims(self.CLB_H*self.GRID_RATIO_Y, 2) self.CBX_W = self.snapDims(self.CLB_W*self.CBX_WIDTH_RATIO, 2) self.CBX_H = self.CLB_GRID_Y-self.CLB_H self.CBY_W = self.CLB_GRID_X-self.CLB_W self.CBY_H = self.snapDims(self.CLB_H*self.CBY_HEIGHT_RATIO, 2) self.SB_W = self.CLB_GRID_X - self.CBX_W self.SB_H = self.CLB_GRID_Y - self.CBY_H self.SIDE_X = self.CLB_GRID_X - self.CLB_W self.SIDE_Y = self.CLB_GRID_Y - self.CLB_H self.GRID_IOV_H = self.CLB_H*self.GRID_IOV_H_RATIO self.GRID_IOH_W = self.CLB_W*self.GRID_IOH_W_RATIO if self.debug: print(f"self.CLB_W {self.CLB_W}") print(f"self.CLB_H {self.CLB_H}") print(f"self.CLB_GRID_X {self.CLB_GRID_X}") print(f"self.CLB_GRID_Y {self.CLB_GRID_Y}") print(f"self.CBX_W {self.CBX_W}") print(f"self.CBX_H {self.CBX_H}") print(f"self.CBY_W {self.CBY_W}") print(f"self.CBY_H {self.CBY_H}") print(f"self.SB_W {self.SB_W}") print(f"self.SB_H {self.SB_H}") if self.padFile: if os.path.exists(self.padFile): print(f"Found PinMapFile {self.padFile}") df_pinMap = pd.read_csv(self.padFile) df_pinMap.rename(columns=lambda x: x.strip(), inplace=True) self.PadNames["L"] = df_pinMap["Remark"] self.PadNames["T"] = df_pinMap["Remark.1"] self.PadNames["R"] = df_pinMap["Remark.2"] self.PadNames["B"] = df_pinMap["Remark.3"] self.NumOfPads = len(df_pinMap.index) def CreateDatabase(self): # Create Blocks for x in range(self.sizeX+1): for y in range(self.sizeY+1): self.add_sb(x, y) if x < self.sizeY: self.add_cbx(x, y) if y < self.sizeX: self.add_cby(x, y) if (x < self.sizeX) and (y < self.sizeY): self.add_clb(x, y) # Create gridIOs if self.gridIO: if (y == self.sizeY) and (x < self.sizeX): self.add_gridIOH(x, y, side="top") if (y == 0) and (x < self.sizeX): self.add_gridIOH(x, y, side="bottom") if (x == 0) and (y < self.sizeY): self.add_gridIOV(x, y, side="left") if (x == self.sizeX) and (y < self.sizeY): self.add_gridIOV(x, y, side="right") # Create Pins if self.PadNames: for side in ["L", "T", "R", "B"]: for i in range(self.NumOfPads): self.add_pad(side, i, self.PadNames[side][i]) return self.PlacementDB def add_clb(self, xi, yi, lbl='grid_clb', shortlabel='LB'): x, y = (xi+1)*self.CLB_GRID_X, (yi+1)*self.CLB_GRID_Y llx = x-self.snapDims(self.CLB_W*0.5) lly = y-self.snapDims(self.CLB_H*0.5) W1 = self.CLB_W H1 = self.CLB_H initShape = [(llx, lly, W1, H1)] if not self.skipChannels: llx += self.CLB_CHAN_L lly += self.CLB_CHAN_B W1 = self.CLB_W-self.CLB_CHAN_L-self.CLB_CHAN_R H1 = self.CLB_H-self.CLB_CHAN_T-self.CLB_CHAN_B block_name = f"{lbl}_{xi+1}__{yi+1}_" short_block_name = f"{shortlabel}_{xi+1}_{yi+1}" COLOR = self.CLB_COLOR points = [0, 0, 0, self.CLB_H, self.CLB_W, self.CLB_H, self.CLB_W, 0] self.PlacementDB.append(block_name) data = {"name": block_name, "short_name": short_block_name, "bbox": [llx, lly, llx+W1, lly+H1], "points": points, "module": "grid_clb_1__1_", "center": [x, y], "color": COLOR, "shape": [(llx, lly, W1, H1)], "initShape": initShape, "xi": xi, "yi": yi} self.PlacementDBKey[block_name] = data return data def add_cbx(self, xi, yi, lbl=None): x, y = (xi+1)*self.CLB_GRID_X, (yi+1)*self.CLB_GRID_Y llx = x-self.snapDims((self.CBX_W)*0.5) lly = y-self.snapDims((self.CLB_H*0.5)+self.CBX_H) W1 = self.CBX_W H1 = self.CBX_H initShape = [(llx, lly, W1, H1)] if not self.skipChannels: llx += self.CBX_CHAN_L lly += self.CBX_CHAN_B W1 = self.CBX_W-self.CBX_CHAN_L-self.CBX_CHAN_R H1 = self.CBX_H-self.CBX_CHAN_T-self.CBX_CHAN_B block_name = f"cbx_{xi+1}__{yi}_" short_block_name = f"CX_{xi+1}_{yi}" points = [0, 0, 0, W1, H1, W1, H1, 0] self.PlacementDB.append(block_name) moduleName = "cbx_1__0_" if yi == 0 else "cbx_1__2_" if yi == self.sizeY else "cbx_1__1_" self.PlacementDBKey[block_name] = {"name": block_name, "short_name": short_block_name, "bbox": [llx, lly, llx+W1, lly+H1], "points": points, "center": [llx+W1*0.5, lly+H1*0.5], "module": moduleName, "color": self.CBX_COLOR, "shape": [(llx, lly, W1, H1)], "initShape": initShape, "xi": xi, "yi": yi} def add_cby(self, xi, yi, lbl=None): x, y = (xi+1)*self.CLB_GRID_X, (yi+1)*self.CLB_GRID_Y - 1 llx = x-self.snapDims((self.CLB_W*0.5)+self.CBY_W) lly = y-self.snapDims(self.CBY_H)*0.5 W1 = self.CBY_W H1 = self.CBY_H initShape = [(llx, lly, W1, H1)] if not self.skipChannels: llx += self.CBY_CHAN_L lly += self.CBY_CHAN_B W1 = self.CBY_W-self.CBY_CHAN_L-self.CBY_CHAN_R H1 = self.CBY_H-self.CBY_CHAN_T-self.CBY_CHAN_B block_name = f"cby_{xi}__{yi+1}_" short_block_name = f"CY_{xi}_{yi+1}" points = [0, 0, 0, W1, H1, W1, H1, 0] self.PlacementDB.append(block_name) moduleName = "cby_0__1_" if xi == 0 else "cby_2__1_" if xi == self.sizeY else "cby_1__1_" self.PlacementDBKey[block_name] = {"name": block_name, "short_name": short_block_name, "bbox": [llx, lly, llx+W1, lly+H1], "points": points, "center": [llx+W1*0.5, lly+H1*0.5], "module": moduleName, "color": self.CBY_COLOR, "shape": [(llx, lly, W1, H1)], "initShape": initShape, "xi": xi, "yi": yi} def get_stype(self, x, y): if x == 0: if y == 0: return 1 elif y == self.sizeX: return 3 else: return 2 elif x == self.sizeY: if y == 0: return 7 elif y == self.sizeX: return 5 else: return 6 else: if y == 0: return 8 elif y == self.sizeX: return 4 else: return 0 def unique(self, sequence): seen = set() u = [x for x in sequence if not (x in seen or seen.add(x))] return [val for sublist in u for val in sublist]
[docs] def add_sb(self, xi, yi): ''' Adds switch-blocks in the placement database .. rst-class:: ascii :: d +----+ c | | b | | e +----+ +----+ a | | Cross Shape | | -lengths {a b c d e f} +----+ +----+ | | | | f +----+ ''' x = xi*self.CLB_GRID_X - 1 y = yi*self.CLB_GRID_Y - 1 llxB1 = x+(self.CLB_W*0.5) llyB1 = y+(self.CBY_H*0.5) WidthB1 = self.SIDE_X HeightB1 = self.SB_H llxB2 = x + (self.CBX_W*0.5) llyB2 = y + (self.CLB_H*0.5) WidthB2 = self.SB_W HeightB2 = self.SIDE_Y a = self.SIDE_Y b = e = (WidthB2-self.SIDE_X)*0.5 c = f = (HeightB1-self.SIDE_Y)*0.5 d = self.SIDE_X Stype = self.get_stype(xi, yi) if Stype == 1: # SB_0__0_ llyB1 += c HeightB1 += -c llxB2 += b WidthB2 += -b b = f = 0 elif Stype == 2: # SB_0__1_ llxB2 += b WidthB2 -= b b = 0 elif Stype == 3: # SB_0__2_ llxB2 += b WidthB2 -= b HeightB1 -= f c = b = 0 elif Stype == 4: # SB_1__2_ HeightB1 -= c c = 0 elif Stype == 5: # SB_2__2_ HeightB1 -= c WidthB2 -= e c = e = 0 elif Stype == 6: # SB_2__1_ WidthB2 -= e e = 0 elif Stype == 7: # SB_2__0_ llyB1 += f HeightB1 -= f WidthB2 -= e e = f = 0 elif Stype == 8: # SB_1__0_ llyB1 += f HeightB1 -= f f = 0 block_name = f"sb_{xi}__{yi}_" short_block_name = f"SB_{xi}_{yi}" initShape = [(llxB1, llyB1, WidthB1, HeightB1), (llxB2, llyB2, WidthB2, HeightB2)] points = self.unique([(b, 0), (b, f), (0, f), (0, (f+a)), (b, (f+a)), (b, (a+c+f)), ((b+d), (a+c+f)), ((b+d), (a+f)), ((b+d+e), (a+f)), ((b+d+e), f), ((b+d), f), ((b+d), 0)]) self.PlacementDB.append(block_name) moduleNames = [ "sb_1__1_", "sb_0__0_", "sb_0__1_", "sb_0__2_", "sb_1__2_", "sb_2__2_", "sb_2__1_", "sb_2__0_", "sb_1__0_", ] llx = min([i[0] for i in initShape]) lly = min([i[1] for i in initShape]) self.PlacementDBKey[block_name] = {"name": block_name, "short_name": short_block_name, "bbox": [llx, lly, llx+f+a+c, lly+b+d+e], "points": points, "center": [llx+(WidthB1*0.5)+b, lly+(HeightB2*0.5)+f], "module": moduleNames[Stype], "color": self.SB_COLOR, "shape": initShape, "xi": xi, "yi": yi, "dims": [a, b, c, d, e, f], "initShape": initShape}
def add_gridIOH(self, xi, yi, side, lbl=None): x, y = (xi+1)*self.CLB_GRID_X, (yi+1)*self.CLB_GRID_Y llx = x-self.snapDims((self.GRID_IOH_W)*0.5) lly = y-self.snapDims((self.CLB_H*0.5)+self.CBX_H) lly += (-1*self.gridIO_HB) if side == "bottom" else self.CBX_H W1 = self.GRID_IOH_W H1 = self.gridIO_HB initShape = [(llx, lly, W1, H1)] if not self.skipChannels: llx += self.CBX_CHAN_L lly += 0 if side == "bottom" else self.gridIO_MT W1 = self.GRID_IOH_W-self.CBX_CHAN_L-self.CBX_CHAN_R H1 = self.gridIO_HB-self.gridIO_MB if side == "bottom": moduleName = f"grid_io_{side}" block_name = f"grid_io_{side}_{xi+1}__{yi}_" short_block_name = f"io{side}_{xi+1}_{yi}" else: moduleName = f"grid_io_{side}" block_name = f"grid_io_{side}_{xi+1}__{yi+1}_" short_block_name = f"io{side}_{xi+1}_{yi+1}" points = [0, 0, 0, W1, H1, W1, H1, 0] self.PlacementDB.append(block_name) self.PlacementDBKey[block_name] = {"name": block_name, "short_name": short_block_name, "bbox": [llx, lly, llx+W1, lly+H1], "points": points, "center": [llx+W1*0.5, lly+H1*0.5], "module": moduleName, "color": self.GRID_IO_COLOR, "shape": [(llx, lly, W1, H1)], "initShape": initShape} def add_gridIOV(self, xi, yi, side, lbl=None): x, y = (xi+1)*self.CLB_GRID_X, (yi+1)*self.CLB_GRID_Y llx = x-self.snapDims((self.CLB_W*0.5)+self.CBY_W) lly = y-self.snapDims(self.GRID_IOV_H)*0.5 llx += (-1*(self.gridIO_WL)) if side == "left" else self.CBY_W W1 = self.gridIO_WL H1 = self.GRID_IOV_H initShape = [(llx, lly, W1, H1)] if not self.skipChannels: llx += self.CBY_CHAN_L llx += (-1*self.gridIO_ML) if side == "left" else self.gridIO_MR lly += self.CBY_CHAN_B W1 = self.gridIO_WL-self.gridIO_ML H1 = self.GRID_IOV_H-self.CBY_CHAN_T-self.CBY_CHAN_B if side == "left": moduleName = f"grid_io_{side}" block_name = f"grid_io_{side}_{xi}__{yi+1}_" short_block_name = f"io{side}_{xi}_{yi+1}" else: moduleName = f"grid_io_{side}" block_name = f"grid_io_{side}_{xi+1}__{yi+1}_" short_block_name = f"io{side}_{xi+1}_{yi+1}" points = [0, 0, 0, W1, H1, W1, H1, 0] self.PlacementDB.append(block_name) self.PlacementDBKey[block_name] = {"name": block_name, "short_name": short_block_name, "bbox": [llx, lly, llx+W1, lly+H1], "points": points, "center": [llx+W1*0.5, lly+H1*0.5], "module": moduleName, "color": self.GRID_IO_COLOR, "shape": [(llx, lly, W1, H1)], "initShape": initShape} def add_pad(self, side="L", number=0, padname="xx"): CoreMinX, CoreMinY = (0.5*self.CLB_W), (0.5*self.CLB_H) CoreMaxX, CoreMaxY = (((self.sizeX+0.5) * self.CLB_GRID_X)+0.5*self.CBY_W, ((self.sizeY+0.5) * self.CLB_GRID_Y)+0.5*self.CBX_H) if side in ["L", "R"]: pad_w = self.pad_w pad_h = (((self.CLB_H+self.CBX_H)*self.sizeY+1) + self.CBX_H)/self.NumOfPads shift = (number*pad_h) initialshitX = (self.CLB_GRID_Y - self.CBX_H-(self.CLB_H*0.5)) initialshitY = (self.CLB_GRID_X - self.CBY_W-(self.CLB_W*0.5)) pad_spacing = 24 if side == "L": pad_x = CoreMinX - (pad_w*0.5) - pad_spacing pad_y = initialshitX + shift + pad_h*0.5 pad_llx = pad_x - (pad_w*0.5) pad_lly = pad_y - (pad_h*0.5) pad_w, pad_h = pad_w, pad_h rot = 0 t = 0.5 elif side == "R": pad_x = CoreMaxX + (pad_w*0.5) + pad_spacing pad_y = initialshitX + shift + pad_h*0.5 pad_llx = pad_x - (pad_w*0.5) pad_lly = pad_y - (pad_h*0.5) pad_w, pad_h = pad_w, pad_h rot = 0 t = 0.5 else: pad_w = (((self.CLB_W+self.CBY_W)*self.sizeX+1) + self.CBY_W)/self.NumOfPads pad_h = self.pad_h shift = (number*pad_w) initialshitY = (self.CLB_GRID_X - self.CBY_W-(self.CLB_W*0.5)) pad_spacing = 3 if side == "T": pad_x = initialshitY + shift + pad_w*0.5 pad_y = CoreMaxY + pad_spacing + pad_h*0.5 pad_llx = pad_x - (0.5*pad_w) pad_lly = pad_y - pad_h*0.5 pad_w, pad_h = pad_w, pad_h rot = 90 t = 0.5 elif side == "B": pad_x = initialshitY + shift + pad_w*0.5 pad_y = CoreMinY - pad_spacing - pad_h*0.5 pad_llx = pad_x - (0.5*pad_w) pad_lly = pad_y - pad_h*0.5 pad_w, pad_h = pad_w, pad_h rot = -90 t = 0.5 self.GPIOPlacmentKey.append( { "side": side, "rot": rot, "text": padname.strip(), "shape": [(pad_llx, pad_lly, pad_w, pad_h)], "color": self.PAD_COLOR, "center": [pad_x, pad_y], } )