diff --git a/assembler_tools/hec-assembler-tools/assembler/common/constants.py b/assembler_tools/hec-assembler-tools/assembler/common/constants.py index 40f10640..4dc18ac7 100644 --- a/assembler_tools/hec-assembler-tools/assembler/common/constants.py +++ b/assembler_tools/hec-assembler-tools/assembler/common/constants.py @@ -28,6 +28,8 @@ class Constants: __MAX_BUNDLE_SIZE: int __XINSTRUCTION_SIZE_BYTES: int + __CINSTRUCTION_SIZE_BYTES: int + __MINSTRUCTION_SIZE_BYTES: int # Data Constants # -------------- @@ -78,6 +80,16 @@ def XINSTRUCTION_SIZE_BYTES(cls) -> int: """Size of an x-instruction in bytes.""" return cls.__XINSTRUCTION_SIZE_BYTES + @classproperty + def CINSTRUCTION_SIZE_BYTES(cls) -> int: + """Size of a c-instruction in bytes.""" + return cls.__CINSTRUCTION_SIZE_BYTES + + @classproperty + def MINSTRUCTION_SIZE_BYTES(cls) -> int: + """Size of a m-instruction in bytes.""" + return cls.__MINSTRUCTION_SIZE_BYTES + @classproperty def MAX_BUNDLE_SIZE(cls) -> int: """Maximum number of instructions in a bundle.""" @@ -124,7 +136,12 @@ def hw_spec_as_dict(cls) -> dict: """ Returns hw configurable attributes as dictionary. """ - return {"bytes_per_xinstruction": cls.XINSTRUCTION_SIZE_BYTES, "max_instructions_per_bundle": cls.MAX_BUNDLE_SIZE} + return { + "bytes_per_xinstruction": cls.XINSTRUCTION_SIZE_BYTES, + "bytes_per_cinstruction": cls.CINSTRUCTION_SIZE_BYTES, + "bytes_per_minstruction": cls.MINSTRUCTION_SIZE_BYTES, + "max_instructions_per_bundle": cls.MAX_BUNDLE_SIZE, + } @classmethod def setMaxBundleSize(cls, val: int): @@ -136,6 +153,16 @@ def setXInstructionSizeBytes(cls, val: int): """Updates size of single XInstruction""" cls.__XINSTRUCTION_SIZE_BYTES = val + @classmethod + def setCInstructionSizeBytes(cls, val: int): + """Updates size of single CInstruction""" + cls.__CINSTRUCTION_SIZE_BYTES = val + + @classmethod + def setMInstructionSizeBytes(cls, val: int): + """Updates size of single MInstruction""" + cls.__MINSTRUCTION_SIZE_BYTES = val + def convertBytes2Words(bytes_in: int) -> int: """ @@ -363,6 +390,11 @@ def XINST_QUEUE_MAX_CAPACITY_WORDS(cls): """Maximum capacity of the XINST queue in words.""" return convertBytes2Words(cls.__XINST_QUEUE_MAX_CAPACITY) + @classproperty + def XINST_QUEUE_MAX_CAPACITY_ENTRIES(cls): + """Maximum number of entries in the XINST queue.""" + return cls.__XINST_QUEUE_MAX_CAPACITY // Constants.XINSTRUCTION_SIZE_BYTES + @classproperty def CINST_QUEUE_MAX_CAPACITY(cls): """Maximum capacity of the CINST queue in bytes.""" @@ -373,6 +405,11 @@ def CINST_QUEUE_MAX_CAPACITY_WORDS(cls): """Maximum capacity of the CINST queue in words.""" return convertBytes2Words(cls.__CINST_QUEUE_MAX_CAPACITY) + @classproperty + def CINST_QUEUE_MAX_CAPACITY_ENTRIES(cls): + """Maximum number of entries in the CINST queue.""" + return cls.__CINST_QUEUE_MAX_CAPACITY // Constants.CINSTRUCTION_SIZE_BYTES + @classproperty def MINST_QUEUE_MAX_CAPACITY(cls): """Maximum capacity of the MINST queue in bytes.""" @@ -383,6 +420,11 @@ def MINST_QUEUE_MAX_CAPACITY_WORDS(cls): """Maximum capacity of the MINST queue in words.""" return convertBytes2Words(cls.__MINST_QUEUE_MAX_CAPACITY) + @classproperty + def MINST_QUEUE_MAX_CAPACITY_ENTRIES(cls): + """Maximum number of entries in the MINST queue.""" + return cls.__MINST_QUEUE_MAX_CAPACITY // Constants.MINSTRUCTION_SIZE_BYTES + @classproperty def STORE_BUFFER_MAX_CAPACITY(cls): """Maximum capacity of the store buffer in bytes.""" diff --git a/assembler_tools/hec-assembler-tools/assembler/spec_config/mem_spec.py b/assembler_tools/hec-assembler-tools/assembler/spec_config/mem_spec.py index ef1c9ce9..9adcadf6 100644 --- a/assembler_tools/hec-assembler-tools/assembler/spec_config/mem_spec.py +++ b/assembler_tools/hec-assembler-tools/assembler/spec_config/mem_spec.py @@ -11,6 +11,8 @@ class MemSpecConfig: _target_attributes = { "bytes_per_xinstruction": Constants.setXInstructionSizeBytes, + "bytes_per_cinstruction": Constants.setCInstructionSizeBytes, + "bytes_per_minstruction": Constants.setMInstructionSizeBytes, "max_instructions_per_bundle": Constants.setMaxBundleSize, "max_xinst_queue_size_in_bytes": MemoryModel.setMaxXInstQueueCapacity, "max_cinst_queue_size_in_bytes": MemoryModel.setMaxCInstQueueCapacity, diff --git a/assembler_tools/hec-assembler-tools/assembler/stages/scheduler.py b/assembler_tools/hec-assembler-tools/assembler/stages/scheduler.py index 8eaad4b6..f5d9bb0b 100644 --- a/assembler_tools/hec-assembler-tools/assembler/stages/scheduler.py +++ b/assembler_tools/hec-assembler-tools/assembler/stages/scheduler.py @@ -6,6 +6,8 @@ import networkx as nx from typing import NamedTuple +from assembler.common import constants + from . import buildVarAccessListFromTopoSort from assembler.common.cycle_tracking import PrioritizedPlaceholder, CycleType from assembler.instructions import xinst, cinst, minst @@ -150,6 +152,11 @@ def enforceKeygenOrdering(deps_graph: nx.DiGraph, mem_model: MemoryModel, verbos comment=f"injected copy to generate keygen var {kg_var_name} (seed = {seed_idx}, key = {key_idx})", ) deps_graph.add_node(copy_instr.id, instruction=copy_instr) + + assert ( + deps_graph.number_of_nodes() <= constants.MemoryModel.XINST_QUEUE_MAX_CAPACITY_ENTRIES + ), f"Exceeded maximum number of instructions in XInstQ while injecting keygen copy instructions: {constants.MemoryModel.XINST_QUEUE_MAX_CAPACITY_ENTRIES} Entries." + # Enforce ordering of copies based on ordering of keygen if last_copy_id is not None: # Last copy -> current copy diff --git a/assembler_tools/hec-assembler-tools/config/mem_spec.json b/assembler_tools/hec-assembler-tools/config/mem_spec.json index c417d12c..5703cd3f 100644 --- a/assembler_tools/hec-assembler-tools/config/mem_spec.json +++ b/assembler_tools/hec-assembler-tools/config/mem_spec.json @@ -9,6 +9,8 @@ "num_register_banks": 4, "num_registers_per_bank": 72, "bytes_per_xinstruction": 8, + "bytes_per_cinstruction": 8, + "bytes_per_minstruction": 8, "max_instructions_per_bundle": 64, "num_blocks_per_twid_meta_word": 4, "num_blocks_per_kgseed_meta_word": 4, diff --git a/assembler_tools/hec-assembler-tools/he_as.py b/assembler_tools/hec-assembler-tools/he_as.py index 10571f2d..81a16dd3 100644 --- a/assembler_tools/hec-assembler-tools/he_as.py +++ b/assembler_tools/hec-assembler-tools/he_as.py @@ -235,6 +235,10 @@ def asmisaAssemble( insts_listing += parsed_insts + assert ( + len(insts_listing) <= constants.MemoryModel.XINST_QUEUE_MAX_CAPACITY_ENTRIES + ), f"Line {line_no}: Exceeded maximum number of instructions in XInstQ: {constants.MemoryModel.XINST_QUEUE_MAX_CAPACITY_ENTRIES} Entries." + if b_verbose: print("Interpreting variable meta information...") with open(mem_filename, "r") as mem_ifnum: @@ -259,6 +263,7 @@ def asmisaAssemble( b_verbose, ) sched_end = time.time() - start_time + num_nops = 0 num_xinsts = 0 for bundle_xinsts, *_ in xinsts: @@ -269,6 +274,15 @@ def asmisaAssemble( if isinstance(xinstr, xinst.Nop): num_nops += 1 + # Final xinst count assertion + assert ( + (num_xinsts + num_nops) <= constants.MemoryModel.XINST_QUEUE_MAX_CAPACITY_ENTRIES + ), f"Exceeded maximum number of instructions in XInstQ: {(num_xinsts + num_nops)} > {constants.MemoryModel.XINST_QUEUE_MAX_CAPACITY_ENTRIES} Entries." + + # Minst count assertion + assert ( + len(minsts) <= constants.MemoryModel.MINST_QUEUE_MAX_CAPACITY_ENTRIES + ), f"Exceeded maximum number of instructions in MInstQ: {len(minsts)} > {constants.MemoryModel.MINST_QUEUE_MAX_CAPACITY_ENTRIES} Entries." if b_verbose: print("Saving minst...") with open(output_minst_filename, "w") as outnum: @@ -277,6 +291,10 @@ def asmisaAssemble( if inst_line: print(f"{idx}, {inst_line}", file=outnum) + # Cinst count assertion + assert ( + len(cinsts) <= constants.MemoryModel.CINST_QUEUE_MAX_CAPACITY_ENTRIES + ), f"Exceeded maximum number of instructions in CInstQ: {len(cinsts)} > {constants.MemoryModel.CINST_QUEUE_MAX_CAPACITY_ENTRIES} Entries." if b_verbose: print("Saving cinst...") with open(output_cinst_filename, "w") as outnum: