Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 485fc3bd2772
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7e9978089153
Choose a head ref

Commits on Feb 25, 2016

  1. test: bring back test_loopback_count (fixes #295).

    whitequark committed Feb 25, 2016
    1
    Copy the full SHA
    8e77e56 View commit details
  2. compiler: quell excessively detailed diagnostics.

    whitequark committed Feb 25, 2016
    Copy the full SHA
    919a49b View commit details
  3. compiler.types: TDelay is always unifiable with self.

    whitequark committed Feb 25, 2016
    Copy the full SHA
    d899d73 View commit details
  4. compiler.embedding: cache attribute types (fixes #276).

    whitequark committed Feb 25, 2016
    Copy the full SHA
    f838b8b View commit details
  5. Commit missing parts of 919a49b.

    whitequark committed Feb 25, 2016
    Copy the full SHA
    6bd16e4 View commit details
  6. transforms.llvm_ir_generator: use private linkage instead of internal.

    This reduces the size of symbol tables (internal adds an STB_LOCAL
    symbol, but private doesn't).
    whitequark committed Feb 25, 2016
    Copy the full SHA
    82a8e81 View commit details

Commits on Feb 26, 2016

  1. Copy the full SHA
    a5bf502 View commit details
  2. gateware/spi: stubs

    jordens committed Feb 26, 2016
    Copy the full SHA
    fb929c8 View commit details
  3. Copy the full SHA
    313a696 View commit details
  4. gateware.spi: design sketch

    jordens committed Feb 26, 2016
    Copy the full SHA
    e7146cc View commit details

Commits on Feb 27, 2016

  1. Copy the full SHA
    ade3eda View commit details
  2. Revert wrong parts of 6bd16e4.

    whitequark committed Feb 27, 2016
    Copy the full SHA
    63e0c7c View commit details
  3. Copy the full SHA
    e421b22 View commit details
  4. Fix tests.

    whitequark committed Feb 27, 2016
    Copy the full SHA
    8bbffab View commit details
  5. Copy the full SHA
    bd9ceb4 View commit details

Commits on Feb 28, 2016

  1. Copy the full SHA
    3b6999a View commit details
  2. Copy the full SHA
    f8732ac View commit details
  3. Copy the full SHA
    312e091 View commit details
  4. Copy the full SHA
    d5893d1 View commit details
  5. Copy the full SHA
    9a881aa View commit details
  6. 8
    Copy the full SHA
    8d7e92e View commit details
  7. spi: add runtime support

    jordens committed Feb 28, 2016
    Copy the full SHA
    d63a635 View commit details
  8. spi: add coredevice support

    jordens committed Feb 28, 2016
    Copy the full SHA
    8b2b278 View commit details
  9. Merge remote-tracking branch 'm-labs/master' into spimaster

    * m-labs/master:
      Fix tests.
      types.TypePrinter: don't waste screen space on empty attribute lists.
      Revert wrong parts of 6bd16e4.
      examples/notebook: cleanup, and fix spelling
      test/LoopbackCount: request correct devices
    jordens committed Feb 28, 2016
    Copy the full SHA
    a450490 View commit details

Commits on Feb 29, 2016

  1. Copy the full SHA
    9a1d6a5 View commit details
  2. Copy the full SHA
    5480099 View commit details
  3. Copy the full SHA
    ad34927 View commit details
  4. gateware.spi: style

    jordens committed Feb 29, 2016
    Copy the full SHA
    948fefa View commit details
  5. 2
    Copy the full SHA
    aeae565 View commit details
  6. gateware.spi: cleanup doc

    jordens committed Feb 29, 2016
    Copy the full SHA
    eb01b0b View commit details
  7. 4
    Copy the full SHA
    df7d15d View commit details
  8. fix indentation

    sbourdeauducq committed Feb 29, 2016
    Copy the full SHA
    785691a View commit details
  9. Copy the full SHA
    572c49f View commit details
  10. Copy the full SHA
    c226aeb View commit details
  11. Copy the full SHA
    6903a1d View commit details
  12. 6
    Copy the full SHA
    1b08e65 View commit details
  13. Copy the full SHA
    4467f91 View commit details
  14. Copy the full SHA
    f73228f View commit details
  15. Revert "gateware/rt2wb: support combinatorial ack"

    This reverts commit f73228f.
    jordens committed Feb 29, 2016
    Copy the full SHA
    cb8815c View commit details
  16. Revert "gateware/rt2wb: only input when active"

    This reverts commit 1b08e65.
    jordens committed Feb 29, 2016
    Copy the full SHA
    a0083f4 View commit details
  17. Copy the full SHA
    d0d56bd View commit details
  18. Copy the full SHA
    a1e1f2b View commit details
  19. Copy the full SHA
    dd57072 View commit details
  20. Copy the full SHA
    5fad570 View commit details
  21. coredevice/spi: clean up api

    jordens committed Feb 29, 2016
    Copy the full SHA
    e113668 View commit details
  22. Copy the full SHA
    d3c9482 View commit details
  23. runtime: refactor rt2wb/dds

    jordens committed Feb 29, 2016
    Copy the full SHA
    5dae9f8 View commit details
  24. Copy the full SHA
    ecedbbe View commit details
  25. coredevice.spi: cleanup

    jordens committed Feb 29, 2016
    Copy the full SHA
    16537d3 View commit details
  26. 10
    Copy the full SHA
    6c899e6 View commit details
Showing with 2,349 additions and 639 deletions.
  1. +2 −0 RELEASE_NOTES.rst
  2. +113 −100 artiq/compiler/embedding.py
  3. +1 −1 artiq/compiler/transforms/asttyped_rewriter.py
  4. +9 −6 artiq/compiler/transforms/llvm_ir_generator.py
  5. +27 −17 artiq/compiler/types.py
  6. +3 −3 artiq/coredevice/__init__.py
  7. +175 −0 artiq/coredevice/ad5360.py
  8. +2 −2 artiq/coredevice/comm_generic.py
  9. +7 −1 artiq/coredevice/core.py
  10. +5 −1 artiq/coredevice/exceptions.py
  11. +112 −0 artiq/coredevice/i2c.py
  12. +18 −0 artiq/coredevice/rtio.py
  13. +248 −0 artiq/coredevice/spi.py
  14. +28 −33 artiq/coredevice/ttl.py
  15. +12 −13 artiq/frontend/artiq_flash.py
  16. +36 −2 artiq/frontend/artiq_rpctool.py
  17. +11 −13 artiq/gateware/nist_clock.py
  18. +1 −1 artiq/gateware/nist_qc2.py
  19. +1 −1 artiq/gateware/rtio/analyzer.py
  20. +19 −15 artiq/gateware/rtio/core.py
  21. +13 −0 artiq/gateware/rtio/phy/spi.py
  22. +30 −0 artiq/gateware/soc.py
  23. +487 −0 artiq/gateware/spi.py
  24. +72 −36 artiq/gateware/targets/kc705.py
  25. +26 −24 artiq/gateware/targets/pipistrello.py
  26. +11 −11 artiq/gui/entries.py
  27. +1 −1 artiq/gui/moninj.py
  28. +201 −132 artiq/gui/scanwidget.py
  29. +1 −1 artiq/master/scheduler.py
  30. +1 −1 artiq/master/worker_db.py
  31. +1 −1 artiq/protocols/analyzer.py
  32. +14 −0 artiq/protocols/pc_rpc.py
  33. +10 −6 artiq/protocols/pipe_ipc.py
  34. +1 −1 artiq/runtime/Makefile
  35. +9 −4 artiq/runtime/bridge.c
  36. +5 −12 artiq/runtime/dds.c
  37. +193 −0 artiq/runtime/i2c.c
  38. +10 −0 artiq/runtime/i2c.h
  39. +11 −8 artiq/runtime/ksupport.c
  40. +2 −2 artiq/runtime/main.c
  41. +80 −5 artiq/runtime/rtio.c
  42. +13 −12 artiq/runtime/rtio.h
  43. +5 −3 artiq/runtime/session.c
  44. +0 −67 artiq/runtime/ttl.c
  45. +3 −5 artiq/runtime/ttl.h
  46. +25 −0 artiq/test/coredevice/test_i2c.py
  47. +53 −5 artiq/test/coredevice/test_rtio.py
  48. +6 −0 artiq/test/lit/codegen/assign_none.py
  49. +1 −1 artiq/test/lit/inferencer/error_with_arity.py
  50. +1 −1 artiq/test/lit/inferencer/error_with_exn.py
  51. +1 −1 artiq/test/lit/iodelay/class.py
  52. +6 −2 artiq/test/test_worker.py
  53. +25 −3 doc/manual/core_device.rst
  54. +19 −1 doc/manual/core_drivers_reference.rst
  55. +4 −0 doc/manual/getting_started_core.rst
  56. +24 −16 doc/manual/installing.rst
  57. +61 −32 examples/artiq_ipython_notebook.ipynb
  58. +70 −29 examples/master/device_db.pyon
  59. +17 −0 examples/master/repository/coredevice_examples/simple/ad5360.py
  60. +6 −7 examples/master/repository/coredevice_examples/tdr.py
2 changes: 2 additions & 0 deletions RELEASE_NOTES.rst
Original file line number Diff line number Diff line change
@@ -10,3 +10,5 @@ Release notes
* Core device flash storage has moved due to increased runtime size.
This requires reflashing the runtime and the flash storage filesystem image
or erase and rewrite its entries.
* RTIOCollisionError has been renamed to RTIOCollision

213 changes: 113 additions & 100 deletions artiq/compiler/embedding.py
Original file line number Diff line number Diff line change
@@ -295,6 +295,102 @@ def __init__(self, engine, value_map, quote):
super().__init__(engine)
self.value_map = value_map
self.quote = quote
self.attr_type_cache = {}

def _compute_value_type(self, object_value, object_type, object_loc, attr_name, loc):
if not hasattr(object_value, attr_name):
if attr_name.startswith('_'):
names = set(filter(lambda name: not name.startswith('_'),
dir(object_value)))
else:
names = set(dir(object_value))
suggestion = suggest_identifier(attr_name, names)

note = diagnostic.Diagnostic("note",
"attribute accessed here", {},
loc)
if suggestion is not None:
diag = diagnostic.Diagnostic("error",
"host object does not have an attribute '{attr}'; "
"did you mean '{suggestion}'?",
{"attr": attr_name, "suggestion": suggestion},
object_loc, notes=[note])
else:
diag = diagnostic.Diagnostic("error",
"host object does not have an attribute '{attr}'",
{"attr": attr_name},
object_loc, notes=[note])
self.engine.process(diag)
return

# Figure out what ARTIQ type does the value of the attribute have.
# We do this by quoting it, as if to serialize. This has some
# overhead (i.e. synthesizing a source buffer), but has the advantage
# of having the host-to-ARTIQ mapping code in only one place and
# also immediately getting proper diagnostics on type errors.
attr_value = getattr(object_value, attr_name)
if inspect.ismethod(attr_value) and types.is_instance(object_type):
# In cases like:
# class c:
# @kernel
# def f(self): pass
# we want f to be defined on the class, not on the instance.
attributes = object_type.constructor.attributes
attr_value = attr_value.__func__
else:
attributes = object_type.attributes

attr_value_type = None

if isinstance(attr_value, list):
# Fast path for lists of scalars.
IS_FLOAT = 1
IS_INT32 = 2
IS_INT64 = 4

state = 0
for elt in attr_value:
if elt.__class__ == float:
state |= IS_FLOAT
elif elt.__class__ == int:
if -2**31 < elt < 2**31-1:
state |= IS_INT32
elif -2**63 < elt < 2**63-1:
state |= IS_INT64
else:
state = -1
break
else:
state = -1

if state == IS_FLOAT:
attr_value_type = builtins.TList(builtins.TFloat())
elif state == IS_INT32:
attr_value_type = builtins.TList(builtins.TInt32())
elif state == IS_INT64:
attr_value_type = builtins.TList(builtins.TInt64())

if attr_value_type is None:
# Slow path. We don't know what exactly is the attribute value,
# so we quote it only for the error message that may possibly result.
ast = self.quote(attr_value, object_loc.expanded_from)

def proxy_diagnostic(diag):
note = diagnostic.Diagnostic("note",
"while inferring a type for an attribute '{attr}' of a host object",
{"attr": attr_name},
loc)
diag.notes.append(note)

self.engine.process(diag)

proxy_engine = diagnostic.Engine()
proxy_engine.process = proxy_diagnostic
Inferencer(engine=proxy_engine).visit(ast)
IntMonomorphizer(engine=proxy_engine).visit(ast)
attr_value_type = ast.type

return attributes, attr_value_type

def _unify_attribute(self, result_type, value_node, attr_name, attr_loc, loc):
# The inferencer can only observe types, not values; however,
@@ -304,108 +400,15 @@ def _unify_attribute(self, result_type, value_node, attr_name, attr_loc, loc):
# its type, we now interrogate every host object we have to ensure
# that we can successfully serialize the value of the attribute we
# are now adding at the code generation stage.
#
# FIXME: We perform exhaustive checks of every known host object every
# time an attribute access is visited, which is potentially quadratic.
# This is done because it is simpler than performing the checks only when:
# * a previously unknown attribute is encountered,
# * a previously unknown host object is encountered;
# which would be the optimal solution.

object_type = value_node.type.find()
for object_value, object_loc in self.value_map[object_type]:
attr_value_type = None
if not hasattr(object_value, attr_name):
if attr_name.startswith('_'):
names = set(filter(lambda name: not name.startswith('_'),
dir(object_value)))
else:
names = set(dir(object_value))
suggestion = suggest_identifier(attr_name, names)

note = diagnostic.Diagnostic("note",
"attribute accessed here", {},
loc)
if suggestion is not None:
diag = diagnostic.Diagnostic("error",
"host object does not have an attribute '{attr}'; "
"did you mean '{suggestion}'?",
{"attr": attr_name, "suggestion": suggestion},
object_loc, notes=[note])
else:
diag = diagnostic.Diagnostic("error",
"host object does not have an attribute '{attr}'",
{"attr": attr_name},
object_loc, notes=[note])
self.engine.process(diag)
return

# Figure out what ARTIQ type does the value of the attribute have.
# We do this by quoting it, as if to serialize. This has some
# overhead (i.e. synthesizing a source buffer), but has the advantage
# of having the host-to-ARTIQ mapping code in only one place and
# also immediately getting proper diagnostics on type errors.
attr_value = getattr(object_value, attr_name)
if inspect.ismethod(attr_value) and types.is_instance(object_type):
# In cases like:
# class c:
# @kernel
# def f(self): pass
# we want f to be defined on the class, not on the instance.
attributes = object_type.constructor.attributes
attr_value = attr_value.__func__
is_method = True
else:
attributes = object_type.attributes
is_method = False

if isinstance(attr_value, list):
# Fast path for lists of scalars.
IS_FLOAT = 1
IS_INT32 = 2
IS_INT64 = 4

state = 0
for elt in attr_value:
if elt.__class__ == float:
state |= IS_FLOAT
elif elt.__class__ == int:
if -2**31 < elt < 2**31-1:
state |= IS_INT32
elif -2**63 < elt < 2**63-1:
state |= IS_INT64
else:
state = -1
break
else:
state = -1

if state == IS_FLOAT:
attr_value_type = builtins.TList(builtins.TFloat())
elif state == IS_INT32:
attr_value_type = builtins.TList(builtins.TInt32())
elif state == IS_INT64:
attr_value_type = builtins.TList(builtins.TInt64())

if attr_value_type is None:
# Slow path. We don't know what exactly is the attribute value,
# so we quote it only for the error message that may possibly result.
ast = self.quote(attr_value, object_loc.expanded_from)

def proxy_diagnostic(diag):
note = diagnostic.Diagnostic("note",
"while inferring a type for an attribute '{attr}' of a host object",
{"attr": attr_name},
loc)
diag.notes.append(note)

self.engine.process(diag)

proxy_engine = diagnostic.Engine()
proxy_engine.process = proxy_diagnostic
Inferencer(engine=proxy_engine).visit(ast)
IntMonomorphizer(engine=proxy_engine).visit(ast)
attr_value_type = ast.type
attr_type_key = (id(object_value), attr_name)
try:
attributes, attr_value_type = self.attr_type_cache[attr_type_key]
except KeyError:
attributes, attr_value_type = \
self._compute_value_type(object_value, object_type, object_loc, attr_name, loc)
self.attr_type_cache[attr_type_key] = attributes, attr_value_type

if attr_name not in attributes:
# We just figured out what the type should be. Add it.
@@ -739,6 +742,16 @@ def _quote_function(self, function, loc):
else:
if hasattr(function, "artiq_embedded"):
if function.artiq_embedded.function is not None:
if function.__name__ == "<lambda>":
note = diagnostic.Diagnostic("note",
"lambda created here", {},
self._function_loc(function.artiq_embedded.function))
diag = diagnostic.Diagnostic("fatal",
"lambdas cannot be used as kernel functions", {},
loc,
notes=[note])
self.engine.process(diag)

# Insert the typed AST for the new function and restart inference.
# It doesn't really matter where we insert as long as it is before
# the final call.
2 changes: 1 addition & 1 deletion artiq/compiler/transforms/asttyped_rewriter.py
Original file line number Diff line number Diff line change
@@ -477,7 +477,7 @@ def visit_For(self, node):
target=node.target, iter=node.iter, body=node.body, orelse=node.orelse,
trip_count=None, trip_interval=None,
keyword_loc=node.keyword_loc, in_loc=node.in_loc, for_colon_loc=node.for_colon_loc,
else_loc=node.else_loc, else_colon_loc=node.else_colon_loc)
else_loc=node.else_loc, else_colon_loc=node.else_colon_loc, loc=node.loc)
return node

def visit_withitem(self, node):
15 changes: 9 additions & 6 deletions artiq/compiler/transforms/llvm_ir_generator.py
Original file line number Diff line number Diff line change
@@ -485,7 +485,7 @@ def rpc_tag_error(typ):
])
llrpcattr.global_constant = True
llrpcattr.unnamed_addr = True
llrpcattr.linkage = 'internal'
llrpcattr.linkage = 'private'

return llrpcattr

@@ -499,14 +499,14 @@ def rpc_tag_error(typ):
llrpcattrs + [ll.Constant(llrpcattrty.as_pointer(), None)])
llrpcattrary.global_constant = True
llrpcattrary.unnamed_addr = True
llrpcattrary.linkage = 'internal'
llrpcattrary.linkage = 'private'

llobjectaryty = ll.ArrayType(llptr, len(llobjects[typ]) + 1)
llobjectary = ll.GlobalVariable(self.llmodule, llobjectaryty,
name="objects.{}".format(type_name))
llobjectary.initializer = ll.Constant(llobjectaryty,
llobjects[typ] + [ll.Constant(llptr, None)])
llobjectary.linkage = 'internal'
llobjectary.linkage = 'private'

lldesc = ll.GlobalVariable(self.llmodule, lldescty,
name="desc.{}".format(type_name))
@@ -515,7 +515,7 @@ def rpc_tag_error(typ):
llobjectary.bitcast(llptr.as_pointer())
])
lldesc.global_constant = True
lldesc.linkage = 'internal'
lldesc.linkage = 'private'
lldescs.append(lldesc)

llglobaldescty = ll.ArrayType(lldescty.as_pointer(), len(lldescs) + 1)
@@ -529,7 +529,7 @@ def process_function(self, func):
self.llfunction = self.map(func)

if func.is_internal:
self.llfunction.linkage = 'internal'
self.llfunction.linkage = 'private'

self.llfunction.attributes.add('uwtable')

@@ -655,8 +655,11 @@ def process_GetConstructor(self, insn):

def process_SetLocal(self, insn):
env = insn.environment()
llptr = self.llptr_to_var(self.map(env), env.type, insn.var_name)
llvalue = self.map(insn.value())
if isinstance(llvalue.type, ll.VoidType):
# We store NoneType as {} but return it as void. So, bail out here.
return ll.Constant(ll.LiteralStructType([]), [])
llptr = self.llptr_to_var(self.map(env), env.type, insn.var_name)
if isinstance(llvalue, ll.Block):
llvalue = ll.BlockAddress(self.llfunction, llvalue)
if llptr.type.pointee != llvalue.type:
Loading