Skip to content
Snippets Groups Projects
entity.py 2.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • """
    Module for code generation of VHDL entity declarations
    """
    from io import TextIOWrapper
    from typing import Set
    
    from b_asic.codegen.vhdl import VHDL_TAB
    from b_asic.port import Port
    from b_asic.process import MemoryVariable, PlainMemoryVariable
    from b_asic.resources import ProcessCollection
    
    
    
    def write_memory_based_storage(
        f: TextIOWrapper, entity_name: str, collection: ProcessCollection, word_length: int
    
    ):
        # Check that this is a ProcessCollection of (Plain)MemoryVariables
        is_memory_variable = all(
            isinstance(process, MemoryVariable) for process in collection
        )
        is_plain_memory_variable = all(
            isinstance(process, PlainMemoryVariable) for process in collection
        )
        if not (is_memory_variable or is_plain_memory_variable):
            raise ValueError(
                "HDL can only be generated for ProcessCollection of (Plain)MemoryVariables"
            )
    
    
        entity_name = entity_name
    
    
        # Write the entity header
        f.write(f'entity {entity_name} is\n')
    
        f.write(f'{VHDL_TAB}generic(\n')
        f.write(f'{2*VHDL_TAB}-- Data word length\n')
        f.write(f'{2*VHDL_TAB}WL : integer := {word_length}\n')
        f.write(f'{VHDL_TAB});\n')
    
        f.write(f'{VHDL_TAB}port(\n')
    
        # Write the clock and reset signal
    
        f.write(f'{2*VHDL_TAB}-- Clock, synchronous reset and enable signals\n')
    
        f.write(f'{2*VHDL_TAB}clk : in std_logic;\n')
        f.write(f'{2*VHDL_TAB}rst : in std_logic;\n')
        f.write(f'{2*VHDL_TAB}en  : in std_logic;\n')
        f.write(f'\n')
    
        # Write the input port specification
        f.write(f'{2*VHDL_TAB}-- Memory port I/O\n')
        read_ports: set[Port] = set(sum((mv.read_ports for mv in collection), ()))  # type: ignore
        for idx, read_port in enumerate(read_ports):
            port_name = read_port if isinstance(read_port, int) else read_port.name
            port_name = 'p_' + str(port_name) + '_in'
    
            f.write(f'{2*VHDL_TAB}{port_name} : in std_logic_vector(WL-1 downto 0);\n')
    
    
        # Write the output port specification
        write_ports: Set[Port] = {mv.write_port for mv in collection}  # type: ignore
        for idx, write_port in enumerate(write_ports):
            port_name = write_port if isinstance(write_port, int) else write_port.name
            port_name = 'p_' + str(port_name) + '_out'
    
            f.write(f'{2*VHDL_TAB}{port_name} : out std_logic_vector(WL-1 downto 0)')
    
            if idx == len(write_ports) - 1:
                f.write('\n')
            else:
                f.write(';\n')
    
        # Write ending of the port header
        f.write(f'{VHDL_TAB});\n')
        f.write(f'end entity {entity_name};\n\n')
    
    
    
    def write_register_based_storage(
        f: TextIOWrapper, entity_name: str, collection: ProcessCollection, word_length: int
    ):
        write_memory_based_storage(f, entity_name, collection, word_length)