Example #1
0
    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"
Example #2
0
    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)
Example #3
0
    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"
Example #4
0
 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)]
Example #5
0
 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)]
Example #6
0
 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
Example #7
0
 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)
Example #8
0
 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 = []
Example #9
0
 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)
Example #10
0
 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     = []
Example #11
0
 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)
Example #12
0
 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"))
Example #13
0
File: Data.py Project: OSSDC/Octavo
 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"))
Example #14
0
    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)
Example #15
0
    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
        ]
Example #16
0
 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)
Example #17
0
 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
Example #18
0
    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]
Example #19
0
    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)
Example #20
0
    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)
Example #21
0
    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]
Example #22
0
    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")
Example #23
0
 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)
Example #24
0
 def __init__ (self, commands):
     Debug.__init__(self)
     self.commands = commands
Example #25
0
File: Data.py Project: OSSDC/Octavo
 def __init__ (self, label = None, address = None, memory = None):
     Debug.__init__(self)
     self.label   = label
     self.address = address
     self.memory  = memory
Example #26
0
 def __init__ (self, label = None, address = None, memory = None):
     Debug.__init__(self)
     self.label   = label
     self.address = address
     self.memory  = memory
Example #27
0
 def __init__(self, data, code, configuration):
     Utility.__init__(self)
     Debug.__init__(self)
     self.data = data
     self.code = code
     self.configuration = configuration
Example #28
0
 def __init__ (self, data, code, configuration):
     Utility.__init__(self)
     Debug.__init__(self)
     self.data           = data
     self.code           = code
     self.configuration  = configuration
Example #29
0
 def __init__(self, commands):
     Debug.__init__(self)
     self.commands = commands
Example #30
0
 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
Example #31
0
 def __init__ (self, data, code):
     Debug.__init__(self)
     self.data = data
     self.code = code
Example #32
0
 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