forked from M-Labs/artiq
Merge branch 'master' into new-py2llvm
This commit is contained in:
commit
7903889082
|
@ -1,8 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
packages="https://people.phys.ethz.ch/~robertjo/artiq-dev/or1k-gcc_20141105-1_amd64.deb
|
packages="http://us.archive.ubuntu.com/ubuntu/pool/universe/i/iverilog/iverilog_0.9.7-1_amd64.deb"
|
||||||
https://people.phys.ethz.ch/~robertjo/artiq-dev/or1k-binutils_20141105-1_amd64.deb
|
archives="http://fehu.whitequark.org/files/binutils-or1k.tbz2 http://fehu.whitequark.org/files/llvm-or1k.tbz2"
|
||||||
http://us.archive.ubuntu.com/ubuntu/pool/universe/i/iverilog/iverilog_0.9.7-1_amd64.deb"
|
|
||||||
|
|
||||||
mkdir -p packages
|
mkdir -p packages
|
||||||
|
|
||||||
|
@ -13,12 +12,18 @@ do
|
||||||
dpkg -x $pkg_name packages
|
dpkg -x $pkg_name packages
|
||||||
done
|
done
|
||||||
|
|
||||||
export PATH=$PWD/packages/usr/local/bin:$PWD/packages/usr/bin:$PATH
|
for a in $archives
|
||||||
|
do
|
||||||
|
wget $a
|
||||||
|
(cd packages && tar xvf ../$(basename $a))
|
||||||
|
done
|
||||||
|
|
||||||
|
export PATH=$PWD/packages/usr/local/llvm-or1k/bin:$PWD/packages/usr/local/bin:$PWD/packages/usr/bin:$PATH
|
||||||
export LD_LIBRARY_PATH=$PWD/packages/usr/lib/x86_64-linux-gnu:$PWD/packages/usr/local/x86_64-unknown-linux-gnu/or1k-elf/lib:$LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH=$PWD/packages/usr/lib/x86_64-linux-gnu:$PWD/packages/usr/local/x86_64-unknown-linux-gnu/or1k-elf/lib:$LD_LIBRARY_PATH
|
||||||
|
|
||||||
echo -e "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> $HOME/.mlabs/build_settings.sh
|
echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> $HOME/.mlabs/build_settings.sh
|
||||||
|
echo "export PATH=$PWD/packages/usr/local/llvm-or1k/bin:$PATH" >> $HOME/.mlabs/build_settings.sh
|
||||||
|
|
||||||
or1k-elf-as --version
|
or1k-linux-as --version
|
||||||
or1k-elf-gcc --version
|
llc --version
|
||||||
clang --version
|
clang --version
|
||||||
llvm-as --version || true
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ from artiq.gui.results import ResultsDock
|
||||||
from artiq.gui.parameters import ParametersDock
|
from artiq.gui.parameters import ParametersDock
|
||||||
from artiq.gui.schedule import ScheduleDock
|
from artiq.gui.schedule import ScheduleDock
|
||||||
from artiq.gui.log import LogDock
|
from artiq.gui.log import LogDock
|
||||||
|
from artiq.gui.console import ConsoleDock
|
||||||
|
|
||||||
|
|
||||||
data_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
data_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
||||||
|
@ -99,7 +100,7 @@ def main():
|
||||||
area.addDock(d_params, "above", d_results)
|
area.addDock(d_params, "above", d_results)
|
||||||
area.addDock(d_explorer, "above", d_params)
|
area.addDock(d_explorer, "above", d_params)
|
||||||
|
|
||||||
d_schedule = ScheduleDock(schedule_ctl)
|
d_schedule = ScheduleDock(status_bar, schedule_ctl)
|
||||||
loop.run_until_complete(d_schedule.sub_connect(
|
loop.run_until_complete(d_schedule.sub_connect(
|
||||||
args.server, args.port_notify))
|
args.server, args.port_notify))
|
||||||
atexit.register(lambda: loop.run_until_complete(d_schedule.sub_close()))
|
atexit.register(lambda: loop.run_until_complete(d_schedule.sub_close()))
|
||||||
|
@ -109,7 +110,19 @@ def main():
|
||||||
args.server, args.port_notify))
|
args.server, args.port_notify))
|
||||||
atexit.register(lambda: loop.run_until_complete(d_log.sub_close()))
|
atexit.register(lambda: loop.run_until_complete(d_log.sub_close()))
|
||||||
|
|
||||||
area.addDock(d_log, "bottom")
|
pdb = AsyncioClient()
|
||||||
|
loop.run_until_complete(pdb.connect_rpc(
|
||||||
|
args.server, args.port_control, "master_pdb"))
|
||||||
|
atexit.register(lambda: pdb.close_rpc())
|
||||||
|
def _get_parameter(k, v):
|
||||||
|
asyncio.async(pdb.set(k, v))
|
||||||
|
d_console = ConsoleDock(
|
||||||
|
d_params.get_parameter,
|
||||||
|
_get_parameter,
|
||||||
|
d_results.get_result)
|
||||||
|
|
||||||
|
area.addDock(d_console, "bottom")
|
||||||
|
area.addDock(d_log, "above", d_console)
|
||||||
area.addDock(d_schedule, "above", d_log)
|
area.addDock(d_schedule, "above", d_log)
|
||||||
|
|
||||||
win.show()
|
win.show()
|
||||||
|
|
|
@ -26,7 +26,7 @@ class ELFRunner(EnvExperiment):
|
||||||
def run(self):
|
def run(self):
|
||||||
with open(self.file, "rb") as f:
|
with open(self.file, "rb") as f:
|
||||||
self.core.comm.load(f.read())
|
self.core.comm.load(f.read())
|
||||||
self.core.comm.run("run", False)
|
self.core.comm.run("run")
|
||||||
self.core.comm.serve(dict(), dict())
|
self.core.comm.serve(dict(), dict())
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
from pyqtgraph import console, dockarea
|
||||||
|
|
||||||
|
|
||||||
|
_help = """
|
||||||
|
This is an interactive Python console.
|
||||||
|
|
||||||
|
The following functions are available:
|
||||||
|
get_parameter(key)
|
||||||
|
set_parameter(key, value) [asynchronous update]
|
||||||
|
get_result(key) [real-time results only]
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
class ConsoleDock(dockarea.Dock):
|
||||||
|
def __init__(self, get_parameter, set_parameter, get_result):
|
||||||
|
dockarea.Dock.__init__(self, "Console", size=(1000, 300))
|
||||||
|
ns = {
|
||||||
|
"get_parameter": get_parameter,
|
||||||
|
"set_parameter": set_parameter,
|
||||||
|
"get_result": get_result
|
||||||
|
}
|
||||||
|
c = console.ConsoleWidget(namespace=ns, text=_help)
|
||||||
|
self.addWidget(c)
|
|
@ -7,7 +7,7 @@ from pyqtgraph import LayoutWidget
|
||||||
|
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
from artiq.protocols.sync_struct import Subscriber
|
||||||
from artiq.protocols import pyon
|
from artiq.protocols import pyon
|
||||||
from artiq.gui.tools import DictSyncModel
|
from artiq.gui.tools import DictSyncModel, force_spinbox_value
|
||||||
from artiq.gui.scan import ScanController
|
from artiq.gui.scan import ScanController
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ class _NumberEntry(QtGui.QDoubleSpinBox):
|
||||||
if procdesc["unit"]:
|
if procdesc["unit"]:
|
||||||
self.setSuffix(" " + procdesc["unit"])
|
self.setSuffix(" " + procdesc["unit"])
|
||||||
if "default" in procdesc:
|
if "default" in procdesc:
|
||||||
self.setValue(procdesc["default"])
|
force_spinbox_value(self, procdesc["default"])
|
||||||
|
|
||||||
def get_argument_value(self):
|
def get_argument_value(self):
|
||||||
return self.value()
|
return self.value()
|
||||||
|
|
|
@ -12,6 +12,15 @@ class _LogModel(ListSyncModel):
|
||||||
ListSyncModel.__init__(self,
|
ListSyncModel.__init__(self,
|
||||||
["RID", "Message"],
|
["RID", "Message"],
|
||||||
parent, init)
|
parent, init)
|
||||||
|
self.fixed_font = QtGui.QFont()
|
||||||
|
self.fixed_font.setFamily("Monospace")
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if (role == QtCore.Qt.FontRole and index.isValid()
|
||||||
|
and index.column() == 1):
|
||||||
|
return self.fixed_font
|
||||||
|
else:
|
||||||
|
return ListSyncModel.data(self, index, role)
|
||||||
|
|
||||||
def convert(self, v, column):
|
def convert(self, v, column):
|
||||||
return v[column]
|
return v[column]
|
||||||
|
|
|
@ -34,7 +34,7 @@ class ParametersDock(dockarea.Dock):
|
||||||
|
|
||||||
self.search = QtGui.QLineEdit()
|
self.search = QtGui.QLineEdit()
|
||||||
self.search.setPlaceholderText("search...")
|
self.search.setPlaceholderText("search...")
|
||||||
self.search.editingFinished.connect(self.search_parameters)
|
self.search.editingFinished.connect(self._search_parameters)
|
||||||
grid.addWidget(self.search, 0, 0)
|
grid.addWidget(self.search, 0, 0)
|
||||||
|
|
||||||
self.table = QtGui.QTableView()
|
self.table = QtGui.QTableView()
|
||||||
|
@ -43,7 +43,10 @@ class ParametersDock(dockarea.Dock):
|
||||||
QtGui.QHeaderView.ResizeToContents)
|
QtGui.QHeaderView.ResizeToContents)
|
||||||
grid.addWidget(self.table, 1, 0)
|
grid.addWidget(self.table, 1, 0)
|
||||||
|
|
||||||
def search_parameters(self):
|
def get_parameter(self, key):
|
||||||
|
return self.table_model.backing_store[key]
|
||||||
|
|
||||||
|
def _search_parameters(self):
|
||||||
model = self.table.model()
|
model = self.table.model()
|
||||||
parentIndex = model.index(0, 0)
|
parentIndex = model.index(0, 0)
|
||||||
numRows = model.rowCount(parentIndex)
|
numRows = model.rowCount(parentIndex)
|
||||||
|
@ -66,6 +69,6 @@ class ParametersDock(dockarea.Dock):
|
||||||
yield from self.subscriber.close()
|
yield from self.subscriber.close()
|
||||||
|
|
||||||
def init_parameters_model(self, init):
|
def init_parameters_model(self, init):
|
||||||
table_model = ParametersModel(self.table, init)
|
self.table_model = ParametersModel(self.table, init)
|
||||||
self.table.setModel(table_model)
|
self.table.setModel(self.table_model)
|
||||||
return table_model
|
return self.table_model
|
||||||
|
|
|
@ -55,6 +55,9 @@ class ResultsDock(dockarea.Dock):
|
||||||
|
|
||||||
self.displays = dict()
|
self.displays = dict()
|
||||||
|
|
||||||
|
def get_result(self, key):
|
||||||
|
return self.table_model.backing_store[key]
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def sub_connect(self, host, port):
|
def sub_connect(self, host, port):
|
||||||
self.subscriber = Subscriber("rt_results", self.init_results_model,
|
self.subscriber = Subscriber("rt_results", self.init_results_model,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from quamash import QtGui
|
from quamash import QtGui
|
||||||
from pyqtgraph import LayoutWidget
|
from pyqtgraph import LayoutWidget
|
||||||
|
|
||||||
|
from artiq.gui.tools import force_spinbox_value
|
||||||
|
|
||||||
|
|
||||||
class _Range(LayoutWidget):
|
class _Range(LayoutWidget):
|
||||||
def __init__(self, global_min, global_max, global_step, unit):
|
def __init__(self, global_min, global_max, global_step, unit):
|
||||||
|
@ -33,9 +35,9 @@ class _Range(LayoutWidget):
|
||||||
self.addWidget(self.npoints, 0, 5)
|
self.addWidget(self.npoints, 0, 5)
|
||||||
|
|
||||||
def set_values(self, min, max, npoints):
|
def set_values(self, min, max, npoints):
|
||||||
self.min.setValue(min)
|
force_spinbox_value(self.min, min)
|
||||||
self.max.setValue(max)
|
force_spinbox_value(self.max, max)
|
||||||
self.npoints.setValue(npoints)
|
force_spinbox_value(self.npoints, npoints)
|
||||||
|
|
||||||
def get_values(self):
|
def get_values(self):
|
||||||
return {
|
return {
|
||||||
|
@ -97,13 +99,13 @@ class ScanController(LayoutWidget):
|
||||||
d = procdesc["default"]
|
d = procdesc["default"]
|
||||||
if d["ty"] == "NoScan":
|
if d["ty"] == "NoScan":
|
||||||
self.noscan.setChecked(True)
|
self.noscan.setChecked(True)
|
||||||
self.v_noscan.setValue(d["value"])
|
force_spinbox_value(self.v_noscan, d["value"])
|
||||||
elif d["ty"] == "LinearScan":
|
elif d["ty"] == "LinearScan":
|
||||||
self.linear.setChecked(True)
|
self.linear.setChecked(True)
|
||||||
self.v_linear.set_values(d["min"], d["max"], d["step"])
|
self.v_linear.set_values(d["min"], d["max"], d["npoints"])
|
||||||
elif d["ty"] == "RandomScan":
|
elif d["ty"] == "RandomScan":
|
||||||
self.random.setChecked(True)
|
self.random.setChecked(True)
|
||||||
self.v_random.set_values(d["min"], d["max"], d["step"])
|
self.v_random.set_values(d["min"], d["max"], d["npoints"])
|
||||||
elif d["ty"] == "ExplicitScan":
|
elif d["ty"] == "ExplicitScan":
|
||||||
self.explicit.setChecked(True)
|
self.explicit.setChecked(True)
|
||||||
self.v_explicit.insert(" ".join(
|
self.v_explicit.insert(" ".join(
|
||||||
|
|
|
@ -46,9 +46,10 @@ class _ScheduleModel(DictSyncModel):
|
||||||
|
|
||||||
|
|
||||||
class ScheduleDock(dockarea.Dock):
|
class ScheduleDock(dockarea.Dock):
|
||||||
def __init__(self, schedule_ctl):
|
def __init__(self, status_bar, schedule_ctl):
|
||||||
dockarea.Dock.__init__(self, "Schedule", size=(1000, 300))
|
dockarea.Dock.__init__(self, "Schedule", size=(1000, 300))
|
||||||
|
|
||||||
|
self.status_bar = status_bar
|
||||||
self.schedule_ctl = schedule_ctl
|
self.schedule_ctl = schedule_ctl
|
||||||
|
|
||||||
self.table = QtGui.QTableView()
|
self.table = QtGui.QTableView()
|
||||||
|
@ -86,4 +87,5 @@ class ScheduleDock(dockarea.Dock):
|
||||||
if idx:
|
if idx:
|
||||||
row = idx[0].row()
|
row = idx[0].row()
|
||||||
rid = self.table_model.row_to_key[row]
|
rid = self.table_model.row_to_key[row]
|
||||||
|
self.status_bar.showMessage("Deleted RID {}".format(rid))
|
||||||
asyncio.async(self.delete(rid))
|
asyncio.async(self.delete(rid))
|
||||||
|
|
|
@ -1,10 +1,23 @@
|
||||||
from quamash import QtCore
|
from quamash import QtCore
|
||||||
|
|
||||||
|
|
||||||
|
def force_spinbox_value(spinbox, value):
|
||||||
|
if spinbox.minimum() > value:
|
||||||
|
spinbox.setMinimum(value)
|
||||||
|
if spinbox.maximum() < value:
|
||||||
|
spinbox.setMaximum(value)
|
||||||
|
spinbox.setValue(value)
|
||||||
|
|
||||||
|
|
||||||
def short_format(v):
|
def short_format(v):
|
||||||
t = type(v)
|
t = type(v)
|
||||||
if t is int or t is float:
|
if t is int or t is float:
|
||||||
return str(v)
|
return str(v)
|
||||||
|
elif t is str:
|
||||||
|
if len(v) < 15:
|
||||||
|
return "\"" + v + "\""
|
||||||
|
else:
|
||||||
|
return "\"" + v[:12] + "\"..."
|
||||||
else:
|
else:
|
||||||
r = t.__name__
|
r = t.__name__
|
||||||
if t is list or t is dict or t is set:
|
if t is list or t is dict or t is set:
|
||||||
|
|
|
@ -9,7 +9,6 @@ and modifications to mutable types are not written back. For example, if the
|
||||||
client passes a list as a parameter of an RPC method, and that method
|
client passes a list as a parameter of an RPC method, and that method
|
||||||
``append()s`` an element to the list, the element is not appended to the
|
``append()s`` an element to the list, the element is not appended to the
|
||||||
client's list.
|
client's list.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
|
@ -29,17 +28,13 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class RemoteError(Exception):
|
class RemoteError(Exception):
|
||||||
"""Raised when a RPC failed or raised an exception on the remote (server)
|
"""Raised when a RPC failed or raised an exception on the remote (server)
|
||||||
side.
|
side."""
|
||||||
|
|
||||||
"""
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IncompatibleServer(Exception):
|
class IncompatibleServer(Exception):
|
||||||
"""Raised by the client when attempting to connect to a server that does
|
"""Raised by the client when attempting to connect to a server that does
|
||||||
not have the expected target.
|
not have the expected target."""
|
||||||
|
|
||||||
"""
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,7 +69,6 @@ class Client:
|
||||||
Use ``None`` to skip selecting a target. The list of targets can then
|
Use ``None`` to skip selecting a target. The list of targets can then
|
||||||
be retrieved using ``get_rpc_id`` and then one can be selected later
|
be retrieved using ``get_rpc_id`` and then one can be selected later
|
||||||
using ``select_rpc_target``.
|
using ``select_rpc_target``.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, host, port, target_name):
|
def __init__(self, host, port, target_name):
|
||||||
self.__socket = socket.create_connection((host, port))
|
self.__socket = socket.create_connection((host, port))
|
||||||
|
@ -93,25 +87,20 @@ class Client:
|
||||||
|
|
||||||
def select_rpc_target(self, target_name):
|
def select_rpc_target(self, target_name):
|
||||||
"""Selects a RPC target by name. This function should be called
|
"""Selects a RPC target by name. This function should be called
|
||||||
exactly once if the object was created with ``target_name=None``.
|
exactly once if the object was created with ``target_name=None``."""
|
||||||
|
|
||||||
"""
|
|
||||||
if target_name not in self.__target_names:
|
if target_name not in self.__target_names:
|
||||||
raise IncompatibleServer
|
raise IncompatibleServer
|
||||||
self.__socket.sendall((target_name + "\n").encode())
|
self.__socket.sendall((target_name + "\n").encode())
|
||||||
|
|
||||||
def get_rpc_id(self):
|
def get_rpc_id(self):
|
||||||
"""Returns a tuple (target_names, id_parameters) containing the
|
"""Returns a tuple (target_names, id_parameters) containing the
|
||||||
identification information of the server.
|
identification information of the server."""
|
||||||
|
|
||||||
"""
|
|
||||||
return (self.__target_names, self.__id_parameters)
|
return (self.__target_names, self.__id_parameters)
|
||||||
|
|
||||||
def close_rpc(self):
|
def close_rpc(self):
|
||||||
"""Closes the connection to the RPC server.
|
"""Closes the connection to the RPC server.
|
||||||
|
|
||||||
No further method calls should be done after this method is called.
|
No further method calls should be done after this method is called.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.__socket.close()
|
self.__socket.close()
|
||||||
|
|
||||||
|
@ -159,6 +148,8 @@ class AsyncioClient:
|
||||||
|
|
||||||
All RPC methods are coroutines.
|
All RPC methods are coroutines.
|
||||||
|
|
||||||
|
Concurrent access from different asyncio tasks is supported; all calls
|
||||||
|
use a single lock.
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__lock = asyncio.Lock()
|
self.__lock = asyncio.Lock()
|
||||||
|
@ -171,9 +162,7 @@ class AsyncioClient:
|
||||||
def connect_rpc(self, host, port, target_name):
|
def connect_rpc(self, host, port, target_name):
|
||||||
"""Connects to the server. This cannot be done in __init__ because
|
"""Connects to the server. This cannot be done in __init__ because
|
||||||
this method is a coroutine. See ``Client`` for a description of the
|
this method is a coroutine. See ``Client`` for a description of the
|
||||||
parameters.
|
parameters."""
|
||||||
|
|
||||||
"""
|
|
||||||
self.__reader, self.__writer = \
|
self.__reader, self.__writer = \
|
||||||
yield from asyncio.open_connection(host, port)
|
yield from asyncio.open_connection(host, port)
|
||||||
try:
|
try:
|
||||||
|
@ -190,7 +179,6 @@ class AsyncioClient:
|
||||||
def select_rpc_target(self, target_name):
|
def select_rpc_target(self, target_name):
|
||||||
"""Selects a RPC target by name. This function should be called
|
"""Selects a RPC target by name. This function should be called
|
||||||
exactly once if the connection was created with ``target_name=None``.
|
exactly once if the connection was created with ``target_name=None``.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if target_name not in self.__target_names:
|
if target_name not in self.__target_names:
|
||||||
raise IncompatibleServer
|
raise IncompatibleServer
|
||||||
|
@ -198,16 +186,13 @@ class AsyncioClient:
|
||||||
|
|
||||||
def get_rpc_id(self):
|
def get_rpc_id(self):
|
||||||
"""Returns a tuple (target_names, id_parameters) containing the
|
"""Returns a tuple (target_names, id_parameters) containing the
|
||||||
identification information of the server.
|
identification information of the server."""
|
||||||
|
|
||||||
"""
|
|
||||||
return (self.__target_names, self.__id_parameters)
|
return (self.__target_names, self.__id_parameters)
|
||||||
|
|
||||||
def close_rpc(self):
|
def close_rpc(self):
|
||||||
"""Closes the connection to the RPC server.
|
"""Closes the connection to the RPC server.
|
||||||
|
|
||||||
No further method calls should be done after this method is called.
|
No further method calls should be done after this method is called.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.__writer.close()
|
self.__writer.close()
|
||||||
self.__reader = None
|
self.__reader = None
|
||||||
|
@ -261,7 +246,6 @@ class BestEffortClient:
|
||||||
connection attempt at object initialization.
|
connection attempt at object initialization.
|
||||||
:param retry: Amount of time to wait between retries when reconnecting
|
:param retry: Amount of time to wait between retries when reconnecting
|
||||||
in the background.
|
in the background.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, host, port, target_name,
|
def __init__(self, host, port, target_name,
|
||||||
firstcon_timeout=0.5, retry=5.0):
|
firstcon_timeout=0.5, retry=5.0):
|
||||||
|
@ -322,7 +306,6 @@ class BestEffortClient:
|
||||||
"""Closes the connection to the RPC server.
|
"""Closes the connection to the RPC server.
|
||||||
|
|
||||||
No further method calls should be done after this method is called.
|
No further method calls should be done after this method is called.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self.__conretry_thread is None:
|
if self.__conretry_thread is None:
|
||||||
if self.__socket is not None:
|
if self.__socket is not None:
|
||||||
|
@ -415,7 +398,6 @@ class Server(_AsyncioServer):
|
||||||
Clients select one of these objects using its name upon connection.
|
Clients select one of these objects using its name upon connection.
|
||||||
:param id_parameters: An optional human-readable string giving more
|
:param id_parameters: An optional human-readable string giving more
|
||||||
information about the parameters of the server.
|
information about the parameters of the server.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, targets, id_parameters=None):
|
def __init__(self, targets, id_parameters=None):
|
||||||
_AsyncioServer.__init__(self)
|
_AsyncioServer.__init__(self)
|
||||||
|
@ -485,7 +467,6 @@ def simple_server_loop(targets, host, port, id_parameters=None):
|
||||||
"""Runs a server until an exception is raised (e.g. the user hits Ctrl-C).
|
"""Runs a server until an exception is raised (e.g. the user hits Ctrl-C).
|
||||||
|
|
||||||
See ``Server`` for a description of the parameters.
|
See ``Server`` for a description of the parameters.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -39,6 +39,16 @@ _encode_map = {
|
||||||
numpy.ndarray: "nparray"
|
numpy.ndarray: "nparray"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_numpy_scalar = {
|
||||||
|
"int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64",
|
||||||
|
"float16", "float32", "float64"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for _t in _numpy_scalar:
|
||||||
|
_encode_map[getattr(numpy, _t)] = "npscalar"
|
||||||
|
|
||||||
|
|
||||||
class _Encoder:
|
class _Encoder:
|
||||||
def __init__(self, pretty):
|
def __init__(self, pretty):
|
||||||
self.pretty = pretty
|
self.pretty = pretty
|
||||||
|
@ -114,6 +124,13 @@ class _Encoder:
|
||||||
r += ")"
|
r += ")"
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
def encode_npscalar(self, x):
|
||||||
|
r = "npscalar("
|
||||||
|
r += "\"" + type(x).__name__ + "\", "
|
||||||
|
r += encode(base64.b64encode(x).decode())
|
||||||
|
r += ")"
|
||||||
|
return r
|
||||||
|
|
||||||
def encode(self, x):
|
def encode(self, x):
|
||||||
return getattr(self, "encode_" + _encode_map[type(x)])(x)
|
return getattr(self, "encode_" + _encode_map[type(x)])(x)
|
||||||
|
|
||||||
|
@ -131,6 +148,10 @@ def _nparray(shape, dtype, data):
|
||||||
return a.reshape(shape)
|
return a.reshape(shape)
|
||||||
|
|
||||||
|
|
||||||
|
def _npscalar(ty, data):
|
||||||
|
return numpy.frombuffer(base64.b64decode(data), dtype=ty)[0]
|
||||||
|
|
||||||
|
|
||||||
_eval_dict = {
|
_eval_dict = {
|
||||||
"__builtins__": None,
|
"__builtins__": None,
|
||||||
|
|
||||||
|
@ -139,7 +160,8 @@ _eval_dict = {
|
||||||
"true": True,
|
"true": True,
|
||||||
|
|
||||||
"Fraction": Fraction,
|
"Fraction": Fraction,
|
||||||
"nparray": _nparray
|
"nparray": _nparray,
|
||||||
|
"npscalar": _npscalar
|
||||||
}
|
}
|
||||||
|
|
||||||
def decode(s):
|
def decode(s):
|
||||||
|
|
|
@ -4,14 +4,15 @@ from fractions import Fraction
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from artiq.language.units import *
|
|
||||||
from artiq.protocols import pyon
|
from artiq.protocols import pyon
|
||||||
|
|
||||||
|
|
||||||
_pyon_test_object = {
|
_pyon_test_object = {
|
||||||
(1, 2): [(3, 4.2), (2, )],
|
(1, 2): [(3, 4.2), (2, )],
|
||||||
Fraction(3, 4): np.linspace(5, 10, 1),
|
Fraction(3, 4): np.linspace(5, 10, 1),
|
||||||
"frequency": 10*GHz
|
"a": np.int8(9), "b": np.int16(-98), "c": np.int32(42), "d": np.int64(-5),
|
||||||
|
"e": np.uint8(8), "f": np.uint16(5), "g": np.uint32(4), "h": np.uint64(9),
|
||||||
|
"x": np.float16(9.0), "y": np.float32(9.0), "z": np.float64(9.0),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,9 @@ from unittest.mock import MagicMock
|
||||||
class Mock(MagicMock):
|
class Mock(MagicMock):
|
||||||
@classmethod
|
@classmethod
|
||||||
def __getattr__(cls, name):
|
def __getattr__(cls, name):
|
||||||
return Mock()
|
if name == "_mock_methods":
|
||||||
|
return None
|
||||||
|
return Mock()
|
||||||
|
|
||||||
|
|
||||||
mock_modules = ["artiq.gui.moninj", "quamash", "pyqtgraph", "matplotlib"]
|
mock_modules = ["artiq.gui.moninj", "quamash", "pyqtgraph", "matplotlib"]
|
||||||
|
|
|
@ -70,7 +70,52 @@ Next step (for KC705) is to flash MAC and IP addresses to the board:
|
||||||
Installing from source
|
Installing from source
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
You can skip this if you already installed from conda.
|
You can skip the first two steps if you already installed from conda.
|
||||||
|
|
||||||
|
Preparing the build environment for the core device
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These steps are required to generate code that can run on the core
|
||||||
|
device. They are necessary both for building the MiSoC BIOS
|
||||||
|
and the ARTIQ kernels.
|
||||||
|
|
||||||
|
* Create a development directory: ::
|
||||||
|
|
||||||
|
$ mkdir ~/artiq-dev
|
||||||
|
|
||||||
|
* Install OpenRISC binutils (or1k-linux-...): ::
|
||||||
|
|
||||||
|
$ cd ~/artiq-dev
|
||||||
|
$ wget https://ftp.gnu.org/gnu/binutils/binutils-2.25.1.tar.bz2
|
||||||
|
$ tar xvf binutils-2.25.1.tar.bz2
|
||||||
|
$ rm binutils-2.25.1.tar.bz2
|
||||||
|
|
||||||
|
$ mkdir binutils-2.25.1/build
|
||||||
|
$ cd binutils-2.25.1/build
|
||||||
|
$ ../configure --target=or1k-linux --prefix=/usr/local
|
||||||
|
$ make -j4
|
||||||
|
$ sudo make install
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
We're using an ``or1k-linux`` target because it is necessary to enable
|
||||||
|
shared library support in ``ld``, not because Linux is involved.
|
||||||
|
|
||||||
|
* Install LLVM and Clang: ::
|
||||||
|
|
||||||
|
$ cd ~/artiq-dev
|
||||||
|
$ git clone https://github.com/openrisc/llvm-or1k
|
||||||
|
$ cd llvm-or1k/tools
|
||||||
|
$ git clone https://github.com/openrisc/clang-or1k clang
|
||||||
|
$ cd ..
|
||||||
|
|
||||||
|
$ mkdir build
|
||||||
|
$ cd build
|
||||||
|
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/llvm-or1k -DLLVM_TARGETS_TO_BUILD="OR1K;X86" -DCMAKE_BUILD_TYPE=Rel -DLLVM_ENABLE_ASSERTIONS=ON
|
||||||
|
$ make -j4
|
||||||
|
$ sudo make install
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Compilation of LLVM can take more than 30 min on some machines.
|
||||||
|
|
||||||
Preparing the core device FPGA board
|
Preparing the core device FPGA board
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -85,10 +130,6 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
|
||||||
|
|
||||||
* During the Xilinx toolchain installation, uncheck ``Install cable drivers`` (they are not required as we use better and open source alternatives).
|
* During the Xilinx toolchain installation, uncheck ``Install cable drivers`` (they are not required as we use better and open source alternatives).
|
||||||
|
|
||||||
* Create a development directory: ::
|
|
||||||
|
|
||||||
$ mkdir ~/artiq-dev
|
|
||||||
|
|
||||||
* Install Migen: ::
|
* Install Migen: ::
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
$ cd ~/artiq-dev
|
||||||
|
@ -99,31 +140,6 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
|
||||||
.. note::
|
.. note::
|
||||||
The options ``develop`` and ``--user`` are for setup.py to install Migen in ``~/.local/lib/python3.4``.
|
The options ``develop`` and ``--user`` are for setup.py to install Migen in ``~/.local/lib/python3.4``.
|
||||||
|
|
||||||
* Install OpenRISC GCC/binutils toolchain (or1k-elf-...): ::
|
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
|
||||||
$ git clone https://github.com/openrisc/or1k-src
|
|
||||||
$ cd or1k-src
|
|
||||||
$ mkdir build
|
|
||||||
$ cd build
|
|
||||||
$ ../configure --target=or1k-elf --enable-shared --disable-itcl \
|
|
||||||
--disable-tk --disable-tcl --disable-winsup \
|
|
||||||
--disable-gdbtk --disable-libgui --disable-rda \
|
|
||||||
--disable-sid --disable-sim --disable-gdb \
|
|
||||||
--disable-newlib --disable-libgloss --disable-werror
|
|
||||||
$ make -j4
|
|
||||||
$ sudo make install
|
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
|
||||||
$ git clone https://github.com/openrisc/or1k-gcc
|
|
||||||
$ cd or1k-gcc
|
|
||||||
$ mkdir build
|
|
||||||
$ cd build
|
|
||||||
$ ../configure --target=or1k-elf --enable-languages=c \
|
|
||||||
--disable-shared --disable-libssp
|
|
||||||
$ make -j4
|
|
||||||
$ sudo make install
|
|
||||||
|
|
||||||
.. _install-xc3sprog:
|
.. _install-xc3sprog:
|
||||||
|
|
||||||
* Install JTAG tools needed to program the Pipistrello and KC705:
|
* Install JTAG tools needed to program the Pipistrello and KC705:
|
||||||
|
@ -181,6 +197,7 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
|
||||||
::
|
::
|
||||||
|
|
||||||
$ cd ~/artiq-dev/misoc
|
$ cd ~/artiq-dev/misoc
|
||||||
|
$ export PATH=$PATH:/usr/local/llvm-or1k/bin
|
||||||
|
|
||||||
* For Pipistrello::
|
* For Pipistrello::
|
||||||
|
|
||||||
|
@ -279,19 +296,7 @@ To flash the ``idle`` kernel:
|
||||||
Installing the host-side software
|
Installing the host-side software
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
* Install LLVM and the llvmlite Python bindings: ::
|
* Install the llvmlite Python bindings: ::
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
|
||||||
$ git clone https://github.com/openrisc/llvm-or1k
|
|
||||||
$ cd llvm-or1k/tools
|
|
||||||
$ git clone https://github.com/openrisc/clang-or1k clang
|
|
||||||
|
|
||||||
$ cd ..
|
|
||||||
$ mkdir build
|
|
||||||
$ cd build
|
|
||||||
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/llvm-or1k -DLLVM_TARGETS_TO_BUILD="OR1K;X86" -DCMAKE_BUILD_TYPE=Debug
|
|
||||||
$ make -j4
|
|
||||||
$ sudo make install
|
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
$ cd ~/artiq-dev
|
||||||
$ git clone https://github.com/numba/llvmlite
|
$ git clone https://github.com/numba/llvmlite
|
||||||
|
@ -299,14 +304,11 @@ Installing the host-side software
|
||||||
$ patch -p1 < ~/artiq-dev/artiq/misc/llvmlite-add-all-targets.patch
|
$ patch -p1 < ~/artiq-dev/artiq/misc/llvmlite-add-all-targets.patch
|
||||||
$ patch -p1 < ~/artiq-dev/artiq/misc/llvmlite-rename.patch
|
$ patch -p1 < ~/artiq-dev/artiq/misc/llvmlite-rename.patch
|
||||||
$ patch -p1 < ~/artiq-dev/artiq/misc/llvmlite-build-as-debug-on-windows.patch
|
$ patch -p1 < ~/artiq-dev/artiq/misc/llvmlite-build-as-debug-on-windows.patch
|
||||||
$ PATH=/usr/local/llvm-or1k/bin:$PATH sudo -E python3 setup.py install
|
$ LLVM_CONFIG=/usr/local/llvm-or1k/bin/llvm-config python3 setup.py install --user
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
llvmlite is in development and its API is not stable yet. Commit ID ``11a8303d02e3d6dd2d1e0e9065701795cd8a979f`` is known to work.
|
llvmlite is in development and its API is not stable yet. Commit ID ``11a8303d02e3d6dd2d1e0e9065701795cd8a979f`` is known to work.
|
||||||
|
|
||||||
.. note::
|
|
||||||
Compilation of LLVM can take more than 30 min on some machines.
|
|
||||||
|
|
||||||
* Install ARTIQ: ::
|
* Install ARTIQ: ::
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
$ cd ~/artiq-dev
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 18}
|
"arguments": {"channel": 17}
|
||||||
},
|
},
|
||||||
|
|
||||||
"dds_bus": {
|
"dds_bus": {
|
||||||
|
|
|
@ -27,12 +27,11 @@ class FloppingF(EnvExperiment):
|
||||||
"""Flopping F simulation"""
|
"""Flopping F simulation"""
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
self.attr_argument("npoints", FreeValue(100))
|
self.attr_argument("frequency_scan", Scannable(
|
||||||
self.attr_argument("min_freq", FreeValue(1000))
|
default=LinearScan(1000, 2000, 100)))
|
||||||
self.attr_argument("max_freq", FreeValue(2000))
|
|
||||||
|
|
||||||
self.attr_argument("F0", FreeValue(1500))
|
self.attr_argument("F0", NumberValue(1500, min=1000, max=2000))
|
||||||
self.attr_argument("noise_amplitude", FreeValue(0.1))
|
self.attr_argument("noise_amplitude", NumberValue(0.1, min=0, max=100))
|
||||||
|
|
||||||
self.frequency = self.set_result("flopping_f_frequency", [], True)
|
self.frequency = self.set_result("flopping_f_frequency", [], True)
|
||||||
self.brightness = self.set_result("flopping_f_brightness", [], True)
|
self.brightness = self.set_result("flopping_f_brightness", [], True)
|
||||||
|
@ -40,8 +39,7 @@ class FloppingF(EnvExperiment):
|
||||||
self.attr_device("scheduler")
|
self.attr_device("scheduler")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
for i in range(self.npoints):
|
for frequency in self.frequency_scan:
|
||||||
frequency = (self.max_freq-self.min_freq)*i/(self.npoints - 1) + self.min_freq
|
|
||||||
brightness = model(frequency, self.F0) + self.noise_amplitude*random.random()
|
brightness = model(frequency, self.F0) + self.noise_amplitude*random.random()
|
||||||
self.frequency.append(frequency)
|
self.frequency.append(frequency)
|
||||||
self.brightness.append(brightness)
|
self.brightness.append(brightness)
|
||||||
|
|
15
setup.py
15
setup.py
|
@ -1,12 +1,22 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages, Command
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
if sys.version_info[:3] < (3, 4, 3):
|
if sys.version_info[:3] < (3, 4, 3):
|
||||||
raise Exception("You need at least Python 3.4.3 to run ARTIQ")
|
raise Exception("You need at least Python 3.4.3 to run ARTIQ")
|
||||||
|
|
||||||
|
class PushDocCommand(Command):
|
||||||
|
description = "uploads the documentation to m-labs.hk"
|
||||||
|
user_options = []
|
||||||
|
def initialize_options(self):
|
||||||
|
pass
|
||||||
|
def finalize_options(self):
|
||||||
|
pass
|
||||||
|
def run(self):
|
||||||
|
os.system("rsync -avz doc/manual/_build/html/ shell.serverraum.org:~/web/m-labs.hk/artiq/manual")
|
||||||
|
|
||||||
requirements = [
|
requirements = [
|
||||||
"sphinx", "sphinx-argparse", "pyserial", "numpy", "scipy",
|
"sphinx", "sphinx-argparse", "pyserial", "numpy", "scipy",
|
||||||
"python-dateutil", "prettytable", "h5py", "pydaqmx", "pyelftools",
|
"python-dateutil", "prettytable", "h5py", "pydaqmx", "pyelftools",
|
||||||
|
@ -52,5 +62,6 @@ setup(
|
||||||
ext_modules=[],
|
ext_modules=[],
|
||||||
entry_points={
|
entry_points={
|
||||||
"console_scripts": scripts,
|
"console_scripts": scripts,
|
||||||
}
|
},
|
||||||
|
cmdclass={"push_doc":PushDocCommand}
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "flash_storage.h"
|
#include "flash_storage.h"
|
||||||
#include "mailbox.h"
|
#include "mailbox.h"
|
||||||
|
#include "messages.h"
|
||||||
#include "elf_loader.h"
|
#include "elf_loader.h"
|
||||||
#include "services.h"
|
#include "services.h"
|
||||||
#include "kloader.h"
|
#include "kloader.h"
|
||||||
|
@ -122,3 +123,65 @@ void kloader_stop(void)
|
||||||
kernel_cpu_reset_write(1);
|
kernel_cpu_reset_write(1);
|
||||||
mailbox_acknowledge();
|
mailbox_acknowledge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int kloader_validate_kpointer(void *p)
|
||||||
|
{
|
||||||
|
unsigned int v = (unsigned int)p;
|
||||||
|
if((v < 0x40400000) || (v > (0x4fffffff - 1024*1024))) {
|
||||||
|
log("Received invalid pointer from kernel CPU: 0x%08x", v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kloader_is_essential_kmsg(int msgtype)
|
||||||
|
{
|
||||||
|
switch(msgtype) {
|
||||||
|
case MESSAGE_TYPE_NOW_INIT_REQUEST:
|
||||||
|
case MESSAGE_TYPE_NOW_SAVE:
|
||||||
|
case MESSAGE_TYPE_LOG:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long long int now;
|
||||||
|
|
||||||
|
void kloader_service_essential_kmsg(void)
|
||||||
|
{
|
||||||
|
struct msg_base *umsg;
|
||||||
|
|
||||||
|
umsg = mailbox_receive();
|
||||||
|
if(umsg) {
|
||||||
|
if(!kloader_validate_kpointer(umsg))
|
||||||
|
return;
|
||||||
|
switch(umsg->type) {
|
||||||
|
case MESSAGE_TYPE_NOW_INIT_REQUEST: {
|
||||||
|
struct msg_now_init_reply reply;
|
||||||
|
|
||||||
|
reply.type = MESSAGE_TYPE_NOW_INIT_REPLY;
|
||||||
|
reply.now = now;
|
||||||
|
mailbox_send_and_wait(&reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MESSAGE_TYPE_NOW_SAVE: {
|
||||||
|
struct msg_now_save *msg = (struct msg_now_save *)umsg;
|
||||||
|
|
||||||
|
now = msg->now;
|
||||||
|
mailbox_acknowledge();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MESSAGE_TYPE_LOG: {
|
||||||
|
struct msg_log *msg = (struct msg_log *)umsg;
|
||||||
|
|
||||||
|
log_va(msg->fmt, msg->args);
|
||||||
|
mailbox_acknowledge();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
/* handled elsewhere */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#define KERNELCPU_EXEC_ADDRESS 0x40400000
|
#define KERNELCPU_EXEC_ADDRESS 0x40400000
|
||||||
#define KERNELCPU_PAYLOAD_ADDRESS 0x40404000
|
#define KERNELCPU_PAYLOAD_ADDRESS 0x40404000
|
||||||
|
|
||||||
|
extern long long int now;
|
||||||
|
|
||||||
typedef void (*kernel_function)(void);
|
typedef void (*kernel_function)(void);
|
||||||
|
|
||||||
int kloader_load(void *buffer, int length);
|
int kloader_load(void *buffer, int length);
|
||||||
|
@ -14,4 +16,8 @@ void kloader_start_idle_kernel(void);
|
||||||
void kloader_start_user_kernel(kernel_function k);
|
void kloader_start_user_kernel(kernel_function k);
|
||||||
void kloader_stop(void);
|
void kloader_stop(void);
|
||||||
|
|
||||||
|
int kloader_validate_kpointer(void *p);
|
||||||
|
int kloader_is_essential_kmsg(int msgtype);
|
||||||
|
void kloader_service_essential_kmsg(void);
|
||||||
|
|
||||||
#endif /* __KLOADER_H */
|
#endif /* __KLOADER_H */
|
||||||
|
|
|
@ -24,6 +24,17 @@ SECTIONS
|
||||||
_etext = .;
|
_etext = .;
|
||||||
} > ksupport
|
} > ksupport
|
||||||
|
|
||||||
|
.got :
|
||||||
|
{
|
||||||
|
_GLOBAL_OFFSET_TABLE_ = .;
|
||||||
|
*(.got)
|
||||||
|
} > ksupport
|
||||||
|
|
||||||
|
.got.plt :
|
||||||
|
{
|
||||||
|
*(.got.plt)
|
||||||
|
} > ksupport
|
||||||
|
|
||||||
.rodata :
|
.rodata :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
@ -39,7 +50,6 @@ SECTIONS
|
||||||
_fdata = .;
|
_fdata = .;
|
||||||
*(.data .data.* .gnu.linkonce.d.*)
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
*(.data1)
|
*(.data1)
|
||||||
_gp = ALIGN(16);
|
|
||||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||||
_edata = .;
|
_edata = .;
|
||||||
} > ksupport
|
} > ksupport
|
||||||
|
|
|
@ -26,6 +26,17 @@ SECTIONS
|
||||||
_etext = .;
|
_etext = .;
|
||||||
} > runtime
|
} > runtime
|
||||||
|
|
||||||
|
.got :
|
||||||
|
{
|
||||||
|
_GLOBAL_OFFSET_TABLE_ = .;
|
||||||
|
*(.got)
|
||||||
|
} > runtime
|
||||||
|
|
||||||
|
.got.plt :
|
||||||
|
{
|
||||||
|
*(.got.plt)
|
||||||
|
} > runtime
|
||||||
|
|
||||||
.rodata :
|
.rodata :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
@ -41,7 +52,6 @@ SECTIONS
|
||||||
_fdata = .;
|
_fdata = .;
|
||||||
*(.data .data.* .gnu.linkonce.d.*)
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
*(.data1)
|
*(.data1)
|
||||||
_gp = ALIGN(16);
|
|
||||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||||
_edata = .;
|
_edata = .;
|
||||||
} > runtime
|
} > runtime
|
||||||
|
|
|
@ -143,6 +143,7 @@ static void regular_main(void)
|
||||||
session_end();
|
session_end();
|
||||||
while(1) {
|
while(1) {
|
||||||
lwip_service();
|
lwip_service();
|
||||||
|
kloader_service_essential_kmsg();
|
||||||
kserver_service();
|
kserver_service();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,8 +202,10 @@ static void regular_main(void)
|
||||||
|
|
||||||
/* Open the session for the serial control. */
|
/* Open the session for the serial control. */
|
||||||
session_start();
|
session_start();
|
||||||
while(1)
|
while(1) {
|
||||||
|
kloader_service_essential_kmsg();
|
||||||
serial_service();
|
serial_service();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "kloader.h"
|
#include "kloader.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "session.h"
|
|
||||||
#include "flash_storage.h"
|
#include "flash_storage.h"
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
#define BUFFER_IN_SIZE (1024*1024)
|
#define BUFFER_IN_SIZE (1024*1024)
|
||||||
#define BUFFER_OUT_SIZE (1024*1024)
|
#define BUFFER_OUT_SIZE (1024*1024)
|
||||||
|
@ -55,7 +55,6 @@ static void submit_output(int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int user_kernel_state;
|
static int user_kernel_state;
|
||||||
static long long int now;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
USER_KERNEL_NONE = 0,
|
USER_KERNEL_NONE = 0,
|
||||||
|
@ -153,7 +152,7 @@ static int process_input(void)
|
||||||
log("Attempted to switch RTIO clock while kernel running");
|
log("Attempted to switch RTIO clock while kernel running");
|
||||||
buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_FAILED;
|
buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_FAILED;
|
||||||
submit_output(9);
|
submit_output(9);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rtio_crg_clock_sel_write(buffer_in[9]);
|
rtio_crg_clock_sel_write(buffer_in[9]);
|
||||||
buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_COMPLETED;
|
buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_COMPLETED;
|
||||||
|
@ -421,16 +420,6 @@ static int add_rpc_value(int bi, int type_tag, void *value)
|
||||||
return bi - obi;
|
return bi - obi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int validate_kpointer(void *p)
|
|
||||||
{
|
|
||||||
unsigned int v = (unsigned int)p;
|
|
||||||
if((v < 0x40400000) || (v > (0x4fffffff - 1024*1024))) {
|
|
||||||
log("Received invalid pointer from kernel CPU: 0x%08x", v);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int send_rpc_request(int rpc_num, va_list args)
|
static int send_rpc_request(int rpc_num, va_list args)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
@ -448,7 +437,7 @@ static int send_rpc_request(int rpc_num, va_list args)
|
||||||
v = NULL;
|
v = NULL;
|
||||||
else {
|
else {
|
||||||
v = va_arg(args, void *);
|
v = va_arg(args, void *);
|
||||||
if(!validate_kpointer(v))
|
if(!kloader_validate_kpointer(v))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
r = add_rpc_value(bi, type_tag, v);
|
r = add_rpc_value(bi, type_tag, v);
|
||||||
|
@ -467,31 +456,16 @@ static int send_rpc_request(int rpc_num, va_list args)
|
||||||
/* assumes output buffer is empty when called */
|
/* assumes output buffer is empty when called */
|
||||||
static int process_kmsg(struct msg_base *umsg)
|
static int process_kmsg(struct msg_base *umsg)
|
||||||
{
|
{
|
||||||
if(!validate_kpointer(umsg))
|
if(!kloader_validate_kpointer(umsg))
|
||||||
return 0;
|
return 0;
|
||||||
if((user_kernel_state != USER_KERNEL_RUNNING)
|
if(kloader_is_essential_kmsg(umsg->type))
|
||||||
&& (umsg->type != MESSAGE_TYPE_NOW_INIT_REQUEST)
|
return 1; /* handled elsewhere */
|
||||||
&& (umsg->type != MESSAGE_TYPE_NOW_SAVE)) {
|
if(user_kernel_state != USER_KERNEL_RUNNING) {
|
||||||
log("Received unexpected message from kernel CPU while not in running state");
|
log("Received unexpected message from kernel CPU while not in running state");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(umsg->type) {
|
switch(umsg->type) {
|
||||||
case MESSAGE_TYPE_NOW_INIT_REQUEST: {
|
|
||||||
struct msg_now_init_reply reply;
|
|
||||||
|
|
||||||
reply.type = MESSAGE_TYPE_NOW_INIT_REPLY;
|
|
||||||
reply.now = now;
|
|
||||||
mailbox_send_and_wait(&reply);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MESSAGE_TYPE_NOW_SAVE: {
|
|
||||||
struct msg_now_save *msg = (struct msg_now_save *)umsg;
|
|
||||||
|
|
||||||
now = msg->now;
|
|
||||||
mailbox_acknowledge();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MESSAGE_TYPE_FINISHED:
|
case MESSAGE_TYPE_FINISHED:
|
||||||
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_FINISHED;
|
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_FINISHED;
|
||||||
submit_output(9);
|
submit_output(9);
|
||||||
|
@ -538,13 +512,6 @@ static int process_kmsg(struct msg_base *umsg)
|
||||||
mailbox_acknowledge();
|
mailbox_acknowledge();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MESSAGE_TYPE_LOG: {
|
|
||||||
struct msg_log *msg = (struct msg_log *)umsg;
|
|
||||||
|
|
||||||
log_va(msg->fmt, msg->args);
|
|
||||||
mailbox_acknowledge();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
default: {
|
||||||
log("Received invalid message type from kernel CPU");
|
log("Received invalid message type from kernel CPU");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue