Compare commits

...

87 Commits
master ... 3.4

Author SHA1 Message Date
Robert Jördens 9db30ce8dc conda: pin openocd build 2018-01-30 11:12:33 +01:00
Robert Jördens 49a265453d conda: sync artiq and artiq-dev
c.f. 4c22d64e
2018-01-30 11:03:55 +01:00
Sebastien Bourdeauducq e1aafcbb4f artiq_flash: add --preinit-command for buildbot compatibility 2018-01-30 17:35:48 +08:00
Sebastien Bourdeauducq 2548e9d833 RELEASE_NOTES: add 3.4 entry 2018-01-30 17:35:14 +08:00
whitequark b92b00a1c8 Update smoltcp.
Fixes #902.
2018-01-30 03:30:53 +00:00
Sebastien Bourdeauducq bfb03fdbba RELEASE_NOTES: 3.3 2018-01-28 00:18:24 +08:00
Sebastien Bourdeauducq 59fe69a4b3 conda: use new migen 2018-01-27 23:13:58 +08:00
Sebastien Bourdeauducq 8276c6588b conda: use misoc release 2018-01-27 22:22:55 +08:00
whitequark aa64b8ad7a runtime: build with -Cpanic=unwind.
This is required for backtraces to function. I'm not sure how it
turned out that master had -Cpanic=abort.
2018-01-26 23:01:54 +00:00
whitequark 6f7771cb01 Fix 3313e997. 2018-01-27 00:31:59 +08:00
whitequark d2e9ea8de6 test: fix test_worker to work when deprecation warnings are emitted. 2018-01-27 00:31:58 +08:00
Robert Jördens a85fd13c21 conda: bump misoc, close #905
* cherry-pick c9b36e35
* also pin migen as we don't do .dev tags anymore
2018-01-25 19:34:47 +01:00
Sebastien Bourdeauducq 5f2256cb25 conda: build artiq- as noarch: python, like artiq itself (#894) 2018-01-17 10:12:06 +08:00
Sebastien Bourdeauducq 917477f937 examples: update KC705 DNS (used for CI) 2018-01-17 09:41:47 +08:00
whitequark 4f3e7af8d5 doc: Rust uses recursive submodules (brrr).
[ci skip]
2018-01-10 01:28:40 +00:00
whitequark 3b82c585d1 doc: update Rust version.
[ci skip]
2018-01-10 01:28:39 +00:00
Sebastien Bourdeauducq a433794483 Work around another conda bug. 2018-01-09 17:04:33 +08:00
Sebastien Bourdeauducq 6641f4c1ac conda: use tagged migen/misoc 2018-01-09 15:39:27 +08:00
whitequark 24562d232e compiler: don't die if addr2line cannot extract line from backtrace.
Fixes #885.
2018-01-08 22:02:38 +00:00
whitequark 40b9a84a2b firmware: update smoltcp. 2018-01-08 22:02:27 +00:00
whitequark 46218c1fff conda: update rustc to 1.23.0. 2018-01-08 21:55:26 +00:00
whitequark 3ba82cf19c firmware: clean up makefiles. 2018-01-03 08:20:45 +00:00
Sebastien Bourdeauducq e14626e432 conda: bump migen 2017-12-29 11:11:18 +08:00
Sebastien Bourdeauducq 4ae93d4fd8 conda: bump misoc 2017-12-29 01:41:40 +08:00
Robert Jördens 66d1647efd spi: register clk 2017-12-29 01:40:45 +08:00
whitequark e6306b712d firmware: fix a typo replacing spiflash::SECTOR_SIZE with PAGE_SIZE. 2017-12-29 01:37:34 +08:00
Sebastien Bourdeauducq 14a90e5386 firmware: enlarge bootloader partition to 4 sectors. 2017-12-29 01:37:11 +08:00
Sebastien Bourdeauducq 00c9b20d1e firmware: remove bitflags references from Cargo.lock
Only master needs bitflags.
2017-12-28 12:28:37 +08:00
Sebastien Bourdeauducq 8c19d90179 firmware: prepare config block for access from BIOS/bootloader.
This is in 3.2 so that users lose storage only once.
2017-12-28 12:23:18 +08:00
whitequark 135c138ec3 runtime: remove borrow_mut!() in favor of backtraces. 2017-12-28 12:06:29 +08:00
whitequark d419ccdeca compiler: do not permit str(...). (#878) 2017-12-27 11:48:21 +08:00
Sebastien Bourdeauducq 246a2bb3e1 RELEASE_NOTES: add 3.2 entry 2017-12-27 10:52:12 +08:00
whitequark 26dbf0841c conda: ship runtime.elf in board-specific packages.
This is so that backtraces may be symbolized.
2017-12-27 10:48:35 +08:00
whitequark 7af02787e0 conda: bump rustc version requirement. 2017-12-27 10:45:52 +08:00
whitequark 4bda29f863 compiler: fix typo in a0a2650f. 2017-12-27 10:44:26 +08:00
whitequark c44d08a826 conda: update llvmlite-artiq dependency. 2017-12-27 10:44:11 +08:00
whitequark fbf7e70ef8 compiler: do not ever emit !tbaa on invoke instructions. 2017-12-27 10:44:03 +08:00
whitequark ca48c29a8b compiler: update for llvmlite 0.20.0. 2017-12-27 10:43:55 +08:00
whitequark c9be535ba5 compiler: do not use invoke for calls to nounwind ffi functions.
Otherwise, declarations such as:

  @syscall(flags={"nounwind", "nowrite"})
  def foo(...):

trip an LLVM assert because the invoke instruction and the !tbaa
metadata are no longer compatible since LLVM 4.0.
2017-12-27 10:43:48 +08:00
whitequark 3f8dc0233a runtime: update smoltcp. 2017-12-27 10:43:32 +08:00
whitequark 30b7bcf362 Update to LLVM 4.0. 2017-12-27 10:43:04 +08:00
whitequark 99bc18dcd7 runtime: fix some final flash storage issues. 2017-12-27 10:42:57 +08:00
whitequark 65204a091f runtime: we're growing, put storage at 1M instead of 512K. 2017-12-27 10:42:21 +08:00
whitequark 2fd3b3324a runtime: ensure flash storage never overlaps with runtime sections. 2017-12-27 10:41:13 +08:00
whitequark 7f04e75042 runtime: simplify. NFC. 2017-12-27 10:38:05 +08:00
whitequark e364213b62 runtime: remove accidentally committed parts of a Makefile. 2017-12-27 10:37:56 +08:00
whitequark 99bb1b0b70 runtime: print (address-only) backtraces on core device panics. 2017-12-27 10:37:44 +08:00
whitequark b72178756e firmware: fix compatibility with newer rustc. NFC. 2017-12-27 10:35:52 +08:00
whitequark 6cbf8786d8 runtime: get rid of config_dummy.rs. NFC.
Use the same strategy as elsewhere.
2017-12-27 10:35:36 +08:00
whitequark 0ede5d8638 doc: developing: show how to make clang source builds faster. 2017-12-27 10:33:43 +08:00
whitequark 231bf77b43 runtime: update smoltcp. 2017-12-19 23:52:50 +08:00
Sebastien Bourdeauducq df2f0ead4a runtime: no startup_clock config is not an error 2017-12-14 18:50:08 +08:00
whitequark 16d49f38c1 artiq_pcap: still grab the file if the command fails. 2017-12-11 07:31:58 +08:00
whitequark 3f0277197f runtime: update smoltcp. 2017-12-11 07:31:30 +08:00
Robert Jördens e02dc834e6 doc: clean up artiq-dev installation instructions
Add a heading to the openocd setup instruction so that it is
clearly distinguishable from the openocd installation. Otherwise people
"re-install" openocd the wrong way.
2017-12-11 07:31:02 +08:00
Robert Jördens 6cb7f2e8e2 conda/artiq-dev: fix channel list
Now, with conda 4.1 packages are sorted by channel, version, build
number in decreasing priority. The highest matching package is
taken. https://conda.io/docs/user-guide/tasks/manage-channels.html

For the artiq-dev environment, the m-labs/label/dev channel should be
first, then the main channel, then defaults, and then conda-forge
(community supported packages).

closes #864
2017-12-11 07:30:36 +08:00
Sebastien Bourdeauducq 4c2f25e85e RELEASE_NOTES: 3.1 2017-12-07 13:12:02 +08:00
Robert Jördens 2c85597daa test_performance: relax network speed to 2 MB/s
At QUARTIQ I am getting 2.4/2.3 MB/s and with single switch at M-Labs we
apparently regularly met 2.2/2.2 MB/s. But with the current multiple
switches and one of them being a problematic switch that triggered #837
it looks like it is a tad slower.

http://buildbot.m-labs.hk/builders/artiq/builds/1818/steps/python_coverage_1/logs/stdio
2017-12-07 12:24:14 +08:00
Sebastien Bourdeauducq 76a908c8a9 backport Ethernet bugfixes from master 2017-12-07 12:21:21 +08:00
whitequark 0e5a5441aa runtime: remove UDP-related code. 2017-12-07 12:16:33 +08:00
Sebastien Bourdeauducq 45f510bcdc phaser: remove ad9154 from mem_map 2017-11-29 18:23:50 +08:00
Sebastien Bourdeauducq 7e5a301a27 manual: fix formatting problem 2017-11-25 14:41:36 +08:00
Sebastien Bourdeauducq 14714d3f9d Hack-patch Sphinx so that ARTIQ-Python types are correctly printed.
Modification proposed to Sphinx but my issue is getting ignored.

Closes #741
2017-11-25 14:37:21 +08:00
Sebastien Bourdeauducq 25d3fc1e55 sawg: fix typo 2017-11-22 20:06:16 +08:00
Sebastien Bourdeauducq f83cf8d1bb artiq_influxdb: use aiohttp.ClientSession. Closes #829 2017-11-22 17:32:10 +08:00
Sebastien Bourdeauducq 8ebca38323 runtime: fix rtio::log 2017-11-03 09:25:56 +08:00
Sebastien Bourdeauducq 0c47f83634 clean up rtio_log 2017-11-03 01:13:07 +08:00
whitequark f0937bde16 runtime: update smoltcp. 2017-10-30 16:39:25 +08:00
whitequark 3ec1850949 runtime: update smoltcp. 2017-10-30 15:43:28 +08:00
whitequark 0d79b7d292 test: verify no network performance regression from current 2.2 MB/s. 2017-10-30 15:43:28 +08:00
whitequark 3e96e0b10d runtime: parse the "ip" configuration as IP, not CIDR.
Or it defaults to the default IP on settings that were previously
perfectly valid.
2017-10-30 15:43:28 +08:00
Sebastien Bourdeauducq 6902868d58 gui: remove '.0' in background logo 2017-10-26 12:53:35 +08:00
whitequark 89b7c9e091 Update smoltcp.
Fixes #840.
2017-10-25 10:57:42 +08:00
Sebastien Bourdeauducq 52e331204e examples: fix first_dds_bus_channel in device database 2017-10-23 15:05:20 +08:00
Robert Jördens 8edb6a135a conda: openocd=0.10.0 (single-tap proxy bitstreams) 2017-10-20 19:47:54 +02:00
Robert Jördens cd0d73a1a2 scanwidget: protect against resize from zero
fix #839
2017-10-11 22:27:09 +02:00
Sebastien Bourdeauducq a6cd42c4aa RELEASE_NOTES: 2.5 2017-10-02 12:16:46 +08:00
whitequark 45c6ca96f8 firmware: unbreak heap view.
This was missing since 7799413a for no good reason.
2017-10-02 11:03:52 +08:00
whitequark db8300c990 compiler: disallow op= on mutable values (fix #835).
In general, we can't reallocate a value in earlier stack frames,
or fixup references to it. This mainly impacts lists.
2017-10-02 11:03:03 +08:00
whitequark ce7e30edfe compiler: implement ~ operator (fix #836). 2017-10-02 11:03:02 +08:00
whitequark a06f04dfbe compiler: minor intrinsic refactoring. 2017-10-02 11:03:02 +08:00
whitequark 1521231b1b compiler: correct semantics of floating point % operator (fix #830). 2017-10-02 11:03:02 +08:00
whitequark 67997d8955 compiler: correct semantics of integer % operator (#830). 2017-10-02 11:03:02 +08:00
Sebastien Bourdeauducq a49bb2bc50 conda: fix llvmlite-artiq dependency 2017-09-30 01:31:50 +08:00
Sebastien Bourdeauducq d500e61d89 RELEASE_NOTES: formatting 2017-09-30 01:10:23 +08:00
Sebastien Bourdeauducq 04a9a0ce95 doc: no more win32 packages 2017-09-29 23:14:21 +08:00
Sebastien Bourdeauducq ac28b377c7 targets: phaser → kc705_phaser 2017-09-29 22:54:18 +08:00
60 changed files with 1105 additions and 763 deletions

View File

@ -3,13 +3,39 @@
Release notes Release notes
============= =============
3.4
---
No further notes.
3.3
---
No further notes.
3.2
---
* To accommodate larger runtimes, the flash layout as changed. As a result, the
contents of the flash storage will be lost when upgrading. Set the values back
(IP, MAC address, startup kernel, etc.) after the upgrade.
3.1
---
No further notes.
3.0 3.0
--- ---
* The --embed option of applets is replaced with the environment variable * The ``--embed`` option of applets is replaced with the environment variable
``ARTIQ_APPLET_EMBED``. The GUI sets this enviroment variable itself and the ``ARTIQ_APPLET_EMBED``. The GUI sets this enviroment variable itself and the
user simply needs to remove the ``--embed`` argument. user simply needs to remove the ``--embed`` argument.
* EnvExperiment's prepare calls prepare for all its children. * ``EnvExperiment``'s ``prepare`` calls ``prepare`` for all its children.
* Dynamic ``__getattr__``'s returning RPC target methods are not supported anymore. * Dynamic ``__getattr__``'s returning RPC target methods are not supported anymore.
Controller driver classes must define all their methods intended for RPC as Controller driver classes must define all their methods intended for RPC as
members. members.
@ -22,7 +48,7 @@ Release notes
* The DDS class names and setup options have changed, this requires an update of * The DDS class names and setup options have changed, this requires an update of
the device database. the device database.
* ``int(a, width=b)`` has been removed. Use ``int32(a)`` and ``int64(a)``. * ``int(a, width=b)`` has been removed. Use ``int32(a)`` and ``int64(a)``.
* The kc705 gateware target has been renamed kc705_dds. * The KC705 gateware target has been renamed ``kc705_dds``.
* ``artiq.coredevice.comm_tcp`` has been renamed ``artiq.coredevice.comm_kernel``, * ``artiq.coredevice.comm_tcp`` has been renamed ``artiq.coredevice.comm_kernel``,
and ``Comm`` has been renamed ``CommKernel``. and ``Comm`` has been renamed ``CommKernel``.
* The "collision" and "busy" RTIO errors are reported through the log instead of * The "collision" and "busy" RTIO errors are reported through the log instead of
@ -38,8 +64,8 @@ Release notes
identifiers (``true``, ``null``, ...) with their Python equivalents identifiers (``true``, ``null``, ...) with their Python equivalents
(``True``, ``None`` ...). (``True``, ``None`` ...).
* Controllers are now named ``aqctl_XXX`` instead of ``XXX_controller``. * Controllers are now named ``aqctl_XXX`` instead of ``XXX_controller``.
* In the device database, the "comm" device has been folded into the "core" device. * In the device database, the ``comm`` device has been folded into the ``core`` device.
Move the "host" argument into the "core" device, and remove the "comm" device. Move the "host" argument into the ``core`` device, and remove the ``comm`` device.
* The core device log now contains important information about events such as * The core device log now contains important information about events such as
RTIO collisions. A new controller ``aqctl_corelog`` must be running to forward RTIO collisions. A new controller ``aqctl_corelog`` must be running to forward
those logs to the master. See the example device databases to see how to those logs to the master. See the example device databases to see how to
@ -52,8 +78,15 @@ Release notes
at https://github.com/m-labs/pdq. All SPI/USB driver layers, Mediator, at https://github.com/m-labs/pdq. All SPI/USB driver layers, Mediator,
CompoundPDQ and examples/documentation has been moved. CompoundPDQ and examples/documentation has been moved.
* The master now rotates log files at midnight, rather than based on log size. * The master now rotates log files at midnight, rather than based on log size.
* The results keys start_time and run_time are now stored as doubles of UNIX time, * The results keys ``start_time`` and ``run_time`` are now stored as doubles of UNIX time,
rather than ints. The file names are still based on local time. rather than ints. The file names are still based on local time.
* Packages are no longer available for 32-bit Windows.
2.5
---
No further notes.
2.4 2.4
@ -62,7 +95,6 @@ Release notes
No further notes. No further notes.
2.3 2.3
--- ---

View File

@ -216,8 +216,12 @@ class Target:
filename, line = location.rsplit(":", 1) filename, line = location.rsplit(":", 1)
if filename == "??" or filename == "<synthesized>": if filename == "??" or filename == "<synthesized>":
continue continue
if line == "?":
line = -1
else:
line = int(line)
# can't get column out of addr2line D: # can't get column out of addr2line D:
backtrace.append((filename, int(line), -1, function, address)) backtrace.append((filename, line, -1, function, address))
return backtrace return backtrace
def demangle(self, names): def demangle(self, names):

View File

@ -1289,6 +1289,10 @@ class ARTIQIRGenerator(algorithm.Visitor):
return self.append(ir.Select(cond, return self.append(ir.Select(cond,
ir.Constant(False, builtins.TBool()), ir.Constant(False, builtins.TBool()),
ir.Constant(True, builtins.TBool()))) ir.Constant(True, builtins.TBool())))
elif isinstance(node.op, ast.Invert):
operand = self.visit(node.operand)
return self.append(ir.Arith(ast.BitXor(loc=None),
ir.Constant(-1, operand.type), operand))
elif isinstance(node.op, ast.USub): elif isinstance(node.op, ast.USub):
operand = self.visit(node.operand) operand = self.visit(node.operand)
return self.append(ir.Arith(ast.Sub(loc=None), return self.append(ir.Arith(ast.Sub(loc=None),
@ -1319,7 +1323,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
lambda: self.alloc_exn(builtins.TException("ValueError"), lambda: self.alloc_exn(builtins.TException("ValueError"),
ir.Constant("shift amount must be nonnegative", builtins.TStr())), ir.Constant("shift amount must be nonnegative", builtins.TStr())),
loc=node.right.loc) loc=node.right.loc)
elif isinstance(node.op, (ast.Div, ast.FloorDiv)): elif isinstance(node.op, (ast.Div, ast.FloorDiv, ast.Mod)):
self._make_check( self._make_check(
self.append(ir.Compare(ast.NotEq(loc=None), rhs, ir.Constant(0, rhs.type))), self.append(ir.Compare(ast.NotEq(loc=None), rhs, ir.Constant(0, rhs.type))),
lambda: self.alloc_exn(builtins.TException("ZeroDivisionError"), lambda: self.alloc_exn(builtins.TException("ZeroDivisionError"),
@ -1721,7 +1725,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
self.polymorphic_print([self.visit(prefix)], self.polymorphic_print([self.visit(prefix)],
separator=" ", suffix="\x1E", as_rtio=True) separator=" ", suffix="\x1E", as_rtio=True)
self.polymorphic_print([self.visit(arg) for arg in args], self.polymorphic_print([self.visit(arg) for arg in args],
separator=" ", suffix="\n\x1D", as_rtio=True) separator=" ", suffix="\x1D", as_rtio=True)
return ir.Constant(None, builtins.TNone()) return ir.Constant(None, builtins.TNone())
elif types.is_builtin(typ, "delay"): elif types.is_builtin(typ, "delay"):
if len(node.args) == 1 and len(node.keywords) == 0: if len(node.args) == 1 and len(node.keywords) == 0:
@ -1808,7 +1812,8 @@ class ARTIQIRGenerator(algorithm.Visitor):
assert None not in args assert None not in args
if self.unwind_target is None: if self.unwind_target is None or \
types.is_c_function(callee.type) and "nounwind" in callee.type.flags:
insn = self.append(ir.Call(func, args, arg_exprs)) insn = self.append(ir.Call(func, args, arg_exprs))
else: else:
after_invoke = self.add_block("invoke") after_invoke = self.add_block("invoke")

View File

@ -682,6 +682,11 @@ class Inferencer(algorithm.Visitor):
pass pass
else: else:
diagnose(valid_forms()) diagnose(valid_forms())
elif types.is_builtin(typ, "str"):
diag = diagnostic.Diagnostic("error",
"strings currently cannot be constructed", {},
node.loc)
self.engine.process(diag)
elif types.is_builtin(typ, "list") or types.is_builtin(typ, "array"): elif types.is_builtin(typ, "list") or types.is_builtin(typ, "array"):
if types.is_builtin(typ, "list"): if types.is_builtin(typ, "list"):
valid_forms = lambda: [ valid_forms = lambda: [

View File

@ -22,7 +22,7 @@ llptr = ll.IntType(8).as_pointer()
llptrptr = ll.IntType(8).as_pointer().as_pointer() llptrptr = ll.IntType(8).as_pointer().as_pointer()
llslice = ll.LiteralStructType([llptr, lli32]) llslice = ll.LiteralStructType([llptr, lli32])
llsliceptr = ll.LiteralStructType([llptr, lli32]).as_pointer() llsliceptr = ll.LiteralStructType([llptr, lli32]).as_pointer()
llmetadata = ll.MetaData() llmetadata = ll.MetaDataType()
def memoize(generator): def memoize(generator):
@ -270,7 +270,7 @@ class LLVMIRGenerator:
sanitized_str = re.sub(rb"[^a-zA-Z0-9_.]", b"", as_bytes[:20]).decode('ascii') sanitized_str = re.sub(rb"[^a-zA-Z0-9_.]", b"", as_bytes[:20]).decode('ascii')
name = self.llmodule.get_unique_name("S.{}".format(sanitized_str)) name = self.llmodule.get_unique_name("S.{}".format(sanitized_str))
llstr = self.llmodule.get_global(name) llstr = self.llmodule.globals.get(name)
if llstr is None: if llstr is None:
llstrty = ll.ArrayType(lli8, len(as_bytes)) llstrty = ll.ArrayType(lli8, len(as_bytes))
llstr = ll.GlobalVariable(self.llmodule, llstrty, name) llstr = ll.GlobalVariable(self.llmodule, llstrty, name)
@ -306,7 +306,7 @@ class LLVMIRGenerator:
assert False assert False
def llbuiltin(self, name): def llbuiltin(self, name):
llglobal = self.llmodule.get_global(name) llglobal = self.llmodule.globals.get(name)
if llglobal is not None: if llglobal is not None:
return llglobal return llglobal
@ -326,6 +326,12 @@ class LLVMIRGenerator:
llty = ll.FunctionType(llptr, []) llty = ll.FunctionType(llptr, [])
elif name == "llvm.stackrestore": elif name == "llvm.stackrestore":
llty = ll.FunctionType(llvoid, [llptr]) llty = ll.FunctionType(llvoid, [llptr])
elif name == "__py_modsi3":
llty = ll.FunctionType(lli32, [lli32, lli32])
elif name == "__py_moddi3":
llty = ll.FunctionType(lli64, [lli64, lli64])
elif name == "__py_moddf3":
llty = ll.FunctionType(lldouble, [lldouble, lldouble])
elif name == self.target.print_function: elif name == self.target.print_function:
llty = ll.FunctionType(llvoid, [llptr], var_arg=True) llty = ll.FunctionType(llvoid, [llptr], var_arg=True)
elif name == "rtio_log": elif name == "rtio_log":
@ -363,13 +369,96 @@ class LLVMIRGenerator:
"watchdog_set", "watchdog_clear", "watchdog_set", "watchdog_clear",
self.target.print_function): self.target.print_function):
llglobal.attributes.add("nounwind") llglobal.attributes.add("nounwind")
if name.find("__py_") == 0:
llglobal.linkage = 'linkonce_odr'
self.emit_intrinsic(name, llglobal)
else: else:
llglobal = ll.GlobalVariable(self.llmodule, llty, name) llglobal = ll.GlobalVariable(self.llmodule, llty, name)
return llglobal return llglobal
def emit_intrinsic(self, name, llfun):
llbuilder = ll.IRBuilder()
llbuilder.position_at_end(llfun.append_basic_block("entry"))
if name == "__py_modsi3" or name == "__py_moddi3":
if name == "__py_modsi3":
llty = lli32
elif name == "__py_moddi3":
llty = lli64
else:
assert False
"""
Reference Objects/intobject.c
xdivy = x / y;
xmody = (long)(x - (unsigned long)xdivy * y);
/* If the signs of x and y differ, and the remainder is non-0,
* C89 doesn't define whether xdivy is now the floor or the
* ceiling of the infinitely precise quotient. We want the floor,
* and we have it iff the remainder's sign matches y's.
*/
if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {
xmody += y;
// ...
}
"""
llx, lly = llfun.args
llxdivy = llbuilder.sdiv(llx, lly)
llxremy = llbuilder.srem(llx, lly)
llxmodynonzero = llbuilder.icmp_signed('!=', llxremy, ll.Constant(llty, 0))
lldiffsign = llbuilder.icmp_signed('<', llbuilder.xor(llx, lly), ll.Constant(llty, 0))
llcond = llbuilder.and_(llxmodynonzero, lldiffsign)
with llbuilder.if_then(llcond):
llbuilder.ret(llbuilder.add(llxremy, lly))
llbuilder.ret(llxremy)
elif name == "__py_moddf3":
"""
Reference Objects/floatobject.c
mod = fmod(vx, wx);
/* fmod is typically exact, so vx-mod is *mathematically* an
exact multiple of wx. But this is fp arithmetic, and fp
vx - mod is an approximation; the result is that div may
not be an exact integral value after the division, although
it will always be very close to one.
*/
// ...
if (mod) {
/* ensure the remainder has the same sign as the denominator */
if ((wx < 0) != (mod < 0)) {
mod += wx;
// ...
}
}
else {
/* the remainder is zero, and in the presence of signed zeroes
fmod returns different results across platforms; ensure
it has the same sign as the denominator; we'd like to do
"mod = wx * 0.0", but that may get optimized away */
mod *= mod; /* hide "mod = +0" from optimizer */
if (wx < 0.0)
mod = -mod;
}
"""
llv, llw = llfun.args
llrem = llbuilder.frem(llv, llw)
llremnonzero = llbuilder.fcmp_unordered('!=', llrem, ll.Constant(lldouble, 0.0))
llwltzero = llbuilder.fcmp_ordered('<', llw, ll.Constant(lldouble, 0.0))
llremltzero = llbuilder.fcmp_ordered('<', llrem, ll.Constant(lldouble, 0.0))
lldiffsign = llbuilder.icmp_unsigned('!=', llwltzero, llremltzero)
llcond = llbuilder.and_(llremnonzero, lldiffsign)
with llbuilder.if_then(llcond):
llbuilder.ret(llbuilder.fadd(llrem, llw))
llbuilder.ret(llrem)
else:
assert False
def get_function(self, typ, name): def get_function(self, typ, name):
llfun = self.llmodule.get_global(name) llfun = self.llmodule.globals.get(name)
if llfun is None: if llfun is None:
llfunty = self.llty_of_type(typ, bare=True) llfunty = self.llty_of_type(typ, bare=True)
llfun = ll.Function(self.llmodule, llfunty, name) llfun = ll.Function(self.llmodule, llfunty, name)
@ -410,7 +499,7 @@ class LLVMIRGenerator:
llobjects = defaultdict(lambda: []) llobjects = defaultdict(lambda: [])
for obj_id, obj_ref, obj_typ in self.embedding_map.iter_objects(): for obj_id, obj_ref, obj_typ in self.embedding_map.iter_objects():
llobject = self.llmodule.get_global("O.{}".format(obj_id)) llobject = self.llmodule.globals.get("O.{}".format(obj_id))
if llobject is not None: if llobject is not None:
llobjects[obj_typ].append(llobject.bitcast(llptr)) llobjects[obj_typ].append(llobject.bitcast(llptr))
@ -905,22 +994,15 @@ class LLVMIRGenerator:
return self.llbuilder.sdiv(self.map(insn.lhs()), self.map(insn.rhs()), return self.llbuilder.sdiv(self.map(insn.lhs()), self.map(insn.rhs()),
name=insn.name) name=insn.name)
elif isinstance(insn.op, ast.Mod): elif isinstance(insn.op, ast.Mod):
# Python only has the modulo operator, LLVM only has the remainder lllhs, llrhs = map(self.map, (insn.lhs(), insn.rhs()))
if builtins.is_float(insn.type): if builtins.is_float(insn.type):
llvalue = self.llbuilder.frem(self.map(insn.lhs()), self.map(insn.rhs())) intrinsic = "__py_moddf3"
self.add_fast_math_flags(llvalue) elif builtins.is_int32(insn.type):
return self.llbuilder.call(self.llbuiltin("llvm.copysign.f64"), intrinsic = "__py_modsi3"
[llvalue, self.map(insn.rhs())], elif builtins.is_int64(insn.type):
name=insn.name) intrinsic = "__py_moddi3"
else: return self.llbuilder.call(self.llbuiltin(intrinsic), [lllhs, llrhs],
lllhs, llrhs = map(self.map, (insn.lhs(), insn.rhs())) name=insn.name)
llxorsign = self.llbuilder.and_(self.llbuilder.xor(lllhs, llrhs),
ll.Constant(lllhs.type, 1 << lllhs.type.width - 1))
llnegate = self.llbuilder.icmp_unsigned('!=',
llxorsign, ll.Constant(llxorsign.type, 0))
llvalue = self.llbuilder.srem(lllhs, llrhs)
llnegvalue = self.llbuilder.sub(ll.Constant(llvalue.type, 0), llvalue)
return self.llbuilder.select(llnegate, llnegvalue, llvalue)
elif isinstance(insn.op, ast.Pow): elif isinstance(insn.op, ast.Pow):
if builtins.is_float(insn.type): if builtins.is_float(insn.type):
return self.llbuilder.call(self.llbuiltin("llvm.pow.f64"), return self.llbuilder.call(self.llbuiltin("llvm.pow.f64"),
@ -1127,7 +1209,7 @@ class LLVMIRGenerator:
llargs.append(llarg) llargs.append(llarg)
llfunname = insn.target_function().type.name llfunname = insn.target_function().type.name
llfun = self.llmodule.get_global(llfunname) llfun = self.llmodule.globals.get(llfunname)
if llfun is None: if llfun is None:
llretty = self.llty_of_type(insn.type, for_return=True) llretty = self.llty_of_type(insn.type, for_return=True)
if self.needs_sret(llretty): if self.needs_sret(llretty):
@ -1366,9 +1448,8 @@ class LLVMIRGenerator:
llcall = self.llbuilder.invoke(llfun, llargs, llnormalblock, llunwindblock, llcall = self.llbuilder.invoke(llfun, llargs, llnormalblock, llunwindblock,
name=insn.name) name=insn.name)
# See the comment in process_Call. # The !tbaa metadata is not legal to use with the invoke instruction,
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags: # so unlike process_Call, we do not set it here.
llcall.set_metadata('tbaa', self.tbaa_nowrite_call)
return llcall return llcall
@ -1561,7 +1642,7 @@ class LLVMIRGenerator:
llclauseexnname = self.llconst_of_const( llclauseexnname = self.llconst_of_const(
ir.Constant(exnname, builtins.TStr())) ir.Constant(exnname, builtins.TStr()))
llclauseexnnameptr = self.llmodule.get_global("exn.{}".format(exnname)) llclauseexnnameptr = self.llmodule.globals.get("exn.{}".format(exnname))
if llclauseexnnameptr is None: if llclauseexnnameptr is None:
llclauseexnnameptr = ll.GlobalVariable(self.llmodule, llclauseexnname.type, llclauseexnnameptr = ll.GlobalVariable(self.llmodule, llclauseexnname.type,
name="exn.{}".format(exnname)) name="exn.{}".format(exnname))

View File

@ -298,8 +298,8 @@ class EscapeValidator(algorithm.Visitor):
# and exceptions can only refer to strings, so we don't actually check # and exceptions can only refer to strings, so we don't actually check
# this property. But we will need to, if string operations are ever added. # this property. But we will need to, if string operations are ever added.
def visit_assignment(self, target, value, is_aug_assign=False): def visit_assignment(self, target, value):
value_region = self._region_of(value) if not is_aug_assign else self.youngest_region value_region = self._region_of(value)
# If this is a variable, we might need to contract the live range. # If this is a variable, we might need to contract the live range.
if isinstance(value_region, Region): if isinstance(value_region, Region):
@ -316,19 +316,11 @@ class EscapeValidator(algorithm.Visitor):
target_regions = [self._region_of(name) for name in target_names] target_regions = [self._region_of(name) for name in target_names]
for target_region in target_regions: for target_region in target_regions:
if not Region.outlives(value_region, target_region): if not Region.outlives(value_region, target_region):
if is_aug_assign:
target_desc = "the assignment target, allocated here,"
else:
target_desc = "the assignment target"
note = diagnostic.Diagnostic("note",
"this expression has type {type}",
{"type": types.TypePrinter().name(value.type)},
value.loc)
diag = diagnostic.Diagnostic("error", diag = diagnostic.Diagnostic("error",
"the assigned value does not outlive the assignment target", {}, "the assigned value does not outlive the assignment target", {},
value.loc, [target.loc], value.loc, [target.loc],
notes=self._diagnostics_for(target_region, target.loc, notes=self._diagnostics_for(target_region, target.loc,
target_desc) + "the assignment target") +
self._diagnostics_for(value_region, value.loc, self._diagnostics_for(value_region, value.loc,
"the assigned value")) "the assigned value"))
self.engine.process(diag) self.engine.process(diag)
@ -339,9 +331,19 @@ class EscapeValidator(algorithm.Visitor):
def visit_AugAssign(self, node): def visit_AugAssign(self, node):
if builtins.is_allocated(node.target.type): if builtins.is_allocated(node.target.type):
# If the target is mutable, op-assignment will allocate note = diagnostic.Diagnostic("note",
# in the youngest region. "try using `{lhs} = {lhs} {op} {rhs}` instead",
self.visit_assignment(node.target, node.value, is_aug_assign=True) {"lhs": node.target.loc.source(),
"rhs": node.value.loc.source(),
"op": node.op.loc.source()[:-1]},
node.loc)
diag = diagnostic.Diagnostic("error",
"values cannot be mutated in-place", {},
node.op.loc, [node.target.loc],
notes=[note])
self.engine.process(diag)
self.visit_assignment(node.target, node.value)
def visit_Return(self, node): def visit_Return(self, node):
region = self._region_of(node.value) region = self._region_of(node.value)

View File

@ -32,7 +32,7 @@ class Config:
Exposes the configurable quantities of a single SAWG channel. Exposes the configurable quantities of a single SAWG channel.
Access to the configuration registers for a SAWG channel can not Access to the configuration registers for a SAWG channel can not
be concurrent. There must be at least :attr:_rtio_interval` machine be concurrent. There must be at least :attr:`_rtio_interval` machine
units of delay between accesses. Replacement is not supported and will be units of delay between accesses. Replacement is not supported and will be
lead to an ``RTIOCollision`` as this is likely a programming error. lead to an ``RTIOCollision`` as this is likely a programming error.
All methods therefore advance the timeline by the duration of one All methods therefore advance the timeline by the duration of one

View File

@ -2,7 +2,7 @@
# The RTIO channel numbers here are for NIST CLOCK on KC705. # The RTIO channel numbers here are for NIST CLOCK on KC705.
# The list of devices here is not exhaustive. # The list of devices here is not exhaustive.
core_addr = "kc705.lab.m-labs.hk" core_addr = "kc705-1.lab.m-labs.hk"
device_db = { device_db = {
"core": { "core": {
@ -33,7 +33,7 @@ device_db = {
"class": "DDSGroupAD9914", "class": "DDSGroupAD9914",
"arguments": { "arguments": {
"sysclk": 3e9, "sysclk": 3e9,
"first_dds_bus_channel": 26, "first_dds_bus_channel": 27,
"dds_bus_count": 2, "dds_bus_count": 2,
"dds_channel_count": 3 "dds_channel_count": 3
} }

View File

@ -1,7 +1,3 @@
[root]
name = "std_artiq"
version = "0.0.0"
[[package]] [[package]]
name = "alloc_list" name = "alloc_list"
version = "0.0.0" version = "0.0.0"
@ -17,23 +13,28 @@ dependencies = [
"board 0.0.0", "board 0.0.0",
] ]
[[package]]
name = "backtrace_artiq"
version = "0.0.0"
[[package]] [[package]]
name = "board" name = "board"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "build_artiq" name = "build_artiq"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"walkdir 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.0.0" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -41,7 +42,7 @@ name = "compiler_builtins"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568#631b5687b24af413fdbffa4c2644484e60660b00" source = "git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568#631b5687b24af413fdbffa4c2644484e60660b00"
dependencies = [ dependencies = [
"gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -55,8 +56,8 @@ name = "drtioaux"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"board 0.0.0", "board 0.0.0",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"std_artiq 0.0.0", "std_artiq 0.0.0",
] ]
@ -69,12 +70,12 @@ name = "fringe"
version = "1.1.0" version = "1.1.0"
source = "git+https://github.com/m-labs/libfringe?rev=bd23494#bd2349467157969324ca7da5d2ae033c7ffac0c0" source = "git+https://github.com/m-labs/libfringe?rev=bd23494#bd2349467157969324ca7da5d2ae033c7ffac0c0"
dependencies = [ dependencies = [
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "gcc" name = "gcc"
version = "0.3.42" version = "0.3.54"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -94,7 +95,7 @@ dependencies = [
"amp 0.0.0", "amp 0.0.0",
"board 0.0.0", "board 0.0.0",
"build_artiq 0.0.0", "build_artiq 0.0.0",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dyld 0.0.0", "dyld 0.0.0",
"proto 0.0.0", "proto 0.0.0",
@ -103,12 +104,12 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.18" version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "log" name = "log"
version = "0.3.6" version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -121,23 +122,23 @@ name = "logger_artiq"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"board 0.0.0", "board 0.0.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "managed" name = "managed"
version = "0.4.0" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "proto" name = "proto"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dyld 0.0.0", "dyld 0.0.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"std_artiq 0.0.0", "std_artiq 0.0.0",
] ]
@ -147,17 +148,18 @@ version = "0.0.0"
dependencies = [ dependencies = [
"alloc_list 0.0.0", "alloc_list 0.0.0",
"amp 0.0.0", "amp 0.0.0",
"backtrace_artiq 0.0.0",
"board 0.0.0", "board 0.0.0",
"build_artiq 0.0.0", "build_artiq 0.0.0",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)", "compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)",
"cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"drtioaux 0.0.0", "drtioaux 0.0.0",
"fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=bd23494)", "fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=bd23494)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"logger_artiq 0.0.0", "logger_artiq 0.0.0",
"proto 0.0.0", "proto 0.0.0",
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=6f5ae33)", "smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=181083f)",
"std_artiq 0.0.0", "std_artiq 0.0.0",
] ]
@ -166,6 +168,15 @@ name = "rustc-cfg"
version = "0.3.0" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "same-file"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "satman" name = "satman"
version = "0.0.0" version = "0.0.0"
@ -175,7 +186,7 @@ dependencies = [
"build_artiq 0.0.0", "build_artiq 0.0.0",
"compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)", "compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)",
"drtioaux 0.0.0", "drtioaux 0.0.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"logger_artiq 0.0.0", "logger_artiq 0.0.0",
"std_artiq 0.0.0", "std_artiq 0.0.0",
] ]
@ -183,19 +194,24 @@ dependencies = [
[[package]] [[package]]
name = "smoltcp" name = "smoltcp"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/m-labs/smoltcp?rev=6f5ae33#6f5ae33501827d57926469c6f1a860205a24f7ae" source = "git+https://github.com/m-labs/smoltcp?rev=181083f#181083f18c977b8a0463a67e360e4db20594fa21"
dependencies = [ dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"managed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "managed 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "std_artiq"
version = "0.0.0"
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "1.0.3" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -210,18 +226,19 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)" = "<none>" "checksum compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)" = "<none>"
"checksum cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a" "checksum cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a"
"checksum fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=bd23494)" = "<none>" "checksum fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=bd23494)" = "<none>"
"checksum gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)" = "291055c78f59ca3d84c99026c9501c469413d386bb46be1e1cf1d285cd1db3b0" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70" "checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"checksum log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec57723b84bbe7bdf76aa93169c9b59e67473317c6de3a83cb2a0f8ccb2aa493" "checksum log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec57723b84bbe7bdf76aa93169c9b59e67473317c6de3a83cb2a0f8ccb2aa493"
"checksum managed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d48e8c30a4363e2981fe4db20527f6ab0f32a243bbc75379dea5a64f60dae4" "checksum managed 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "786bd3519bdfb0e1a57146a74b7584555dd6c4f1b6e1137c70e177d60dde8186"
"checksum rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704" "checksum rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704"
"checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=6f5ae33)" = "<none>" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum walkdir 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd7c16466ecc507c7cb5988db03e6eab4aaeab89a5c37a29251fcfd3ac9b7afe" "checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=181083f)" = "<none>"
"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

View File

@ -1,2 +1,5 @@
[workspace] [workspace]
members = ["runtime", "ksupport", "satman"] members = ["runtime", "ksupport", "satman"]
[profile.dev]
debug = 1 # either 0 or 2 cause an LLVM ICE

View File

@ -0,0 +1,24 @@
[package]
authors = ["M-Labs"]
name = "bootloader"
version = "0.0.0"
build = "build.rs"
[lib]
name = "bootloader"
crate-type = ["staticlib"]
path = "main.rs"
[build-dependencies]
build_misoc = { path = "../libbuild_misoc" }
[dependencies]
byteorder = { version = "1.0", default-features = false }
crc = { version = "1.7", default-features = false }
board = { path = "../libboard", features = ["uart_console", "smoltcp"] }
[dependencies.smoltcp]
git = "https://github.com/m-labs/smoltcp"
rev = "181083f"
default-features = false
features = ["proto-ipv4", "socket-tcp"]

View File

@ -5,7 +5,6 @@ CFLAGS += \
-I$(LIBUNWIND_DIRECTORY) \ -I$(LIBUNWIND_DIRECTORY) \
-I$(LIBUNWIND_DIRECTORY)/../unwinder/include \ -I$(LIBUNWIND_DIRECTORY)/../unwinder/include \
-I$(MISOC_DIRECTORY)/software/include/dyld -I$(MISOC_DIRECTORY)/software/include/dyld
CFLAGS += -DNDEBUG
LDFLAGS += --eh-frame-hdr \ LDFLAGS += --eh-frame-hdr \
-L../libcompiler-rt \ -L../libcompiler-rt \
@ -15,22 +14,15 @@ LDFLAGS += --eh-frame-hdr \
RUSTFLAGS += -Cpanic=unwind RUSTFLAGS += -Cpanic=unwind
all: ksupport.elf all:: ksupport.elf
.PHONY: $(RUSTOUT)/libksupport.a .PHONY: $(RUSTOUT)/libksupport.a
$(RUSTOUT)/libksupport.a: $(RUSTOUT)/libksupport.a:
$(cargo) --manifest-path $(KSUPPORT_DIRECTORY)/Cargo.toml $(cargo) --manifest-path $(KSUPPORT_DIRECTORY)/Cargo.toml
ksupport.elf: $(RUSTOUT)/libksupport.a glue.o ksupport.elf: $(RUSTOUT)/libksupport.a glue.o
$(LD) $(LDFLAGS) -T $(KSUPPORT_DIRECTORY)/ksupport.ld -o $@ $^ \ $(link) -T $(KSUPPORT_DIRECTORY)/ksupport.ld \
-lunwind -lcompiler-rt -lbase -lm -lunwind-elf -lcompiler-rt -lbase -lm
@chmod -x $@
%.o: $(KSUPPORT_DIRECTORY)/%.c %.o: $(KSUPPORT_DIRECTORY)/%.c
$(compile) $(compile)
clean:
$(RM) *.o ksupport.elf
$(RM) -rf cargo
.PHONY: all clean

View File

@ -167,7 +167,7 @@ extern fn rpc_recv(slot: *mut ()) -> usize {
}) })
} }
fn terminate(exception: &eh::Exception, mut backtrace: &mut [usize]) -> ! { fn terminate(exception: &eh::Exception, backtrace: &mut [usize]) -> ! {
let mut cursor = 0; let mut cursor = 0;
for index in 0..backtrace.len() { for index in 0..backtrace.len() {
if backtrace[index] > kernel_proto::KERNELCPU_PAYLOAD_ADDRESS { if backtrace[index] > kernel_proto::KERNELCPU_PAYLOAD_ADDRESS {
@ -333,8 +333,8 @@ extern fn dma_record_output_wide(timestamp: i64, channel: i32, address: i32, wor
if DMA_RECORDER.buffer.len() - DMA_RECORDER.data_len < length { if DMA_RECORDER.buffer.len() - DMA_RECORDER.data_len < length {
dma_record_flush() dma_record_flush()
} }
let mut dst = &mut DMA_RECORDER.buffer[DMA_RECORDER.data_len.. let dst = &mut DMA_RECORDER.buffer[DMA_RECORDER.data_len..
DMA_RECORDER.data_len + length]; DMA_RECORDER.data_len + length];
dst[..header_length].copy_from_slice(&header[..]); dst[..header_length].copy_from_slice(&header[..]);
dst[header_length..].copy_from_slice(&data[..]); dst[header_length..].copy_from_slice(&data[..]);
DMA_RECORDER.data_len += length; DMA_RECORDER.data_len += length;

View File

@ -140,16 +140,17 @@ pub fn log(timestamp: i64, data: &[u8]) {
for i in 0..data.len() { for i in 0..data.len() {
word <<= 8; word <<= 8;
word |= data[i] as u32; word |= data[i] as u32;
if i % 4 == 0 { if i % 4 == 3 {
rtio_o_data_write(0, word); rtio_o_data_write(0, word);
csr::rtio::o_we_write(1); csr::rtio::o_we_write(1);
word = 0; word = 0;
} }
} }
word <<= 8; if word != 0 {
rtio_o_data_write(0, word); rtio_o_data_write(0, word);
csr::rtio::o_we_write(1); csr::rtio::o_we_write(1);
}
} }
} }

View File

@ -104,19 +104,17 @@ unsafe impl<'a> Alloc for &'a ListAlloc {
} }
fn oom(&mut self, err: AllocErr) -> ! { fn oom(&mut self, err: AllocErr) -> ! {
panic!("cannot allocate: {:?}", err) panic!("heap view: {}\ncannot allocate: {:?}", self, err)
} }
} }
impl ListAlloc { impl fmt::Display for ListAlloc {
pub fn debug_dump(&self, f: &mut fmt::Write) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
unsafe { unsafe {
let mut total_busy = 0; let mut total_busy = 0;
let mut total_idle = 0; let mut total_idle = 0;
let mut total_meta = 0; let mut total_meta = 0;
write!(f, "Heap view:\n")?;
let mut curr = self.root; let mut curr = self.root;
while !curr.is_null() { while !curr.is_null() {
total_meta += mem::size_of::<Header>(); total_meta += mem::size_of::<Header>();

View File

@ -0,0 +1,8 @@
[package]
authors = ["M-Labs"]
name = "backtrace_artiq"
version = "0.0.0"
[lib]
name = "backtrace_artiq"
path = "lib.rs"

View File

@ -0,0 +1,30 @@
#![feature(libc, panic_unwind)]
#![no_std]
extern crate unwind;
extern crate libc;
use unwind as uw;
use libc::c_void;
pub fn backtrace<F>(mut f: F) -> Result<(), uw::_Unwind_Reason_Code>
where F: FnMut(usize) -> ()
{
extern fn trace<F>(context: *mut uw::_Unwind_Context, arg: *mut c_void)
-> uw::_Unwind_Reason_Code
where F: FnMut(usize) -> ()
{
unsafe {
let step_fn = &mut *(arg as *mut F);
step_fn(uw::_Unwind_GetIP(context));
uw::_URC_NO_REASON
}
}
unsafe {
match uw::_Unwind_Backtrace(trace::<F>, &mut f as *mut _ as *mut c_void) {
uw::_URC_NO_REASON => Ok(()),
err => Err(err)
}
}
}

View File

@ -9,6 +9,7 @@ name = "board"
path = "lib.rs" path = "lib.rs"
[dependencies] [dependencies]
byteorder = { version = "1.0", default-features = false }
log = { version = "0.3", default-features = false } log = { version = "0.3", default-features = false }
[features] [features]

View File

@ -0,0 +1,232 @@
#[cfg(has_spiflash)]
mod imp {
use core::str;
use byteorder::{ByteOrder, BigEndian};
use cache;
use spiflash;
// One flash sector immediately before the firmware.
const ADDR: usize = ::mem::FLASH_BOOT_ADDRESS - spiflash::SECTOR_SIZE;
const SIZE: usize = spiflash::SECTOR_SIZE;
mod lock {
use core::slice;
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
static LOCKED: AtomicUsize = ATOMIC_USIZE_INIT;
pub struct Lock;
impl Lock {
pub fn take() -> Result<Lock, ()> {
if LOCKED.swap(1, Ordering::SeqCst) != 0 {
Err(()) // already locked
} else {
Ok(Lock) // locked now
}
}
pub fn data(&self) -> &'static [u8] {
unsafe { slice::from_raw_parts(super::ADDR as *const u8, super::SIZE) }
}
}
impl Drop for Lock {
fn drop(&mut self) {
LOCKED.store(0, Ordering::SeqCst)
}
}
}
use self::lock::Lock;
#[derive(Clone)]
struct Iter<'a> {
data: &'a [u8],
offset: usize
}
impl<'a> Iter<'a> {
fn new(data: &'a [u8]) -> Iter<'a> {
Iter { data: data, offset: 0 }
}
}
impl<'a> Iterator for Iter<'a> {
type Item = Result<(&'a [u8], &'a [u8]), ()>;
fn next(&mut self) -> Option<Self::Item> {
let data = &self.data[self.offset..];
if data.len() < 4 {
error!("offset {}: truncated record", self.offset);
return Some(Err(()))
}
let record_size = BigEndian::read_u32(data) as usize;
if record_size == !0 /* all ones; erased flash */ {
return None
} else if record_size < 4 || record_size > data.len() {
error!("offset {}: invalid record size {}", self.offset, record_size);
return Some(Err(()))
}
let record_body = &data[4..record_size];
match record_body.iter().position(|&x| x == 0) {
None => {
error!("offset {}: missing separator", self.offset);
Some(Err(()))
}
Some(pos) => {
self.offset += record_size;
let (key, zero_and_value) = record_body.split_at(pos);
Some(Ok((key, &zero_and_value[1..])))
}
}
}
}
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(key: &str, f: F) -> R {
f(Lock::take().and_then(|lock| {
let mut iter = Iter::new(lock.data());
let mut value = &[][..];
while let Some(result) = iter.next() {
let (record_key, record_value) = result?;
if key.as_bytes() == record_key {
// last write wins
value = record_value
}
}
Ok(value)
}))
}
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(key: &str, f: F) -> R {
read(key, |result| {
f(result.and_then(|value| str::from_utf8(value).map_err(|_| ())))
})
}
unsafe fn append_at<'a>(mut data: &'a [u8], key: &[u8], value: &[u8]) -> Result<&'a [u8], ()> {
let record_size = 4 + key.len() + 1 + value.len();
if data.len() < record_size {
return Err(())
}
let mut record_size_bytes = [0u8; 4];
BigEndian::write_u32(&mut record_size_bytes[..], record_size as u32);
spiflash::write(data.as_ptr() as usize, &record_size_bytes[..]);
data = &data[record_size_bytes.len()..];
spiflash::write(data.as_ptr() as usize, key);
data = &data[key.len()..];
spiflash::write(data.as_ptr() as usize, &[0]);
data = &data[1..];
spiflash::write(data.as_ptr() as usize, value);
data = &data[value.len()..];
cache::flush_l2_cache();
Ok(data)
}
fn compact() -> Result<(), ()> {
let lock = Lock::take()?;
static mut OLD_DATA: [u8; SIZE] = [0; SIZE];
let old_data = unsafe {
OLD_DATA.copy_from_slice(lock.data());
&OLD_DATA[..]
};
let mut data = lock.data();
unsafe { spiflash::erase_sector(data.as_ptr() as usize) };
// This is worst-case quadratic, but we're limited by a small SPI flash sector size,
// so it does not really matter.
let mut iter = Iter::new(old_data);
while let Some(result) = iter.next() {
let (key, mut value) = result?;
let mut next_iter = iter.clone();
while let Some(next_result) = next_iter.next() {
let (next_key, next_value) = next_result?;
if key == next_key {
value = next_value
}
}
data = unsafe { append_at(data, key, value)? };
}
Ok(())
}
fn append(key: &str, value: &[u8]) -> Result<(), ()> {
let lock = Lock::take()?;
let free = {
let mut iter = Iter::new(lock.data());
while let Some(result) = iter.next() {
let _ = result?;
}
&iter.data[iter.offset..]
};
unsafe { append_at(free, key.as_bytes(), value)? };
Ok(())
}
pub fn write(key: &str, value: &[u8]) -> Result<(), ()> {
match append(key, value) {
Ok(()) => (),
Err(()) => {
compact()?;
append(key, value)?;
}
}
Ok(())
}
pub fn remove(key: &str) -> Result<(), ()> {
write(key, &[])
}
pub fn erase() -> Result<(), ()> {
let lock = Lock::take()?;
unsafe { spiflash::erase_sector(lock.data().as_ptr() as usize) };
cache::flush_l2_cache();
Ok(())
}
}
#[cfg(not(has_spiflash))]
mod imp {
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(_key: &str, f: F) -> R {
f(Err(()))
}
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(_key: &str, f: F) -> R {
f(Err(()))
}
pub fn write(_key: &str, _value: &[u8]) -> Result<(), ()> {
Err(())
}
pub fn remove(_key: &str) -> Result<(), ()> {
Err(())
}
pub fn erase() -> Result<(), ()> {
Err(())
}
}
pub use self::imp::*;

View File

@ -1,6 +1,7 @@
#![feature(asm, lang_items)] #![feature(asm, lang_items)]
#![no_std] #![no_std]
extern crate byteorder;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
@ -18,6 +19,7 @@ pub mod uart_console;
#[cfg(has_spiflash)] #[cfg(has_spiflash)]
pub mod spiflash; pub mod spiflash;
pub mod config;
pub mod i2c; pub mod i2c;
pub mod spi; pub mod spi;

View File

@ -3,6 +3,11 @@
use core::cmp; use core::cmp;
use csr; use csr;
pub const SECTOR_SIZE: usize = csr::CONFIG_SPIFLASH_SECTOR_SIZE as usize;
pub const PAGE_SIZE: usize = csr::CONFIG_SPIFLASH_PAGE_SIZE as usize;
const PAGE_MASK: usize = PAGE_SIZE - 1;
const CMD_PP: u8 = 0x02; const CMD_PP: u8 = 0x02;
const CMD_WRDI: u8 = 0x04; const CMD_WRDI: u8 = 0x04;
const CMD_RDSR: u8 = 0x05; const CMD_RDSR: u8 = 0x05;
@ -15,28 +20,24 @@ const PIN_DQ_I: u8 = 1 << 3;
const SR_WIP: u8 = 1; const SR_WIP: u8 = 1;
fn write_byte(mut byte: u8) { unsafe fn write_byte(mut byte: u8) {
unsafe { csr::spiflash::bitbang_write(0);
csr::spiflash::bitbang_write(0); for _ in 0..8 {
for _ in 0..8 { csr::spiflash::bitbang_write((byte & 0x80) >> 7);
csr::spiflash::bitbang_write((byte & 0x80) >> 7); csr::spiflash::bitbang_write((byte & 0x80) >> 7 | PIN_CLK);
csr::spiflash::bitbang_write((byte & 0x80) >> 7 | PIN_CLK); byte <<= 1;
byte <<= 1;
}
csr::spiflash::bitbang_write(0);
} }
csr::spiflash::bitbang_write(0);
} }
fn write_addr(mut addr: usize) { unsafe fn write_addr(mut addr: usize) {
unsafe { csr::spiflash::bitbang_write(0);
csr::spiflash::bitbang_write(0); for _ in 0..24 {
for _ in 0..24 { csr::spiflash::bitbang_write(((addr & 0x800000) >> 23) as u8);
csr::spiflash::bitbang_write(((addr & 0x800000) >> 23) as u8); csr::spiflash::bitbang_write(((addr & 0x800000) >> 23) as u8 | PIN_CLK);
csr::spiflash::bitbang_write(((addr & 0x800000) >> 23) as u8 | PIN_CLK); addr <<= 1;
addr <<= 1;
}
csr::spiflash::bitbang_write(0);
} }
csr::spiflash::bitbang_write(0);
} }
fn wait_until_ready() { fn wait_until_ready() {
@ -59,54 +60,47 @@ fn wait_until_ready() {
} }
} }
pub fn erase_sector(addr: usize) { pub unsafe fn erase_sector(addr: usize) {
unsafe { let sector_addr = addr & !(csr::CONFIG_SPIFLASH_SECTOR_SIZE as usize - 1);
let sector_addr = addr & !(csr::CONFIG_SPIFLASH_SECTOR_SIZE as usize - 1);
csr::spiflash::bitbang_en_write(1); csr::spiflash::bitbang_en_write(1);
wait_until_ready(); wait_until_ready();
write_byte(CMD_WREN); write_byte(CMD_WREN);
csr::spiflash::bitbang_write(PIN_CS_N); csr::spiflash::bitbang_write(PIN_CS_N);
write_byte(CMD_SE); write_byte(CMD_SE);
write_addr(sector_addr); write_addr(sector_addr);
csr::spiflash::bitbang_write(PIN_CS_N); csr::spiflash::bitbang_write(PIN_CS_N);
wait_until_ready(); wait_until_ready();
csr::spiflash::bitbang_en_write(0); csr::spiflash::bitbang_en_write(0);
}
} }
fn write_page(addr: usize, data: &[u8]) { unsafe fn write_page(addr: usize, data: &[u8]) {
unsafe { csr::spiflash::bitbang_en_write(1);
csr::spiflash::bitbang_en_write(1);
wait_until_ready(); wait_until_ready();
write_byte(CMD_WREN); write_byte(CMD_WREN);
csr::spiflash::bitbang_write(PIN_CS_N); csr::spiflash::bitbang_write(PIN_CS_N);
write_byte(CMD_PP); write_byte(CMD_PP);
write_addr(addr); write_addr(addr);
for &byte in data { for &byte in data {
write_byte(byte) write_byte(byte)
}
csr::spiflash::bitbang_write(PIN_CS_N);
csr::spiflash::bitbang_write(0);
wait_until_ready();
csr::spiflash::bitbang_en_write(0);
} }
csr::spiflash::bitbang_write(PIN_CS_N);
csr::spiflash::bitbang_write(0);
wait_until_ready();
csr::spiflash::bitbang_en_write(0);
} }
const PAGE_SIZE: usize = csr::CONFIG_SPIFLASH_PAGE_SIZE as usize; pub unsafe fn write(mut addr: usize, mut data: &[u8]) {
const PAGE_MASK: usize = PAGE_SIZE - 1;
pub fn write(mut addr: usize, mut data: &[u8]) {
if addr & PAGE_MASK != 0 { if addr & PAGE_MASK != 0 {
let size = cmp::min((PAGE_SIZE - (addr & PAGE_MASK)) as usize, data.len()); let size = cmp::min((PAGE_SIZE - (addr & PAGE_MASK)) as usize, data.len());
write_page(addr, &data[..size]); write_page(addr, &data[..size]);

View File

@ -19,6 +19,7 @@ log = { version = "0.3", default-features = false }
alloc_list = { path = "../liballoc_list" } alloc_list = { path = "../liballoc_list" }
std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] } std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] }
logger_artiq = { path = "../liblogger_artiq" } logger_artiq = { path = "../liblogger_artiq" }
backtrace_artiq = { path = "../libbacktrace_artiq" }
board = { path = "../libboard", features = ["uart_console"] } board = { path = "../libboard", features = ["uart_console"] }
proto = { path = "../libproto", features = ["log"] } proto = { path = "../libproto", features = ["log"] }
amp = { path = "../libamp" } amp = { path = "../libamp" }
@ -37,6 +38,6 @@ features = ["alloc"]
[dependencies.smoltcp] [dependencies.smoltcp]
git = "https://github.com/m-labs/smoltcp" git = "https://github.com/m-labs/smoltcp"
rev = "6f5ae33" rev = "181083f"
default-features = false default-features = false
features = ["alloc", "log"] features = ["alloc", "log", "proto-ipv4", "socket-tcp"]

View File

@ -1,32 +1,30 @@
include ../include/generated/variables.mak include ../include/generated/variables.mak
include $(MISOC_DIRECTORY)/software/common.mak include $(MISOC_DIRECTORY)/software/common.mak
LDFLAGS += -L../libbase CFLAGS += \
-I$(LIBUNWIND_DIRECTORY) \
-I$(LIBUNWIND_DIRECTORY)/../unwinder/include
RUSTFLAGS += -Cpanic=abort LDFLAGS += -L../libbase \
-L../libunwind
all: runtime.bin runtime.fbi RUSTFLAGS += -Cpanic=unwind
all:: runtime.bin runtime.fbi
.PHONY: $(RUSTOUT)/libruntime.a .PHONY: $(RUSTOUT)/libruntime.a
$(RUSTOUT)/libruntime.a: $(RUSTOUT)/libruntime.a:
$(cargo) --manifest-path $(RUNTIME_DIRECTORY)/Cargo.toml $(cargo) --manifest-path $(RUNTIME_DIRECTORY)/Cargo.toml
runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o
$(LD) $(LDFLAGS) -T $(RUNTIME_DIRECTORY)/runtime.ld -o $@ $^ $(link) -T $(RUNTIME_DIRECTORY)/runtime.ld \
@chmod -x $@ -lunwind-bare
ksupport_data.o: ../ksupport/ksupport.elf ksupport_data.o: ../ksupport/ksupport.elf
$(LD) -r -b binary -o $@ $< $(LD) -r -b binary -o $@ $<
%.bin: %.elf %.bin: %.elf
$(OBJCOPY) -O binary $< $@ $(objcopy) -O binary
@chmod -x $@
%.fbi: %.bin %.fbi: %.bin
@echo " MSCIMG " $@ && $(PYTHON) -m misoc.tools.mkmscimg -f -o $@ $< $(mscimg) -f
clean:
$(RM) *.o runtime.elf runtime.bin runtime.fbi
$(RM) -rf cargo
.PHONY: all clean

View File

@ -1,192 +0,0 @@
use core::str;
use std::btree_map::BTreeMap;
use byteorder::{ByteOrder, BigEndian};
use board::{mem, csr, cache, spiflash};
const ADDR: usize = mem::FLASH_BOOT_ADDRESS + 0x80000 /* max runtime size */;
const SIZE: usize = csr::CONFIG_SPIFLASH_SECTOR_SIZE as usize;
mod lock {
use core::slice;
use core::sync::atomic::{AtomicUsize, Ordering};
static LOCKED: AtomicUsize = AtomicUsize::new(0);
pub struct Lock;
impl Lock {
pub fn take() -> Result<Lock, ()> {
if LOCKED.swap(1, Ordering::SeqCst) != 0 {
Err(()) // already locked
} else {
Ok(Lock) // locked now
}
}
pub fn data(&self) -> &'static [u8] {
unsafe { slice::from_raw_parts(super::ADDR as *const u8, super::SIZE) }
}
}
impl Drop for Lock {
fn drop(&mut self) {
LOCKED.store(0, Ordering::SeqCst)
}
}
}
pub use self::lock::Lock;
struct Iter<'a> {
data: &'a [u8],
offset: usize
}
impl<'a> Iter<'a> {
fn new(data: &'a [u8]) -> Iter<'a> {
Iter { data: data, offset: 0 }
}
}
impl<'a> Iterator for Iter<'a> {
type Item = Result<(&'a [u8], &'a [u8]), ()>;
fn next(&mut self) -> Option<Self::Item> {
let data = &self.data[self.offset..];
if data.len() < 4 {
error!("offset {}: truncated record", self.offset);
return Some(Err(()))
}
let record_size = BigEndian::read_u32(data) as usize;
if record_size < 4 {
error!("offset {}: invalid record size", self.offset);
return Some(Err(()))
}
if record_size == !0 /* all ones; erased flash */ {
return None
}
let record_body = &data[4..record_size];
match record_body.iter().position(|&x| x == 0) {
None => {
error!("offset {}: missing separator", self.offset);
Some(Err(()))
}
Some(pos) => {
self.offset += record_size;
let (key, zero_and_value) = record_body.split_at(pos);
Some(Ok((key, &zero_and_value[1..])))
}
}
}
}
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(key: &str, f: F) -> R {
f(Lock::take().and_then(|lock| {
let mut iter = Iter::new(lock.data());
let mut value = &[][..];
while let Some(result) = iter.next() {
let (record_key, record_value) = result?;
if key.as_bytes() == record_key {
// last write wins
value = record_value
}
}
Ok(value)
}))
}
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(key: &str, f: F) -> R {
read(key, |result| {
f(result.and_then(|value| str::from_utf8(value).map_err(|_| ())))
})
}
fn append_at(mut offset: usize, key: &[u8], value: &[u8]) -> Result<usize, ()> {
let record_size = 4 + key.len() + 1 + value.len();
if offset + record_size > SIZE {
return Err(())
}
let mut record_size_bytes = [0u8; 4];
BigEndian::write_u32(&mut record_size_bytes[..], record_size as u32);
spiflash::write(ADDR + offset, &record_size_bytes[..]);
offset += record_size_bytes.len();
spiflash::write(ADDR + offset, key);
offset += key.len();
spiflash::write(ADDR + offset, &[0]);
offset += 1;
spiflash::write(ADDR + offset, value);
offset += value.len();
cache::flush_l2_cache();
Ok(offset)
}
fn compact() -> Result<(), ()> {
let lock = Lock::take()?;
let mut items = BTreeMap::new();
{
let mut iter = Iter::new(lock.data());
while let Some(result) = iter.next() {
let (key, value) = result?;
items.insert(key, value);
}
}
spiflash::erase_sector(ADDR);
cache::flush_l2_cache();
let mut offset = 0;
for (key, value) in items {
offset = append_at(offset, key, value)?;
}
Ok(())
}
fn append(key: &str, value: &[u8]) -> Result<(), ()> {
let lock = Lock::take()?;
let free_offset = {
let mut iter = Iter::new(lock.data());
while let Some(result) = iter.next() {
let _ = result?;
}
iter.offset
};
append_at(free_offset, key.as_bytes(), value)?;
Ok(())
}
pub fn write(key: &str, value: &[u8]) -> Result<(), ()> {
match append(key, value) {
Ok(()) => (),
Err(()) => {
compact()?;
append(key, value)?;
}
}
Ok(())
}
pub fn remove(key: &str) -> Result<(), ()> {
write(key, &[])
}
pub fn erase() -> Result<(), ()> {
let _lock = Lock::take()?;
spiflash::erase_sector(ADDR);
cache::flush_l2_cache();
Ok(())
}

View File

@ -1,19 +0,0 @@
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(_key: &str, f: F) -> R {
f(Err(()))
}
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(_key: &str, f: F) -> R {
f(Err(()))
}
pub fn write(_key: &str, _value: &[u8]) -> Result<(), ()> {
Err(())
}
pub fn remove(_key: &str) -> Result<(), ()> {
Err(())
}
pub fn erase() -> Result<(), ()> {
Err(())
}

View File

@ -1,88 +1,158 @@
use core::slice; use core::{slice, fmt};
use smoltcp::Result;
use smoltcp::phy::{self, DeviceCapabilities, Device};
use board::{csr, mem}; use board::{csr, mem};
use smoltcp::Error;
use smoltcp::phy::{DeviceLimits, Device};
const RX0_BASE: usize = mem::ETHMAC_BASE + 0x0000; const RX_SLOTS: usize = csr::ETHMAC_RX_SLOTS as usize;
const RX1_BASE: usize = mem::ETHMAC_BASE + 0x0800; const TX_SLOTS: usize = csr::ETHMAC_TX_SLOTS as usize;
const RX2_BASE: usize = mem::ETHMAC_BASE + 0x1000; const SLOT_SIZE: usize = csr::ETHMAC_SLOT_SIZE as usize;
const RX3_BASE: usize = mem::ETHMAC_BASE + 0x1800;
const TX0_BASE: usize = mem::ETHMAC_BASE + 0x2000;
const TX1_BASE: usize = mem::ETHMAC_BASE + 0x2800;
const TX2_BASE: usize = mem::ETHMAC_BASE + 0x3000;
const TX3_BASE: usize = mem::ETHMAC_BASE + 0x3800;
const RX_BUFFERS: [*mut u8; 4] = [RX0_BASE as *mut u8, RX1_BASE as *mut u8, fn next_rx_slot() -> Option<usize> {
RX2_BASE as *mut u8, RX3_BASE as *mut u8]; unsafe {
const TX_BUFFERS: [*mut u8; 4] = [TX0_BASE as *mut u8, TX1_BASE as *mut u8, if csr::ethmac::sram_writer_ev_pending_read() == 0 {
TX2_BASE as *mut u8, TX3_BASE as *mut u8]; None
} else {
pub struct EthernetDevice; Some(csr::ethmac::sram_writer_slot_read() as usize)
impl Device for EthernetDevice {
type RxBuffer = RxBuffer;
type TxBuffer = TxBuffer;
fn limits(&self) -> DeviceLimits {
let mut limits = DeviceLimits::default();
limits.max_transmission_unit = 1514;
limits.max_burst_size = Some(RX_BUFFERS.len());
limits
}
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer, Error> {
unsafe {
if csr::ethmac::sram_writer_ev_pending_read() != 0 {
let slot = csr::ethmac::sram_writer_slot_read();
let length = csr::ethmac::sram_writer_length_read();
Ok(RxBuffer(slice::from_raw_parts(RX_BUFFERS[slot as usize],
length as usize)))
} else {
Err(Error::Exhausted)
}
}
}
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> {
unsafe {
if csr::ethmac::sram_reader_ready_read() != 0 {
let slot = csr::ethmac::sram_reader_slot_read();
let slot = (slot + 1) % (TX_BUFFERS.len() as u8);
csr::ethmac::sram_reader_slot_write(slot);
csr::ethmac::sram_reader_length_write(length as u16);
Ok(TxBuffer(slice::from_raw_parts_mut(TX_BUFFERS[slot as usize],
length as usize)))
} else {
Err(Error::Exhausted)
}
} }
} }
} }
pub struct RxBuffer(&'static [u8]); fn next_tx_slot() -> Option<usize> {
unsafe {
impl AsRef<[u8]> for RxBuffer { if csr::ethmac::sram_reader_ready_read() == 0 {
fn as_ref(&self) -> &[u8] { self.0 } None
} } else {
Some((csr::ethmac::sram_reader_slot_read() as usize + 1) % TX_SLOTS)
impl Drop for RxBuffer { }
fn drop(&mut self) {
unsafe { csr::ethmac::sram_writer_ev_pending_write(1) }
} }
} }
pub struct TxBuffer(&'static mut [u8]); fn rx_buffer(slot: usize) -> *const u8 {
debug_assert!(slot < RX_SLOTS);
impl AsRef<[u8]> for TxBuffer { (mem::ETHMAC_BASE + SLOT_SIZE * slot) as _
fn as_ref(&self) -> &[u8] { self.0 }
} }
impl AsMut<[u8]> for TxBuffer { fn tx_buffer(slot: usize) -> *mut u8 {
fn as_mut(&mut self) -> &mut [u8] { self.0 } debug_assert!(slot < TX_SLOTS);
(mem::ETHMAC_BASE + SLOT_SIZE * (RX_SLOTS + slot)) as _
} }
impl Drop for TxBuffer { pub struct EthernetDevice(());
fn drop(&mut self) {
unsafe { csr::ethmac::sram_reader_start_write(1) } impl EthernetDevice {
pub unsafe fn new() -> EthernetDevice {
EthernetDevice(())
}
}
impl<'a> Device<'a> for EthernetDevice {
type RxToken = EthernetRxSlot;
type TxToken = EthernetTxSlot;
fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default();
caps.max_transmission_unit = 1514;
caps.max_burst_size = Some(RX_SLOTS);
caps
}
fn receive(&mut self) -> Option<(Self::RxToken, Self::TxToken)> {
if let (Some(rx_slot), Some(tx_slot)) = (next_rx_slot(), next_tx_slot()) {
Some((EthernetRxSlot(rx_slot), EthernetTxSlot(tx_slot)))
} else {
None
}
}
fn transmit(&mut self) -> Option<Self::TxToken> {
if let Some(tx_slot) = next_tx_slot() {
Some(EthernetTxSlot(tx_slot))
} else {
None
}
}
}
pub struct EthernetRxSlot(usize);
impl phy::RxToken for EthernetRxSlot {
fn consume<R, F>(self, _timestamp: u64, f: F) -> Result<R>
where F: FnOnce(&[u8]) -> Result<R>
{
unsafe {
let length = csr::ethmac::sram_writer_length_read() as usize;
let result = f(slice::from_raw_parts(rx_buffer(self.0), length));
csr::ethmac::sram_writer_ev_pending_write(1);
result
}
}
}
pub struct EthernetTxSlot(usize);
impl phy::TxToken for EthernetTxSlot {
fn consume<R, F>(self, _timestamp: u64, length: usize, f: F) -> Result<R>
where F: FnOnce(&mut [u8]) -> Result<R>
{
debug_assert!(length < SLOT_SIZE);
unsafe {
let result = f(slice::from_raw_parts_mut(tx_buffer(self.0), length))?;
csr::ethmac::sram_reader_slot_write(self.0 as u8);
csr::ethmac::sram_reader_length_write(length as u16);
csr::ethmac::sram_reader_start_write(1);
Ok(result)
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct EthernetStatistics {
rx_preamble_errors: u32,
rx_crc_errors: u32,
rx_dropped: u32,
}
impl EthernetStatistics {
pub fn new() -> Self {
unsafe {
EthernetStatistics {
rx_preamble_errors: csr::ethmac::preamble_errors_read(),
rx_crc_errors: csr::ethmac::crc_errors_read(),
rx_dropped: csr::ethmac::sram_writer_errors_read(),
}
}
}
pub fn update(&mut self) -> Option<Self> {
let old = self.clone();
*self = Self::new();
let diff = EthernetStatistics {
rx_preamble_errors: self.rx_preamble_errors.wrapping_sub(old.rx_preamble_errors),
rx_crc_errors: self.rx_crc_errors.wrapping_sub(old.rx_crc_errors),
rx_dropped: self.rx_dropped.wrapping_sub(old.rx_dropped),
};
if diff == EthernetStatistics::default() {
None
} else {
Some(diff)
}
}
}
impl fmt::Display for EthernetStatistics {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.rx_preamble_errors > 0 {
write!(f, " rx preamble errors: {}", self.rx_preamble_errors)?
}
if self.rx_crc_errors > 0 {
write!(f, " rx crc errors: {}", self.rx_crc_errors)?
}
if self.rx_dropped > 0 {
write!(f, " rx dropped: {}", self.rx_dropped)?
}
Ok(())
} }
} }

View File

@ -14,6 +14,7 @@ extern crate alloc_list;
#[macro_use] #[macro_use]
extern crate std_artiq as std; extern crate std_artiq as std;
extern crate logger_artiq; extern crate logger_artiq;
extern crate backtrace_artiq;
#[macro_use] #[macro_use]
extern crate board; extern crate board;
extern crate proto; extern crate proto;
@ -21,24 +22,12 @@ extern crate amp;
#[cfg(has_drtio)] #[cfg(has_drtio)]
extern crate drtioaux; extern crate drtioaux;
use std::boxed::Box; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
use smoltcp::wire::{EthernetAddress, IpAddress};
use board::config;
use proto::{mgmt_proto, analyzer_proto, moninj_proto, rpc_proto, session_proto, kernel_proto}; use proto::{mgmt_proto, analyzer_proto, moninj_proto, rpc_proto, session_proto, kernel_proto};
use amp::{mailbox, rpc_queue}; use amp::{mailbox, rpc_queue};
macro_rules! borrow_mut {
($x:expr) => ({
match $x.try_borrow_mut() {
Ok(x) => x,
Err(_) => panic!("cannot borrow mutably at {}:{}", file!(), line!())
}
})
}
#[cfg(has_spiflash)]
mod config;
#[cfg(not(has_spiflash))]
#[path="config_dummy.rs"] mod config;
mod ethmac; mod ethmac;
mod rtio_mgt; mod rtio_mgt;
@ -95,7 +84,7 @@ fn startup() {
let protocol_addr; let protocol_addr;
match config::read_str("ip", |r| r?.parse()) { match config::read_str("ip", |r| r?.parse()) {
Err(()) | Ok(IpAddress::Unspecified) => { Err(()) => {
protocol_addr = IpAddress::v4(192, 168, 1, 50); protocol_addr = IpAddress::v4(192, 168, 1, 50);
info!("using default IP address {}", protocol_addr); info!("using default IP address {}", protocol_addr);
} }
@ -109,15 +98,20 @@ fn startup() {
// where U: smoltcp::wire::pretty_print::PrettyPrint { // where U: smoltcp::wire::pretty_print::PrettyPrint {
// let seconds = timestamp / 1000; // let seconds = timestamp / 1000;
// let micros = timestamp % 1000 * 1000; // let micros = timestamp % 1000 * 1000;
// print!("\x1b[37m[{:6}.{:06}s]\n{}\x1b[0m", seconds, micros, printer) // print!("\x1b[37m[{:6}.{:06}s]\n{}\x1b[0m\n", seconds, micros, printer)
// } // }
let net_device = ethmac::EthernetDevice; let net_device = unsafe { ethmac::EthernetDevice::new() };
// let net_device = smoltcp::phy::EthernetTracer::new(net_device, _net_trace_writer); // let net_device = smoltcp::phy::EthernetTracer::new(net_device, _net_trace_writer);
let arp_cache = smoltcp::iface::SliceArpCache::new([Default::default(); 8]); let mut neighbor_cache_storage = [None; 8];
let mut interface = smoltcp::iface::EthernetInterface::new( let neighbor_cache =
Box::new(net_device), Box::new(arp_cache) as Box<smoltcp::iface::ArpCache>, smoltcp::iface::NeighborCache::new(&mut neighbor_cache_storage[..]);
hardware_addr, [protocol_addr]); let mut interface =
smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
.neighbor_cache(neighbor_cache)
.ethernet_addr(hardware_addr)
.ip_addrs([IpCidr::new(protocol_addr, 0)])
.finalize();
let mut scheduler = sched::Scheduler::new(); let mut scheduler = sched::Scheduler::new();
let io = scheduler.io(); let io = scheduler.io();
@ -154,11 +148,16 @@ fn startup() {
loop { loop {
scheduler.run(); scheduler.run();
match interface.poll(&mut *borrow_mut!(scheduler.sockets()), {
board::clock::get_ms()) { let sockets = &mut *scheduler.sockets().borrow_mut();
Ok(_poll_at) => (), loop {
Err(smoltcp::Error::Unrecognized) => (), match interface.poll(sockets, board::clock::get_ms()) {
Err(err) => warn!("network error: {}", err) Ok(true) => (),
Ok(false) => break,
Err(smoltcp::Error::Unrecognized) => (),
Err(err) => warn!("network error: {}", err)
}
}
} }
} }
} }
@ -189,7 +188,9 @@ pub extern fn exception_handler(vect: u32, _regs: *const u32, pc: u32, ea: u32)
#[no_mangle] #[no_mangle]
pub extern fn abort() { pub extern fn abort() {
panic!("aborted") println!("aborted");
loop {}
} }
#[no_mangle] #[no_mangle]
@ -197,6 +198,12 @@ pub extern fn abort() {
pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! { pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
println!("panic at {}:{}: {}", file, line, args); println!("panic at {}:{}: {}", file, line, args);
println!("backtrace for software version {}:",
include_str!(concat!(env!("OUT_DIR"), "/git-describe")));
let _ = backtrace_artiq::backtrace(|ip| {
println!("{:#08x}", ip);
});
if config::read_str("panic_reboot", |r| r == Ok("1")) { if config::read_str("panic_reboot", |r| r == Ok("1")) {
println!("rebooting..."); println!("rebooting...");
unsafe { board::boot::reboot() } unsafe { board::boot::reboot() }
@ -206,11 +213,3 @@ pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u3
loop {} loop {}
} }
} }
// Allow linking with crates that are built as -Cpanic=unwind even if we use -Cpanic=abort.
// This is never called.
#[allow(non_snake_case)]
#[no_mangle]
pub extern fn _Unwind_Resume() -> ! {
loop {}
}

View File

@ -1,5 +1,4 @@
use config; use board::{csr, config};
use board::csr;
use sched::Io; use sched::Io;
#[cfg(has_rtio_crg)] #[cfg(has_rtio_crg)]
@ -219,16 +218,25 @@ pub fn startup(io: &Io) {
let clk = config::read("startup_clock", |result| { let clk = config::read("startup_clock", |result| {
match result { match result {
Ok(b"i") => RtioClock::Internal, Ok(b"i") => {
Ok(b"e") => RtioClock::External, info!("using internal startup RTIO clock");
_ => { RtioClock::Internal
error!("unrecognized startup_clock configuration entry"); },
Ok(b"e") => {
info!("using external startup RTIO clock");
RtioClock::External
},
Err(()) => {
info!("using internal startup RTIO clock (by default)");
RtioClock::Internal
},
Ok(_) => {
error!("unrecognized startup_clock configuration entry, using internal RTIO clock");
RtioClock::Internal RtioClock::Internal
} }
} }
}); });
info!("startup RTIO clock: {:?}", clk);
if !crg::switch_clock(clk as u8) { if !crg::switch_clock(clk as u8) {
error!("startup RTIO clock failed"); error!("startup RTIO clock failed");
warn!("this may cause the system initialization to fail"); warn!("this may cause the system initialization to fail");

View File

@ -20,6 +20,21 @@ SECTIONS
_etext = .; _etext = .;
} > runtime } > runtime
.eh_frame :
{
__eh_frame_start = .;
KEEP(*(.eh_frame))
__eh_frame_end = .;
} > runtime
.eh_frame_hdr :
{
KEEP(*(.eh_frame_hdr))
} > runtime
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
/* https://sourceware.org/bugzilla/show_bug.cgi?id=20475 */ /* https://sourceware.org/bugzilla/show_bug.cgi?id=20475 */
.got : .got :
{ {
@ -79,10 +94,4 @@ SECTIONS
. = ORIGIN(runtime) + LENGTH(runtime); . = ORIGIN(runtime) + LENGTH(runtime);
_eheap = .; _eheap = .;
} > runtime } > runtime
/DISCARD/ :
{
*(.eh_frame)
*(.gcc_except_table)
}
} }

View File

@ -1,19 +1,20 @@
#![allow(dead_code)] #![allow(dead_code)]
use std::mem; use std::mem;
use std::cell::{Cell, RefCell, RefMut}; use std::cell::{Cell, RefCell};
use std::vec::Vec; use std::vec::Vec;
use std::io::{Read, Write, Result, Error, ErrorKind}; use std::io::{Read, Write, Result, Error, ErrorKind};
use fringe::OwnedStack; use fringe::OwnedStack;
use fringe::generator::{Generator, Yielder, State as GeneratorState}; use fringe::generator::{Generator, Yielder, State as GeneratorState};
use smoltcp::wire::IpEndpoint; use smoltcp::wire::IpEndpoint;
use smoltcp::socket::{AsSocket, SocketHandle}; use smoltcp::socket::{SocketHandle, SocketRef};
type SocketSet = ::smoltcp::socket::SocketSet<'static, 'static, 'static>;
use board; use board;
use urc::Urc; use urc::Urc;
type SocketSet = ::smoltcp::socket::SocketSet<'static, 'static, 'static>;
#[derive(Debug)] #[derive(Debug)]
struct WaitRequest { struct WaitRequest {
event: Option<*const (Fn() -> bool + 'static)>, event: Option<*const (Fn() -> bool + 'static)>,
@ -123,7 +124,7 @@ impl Scheduler {
pub fn run(&mut self) { pub fn run(&mut self) {
self.sockets.borrow_mut().prune(); self.sockets.borrow_mut().prune();
self.threads.append(&mut *borrow_mut!(self.spawned)); self.threads.append(&mut *self.spawned.borrow_mut());
if self.threads.len() == 0 { return } if self.threads.len() == 0 { return }
let now = board::clock::get_ms(); let now = board::clock::get_ms();
@ -132,7 +133,7 @@ impl Scheduler {
self.run_idx = (self.run_idx + 1) % self.threads.len(); self.run_idx = (self.run_idx + 1) % self.threads.len();
let result = { let result = {
let mut thread = borrow_mut!(self.threads[self.run_idx].0); let mut thread = self.threads[self.run_idx].0.borrow_mut();
match thread.waiting_for { match thread.waiting_for {
_ if thread.interrupted => { _ if thread.interrupted => {
thread.interrupted = false; thread.interrupted = false;
@ -163,7 +164,7 @@ impl Scheduler {
}, },
Some(wait_request) => { Some(wait_request) => {
// The thread has suspended itself. // The thread has suspended itself.
let mut thread = borrow_mut!(self.threads[self.run_idx].0); let mut thread = self.threads[self.run_idx].0.borrow_mut();
thread.waiting_for = wait_request thread.waiting_for = wait_request
} }
} }
@ -188,7 +189,7 @@ impl<'a> Io<'a> {
pub fn spawn<F>(&self, stack_size: usize, f: F) -> ThreadHandle pub fn spawn<F>(&self, stack_size: usize, f: F) -> ThreadHandle
where F: 'static + FnOnce(Io) + Send { where F: 'static + FnOnce(Io) + Send {
let handle = unsafe { Thread::new(self, stack_size, f) }; let handle = unsafe { Thread::new(self, stack_size, f) };
borrow_mut!(self.spawned).push(handle.clone()); self.spawned.borrow_mut().push(handle.clone());
handle handle
} }
@ -240,87 +241,18 @@ macro_rules! until {
($socket:expr, $ty:ty, |$var:ident| $cond:expr) => ({ ($socket:expr, $ty:ty, |$var:ident| $cond:expr) => ({
let (sockets, handle) = ($socket.io.sockets.clone(), $socket.handle); let (sockets, handle) = ($socket.io.sockets.clone(), $socket.handle);
$socket.io.until(move || { $socket.io.until(move || {
let mut sockets = borrow_mut!(sockets); let mut sockets = sockets.borrow_mut();
let $var: &mut $ty = sockets.get_mut(handle).as_socket(); let $var = sockets.get::<$ty>(handle);
$cond $cond
}) })
}) })
} }
use ::smoltcp::Error as ErrorLower; use ::smoltcp::Error as ErrorLower;
// https://github.com/rust-lang/rust/issues/44057 // https://github.com/rust-lang/rust/issues/44057
// type ErrorLower = ::smoltcp::Error; // type ErrorLower = ::smoltcp::Error;
type UdpPacketBuffer = ::smoltcp::socket::UdpPacketBuffer<'static>;
type UdpSocketBuffer = ::smoltcp::socket::UdpSocketBuffer<'static, 'static>;
type UdpSocketLower = ::smoltcp::socket::UdpSocket<'static, 'static>;
pub struct UdpSocket<'a> {
io: &'a Io<'a>,
handle: SocketHandle
}
impl<'a> UdpSocket<'a> {
pub fn new(io: &'a Io<'a>, buffer_depth: usize, buffer_width: usize) -> UdpSocket<'a> {
let mut rx_buffer = vec![];
let mut tx_buffer = vec![];
for _ in 0..buffer_depth {
rx_buffer.push(UdpPacketBuffer::new(vec![0; buffer_width]));
tx_buffer.push(UdpPacketBuffer::new(vec![0; buffer_width]));
}
let handle = borrow_mut!(io.sockets)
.add(UdpSocketLower::new(
UdpSocketBuffer::new(rx_buffer),
UdpSocketBuffer::new(tx_buffer)));
UdpSocket {
io: io,
handle: handle
}
}
fn as_lower<'b>(&'b self) -> RefMut<'b, UdpSocketLower> {
RefMut::map(borrow_mut!(self.io.sockets),
|sockets| sockets.get_mut(self.handle).as_socket())
}
pub fn bind<T: Into<IpEndpoint>>(&self, endpoint: T) -> Result<()> {
match self.as_lower().bind(endpoint) {
Ok(()) => Ok(()),
Err(ErrorLower::Illegal) =>
Err(Error::new(ErrorKind::Other, "already listening")),
Err(ErrorLower::Unaddressable) =>
Err(Error::new(ErrorKind::AddrNotAvailable, "port cannot be zero")),
_ => unreachable!()
}
}
pub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, IpEndpoint)> {
until!(self, UdpSocketLower, |s| s.can_recv())?;
match self.as_lower().recv_slice(buf) {
Ok(result) => Ok(result),
Err(_) => unreachable!()
}
}
pub fn send_to(&self, buf: &[u8], addr: IpEndpoint) -> Result<()> {
until!(self, UdpSocketLower, |s| s.can_send())?;
match self.as_lower().send_slice(buf, addr) {
Ok(()) => Ok(()),
Err(ErrorLower::Unaddressable) =>
Err(Error::new(ErrorKind::AddrNotAvailable, "unaddressable destination")),
Err(ErrorLower::Truncated) =>
Err(Error::new(ErrorKind::Other, "packet does not fit in buffer")),
Err(_) => unreachable!()
}
}
}
impl<'a> Drop for UdpSocket<'a> {
fn drop(&mut self) {
borrow_mut!(self.io.sockets).release(self.handle)
}
}
type TcpSocketBuffer = ::smoltcp::socket::TcpSocketBuffer<'static>; type TcpSocketBuffer = ::smoltcp::socket::TcpSocketBuffer<'static>;
type TcpSocketLower = ::smoltcp::socket::TcpSocket<'static>; type TcpSocketLower = ::smoltcp::socket::TcpSocket<'static>;
@ -337,7 +269,8 @@ impl<'a> TcpListener<'a> {
fn new_lower(io: &'a Io<'a>, buffer_size: usize) -> SocketHandle { fn new_lower(io: &'a Io<'a>, buffer_size: usize) -> SocketHandle {
let rx_buffer = vec![0; buffer_size]; let rx_buffer = vec![0; buffer_size];
let tx_buffer = vec![0; buffer_size]; let tx_buffer = vec![0; buffer_size];
borrow_mut!(io.sockets) io.sockets
.borrow_mut()
.add(TcpSocketLower::new( .add(TcpSocketLower::new(
TcpSocketBuffer::new(rx_buffer), TcpSocketBuffer::new(rx_buffer),
TcpSocketBuffer::new(tx_buffer))) TcpSocketBuffer::new(tx_buffer)))
@ -352,35 +285,41 @@ impl<'a> TcpListener<'a> {
} }
} }
fn as_lower<'b>(&'b self) -> RefMut<'b, TcpSocketLower> { fn with_lower<F, R>(&self, f: F) -> R
RefMut::map(borrow_mut!(self.io.sockets), where F: FnOnce(SocketRef<TcpSocketLower>) -> R {
|sockets| sockets.get_mut(self.handle.get()).as_socket()) let mut sockets = self.io.sockets.borrow_mut();
let result = f(sockets.get(self.handle.get()));
result
} }
pub fn is_open(&self) -> bool { pub fn is_open(&self) -> bool {
self.as_lower().is_open() self.with_lower(|s| s.is_open())
} }
pub fn can_accept(&self) -> bool { pub fn can_accept(&self) -> bool {
self.as_lower().is_active() self.with_lower(|s| s.is_active())
} }
pub fn local_endpoint(&self) -> IpEndpoint { pub fn local_endpoint(&self) -> IpEndpoint {
self.as_lower().local_endpoint() self.with_lower(|s| s.local_endpoint())
} }
pub fn listen<T: Into<IpEndpoint>>(&self, endpoint: T) -> Result<()> { pub fn listen<T: Into<IpEndpoint>>(&self, endpoint: T) -> Result<()> {
let endpoint = endpoint.into(); let endpoint = endpoint.into();
match self.as_lower().listen(endpoint) { self.with_lower(|mut s| s.listen(endpoint))
Ok(()) => Ok(()), .map(|()| {
Err(ErrorLower::Illegal) => self.endpoint.set(endpoint);
Err(Error::new(ErrorKind::Other, "already listening")), ()
Err(ErrorLower::Unaddressable) => })
Err(Error::new(ErrorKind::InvalidInput, "port cannot be zero")), .map_err(|err| {
_ => unreachable!() match err {
}?; ErrorLower::Illegal =>
self.endpoint.set(endpoint); Error::new(ErrorKind::Other, "already listening"),
Ok(()) ErrorLower::Unaddressable =>
Error::new(ErrorKind::InvalidInput, "port cannot be zero"),
_ => unreachable!()
}
})
} }
pub fn accept(&self) -> Result<TcpStream<'a>> { pub fn accept(&self) -> Result<TcpStream<'a>> {
@ -389,8 +328,8 @@ impl<'a> TcpListener<'a> {
// that still counts as accepting even though nothing may be sent. // that still counts as accepting even though nothing may be sent.
let (sockets, handle) = (self.io.sockets.clone(), self.handle.get()); let (sockets, handle) = (self.io.sockets.clone(), self.handle.get());
self.io.until(move || { self.io.until(move || {
let mut sockets = borrow_mut!(sockets); let mut sockets = sockets.borrow_mut();
let socket: &mut TcpSocketLower = sockets.get_mut(handle).as_socket(); let socket = sockets.get::<TcpSocketLower>(handle);
socket.may_send() || socket.may_recv() socket.may_send() || socket.may_recv()
})?; })?;
@ -407,14 +346,14 @@ impl<'a> TcpListener<'a> {
} }
pub fn close(&self) { pub fn close(&self) {
self.as_lower().close() self.with_lower(|mut s| s.close())
} }
} }
impl<'a> Drop for TcpListener<'a> { impl<'a> Drop for TcpListener<'a> {
fn drop(&mut self) { fn drop(&mut self) {
self.as_lower().close(); self.with_lower(|mut s| s.close());
borrow_mut!(self.io.sockets).release(self.handle.get()) self.io.sockets.borrow_mut().release(self.handle.get())
} }
} }
@ -437,57 +376,59 @@ impl<'a> TcpStream<'a> {
} }
} }
fn as_lower<'b>(&'b self) -> RefMut<'b, TcpSocketLower> { fn with_lower<F, R>(&self, f: F) -> R
RefMut::map(borrow_mut!(self.io.sockets), where F: FnOnce(SocketRef<TcpSocketLower>) -> R {
|sockets| sockets.get_mut(self.handle).as_socket()) let mut sockets = self.io.sockets.borrow_mut();
let result = f(sockets.get(self.handle));
result
} }
pub fn is_open(&self) -> bool { pub fn is_open(&self) -> bool {
self.as_lower().is_open() self.with_lower(|s| s.is_open())
} }
pub fn may_send(&self) -> bool { pub fn may_send(&self) -> bool {
self.as_lower().may_send() self.with_lower(|s| s.may_send())
} }
pub fn may_recv(&self) -> bool { pub fn may_recv(&self) -> bool {
self.as_lower().may_recv() self.with_lower(|s| s.may_recv())
} }
pub fn can_send(&self) -> bool { pub fn can_send(&self) -> bool {
self.as_lower().can_send() self.with_lower(|s| s.can_send())
} }
pub fn can_recv(&self) -> bool { pub fn can_recv(&self) -> bool {
self.as_lower().can_recv() self.with_lower(|s| s.can_recv())
} }
pub fn local_endpoint(&self) -> IpEndpoint { pub fn local_endpoint(&self) -> IpEndpoint {
self.as_lower().local_endpoint() self.with_lower(|s| s.local_endpoint())
} }
pub fn remote_endpoint(&self) -> IpEndpoint { pub fn remote_endpoint(&self) -> IpEndpoint {
self.as_lower().remote_endpoint() self.with_lower(|s| s.remote_endpoint())
} }
pub fn timeout(&self) -> Option<u64> { pub fn timeout(&self) -> Option<u64> {
self.as_lower().timeout() self.with_lower(|s| s.timeout())
} }
pub fn set_timeout(&self, value: Option<u64>) { pub fn set_timeout(&self, value: Option<u64>) {
self.as_lower().set_timeout(value) self.with_lower(|mut s| s.set_timeout(value))
} }
pub fn keep_alive(&self) -> Option<u64> { pub fn keep_alive(&self) -> Option<u64> {
self.as_lower().keep_alive() self.with_lower(|s| s.keep_alive())
} }
pub fn set_keep_alive(&self, value: Option<u64>) { pub fn set_keep_alive(&self, value: Option<u64>) {
self.as_lower().set_keep_alive(value) self.with_lower(|mut s| s.set_keep_alive(value))
} }
pub fn close(&self) -> Result<()> { pub fn close(&self) -> Result<()> {
self.as_lower().close(); self.with_lower(|mut s| s.close());
until!(self, TcpSocketLower, |s| !s.is_open())?; until!(self, TcpSocketLower, |s| !s.is_open())?;
// right now the socket may be in TIME-WAIT state. if we don't give it a chance to send // right now the socket may be in TIME-WAIT state. if we don't give it a chance to send
// a packet, and the user code executes a loop { s.listen(); s.read(); s.close(); } // a packet, and the user code executes a loop { s.listen(); s.read(); s.close(); }
@ -499,12 +440,12 @@ impl<'a> TcpStream<'a> {
impl<'a> Read for TcpStream<'a> { impl<'a> Read for TcpStream<'a> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> { fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
// Only borrow the underlying socket for the span of the next statement. // Only borrow the underlying socket for the span of the next statement.
let result = self.as_lower().recv_slice(buf); let result = self.with_lower(|mut s| s.recv_slice(buf));
match result { match result {
// Slow path: we need to block until buffer is non-empty. // Slow path: we need to block until buffer is non-empty.
Ok(0) => { Ok(0) => {
until!(self, TcpSocketLower, |s| s.can_recv() || !s.may_recv())?; until!(self, TcpSocketLower, |s| s.can_recv() || !s.may_recv())?;
match self.as_lower().recv_slice(buf) { match self.with_lower(|mut s| s.recv_slice(buf)) {
Ok(length) => Ok(length), Ok(length) => Ok(length),
Err(ErrorLower::Illegal) => Ok(0), Err(ErrorLower::Illegal) => Ok(0),
_ => unreachable!() _ => unreachable!()
@ -523,12 +464,12 @@ impl<'a> Read for TcpStream<'a> {
impl<'a> Write for TcpStream<'a> { impl<'a> Write for TcpStream<'a> {
fn write(&mut self, buf: &[u8]) -> Result<usize> { fn write(&mut self, buf: &[u8]) -> Result<usize> {
// Only borrow the underlying socket for the span of the next statement. // Only borrow the underlying socket for the span of the next statement.
let result = self.as_lower().send_slice(buf); let result = self.with_lower(|mut s| s.send_slice(buf));
match result { match result {
// Slow path: we need to block until buffer is non-full. // Slow path: we need to block until buffer is non-full.
Ok(0) => { Ok(0) => {
until!(self, TcpSocketLower, |s| s.can_send() || !s.may_send())?; until!(self, TcpSocketLower, |s| s.can_send() || !s.may_send())?;
match self.as_lower().send_slice(buf) { match self.with_lower(|mut s| s.send_slice(buf)) {
Ok(length) => Ok(length), Ok(length) => Ok(length),
Err(ErrorLower::Illegal) => Ok(0), Err(ErrorLower::Illegal) => Ok(0),
_ => unreachable!() _ => unreachable!()
@ -545,7 +486,7 @@ impl<'a> Write for TcpStream<'a> {
fn flush(&mut self) -> Result<()> { fn flush(&mut self) -> Result<()> {
until!(self, TcpSocketLower, |s| s.send_queue() == 0 || !s.may_send())?; until!(self, TcpSocketLower, |s| s.send_queue() == 0 || !s.may_send())?;
if self.as_lower().send_queue() == 0 { if self.with_lower(|s| s.send_queue()) == 0 {
Ok(()) Ok(())
} else { } else {
Err(Error::new(ErrorKind::ConnectionAborted, "connection aborted")) Err(Error::new(ErrorKind::ConnectionAborted, "connection aborted"))
@ -555,7 +496,7 @@ impl<'a> Write for TcpStream<'a> {
impl<'a> Drop for TcpStream<'a> { impl<'a> Drop for TcpStream<'a> {
fn drop(&mut self) { fn drop(&mut self) {
self.as_lower().close(); self.with_lower(|mut s| s.close());
borrow_mut!(self.io.sockets).release(self.handle) self.io.sockets.borrow_mut().release(self.handle)
} }
} }

View File

@ -3,14 +3,14 @@ use std::{mem, str};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::error::Error; use std::error::Error;
use {config, rtio_mgt, mailbox, rpc_queue, kernel}; use {rtio_mgt, mailbox, rpc_queue, kernel};
use cache::Cache; use cache::Cache;
use rtio_dma::Manager as DmaManager; use rtio_dma::Manager as DmaManager;
use urc::Urc; use urc::Urc;
use sched::{ThreadHandle, Io}; use sched::{ThreadHandle, Io};
use sched::{TcpListener, TcpStream}; use sched::{TcpListener, TcpStream};
use byteorder::{ByteOrder, NetworkEndian}; use byteorder::{ByteOrder, NetworkEndian};
use board; use board::{self, config};
use rpc_proto as rpc; use rpc_proto as rpc;
use session_proto as host; use session_proto as host;
@ -615,7 +615,7 @@ pub fn thread(io: Io) {
{ {
let congress = congress.clone(); let congress = congress.clone();
respawn(&io, &mut kernel_thread, move |io| { respawn(&io, &mut kernel_thread, move |io| {
let mut congress = borrow_mut!(congress); let mut congress = congress.borrow_mut();
info!("running startup kernel"); info!("running startup kernel");
match flash_kernel_worker(&io, &mut congress, "startup_kernel") { match flash_kernel_worker(&io, &mut congress, "startup_kernel") {
Ok(()) => info!("startup kernel finished"), Ok(()) => info!("startup kernel finished"),
@ -650,7 +650,7 @@ pub fn thread(io: Io) {
let congress = congress.clone(); let congress = congress.clone();
let stream = stream.into_handle(); let stream = stream.into_handle();
respawn(&io, &mut kernel_thread, move |io| { respawn(&io, &mut kernel_thread, move |io| {
let mut congress = borrow_mut!(congress); let mut congress = congress.borrow_mut();
let mut stream = TcpStream::from_handle(&io, stream); let mut stream = TcpStream::from_handle(&io, stream);
match host_kernel_worker(&io, &mut stream, &mut *congress) { match host_kernel_worker(&io, &mut stream, &mut *congress) {
Ok(()) => (), Ok(()) => (),
@ -673,7 +673,7 @@ pub fn thread(io: Io) {
let congress = congress.clone(); let congress = congress.clone();
respawn(&io, &mut kernel_thread, move |io| { respawn(&io, &mut kernel_thread, move |io| {
let mut congress = borrow_mut!(congress); let mut congress = congress.borrow_mut();
match flash_kernel_worker(&io, &mut *congress, "idle_kernel") { match flash_kernel_worker(&io, &mut *congress, "idle_kernel") {
Ok(()) => Ok(()) =>
info!("idle kernel finished, standing by"), info!("idle kernel finished, standing by"),

View File

@ -5,25 +5,17 @@ LDFLAGS += -L../libbase
RUSTFLAGS += -Cpanic=abort RUSTFLAGS += -Cpanic=abort
all: satman.bin satman.fbi all:: satman.bin satman.fbi
.PHONY: $(RUSTOUT)/libsatman.a .PHONY: $(RUSTOUT)/libsatman.a
$(RUSTOUT)/libsatman.a: $(RUSTOUT)/libsatman.a:
$(cargo) --manifest-path $(SATMAN_DIRECTORY)/Cargo.toml $(cargo) --manifest-path $(SATMAN_DIRECTORY)/Cargo.toml
satman.elf: $(RUSTOUT)/libsatman.a satman.elf: $(RUSTOUT)/libsatman.a
$(LD) $(LDFLAGS) -T $(SATMAN_DIRECTORY)/satman.ld -o $@ $^ $(link) -T $(SATMAN_DIRECTORY)/satman.ld
@chmod -x $@
%.bin: %.elf %.bin: %.elf
$(OBJCOPY) -O binary $< $@ $(objcopy) -O binary
@chmod -x $@
%.fbi: %.bin %.fbi: %.bin
@echo " MSCIMG " $@ && $(PYTHON) -m misoc.tools.mkmscimg -f -o $@ $< $(mscimg) -f
clean:
$(RM) satman.elf satman.bin satman.fbi
$(RM) -rf cargo
.PHONY: all clean

View File

@ -51,6 +51,10 @@ Prerequisites:
help="target adapter, default: %(default)s") help="target adapter, default: %(default)s")
parser.add_argument("--target-file", default=None, parser.add_argument("--target-file", default=None,
help="use alternative OpenOCD target file") help="use alternative OpenOCD target file")
parser.add_argument("-I", "--preinit-command", default=[], action="append",
help="add a pre-initialization OpenOCD command. "
"Useful for selecting a development board "
"when several are connected.")
parser.add_argument("-f", "--storage", help="write file to storage area") parser.add_argument("-f", "--storage", help="write file to storage area")
parser.add_argument("-d", "--dir", help="look for files in this directory") parser.add_argument("-d", "--dir", help="look for files in this directory")
parser.add_argument("action", metavar="ACTION", nargs="*", parser.add_argument("action", metavar="ACTION", nargs="*",
@ -69,8 +73,8 @@ def main():
"start": "xc7_program xc7.tap", "start": "xc7_program xc7.tap",
"gateware": 0x000000, "gateware": 0x000000,
"bios": 0xaf0000, "bios": 0xaf0000,
"runtime": 0xb00000, "storage": 0xb30000,
"storage": 0xb80000, "runtime": 0xb40000,
}, },
}[opts.target] }[opts.target]
@ -84,6 +88,7 @@ def main():
conv = False conv = False
prog = [] prog = []
prog.extend(opts.preinit_command)
prog.append("init") prog.append("init")
for action in opts.action: for action in opts.action:
if action == "proxy": if action == "proxy":

View File

@ -94,26 +94,26 @@ class DBWriter(TaskObject):
"too many pending updates", k) "too many pending updates", k)
async def _do(self): async def _do(self):
while True: async with aiohttp.ClientSession() as session:
k, v, t = await self._queue.get() while True:
url = self.base_url + "/write" k, v, t = await self._queue.get()
params = {"u": self.user, "p": self.password, "db": self.database, url = self.base_url + "/write"
"precision": "ms"} params = {"u": self.user, "p": self.password, "db": self.database,
data = "{},dataset={} {} {}".format( "precision": "ms"}
self.table, k, format_influxdb(v), round(t*1e3)) data = "{},dataset={} {} {}".format(
try: self.table, k, format_influxdb(v), round(t*1e3))
response = await aiohttp.request( try:
"POST", url, params=params, data=data) response = await session.post(url, params=params, data=data)
except: except:
logger.warning("got exception trying to update '%s'", logger.warning("got exception trying to update '%s'",
k, exc_info=True) k, exc_info=True)
else: else:
if response.status not in (200, 204): if response.status not in (200, 204):
content = (await response.content.read()).decode().strip() content = (await response.content.read()).decode().strip()
logger.warning("got HTTP status %d " logger.warning("got HTTP status %d "
"trying to update '%s': %s", "trying to update '%s': %s",
response.status, k, content) response.status, k, content)
response.close() response.close()
class _Mock: class _Mock:

View File

@ -4,8 +4,8 @@
# * tcpdump has CAP_NET_RAW capabilities set # * tcpdump has CAP_NET_RAW capabilities set
# use # setcap cap_net_raw+eip /usr/sbin/tcpdump # use # setcap cap_net_raw+eip /usr/sbin/tcpdump
import argparse
import os import os
import argparse
import subprocess import subprocess
from artiq.tools import verbosity_args, init_logger, logger, SSHClient from artiq.tools import verbosity_args, init_logger, logger, SSHClient
@ -49,7 +49,6 @@ def main():
subprocess.check_call(args.command) subprocess.check_call(args.command)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
logger.error("Command failed") logger.error("Command failed")
sys.exit(1)
tcpdump.close() tcpdump.close()
sftp.get("{tmp}/trace.pcap".format(tmp=client.tmp), sftp.get("{tmp}/trace.pcap".format(tmp=client.tmp),

View File

@ -208,9 +208,11 @@ class SPIMaster(Module):
clk_t = TSTriple() clk_t = TSTriple()
self.specials += clk_t.get_tristate(pads.clk) self.specials += clk_t.get_tristate(pads.clk)
self.comb += [ self.comb += clk_t.oe.eq(~config.offline),
clk_t.oe.eq(~config.offline), self.sync += [
clk_t.o.eq((spi.cg.clk & spi.cs) ^ config.clk_polarity), If(spi.cg.ce & spi.cg.edge,
clk_t.o.eq((~spi.cg.clk & spi.cs_next) ^ config.clk_polarity)
)
] ]
mosi_t = TSTriple() mosi_t = TSTriple()

View File

@ -157,7 +157,6 @@ class Phaser(MiniSoC, AMPSoC):
"rtio": 0x20000000, "rtio": 0x20000000,
"rtio_dma": 0x30000000, "rtio_dma": 0x30000000,
"mailbox": 0x70000000, "mailbox": 0x70000000,
"ad9154": 0x50000000,
} }
mem_map.update(MiniSoC.mem_map) mem_map.update(MiniSoC.mem_map)

View File

@ -12,17 +12,17 @@
version="1.1" version="1.1"
x="0px" x="0px"
y="0px" y="0px"
width="360.147" width="323.49704"
height="432.04401" height="432.04401"
viewBox="0 0 360.147 432.04401" viewBox="0 0 323.49704 432.04401"
enable-background="new 0 0 800 800" enable-background="new 0 0 800 800"
xml:space="preserve" xml:space="preserve"
id="svg2" id="svg2"
inkscape:version="0.91 r13725" inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="logo_ver.svg"><metadata sodipodi:docname="logo_ver.svg"><metadata
id="metadata548"><rdf:RDF><cc:Work id="metadata548"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs546" /><sodipodi:namedview id="defs546" /><sodipodi:namedview
pagecolor="#ffffff" pagecolor="#ffffff"
bordercolor="#666666" bordercolor="#666666"
@ -33,7 +33,7 @@
inkscape:pageopacity="0" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1156" inkscape:window-height="1124"
id="namedview544" id="namedview544"
showgrid="false" showgrid="false"
fit-margin-top="0" fit-margin-top="0"
@ -41,12 +41,12 @@
fit-margin-right="0" fit-margin-right="0"
fit-margin-bottom="0" fit-margin-bottom="0"
inkscape:zoom="0.834386" inkscape:zoom="0.834386"
inkscape:cx="-244.98179" inkscape:cx="-466.10247"
inkscape:cy="163.75581" inkscape:cy="163.7558"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="44" inkscape:window-y="0"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="svg2" /><path inkscape:current-layer="text3371" /><path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path381" id="path381"
@ -54,7 +54,7 @@
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path383" id="path383"
d="m 53.761,135.723 10.609,9.812 c 0.215,-0.162 0.461,-0.348 0.689,-0.549 20.543,-18.001 43.98,-33.619 69.662,-46.423 32.912,-16.404 60.969,-25.002 88.295,-27.058 2.504,-0.188 4.811,-0.279 7.051,-0.279 9.105,0 16.873,1.591 23.744,4.864 7.635,3.636 11.473,9.741 11.404,18.146 -0.053,6.609 -1.955,13.229 -5.812,20.239 -2.68,4.868 -5.713,9.68 -8.646,14.332 -1.248,1.979 -2.502,3.969 -3.744,5.982 l 10.135,9.65 c 8.092,-10.235 16.82,-22.731 20.846,-38.001 0.467,-1.765 0.861,-3.586 1.244,-5.348 0.174,-0.804 0.348,-1.606 0.529,-2.408 l 0,-8.887 c -0.049,-0.148 -0.102,-0.297 -0.154,-0.444 -0.141,-0.387 -0.285,-0.787 -0.357,-1.216 -2.037,-12.213 -8.967,-20.778 -21.184,-26.186 -7.824,-3.462 -16.289,-4.355 -23.535,-4.772 -2.264,-0.13 -4.576,-0.196 -6.877,-0.196 -11.945,0 -24.328,1.727 -37.859,5.278 -46.736,12.272 -90.896,35.554 -131.252,69.197 -1.098,0.917 -2.182,1.903 -3.332,2.947 -0.465,0.425 -0.948,0.863 -1.456,1.32 z" /><path d="m 53.761,135.723 10.609,9.812 c 0.215,-0.162 0.461,-0.348 0.689,-0.549 20.543,-18.001 43.98,-33.619 69.662,-46.423 32.912,-16.404 60.969,-25.002 88.295,-27.058 2.504,-0.188 4.811,-0.279 7.051,-0.279 9.105,0 16.873,1.591 23.744,4.864 7.635,3.636 11.473,9.741 11.404,18.146 -0.053,6.609 -1.955,13.229 -5.812,20.239 -2.68,4.868 -5.713,9.68 -8.646,14.332 -1.248,1.979 -2.502,3.969 -3.744,5.982 l 10.135,9.65 c 8.092,-10.235 16.82,-22.731 20.846,-38.001 0.467,-1.765 0.861,-3.586 1.244,-5.348 0.174,-0.804 0.348,-1.606 0.529,-2.408 v -8.887 c -0.049,-0.148 -0.102,-0.297 -0.154,-0.444 -0.141,-0.387 -0.285,-0.787 -0.357,-1.216 -2.037,-12.213 -8.967,-20.778 -21.184,-26.186 -7.824,-3.462 -16.289,-4.355 -23.535,-4.772 -2.264,-0.13 -4.576,-0.196 -6.877,-0.196 -11.945,0 -24.328,1.727 -37.859,5.278 -46.736,12.272 -90.896,35.554 -131.252,69.197 -1.098,0.917 -2.182,1.903 -3.332,2.947 -0.465,0.425 -0.948,0.863 -1.456,1.32 z" /><path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path385" id="path385"
@ -82,11 +82,11 @@
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path397" id="path397"
d="m 180.738,111.632 c -0.625,-4.189 -1.227,-8.218 -1.867,-12.238 -0.326,-2.036 -5.861,-6.224 -8.229,-6.224 -0.156,0 -0.291,0.02 -0.402,0.058 -4.172,1.46 -8.242,3.096 -12.551,4.827 -1.42,0.57 -2.855,1.146 -4.316,1.727 l 28,16.088 -0.635,-4.238 z" /><path d="m 180.738,111.632 c -0.625,-4.189 -1.227,-8.218 -1.867,-12.238 -0.326,-2.036 -5.861,-6.224 -8.229,-6.224 -0.156,0 -0.291,0.02 -0.402,0.058 -4.172,1.46 -8.242,3.096 -12.551,4.827 -1.42,0.57 -2.855,1.146 -4.316,1.727 l 28,16.088 z" /><path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path399" id="path399"
d="m 90.154,136.545 c -0.338,0.264 -0.668,0.525 -1,0.788 -0.463,0.366 -0.936,0.736 -1.393,1.099 -2.838,2.248 -5.516,4.371 -8.346,6.353 -2.75,1.927 -3.779,4.095 -3.336,7.03 0.102,0.675 0.096,1.436 0.09,2.17 -0.01,1.219 -0.02,2.479 0.488,2.946 3.336,3.059 6.891,5.851 10.654,8.807 0.605,0.477 1.227,0.968 1.842,1.452 0.334,0.264 0.664,0.523 1,0.789 0.188,0.148 0.369,0.29 0.557,0.439 l 0,-32.312 c -0.189,0.148 -0.369,0.291 -0.556,0.439 z" /><path d="m 90.154,136.545 c -0.338,0.264 -0.668,0.525 -1,0.788 -0.463,0.366 -0.936,0.736 -1.393,1.099 -2.838,2.248 -5.516,4.371 -8.346,6.353 -2.75,1.927 -3.779,4.095 -3.336,7.03 0.102,0.675 0.096,1.436 0.09,2.17 -0.01,1.219 -0.02,2.479 0.488,2.946 3.336,3.059 6.891,5.851 10.654,8.807 0.605,0.477 1.227,0.968 1.842,1.452 0.334,0.264 0.664,0.523 1,0.789 0.188,0.148 0.369,0.29 0.557,0.439 v -32.312 c -0.189,0.148 -0.369,0.291 -0.556,0.439 z" /><path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path401" id="path401"
@ -98,7 +98,7 @@
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path405" id="path405"
d="M 231.324,171.353 221.01,161.63 c -0.9,2.513 -2.059,14.3 -1.457,19.737 l 11.771,-10.014 z" /><path d="M 231.324,171.353 221.01,161.63 c -0.9,2.513 -2.059,14.3 -1.457,19.737 z" /><path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path407" id="path407"
@ -117,25 +117,25 @@
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path415" id="path415"
d="m 366.13,593.558 c 7.498,-5.083 10.756,-15.119 7.922,-24.407 -2.773,-9.089 -10.521,-14.536 -20.727,-14.573 l -26.715,0 0,61.202 14.156,0 0,-18.602 9.979,0 10.836,18.602 16.479,0 0,-1.06 -12.725,-20.623 0.795,-0.539 z m -12.801,-8.731 -12.562,0 0,-17.809 1.004,0 c 1.254,0 2.529,-0.01 3.811,-0.02 2.6,-0.021 5.225,-0.041 7.771,0.02 5.328,0.052 7.74,4.621 7.719,8.845 -0.022,4.454 -2.688,8.964 -7.743,8.964 z" /><polygon d="m 366.13,593.558 c 7.498,-5.083 10.756,-15.119 7.922,-24.407 -2.773,-9.089 -10.521,-14.536 -20.727,-14.573 H 326.61 v 61.202 h 14.156 v -18.602 h 9.979 l 10.836,18.602 h 16.479 v -1.06 l -12.725,-20.623 z m -12.801,-8.731 h -12.562 v -17.809 h 1.004 c 1.254,0 2.529,-0.01 3.811,-0.02 2.6,-0.021 5.225,-0.041 7.771,0.02 5.328,0.052 7.74,4.621 7.719,8.845 -0.022,4.454 -2.688,8.964 -7.743,8.964 z" /><polygon
style="fill:#ffffff" style="fill:#ffffff"
id="polygon417" id="polygon417"
points="432.151,554.577 387.202,554.577 387.202,567.019 402.733,567.019 402.733,615.779 416.71,615.779 416.71,567.019 432.151,567.019 " /><polygon points="387.202,567.019 402.733,567.019 402.733,615.779 416.71,615.779 416.71,567.019 432.151,567.019 432.151,554.577 387.202,554.577 " /><polygon
style="fill:#ffffff" style="fill:#ffffff"
id="polygon419" id="polygon419"
points="464.571,566.657 471.976,566.657 471.976,554.577 443.19,554.577 443.19,566.657 450.595,566.657 450.595,603.608 442.558,603.608 442.558,615.779 472.606,615.779 472.606,603.608 464.571,603.608 " /><path points="471.976,554.577 443.19,554.577 443.19,566.657 450.595,566.657 450.595,603.608 442.558,603.608 442.558,615.779 472.606,615.779 472.606,603.608 464.571,603.608 464.571,566.657 471.976,566.657 " /><path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path421" id="path421"
d="m 542.927,603.421 c 3.252,-5.109 4.9,-11.218 4.9,-18.153 0,-21.831 -16.283,-31.774 -31.414,-31.774 -15.129,0 -31.414,9.943 -31.414,31.774 0,21.683 16.174,31.56 31.199,31.56 5.541,0 10.949,-1.321 15.637,-3.82 l 0.885,-0.472 1.725,3.244 14.828,0 0,-0.794 -6.68,-11.039 0.334,-0.526 z m -26.514,0.053 c -8.094,0 -16.805,-5.697 -16.805,-18.206 0,-12.415 8.711,-18.069 16.805,-18.069 8.094,0 16.807,5.654 16.807,18.069 0,12.508 -8.713,18.206 -16.807,18.206 z" /></g><path d="m 542.927,603.421 c 3.252,-5.109 4.9,-11.218 4.9,-18.153 0,-21.831 -16.283,-31.774 -31.414,-31.774 -15.129,0 -31.414,9.943 -31.414,31.774 0,21.683 16.174,31.56 31.199,31.56 5.541,0 10.949,-1.321 15.637,-3.82 l 0.885,-0.472 1.725,3.244 h 14.828 v -0.794 l -6.68,-11.039 z m -26.514,0.053 c -8.094,0 -16.805,-5.697 -16.805,-18.206 0,-12.415 8.711,-18.069 16.805,-18.069 8.094,0 16.807,5.654 16.807,18.069 0,12.508 -8.713,18.206 -16.807,18.206 z" /></g><path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path431" id="path431"
d="m 165.162,221.756 0.006,-0.025 C 140.75,212.522 116.912,200.02 94.189,184.475 69.636,167.678 51.56,151.283 37.304,132.879 28.589,121.632 23.536,112.162 20.923,102.174 c -3.068,-11.729 0.105,-20.54 9.178,-25.482 2.277,-1.241 4.834,-2.269 7.596,-3.054 7.576,-2.153 15.721,-2.812 25.201,-2.015 1.244,0.104 2.52,0.217 3.805,0.332 1.402,0.123 2.803,0.242 4.209,0.368 l 3.176,0.281 3.846,-13.919 c -0.947,-0.121 -1.893,-0.245 -2.83,-0.37 -2.537,-0.337 -4.934,-0.656 -7.25,-0.857 -4.689,-0.406 -8.803,-0.604 -12.578,-0.604 -8.74,0 -16.342,1.076 -23.24,3.29 -14.58,4.68 -23.049,13.281 -25.893,26.297 -1.943,8.9 -0.568,18.38 4.328,29.833 6.098,14.267 15.623,27.692 29.977,42.251 31.707,32.162 69.879,56.911 116.699,75.662 3.182,1.274 6.383,2.416 9.771,3.624 1.434,0.511 2.889,1.029 4.369,1.568 l 2.396,-8.365 -8.521,-9.258 z" /><path d="m 165.162,221.756 0.006,-0.025 C 140.75,212.522 116.912,200.02 94.189,184.475 69.636,167.678 51.56,151.283 37.304,132.879 28.589,121.632 23.536,112.162 20.923,102.174 c -3.068,-11.729 0.105,-20.54 9.178,-25.482 2.277,-1.241 4.834,-2.269 7.596,-3.054 7.576,-2.153 15.721,-2.812 25.201,-2.015 1.244,0.104 2.52,0.217 3.805,0.332 1.402,0.123 2.803,0.242 4.209,0.368 l 3.176,0.281 3.846,-13.919 c -0.947,-0.121 -1.893,-0.245 -2.83,-0.37 -2.537,-0.337 -4.934,-0.656 -7.25,-0.857 -4.689,-0.406 -8.803,-0.604 -12.578,-0.604 -8.74,0 -16.342,1.076 -23.24,3.29 -14.58,4.68 -23.049,13.281 -25.893,26.297 -1.943,8.9 -0.568,18.38 4.328,29.833 6.098,14.267 15.623,27.692 29.977,42.251 31.707,32.162 69.879,56.911 116.699,75.662 3.182,1.274 6.383,2.416 9.771,3.624 1.434,0.511 2.889,1.029 4.369,1.568 l 2.396,-8.365 z" /><path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path433" id="path433"
d="m 279.656,208.102 c -0.146,-0.262 -0.314,-0.56 -0.359,-0.905 -0.99,-8.005 -3.834,-16.142 -8.688,-24.875 -7.945,-14.297 -18.83,-27.683 -34.252,-42.126 -3.812,-3.572 -7.723,-6.949 -11.863,-10.523 -1.678,-1.448 -3.377,-2.915 -5.096,-4.419 -0.006,0.032 -0.012,0.062 -0.018,0.092 -0.062,0.355 -0.096,0.551 -0.09,0.713 l 0.148,3.794 c 0.176,4.559 0.359,9.272 0.67,13.896 0.047,0.706 0.615,1.672 1.52,2.583 2.135,2.144 4.346,4.286 6.484,6.358 3.807,3.687 7.742,7.5 11.389,11.467 11.611,12.634 19.076,24.245 23.488,36.543 2.049,5.705 2.707,10.802 2.012,15.581 -1.146,7.896 -6.145,13.235 -15.281,16.322 -2.455,0.829 -5.002,1.474 -7.656,1.956 l 9.738,12.6 c 1.551,-0.468 3.08,-0.975 4.574,-1.562 12.387,-4.858 19.754,-12.956 22.521,-24.758 l 0.869,-3.686 0,-8.847 c -0.034,-0.068 -0.071,-0.136 -0.11,-0.204 z" /><g d="m 279.656,208.102 c -0.146,-0.262 -0.314,-0.56 -0.359,-0.905 -0.99,-8.005 -3.834,-16.142 -8.688,-24.875 -7.945,-14.297 -18.83,-27.683 -34.252,-42.126 -3.812,-3.572 -7.723,-6.949 -11.863,-10.523 -1.678,-1.448 -3.377,-2.915 -5.096,-4.419 -0.006,0.032 -0.012,0.062 -0.018,0.092 -0.062,0.355 -0.096,0.551 -0.09,0.713 l 0.148,3.794 c 0.176,4.559 0.359,9.272 0.67,13.896 0.047,0.706 0.615,1.672 1.52,2.583 2.135,2.144 4.346,4.286 6.484,6.358 3.807,3.687 7.742,7.5 11.389,11.467 11.611,12.634 19.076,24.245 23.488,36.543 2.049,5.705 2.707,10.802 2.012,15.581 -1.146,7.896 -6.145,13.235 -15.281,16.322 -2.455,0.829 -5.002,1.474 -7.656,1.956 l 9.738,12.6 c 1.551,-0.468 3.08,-0.975 4.574,-1.562 12.387,-4.858 19.754,-12.956 22.521,-24.758 l 0.869,-3.686 v -8.847 c -0.034,-0.068 -0.071,-0.136 -0.11,-0.204 z" /><g
style="fill:#ffffff" style="fill:#ffffff"
id="g435" id="g435"
transform="translate(-250.847,-184.784)"><path transform="translate(-250.847,-184.784)"><path
@ -146,19 +146,14 @@
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path439" id="path439"
d="m 433.437,425.474 c -2.322,7.348 -4.98,14.184 -8.043,20.678 -3.967,8.416 -9.191,17.993 -17.877,25.219 -9.297,7.733 -19.082,7.701 -28.365,-0.092 -5.934,-4.982 -10.92,-11.633 -15.691,-20.929 -6.629,-12.926 -11.459,-27.311 -15.66,-46.642 l -0.072,-0.342 c -0.174,-0.828 -0.412,-1.962 -0.893,-2.284 -4.152,-2.786 -8.357,-5.448 -12.807,-8.267 -1.068,-0.677 -2.146,-1.359 -3.238,-2.054 0.164,0.969 0.32,1.911 0.475,2.834 0.434,2.596 0.842,5.047 1.303,7.478 4.703,24.702 10.705,42.76 19.463,58.551 7.541,13.604 17.859,28.05 37.209,32.08 l 8.318,0 c 17.949,-3.632 27.887,-16.568 35.24,-28.748 1.953,-3.234 3.717,-6.507 5.244,-9.726 2.389,-5.035 4.557,-10.249 6.533,-15.655 l -11.139,-12.101 z" /></g><path d="m 433.437,425.474 c -2.322,7.348 -4.98,14.184 -8.043,20.678 -3.967,8.416 -9.191,17.993 -17.877,25.219 -9.297,7.733 -19.082,7.701 -28.365,-0.092 -5.934,-4.982 -10.92,-11.633 -15.691,-20.929 -6.629,-12.926 -11.459,-27.311 -15.66,-46.642 l -0.072,-0.342 c -0.174,-0.828 -0.412,-1.962 -0.893,-2.284 -4.152,-2.786 -8.357,-5.448 -12.807,-8.267 -1.068,-0.677 -2.146,-1.359 -3.238,-2.054 0.164,0.969 0.32,1.911 0.475,2.834 0.434,2.596 0.842,5.047 1.303,7.478 4.703,24.702 10.705,42.76 19.463,58.551 7.541,13.604 17.859,28.05 37.209,32.08 h 8.318 c 17.949,-3.632 27.887,-16.568 35.24,-28.748 1.953,-3.234 3.717,-6.507 5.244,-9.726 2.389,-5.035 4.557,-10.249 6.533,-15.655 z" /></g><path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:#ffffff" style="fill:#ffffff"
id="path493" id="path493"
d="M 28.084,368.98 0,429.872 l 0,1.124 14.16,0 4.202,-8.945 25.208,0 4.195,8.945 14.16,0 0,-1.124 -28.172,-60.892 -5.669,0 z m -5.438,41.259 8.215,-19.134 8.424,19.134 -16.639,0 z" /><g d="M 28.084,368.98 0,429.872 v 1.124 h 14.16 l 4.202,-8.945 H 43.57 l 4.195,8.945 h 14.16 v -1.124 L 33.753,368.98 Z m -5.438,41.259 8.215,-19.134 8.424,19.134 z" /><g
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:expanded;font-size:45px;line-height:125%;font-family:'Novecento sans wide';-inkscape-font-specification:'Novecento sans wide, Semi-Bold Expanded';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:expanded;font-size:45px;line-height:125%;font-family:'Novecento sans wide';-inkscape-font-specification:'Novecento sans wide, Semi-Bold Expanded';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text3371"><path id="text3371"><path
d="m 318.27705,360.24104 c 2.295,-0.315 4.95,-2.115 4.95,-5.895 0,-3.96 -2.88,-6.57 -8.775,-6.57 -4.635,0 -8.685,1.62 -9.675,6.57 l 4.275,1.17 c 0.27,-1.98 1.395,-3.87 4.95,-3.87 2.925,0 4.635,1.305 4.635,3.51 0,2.295 -1.755,3.555 -4.77,3.555 l -2.475,0 0,3.42 2.655,0 c 2.925,0 4.86,1.215 4.86,3.69 0,2.295 -1.62,4.095 -4.86,4.095 -3.06,0 -5.04,-1.53 -5.625,-4.275 l -4.14,1.17 c 0.9,4.59 4.68,7.155 9.9,7.155 5.715,0 9.315,-3.015 9.315,-7.515 0,-3.69 -2.385,-5.76 -5.22,-6.03 l 0,-0.18 z" d="m 318.27705,360.24104 c 2.295,-0.315 4.95,-2.115 4.95,-5.895 0,-3.96 -2.88,-6.57 -8.775,-6.57 -4.635,0 -8.685,1.62 -9.675,6.57 l 4.275,1.17 c 0.27,-1.98 1.395,-3.87 4.95,-3.87 2.925,0 4.635,1.305 4.635,3.51 0,2.295 -1.755,3.555 -4.77,3.555 h -2.475 v 3.42 h 2.655 c 2.925,0 4.86,1.215 4.86,3.69 0,2.295 -1.62,4.095 -4.86,4.095 -3.06,0 -5.04,-1.53 -5.625,-4.275 l -4.14,1.17 c 0.9,4.59 4.68,7.155 9.9,7.155 5.715,0 9.315,-3.015 9.315,-7.515 0,-3.69 -2.385,-5.76 -5.22,-6.03 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:expanded;font-size:45px;line-height:125%;font-family:'Novecento sans wide';-inkscape-font-specification:'Novecento sans wide, Semi-Bold Expanded';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff" style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:expanded;font-size:45px;line-height:125%;font-family:'Novecento sans wide';-inkscape-font-specification:'Novecento sans wide, Semi-Bold Expanded';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff"
id="path3376" /><path id="path3376"
d="m 330.56416,373.87604 c 1.89,0 2.88,-1.17 2.88,-2.7 0,-1.485 -0.99,-2.655 -2.88,-2.655 -1.89,0 -2.925,1.17 -2.925,2.655 0,1.485 0.99,2.7 2.925,2.7 z" inkscape:connector-curvature="0" /></g></svg>
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:expanded;font-size:45px;line-height:125%;font-family:'Novecento sans wide';-inkscape-font-specification:'Novecento sans wide, Semi-Bold Expanded';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff"
id="path3378" /><path
d="m 346.79791,347.77604 c -6.39,0 -10.26,4.455 -10.26,13.095 0,8.64 3.87,13.095 10.26,13.095 6.345,0 10.215,-4.455 10.215,-13.095 0,-8.64 -3.87,-13.095 -10.215,-13.095 z m 0,4.32 c 3.78,0 5.49,2.79 5.49,8.775 0,5.94 -1.71,8.775 -5.49,8.775 -3.825,0 -5.535,-2.835 -5.535,-8.775 0,-5.985 1.71,-8.775 5.535,-8.775 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:expanded;font-size:45px;line-height:125%;font-family:'Novecento sans wide';-inkscape-font-specification:'Novecento sans wide, Semi-Bold Expanded';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff"
id="path3380" /></g></svg>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -223,7 +223,7 @@ class ScanWidget(QtWidgets.QWidget):
self._zoom(self.zoomFactor**y, ev.x()) self._zoom(self.zoomFactor**y, ev.x())
def resizeEvent(self, ev): def resizeEvent(self, ev):
if not ev.oldSize().isValid(): if not ev.oldSize().isValid() or not ev.oldSize().width():
self.viewRange() self.viewRange()
return return
self.ticker.min_ticks = max( self.ticker.min_ticks = max(

View File

@ -74,4 +74,4 @@ class AnalyzerTest(ExperimentCase):
log = "".join([_extract_log_chars(msg.data) log = "".join([_extract_log_chars(msg.data)
for msg in dump.messages for msg in dump.messages
if isinstance(msg, OutputMessage) and msg.channel == dump.log_channel]) if isinstance(msg, OutputMessage) and msg.channel == dump.log_channel])
self.assertEqual(log, "foo\x1E32\n\x1D") self.assertEqual(log, "foo\x1E32\x1D")

View File

@ -0,0 +1,54 @@
import os
import unittest
from artiq.experiment import *
from artiq.test.hardware_testbench import ExperimentCase
artiq_low_latency = os.getenv("ARTIQ_LOW_LATENCY")
class _Transfer(EnvExperiment):
def build(self):
self.setattr_device("core")
self.data = b"\x00"*(10**6)
@rpc
def source(self) -> TBytes:
return self.data
@rpc(flags={"async"})
def sink(self, data):
assert data == self.data
@kernel
def host_to_device(self):
t0 = self.core.get_rtio_counter_mu()
data = self.source()
t1 = self.core.get_rtio_counter_mu()
return len(data)/self.core.mu_to_seconds(t1-t0)
@kernel
def device_to_host(self):
t0 = self.core.get_rtio_counter_mu()
self.sink(self.data)
t1 = self.core.get_rtio_counter_mu()
return len(self.data)/self.core.mu_to_seconds(t1-t0)
class TransferTest(ExperimentCase):
@unittest.skipUnless(artiq_low_latency,
"timings are dependent on CPU load and network conditions")
def test_host_to_device(self):
exp = self.create(_Transfer)
host_to_device_rate = exp.host_to_device()
print(host_to_device_rate, "B/s")
self.assertGreater(host_to_device_rate, 2e6)
@unittest.skipUnless(artiq_low_latency,
"timings are dependent on CPU load and network conditions")
def test_device_to_host(self):
exp = self.create(_Transfer)
device_to_host_rate = exp.device_to_host()
print(device_to_host_rate, "B/s")
self.assertGreater(device_to_host_rate, 2e6)

View File

@ -0,0 +1,12 @@
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
# RUN: OutputCheck %s --file-to-check=%t
from artiq.experiment import *
@kernel
def entrypoint():
a = [1,2]
# CHECK-L: ${LINE:+2}: error: values cannot be mutated in-place
# CHECK-L: ${LINE:+1}: note: try using `a = a + [3,4]`
a += [3,4]

View File

@ -9,3 +9,6 @@ list(1)
# CHECK-L: ${LINE:+1}: error: the arguments of min() must be of a numeric type # CHECK-L: ${LINE:+1}: error: the arguments of min() must be of a numeric type
min([1], [1]) min([1], [1])
# CHECK-L: ${LINE:+1}: error: strings currently cannot be constructed
str(1)

View File

@ -1,5 +1,5 @@
# RUN: %python -m artiq.compiler.testbench.jit %s
# RUN: %python %s # RUN: %python %s
# RUN: %python -m artiq.compiler.testbench.jit %s
# REQUIRES: exceptions # REQUIRES: exceptions
assert -(-1) == 1 assert -(-1) == 1
@ -20,6 +20,12 @@ assert 3 % 2 == 1
assert -3 % 2 == 1 assert -3 % 2 == 1
assert 3 % -2 == -1 assert 3 % -2 == -1
assert -3 % -2 == -1 assert -3 % -2 == -1
assert -1 % 8 == 7
#ARTIQ#assert int64(3) % 2 == 1
#ARTIQ#assert int64(-3) % 2 == 1
#ARTIQ#assert int64(3) % -2 == -1
#ARTIQ#assert int64(-3) % -2 == -1
assert -1 % 8 == 7
assert 3.0 % 2.0 == 1.0 assert 3.0 % 2.0 == 1.0
assert -3.0 % 2.0 == 1.0 assert -3.0 % 2.0 == 1.0
assert 3.0 % -2.0 == -1.0 assert 3.0 % -2.0 == -1.0
@ -35,6 +41,24 @@ assert -1 >> 32 == -1
assert 0x18 & 0x0f == 0x08 assert 0x18 & 0x0f == 0x08
assert 0x18 | 0x0f == 0x1f assert 0x18 | 0x0f == 0x1f
assert 0x18 ^ 0x0f == 0x17 assert 0x18 ^ 0x0f == 0x17
#ARTIQ#assert ~0x18 == -25
#ARTIQ#assert ~int64(0x18) == -25
assert [1] + [2] == [1, 2] try:
assert [1] * 3 == [1, 1, 1] 1 / 0
except ZeroDivisionError:
pass
else:
assert False
try:
1 // 0
except ZeroDivisionError:
pass
else:
assert False
try:
1 % 0
except ZeroDivisionError:
pass
else:
assert False

View File

@ -3,3 +3,6 @@
ary = array([1, 2, 3]) ary = array([1, 2, 3])
assert [x*x for x in ary] == [1, 4, 9] assert [x*x for x in ary] == [1, 4, 9]
assert [1] + [2] == [1, 2]
assert [1] * 3 == [1, 1, 1]

View File

@ -90,9 +90,9 @@ class WorkerCase(unittest.TestCase):
with self.assertLogs() as logs: with self.assertLogs() as logs:
with self.assertRaises(WorkerInternalException): with self.assertRaises(WorkerInternalException):
_run_experiment("ExceptionTermination") _run_experiment("ExceptionTermination")
self.assertEqual(len(logs.records), 1) self.assertGreater(len(logs.records), 0)
self.assertIn("Terminating with exception (TypeError)", self.assertIn("Terminating with exception (TypeError)",
logs.output[0]) logs.output[-1])
def test_watchdog_no_timeout(self): def test_watchdog_no_timeout(self):
_run_experiment("WatchdogNoTimeout") _run_experiment("WatchdogNoTimeout")

View File

@ -2,9 +2,9 @@
# $ conda env create -f conda/artiq-dev.yaml # $ conda env create -f conda/artiq-dev.yaml
name: artiq-dev name: artiq-dev
channels: channels:
- defaults
- conda-forge/label/main
- m-labs/label/dev - m-labs/label/dev
- m-labs/label/main - m-labs/label/main
- defaults
- conda-forge/label/main
dependencies: dependencies:
- artiq-dev - artiq-dev

View File

@ -14,15 +14,14 @@ requirements:
run: run:
- python >=3.5.3,<3.6 - python >=3.5.3,<3.6
- setuptools 33.1.1 - setuptools 33.1.1
- migen 0.5 - migen 0.7 py35_0+gite554f07
- misoc 0.6 - misoc 0.9 py35_0+gitcb8e314c
- jesd204b 0.3 - jesd204b 0.3
- binutils-or1k-linux >=2.27 - binutils-or1k-linux >=2.27
- llvm-or1k - llvm-or1k 4.0.1
- llvmlite-artiq 0.12.0 - llvmlite-artiq 0.20.0
- rust-core-or1k 1.20.0 16 - rust-core-or1k 1.23.0 19
- cargo 0.11.0 - openocd 0.10.0 1
- openocd >=0.10
- lit - lit
- outputcheck - outputcheck
- coverage - coverage
@ -38,7 +37,7 @@ requirements:
- python-dateutil - python-dateutil
- pyqt >=5.5 - pyqt >=5.5
- quamash - quamash
- pyqtgraph - pyqtgraph 0.10.0
- pygit2 - pygit2
- aiohttp - aiohttp
- pythonparser >=1.1 - pythonparser >=1.1

View File

@ -2,10 +2,10 @@
# $ conda env create -f conda/artiq-doc.yaml # $ conda env create -f conda/artiq-doc.yaml
name: artiq-doc name: artiq-doc
channels: channels:
- defaults
- conda-forge/label/main
- m-labs/label/dev - m-labs/label/dev
- m-labs/label/main - m-labs/label/main
- defaults
- conda-forge/label/main
dependencies: dependencies:
- python>=3.5.3,<3.6 - python>=3.5.3,<3.6
- sphinx=1.4.8 - sphinx=1.4.8

View File

@ -9,6 +9,6 @@ mkdir -p $SOC_PREFIX
V=1 $PYTHON -m artiq.gateware.targets.kc705_dds -H nist_clock --toolchain vivado $MISOC_EXTRA_VIVADO_CMDLINE V=1 $PYTHON -m artiq.gateware.targets.kc705_dds -H nist_clock --toolchain vivado $MISOC_EXTRA_VIVADO_CMDLINE
cp misoc_nist_clock_kc705/gateware/top.bit $SOC_PREFIX cp misoc_nist_clock_kc705/gateware/top.bit $SOC_PREFIX
cp misoc_nist_clock_kc705/software/bios/bios.bin $SOC_PREFIX cp misoc_nist_clock_kc705/software/bios/bios.bin $SOC_PREFIX
cp misoc_nist_clock_kc705/software/runtime/runtime.fbi $SOC_PREFIX cp misoc_nist_clock_kc705/software/runtime/runtime.{elf,fbi} $SOC_PREFIX
wget -P $SOC_PREFIX https://raw.githubusercontent.com/jordens/bscan_spi_bitstreams/single-tap/bscan_spi_xc7k325t.bit wget -P $SOC_PREFIX https://raw.githubusercontent.com/jordens/bscan_spi_bitstreams/single-tap/bscan_spi_xc7k325t.bit

View File

@ -6,7 +6,7 @@ source:
git_url: ../.. git_url: ../..
build: build:
noarch: generic noarch: python
ignore_prefix_files: True ignore_prefix_files: True
number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }} number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}
string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_FULL_HASH", "")[:8] }} string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_FULL_HASH", "")[:8] }}

View File

@ -9,6 +9,6 @@ mkdir -p $SOC_PREFIX
V=1 $PYTHON -m artiq.gateware.targets.kc705_dds -H nist_qc2 --toolchain vivado $MISOC_EXTRA_VIVADO_CMDLINE V=1 $PYTHON -m artiq.gateware.targets.kc705_dds -H nist_qc2 --toolchain vivado $MISOC_EXTRA_VIVADO_CMDLINE
cp misoc_nist_qc2_kc705/gateware/top.bit $SOC_PREFIX cp misoc_nist_qc2_kc705/gateware/top.bit $SOC_PREFIX
cp misoc_nist_qc2_kc705/software/bios/bios.bin $SOC_PREFIX cp misoc_nist_qc2_kc705/software/bios/bios.bin $SOC_PREFIX
cp misoc_nist_qc2_kc705/software/runtime/runtime.fbi $SOC_PREFIX cp misoc_nist_qc2_kc705/software/runtime/runtime.{elf,fbi} $SOC_PREFIX
wget -P $SOC_PREFIX https://raw.githubusercontent.com/jordens/bscan_spi_bitstreams/single-tap/bscan_spi_xc7k325t.bit wget -P $SOC_PREFIX https://raw.githubusercontent.com/jordens/bscan_spi_bitstreams/single-tap/bscan_spi_xc7k325t.bit

View File

@ -6,7 +6,7 @@ source:
git_url: ../.. git_url: ../..
build: build:
noarch: generic noarch: python
ignore_prefix_files: True ignore_prefix_files: True
number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }} number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}
string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_FULL_HASH", "")[:8] }} string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_FULL_HASH", "")[:8] }}

View File

@ -6,9 +6,9 @@ BUILD_SETTINGS_FILE=$HOME/.m-labs/build_settings.sh
SOC_PREFIX=$PREFIX/lib/python3.5/site-packages/artiq/binaries/kc705-phaser SOC_PREFIX=$PREFIX/lib/python3.5/site-packages/artiq/binaries/kc705-phaser
mkdir -p $SOC_PREFIX mkdir -p $SOC_PREFIX
V=1 $PYTHON -m artiq.gateware.targets.phaser --toolchain vivado $MISOC_EXTRA_VIVADO_CMDLINE V=1 $PYTHON -m artiq.gateware.targets.kc705_phaser --toolchain vivado $MISOC_EXTRA_VIVADO_CMDLINE
cp misoc_phaser_kc705/gateware/top.bit $SOC_PREFIX cp misoc_phaser_kc705/gateware/top.bit $SOC_PREFIX
cp misoc_phaser_kc705/software/bios/bios.bin $SOC_PREFIX cp misoc_phaser_kc705/software/bios/bios.bin $SOC_PREFIX
cp misoc_phaser_kc705/software/runtime/runtime.fbi $SOC_PREFIX cp misoc_phaser_kc705/software/runtime/runtime.{elf,fbi} $SOC_PREFIX
wget -P $SOC_PREFIX https://raw.githubusercontent.com/jordens/bscan_spi_bitstreams/single-tap/bscan_spi_xc7k325t.bit wget -P $SOC_PREFIX https://raw.githubusercontent.com/jordens/bscan_spi_bitstreams/single-tap/bscan_spi_xc7k325t.bit

View File

@ -6,7 +6,7 @@ source:
git_url: ../.. git_url: ../..
build: build:
noarch: generic noarch: python
ignore_prefix_files: True ignore_prefix_files: True
number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }} number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}
string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_FULL_HASH", "")[:8] }} string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_FULL_HASH", "")[:8] }}

View File

@ -26,10 +26,10 @@ requirements:
- setuptools 33.1.1 - setuptools 33.1.1
run: run:
- python >=3.5.3,<3.6 - python >=3.5.3,<3.6
- llvmlite-artiq 0.12.0.dev py35_30 - llvmlite-artiq 0.20.0
- binutils-or1k-linux - binutils-or1k-linux >=2.27
- pythonparser >=1.1 - pythonparser >=1.1
- openocd >=0.10 - openocd 0.10.0 1
- lit - lit
- outputcheck - outputcheck
- scipy - scipy

View File

@ -20,6 +20,12 @@ import sphinx_rtd_theme
from unittest.mock import MagicMock from unittest.mock import MagicMock
# Hack-patch Sphinx so that ARTIQ-Python types are correctly printed
# See: https://github.com/m-labs/artiq/issues/741
from sphinx.ext import autodoc
autodoc.repr = str
class Mock(MagicMock): class Mock(MagicMock):
@classmethod @classmethod
def __getattr__(cls, name): def __getattr__(cls, name):

View File

@ -162,11 +162,10 @@ Installation
............ ............
These installation instructions are a short form of those in the ARTIQ manual. These installation instructions are a short form of those in the ARTIQ manual.
* See the chapter on setting up a :ref:`development environment <develop-from-conda>`. * See the chapter on setting up a :ref:`development environment <develop-from-conda>`.
* When compiling the binaries, use the ``phaser`` target::: * When compiling the binaries, use the ``phaser`` target: ``python -m artiq.gateware.targets.kc705_phaser``
$ python -m artiq.gateware.targets.phaser * From time to time and on request there may be pre-built binaries in the ``artiq-kc705-phaser`` package on the M-Labs conda package label.
* From time to time and on request there may be pre-built binaries in the
``artiq-kc705-phaser`` package on the M-Labs conda package label.
Setup Setup
..... .....

View File

@ -27,7 +27,7 @@ ARTIQ Anaconda development environment
$ git clone --recursive https://github.com/m-labs/artiq ~/artiq-dev/artiq $ git clone --recursive https://github.com/m-labs/artiq ~/artiq-dev/artiq
$ cd ~/artiq-dev/artiq $ cd ~/artiq-dev/artiq
Add ``-b release-X`` to the ``git clone`` command if you are building a stable branch of ARTIQ (the default will fetch the development ``master`` branch). Add ``-b release-X`` to the ``git clone`` command if you are building a stable branch of ARTIQ. Replace ``X`` with the major release. The default will fetch the development ``master`` branch.
3. :ref:`Install Anaconda or Miniconda <install-anaconda>` 3. :ref:`Install Anaconda or Miniconda <install-anaconda>`
4. Create and activate a conda environment named ``artiq-dev`` and install the ``artiq-dev`` package which pulls in all the packages required to develop ARTIQ:: 4. Create and activate a conda environment named ``artiq-dev`` and install the ``artiq-dev`` package which pulls in all the packages required to develop ARTIQ::
@ -37,10 +37,9 @@ ARTIQ Anaconda development environment
$ pip install -e . $ pip install -e .
6. :ref:`Install Vivado <install-xilinx>` 6. :ref:`Install Vivado <install-xilinx>`
7. :ref:`Obtain and install the JTAG SPI flash proxy bitstream <install-bscan-spi>` 7. :ref:`Configure OpenOCD <setup-openocd>`
8. :ref:`Configure OpenOCD <setup-openocd>` 8. :ref:`Build target binaries <build-target-binaries>`
9. :ref:`Build target binaries <build-target-binaries>` 9. :ref:`Flash target binaries <flash-target-binaries>`
10. :ref:`Flash target binaries <flash-target-binaries>`
.. _install-from-source: .. _install-from-source:
@ -90,22 +89,22 @@ and the ARTIQ kernels.
* Install LLVM and Clang: :: * Install LLVM and Clang: ::
$ cd ~/artiq-dev $ cd ~/artiq-dev
$ git clone -b artiq-3.9 https://github.com/m-labs/llvm-or1k $ git clone -b artiq-4.0 https://github.com/m-labs/llvm-or1k
$ cd llvm-or1k $ cd llvm-or1k
$ git clone -b artiq-3.9 https://github.com/m-labs/clang-or1k tools/clang $ git clone -b artiq-4.0 https://github.com/m-labs/clang-or1k tools/clang
$ mkdir build $ mkdir build
$ cd build $ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local/llvm-or1k -DLLVM_TARGETS_TO_BUILD="OR1K;X86" -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_INSTALL_UTILS=ON $ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local/llvm-or1k -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=OR1K -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_INSTALL_UTILS=ON -DCLANG_ENABLE_ARCMT=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF
$ make -j4 $ make -j4
$ sudo make install $ sudo make install
* Install Rust: :: * Install Rust: ::
$ cd ~/artiq-dev $ cd ~/artiq-dev
$ git clone -b artiq-1.20.0 https://github.com/m-labs/rust $ git clone -b artiq-1.23.0 https://github.com/m-labs/rust
$ cd rust $ cd rust
$ git submodule update --init $ git submodule update --init --recursive
$ mkdir build $ mkdir build
$ cd build $ cd build
$ ../configure --prefix=/usr/local/rust-or1k --llvm-root=/usr/local/llvm-or1k --disable-manage-submodules --disable-docs $ ../configure --prefix=/usr/local/rust-or1k --llvm-root=/usr/local/llvm-or1k --disable-manage-submodules --disable-docs
@ -113,14 +112,16 @@ and the ARTIQ kernels.
$ sudo chown $USER.$USER /usr/local/rust-or1k $ sudo chown $USER.$USER /usr/local/rust-or1k
$ make install $ make install
$ libs="libcore libstd_unicode liballoc liblibc_mini libunwind" $ libs="core std_unicode alloc"
$ rustc="/usr/local/rust-or1k/bin/rustc --target or1k-unknown-none -g -C target-feature=+mul,+div,+ffl1,+cmov,+addc -C opt-level=s -L ." $ rustc="/usr/local/rust-or1k/bin/rustc --target or1k-unknown-none -C target-feature=+mul,+div,+ffl1,+cmov,+addc -C opt-level=s -g --crate-type rlib -L ."
$ destdir="/usr/local/rust-or1k/lib/rustlib/or1k-unknown-none/lib/" $ destdir="/usr/local/rust-or1k/lib/rustlib/or1k-unknown-none/lib/"
$ mkdir ../build-or1k $ mkdir ../build-or1k
$ cd ../build-or1k $ cd ../build-or1k
$ for lib in ${libs}; do ${rustc} ../src/${lib}/lib.rs; done $ for lib in ${libs}; do ${rustc} --crate-name ${lib} ../src/lib${lib}/lib.rs; done
$ ${rustc} -Cpanic=abort ../src/libpanic_abort/lib.rs $ ${rustc} --crate-name libc ../src/liblibc_mini/lib.rs
$ ${rustc} -Cpanic=unwind ../src/libpanic_unwind/lib.rs --cfg llvm_libunwind $ ${rustc} --crate-name unwind ../src/libunwind/lib.rs
$ ${rustc} -Cpanic=abort --crate-name panic_abort ../src/libpanic_abort/lib.rs
$ ${rustc} -Cpanic=unwind --crate-name panic_unwind ../src/libpanic_unwind/lib.rs --cfg llvm_libunwind
$ mkdir -p ${destdir} $ mkdir -p ${destdir}
$ cp *.rlib ${destdir} $ cp *.rlib ${destdir}

View File

@ -13,8 +13,8 @@ The conda package contains pre-built binaries that you can directly flash to you
.. warning:: .. warning::
Conda packages are supported for Linux (64-bit) and Windows (32- and 64-bit). Conda packages are supported for Linux (64-bit) and Windows (64-bit).
Users of other operating systems (32-bit Linux, BSD, OSX ...) should and can :ref:`install from source <install-from-source>`. Users of other operating systems (32-bit Linux or Windows, BSD, OSX ...) should and can :ref:`install from source <install-from-source>`.
.. _install-anaconda: .. _install-anaconda:
@ -37,18 +37,18 @@ Installing the ARTIQ packages
First add the conda-forge repository containing ARTIQ dependencies to your conda configuration:: First add the conda-forge repository containing ARTIQ dependencies to your conda configuration::
$ conda config --add channels http://conda.anaconda.org/conda-forge/label/main $ conda config --prepend channels http://conda.anaconda.org/conda-forge/label/main
Then add the M-Labs ``main`` Anaconda package repository containing stable releases and release candidates:: Then add the M-Labs ``main`` Anaconda package repository containing stable releases and release candidates::
$ conda config --add channels http://conda.anaconda.org/m-labs/label/main $ conda config --prepend channels http://conda.anaconda.org/m-labs/label/main
.. note:: .. note::
To use the development versions of ARTIQ, also add the ``dev`` label (http://conda.anaconda.org/m-labs/label/dev). To use the development versions of ARTIQ, also add the ``dev`` label (http://conda.anaconda.org/m-labs/label/dev).
Development versions are built for every change and contain more features, but are not as well-tested and are more likely to contain more bugs or inconsistencies than the releases in the ``main`` label. Development versions are built for every change and contain more features, but are not as well-tested and are more likely to contain more bugs or inconsistencies than the releases in the ``main`` label.
Then prepare to create a new conda environment with the ARTIQ package and the matching binaries for your hardware: Then prepare to create a new conda environment with the ARTIQ package and the matching binaries for your hardware:
choose a suitable name for the environment, for example ``artiq-main`` if you intend to track the main label or ``artiq-2016-04-01`` if you consider the environment a snapshot of ARTIQ on 2016-04-01. choose a suitable name for the environment, for example ``artiq-main`` if you intend to track the main label, ``artiq-3`` for the 3.x release series, or ``artiq-2016-04-01`` if you consider the environment a snapshot of ARTIQ on 2016-04-01.
Choose the package containing the binaries for your hardware: Choose the package containing the binaries for your hardware:
* ``artiq-kc705-nist_clock`` for the KC705 board with the NIST "clock" FMC backplane and AD9914 DDS chips. * ``artiq-kc705-nist_clock`` for the KC705 board with the NIST "clock" FMC backplane and AD9914 DDS chips.
@ -112,6 +112,9 @@ The ``artiq`` or ``artiq-dev`` conda packages install ``openocd`` automatically
.. _setup-openocd: .. _setup-openocd:
Configuring OpenOCD
^^^^^^^^^^^^^^^^^^^
Some additional steps are necessary to ensure that OpenOCD can communicate with the FPGA board. Some additional steps are necessary to ensure that OpenOCD can communicate with the FPGA board.
On Linux, first ensure that the current user belongs to the ``plugdev`` group. If it does not, run ``sudo adduser $USER plugdev`` and relogin. Afterwards:: On Linux, first ensure that the current user belongs to the ``plugdev`` group. If it does not, run ``sudo adduser $USER plugdev`` and relogin. Afterwards::