def end_finite(self, target_name, automatic_label=False): """At the ending of a finite loop Adds a bdec instruction and fills the branch delay slots @param target_name: String identifier of the label to jump to @param automatic_label: Generate an automated label """ register_addr = len(self.sequencer.bdec_register) - 1 if register_addr < 0: raise RuntimeError("Cannot pop from empty loop stack") self.sequencer.bdec_register.pop() # apply address of register earlier to prevent timing problems in the bus nop_insn = instructions.nop(val=(register_addr << 23)) self.sequencer.add_insn(nop_insn) if automatic_label == False: bdec_insn = instructions.bdec(target_name, register_addr) else: l = len(self.sequencer.open_automatic_labels) - 1 aut_target_name = self.sequencer.open_automatic_labels[l] self.sequencer.open_automatic_labels.pop() bdec_insn = instructions.bdec(aut_target_name, register_addr) nop_insn = instructions.nop() self.sequencer.add_insn(bdec_insn) for index in range(self.branch_delay_slots): self.sequencer.add_insn(copy.copy(nop_insn))
def compile_sequence(self): """generates the binary list """ # Addresses are broken when using subroutines # Add a halt instruction to the current sequence ! halt_insn = instructions.halt() self.add_insn(halt_insn) nop_insn = instructions.nop() for i in range(self.branch_delay_slots): self.add_insn(copy.copy(nop_insn)) sequence_list = self.current_sequence word_index = len(self.current_sequence) # Add the subroutines to current_sequence for insn_list in self.sub_list: self.label_dict[insn_list[0].label] = word_index sequence_list += insn_list word_index += len(insn_list) self.word_list = [] # reset the address counter address = 0 # Append the binary charlist to the word_list # If the calue of the insn is None we are dealing # with a jump insn and adding it to the jump_list for insn in sequence_list: # calculate the instruction's machine code as an int value = insn.get_value() if insn.is_branch == True: self.word_list.append(insn) self.jump_list.append(len(self.word_list) - 1) else: # Generate a 32bit binary word from value self.word_list.append(self.get_binary_charlist(value, 4)) # set the insn address and increase the address counter insn.address = address address += 1 # calculate the addresses for the branch insns in jump_list for word_num in self.jump_list: jump_insn = self.word_list[word_num] try: target_num = self.label_dict[jump_insn.target_name] target_insn = self.current_sequence[target_num] target_address = target_insn.address value = jump_insn.get_jump_value(target_address) self.word_list[word_num] = self.get_binary_charlist(value, 4) except: self.logger.exception("error while handling jump: " \ + str(jump_insn.target_name)) # update current_sequence to make debugging possible if len(sequence_list) > self.max_sequence_length - 1: raise RuntimeError("Maximum sequence length exceeded: " + \ str(hex(len(sequence_list)))) self.current_sequence = sequence_list
def jump(self, target_name): """unconditional jump to label @param target_name: String identifier of the label to jump to """ jump_insn = instructions.j(target_name) nop_insn = instructions.nop() self.sequencer.add_insn(jump_insn) for index in range(self.branch_delay_slots): self.sequencer.add_insn(copy.copy(nop_insn))
def call_subroutine(self, sub_name): """calls a subroutine sub_name @param sub_name: String identifier of the subroutine to call """ call_insn = instructions.call(sub_name) nop_insn = instructions.nop() self.sequencer.add_insn(call_insn) self.sequencer.add_insn(nop_insn) self.sequencer.add_insn(copy.copy(nop_insn)) self.sequencer.add_insn(copy.copy(nop_insn))
def jump_trigger(self, target_name, trigger, invert=False): """branch on trigger Adds a conditional jump @param target_name: String identifier of the label to jump to @param trigger : trigger state in hex """ jump_insn = instructions.btr(target_name, trigger, invert=invert) nop_insn = instructions.nop() self.sequencer.add_insn(jump_insn) for index in range(self.branch_delay_slots): self.sequencer.add_insn(copy.copy(nop_insn))
def wait_trigger(self, trigger): """Inserts a wait on trigger operation @param trigger: trigger state in hex """ #generate an automatic label aut_target_name = self.generate_auto_label() label_insn = instructions.label(aut_target_name) halt_insn = instructions.halt() jump_insn = instructions.btr(aut_target_name, trigger) nop_insn = instructions.nop() self.sequencer.add_insn(halt_insn) for index in range(self.branch_delay_slots - 1): self.sequencer.add_insn(copy.copy(nop_insn)) self.sequencer.add_insn(jump_insn) for index in range(self.branch_delay_slots): self.sequencer.add_insn(copy.copy(nop_insn)) self.sequencer.add_insn(label_insn)
def wait(self, wait_time, use_cycles=False): """inserts a wait event needs calibration !!! wait has to be > 4 ? @param wait_time : time in us to wait @param use_cycles: If set to True the wait_time will be interpreted as cycles """ if use_cycles: wait_cycles = wait_time else: wait_cycles = int(wait_time / self.cycle_time) if wait_cycles < 1.0: self.logger.debug("Cannot wait for less than one cycle") return nop_insn = instructions.nop() while wait_cycles > 0: if wait_cycles > self.branch_delay_slots + 2: # wait_cycles -= self.branch_delay_slots - 1 # Subtract one more cycle - we need it for the wait # instruction itself if wait_cycles > self.max_wait_cycles: my_wait = self.max_wait_cycles else: my_wait = wait_cycles - self.branch_delay_slots - 1 wait_insn = instructions.wait(my_wait) # Do we really need wait_cycles - 5 ?? wait_cycles -= my_wait + self.branch_delay_slots + 1 self.sequencer.add_insn(wait_insn) for i in range(self.branch_delay_slots): self.sequencer.add_insn(copy.copy(nop_insn)) else: for i in range(wait_cycles): self.sequencer.add_insn(copy.copy(nop_insn)) wait_cycles = 0