Example #1
0
class Context(object):

    def __init__(self, instructions):
        self.registers = Registers()
        self.flags = Flags()
        self.instructions = instructions
        self.heap = Memory(size=40, mode=HEAP, start_address=0x0000)
        self.stack = Memory(size=40, mode=STACK, start_address=0xFFFF)
        self.registers.set(SP, 0xFFFF)

    def run(self):
        """
        initialize the context and execute the first instruction
        """
        self.registers.reset()

    def step(self):
        """
        execute the next instruction whose address in the EIP value
        :return:
        """
        self.registers.tick()
        self.flags.tick()
        self.heap.tick()
        self.stack.tick()
        next_address = self.registers.get(IP).value
        if next_address < len(self.instructions):
            next_instruction = self.instructions[next_address]
            next_instruction.execute(self)
            self.registers.set(IP, next_address + 1)
            return True
        else:
            return False
Example #2
0
class RedPitayaControlService(BaseService):
    """Control server that runs on the RP that provides high-level methods."""
    def __init__(self, **kwargs):
        self._cached_data = {}
        self.exposed_is_locked = None

        super().__init__()

        from registers import Registers

        self.registers = Registers(**kwargs)
        self.registers.connect(self, self.parameters)

    def run_acquiry_loop(self):
        """Starts a background process that keeps polling control and error
        signal. Every received value is pushed to `parameters.to_plot`."""
        def data_received(is_raw, plot_data, data_uuid):
            # When a parameter is changed, `pause_acquisition` is set.
            # This means that the we should skip new data until we are sure that
            # it was recorded with the new settings.
            if not self.parameters.pause_acquisition.value:
                if data_uuid != self.data_uuid:
                    return

                data_loaded = pickle.loads(plot_data)

                if not is_raw:
                    is_locked = self.parameters.lock.value

                    if not check_plot_data(is_locked, data_loaded):
                        print(
                            "warning: incorrect data received for lock state, ignoring!"
                        )
                        return

                    self.parameters.to_plot.value = plot_data
                    self._generate_signal_stats(data_loaded)

                    # update signal history (if in locked state)
                    (
                        self.parameters.control_signal_history.value,
                        self.parameters.monitor_signal_history.value,
                    ) = update_signal_history(
                        self.parameters.control_signal_history.value,
                        self.parameters.monitor_signal_history.value,
                        data_loaded,
                        is_locked,
                        self.parameters.control_signal_history_length.value,
                    )
                else:
                    self.parameters.acquisition_raw_data.value = plot_data

        self.registers.run_data_acquisition(data_received)
        self.pause_acquisition()
        self.continue_acquisition()

    def _generate_signal_stats(self, to_plot):
        stats = {}

        for signal_name, signal in to_plot.items():
            stats["%s_mean" % signal_name] = np.mean(signal)
            stats["%s_std" % signal_name] = np.std(signal)
            stats["%s_max" % signal_name] = np.max(signal)
            stats["%s_min" % signal_name] = np.min(signal)

        self.parameters.signal_stats.value = stats

    def exposed_write_data(self):
        """Syncs the parameters with the FPGA registers."""
        self.registers.write_registers()

    def task_running(self):
        return (self.parameters.autolock_running.value
                or self.parameters.optimization_running.value
                or self.parameters.psd_acquisition_running.value
                or self.parameters.psd_optimization_running.value)

    def exposed_start_autolock(self,
                               x0,
                               x1,
                               spectrum,
                               additional_spectra=None):
        spectrum = pickle.loads(spectrum)
        # start_watching = self.parameters.watch_lock.value
        start_watching = False
        auto_offset = self.parameters.autolock_determine_offset.value

        if not self.task_running():
            autolock = Autolock(self, self.parameters)
            self.parameters.task.value = autolock
            autolock.run(
                x0,
                x1,
                spectrum,
                should_watch_lock=start_watching,
                auto_offset=auto_offset,
                additional_spectra=pickle.loads(additional_spectra)
                if additional_spectra is not None else None,
            )

    def exposed_start_optimization(self, x0, x1, spectrum):
        if not self.task_running():
            optim = OptimizeSpectroscopy(self, self.parameters)
            self.parameters.task.value = optim
            optim.run(x0, x1, spectrum)

    def exposed_start_psd_acquisition(self):
        if not self.task_running():
            self.parameters.task.value = PSDAcquisition(self, self.parameters)
            self.parameters.task.value.run()

    def exposed_start_pid_optimization(self):
        if not self.task_running():
            self.parameters.task.value = PIDOptimization(self, self.parameters)
            self.parameters.task.value.run()

    def exposed_start_ramp(self):
        self.pause_acquisition()

        self.parameters.combined_offset.value = 0
        self.parameters.lock.value = False
        self.exposed_write_data()

        self.continue_acquisition()

    def exposed_start_lock(self):
        self.pause_acquisition()

        self.parameters.lock.value = True
        self.exposed_write_data()

        self.continue_acquisition()

    def exposed_shutdown(self):
        """Kills the server."""
        self.registers.acquisition.shutdown()
        _thread.interrupt_main()
        # we use SystemExit instead of os._exit because we want to call atexit
        # handlers
        raise SystemExit

    def exposed_get_server_version(self):
        import linien

        return linien.__version__

    def exposed_get_restorable_parameters(self):
        return self.parameters._restorable_parameters

    def exposed_pause_acquisition(self):
        self.pause_acquisition()

    def exposed_continue_acquisition(self):
        self.continue_acquisition()

    def exposed_set_csr_direct(self, k, v):
        """Directly sets a CSR register. This method is intended for debugging.
        Normally, the FPGA should be controlled via manipulation of parameters."""
        self.registers.set(k, v)

    def pause_acquisition(self):
        """Pause continuous acquisition. Call this before changing a parameter
        that alters the error / control signal. This way, no inconsistent signals
        reach the application. After setting the new parameter values, call
        `continue_acquisition`."""
        self.parameters.pause_acquisition.value = True
        self.data_uuid = random()
        self.registers.acquisition.pause_acquisition()

    def continue_acquisition(self):
        """Continue acquisition after a short delay, when we are sure that the
        new parameters values have been written to the FPGA and that data that
        is now recorded is recorded with the correct parameters."""
        self.parameters.pause_acquisition.value = False
        self.registers.acquisition.continue_acquisition(self.data_uuid)
