Source code for frontend.verilog.modules.ports

#!/usr/bin/env python
# -*- encoding=utf8 -*-

"""
Author: Hanyu Wang
Created time: 2024-06-25 21:29:47
Last Modified by: Hanyu Wang
Last Modified time: 2024-06-25 23:58:04
"""

from enum import Enum, auto
from .dfg import *


class PortDirection(Enum):
    INPUT = "input"
    OUTPUT = "output"
    INOUT = "inout"

    @staticmethod
    def fromString(direction: str):
        if direction == "input":
            return PortDirection.INPUT
        elif direction == "output":
            return PortDirection.OUTPUT
        elif direction == "inout":
            return PortDirection.INOUT
        else:
            return None

    @staticmethod
    def toString(direction: "PortDirection"):
        return direction.value.lower() if direction is not None else None


class PortType(Enum):
    WIRE = "wire"
    REG = "reg"
    INTEGER = "integer"
    REAL = "real"
    TIME = "time"
    PARAMETER = "parameter"
    LOCALPARAM = "localparam"

    @staticmethod
    def fromString(type: str):
        if type == "wire":
            return PortType.WIRE
        elif type == "reg":
            return PortType.REG
        elif type == "integer":
            return PortType.INTEGER
        elif type == "real":
            return PortType.REAL
        elif type == "time":
            return PortType.TIME
        elif type == "parameter":
            return PortType.PARAMETER
        elif type == "localparam":
            return PortType.LOCALPARAM
        else:
            return None

    @staticmethod
    def toString(type: "PortType"):
        return type.value if type is not None else None


[docs]class Port: def __init__( self, name: str, ): self.name = name self.range = None self.direction = None self.type = None def setRange(self, range: tuple): if self.range is None and range is not None: self.range = range return True return False def setHeader(self, header: tuple): direction, type = header return self.setDirection(direction) and self.setType(type) def setDirection(self, direction: PortDirection): if self.direction is None and direction is not None: assert isinstance(direction, PortDirection) self.direction = direction return True return False def setType(self, type: str): if self.type is None and type is not None: assert isinstance(type, PortType) self.type = type return True return False def setAll(self, direction: PortDirection, type: str, range: tuple): return ( self.setDirection(direction) and self.setType(type) and self.setRange(range) ) def getType(self): return self.type def getPortName(self): return self.name def getRange(self): return self.range def getHeader(self): return (self.direction, self.type) def __repr__(self): direction_str = ( "(" + self.direction.value + ")" if self.direction is not None else "" ) return f"Port({self.name} {direction_str})"
def portToString(port: Port): portDirString = "" if port.direction is not None: portDirString = PortDirection.toString(port.direction) + " " typeString = port.type + " " if port.type is not None else "" # range is optional, the space is to be consistent with the space in the middle rangeString = f"{rangeToString(port.range)} " if port.range is not None else " " return f"{portDirString}{typeString}{rangeString}{port.name}" class BasicPort(Port): def __init__( self, name: str, direction: PortDirection, type: str = "wire", range: tuple = None, ): super().__init__(name) self.setDirection(direction) self.setType(type) self.setRange(range) class OutputPort(BasicPort): def __init__( self, name: str, type: str = "wire", range: tuple = None, ): super().__init__(name, PortDirection.OUTPUT, type, range) class InputPort(BasicPort): def __init__( self, name: str, type: str = "wire", range: tuple = None, ): super().__init__(name, PortDirection.INPUT, type, range) class Frame: def __init__(self) -> None: self.portDefs = {} self.ioPorts = set() def addPort(self, port: Port): name = port.getPortName() if name in self.portDefs: self.portDefs[name].setRange(port.getRange()) self.portDefs[name].setHeader(port.getHeader()) else: self.portDefs[name] = port if port.direction is not None: self.ioPorts.add(name) def addPorts(self, ports: list): for port in ports: self.addPort(port) def getIOs(self) -> set: return self.ioPorts def getPorts(self) -> dict: return self.portDefs def getPortNames(self) -> list: return list(self.portDefs.keys()) def getPort(self, portName: str): return self.portDefs[portName] def getVariableType(self, variableName: str): return self.portDefs[variableName].getType() def getPortsByType(self, portType: PortDirection): return [ port.name for port in self.portDefs.values() if port.direction == portType ] @property def numInputs(self) -> int: return len(self.getPortsByType(PortDirection.INPUT)) @property def numOutputs(self) -> int: return len(self.getPortsByType(PortDirection.OUTPUT)) @property def numInouts(self) -> int: return len(self.getPortsByType(PortDirection.INOUT))