def __init__ (self, dyadic_obj): Debug.__init__(self) self.dyadic = dyadic_obj # From Verilog code self.control_width = 31 self.origin_enabled = BitArray("0b1") self.origin_disabled = BitArray("0b0") self.predict_taken = BitArray("0b1") self.predict_not_taken = BitArray("0b0") self.predict_enabled = BitArray("0b1") self.predict_disabled = BitArray("0b0") self.a_negative = BitArray("0b00") self.a_carryout = BitArray("0b01") self.a_sentinel = BitArray("0b10") self.a_external = BitArray("0b11") self.b_lessthan = BitArray("0b00") self.b_counter = BitArray("0b01") self.b_sentinel = BitArray("0b10") self.b_external = BitArray("0b11") self.origin_width = 10 self.origin_enable_width = 1 self.destination_width = 10 self.predict_taken_width = 1 self.predict_enable_width = 1 self.a_width = 2 self.b_width = 2 self.ab_operator_width = self.dyadic.operator_width self.condition_width = self.a_width + self.b_width + self.ab_operator_width assert (self.origin_width + self.origin_enable_width + self.destination_width + self.predict_taken_width + self.predict_enable_width + self.condition_width) == self.control_width, "ERROR: Branch Detector control word width and sum of control bits widths do not agree"
def __init__ (self, data, code, configuration, operators): Debug.__init__(self) self.operators = operators self.init_mems = [] # Do all these first. Instructions and data depend on them self.OD = Opcode_Decoder(configuration.filename_od, self.operators, code, configuration) self.init_mems.append(self.OD) self.PC = Program_Counter(configuration.filename_pc, code, configuration) self.PC_prev = Program_Counter(configuration.filename_pc_prev, code, configuration) self.init_mems.append(self.PC) self.init_mems.append(self.PC_prev) self.DO = Default_Offset(configuration.filename_do, configuration) self.init_mems.append(self.DO) self.BD = Branch_Detector(self.operators.branch_detector, code, configuration) self.PO = Programmed_Offset(data, configuration) # Now all Code and Data have been resolved and generated # We can now create the Data and Instruction Memories self.A = Data_Memory(configuration.filename_data_A, configuration.data_A_label, data, code, configuration) self.B = Data_Memory(configuration.filename_data_B, configuration.data_B_label, data, code, configuration) self.init_mems.append(self.A) self.init_mems.append(self.B) self.I = Instruction_Memory(configuration.filename_I, code, configuration) self.init_mems.append(self.I)
def __init__ (self, dyadic_obj): Debug.__init__(self) self.dyadic = dyadic_obj # From Verilog code self.control_width = 20 self.select_r = BitArray("0b00") self.select_r_zero = BitArray("0b01") self.select_r_neg = BitArray("0b10") self.select_s = BitArray("0b11") self.simple = BitArray("0b0") self.dual = BitArray("0b1") self.addsub_a_plus_b = BitArray("0b00") self.addsub_minus_a_plus_b = BitArray("0b01") self.addsub_a_minus_b = BitArray("0b10") self.addsub_minus_a_minus_b = BitArray("0b11") self.shift_none = BitArray("0b00") self.shift_right = BitArray("0b01") self.shift_right_signed = BitArray("0b10") self.shift_left = BitArray("0b11") self.split_no = BitArray("0b0") self.split_yes = BitArray("0b1") self.select_width = 2 self.dyadic1_width = self.dyadic.operator_width self.dyadic2_width = self.dyadic.operator_width self.dual_width = 1 self.addsub_width = 2 self.dyadic3_width = self.dyadic.operator_width self.shift_width = 2 self.split_width = 1 assert (self.select_width + self.dyadic1_width + self.dyadic2_width + self.dual_width + self.addsub_width + self.dyadic3_width + self.shift_width + self.split_width) == self.control_width, "ERROR: ALU control word width and sum of control bits widths do not agree"
def __init__(self, data_mem_depth, start_of_private_mem, thread_count): Debug.__init__(self) # Divide between threads the remaining data memory after the shared memory range. self.private_mem_depth = ceil( (data_mem_depth - start_of_private_mem) / thread_count) self.offsets = [(self.private_mem_depth * thread) for thread in range(thread_count)]
def __init__ (self, code, data, configuration, operators): Debug.__init__(self) self.operators = operators self.code = code self.data = data self.configuration = configuration self.defined_opcodes = {} # {label:opcode_obj} # One set of initial/current opcodes per thread self.initial_opcodes = [[None for entry in range(self.configuration.opcode_count)] for thread in range(self.configuration.thread_count)] self.current_opcodes = [[None for entry in range(self.configuration.opcode_count)] for thread in range(self.configuration.thread_count)]
def __init__ (self, label = None, address = None, opcode = None, D = None, DA = None, DB = None, A = None, B = None): Debug.__init__(self) self.label = label self.address = address self.opcode = opcode self.D = D self.DA = DA self.DB = DB self.A = A self.B = B
def __init__ (self, data, code, label = None, destination = None,): Debug.__init__(self) self.label = label self.destination = destination self.instructions = [] self.init_data = [] self.data = data self.code = code # keep any init instructions added later in order, # so add list of init instructions to global list self.code.instructions.append(self.instructions)
def __init__(self, data, configuration, operators): Debug.__init__(self) self.operators = operators self.data = data self.configuration = configuration self.usage = Usage(configuration) self.init_loads = [] self.instructions = [] self.opcodes = Opcode_Manager(self, data, configuration, operators) self.conditions = [] self.branches = [] self.initial_pc = []
def __init__ (self, label, split, shift, dyadic3, addsub, dual, dyadic2, dyadic1, select, operators): Debug.__init__(self) self.label = label self.split = split self.shift = shift self.dyadic3 = dyadic3 self.addsub = addsub self.dual = dual self.dyadic2 = dyadic2 self.dyadic1 = dyadic1 self.select = select self.binary = self.to_binary(operators)
def __init__ (self, data, configuration, operators): Debug.__init__(self) self.operators = operators self.data = data self.configuration = configuration self.usage = Usage(configuration) self.init_loads = [] self.instructions = [] self.opcodes = Opcode_Manager(self, data, configuration, operators) self.conditions = [] self.branches = [] self.initial_pc = []
def __init__(self): Debug.__init__(self) self.filename_od = "OD.mem" self.filename_pc = "PC.mem" self.filename_pc_prev = "PC_prev.mem" self.filename_do = "DO.mem" self.filename_data_A = "A.mem" self.data_A_label = "A" self.filename_data_B = "B.mem" self.data_B_label = "B" self.filename_I = "I.mem" self.branch_label_not_taken = "not_taken" self.branch_label_taken = "taken" self.branch_label_none = "unpredicted" self.branch_label_anywhere = "anywhere" self.branch_label_anywhere_cancel = "anywhere_cancel" self.pc_width = 10 self.instr_OP_width = 4 self.instr_D_width = 12 self.instr_DA_width = 6 self.instr_DB_width = 6 self.instr_A_width = 10 self.instr_B_width = 10 self.opcode_count = 16 self.thread_count = 8 self.memory_depth_words = 1024 self.memory_depth_words_write = self.memory_depth_words * 4 # ECL FIXME this needs a cleaner definition self.memory_width_bits = 36 self.memory_shared_count = 32 # Indirect and I/O memory must fit in shared, and match hardware self.memory_indirect_base = 24 self.memory_indirect_count = 4 self.memory_io_base = 28 self.memory_io_count = 4 # Contrary to Default Offset, the offset length matters here, since other # data follows it in the upper bits. self.po_read_offset_bit_width = 10 self.po_write_offset_bit_width = 12 # These must match the Verilog parameters self.po_increment_bits = 4 self.po_increment_sign_bits = 1 # Must match Verilog code, currently 10 or 12 bits, so same hex output either way self.default_offset_width = 12 self.default_offset = DefaultOffset(self.memory_depth_words, self.memory_shared_count, self.thread_count) self.memory_map = MemoryMap(self.memory_shared_count, self.memory_indirect_base, self.memory_indirect_count, self.memory_io_base, self.memory_io_count, self.default_offset)
def __init__ (self, configuration): Utility.__init__(self) Debug.__init__(self) # Used for private and pointer variables self.current_threads = [] # Variable type lists self.shared = [] self.private = [] self.pointers = [] self.ports = [] self.variables = [self.shared, self.private, self.pointers, self.ports] self.configuration = configuration # Location Zero is a special case always equal to zero. # It must exist before any other shared variable. self.shared.append(Shared_Variable(label = None, address = 0, value = 0, memory = "A")) self.shared.append(Shared_Variable(label = None, address = 0, value = 0, memory = "B"))
def __init__ (self, configuration): Debug.__init__(self) self.configuration = configuration self.po_in_use = dict() for operand in ["A", "B", "DA", "DB"]: self.po_in_use[operand] = self.init_flags(self.configuration.memory_map.po[operand]) self.sentinel_in_use = dict() self.mask_in_use = dict() for operand in ["A", "B"]: self.sentinel_in_use[operand] = self.init_flags(self.configuration.memory_map.sentinel[operand]) self.mask_in_use[operand] = self.init_flags(self.configuration.memory_map.mask[operand]) self.bc_in_use = self.init_flags(self.configuration.memory_map.bc) self.bd_in_use = self.init_flags(self.configuration.memory_map.bd)
def __init__(self, memory_shared_count, memory_indirect_base, memory_indirect_count, memory_io_base, memory_io_count, default_offset_obj): Debug.__init__(self) # Shared memory (all threads): self.shared = range(memory_shared_count) # Shared Literal Pool (Zero is reserved as zero-register, implemented by hardware also) self.pool = range(1, memory_indirect_base) self.indirect = range(memory_indirect_base, memory_indirect_base + memory_indirect_count) self.io = range(memory_io_base, memory_io_base + memory_io_count) # Private memory range for one thread, no offset applied. self.private = range( memory_shared_count, memory_shared_count + default_offset_obj.private_mem_depth) # Total thread mem is shared + private, mapped consecutively. self.total = chain(self.shared, self.private) # Base write addresses. # Add these to A/B read address to get write address. # I is only readable by the Program Counter, writable by code. # H is only writable by code. Not readable at all. self.write_bases = {"A": 0, "B": 1024, "I": 2048, "H": 3072} # Config registers write addresses in write-only H (high) memory # ECL XXX FIXME These should be computed from configuration, not hardcoded. self.s = 3072 self.po = dict() self.po["A"] = [3076, 3077, 3078, 3079] self.po["B"] = [3080, 3081, 3082, 3083] self.po["DA"] = [3084, 3085, 3086, 3087] self.po["DB"] = [3088, 3089, 3090, 3091] self.do = 3092 self.sentinel = dict() self.mask = dict() self.sentinel["A"] = [3100, 3106, 3112, 3118] self.mask["A"] = [3101, 3107, 3113, 3119] self.sentinel["B"] = [3102, 3108, 3114, 3120] self.mask["B"] = [3103, 3109, 3115, 3121] self.bc = [3104, 3110, 3116, 3122] self.bd = [3105, 3111, 3117, 3123] self.od = [ 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215 ]
def __init__( self, data, code, label=None, destination=None, ): Debug.__init__(self) self.label = label self.destination = destination self.instructions = [] self.init_data = [] self.data = data self.code = code # keep any init instructions added later in order, # so add list of init instructions to global list self.code.instructions.append(self.instructions)
def __init__(self, label=None, address=None, opcode=None, D=None, DA=None, DB=None, A=None, B=None): Debug.__init__(self) self.label = label self.address = address self.opcode = opcode self.D = D self.DA = DA self.DB = DB self.A = A self.B = B
def __init__(self, code, condition_label, branch_parameters): Debug.__init__(self) self.condition = code.lookup_condition(condition_label) # The init load was already given, just blank. # We will fill it with the necessary code/data when we allocate this branch. self.init_load = None label = branch_parameters.pop(0) if label is not None: print("Branches cannot have labels: {0} at {1}".format( label, condition_label)) self.ask_for_debugger() self.prediction = branch_parameters.pop(0) self.sentinel_a = None self.mask_a = None self.sentinel_b = None self.mask_b = None self.counter = None self.destination = None self.origin = None if self.condition.a == "a_sentinel": self.sentinel_a = branch_parameters.pop(0) self.mask_a = branch_parameters.pop(0) if self.condition.b == "b_sentinel": self.sentinel_b = branch_parameters.pop(0) self.mask_b = branch_parameters.pop(0) if self.condition.b == "b_counter": self.counter = branch_parameters.pop(0) self.destination = branch_parameters.pop(0) if len(branch_parameters) > 0: print("Unparsed branch parameters {0} for branch {1}".format( branch_parameters, condition_label)) self.ask_for_debugger() # A branch definition always follows an instruction, and will execute "in parallel", # so we need to know which instruction so we know the branch origin, which will be # resolved after all the instructions are resolved and given addresses. self.instruction = code.instructions[-1]
def __init__(self, configuration): Debug.__init__(self) self.configuration = configuration self.po_in_use = dict() for operand in ["A", "B", "DA", "DB"]: self.po_in_use[operand] = self.init_flags( self.configuration.memory_map.po[operand]) self.sentinel_in_use = dict() self.mask_in_use = dict() for operand in ["A", "B"]: self.sentinel_in_use[operand] = self.init_flags( self.configuration.memory_map.sentinel[operand]) self.mask_in_use[operand] = self.init_flags( self.configuration.memory_map.mask[operand]) self.bc_in_use = self.init_flags(self.configuration.memory_map.bc) self.bd_in_use = self.init_flags(self.configuration.memory_map.bd)
def __init__(self, data, code, configuration, operators): Debug.__init__(self) self.operators = operators self.init_mems = [] # Do all these first. Instructions and data depend on them self.OD = Opcode_Decoder(configuration.filename_od, self.operators, code, configuration) self.init_mems.append(self.OD) self.PC = Program_Counter(configuration.filename_pc, code, configuration) self.PC_prev = Program_Counter(configuration.filename_pc_prev, code, configuration) self.init_mems.append(self.PC) self.init_mems.append(self.PC_prev) self.DO = Default_Offset(configuration.filename_do, configuration) self.init_mems.append(self.DO) self.BD = Branch_Detector(self.operators.branch_detector, code, configuration) self.PO = Programmed_Offset(data, configuration) # Now all Code and Data have been resolved and generated # We can now create the Data and Instruction Memories self.A = Data_Memory(configuration.filename_data_A, configuration.data_A_label, data, code, configuration) self.B = Data_Memory(configuration.filename_data_B, configuration.data_B_label, data, code, configuration) self.init_mems.append(self.A) self.init_mems.append(self.B) self.I = Instruction_Memory(configuration.filename_I, code, configuration) self.init_mems.append(self.I)
def __init__ (self, code, condition_label, branch_parameters): Debug.__init__(self) self.condition = code.lookup_condition(condition_label) # The init load was already given, just blank. # We will fill it with the necessary code/data when we allocate this branch. self.init_load = None label = branch_parameters.pop(0) if label is not None: print("Branches cannot have labels: {0} at {1}".format(label, condition_label)) self.ask_for_debugger() self.prediction = branch_parameters.pop(0) self.sentinel_a = None self.mask_a = None self.sentinel_b = None self.mask_b = None self.counter = None self.destination = None self.origin = None if self.condition.a == "a_sentinel": self.sentinel_a = branch_parameters.pop(0) self.mask_a = branch_parameters.pop(0) if self.condition.b == "b_sentinel": self.sentinel_b = branch_parameters.pop(0) self.mask_b = branch_parameters.pop(0) if self.condition.b == "b_counter": self.counter = branch_parameters.pop(0) self.destination = branch_parameters.pop(0) if len(branch_parameters) > 0: print("Unparsed branch parameters {0} for branch {1}".format(branch_parameters, condition_label)) self.ask_for_debugger() # A branch definition always follows an instruction, and will execute "in parallel", # so we need to know which instruction so we know the branch origin, which will be # resolved after all the instructions are resolved and given addresses. self.instruction = code.instructions[-1]
def __init__ (self): Debug.__init__(self) self.operator_width = 4 self.always_zero = BitArray("0b0000") self.a_and_b = BitArray("0b1000") self.a_and_not_b = BitArray("0b0100") self.a = BitArray("0b1100") self.not_a_and_b = BitArray("0b0010") self.b = BitArray("0b1010") self.a_xor_b = BitArray("0b0110") self.a_or_b = BitArray("0b1110") self.a_nor_b = BitArray("0b0001") self.a_xnor_b = BitArray("0b1001") self.not_b = BitArray("0b0101") self.a_or_not_b = BitArray("0b1101") self.not_a = BitArray("0b0011") self.not_a_or_b = BitArray("0b1011") self.a_nand_b = BitArray("0b0111") self.always_one = BitArray("0b1111")
def __init__ (self): Debug.__init__(self) self.dyadic = Dyadic_Operators() self.triadic = Triadic_ALU_Operators(self.dyadic) self.branch_detector = Branch_Detector_Operators(self.dyadic)
def __init__ (self, commands): Debug.__init__(self) self.commands = commands
def __init__ (self, label = None, address = None, memory = None): Debug.__init__(self) self.label = label self.address = address self.memory = memory
def __init__(self, data, code, configuration): Utility.__init__(self) Debug.__init__(self) self.data = data self.code = code self.configuration = configuration
def __init__ (self, data, code, configuration): Utility.__init__(self) Debug.__init__(self) self.data = data self.code = code self.configuration = configuration
def __init__(self, commands): Debug.__init__(self) self.commands = commands
def __init__ (self, label, a, b, ab_operator): Debug.__init__(self) self.label = label self.a = a self.b = b self.ab_operator = ab_operator
def __init__ (self, data, code): Debug.__init__(self) self.data = data self.code = code
def __init__(self, label, a, b, ab_operator): Debug.__init__(self) self.label = label self.a = a self.b = b self.ab_operator = ab_operator