diff --git a/b_asic/architecture.py b/b_asic/architecture.py index d80545435094e4e9cf4812afaacd11a5688b3ded..cd318b29e1b92bc8b5fe6f2037bb5fdead2d42fd 100644 --- a/b_asic/architecture.py +++ b/b_asic/architecture.py @@ -245,9 +245,11 @@ class Architecture(HardwareBlock): Parameters ---------- - processing_elements : :class:`~b_asic.architecture.ProcessingElement` or iterable of :class:`~b_asic.architecture.ProcessingElement` + processing_elements : :class:`~b_asic.architecture.ProcessingElement` or iterable \ +of :class:`~b_asic.architecture.ProcessingElement` The processing elements in the architecture. - memories : :class:`~b_asic.architecture.Memory` or iterable of :class:`~b_asic.architecture.Memory` + memories : :class:`~b_asic.architecture.Memory` or iterable of \ +:class:`~b_asic.architecture.Memory` The memories in the architecture. entity_name : str, default: "arch" Name for the top-level entity. diff --git a/b_asic/codegen/vhdl/architecture.py b/b_asic/codegen/vhdl/architecture.py index d41d76f210e575396687ebfb020889e91707429b..d59386df944d352491f48aa28af527692ad51ee4 100644 --- a/b_asic/codegen/vhdl/architecture.py +++ b/b_asic/codegen/vhdl/architecture.py @@ -11,7 +11,7 @@ if TYPE_CHECKING: from b_asic.resources import ProcessCollection, _ForwardBackwardTable -def write_memory_based_storage( +def memory_based_storage( f: TextIOWrapper, assignment: Set["ProcessCollection"], entity_name: str, @@ -62,41 +62,45 @@ def write_memory_based_storage( # Architecture declerative region begin # vhdl.write(f, 1, '-- HDL memory description') - vhdl.common.write_constant_decl( - f, name='MEM_WL', type='integer', value=word_length, name_pad=12 + vhdl.common.constant_declaration( + f, name='MEM_WL', signal_type='integer', value=word_length, name_pad=12 ) - vhdl.common.write_constant_decl( - f, name='MEM_DEPTH', type='integer', value=mem_depth, name_pad=12 + vhdl.common.constant_declaration( + f, name='MEM_DEPTH', signal_type='integer', value=mem_depth, name_pad=12 ) - vhdl.common.write_type_decl( + vhdl.common.type_declaration( f, 'mem_type', 'array(0 to MEM_DEPTH-1) of std_logic_vector(MEM_WL-1 downto 0)' ) - vhdl.common.write_signal_decl( - f, name='memory', type='mem_type', name_pad=14, vivado_ram_style='distributed' + vhdl.common.signal_decl( + f, + name='memory', + signal_type='mem_type', + name_pad=14, + vivado_ram_style='distributed', ) for i in range(read_ports): - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, f'read_port_{i}', 'std_logic_vector(MEM_WL-1 downto 0)', name_pad=14 ) - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, f'read_adr_{i}', f'integer range 0 to {schedule_time}-1', name_pad=14 ) - vhdl.common.write_signal_decl(f, f'read_en_{i}', 'std_logic', name_pad=14) + vhdl.common.signal_decl(f, f'read_en_{i}', 'std_logic', name_pad=14) for i in range(write_ports): - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, f'write_port_{i}', 'std_logic_vector(MEM_WL-1 downto 0)', name_pad=14 ) - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, f'write_adr_{i}', f'integer range 0 to {schedule_time}-1', name_pad=14 ) - vhdl.common.write_signal_decl(f, f'write_en_{i}', 'std_logic', name_pad=14) + vhdl.common.signal_decl(f, f'write_en_{i}', 'std_logic', name_pad=14) # Schedule time counter vhdl.write(f, 1, '-- Schedule counter', start='\n') - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, name='schedule_cnt', - type=f'integer range 0 to {schedule_time}-1', + signal_type=f'integer range 0 to {schedule_time}-1', name_pad=14, ) @@ -104,7 +108,7 @@ def write_memory_based_storage( if input_sync: vhdl.write(f, 1, '-- Input synchronization', start='\n') for i in range(read_ports): - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, f'p_{i}_in_sync', 'std_logic_vector(WL-1 downto 0)', name_pad=14 ) @@ -113,7 +117,7 @@ def write_memory_based_storage( # vhdl.write(f, 0, 'begin', start='\n', end='\n\n') vhdl.write(f, 1, '-- Schedule counter') - vhdl.common.write_synchronous_process_prologue( + vhdl.common.synchronous_process_prologue( f=f, name='schedule_cnt_proc', clk='clk', @@ -134,7 +138,7 @@ def write_memory_based_storage( (3, 'end if;'), ], ) - vhdl.common.write_synchronous_process_epilogue( + vhdl.common.synchronous_process_epilogue( f=f, name='schedule_cnt_proc', clk='clk', @@ -142,14 +146,14 @@ def write_memory_based_storage( if input_sync: vhdl.write(f, 1, '-- Input synchronization', start='\n') - vhdl.common.write_synchronous_process_prologue( + vhdl.common.synchronous_process_prologue( f=f, name='input_sync_proc', clk='clk', ) for i in range(read_ports): vhdl.write(f, 3, f'p_{i}_in_sync <= p_{i}_in;') - vhdl.common.write_synchronous_process_epilogue( + vhdl.common.synchronous_process_epilogue( f=f, name='input_sync_proc', clk='clk', @@ -157,7 +161,7 @@ def write_memory_based_storage( # Infer memory vhdl.write(f, 1, '-- Memory', start='\n') - vhdl.common.write_asynchronous_read_memory( + vhdl.common.asynchronous_read_memory( f=f, clk='clk', name=f'mem_{0}_proc', @@ -174,11 +178,11 @@ def write_memory_based_storage( # Write address generation vhdl.write(f, 1, '-- Memory write address generation', start='\n') if input_sync: - vhdl.common.write_synchronous_process_prologue( + vhdl.common.synchronous_process_prologue( f, clk="clk", name="mem_write_address_proc" ) else: - vhdl.common.write_process_prologue( + vhdl.common.process_prologue( f, sensitivity_list="schedule_cnt", name="mem_write_address_proc" ) vhdl.write(f, 3, 'case schedule_cnt is') @@ -205,19 +209,17 @@ def write_memory_based_storage( ], ) if input_sync: - vhdl.common.write_synchronous_process_epilogue( + vhdl.common.synchronous_process_epilogue( f, clk="clk", name="mem_write_address_proc" ) else: - vhdl.common.write_process_epilogue( + vhdl.common.process_epilogue( f, sensitivity_list="clk", name="mem_write_address_proc" ) # Read address generation vhdl.write(f, 1, '-- Memory read address generation', start='\n') - vhdl.common.write_synchronous_process_prologue( - f, clk="clk", name="mem_read_address_proc" - ) + vhdl.common.synchronous_process_prologue(f, clk="clk", name="mem_read_address_proc") vhdl.write(f, 3, 'case schedule_cnt is') for i, collection in enumerate(assignment): for mv in collection: @@ -246,9 +248,7 @@ def write_memory_based_storage( (3, 'end case;'), ], ) - vhdl.common.write_synchronous_process_epilogue( - f, clk="clk", name="mem_read_address_proc" - ) + vhdl.common.synchronous_process_epilogue(f, clk="clk", name="mem_read_address_proc") vhdl.write(f, 1, '-- Input and output assignmentn', start='\n') if input_sync: @@ -258,7 +258,7 @@ def write_memory_based_storage( p_zero_exec = filter( lambda p: p.execution_time == 0, (p for pc in assignment for p in pc) ) - vhdl.common.write_synchronous_process_prologue( + vhdl.common.synchronous_process_prologue( f, clk='clk', name='output_reg_proc', @@ -278,7 +278,7 @@ def write_memory_based_storage( (3, 'end case;'), ], ) - vhdl.common.write_synchronous_process_epilogue( + vhdl.common.synchronous_process_epilogue( f, clk='clk', name='output_reg_proc', @@ -286,7 +286,7 @@ def write_memory_based_storage( vhdl.write(f, 0, f'end architecture {architecture_name};', start='\n') -def write_register_based_storage( +def register_based_storage( f: TextIOWrapper, forward_backward_table: "_ForwardBackwardTable", entity_name: str, @@ -332,43 +332,43 @@ def write_register_based_storage( # Schedule time counter vhdl.write(f, 1, '-- Schedule counter') - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, name='schedule_cnt', - type=f'integer range 0 to {schedule_time}-1', + signal_type=f'integer range 0 to {schedule_time}-1', name_pad=18, default_value='0', ) # Shift register vhdl.write(f, 1, '-- Shift register', start='\n') - vhdl.common.write_type_decl( + vhdl.common.type_declaration( f, name='shift_reg_type', alias=f'array(0 to {reg_cnt}-1) of std_logic_vector(WL-1 downto 0)', ) - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, name='shift_reg', - type='shift_reg_type', + signal_type='shift_reg_type', name_pad=18, ) # Back edge mux decoder vhdl.write(f, 1, '-- Back-edge mux select signal', start='\n') - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, name='back_edge_mux_sel', - type=f'integer range 0 to {len(back_edges)}', + signal_type=f'integer range 0 to {len(back_edges)}', name_pad=18, ) # Output mux selector vhdl.write(f, 1, '-- Output mux select signal', start='\n') - vhdl.common.write_signal_decl( + vhdl.common.signal_decl( f, name='out_mux_sel', - type=f'integer range 0 to {len(output_regs)-1}', + signal_type=f'integer range 0 to {len(output_regs) - 1}', name_pad=18, ) @@ -377,7 +377,7 @@ def write_register_based_storage( # vhdl.write(f, 0, 'begin', start='\n', end='\n\n') vhdl.write(f, 1, '-- Schedule counter') - vhdl.common.write_synchronous_process_prologue( + vhdl.common.synchronous_process_prologue( f=f, name='schedule_cnt_proc', clk='clk', @@ -394,7 +394,7 @@ def write_register_based_storage( (4, 'end if;'), ], ) - vhdl.common.write_synchronous_process_epilogue( + vhdl.common.synchronous_process_epilogue( f=f, name='schedule_cnt_proc', clk='clk', @@ -402,7 +402,7 @@ def write_register_based_storage( # Shift register back-edge decoding vhdl.write(f, 1, '-- Shift register back-edge decoding', start='\n') - vhdl.common.write_synchronous_process_prologue( + vhdl.common.synchronous_process_prologue( f, clk='clk', name='shift_reg_back_edge_decode_proc', @@ -429,7 +429,7 @@ def write_register_based_storage( (3, 'end case;'), ], ) - vhdl.common.write_synchronous_process_epilogue( + vhdl.common.synchronous_process_epilogue( f, clk='clk', name='shift_reg_back_edge_decode_proc', @@ -437,7 +437,7 @@ def write_register_based_storage( # Shift register multiplexer logic vhdl.write(f, 1, '-- Multiplexers for shift register', start='\n') - vhdl.common.write_synchronous_process_prologue( + vhdl.common.synchronous_process_prologue( f, clk='clk', name='shift_reg_proc', @@ -477,7 +477,7 @@ def write_register_based_storage( if sync_rst: vhdl.write(f, 3, 'end if;') - vhdl.common.write_synchronous_process_epilogue( + vhdl.common.synchronous_process_epilogue( f, clk='clk', name='shift_reg_proc', @@ -485,9 +485,7 @@ def write_register_based_storage( # Output multiplexer decoding logic vhdl.write(f, 1, '-- Output muliplexer decoding logic', start='\n') - vhdl.common.write_synchronous_process_prologue( - f, clk='clk', name='out_mux_decode_proc' - ) + vhdl.common.synchronous_process_prologue(f, clk='clk', name='out_mux_decode_proc') vhdl.write(f, 3, 'case schedule_cnt is') for i, entry in enumerate(forward_backward_table): if entry.outputs_from is not None: @@ -495,13 +493,11 @@ def write_register_based_storage( vhdl.write(f, 4, f'when {(i-1)%schedule_time} =>') vhdl.write(f, 5, f'out_mux_sel <= {sel};') vhdl.write(f, 3, 'end case;') - vhdl.common.write_synchronous_process_epilogue( - f, clk='clk', name='out_mux_decode_proc' - ) + vhdl.common.synchronous_process_epilogue(f, clk='clk', name='out_mux_decode_proc') # Output multiplexer logic vhdl.write(f, 1, '-- Output muliplexer', start='\n') - vhdl.common.write_synchronous_process_prologue( + vhdl.common.synchronous_process_prologue( f, clk='clk', name='out_mux_proc', @@ -514,7 +510,7 @@ def write_register_based_storage( else: vhdl.write(f, 5, f'p_0_out <= shift_reg({reg_i});') vhdl.write(f, 3, 'end case;') - vhdl.common.write_synchronous_process_epilogue( + vhdl.common.synchronous_process_epilogue( f, clk='clk', name='out_mux_proc', diff --git a/b_asic/codegen/vhdl/common.py b/b_asic/codegen/vhdl/common.py index cf3dfee844184cef54148e0180b21716a46a5989..cece97a2d0cf88ba42859f874092103ca50f520e 100644 --- a/b_asic/codegen/vhdl/common.py +++ b/b_asic/codegen/vhdl/common.py @@ -10,7 +10,7 @@ from typing import Any, Optional, Set, Tuple from b_asic.codegen import vhdl -def write_b_asic_vhdl_preamble(f: TextIOWrapper): +def b_asic_preamble(f: TextIOWrapper): """ Write a standard BASIC VHDL preamble comment. @@ -45,7 +45,7 @@ def write_b_asic_vhdl_preamble(f: TextIOWrapper): ) -def write_ieee_header( +def ieee_header( f: TextIOWrapper, std_logic_1164: bool = True, numeric_std: bool = True, @@ -70,10 +70,10 @@ def write_ieee_header( vhdl.write(f, 0, '') -def write_signal_decl( +def signal_decl( f: TextIOWrapper, name: str, - type: str, + signal_type: str, default_value: Optional[str] = None, name_pad: Optional[int] = None, vivado_ram_style: Optional[str] = None, @@ -90,7 +90,7 @@ def write_signal_decl( The TextIOWrapper object to write the IEEE header to. name : str Signal name. - type : str + signal_type : str Signal type. default_value : string, optional An optional default value to the signal. @@ -105,7 +105,7 @@ def write_signal_decl( """ # Spacing of VHDL signals declaration always with a single tab name_pad = name_pad or 0 - vhdl.write(f, 1, f'signal {name:<{name_pad}} : {type}', end='') + vhdl.write(f, 1, f'signal {name:<{name_pad}} : {signal_type}', end='') if default_value is not None: vhdl.write(f, 0, f' := {default_value}', end='') vhdl.write(f, 0, ';') @@ -127,10 +127,10 @@ def write_signal_decl( ) -def write_constant_decl( +def constant_declaration( f: TextIOWrapper, name: str, - type: str, + signal_type: str, value: Any, name_pad: Optional[int] = None, type_pad: Optional[int] = None, @@ -144,7 +144,7 @@ def write_constant_decl( The TextIOWrapper object to write the constant declaration to. name : str Signal name. - type : str + signal_type : str Signal type. value : anything convertable to str Default value to the signal. @@ -152,10 +152,10 @@ def write_constant_decl( An optional left padding value applied to the name. """ name_pad = 0 if name_pad is None else name_pad - vhdl.write(f, 1, f'constant {name:<{name_pad}} : {type} := {str(value)};') + vhdl.write(f, 1, f'constant {name:<{name_pad}} : {signal_type} := {str(value)};') -def write_type_decl( +def type_declaration( f: TextIOWrapper, name: str, alias: str, @@ -175,7 +175,7 @@ def write_type_decl( vhdl.write(f, 1, f'type {name} is {alias};') -def write_process_prologue( +def process_prologue( f: TextIOWrapper, sensitivity_list: str, indent: int = 1, @@ -183,7 +183,8 @@ def write_process_prologue( ): """ Write only the prologue of a regular VHDL process with a user provided sensitivity list. - This method should almost always guarantely be followed by a write_process_epilogue. + + This method should almost always be followed by a :func:`process_epilogue`. Parameters ---------- @@ -203,7 +204,7 @@ def write_process_prologue( vhdl.write(f, indent, 'begin') -def write_process_epilogue( +def process_epilogue( f: TextIOWrapper, sensitivity_list: Optional[str] = None, indent: int = 1, @@ -215,7 +216,7 @@ def write_process_epilogue( f : :class:`io.TextIOWrapper` The TextIOWrapper object to write the type declaration to. sensitivity_list : str - Content of the process sensitivity list. Not needed when writing the epligoue. + Content of the process sensitivity list. Not needed when writing the epilogue. indent : int, default: 1 Indentation level to use for this process. indent : int, default: 1 @@ -230,7 +231,7 @@ def write_process_epilogue( vhdl.write(f, 0, ';') -def write_synchronous_process_prologue( +def synchronous_process_prologue( f: TextIOWrapper, clk: str, indent: int = 1, @@ -239,7 +240,8 @@ def write_synchronous_process_prologue( """ Write only the prologue of a regular VHDL synchronous process with a single clock object in the sensitivity list triggering a rising edge block by some body of VHDL code. - This method should almost always guarantely be followed by a write_synchronous_process_epilogue. + + This method should almost always be followed by a :func:`synchronous_process_epilogue`. Parameters ---------- @@ -252,11 +254,11 @@ def write_synchronous_process_prologue( name : Optional[str] An optional name for the process. """ - write_process_prologue(f, sensitivity_list=clk, indent=indent, name=name) + process_prologue(f, sensitivity_list=clk, indent=indent, name=name) vhdl.write(f, indent + 1, 'if rising_edge(clk) then') -def write_synchronous_process_epilogue( +def synchronous_process_epilogue( f: TextIOWrapper, clk: Optional[str], indent: int = 1, @@ -265,7 +267,6 @@ def write_synchronous_process_epilogue( """ Write only the epilogue of a regular VHDL synchronous process with a single clock object in the sensitivity list triggering a rising edge block by some body of VHDL code. - This method should almost always guarantely be followed by a write_synchronous_process_epilogue. Parameters ---------- @@ -280,10 +281,10 @@ def write_synchronous_process_epilogue( """ _ = clk vhdl.write(f, indent + 1, 'end if;') - write_process_epilogue(f, sensitivity_list=clk, indent=indent, name=name) + process_epilogue(f, sensitivity_list=clk, indent=indent, name=name) -def write_synchronous_process( +def synchronous_process( f: TextIOWrapper, clk: str, body: str, @@ -307,14 +308,14 @@ def write_synchronous_process( name : Optional[str] An optional name for the process """ - write_synchronous_process_prologue(f, clk, indent, name) + synchronous_process_prologue(f, clk, indent, name) for line in body.split('\n'): if len(line): vhdl.write(f, indent + 2, f'{line}') - write_synchronous_process_epilogue(f, clk, indent, name) + synchronous_process_epilogue(f, clk, indent, name) -def write_synchronous_memory( +def synchronous_memory( f: TextIOWrapper, clk: str, read_ports: Set[Tuple[str, str, str]], @@ -339,7 +340,7 @@ def write_synchronous_memory( """ assert len(read_ports) >= 1 assert len(write_ports) >= 1 - write_synchronous_process_prologue(f, clk=clk, name=name) + synchronous_process_prologue(f, clk=clk, name=name) for read_name, address, re in read_ports: vhdl.write_lines( f, @@ -358,10 +359,10 @@ def write_synchronous_memory( (3, 'end if;'), ], ) - write_synchronous_process_epilogue(f, clk=clk, name=name) + synchronous_process_epilogue(f, clk=clk, name=name) -def write_asynchronous_read_memory( +def asynchronous_read_memory( f: TextIOWrapper, clk: str, read_ports: Set[Tuple[str, str, str]], @@ -386,7 +387,7 @@ def write_asynchronous_read_memory( """ assert len(read_ports) >= 1 assert len(write_ports) >= 1 - write_synchronous_process_prologue(f, clk=clk, name=name) + synchronous_process_prologue(f, clk=clk, name=name) for write_name, address, we in write_ports: vhdl.write_lines( f, @@ -396,6 +397,6 @@ def write_asynchronous_read_memory( (3, 'end if;'), ], ) - write_synchronous_process_epilogue(f, clk=clk, name=name) + synchronous_process_epilogue(f, clk=clk, name=name) for read_name, address, _ in read_ports: vhdl.write(f, 1, f'{read_name} <= memory({address});') diff --git a/b_asic/codegen/vhdl/entity.py b/b_asic/codegen/vhdl/entity.py index 962ce7bd88774cdf5dc0aaef59671e11f8bdf6c5..e79f7753f17670fa943b42f0a4725412eee358d2 100644 --- a/b_asic/codegen/vhdl/entity.py +++ b/b_asic/codegen/vhdl/entity.py @@ -11,7 +11,7 @@ from b_asic.process import MemoryVariable, PlainMemoryVariable from b_asic.resources import ProcessCollection -def write_memory_based_storage( +def memory_based_storage( f: TextIOWrapper, entity_name: str, collection: ProcessCollection, word_length: int ): # Check that this is a ProcessCollection of (Plain)MemoryVariables @@ -77,7 +77,7 @@ def write_memory_based_storage( f.write(f'end entity {entity_name};\n\n') -def write_register_based_storage( +def register_based_storage( f: TextIOWrapper, entity_name: str, collection: ProcessCollection, word_length: int ): - write_memory_based_storage(f, entity_name, collection, word_length) + memory_based_storage(f, entity_name, collection, word_length) diff --git a/b_asic/resources.py b/b_asic/resources.py index bdf330cef7617b42f0bd087c8109bf28eb72fa4c..9b2a6bbc06fb3591e799941b98dbb6246af4499c 100644 --- a/b_asic/resources.py +++ b/b_asic/resources.py @@ -1002,7 +1002,7 @@ class ProcessCollection: coloring_strategy : str, default: "saturation_largest_first" Graph coloring strategy passed to :func:`networkx.algorithms.coloring.greedy_color`. - coloring : dictionary, optional + coloring : dict, optional An optional graph coloring, dictionary with Process and its associated color (int). If a graph coloring is not provided throught this parameter, one will be created when calling this method. @@ -1049,8 +1049,9 @@ class ProcessCollection: if ( next_process.start_time < process.start_time + process.execution_time - or next_process_stop_time < next_process.start_time - and next_process_stop_time > process.start_time + or next_process.start_time + > next_process_stop_time + > process.start_time ): insert_to_this_cell = False break @@ -1107,8 +1108,9 @@ class ProcessCollection: memory variable access. input_sync : bool, default: True Add registers to the input signals (enable signal and data input signals). - Adding registers to the inputs allow pipelining of address generation (which is added automatically). - For large interleavers, this can improve timing significantly. + Adding registers to the inputs allow pipelining of address generation + (which is added automatically). For large interleavers, this can improve + timing significantly. """ # Check that this is a ProcessCollection of (Plain)MemoryVariables is_memory_variable = all( @@ -1163,12 +1165,12 @@ class ProcessCollection: with open(filename, 'w') as f: from b_asic.codegen.vhdl import architecture, common, entity - common.write_b_asic_vhdl_preamble(f) - common.write_ieee_header(f) - entity.write_memory_based_storage( + common.b_asic_preamble(f) + common.ieee_header(f) + entity.memory_based_storage( f, entity_name=entity_name, collection=self, word_length=word_length ) - architecture.write_memory_based_storage( + architecture.memory_based_storage( f, assignment=assignment, entity_name=entity_name, @@ -1265,12 +1267,12 @@ class ProcessCollection: with open(filename, 'w') as f: from b_asic.codegen import vhdl - vhdl.common.write_b_asic_vhdl_preamble(f) - vhdl.common.write_ieee_header(f) - vhdl.entity.write_register_based_storage( + vhdl.common.b_asic_preamble(f) + vhdl.common.ieee_header(f) + vhdl.entity.register_based_storage( f, entity_name=entity_name, collection=self, word_length=word_length ) - vhdl.architecture.write_register_based_storage( + vhdl.architecture.register_based_storage( f, forward_backward_table=forward_backward_table, entity_name=entity_name,