Example #3
0
class Interp:
    def __init__(self):

        self.cmds = {
            'ADD': self.add,
            'ADDU': self.add,
            'SUB': self.add,
            'SUBU': self.add,
            'OR': self.add,
            'AND': self.add,
            'NOR': self.add,
            'XOR': self.add,
            'ADDI': self.addi,
            'ADDIU': self.addi,
            'SUBI': self.addi,
            'SUBIU': self.addi,
            'ANDI': self.addi,
            'ORI': self.addi,
            'XORI': self.addi,
            'LI': self.li,
            'MOVE': self.move,
            'SLT': self.slt,
            'SLTU': self.slt,
            'SLTI': self.slti,
            'SLTIU': self.slti,
            'SLL': self.sll,
            'SRL': self.sll,
            'J': self.j,
            'JAL': self.jal,
            'JR': self.jr,
            'BEQ': self.beq,
            'BNE': self.beq,
            'MULT': self.mult,
            'MULTU': self.mult,
            'DIV': self.div,
            'DIVU': self.div,
            'MFLO': self.mfhi,
            'MFHI': self.mfhi,
            'NOP': self.nop,
            'PYEVAL': self.pyeval,
            'PYJAL': self.pycall,
            'SYSCALL': self.pysyscall,
            'PYEXEC': self.pyexec,
            'LW': self.lw,
            'SW': self.lw,
        }
        self.regs = Registers()
        self.mem = Memory(32)

    def pcinc(self):
        pc = self.regs.get('pc')
        pc += 4
        self.regs.set('pc', pc, special=True)

    def add(self, name, d, s, t):
        sval = self.regs.get(s)
        tval = self.regs.get(t)

        if name == 'SUB' or name == 'SUBU':
            sval -= tval
        elif name == 'OR':
            sval |= tval
        elif name == 'AND':
            sval &= tval
        elif name == 'XOR':
            sval ^= tval
        elif name == 'NOR':
            sval = ~(sval | tval)
        else:
            sval += tval

        if name == 'ADDU' or name == 'SUBU':
            sval = abs(sval)

        self.regs.set(d, sval)
        self.pcinc()

    def addi(self, name, d, s, i):
        val = self.regs.get(s)

        if name == 'SUBI' or name == 'SUBIU':
            val -= i
        elif name == 'ADDI' or name == 'ADDIU':
            val += i
        elif name == 'ANDI':
            val &= i
        elif name == 'ORI':
            val |= i
        elif name == 'XORI':
            val ^= i

        if name == 'ADDIU' or name == 'SUBIU':
            val = abs(val)

        self.regs.set(d, val)
        self.pcinc()

    def li(self, name, d, i):
        self.addi('ADDI', d, '$0', i)

    def move(self, name, d, s):
        self.add('ADD', d, s, '$0')

    def slt(self, name, d, a, b):
        aval = self.regs.get(a)
        bval = self.regs.get(b)

        if name == 'SLTU':
            aval = abs(aval)
            bval = abs(bval)

        if aval < bval:
            val = 1
        else:
            val = 0

        self.regs.set(d, val)
        self.pcinc()

    def slti(self, name, d, a, imm):
        aval = self.regs.get(a)
        self.regs.set(d, int(aval < imm))
        self.pcinc()

    def sll(self, name, d, s, i):
        val = self.regs.get(s)

        if i > 5:
            i = 5

        if name == 'SLL':
            val <<= i
        elif name == 'SRL':
            val >>= i

        self.regs.set(d, val)
        self.pcinc()

    def j(self, name, addr):
        self.regs.set('pc', addr, special=True)

    def jr(self, name, r):
        self.regs.set('pc', self.regs.get(r), special=True)

    def jal(self, name, addr):
        self.regs.set('$ra', self.regs.get('pc') + 4)
        self.j('J', addr)

    def beq(self, name, a, b, addr):
        aval = self.regs.get(a)
        bval = self.regs.get(b)

        if name == 'BEQ':
            truth = (aval == bval)
        elif name == 'BNE':
            truth = (bval != aval)

        if truth:
            self.j('J', addr)
        else:
            self.pcinc()

    def mult(self, name, a, b):
        aval = self.regs.get(a)
        bval = self.regs.get(b)

        if name == 'MULT' or name == 'MULTU':
            aval *= bval

        # We're going to store high and low just cause
        hi = (aval & 0xFFFFFFFF00000000) >> 0x20
        lo = (aval & 0x00000000FFFFFFFF)
        self.regs.set('hi', int(hi), special=True)
        self.regs.set('lo', lo, special=True)
        self.pcinc()

    def div(self, name, a, b):
        aval = self.regs.get(a)
        bval = self.regs.get(b)

        if name == 'DIV' or name == 'DIVU':
            hi = aval / bval
            lo = aval % bval

        self.regs.set('hi', hi, special=True)
        self.regs.set('lo', lo, special=True)
        self.pcinc()

    def mfhi(self, name, to):
        if name == 'MFHI':
            val = self.regs.get('hi')
        elif name == 'MFLO':
            val = self.regs.get('lo')

        self.regs.set(to, val)
        self.pcinc()

    def nop(self, name):
        self.pcinc()

    def _ret_conv(self, val):
        if type(val) == int:
            return val
        try:
            res = int(val)
        except:
            res = 0xdeadbeef

        return res

    def pyeval(self, name, code):
        code = code[1:-1]
        res = eval(code)
        if type(res) in [list, tuple]:
            res0, res1 = res
            res0 = self._ret_conv(res0)
            res1 = self._ret_conv(res1)
            self.regs.set('$v0', res0)
            self.regs.set('$v1', res1)
        else:
            res = self._ret_conv(res)
            self.regs.set('$v0', res)

        self.pcinc()

    def pycall(self, name, func):
        args = [
            self.regs.get('$a0'),
            self.regs.get('$a1'),
            self.regs.get('$a2'),
            self.regs.get('$a3')
        ]
        args = repr(tuple(filter(lambda x: x != 0, args)))
        code = '"' + func + args + '"'
        self.pyeval("PYEVAL", code)

    def pyexec(self, name, code):
        eval(code)
        self.pcinc()

    def pysyscall(self, name, func):
        args = (self.regs.get('$a0'), self.regs.get('$a1'),
                self.regs.get('$a2'), self.regs.get('$a3'))
        code = '"' + func + '(self,' + repr(args) + ')"'
        self.pyeval("PYEVAL", code)

    def _addr_decode(self, addr):
        import re
        match = re.match("((\d+)?\((.*?)\)|(.*))", addr)
        if match:
            g = match.groups()
            if g[1]:
                offset = int(g[1])
            else:
                offset = 0

            if g[2]:
                reg = g[2]
            elif g[3]:
                reg = g[3]

        else:
            offset = 0
            reg = '$0'

        return offset, reg

    def lw(self, name, reg, addr):
        off, srcreg = self._addr_decode(addr)
        addr = self.regs.get(srcreg) + off

        if name == 'LW':
            self.regs.set(reg, self.mem.get(addr, 4))
        elif name == 'SW':
            self.mem.set(addr, 4, self.regs.get(reg))

        self.pcinc()

    def loader(self, code):
        self.mem.rom(0, code)

    def execute(self, args):
        inst = args[0]
        self.cmds[inst](*args)

    def run(self):
        while True:
            pc = self.regs.get('pc')
            inst = self.mem.rawget(pc)
            ij = []
            for e in inst:
                ij.append(str(e))
            ij[0] = "\033[1m" + ij[0] + "\033[0m"

            dbg = "\t\033[30m\033[1;34m*\033[0;37m%5d:\033[0m\t%s\033[0m\n" % (
                pc, " ".join(ij))
            sys.stderr.write(dbg)
            self.execute(inst)