From cca654bd475bf7401bfce76afdcb6bd62c1cad24 Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Mon, 21 Jun 2021 10:39:39 +0200 Subject: [PATCH 001/238] test_device_db: fix on Windows (tempfile access limitations) Signed-off-by: Etienne Wodey --- artiq/test/test_device_db.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/artiq/test/test_device_db.py b/artiq/test/test_device_db.py index a05093aee..cde57e200 100644 --- a/artiq/test/test_device_db.py +++ b/artiq/test/test_device_db.py @@ -1,5 +1,6 @@ """Test device DB interface""" +import os import unittest import tempfile from pathlib import Path @@ -22,19 +23,27 @@ device_db = { } """ +# tempfile.NamedTemporaryFile: +# use delete=False and manual cleanup +# for Windows compatibility + class TestDeviceDBImport(unittest.TestCase): def test_no_device_db_in_file(self): - with tempfile.NamedTemporaryFile(mode="w+", suffix=".py") as f: + with tempfile.NamedTemporaryFile(mode="w+", suffix=".py", delete=False) as f: + print(f.name) print("", file=f, flush=True) with self.assertRaisesRegex(KeyError, "device_db"): DeviceDB(f.name) + os.unlink(f.name) + def test_import_same_level(self): with tempfile.TemporaryDirectory() as tmpdir: # make sure both files land in the same directory - args = dict(mode="w+", suffix=".py", dir=tmpdir) + # tempfiles are cleanup together with tmpdir + args = dict(mode="w+", suffix=".py", dir=tmpdir, delete=False) with tempfile.NamedTemporaryFile( **args ) as fileA, tempfile.NamedTemporaryFile(**args) as fileB: @@ -58,11 +67,17 @@ device_db["new_core_alias"] = "core" class TestDeviceDB(unittest.TestCase): def setUp(self): - self.ddb_file = tempfile.NamedTemporaryFile(mode="w+", suffix=".py") + self.ddb_file = tempfile.NamedTemporaryFile( + mode="w+", suffix=".py", delete=False + ) print(DUMMY_DDB_FILE, file=self.ddb_file, flush=True) self.ddb = DeviceDB(self.ddb_file.name) + def tearDown(self): + self.ddb_file.close() + os.unlink(self.ddb_file.name) + def test_get(self): core = self.ddb.get("core") self.assertEqual(core["class"], "Core") From 68268e3db8a1774332b1eb2018f3376812643f99 Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Tue, 22 Jun 2021 11:57:28 +0200 Subject: [PATCH 002/238] docs: fix some formatting issues Signed-off-by: Etienne Wodey --- artiq/coredevice/mirny.py | 5 ++--- doc/manual/faq.rst | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/artiq/coredevice/mirny.py b/artiq/coredevice/mirny.py index a29f57aeb..ddcdd1931 100644 --- a/artiq/coredevice/mirny.py +++ b/artiq/coredevice/mirny.py @@ -40,9 +40,8 @@ class Mirny: :param refclk: Reference clock (SMA, MMCX or on-board 100 MHz oscillator) frequency in Hz :param clk_sel: Reference clock selection. - valid options are: "XO" - onboard crystal oscillator - "SMA" - front-panel SMA connector - "MMCX" - internal MMCX connector + Valid options are: "XO" - onboard crystal oscillator; + "SMA" - front-panel SMA connector; "MMCX" - internal MMCX connector. Passing an integer writes it as ``clk_sel`` in the CPLD's register 1. The effect depends on the hardware revision. :param core_device: Core device name (default: "core") diff --git a/doc/manual/faq.rst b/doc/manual/faq.rst index 817b64130..bd5d4ac89 100644 --- a/doc/manual/faq.rst +++ b/doc/manual/faq.rst @@ -118,4 +118,5 @@ find the dashboard and browser configuration files are stored? -------------------------------------------------------------- :: + python -c "from artiq.tools import get_user_config_dir; print(get_user_config_dir())" From 094a346974642150f9df4d89197207d711e12088 Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Tue, 22 Jun 2021 11:48:06 +0200 Subject: [PATCH 003/238] docs: fix snippet to advance the timeline by one coarse RTIO cycle Signed-off-by: Etienne Wodey --- doc/manual/rtio.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/rtio.rst b/doc/manual/rtio.rst index 67c8bdcaf..f5901ab0d 100644 --- a/doc/manual/rtio.rst +++ b/doc/manual/rtio.rst @@ -131,7 +131,7 @@ Notes: * Configuring the gateware with more lanes for the RTIO core reduces the frequency of sequence errors. * The number of lanes is a hard limit on the number of simultaneous RTIO output events. * Whether a particular sequence of timestamps causes a sequence error or not is fully deterministic (starting from a known RTIO state, e.g. after a reset). Adding a constant offset to the whole sequence does not affect the result. -* Zero-duration methods (such as :meth:`artiq.coredevice.ttl.TTLOut.on()`) do not advance the timeline and so will consume additional lanes if they are scheduled simultaneously. Adding a tiny delay will prevent this (e.g. ``delay_mu(self.core.ref_multiplier)``, at least one coarse rtio cycle). +* Zero-duration methods (such as :meth:`artiq.coredevice.ttl.TTLOut.on()`) do not advance the timeline and so will consume additional lanes if they are scheduled simultaneously. Adding a tiny delay will prevent this (e.g. ``delay_mu(np.int64(self.core.ref_multiplier))``, at least one coarse rtio cycle). The offending event is discarded and the RTIO core keeps operating. From c29a149d16758fb3101ff4a8d7af4b2ea89e7721 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 25 Jun 2021 10:25:33 +0800 Subject: [PATCH 004/238] compiler: allows string annotation According to PEP484, type hint can be a string literal for forward references. With PEP563, type hint would be preserved in annotations in string form. --- artiq/compiler/embedding.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/artiq/compiler/embedding.py b/artiq/compiler/embedding.py index fe197d81b..d4628bd77 100644 --- a/artiq/compiler/embedding.py +++ b/artiq/compiler/embedding.py @@ -949,6 +949,27 @@ class Stitcher: if annot is None: annot = builtins.TNone() + if isinstance(function, SpecializedFunction): + host_function = function.host_function + else: + host_function = function + + embedded_function = host_function.artiq_embedded.function + + if isinstance(embedded_function, str): + embedded_function = host_function + + if isinstance(annot, str): + if annot not in embedded_function.__globals__: + diag = diagnostic.Diagnostic( + "error", + "type annotation for {kind}, {annot}, is not defined", + {"kind": kind, "annot": repr(annot)}, + self._function_loc(function), + notes=self._call_site_note(call_loc, fn_kind)) + self.engine.process(diag) + annot = embedded_function.__globals__[annot] + if not isinstance(annot, types.Type): diag = diagnostic.Diagnostic("error", "type annotation for {kind}, '{annot}', is not an ARTIQ type", From f531af510c8b90612893d32742b98084433b5138 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 25 Jun 2021 11:17:34 +0800 Subject: [PATCH 005/238] compiler: fixed embedding annotation evaluation --- artiq/compiler/embedding.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/artiq/compiler/embedding.py b/artiq/compiler/embedding.py index d4628bd77..affb69b9b 100644 --- a/artiq/compiler/embedding.py +++ b/artiq/compiler/embedding.py @@ -954,21 +954,25 @@ class Stitcher: else: host_function = function - embedded_function = host_function.artiq_embedded.function + if hasattr(host_function, 'artiq_embedded'): + embedded_function = host_function.artiq_embedded.function + else: + embedded_function = host_function if isinstance(embedded_function, str): embedded_function = host_function if isinstance(annot, str): - if annot not in embedded_function.__globals__: + try: + annot = eval(annot, embedded_function.__globals__) + except Exception: diag = diagnostic.Diagnostic( - "error", - "type annotation for {kind}, {annot}, is not defined", - {"kind": kind, "annot": repr(annot)}, - self._function_loc(function), - notes=self._call_site_note(call_loc, fn_kind)) + "error", + "type annotation for {kind}, {annot}, cannot be evaluated", + {"kind": kind, "annot": repr(annot)}, + self._function_loc(function), + notes=self._call_site_note(call_loc, fn_kind)) self.engine.process(diag) - annot = embedded_function.__globals__[annot] if not isinstance(annot, types.Type): diag = diagnostic.Diagnostic("error", From 0806b67dbf73188049f61d27ce73638ee907ea5e Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 2 Jul 2021 13:54:54 +0800 Subject: [PATCH 006/238] compiler: speedup list processing --- artiq/compiler/embedding.py | 72 ++++++++++-- .../compiler/transforms/llvm_ir_generator.py | 104 +++++++++++------- 2 files changed, 125 insertions(+), 51 deletions(-) diff --git a/artiq/compiler/embedding.py b/artiq/compiler/embedding.py index affb69b9b..4ff303274 100644 --- a/artiq/compiler/embedding.py +++ b/artiq/compiler/embedding.py @@ -156,6 +156,67 @@ class ASTSynthesizer: return source.Range(self.source_buffer, range_from, range_to, expanded_from=self.expanded_from) + def fast_quote_list(self, value): + elts = [None] * len(value) + is_T = False + if len(value) > 0: + v = value[0] + is_T = True + if isinstance(v, int): + T = int + elif isinstance(v, float): + T = float + elif isinstance(v, numpy.int32): + T = numpy.int32 + elif isinstance(v, numpy.int64): + T = numpy.int64 + else: + is_T = False + if is_T: + for v in value: + if not isinstance(v, T): + is_T = False + break + if is_T: + is_int = T != float + if T == int: + typ = builtins.TInt() + elif T == float: + typ = builtins.TFloat() + elif T == numpy.int32: + typ = builtins.TInt32() + elif T == numpy.int64: + typ = builtins.TInt64() + else: + assert False + text = [repr(elt) for elt in value] + start = len(self.source) + self.source += ", ".join(text) + if is_int: + for i, (v, t) in enumerate(zip(value, text)): + l = len(t) + elts[i] = asttyped.NumT( + n=int(v), ctx=None, type=typ, + loc=source.Range( + self.source_buffer, start, start + l, + expanded_from=self.expanded_from)) + start += l + 2 + else: + for i, (v, t) in enumerate(zip(value, text)): + l = len(t) + elts[i] = asttyped.NumT( + n=v, ctx=None, type=typ, + loc=source.Range( + self.source_buffer, start, start + l, + expanded_from=self.expanded_from)) + start += l + 2 + else: + for index, elt in enumerate(value): + elts[index] = self.quote(elt) + if index < len(value) - 1: + self._add(", ") + return elts + def quote(self, value): """Construct an AST fragment equal to `value`.""" if value is None: @@ -217,21 +278,14 @@ class ASTSynthesizer: return asttyped.QuoteT(value=value, type=builtins.TByteArray(), loc=loc) elif isinstance(value, list): begin_loc = self._add("[") - elts = [] - for index, elt in enumerate(value): - elts.append(self.quote(elt)) - if index < len(value) - 1: - self._add(", ") + elts = self.fast_quote_list(value) end_loc = self._add("]") return asttyped.ListT(elts=elts, ctx=None, type=builtins.TList(), begin_loc=begin_loc, end_loc=end_loc, loc=begin_loc.join(end_loc)) elif isinstance(value, tuple): begin_loc = self._add("(") - elts = [] - for index, elt in enumerate(value): - elts.append(self.quote(elt)) - self._add(", ") + elts = self.fast_quote_list(value) end_loc = self._add(")") return asttyped.TupleT(elts=elts, ctx=None, type=types.TTuple([e.type for e in elts]), diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 49bbebc57..b8df85d17 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -180,6 +180,7 @@ class LLVMIRGenerator: self.tbaa_tree, ll.Constant(lli64, 1) ]) + self.quote_fail_msg = None def needs_sret(self, lltyp, may_be_large=True): if isinstance(lltyp, ll.VoidType): @@ -1492,8 +1493,24 @@ class LLVMIRGenerator: return llresult def _quote_listish_to_llglobal(self, value, elt_type, path, kind_name): - llelts = [self._quote(value[i], elt_type, lambda: path() + [str(i)]) - for i in range(len(value))] + fail_msg = "at " + ".".join(path()) + if len(value) > 0: + if builtins.is_int(elt_type): + int_typ = (int, numpy.int32, numpy.int64) + for v in value: + assert isinstance(v, int_typ), fail_msg + llty = self.llty_of_type(elt_type) + llelts = [ll.Constant(llty, int(v)) for v in value] + elif builtins.is_float(elt_type): + for v in value: + assert isinstance(v, float), fail_msg + llty = self.llty_of_type(elt_type) + llelts = [ll.Constant(llty, v) for v in value] + else: + llelts = [self._quote(value[i], elt_type, lambda: path() + [str(i)]) + for i in range(len(value))] + else: + assert False, fail_msg lleltsary = ll.Constant(ll.ArrayType(self.llty_of_type(elt_type), len(llelts)), list(llelts)) name = self.llmodule.scope.deduplicate("quoted.{}".format(kind_name)) @@ -1502,60 +1519,63 @@ class LLVMIRGenerator: llglobal.linkage = "private" return llglobal.bitcast(lleltsary.type.element.as_pointer()) + def _quote_attributes(self, value, typ, path, value_id, llty): + llglobal = None + llfields = [] + emit_as_constant = True + for attr in typ.attributes: + if attr == "__objectid__": + objectid = self.embedding_map.store_object(value) + llfields.append(ll.Constant(lli32, objectid)) + + assert llglobal is None + if types.is_constructor(typ): + llglobal = self.get_class(typ) + else: + llglobal = ll.GlobalVariable(self.llmodule, llty.pointee, + name="O.{}".format(objectid)) + + self.llobject_map[value_id] = llglobal + else: + attrvalue = getattr(value, attr) + is_class_function = (types.is_constructor(typ) and + types.is_function(typ.attributes[attr]) and + not types.is_external_function(typ.attributes[attr])) + if is_class_function: + attrvalue = self.embedding_map.specialize_function(typ.instance, attrvalue) + if not (types.is_instance(typ) and attr in typ.constant_attributes): + emit_as_constant = False + llattrvalue = self._quote(attrvalue, typ.attributes[attr], + lambda: path() + [attr]) + llfields.append(llattrvalue) + if is_class_function: + llclosureptr = self.get_global_closure_ptr(typ, attr) + llclosureptr.initializer = llattrvalue + + llglobal.global_constant = emit_as_constant + llglobal.initializer = ll.Constant(llty.pointee, llfields) + llglobal.linkage = "private" + return llglobal + def _quote(self, value, typ, path): value_id = id(value) if value_id in self.llobject_map: return self.llobject_map[value_id] llty = self.llty_of_type(typ) - def _quote_attributes(): - llglobal = None - llfields = [] - emit_as_constant = True - for attr in typ.attributes: - if attr == "__objectid__": - objectid = self.embedding_map.store_object(value) - llfields.append(ll.Constant(lli32, objectid)) + fail_msg = self.quote_fail_msg + if fail_msg == None: + self.quote_fail_msg = fail_msg = "at " + ".".join(path()) - assert llglobal is None - if types.is_constructor(typ): - llglobal = self.get_class(typ) - else: - llglobal = ll.GlobalVariable(self.llmodule, llty.pointee, - name="O.{}".format(objectid)) - - self.llobject_map[value_id] = llglobal - else: - attrvalue = getattr(value, attr) - is_class_function = (types.is_constructor(typ) and - types.is_function(typ.attributes[attr]) and - not types.is_external_function(typ.attributes[attr])) - if is_class_function: - attrvalue = self.embedding_map.specialize_function(typ.instance, attrvalue) - if not (types.is_instance(typ) and attr in typ.constant_attributes): - emit_as_constant = False - llattrvalue = self._quote(attrvalue, typ.attributes[attr], - lambda: path() + [attr]) - llfields.append(llattrvalue) - if is_class_function: - llclosureptr = self.get_global_closure_ptr(typ, attr) - llclosureptr.initializer = llattrvalue - - llglobal.global_constant = emit_as_constant - llglobal.initializer = ll.Constant(llty.pointee, llfields) - llglobal.linkage = "private" - return llglobal - - fail_msg = "at " + ".".join(path()) if types.is_constructor(typ) or types.is_instance(typ): if types.is_instance(typ): # Make sure the class functions are quoted, as this has the side effect of # initializing the global closures. self._quote(type(value), typ.constructor, lambda: path() + ['__class__']) - return _quote_attributes() + return self._quote_attributes(value, typ, path, value_id, llty) elif types.is_module(typ): - return _quote_attributes() + return self._quote_attributes(value, typ, path, value_id, llty) elif builtins.is_none(typ): assert value is None, fail_msg return ll.Constant.literal_struct([]) From 6fb31a7abb8d3367cd60b7b889fc472613252486 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 2 Jul 2021 15:16:19 +0800 Subject: [PATCH 007/238] compiler: allow empty list in quote --- artiq/compiler/transforms/llvm_ir_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index b8df85d17..49fc339bd 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1510,7 +1510,7 @@ class LLVMIRGenerator: llelts = [self._quote(value[i], elt_type, lambda: path() + [str(i)]) for i in range(len(value))] else: - assert False, fail_msg + llelts = [] lleltsary = ll.Constant(ll.ArrayType(self.llty_of_type(elt_type), len(llelts)), list(llelts)) name = self.llmodule.scope.deduplicate("quoted.{}".format(kind_name)) From 822e8565f74928df5673364186e061c9f1a4e8e6 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 2 Jul 2021 16:28:47 +0800 Subject: [PATCH 008/238] compiler: supports kernel decorators with path --- artiq/compiler/transforms/inferencer.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/artiq/compiler/transforms/inferencer.py b/artiq/compiler/transforms/inferencer.py index 7d6d065b7..fdc268d4f 100644 --- a/artiq/compiler/transforms/inferencer.py +++ b/artiq/compiler/transforms/inferencer.py @@ -6,6 +6,7 @@ from collections import OrderedDict from pythonparser import algorithm, diagnostic, ast from .. import asttyped, types, builtins from .typedtree_printer import TypedtreePrinter +from artiq.experiment import kernel def is_nested_empty_list(node): @@ -1662,7 +1663,14 @@ class Inferencer(algorithm.Visitor): def visit_FunctionDefT(self, node): for index, decorator in enumerate(node.decorator_list): - if types.is_builtin(decorator.type, "kernel") or \ + def eval_attr(attr): + if isinstance(attr.value, asttyped.QuoteT): + return getattr(attr.value.value, attr.attr) + return getattr(eval_attr(attr.value), attr.attr) + if isinstance(decorator, asttyped.AttributeT): + decorator = eval_attr(decorator) + if id(decorator) == id(kernel) or \ + types.is_builtin(decorator.type, "kernel") or \ isinstance(decorator, asttyped.CallT) and \ types.is_builtin(decorator.func.type, "kernel"): continue From 0257ecc332286481487c4edd11a39ff5fc42d7a0 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 2 Jul 2021 16:53:24 +0800 Subject: [PATCH 009/238] update release notes --- RELEASE_NOTES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 1c668fd3f..9a8255d05 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -13,6 +13,9 @@ Highlights: - Improved documentation - Expose the DAC coarse mixer and sif_sync - Exposes upconverter calibration and enabling/disabling of upconverter LO & RF outputs. +* Compiler: + - Supports kernel decorator with paths. + - Faster compilation for large arrays/lists. Breaking changes: * Updated Phaser-Upconverter default frequency 2.875 GHz. The new default uses the target PFD From 29fd58e34be880d92d67614b474873d4e800a37a Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 5 Jul 2021 21:22:34 +0800 Subject: [PATCH 010/238] RELEASE_NOTES: update and fix formatting --- RELEASE_NOTES.rst | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 9a8255d05..ec211cf3a 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -7,20 +7,24 @@ ARTIQ-7 ------- Highlights: + +* Support for Kasli-SoC, a new EEM carrier based on a Zynq SoC, enabling much faster kernel execution. +* Softcore targets now use the RISC-V architecture (VexRiscv) instead of OR1K (mor1kx). * WRPLL -* ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912 -* Phaser: - - Improved documentation - - Expose the DAC coarse mixer and sif_sync - - Exposes upconverter calibration and enabling/disabling of upconverter LO & RF outputs. * Compiler: - Supports kernel decorator with paths. - Faster compilation for large arrays/lists. +* Phaser: + - Improved documentation + - Expose the DAC coarse mixer and ``sif_sync`` + - Exposes upconverter calibration and enabling/disabling of upconverter LO & RF outputs. +* ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912 Breaking changes: + * Updated Phaser-Upconverter default frequency 2.875 GHz. The new default uses the target PFD frequency of the hardware design. -* `Phaser.init()` now disables all Kasli-oscillators. This avoids full power RF output being +* ``Phaser.init()`` now disables all Kasli-oscillators. This avoids full power RF output being generated for some configurations. * Phaser: fixed coarse mixer frequency configuration @@ -33,7 +37,7 @@ Highlights: * New hardware support: - Phaser, a quad channel 1GS/s RF generator card with dual IQ upconverter and dual 5MS/s ADC and FPGA. - - Zynq SoC core devices, enabling kernels to run on 1 GHz CPU core with a floating-point + - Zynq SoC core device (ZC706), enabling kernels to run on 1 GHz CPU core with a floating-point unit for faster computations. This currently requires an external repository (https://git.m-labs.hk/m-labs/artiq-zynq). - Mirny 4-channel wide-band PLL/VCO-based microwave frequency synthesiser From 51d2861e6363827a18afa4e490614b77e852aed9 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 5 Jul 2021 22:15:58 +0800 Subject: [PATCH 011/238] Freenode -> OFTC --- CONTRIBUTING.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 8fa7d0336..88100ddf5 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -7,8 +7,7 @@ Reporting Issues/Bugs Thanks for `reporting issues to ARTIQ `_! You can also discuss issues and -ask questions on IRC (the `#m-labs channel on freenode -`_), the `Mattermost chat +ask questions on IRC (the #m-labs channel on OFTC), the `Mattermost chat `_, or on the `forum `_. The best bug reports are those which contain sufficient information. With From 4ede58e44b5469e21ba7715390c353962b7c058c Mon Sep 17 00:00:00 2001 From: pca006132 Date: Tue, 6 Jul 2021 15:23:24 +0800 Subject: [PATCH 012/238] compiler: reduce calls to TypedTreeHasher We need to check if our inference reached a fixed point. This is checked using hash of the types in the AST, which is very slow. This patch avoids computing the hash if we can make sure that the AST is definitely changed, which is when we parse a new function. For some simple programs with many functions, this can significantly reduce the compile time by up to ~30%. --- artiq/compiler/embedding.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/artiq/compiler/embedding.py b/artiq/compiler/embedding.py index 4ff303274..6fa6078f3 100644 --- a/artiq/compiler/embedding.py +++ b/artiq/compiler/embedding.py @@ -737,6 +737,7 @@ class Stitcher: self.embedding_map = EmbeddingMap() self.value_map = defaultdict(lambda: []) + self.definitely_changed = False def stitch_call(self, function, args, kwargs, callback=None): # We synthesize source code for the initial call so that @@ -757,13 +758,19 @@ class Stitcher: old_attr_count = None while True: inferencer.visit(self.typedtree) - typedtree_hash = typedtree_hasher.visit(self.typedtree) - attr_count = self.embedding_map.attribute_count() + if self.definitely_changed: + changed = True + self.definitely_changed = False + else: + typedtree_hash = typedtree_hasher.visit(self.typedtree) + attr_count = self.embedding_map.attribute_count() + changed = old_attr_count != attr_count or \ + old_typedtree_hash != typedtree_hash + old_typedtree_hash = typedtree_hash + old_attr_count = attr_count - if old_typedtree_hash == typedtree_hash and old_attr_count == attr_count: + if not changed: break - old_typedtree_hash = typedtree_hash - old_attr_count = attr_count # After we've discovered every referenced attribute, check if any kernel_invariant # specifications refers to ones we didn't encounter. @@ -891,6 +898,9 @@ class Stitcher: return types.TVar() def _quote_embedded_function(self, function, flags): + # we are now parsing new functions... definitely changed the type + self.definitely_changed = True + if isinstance(function, SpecializedFunction): host_function = function.host_function else: From b10d1bdd378a9a9f904b97c1434c36fcc619f112 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Wed, 7 Jul 2021 09:20:41 +0800 Subject: [PATCH 013/238] compiler: proper union find The find implementation was not very optimized, and the unify function did not consider tree height and may build some tall trees. --- artiq/compiler/types.py | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/artiq/compiler/types.py b/artiq/compiler/types.py index e7b68a3a4..78364101b 100644 --- a/artiq/compiler/types.py +++ b/artiq/compiler/types.py @@ -55,40 +55,39 @@ class TVar(Type): def __init__(self): self.parent = self + self.rank = 0 def find(self): - if self.parent is self: + parent = self.parent + if parent is self: return self else: # The recursive find() invocation is turned into a loop # because paths resulting from unification of large arrays # can easily cause a stack overflow. root = self - while root.__class__ == TVar: - if root is root.parent: - break - else: - root = root.parent - - # path compression - iter = self - while iter.__class__ == TVar: - if iter is root: - break - else: - iter, iter.parent = iter.parent, root - - return root + while parent.__class__ == TVar and root is not parent: + _, parent = root, root.parent = parent, parent.parent + return root.parent def unify(self, other): if other is self: return - other = other.find() - - if self.parent is self: - self.parent = other + x = other.find() + y = self.find() + if x is y: + return + if y.__class__ == TVar: + if x.__class__ == TVar: + if x.rank < y.rank: + x, y = y, x + y.parent = x + if x.rank == y.rank: + x.rank += 1 + else: + y.parent = x else: - self.find().unify(other) + y.unify(x) def fold(self, accum, fn): if self.parent is self: From 2204fd2b22248bca3cc2e61c6872d924736f34b0 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 8 Jul 2021 10:03:13 +0800 Subject: [PATCH 014/238] adf5356: add delay to sync() Signed-off-by: Oi Chee Cheung --- RELEASE_NOTES.rst | 2 ++ artiq/coredevice/adf5356.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index ec211cf3a..37af7ed33 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -27,6 +27,8 @@ Breaking changes: * ``Phaser.init()`` now disables all Kasli-oscillators. This avoids full power RF output being generated for some configurations. * Phaser: fixed coarse mixer frequency configuration +* Mirny: Added extra delays in ``ADF5356.sync()``. This avoids the need of an extra delay before + calling `ADF5356.init()`. ARTIQ-6 diff --git a/artiq/coredevice/adf5356.py b/artiq/coredevice/adf5356.py index dae2c97cb..845067541 100644 --- a/artiq/coredevice/adf5356.py +++ b/artiq/coredevice/adf5356.py @@ -236,6 +236,7 @@ class ADF5356: Write all registers to the device. Attempts to lock the PLL. """ f_pfd = self.f_pfd() + delay(200 * us) # Slack if f_pfd <= 75.0 * MHz: for i in range(13, 0, -1): @@ -249,6 +250,7 @@ class ADF5356: n, frac1, (frac2_msb, frac2_lsb), (mod2_msb, mod2_lsb) = calculate_pll( self.f_vco(), f_pfd >> 1 ) + delay(200 * us) # Slack self.write( 13 From 6ce9c26402e62e44797b9398c30f872a2074d3dc Mon Sep 17 00:00:00 2001 From: Star Chen <43180603+SidaChen1999@users.noreply.github.com> Date: Tue, 13 Jul 2021 12:53:35 +0800 Subject: [PATCH 015/238] GUI: add option to create new datasets (#1716) --- artiq/dashboard/datasets.py | 73 ++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/artiq/dashboard/datasets.py b/artiq/dashboard/datasets.py index 5e353d4c9..10e51e906 100644 --- a/artiq/dashboard/datasets.py +++ b/artiq/dashboard/datasets.py @@ -3,8 +3,9 @@ import logging import numpy as np from PyQt5 import QtCore, QtWidgets +from sipyco import pyon -from artiq.tools import short_format +from artiq.tools import short_format, exc_to_warning from artiq.gui.tools import LayoutWidget, QRecursiveFilterProxyModel from artiq.gui.models import DictSyncTreeSepModel from artiq.gui.scientific_spinbox import ScientificSpinBox @@ -82,6 +83,68 @@ class StringEditor(Editor): return self.edit_widget.text() +class Creator(QtWidgets.QDialog): + def __init__(self, parent, dataset_ctl): + QtWidgets.QDialog.__init__(self, parent=parent) + self.dataset_ctl = dataset_ctl + + self.setWindowTitle("Create dataset") + grid = QtWidgets.QGridLayout() + grid.setRowMinimumHeight(1, 40) + grid.setColumnMinimumWidth(2, 60) + self.setLayout(grid) + + grid.addWidget(QtWidgets.QLabel("Name:"), 0, 0) + self.name_widget = QtWidgets.QLineEdit() + grid.addWidget(self.name_widget, 0, 1) + + grid.addWidget(QtWidgets.QLabel("Value:"), 1, 0) + self.value_widget = QtWidgets.QLineEdit() + self.value_widget.setPlaceholderText('PYON (Python)') + grid.addWidget(self.value_widget, 1, 1) + self.data_type = QtWidgets.QLabel("data type") + grid.addWidget(self.data_type, 1, 2) + self.value_widget.textChanged.connect(self.dtype) + + grid.addWidget(QtWidgets.QLabel("Persist:"), 2, 0) + self.box_widget = QtWidgets.QCheckBox() + grid.addWidget(self.box_widget, 2, 1) + + self.ok = QtWidgets.QPushButton('&Ok') + self.ok.setEnabled(False) + self.cancel = QtWidgets.QPushButton('&Cancel') + self.buttons = QtWidgets.QDialogButtonBox(self) + self.buttons.addButton( + self.ok, QtWidgets.QDialogButtonBox.AcceptRole) + self.buttons.addButton( + self.cancel, QtWidgets.QDialogButtonBox.RejectRole) + grid.setRowStretch(3, 1) + grid.addWidget(self.buttons, 4, 0, 1, 3) + self.buttons.accepted.connect(self.accept) + self.buttons.rejected.connect(self.reject) + + def accept(self): + key = self.name_widget.text() + value = self.value_widget.text() + persist = self.box_widget.isChecked() + asyncio.ensure_future(exc_to_warning(self.dataset_ctl.set( + key, pyon.decode(value), persist))) + QtWidgets.QDialog.accept(self) + + def dtype(self): + txt = self.value_widget.text() + try: + result = pyon.decode(txt) + except: + pixmap = self.style().standardPixmap( + QtWidgets.QStyle.SP_MessageBoxWarning) + self.data_type.setPixmap(pixmap) + self.ok.setEnabled(False) + else: + self.data_type.setText(type(result).__name__) + self.ok.setEnabled(True) + + class Model(DictSyncTreeSepModel): def __init__(self, init): DictSyncTreeSepModel.__init__(self, ".", @@ -120,6 +183,11 @@ class DatasetsDock(QtWidgets.QDockWidget): grid.addWidget(self.table, 1, 0) self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + create_action = QtWidgets.QAction("New dataset", self.table) + create_action.triggered.connect(self.create_clicked) + create_action.setShortcut("CTRL+N") + create_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + self.table.addAction(create_action) edit_action = QtWidgets.QAction("Edit dataset", self.table) edit_action.triggered.connect(self.edit_clicked) edit_action.setShortcut("RETURN") @@ -146,6 +214,9 @@ class DatasetsDock(QtWidgets.QDockWidget): self.table_model_filter.setSourceModel(self.table_model) self.table.setModel(self.table_model_filter) + def create_clicked(self): + Creator(self, self.dataset_ctl).open() + def edit_clicked(self): idx = self.table.selectedIndexes() if idx: From bc7ce7d6aa9a730e59c9e758c21ec435df23a0b6 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 14 Jul 2021 08:27:08 +0800 Subject: [PATCH 016/238] doc: mention Vivado version from vivado.nix. Closes #1715 --- doc/manual/developing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/developing.rst b/doc/manual/developing.rst index 350bc2ac4..1eec41dd5 100644 --- a/doc/manual/developing.rst +++ b/doc/manual/developing.rst @@ -7,12 +7,12 @@ Developing ARTIQ The easiest way to obtain an ARTIQ development environment is via the Nix package manager on Linux. The Nix system is used on the `M-Labs Hydra server `_ to build ARTIQ and its dependencies continuously; it ensures that all build instructions are up-to-date and allows binary packages to be used on developers' machines, in particular for large tools such as the Rust compiler. ARTIQ itself does not depend on Nix, and it is also possible to compile everything from source (look into the ``.nix`` files from the ``nix-scripts`` repository and run the commands manually) - but Nix makes the process a lot easier. -* Download Vivado from Xilinx and install it (by running the official installer in a FHS chroot environment if using NixOS). If you do not want to write to ``/opt``, you can install it in a folder of your home directory. The "appropriate" Vivado version to use for building the bitstream can vary. Some versions contain bugs that lead to hidden or visible failures, others work fine. Refer to the `M-Labs Hydra logs `_ to determine which version is currently used when building the binary packages. If the Vivado GUI installer crashes, you may be able to work around the problem by running it in unattended mode with a command such as ``./xsetup -a XilinxEULA,3rdPartyEULA,WebTalkTerms -b Install -e 'Vitis Unified Software Platform' -l /opt/Xilinx/``. +* Download Vivado from Xilinx and install it (by running the official installer in a FHS chroot environment if using NixOS). If you do not want to write to ``/opt``, you can install it in a folder of your home directory. The "appropriate" Vivado version to use for building the bitstream can vary. Some versions contain bugs that lead to hidden or visible failures, others work fine. Refer to `Hydra `_ and/or the ``vivado.nix`` file from the ``nix-scripts`` repository in order to determine which version is used at M-Labs. If the Vivado GUI installer crashes, you may be able to work around the problem by running it in unattended mode with a command such as ``./xsetup -a XilinxEULA,3rdPartyEULA,WebTalkTerms -b Install -e 'Vitis Unified Software Platform' -l /opt/Xilinx/``. * During the Vivado installation, uncheck ``Install cable drivers`` (they are not required as we use better and open source alternatives). * Install the `Nix package manager `_ and Git (e.g. ``$ nix-shell -p git``). * Set up the M-Labs binary substituter (:ref:`same procedure as the user section `) to allow binaries to be downloaded. Otherwise, tools such as LLVM and the Rust compiler will be compiled on your machine, which uses a lot of CPU time, memory, and disk space. * Clone the repositories https://github.com/m-labs/artiq and https://git.m-labs.hk/m-labs/nix-scripts. -* If you did not install Vivado in its default location ``/opt``, edit the Nix files accordingly. +* If you did not install Vivado in its default location ``/opt``, edit ``vivado.nix`` accordingly. * Run ``$ nix-shell -I artiqSrc=path_to_artiq_sources shell-dev.nix`` to obtain an environment containing all the required development tools (e.g. Migen, MiSoC, Clang, Rust, OpenOCD...) in addition to the ARTIQ user environment. ``artiqSrc`` should point to the root of the cloned ``artiq`` repository, and ``shell-dev.nix`` can be found in the ``artiq-fast`` folder of the ``nix-scripts`` repository. * You can then build the firmware and gateware with a command such as ``$ python -m artiq.gateware.targets.kasli``. If you are using a JSON system description file, use ``$ python -m artiq.gateware.targets.kasli_generic file.json``. * Flash the binaries into the FPGA board with a command such as ``$ artiq_flash --srcbuild -d artiq_kasli -V ``. You need to configure OpenOCD as explained :ref:`in the user section `. OpenOCD is already part of the shell started by ``shell-dev.nix``. From d327d2a505763c7a69dba9649341922a037d3745 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 14 Jul 2021 08:32:03 +0800 Subject: [PATCH 017/238] doc: document shell-dev shortcut --- doc/manual/developing.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/manual/developing.rst b/doc/manual/developing.rst index 1eec41dd5..fa26c14fd 100644 --- a/doc/manual/developing.rst +++ b/doc/manual/developing.rst @@ -19,5 +19,10 @@ ARTIQ itself does not depend on Nix, and it is also possible to compile everythi * Check that the board boots and examine the UART messages by running a serial terminal program, e.g. ``$ flterm /dev/ttyUSB1`` (``flterm`` is part of MiSoC and installed by ``shell-dev.nix``). Leave the terminal running while you are flashing the board, so that you see the startup messages when the board boots immediately after flashing. You can also restart the board (without reflashing it) with ``$ artiq_flash start``. * The communication parameters are 115200 8-N-1. Ensure that your user has access to the serial device (e.g. by adding the user account to the ``dialout`` group). + +.. note:: + If you do not plan to modify ``nix-scripts``, with the ARTIQ channel configured you can simply enter the development Nix shell with ``nix-shell ""``. No repositories need to be cloned. This is especially useful if you simply want to build firmware using an unmodified version of ARTIQ. + + .. warning:: Nix will make a read-only copy of the ARTIQ source to use in the shell environment. Therefore, any modifications that you make to the source after the shell is started will not be taken into account. A solution applicable to ARTIQ (and several other Python packages such as Migen and MiSoC) is to prepend the ARTIQ source directory to the ``PYTHONPATH`` environment variable after entering the shell. If you want this to be done by default, edit ``profile`` in ``shell-dev.nix``. From 5cd721c514394fa9008d7214f5bec9eb3173a7a7 Mon Sep 17 00:00:00 2001 From: Star Chen Date: Wed, 14 Jul 2021 15:57:55 +0800 Subject: [PATCH 018/238] applets: add plot_hist dataset length mismatch warning (#1718) --- artiq/applets/plot_hist.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/artiq/applets/plot_hist.py b/artiq/applets/plot_hist.py index dc46997b9..71f227ac3 100755 --- a/artiq/applets/plot_hist.py +++ b/artiq/applets/plot_hist.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 -import PyQt5 # make sure pyqtgraph imports Qt5 +import PyQt5 # make sure pyqtgraph imports Qt5 +from PyQt5.QtCore import QTimer import pyqtgraph from artiq.applets.simple import TitleApplet @@ -10,6 +11,9 @@ class HistogramPlot(pyqtgraph.PlotWidget): def __init__(self, args): pyqtgraph.PlotWidget.__init__(self) self.args = args + self.timer = QTimer() + self.timer.setSingleShot(True) + self.timer.timeout.connect(self.length_warning) def data_changed(self, data, mods, title): try: @@ -24,10 +28,19 @@ class HistogramPlot(pyqtgraph.PlotWidget): x = list(range(len(y)+1)) if len(y) and len(x) == len(y) + 1: + self.timer.stop() self.clear() self.plot(x, y, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150)) self.setTitle(title) + else: + self.timer.start(1000) + + def length_warning(self): + self.clear() + text = "⚠️ dataset lengths mismatch:\n"\ + "There should be one more bin boundaries than there are Y values" + self.addItem(pyqtgraph.TextItem(text)) def main(): From 4fb8ea5b7332a74b43e4f2c023aa39e88ad99dba Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 14 Jul 2021 16:43:00 +0800 Subject: [PATCH 019/238] artiq_flash: determine which firmware to flash by looking at filesystem Closes #1719 --- artiq/frontend/artiq_flash.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index 8868b3fda..fab1db63e 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -446,13 +446,17 @@ def main(): storage_img = args.storage programmer.write_binary(*config["storage"], storage_img) elif action == "firmware": - if variant.endswith("satellite"): - firmware = "satman" - else: - firmware = "runtime" - - firmware_fbi = artifact_path(variant_dir, "software", firmware, firmware + ".fbi") - programmer.write_binary(*config["firmware"], firmware_fbi) + firmware_fbis = [] + for firmware in "satman", "runtime": + filename = artifact_path(variant_dir, "software", firmware, firmware + ".fbi") + if os.path.exists(filename): + firmware_fbis.append(filename) + if not firmware_fbis: + raise FileNotFoundError("no firmware found") + if len(firmware_fbis) > 1: + raise ValueError("more than one firmware file, please clean up your build directory. " + "Found firmware files: {}".format(" ".join(firmware_fbis))) + programmer.write_binary(*config["firmware"], firmware_fbis[0]) elif action == "load": if args.target == "sayma": gateware_bit = artifact_path(variant_dir, "gateware", "top.bit") From 796aeabb53bff62fcd2e80fd9d80054eb3f394e7 Mon Sep 17 00:00:00 2001 From: StarChen Date: Mon, 19 Jul 2021 12:05:24 +0800 Subject: [PATCH 020/238] documentation: correct artiq_coremgmt examples --- doc/manual/utilities.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/utilities.rst b/doc/manual/utilities.rst index 9e056e55e..5efe5baf3 100644 --- a/doc/manual/utilities.rst +++ b/doc/manual/utilities.rst @@ -81,11 +81,11 @@ You can write several records at once:: To remove the previously written key ``my_key``:: - $ artiq_coremgmt config delete my_key + $ artiq_coremgmt config remove my_key You can remove several keys at once:: - $ artiq_coremgmt config delete key1 key2 + $ artiq_coremgmt config remove key1 key2 To erase the entire flash storage area:: From e996b5f635ee158140378985ba0c3d80b23eb279 Mon Sep 17 00:00:00 2001 From: Star Chen Date: Mon, 19 Jul 2021 12:26:01 +0800 Subject: [PATCH 021/238] applets: fix warning timing --- artiq/applets/plot_hist.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/artiq/applets/plot_hist.py b/artiq/applets/plot_hist.py index 71f227ac3..b3493c836 100755 --- a/artiq/applets/plot_hist.py +++ b/artiq/applets/plot_hist.py @@ -34,7 +34,8 @@ class HistogramPlot(pyqtgraph.PlotWidget): brush=(0, 0, 255, 150)) self.setTitle(title) else: - self.timer.start(1000) + if not self.timer.isActive(): + self.timer.start(1000) def length_warning(self): self.clear() From 943a95e07a138f272a925559276fe2673d6af610 Mon Sep 17 00:00:00 2001 From: Star Chen Date: Mon, 19 Jul 2021 15:14:15 +0800 Subject: [PATCH 022/238] applets: add data length warning message for `plot_xy` (#1722) --- artiq/applets/plot_xy.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/artiq/applets/plot_xy.py b/artiq/applets/plot_xy.py index da7f2197d..8eaf9786a 100755 --- a/artiq/applets/plot_xy.py +++ b/artiq/applets/plot_xy.py @@ -2,6 +2,7 @@ import numpy as np import PyQt5 # make sure pyqtgraph imports Qt5 +from PyQt5.QtCore import QTimer import pyqtgraph from artiq.applets.simple import TitleApplet @@ -11,6 +12,12 @@ class XYPlot(pyqtgraph.PlotWidget): def __init__(self, args): pyqtgraph.PlotWidget.__init__(self) self.args = args + self.timer = QTimer() + self.timer.setSingleShot(True) + self.timer.timeout.connect(self.length_warning) + self.mismatch = {'X values': False, + 'Error bars': False, + 'Fit values': False} def data_changed(self, data, mods, title): try: @@ -24,17 +31,29 @@ class XYPlot(pyqtgraph.PlotWidget): fit = data.get(self.args.fit, (False, None))[1] if not len(y) or len(y) != len(x): - return + self.mismatch['X values'] = True + else: + self.mismatch['X values'] = False if error is not None and hasattr(error, "__len__"): if not len(error): error = None elif len(error) != len(y): - return + self.mismatch['Error bars'] = True + else: + self.mismatch['Error bars'] = False if fit is not None: if not len(fit): fit = None elif len(fit) != len(y): - return + self.mismatch['Fit values'] = True + else: + self.mismatch['Fit values'] = False + if not any(self.mismatch.values()): + self.timer.stop() + else: + if not self.timer.isActive(): + self.timer.start(1000) + return self.clear() self.plot(x, y, pen=None, symbol="x") @@ -50,6 +69,13 @@ class XYPlot(pyqtgraph.PlotWidget): xi = np.argsort(x) self.plot(x[xi], fit[xi]) + def length_warning(self): + self.clear() + text = "⚠️ dataset lengths mismatch:\n" + errors = ', '.join([k for k, v in self.mismatch.items() if v]) + text = ' '.join([errors, "should have the same length as Y values"]) + self.addItem(pyqtgraph.TextItem(text)) + def main(): applet = TitleApplet(XYPlot) From ebb67eaeee8386cb03efbb543950968b3be55981 Mon Sep 17 00:00:00 2001 From: Star Chen Date: Mon, 19 Jul 2021 15:45:48 +0800 Subject: [PATCH 023/238] applets: add length warning message on plot for `plot_xy_hist` and fix bug (#1725) --- artiq/applets/plot_xy_hist.py | 54 +++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/artiq/applets/plot_xy_hist.py b/artiq/applets/plot_xy_hist.py index 7b8135561..39bd49098 100755 --- a/artiq/applets/plot_xy_hist.py +++ b/artiq/applets/plot_xy_hist.py @@ -2,6 +2,7 @@ import numpy as np from PyQt5 import QtWidgets +from PyQt5.QtCore import QTimer import pyqtgraph from artiq.applets.simple import SimpleApplet @@ -37,6 +38,10 @@ class XYHistPlot(QtWidgets.QSplitter): self.hist_plot_data = None self.args = args + self.timer = QTimer() + self.timer.setSingleShot(True) + self.timer.timeout.connect(self.length_warning) + self.mismatch = {'bins': False, 'xs': False} def _set_full_data(self, xs, histogram_bins, histograms_counts): self.xy_plot.clear() @@ -59,9 +64,9 @@ class XYHistPlot(QtWidgets.QSplitter): point.histogram_index = index point.histogram_counts = counts - self.hist_plot_data = self.hist_plot.plot( - stepMode=True, fillLevel=0, - brush=(0, 0, 255, 150)) + text = "click on a data point at the left\n"\ + "to see the corresponding histogram" + self.hist_plot.addItem(pyqtgraph.TextItem(text)) def _set_partial_data(self, xs, histograms_counts): ys = _compute_ys(self.histogram_bins, histograms_counts) @@ -87,8 +92,17 @@ class XYHistPlot(QtWidgets.QSplitter): else: self.arrow.setPos(position) self.selected_index = spot_item.histogram_index - self.hist_plot_data.setData(x=self.histogram_bins, - y=spot_item.histogram_counts) + + if self.hist_plot_data is None: + self.hist_plot.clear() + self.hist_plot_data = self.hist_plot.plot( + x=self.histogram_bins, + y=spot_item.histogram_counts, + stepMode=True, fillLevel=0, + brush=(0, 0, 255, 150)) + else: + self.hist_plot_data.setData(x=self.histogram_bins, + y=spot_item.histogram_counts) def _can_use_partial(self, mods): if self.hist_plot_data is None: @@ -117,11 +131,41 @@ class XYHistPlot(QtWidgets.QSplitter): histograms_counts = data[self.args.histograms_counts][1] except KeyError: return + if len(xs) != histograms_counts.shape[0]: + self.mismatch['xs'] = True + else: + self.mismatch['xs'] = False + if histograms_counts.shape[1] != len(histogram_bins) - 1: + self.mismatch['bins'] = True + else: + self.mismatch['bins'] = False + if any(self.mismatch.values()): + if not self.timer.isActive(): + self.timer.start(1000) + return + else: + self.timer.stop() if self._can_use_partial(mods): self._set_partial_data(xs, histograms_counts) else: self._set_full_data(xs, histogram_bins, histograms_counts) + def length_warning(self): + self.xy_plot.clear() + self.hist_plot.clear() + text = "⚠️ dataset lengths mismatch:\n\n" + if self.mismatch['bins']: + text = ''.join([text, + "bin boundaries should have the same length\n" + "as the first dimension of histogram counts."]) + if self.mismatch['bins'] and self.mismatch['xs']: + text = ''.join([text, '\n\n']) + if self.mismatch['xs']: + text = ''.join([text, + "point abscissas should have the same length\n" + "as the second dimension of histogram counts."]) + self.xy_plot.addItem(pyqtgraph.TextItem(text)) + def main(): applet = SimpleApplet(XYHistPlot) From 30e5e06a33b3c5d78bd797aaf5b4e33a85def287 Mon Sep 17 00:00:00 2001 From: Star Chen Date: Thu, 22 Jul 2021 17:56:38 +0800 Subject: [PATCH 024/238] moninj: fix read of incomplete data (#1729) --- artiq/coredevice/comm_moninj.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/coredevice/comm_moninj.py b/artiq/coredevice/comm_moninj.py index 0c3a577dc..392ad701a 100644 --- a/artiq/coredevice/comm_moninj.py +++ b/artiq/coredevice/comm_moninj.py @@ -82,12 +82,12 @@ class CommMonInj: if not ty: return if ty == b"\x00": - payload = await self._reader.read(9) + payload = await self._reader.readexactly(9) channel, probe, value = struct.unpack( self.endian + "lbl", payload) self.monitor_cb(channel, probe, value) elif ty == b"\x01": - payload = await self._reader.read(6) + payload = await self._reader.readexactly(6) channel, override, value = struct.unpack( self.endian + "lbb", payload) self.injection_status_cb(channel, override, value) From 53a98acfe4956010b0a1aca012cd2474c4cc03ea Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 26 Jul 2021 17:01:24 +0800 Subject: [PATCH 025/238] artiq_flash: cleanup openocd handling, do not follow symlinks Not following symlinks allows files to be added to OpenOCD via nixpkgs buildEnv. --- artiq/frontend/artiq_flash.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index fab1db63e..d7a5bdb78 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -79,28 +79,22 @@ Prerequisites: help="actions to perform, default: flash everything") return parser -def which_openocd(): +def openocd_root(): openocd = shutil.which("openocd") if not openocd: raise FileNotFoundError("OpenOCD is required but was not found in PATH. Is it installed?") - return openocd + return os.path.dirname(os.path.dirname(openocd)) + def scripts_path(): p = ["share", "openocd", "scripts"] if os.name == "nt": p.insert(0, "Library") - p = os.path.abspath(os.path.join( - os.path.dirname(os.path.realpath(which_openocd())), - "..", *p)) - return p + return os.path.abspath(os.path.join(openocd_root(), *p)) def proxy_path(): - p = ["share", "bscan-spi-bitstreams"] - p = os.path.abspath(os.path.join( - os.path.dirname(os.path.realpath(which_openocd())), - "..", *p)) - return p + return os.path.abspath(os.path.join(openocd_root(), "share", "bscan-spi-bitstreams")) def find_proxy_bitfile(filename): From 1e869aedd3d4edaf38d6d1d16e40da3c36aa153c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Tue, 3 Aug 2021 11:36:04 +0200 Subject: [PATCH 026/238] docs: clarify rtio_clock=e req's and use case This regularly leads to people misunderstanding the setting. Mentioning the Si5324 specifically or Urukul synchronization doesn't help constraining or explaining the feature, its consequences and requirements. Despite being non-standard this feature is also generally not sufficient to achieve cross-device determinism as the other devices need to be made deterministic as well. --- doc/manual/core_device.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/core_device.rst b/doc/manual/core_device.rst index 9488e4d33..bb38c2b9e 100644 --- a/doc/manual/core_device.rst +++ b/doc/manual/core_device.rst @@ -164,6 +164,6 @@ See :mod:`artiq.coredevice.i2c` for more details. Clocking ++++++++ -The KC705 supports an internal 125MHz RTIO clock (based on its crystal oscillator) and an external clock, that can be selected using the ``rtio_clock`` configuration entry. Valid values are ``i`` and ``e``, and the default is ``i``. The selected option can be observed in the core device boot logs. +The KC705 supports an internal 125 MHz RTIO clock (based on its crystal oscillator) and an external clock, that can be selected using the ``rtio_clock`` configuration entry. Valid values are ``i`` and ``e``, and the default is ``i``. The selected option can be observed in the core device boot logs. -On Kasli, when set to ``e``, the ``rtio_clock`` setting overrides the built-in (and variant-dependent) Si5324 synthesizer configuration and disables the Si5324. The user must apply a clock at the RTIO frequency on the Kasli front panel SMA. As the Si5324 is bypassed in this mode, its skew is deterministic, which is useful to distribute clocks externally to Kasli and Urukul when Urukul phase synchronization is desired. +On Kasli, ``rtio_clock=i`` is the default and generates the RTIO clock using a PLL locked either to an internal crystal or to an external frequency reference (variant-dependent). ``rtio_clock=e`` bypasses that PLL and the user must supply the RTIO clock (typically 125 MHz) at the Kasli front panel SMA input. Bypassing the PLL ensures the skews between input clock, Kasli downstream clock outputs, and RTIO clock are deterministic accross reboots of the system. This is useful when phase determinism is required in situtations where the reference clock fans out to other devices before reaching Kasli. From c3d765f74543f1b395a02835e16afb5de267664a Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 5 Aug 2021 11:30:54 +0800 Subject: [PATCH 027/238] ad9910: fix type annotations --- artiq/coredevice/ad9910.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/coredevice/ad9910.py b/artiq/coredevice/ad9910.py index f0cb8e54e..95ad66896 100644 --- a/artiq/coredevice/ad9910.py +++ b/artiq/coredevice/ad9910.py @@ -324,7 +324,7 @@ class AD9910: self.bus.write(data_low) @kernel - def write_ram(self, data: TList(int32)): + def write_ram(self, data: TList(TInt32)): """Write data to RAM. The profile to write to and the step, start, and end address @@ -345,7 +345,7 @@ class AD9910: self.bus.write(data[len(data) - 1]) @kernel - def read_ram(self, data: TList(int32)): + def read_ram(self, data: TList(TInt32)): """Read data from RAM. The profile to read from and the step, start, and end address From 97e994700bc98f1d7376c184efda87b4919bdea0 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 5 Aug 2021 11:32:20 +0800 Subject: [PATCH 028/238] compiler: turn __repr__ into __str__ when sphinx is used. Closes #741 --- artiq/compiler/types.py | 21 +++++++++++++++++++++ doc/manual/conf.py | 7 +++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/artiq/compiler/types.py b/artiq/compiler/types.py index 78364101b..b5a220aeb 100644 --- a/artiq/compiler/types.py +++ b/artiq/compiler/types.py @@ -3,6 +3,7 @@ The :mod:`types` module contains the classes describing the types in :mod:`asttyped`. """ +import builtins import string from collections import OrderedDict from . import iodelay @@ -96,6 +97,8 @@ class TVar(Type): return self.find().fold(accum, fn) def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) if self.parent is self: return "" % id(self) else: @@ -142,6 +145,8 @@ class TMono(Type): return fn(accum, self) def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) return "artiq.compiler.types.TMono(%s, %s)" % (repr(self.name), repr(self.params)) def __getitem__(self, param): @@ -190,6 +195,8 @@ class TTuple(Type): return fn(accum, self) def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) return "artiq.compiler.types.TTuple(%s)" % repr(self.elts) def __eq__(self, other): @@ -268,6 +275,8 @@ class TFunction(Type): return fn(accum, self) def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) return "artiq.compiler.types.TFunction({}, {}, {})".format( repr(self.args), repr(self.optargs), repr(self.ret)) @@ -361,6 +370,8 @@ class TRPC(Type): return fn(accum, self) def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) return "artiq.compiler.types.TRPC({})".format(repr(self.ret)) def __eq__(self, other): @@ -398,6 +409,8 @@ class TBuiltin(Type): return fn(accum, self) def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) return "artiq.compiler.types.{}({})".format(type(self).__name__, repr(self.name)) def __eq__(self, other): @@ -458,6 +471,8 @@ class TInstance(TMono): self.constant_attributes = set() def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) return "artiq.compiler.types.TInstance({}, {})".format( repr(self.name), repr(self.attributes)) @@ -473,6 +488,8 @@ class TModule(TMono): self.constant_attributes = set() def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) return "artiq.compiler.types.TModule({}, {})".format( repr(self.name), repr(self.attributes)) @@ -512,6 +529,8 @@ class TValue(Type): return fn(accum, self) def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) return "artiq.compiler.types.TValue(%s)" % repr(self.value) def __eq__(self, other): @@ -570,6 +589,8 @@ class TDelay(Type): return not (self == other) def __repr__(self): + if getattr(builtins, "__in_sphinx__", False): + return str(self) if self.duration is None: return "<{}.TIndeterminateDelay>".format(__name__) elif self.cause is None: diff --git a/doc/manual/conf.py b/doc/manual/conf.py index 997801987..509816e80 100644 --- a/doc/manual/conf.py +++ b/doc/manual/conf.py @@ -20,11 +20,10 @@ from unittest.mock import Mock import sphinx_rtd_theme -# Hack-patch Sphinx so that ARTIQ-Python types are correctly printed +# Ensure that ARTIQ-Python types are correctly printed # See: https://github.com/m-labs/artiq/issues/741 -from sphinx.ext import autodoc -from sphinx.util import inspect -autodoc.repr = inspect.repr = str +import builtins +builtins.__in_sphinx__ = True # we cannot use autodoc_mock_imports (does not help with argparse) From 6b88ea563d80145ffe42c50c6bfb9d3229cdb70c Mon Sep 17 00:00:00 2001 From: Star Chen Date: Thu, 5 Aug 2021 17:00:31 +0800 Subject: [PATCH 029/238] talk to ICAP primitive to restart gateware (#1733) --- artiq/coredevice/comm_mgmt.py | 6 ---- artiq/firmware/libboard_misoc/or1k/boot.rs | 38 --------------------- artiq/firmware/libboard_misoc/spiflash.rs | 5 +++ artiq/firmware/libproto_artiq/mgmt_proto.rs | 2 -- artiq/firmware/runtime/main.rs | 6 ++-- artiq/firmware/runtime/mgmt.rs | 13 ++----- artiq/frontend/artiq_coremgmt.py | 11 +----- 7 files changed, 11 insertions(+), 70 deletions(-) diff --git a/artiq/coredevice/comm_mgmt.py b/artiq/coredevice/comm_mgmt.py index 79fde1a81..6a268c8e1 100644 --- a/artiq/coredevice/comm_mgmt.py +++ b/artiq/coredevice/comm_mgmt.py @@ -24,7 +24,6 @@ class Request(Enum): StopProfiler = 10 GetProfile = 11 - Hotswap = 4 Reboot = 5 DebugAllocator = 8 @@ -224,11 +223,6 @@ class CommMgmt: return hits, edges - def hotswap(self, firmware): - self._write_header(Request.Hotswap) - self._write_bytes(firmware) - self._read_expect(Reply.RebootImminent) - def reboot(self): self._write_header(Request.Reboot) self._read_expect(Reply.RebootImminent) diff --git a/artiq/firmware/libboard_misoc/or1k/boot.rs b/artiq/firmware/libboard_misoc/or1k/boot.rs index 51a368e6e..a967c3e66 100644 --- a/artiq/firmware/libboard_misoc/or1k/boot.rs +++ b/artiq/firmware/libboard_misoc/or1k/boot.rs @@ -1,14 +1,5 @@ use super::{irq, cache}; -pub unsafe fn reset() -> ! { - irq::set_ie(false); - asm!(r#" - l.j _reset_handler - l.nop - "# : : : : "volatile"); - loop {} -} - pub unsafe fn jump(addr: usize) -> ! { irq::set_ie(false); cache::flush_cpu_icache(); @@ -18,32 +9,3 @@ pub unsafe fn jump(addr: usize) -> ! { "# : : "r"(addr) : : "volatile"); loop {} } - -pub unsafe fn hotswap(firmware: &[u8]) -> ! { - irq::set_ie(false); - asm!(r#" - # This loop overwrites itself, but it's structured in such a way - # that before that happens, it loads itself into I$$ fully. - l.movhi r4, hi(_reset_handler) - l.ori r4, r4, lo(_reset_handler) - l.or r7, r4, r0 - 0: l.sfnei r5, 0 - l.bf 1f - l.nop - l.jr r7 - l.nop - 1: l.lwz r6, 0(r3) - l.sw 0(r4), r6 - l.addi r3, r3, 4 - l.addi r4, r4, 4 - l.addi r5, r5, -4 - l.bf 0b - l.nop - "# - : - : "{r3}"(firmware.as_ptr() as usize), - "{r5}"(firmware.len()) - : - : "volatile"); - loop {} -} diff --git a/artiq/firmware/libboard_misoc/spiflash.rs b/artiq/firmware/libboard_misoc/spiflash.rs index 3a4e7cb59..7b1244775 100644 --- a/artiq/firmware/libboard_misoc/spiflash.rs +++ b/artiq/firmware/libboard_misoc/spiflash.rs @@ -113,3 +113,8 @@ pub unsafe fn write(mut addr: usize, mut data: &[u8]) { data = &data[size..]; } } + +pub unsafe fn reload () -> ! { + csr::icap::iprog_write(1); + loop {} +} diff --git a/artiq/firmware/libproto_artiq/mgmt_proto.rs b/artiq/firmware/libproto_artiq/mgmt_proto.rs index ffa2a9763..c5937fac6 100644 --- a/artiq/firmware/libproto_artiq/mgmt_proto.rs +++ b/artiq/firmware/libproto_artiq/mgmt_proto.rs @@ -71,7 +71,6 @@ pub enum Request { StopProfiler, GetProfile, - Hotswap(Vec), Reboot, DebugAllocator, @@ -138,7 +137,6 @@ impl Request { 10 => Request::StopProfiler, 11 => Request::GetProfile, - 4 => Request::Hotswap(reader.read_bytes()?), 5 => Request::Reboot, 8 => Request::DebugAllocator, diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 91646cc5e..df103d7ef 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -30,7 +30,7 @@ use core::cell::RefCell; use core::convert::TryFrom; use smoltcp::wire::IpCidr; -use board_misoc::{csr, irq, ident, clock, boot, config, net_settings}; +use board_misoc::{csr, irq, ident, clock, spiflash, config, net_settings}; #[cfg(has_ethmac)] use board_misoc::ethmac; #[cfg(has_drtio)] @@ -332,11 +332,11 @@ pub fn panic_impl(info: &core::panic::PanicInfo) -> ! { println!("{:#08x}", ip - 2 * 4); }); - if config::read_str("panic_reset", |r| r == Ok("1")) { + if config::read_str("panic_reset", |r| r == Ok("1")) && cfg!(has_spiflash) { println!("restarting..."); unsafe { kernel::stop(); - boot::reset(); + spiflash::reload(); } } else { println!("halting."); diff --git a/artiq/firmware/runtime/mgmt.rs b/artiq/firmware/runtime/mgmt.rs index 3a16e94aa..2f632a7da 100644 --- a/artiq/firmware/runtime/mgmt.rs +++ b/artiq/firmware/runtime/mgmt.rs @@ -1,7 +1,7 @@ use log::{self, LevelFilter}; use io::{Write, ProtoWrite, Error as IoError}; -use board_misoc::{config, boot}; +use board_misoc::{config, spiflash}; use logger_artiq::BufferLogger; use mgmt_proto::*; use sched::{Io, TcpListener, TcpStream, Error as SchedError}; @@ -144,15 +144,6 @@ fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error> { })?; } - Request::Hotswap(firmware) => { - Reply::RebootImminent.write_to(stream)?; - stream.close()?; - stream.flush()?; - - profiler::stop(); - warn!("hotswapping firmware"); - unsafe { boot::hotswap(&firmware) } - } Request::Reboot => { Reply::RebootImminent.write_to(stream)?; stream.close()?; @@ -160,7 +151,7 @@ fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error> { profiler::stop(); warn!("restarting"); - unsafe { boot::reset() } + unsafe { spiflash::reload(); } } Request::DebugAllocator => diff --git a/artiq/frontend/artiq_coremgmt.py b/artiq/frontend/artiq_coremgmt.py index 542e12925..39baf26cf 100755 --- a/artiq/frontend/artiq_coremgmt.py +++ b/artiq/frontend/artiq_coremgmt.py @@ -84,13 +84,7 @@ def get_argparser(): # booting t_boot = tools.add_parser("reboot", - help="reboot the currently running firmware") - - t_hotswap = tools.add_parser("hotswap", - help="load the specified firmware in RAM") - - t_hotswap.add_argument("image", metavar="IMAGE", type=argparse.FileType("rb"), - help="runtime image to be executed") + help="reboot the running system") # profiling t_profile = tools.add_parser("profile", @@ -180,9 +174,6 @@ def main(): if args.tool == "reboot": mgmt.reboot() - if args.tool == "hotswap": - mgmt.hotswap(args.image.read()) - if args.tool == "profile": if args.action == "start": mgmt.start_profiler(args.interval, args.hits_size, args.edges_size) From c9608c0a89c146fff66b7918f3e3ed349d52ab5f Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Thu, 5 Aug 2021 16:54:36 +0800 Subject: [PATCH 030/238] zotino: default div_read unified with ad53xx at 16, fix ad53xx doc --- artiq/coredevice/ad53xx.py | 6 +++--- artiq/coredevice/zotino.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/artiq/coredevice/ad53xx.py b/artiq/coredevice/ad53xx.py index 3445555d9..9a2b8eb2e 100644 --- a/artiq/coredevice/ad53xx.py +++ b/artiq/coredevice/ad53xx.py @@ -127,9 +127,9 @@ class AD53xx: transactions (default: 1) :param div_write: SPI clock divider for write operations (default: 4, 50MHz max SPI clock with {t_high, t_low} >=8ns) - :param div_read: SPI clock divider for read operations (default: 8, not - optimized for speed, but cf data sheet t22: 25ns min SCLK edge to SDO - valid) + :param div_read: SPI clock divider for read operations (default: 16, not + optimized for speed; datasheet says t22: 25ns min SCLK edge to SDO + valid, and suggests the SPI speed for reads should be <=20 MHz) :param vref: DAC reference voltage (default: 5.) :param offset_dacs: Initial register value for the two offset DACs, device dependent and must be set correctly for correct voltage to mu diff --git a/artiq/coredevice/zotino.py b/artiq/coredevice/zotino.py index e56842be5..9052f589a 100644 --- a/artiq/coredevice/zotino.py +++ b/artiq/coredevice/zotino.py @@ -27,15 +27,15 @@ class Zotino(AD53xx): :param clr_device: CLR RTIO TTLOut channel name. :param div_write: SPI clock divider for write operations (default: 4, 50MHz max SPI clock) - :param div_read: SPI clock divider for read operations (default: 8, not - optimized for speed, but cf data sheet t22: 25ns min SCLK edge to SDO - valid) + :param div_read: SPI clock divider for read operations (default: 16, not + optimized for speed; datasheet says t22: 25ns min SCLK edge to SDO + valid, and suggests the SPI speed for reads should be <=20 MHz) :param vref: DAC reference voltage (default: 5.) :param core_device: Core device name (default: "core") """ def __init__(self, dmgr, spi_device, ldac_device=None, clr_device=None, - div_write=4, div_read=8, vref=5., core="core"): + div_write=4, div_read=16, vref=5., core="core"): AD53xx.__init__(self, dmgr=dmgr, spi_device=spi_device, ldac_device=ldac_device, clr_device=clr_device, chip_select=_SPI_CS_DAC, div_write=div_write, From fd824f7ad0b2566d3cbfc373e8580c8aa3d63a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Thu, 5 Aug 2021 17:29:38 +0200 Subject: [PATCH 031/238] ddb_template: print LED channel nos on Kasli v2 --- artiq/gateware/targets/kasli_generic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/artiq/gateware/targets/kasli_generic.py b/artiq/gateware/targets/kasli_generic.py index 85fbdc70d..122c3e0cf 100755 --- a/artiq/gateware/targets/kasli_generic.py +++ b/artiq/gateware/targets/kasli_generic.py @@ -48,9 +48,10 @@ class GenericStandalone(StandaloneBase): self.rtio_channels.append(rtio.Channel.from_phy(phy)) if hw_rev == "v2.0": for i in (1, 2): + print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels))) phy = ttl_simple.Output(self.platform.request("user_led", i)) self.submodules += phy - self.rtio_channels.append(rtio.Channel.from_phy(phy)) + self.rtio_channels.append(rtio.Channel.from_phy(phy)) self.config["HAS_RTIO_LOG"] = None self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels) From dc546630e4ed070ba591d4c888ae49e4aaf3ee34 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 6 Aug 2021 14:41:41 +0800 Subject: [PATCH 032/238] kc705: DRTIO variants WIP --- artiq/gateware/targets/kc705.py | 419 ++++++++++++++---- artiq/gateware/targets/kc705_drtio_master.py | 180 -------- .../gateware/targets/kc705_drtio_satellite.py | 194 -------- 3 files changed, 334 insertions(+), 459 deletions(-) delete mode 100755 artiq/gateware/targets/kc705_drtio_master.py delete mode 100755 artiq/gateware/targets/kc705_drtio_satellite.py diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 1481fd351..0c1c431b6 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -11,12 +11,16 @@ from migen.build.xilinx.ise import XilinxISEToolchain from misoc.interconnect.csr import * from misoc.cores import gpio, timer -from misoc.targets.kc705 import MiniSoC, soc_kc705_args, soc_kc705_argdict +from misoc.targets.kc705 import BaseSoC, MiniSoC, soc_kc705_args, soc_kc705_argdict from misoc.integration.builder import builder_args, builder_argdict from artiq.gateware.amp import AMPSoC from artiq.gateware import rtio, nist_clock, nist_qc2 from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2 +from artiq.gateware.drtio.transceiver import gtx_7series +from artiq.gateware.drtio.siphaser import SiPhaser7Series +from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer +from artiq.gateware.drtio import * from artiq.build_soc import * @@ -109,7 +113,6 @@ _sdcard_spi_33 = [ ] - class _StandaloneBase(MiniSoC, AMPSoC): mem_map = { "cri_con": 0x10000000, @@ -187,13 +190,294 @@ class _StandaloneBase(MiniSoC, AMPSoC): self.csr_devices.append("rtio_analyzer") -class NIST_CLOCK(_StandaloneBase): +class _MasterBase(MiniSoC, AMPSoC): + mem_map = { + "cri_con": 0x10000000, + "rtio": 0x20000000, + "rtio_dma": 0x30000000, + "drtioaux": 0x50000000, + "mailbox": 0x70000000 + } + mem_map.update(MiniSoC.mem_map) + + def __init__(self, gateware_identifier_str=None, **kwargs): + MiniSoC.__init__(self, + cpu_type="or1k", + sdram_controller_type="minicon", + l2_size=128*1024, + integrated_sram_size=8192, + ethmac_nrxslots=4, + ethmac_ntxslots=4, + **kwargs) + AMPSoC.__init__(self) + add_identifier(self, gateware_identifier_str=gateware_identifier_str) + + if isinstance(self.platform.toolchain, XilinxVivadoToolchain): + self.platform.toolchain.bitstream_commands.extend([ + "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", + ]) + if isinstance(self.platform.toolchain, XilinxISEToolchain): + self.platform.toolchain.bitgen_opt += " -g compress" + + platform = self.platform + platform.add_extension(_sma33_io) + platform.add_extension(_ams101_dac) + platform.add_extension(_sdcard_spi_33) + + self.comb += platform.request("sfp_tx_disable_n").eq(1) + tx_pads = [ + platform.request("sfp_tx"), platform.request("user_sma_mgt_tx") + ] + rx_pads = [ + platform.request("sfp_rx"), platform.request("user_sma_mgt_rx") + ] + + # 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock + self.submodules.drtio_transceiver = gtx_7series.GTX( + clock_pads=platform.request("si5324_clkout"), + tx_pads=tx_pads, + rx_pads=rx_pads, + sys_clk_freq=self.clk_freq) + self.csr_devices.append("drtio_transceiver") + + self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) + + drtio_csr_group = [] + drtioaux_csr_group = [] + drtioaux_memory_group = [] + self.drtio_cri = [] + for i in range(len(self.drtio_transceiver.channels)): + core_name = "drtio" + str(i) + coreaux_name = "drtioaux" + str(i) + memory_name = "drtioaux" + str(i) + "_mem" + drtio_csr_group.append(core_name) + drtioaux_csr_group.append(coreaux_name) + drtioaux_memory_group.append(memory_name) + + cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)}) + + core = cdr(DRTIOMaster( + self.rtio_tsc, self.drtio_transceiver.channels[i])) + setattr(self.submodules, core_name, core) + self.drtio_cri.append(core.cri) + self.csr_devices.append(core_name) + + coreaux = cdr(DRTIOAuxController(core.link_layer)) + setattr(self.submodules, coreaux_name, coreaux) + self.csr_devices.append(coreaux_name) + + memory_address = self.mem_map["drtioaux"] + 0x800*i + self.add_wb_slave(memory_address, 0x800, + coreaux.bus) + self.add_memory_region(memory_name, memory_address | self.shadow_base, 0x800) + self.config["HAS_DRTIO"] = None + self.config["HAS_DRTIO_ROUTING"] = None + self.add_csr_group("drtio", drtio_csr_group) + self.add_csr_group("drtioaux", drtioaux_csr_group) + self.add_memory_group("drtioaux_mem", drtioaux_memory_group) + + self.config["RTIO_FREQUENCY"] = str(self.drtio_transceiver.rtio_clk_freq/1e6) + self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n) + self.csr_devices.append("si5324_rst_n") + i2c = self.platform.request("i2c") + self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) + self.csr_devices.append("i2c") + self.config["I2C_BUS_COUNT"] = 1 + self.config["HAS_SI5324"] = None + self.config["SI5324_AS_SYNTHESIZER"] = None + + self.comb += [ + platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")), + platform.request("user_sma_clock_n").eq(ClockSignal("rtio")) + ] + + rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq + # Constrain TX & RX timing for the first transceiver channel + # (First channel acts as master for phase alignment for all channels' TX) + gtx0 = self.drtio_transceiver.gtxs[0] + platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period) + platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period) + platform.add_false_path_constraints( + self.crg.cd_sys.clk, + gtx0.txoutclk, gtx0.rxoutclk) + # Constrain RX timing for the each transceiver channel + # (Each channel performs single-lane phase alignment for RX) + for gtx in self.drtio_transceiver.gtxs[1:]: + platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period) + platform.add_false_path_constraints( + self.crg.cd_sys.clk, gtx0.txoutclk, gtx.rxoutclk) + + def add_rtio(self, rtio_channels): + self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) + self.csr_devices.append("rtio_moninj") + + self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) + self.csr_devices.append("rtio_core") + + self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) + self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( + rtio.DMA(self.get_native_sdram_if())) + self.register_kernel_cpu_csrdevice("rtio") + self.register_kernel_cpu_csrdevice("rtio_dma") + self.submodules.cri_con = rtio.CRIInterconnectShared( + [self.rtio.cri, self.rtio_dma.cri], + [self.rtio_core.cri] + self.drtio_cri, + enable_routing=True) + self.register_kernel_cpu_csrdevice("cri_con") + self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) + self.csr_devices.append("routing_table") + + +class _SatelliteBase(BaseSoC): + mem_map = { + "drtioaux": 0x50000000, + } + mem_map.update(BaseSoC.mem_map) + + def __init__(self, gateware_identifier_str=None, sma_as_sat=False, **kwargs): + BaseSoC.__init__(self, + cpu_type="or1k", + sdram_controller_type="minicon", + l2_size=128*1024, + integrated_sram_size=8192, + **kwargs) + add_identifier(self, gateware_identifier_str=gateware_identifier_str) + + if isinstance(self.platform.toolchain, XilinxVivadoToolchain): + self.platform.toolchain.bitstream_commands.extend([ + "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", + ]) + if isinstance(self.platform.toolchain, XilinxISEToolchain): + self.platform.toolchain.bitgen_opt += " -g compress" + + platform = self.platform + platform.add_extension(_sma33_io) + platform.add_extension(_ams101_dac) + platform.add_extension(_sdcard_spi_33) + + self.comb += platform.request("sfp_tx_disable_n").eq(1) + tx_pads = [ + platform.request("sfp_tx"), platform.request("user_sma_mgt_tx") + ] + rx_pads = [ + platform.request("sfp_rx"), platform.request("user_sma_mgt_rx") + ] + if sma_as_sat: + tx_pads = tx_pads[::-1] + rx_pads = rx_pads[::-1] + + # 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock + self.submodules.drtio_transceiver = gtx_7series.GTX( + clock_pads=platform.request("si5324_clkout"), + tx_pads=tx_pads, + rx_pads=rx_pads, + sys_clk_freq=self.clk_freq) + self.csr_devices.append("drtio_transceiver") + + self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3) + + drtioaux_csr_group = [] + drtioaux_memory_group = [] + drtiorep_csr_group = [] + self.drtio_cri = [] + for i in range(len(self.drtio_transceiver.channels)): + coreaux_name = "drtioaux" + str(i) + memory_name = "drtioaux" + str(i) + "_mem" + drtioaux_csr_group.append(coreaux_name) + drtioaux_memory_group.append(memory_name) + + cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)}) + + # Satellite + if i == 0: + self.submodules.rx_synchronizer = cdr(XilinxRXSynchronizer()) + core = cdr(DRTIOSatellite( + self.rtio_tsc, self.drtio_transceiver.channels[0], self.rx_synchronizer)) + self.submodules.drtiosat = core + self.csr_devices.append("drtiosat") + # Repeaters + else: + corerep_name = "drtiorep" + str(i-1) + drtiorep_csr_group.append(corerep_name) + core = cdr(DRTIORepeater( + self.rtio_tsc, self.drtio_transceiver.channels[i])) + setattr(self.submodules, corerep_name, core) + self.drtio_cri.append(core.cri) + self.csr_devices.append(corerep_name) + + coreaux = cdr(DRTIOAuxController(core.link_layer)) + setattr(self.submodules, coreaux_name, coreaux) + self.csr_devices.append(coreaux_name) + + memory_address = self.mem_map["drtioaux"] + 0x800*i + self.add_wb_slave(memory_address, 0x800, + coreaux.bus) + self.add_memory_region(memory_name, memory_address | self.shadow_base, 0x800) + self.config["HAS_DRTIO"] = None + self.config["HAS_DRTIO_ROUTING"] = None + self.add_csr_group("drtioaux", drtioaux_csr_group) + self.add_memory_group("drtioaux_mem", drtioaux_memory_group) + self.add_csr_group("drtiorep", drtiorep_csr_group) + + self.config["RTIO_FREQUENCY"] = str(self.drtio_transceiver.rtio_clk_freq/1e6) + # Si5324 Phaser + self.submodules.siphaser = SiPhaser7Series( + si5324_clkin=platform.request("si5324_clkin"), + rx_synchronizer=self.rx_synchronizer, + ultrascale=False, + rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq) + platform.add_false_path_constraints( + self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) + self.csr_devices.append("siphaser") + self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n) + self.csr_devices.append("si5324_rst_n") + i2c = self.platform.request("i2c") + self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) + self.csr_devices.append("i2c") + self.config["I2C_BUS_COUNT"] = 1 + self.config["HAS_SI5324"] = None + + self.comb += [ + platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")), + platform.request("user_sma_clock_n").eq(ClockSignal("rtio")) + ] + + rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq + # Constrain TX & RX timing for the first transceiver channel + # (First channel acts as master for phase alignment for all channels' TX) + gtx0 = self.drtio_transceiver.gtxs[0] + platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period) + platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period) + platform.add_false_path_constraints( + self.crg.cd_sys.clk, + gtx0.txoutclk, gtx0.rxoutclk) + # Constrain RX timing for the each transceiver channel + # (Each channel performs single-lane phase alignment for RX) + for gtx in self.drtio_transceiver.gtxs[1:]: + platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period) + platform.add_false_path_constraints( + self.crg.cd_sys.clk, gtx.rxoutclk) + + def add_rtio(self, rtio_channels): + self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) + self.csr_devices.append("rtio_moninj") + + self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels) + self.comb += self.drtiosat.async_errors.eq(self.local_io.async_errors) + self.submodules.cri_con = rtio.CRIInterconnectShared( + [self.drtiosat.cri], + [self.local_io.cri] + self.drtio_cri, + mode="sync", enable_routing=True) + self.csr_devices.append("cri_con") + self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) + self.csr_devices.append("routing_table") + + +class _NIST_CLOCK_RTIO: """ NIST clock hardware, with old backplane and 11 DDS channels """ - def __init__(self, **kwargs): - _StandaloneBase.__init__(self, **kwargs) - + def __init__(self): platform = self.platform platform.add_extension(nist_clock.fmc_adapter_io) @@ -257,14 +541,12 @@ class NIST_CLOCK(_StandaloneBase): self.add_rtio(rtio_channels) -class NIST_QC2(_StandaloneBase): +class _NIST_QC2_RTIO: """ NIST QC2 hardware, as used in Quantum I and Quantum II, with new backplane and 24 DDS channels. Two backplanes are used. """ - def __init__(self, **kwargs): - _StandaloneBase.__init__(self, **kwargs) - + def __init__(self): platform = self.platform platform.add_extension(nist_qc2.fmc_adapter_io) @@ -327,94 +609,61 @@ class NIST_QC2(_StandaloneBase): self.add_rtio(rtio_channels) -_sma_spi = [ - ("sma_spi", 0, - Subsignal("clk", Pins("Y23")), # user_sma_gpio_p - Subsignal("cs_n", Pins("Y24")), # user_sma_gpio_n - Subsignal("mosi", Pins("L25")), # user_sma_clk_p - Subsignal("miso", Pins("K25")), # user_sma_clk_n - IOStandard("LVCMOS25")), -] - - -class SMA_SPI(_StandaloneBase): - """ - SPI on 4 SMA for PDQ2 test/demo. - """ +class NIST_CLOCK(_StandaloneBase, _NIST_CLOCK_RTIO): def __init__(self, **kwargs): _StandaloneBase.__init__(self, **kwargs) - - platform = self.platform - self.platform.add_extension(_sma_spi) - - rtio_channels = [] - - phy = ttl_simple.Output(platform.request("user_led", 2)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - ams101_dac = self.platform.request("ams101_dac", 0) - phy = ttl_simple.Output(ams101_dac.ldac) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - phy = spi2.SPIMaster(ams101_dac) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy( - phy, ififo_depth=4)) - - phy = spi2.SPIMaster(self.platform.request("sma_spi")) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy( - phy, ififo_depth=128)) - - self.config["HAS_RTIO_LOG"] = None - self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) - rtio_channels.append(rtio.LogChannel()) - - self.add_rtio(rtio_channels) - - def add_rtio(self, rtio_channels): - self.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk, - use_sma=False) - self.csr_devices.append("rtio_crg") - self.config["HAS_RTIO_CLOCK_SWITCH"] = None - self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) - self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) - self.csr_devices.append("rtio_core") - self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) - self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( - rtio.DMA(self.get_native_sdram_if())) - self.register_kernel_cpu_csrdevice("rtio") - self.register_kernel_cpu_csrdevice("rtio_dma") - self.submodules.cri_con = rtio.CRIInterconnectShared( - [self.rtio.cri, self.rtio_dma.cri], - [self.rtio_core.cri]) - self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) - self.csr_devices.append("rtio_moninj") - - self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.) - self.platform.add_false_path_constraints( - self.crg.cd_sys.clk, - self.rtio_crg.cd_rtio.clk) - - self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri, - self.get_native_sdram_if()) - self.csr_devices.append("rtio_analyzer") + _NIST_CLOCK_RTIO.__init__(self) -VARIANTS = {cls.__name__.lower(): cls for cls in [NIST_CLOCK, NIST_QC2, SMA_SPI]} +class NIST_QC2(_StandaloneBase, _NIST_QC2_RTIO): + def __init__(self, **kwargs): + _StandaloneBase.__init__(self, **kwargs) + _NIST_QC2_RTIO.__init__(self) + + +class NIST_CLOCK_Master(_MasterBase, _NIST_CLOCK_RTIO): + def __init__(self, **kwargs): + _MasterBase.__init__(self, **kwargs) + _NIST_CLOCK_RTIO.__init__(self) + + +class NIST_QC2_Master(_MasterBase, _NIST_QC2_RTIO): + def __init__(self, **kwargs): + _MasterBase.__init__(self, **kwargs) + _NIST_QC2_RTIO.__init__(self) + + +class NIST_CLOCK_Satellite(_SatelliteBase, _NIST_CLOCK_RTIO): + def __init__(self, **kwargs): + _SatelliteBase.__init__(self, **kwargs) + _NIST_CLOCK_RTIO.__init__(self) + + +class NIST_QC2_Satellite(_SatelliteBase, _NIST_QC2_RTIO): + def __init__(self, **kwargs): + _SatelliteBase.__init__(self, **kwargs) + _NIST_QC2_RTIO.__init__(self) + + +VARIANT_CLS = [ + NIST_CLOCK, NIST_QC2, + NIST_CLOCK_Master, NIST_QC2_Master, + NIST_CLOCK_Satellite, NIST_QC2_Satellite, +] +VARIANTS = {cls.__name__.lower(): cls for cls in VARIANT_CLS} def main(): parser = argparse.ArgumentParser( - description="KC705 gateware and firmware builder") + description="ARTIQ device binary builder for KC705 systems") builder_args(parser) soc_kc705_args(parser) parser.set_defaults(output_dir="artiq_kc705") parser.add_argument("-V", "--variant", default="nist_clock", help="variant: " - "nist_clock/nist_qc2/sma_spi " + "[standalone: nist_clock/nist_qc2] " + "[DRTIO master: nist_clock_master/nist_qc2_master] " + "[DRTIO satellite: nist_clock_satellite/nist_qc2_satellite] " "(default: %(default)s)") parser.add_argument("--gateware-identifier-str", default=None, help="Override ROM identifier") diff --git a/artiq/gateware/targets/kc705_drtio_master.py b/artiq/gateware/targets/kc705_drtio_master.py deleted file mode 100755 index 78d5d054b..000000000 --- a/artiq/gateware/targets/kc705_drtio_master.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env python3 - -import argparse - -from migen import * -from migen.build.generic_platform import * -from migen.build.xilinx.vivado import XilinxVivadoToolchain -from migen.build.xilinx.ise import XilinxISEToolchain - -from misoc.cores import spi as spi_csr -from misoc.cores import gpio -from misoc.integration.builder import * -from misoc.targets.kc705 import MiniSoC, soc_kc705_args, soc_kc705_argdict - -from artiq.gateware.amp import AMPSoC -from artiq.gateware import rtio -from artiq.gateware.rtio.phy import ttl_simple -from artiq.gateware.drtio.transceiver import gtx_7series -from artiq.gateware.drtio import * -from artiq.build_soc import * - - -class Master(MiniSoC, AMPSoC): - mem_map = { - "cri_con": 0x10000000, - "rtio": 0x20000000, - "rtio_dma": 0x30000000, - "drtioaux": 0x50000000, - "mailbox": 0x70000000 - } - mem_map.update(MiniSoC.mem_map) - - def __init__(self, gateware_identifier_str=None, **kwargs): - MiniSoC.__init__(self, - cpu_type="or1k", - sdram_controller_type="minicon", - l2_size=128*1024, - integrated_sram_size=8192, - ethmac_nrxslots=4, - ethmac_ntxslots=4, - **kwargs) - AMPSoC.__init__(self) - add_identifier(self, gateware_identifier_str=gateware_identifier_str) - - if isinstance(self.platform.toolchain, XilinxVivadoToolchain): - self.platform.toolchain.bitstream_commands.extend([ - "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", - ]) - if isinstance(self.platform.toolchain, XilinxISEToolchain): - self.platform.toolchain.bitgen_opt += " -g compress" - - platform = self.platform - - self.comb += platform.request("sfp_tx_disable_n").eq(1) - tx_pads = [ - platform.request("sfp_tx"), platform.request("user_sma_mgt_tx") - ] - rx_pads = [ - platform.request("sfp_rx"), platform.request("user_sma_mgt_rx") - ] - - # 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock - self.submodules.drtio_transceiver = gtx_7series.GTX( - clock_pads=platform.request("si5324_clkout"), - tx_pads=tx_pads, - rx_pads=rx_pads, - sys_clk_freq=self.clk_freq) - self.csr_devices.append("drtio_transceiver") - - self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) - - drtio_csr_group = [] - drtioaux_csr_group = [] - drtioaux_memory_group = [] - drtio_cri = [] - for i in range(len(self.drtio_transceiver.channels)): - core_name = "drtio" + str(i) - coreaux_name = "drtioaux" + str(i) - memory_name = "drtioaux" + str(i) + "_mem" - drtio_csr_group.append(core_name) - drtioaux_csr_group.append(coreaux_name) - drtioaux_memory_group.append(memory_name) - - cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)}) - - core = cdr(DRTIOMaster( - self.rtio_tsc, self.drtio_transceiver.channels[i])) - setattr(self.submodules, core_name, core) - drtio_cri.append(core.cri) - self.csr_devices.append(core_name) - - coreaux = cdr(DRTIOAuxController(core.link_layer)) - setattr(self.submodules, coreaux_name, coreaux) - self.csr_devices.append(coreaux_name) - - memory_address = self.mem_map["drtioaux"] + 0x800*i - self.add_wb_slave(memory_address, 0x800, - coreaux.bus) - self.add_memory_region(memory_name, memory_address | self.shadow_base, 0x800) - self.config["HAS_DRTIO"] = None - self.config["HAS_DRTIO_ROUTING"] = None - self.add_csr_group("drtio", drtio_csr_group) - self.add_csr_group("drtioaux", drtioaux_csr_group) - self.add_memory_group("drtioaux_mem", drtioaux_memory_group) - - self.config["RTIO_FREQUENCY"] = str(self.drtio_transceiver.rtio_clk_freq/1e6) - self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n) - self.csr_devices.append("si5324_rst_n") - i2c = self.platform.request("i2c") - self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) - self.csr_devices.append("i2c") - self.config["I2C_BUS_COUNT"] = 1 - self.config["HAS_SI5324"] = None - self.config["SI5324_AS_SYNTHESIZER"] = None - - self.comb += [ - platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")), - platform.request("user_sma_clock_n").eq(ClockSignal("rtio")) - ] - - rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq - # Constrain TX & RX timing for the first transceiver channel - # (First channel acts as master for phase alignment for all channels' TX) - gtx0 = self.drtio_transceiver.gtxs[0] - platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period) - platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, - gtx0.txoutclk, gtx0.rxoutclk) - # Constrain RX timing for the each transceiver channel - # (Each channel performs single-lane phase alignment for RX) - for gtx in self.drtio_transceiver.gtxs[1:]: - platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, gtx0.txoutclk, gtx.rxoutclk) - - rtio_channels = [] - for i in range(8): - phy = ttl_simple.Output(platform.request("user_led", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - for sma in "user_sma_gpio_p", "user_sma_gpio_n": - phy = ttl_simple.InOut(platform.request(sma)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) - self.csr_devices.append("rtio_moninj") - - self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) - self.csr_devices.append("rtio_core") - - self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) - self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( - rtio.DMA(self.get_native_sdram_if())) - self.register_kernel_cpu_csrdevice("rtio") - self.register_kernel_cpu_csrdevice("rtio_dma") - self.submodules.cri_con = rtio.CRIInterconnectShared( - [self.rtio.cri, self.rtio_dma.cri], - [self.rtio_core.cri] + drtio_cri, - enable_routing=True) - self.register_kernel_cpu_csrdevice("cri_con") - self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) - self.csr_devices.append("routing_table") - - -def main(): - parser = argparse.ArgumentParser( - description="ARTIQ device binary builder / KC705 DRTIO master") - builder_args(parser) - soc_kc705_args(parser) - parser.set_defaults(output_dir="artiq_kc705/master") - args = parser.parse_args() - - soc = Master(**soc_kc705_argdict(args)) - build_artiq_soc(soc, builder_argdict(args)) - - -if __name__ == "__main__": - main() diff --git a/artiq/gateware/targets/kc705_drtio_satellite.py b/artiq/gateware/targets/kc705_drtio_satellite.py deleted file mode 100755 index 4ff346fdf..000000000 --- a/artiq/gateware/targets/kc705_drtio_satellite.py +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/env python3 - -import argparse - -from migen import * -from migen.build.generic_platform import * -from migen.build.xilinx.vivado import XilinxVivadoToolchain -from migen.build.xilinx.ise import XilinxISEToolchain - -from misoc.cores import spi as spi_csr -from misoc.cores import gpio -from misoc.integration.builder import * -from misoc.targets.kc705 import BaseSoC, soc_kc705_args, soc_kc705_argdict - -from artiq.gateware import rtio -from artiq.gateware.rtio.phy import ttl_simple -from artiq.gateware.drtio.transceiver import gtx_7series -from artiq.gateware.drtio.siphaser import SiPhaser7Series -from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer -from artiq.gateware.drtio import * -from artiq.build_soc import * - - -class Satellite(BaseSoC): - mem_map = { - "drtioaux": 0x50000000, - } - mem_map.update(BaseSoC.mem_map) - - def __init__(self, gateware_identifier_str=None, sma_as_sat=False, **kwargs): - BaseSoC.__init__(self, - cpu_type="or1k", - sdram_controller_type="minicon", - l2_size=128*1024, - integrated_sram_size=8192, - **kwargs) - add_identifier(self, gateware_identifier_str=gateware_identifier_str) - - if isinstance(self.platform.toolchain, XilinxVivadoToolchain): - self.platform.toolchain.bitstream_commands.extend([ - "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", - ]) - if isinstance(self.platform.toolchain, XilinxISEToolchain): - self.platform.toolchain.bitgen_opt += " -g compress" - - platform = self.platform - - self.comb += platform.request("sfp_tx_disable_n").eq(1) - tx_pads = [ - platform.request("sfp_tx"), platform.request("user_sma_mgt_tx") - ] - rx_pads = [ - platform.request("sfp_rx"), platform.request("user_sma_mgt_rx") - ] - if sma_as_sat: - tx_pads = tx_pads[::-1] - rx_pads = rx_pads[::-1] - - # 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock - self.submodules.drtio_transceiver = gtx_7series.GTX( - clock_pads=platform.request("si5324_clkout"), - tx_pads=tx_pads, - rx_pads=rx_pads, - sys_clk_freq=self.clk_freq) - self.csr_devices.append("drtio_transceiver") - - self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3) - - drtioaux_csr_group = [] - drtioaux_memory_group = [] - drtiorep_csr_group = [] - self.drtio_cri = [] - for i in range(len(self.drtio_transceiver.channels)): - coreaux_name = "drtioaux" + str(i) - memory_name = "drtioaux" + str(i) + "_mem" - drtioaux_csr_group.append(coreaux_name) - drtioaux_memory_group.append(memory_name) - - cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)}) - - # Satellite - if i == 0: - self.submodules.rx_synchronizer = cdr(XilinxRXSynchronizer()) - core = cdr(DRTIOSatellite( - self.rtio_tsc, self.drtio_transceiver.channels[0], self.rx_synchronizer)) - self.submodules.drtiosat = core - self.csr_devices.append("drtiosat") - # Repeaters - else: - corerep_name = "drtiorep" + str(i-1) - drtiorep_csr_group.append(corerep_name) - core = cdr(DRTIORepeater( - self.rtio_tsc, self.drtio_transceiver.channels[i])) - setattr(self.submodules, corerep_name, core) - self.drtio_cri.append(core.cri) - self.csr_devices.append(corerep_name) - - coreaux = cdr(DRTIOAuxController(core.link_layer)) - setattr(self.submodules, coreaux_name, coreaux) - self.csr_devices.append(coreaux_name) - - memory_address = self.mem_map["drtioaux"] + 0x800*i - self.add_wb_slave(memory_address, 0x800, - coreaux.bus) - self.add_memory_region(memory_name, memory_address | self.shadow_base, 0x800) - self.config["HAS_DRTIO"] = None - self.config["HAS_DRTIO_ROUTING"] = None - self.add_csr_group("drtioaux", drtioaux_csr_group) - self.add_memory_group("drtioaux_mem", drtioaux_memory_group) - self.add_csr_group("drtiorep", drtiorep_csr_group) - - self.config["RTIO_FREQUENCY"] = str(self.drtio_transceiver.rtio_clk_freq/1e6) - # Si5324 Phaser - self.submodules.siphaser = SiPhaser7Series( - si5324_clkin=platform.request("si5324_clkin"), - rx_synchronizer=self.rx_synchronizer, - ultrascale=False, - rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) - self.csr_devices.append("siphaser") - self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n) - self.csr_devices.append("si5324_rst_n") - i2c = self.platform.request("i2c") - self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) - self.csr_devices.append("i2c") - self.config["I2C_BUS_COUNT"] = 1 - self.config["HAS_SI5324"] = None - - self.comb += [ - platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")), - platform.request("user_sma_clock_n").eq(ClockSignal("rtio")) - ] - - rtio_clk_period = 1e9/self.drtio_transceiver.rtio_clk_freq - # Constrain TX & RX timing for the first transceiver channel - # (First channel acts as master for phase alignment for all channels' TX) - gtx0 = self.drtio_transceiver.gtxs[0] - platform.add_period_constraint(gtx0.txoutclk, rtio_clk_period) - platform.add_period_constraint(gtx0.rxoutclk, rtio_clk_period) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, - gtx0.txoutclk, gtx0.rxoutclk) - # Constrain RX timing for the each transceiver channel - # (Each channel performs single-lane phase alignment for RX) - for gtx in self.drtio_transceiver.gtxs[1:]: - platform.add_period_constraint(gtx.rxoutclk, rtio_clk_period) - platform.add_false_path_constraints( - self.crg.cd_sys.clk, gtx.rxoutclk) - - rtio_channels = [] - for i in range(8): - phy = ttl_simple.Output(platform.request("user_led", i)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - for sma in "user_sma_gpio_p", "user_sma_gpio_n": - phy = ttl_simple.InOut(platform.request(sma)) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy)) - - self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) - self.csr_devices.append("rtio_moninj") - - self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels) - self.comb += self.drtiosat.async_errors.eq(self.local_io.async_errors) - self.submodules.cri_con = rtio.CRIInterconnectShared( - [self.drtiosat.cri], - [self.local_io.cri] + self.drtio_cri, - mode="sync", enable_routing=True) - self.csr_devices.append("cri_con") - self.submodules.routing_table = rtio.RoutingTableAccess(self.cri_con) - self.csr_devices.append("routing_table") - - -def main(): - parser = argparse.ArgumentParser( - description="ARTIQ device binary builder / KC705 DRTIO satellite") - builder_args(parser) - soc_kc705_args(parser) - parser.set_defaults(output_dir="artiq_kc705/satellite") - parser.add_argument("--sma", default=False, action="store_true", - help="use the SMA connectors (RX: J17, J18, TX: J19, J20) " - "as DRTIO satellite channel instead of the SFP") - args = parser.parse_args() - - argdict = dict() - argdict["sma_as_sat"] = args.sma - - soc = Satellite(**soc_kc705_argdict(args), **argdict) - build_artiq_soc(soc, builder_argdict(args)) - - -if __name__ == "__main__": - main() From 5111132ef0a3c357bbdbdae16bf5298f66cea44d Mon Sep 17 00:00:00 2001 From: Star Chen Date: Fri, 6 Aug 2021 15:08:30 +0800 Subject: [PATCH 033/238] ICAP: prevent sayma from using it (#1740) --- artiq/firmware/libboard_misoc/spiflash.rs | 1 + artiq/firmware/runtime/main.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/artiq/firmware/libboard_misoc/spiflash.rs b/artiq/firmware/libboard_misoc/spiflash.rs index 7b1244775..9b5ca31f5 100644 --- a/artiq/firmware/libboard_misoc/spiflash.rs +++ b/artiq/firmware/libboard_misoc/spiflash.rs @@ -114,6 +114,7 @@ pub unsafe fn write(mut addr: usize, mut data: &[u8]) { } } +#[cfg(any(soc_platform = "kasli", soc_platform = "metlino", soc_platform = "kc705"))] pub unsafe fn reload () -> ! { csr::icap::iprog_write(1); loop {} diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index df103d7ef..e57e34f7a 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -332,7 +332,8 @@ pub fn panic_impl(info: &core::panic::PanicInfo) -> ! { println!("{:#08x}", ip - 2 * 4); }); - if config::read_str("panic_reset", |r| r == Ok("1")) && cfg!(has_spiflash) { + if config::read_str("panic_reset", |r| r == Ok("1")) && + cfg!(any(soc_platform = "kasli", soc_platform = "metlino", soc_platform = "kc705")) { println!("restarting..."); unsafe { kernel::stop(); From 242dfae38eb4d22ee1adc88daa0fc311e54f1849 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 6 Aug 2021 15:36:10 +0800 Subject: [PATCH 034/238] kc705: fix DRTIO targets --- artiq/gateware/targets/kc705.py | 103 ++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 25 deletions(-) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 0c1c431b6..45678103c 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -82,16 +82,75 @@ class _RTIOCRG(Module, AutoCSR): ] -# The default user SMA voltage on KC705 is 2.5V, and the Migen platform +class _RTIOClockMultiplier(Module, AutoCSR): + def __init__(self, rtio_clk_freq): + self.pll_reset = CSRStorage(reset=1) + self.pll_locked = CSRStatus() + self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True) + + # See "Global Clock Network Deskew Using Two BUFGs" in ug472. + clkfbout = Signal() + clkfbin = Signal() + rtiox4_clk = Signal() + pll_locked = Signal() + self.specials += [ + Instance("MMCME2_BASE", + p_CLKIN1_PERIOD=1e9/rtio_clk_freq, + i_CLKIN1=ClockSignal("rtio"), + i_RST=self.pll_reset.storage, + o_LOCKED=pll_locked, + + p_CLKFBOUT_MULT_F=8.0, p_DIVCLK_DIVIDE=1, + + o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbin, + + p_CLKOUT0_DIVIDE_F=2.0, o_CLKOUT0=rtiox4_clk, + ), + Instance("BUFG", i_I=clkfbout, o_O=clkfbin), + Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk), + + MultiReg(pll_locked, self.pll_locked.status) + ] + + +def fix_serdes_timing_path(platform): + # ignore timing of path from OSERDESE2 through the pad to ISERDESE2 + platform.add_platform_command( + "set_false_path -quiet " + "-through [get_pins -filter {{REF_PIN_NAME == OQ || REF_PIN_NAME == TQ}} " + "-of [get_cells -filter {{REF_NAME == OSERDESE2}}]] " + "-to [get_pins -filter {{REF_PIN_NAME == D}} " + "-of [get_cells -filter {{REF_NAME == ISERDESE2}}]]" + ) + + +# The default voltage for these signals on KC705 is 2.5V, and the Migen platform # follows this default. But since the SMAs are on the same bank as the DDS, # which is set to 3.3V by reprogramming the KC705 power ICs, we need to # redefine them here. -_sma33_io = [ +_reprogrammed3v3_io = [ ("user_sma_gpio_p_33", 0, Pins("Y23"), IOStandard("LVCMOS33")), ("user_sma_gpio_n_33", 0, Pins("Y24"), IOStandard("LVCMOS33")), + ("si5324_33", 0, + Subsignal("rst_n", Pins("AE20"), IOStandard("LVCMOS33")), + Subsignal("int", Pins("AG24"), IOStandard("LVCMOS33")) + ), + ("sfp_tx_disable_n_33", 0, Pins("Y20"), IOStandard("LVCMOS33")), + # HACK: this should be LVDS, but TMDS is the only supported differential + # output standard at 3.3V. KC705 hardware design issue? + ("si5324_clkin_33", 0, + Subsignal("p", Pins("W27"), IOStandard("TMDS_33")), + Subsignal("n", Pins("W28"), IOStandard("TMDS_33")) + ), + ("sdcard_spi_33", 0, + Subsignal("miso", Pins("AC20"), Misc("PULLUP=TRUE")), + Subsignal("clk", Pins("AB23")), + Subsignal("mosi", Pins("AB22")), + Subsignal("cs_n", Pins("AC21")), + IOStandard("LVCMOS33") + ) ] - _ams101_dac = [ ("ams101_dac", 0, Subsignal("ldac", Pins("XADC:GPIO0")), @@ -102,17 +161,6 @@ _ams101_dac = [ ) ] -_sdcard_spi_33 = [ - ("sdcard_spi_33", 0, - Subsignal("miso", Pins("AC20"), Misc("PULLUP=TRUE")), - Subsignal("clk", Pins("AB23")), - Subsignal("mosi", Pins("AB22")), - Subsignal("cs_n", Pins("AC21")), - IOStandard("LVCMOS33") - ) -] - - class _StandaloneBase(MiniSoC, AMPSoC): mem_map = { "cri_con": 0x10000000, @@ -150,9 +198,8 @@ class _StandaloneBase(MiniSoC, AMPSoC): self.platform.request("user_led", 1))) self.csr_devices.append("leds") - self.platform.add_extension(_sma33_io) + self.platform.add_extension(_reprogrammed3v3_io) self.platform.add_extension(_ams101_dac) - self.platform.add_extension(_sdcard_spi_33) i2c = self.platform.request("i2c") self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) @@ -220,11 +267,10 @@ class _MasterBase(MiniSoC, AMPSoC): self.platform.toolchain.bitgen_opt += " -g compress" platform = self.platform - platform.add_extension(_sma33_io) + platform.add_extension(_reprogrammed3v3_io) platform.add_extension(_ams101_dac) - platform.add_extension(_sdcard_spi_33) - self.comb += platform.request("sfp_tx_disable_n").eq(1) + self.comb += platform.request("sfp_tx_disable_n_33").eq(1) tx_pads = [ platform.request("sfp_tx"), platform.request("user_sma_mgt_tx") ] @@ -277,7 +323,7 @@ class _MasterBase(MiniSoC, AMPSoC): self.add_memory_group("drtioaux_mem", drtioaux_memory_group) self.config["RTIO_FREQUENCY"] = str(self.drtio_transceiver.rtio_clk_freq/1e6) - self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n) + self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324_33").rst_n) self.csr_devices.append("si5324_rst_n") i2c = self.platform.request("i2c") self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) @@ -307,6 +353,10 @@ class _MasterBase(MiniSoC, AMPSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtx0.txoutclk, gtx.rxoutclk) + self.submodules.rtio_crg = _RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq) + self.csr_devices.append("rtio_crg") + fix_serdes_timing_path(platform) + def add_rtio(self, rtio_channels): self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) self.csr_devices.append("rtio_moninj") @@ -351,11 +401,10 @@ class _SatelliteBase(BaseSoC): self.platform.toolchain.bitgen_opt += " -g compress" platform = self.platform - platform.add_extension(_sma33_io) + platform.add_extension(_reprogrammed3v3_io) platform.add_extension(_ams101_dac) - platform.add_extension(_sdcard_spi_33) - self.comb += platform.request("sfp_tx_disable_n").eq(1) + self.comb += platform.request("sfp_tx_disable_n_33").eq(1) tx_pads = [ platform.request("sfp_tx"), platform.request("user_sma_mgt_tx") ] @@ -422,14 +471,14 @@ class _SatelliteBase(BaseSoC): self.config["RTIO_FREQUENCY"] = str(self.drtio_transceiver.rtio_clk_freq/1e6) # Si5324 Phaser self.submodules.siphaser = SiPhaser7Series( - si5324_clkin=platform.request("si5324_clkin"), + si5324_clkin=platform.request("si5324_clkin_33"), rx_synchronizer=self.rx_synchronizer, ultrascale=False, rtio_clk_freq=self.drtio_transceiver.rtio_clk_freq) platform.add_false_path_constraints( self.crg.cd_sys.clk, self.siphaser.mmcm_freerun_output) self.csr_devices.append("siphaser") - self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n) + self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324_33").rst_n) self.csr_devices.append("si5324_rst_n") i2c = self.platform.request("i2c") self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) @@ -458,6 +507,10 @@ class _SatelliteBase(BaseSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtx.rxoutclk) + self.submodules.rtio_crg = _RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq) + self.csr_devices.append("rtio_crg") + fix_serdes_timing_path(platform) + def add_rtio(self, rtio_channels): self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) self.csr_devices.append("rtio_moninj") From 7879d3630b1b1ec581bc627f5f347c1fc0e98e0f Mon Sep 17 00:00:00 2001 From: mwojcik Date: Mon, 9 Aug 2021 15:55:28 +0200 Subject: [PATCH 035/238] made kc705/gtx interface more similar to kasli/gtp --- .../gateware/drtio/transceiver/gtx_7series.py | 17 +++++++------- artiq/gateware/targets/kc705.py | 23 ++++++------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/artiq/gateware/drtio/transceiver/gtx_7series.py b/artiq/gateware/drtio/transceiver/gtx_7series.py index a2da39822..28b9536db 100644 --- a/artiq/gateware/drtio/transceiver/gtx_7series.py +++ b/artiq/gateware/drtio/transceiver/gtx_7series.py @@ -16,7 +16,7 @@ class GTX_20X(Module): # * GTX PLL frequency @ 2.5GHz # * GTX line rate (TX & RX) @ 2.5Gb/s # * GTX TX/RX USRCLK @ 125MHz == coarse RTIO frequency - def __init__(self, refclk, tx_pads, rx_pads, sys_clk_freq, rtio_clk_freq=125e6, tx_mode="single", rx_mode="single"): + def __init__(self, refclk, pads, sys_clk_freq, rtio_clk_freq=125e6, tx_mode="single", rx_mode="single"): assert tx_mode in ["single", "master", "slave"] assert rx_mode in ["single", "master", "slave"] @@ -229,10 +229,10 @@ class GTX_20X(Module): p_RXCDR_LOCK_CFG=0b010101, # Pads - i_GTXRXP=rx_pads.p, - i_GTXRXN=rx_pads.n, - o_GTXTXP=tx_pads.p, - o_GTXTXN=tx_pads.n, + i_GTXRXP=pads.rxp, + i_GTXRXN=pads.rxn, + o_GTXTXP=pads.txp, + o_GTXTXN=pads.txn, # Other parameters p_PCS_RSVD_ATTR=( @@ -282,9 +282,8 @@ class GTX_20X(Module): class GTX(Module, TransceiverInterface): - def __init__(self, clock_pads, tx_pads, rx_pads, sys_clk_freq, rtio_clk_freq=125e6, master=0): - assert len(tx_pads) == len(rx_pads) - self.nchannels = nchannels = len(tx_pads) + def __init__(self, clock_pads, pads, sys_clk_freq, rtio_clk_freq=125e6, master=0): + self.nchannels = nchannels = len(pads) self.gtxs = [] self.rtio_clk_freq = rtio_clk_freq @@ -307,7 +306,7 @@ class GTX(Module, TransceiverInterface): else: mode = "master" if i == master else "slave" # Note: RX phase alignment is to be done on individual lanes, not multi-lane. - gtx = GTX_20X(refclk, tx_pads[i], rx_pads[i], sys_clk_freq, rtio_clk_freq=rtio_clk_freq, tx_mode=mode, rx_mode="single") + gtx = GTX_20X(refclk, pads[i], sys_clk_freq, rtio_clk_freq=rtio_clk_freq, tx_mode=mode, rx_mode="single") # Fan-out (to slave) / Fan-in (from master) of the TXUSRCLK if mode == "slave": self.comb += gtx.cd_rtio_tx.clk.eq(rtio_tx_clk) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 45678103c..9d167b566 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -271,18 +271,14 @@ class _MasterBase(MiniSoC, AMPSoC): platform.add_extension(_ams101_dac) self.comb += platform.request("sfp_tx_disable_n_33").eq(1) - tx_pads = [ - platform.request("sfp_tx"), platform.request("user_sma_mgt_tx") - ] - rx_pads = [ - platform.request("sfp_rx"), platform.request("user_sma_mgt_rx") + data_pads = [ + platform.request("sfp"), platform.request("user_sma_mgt") ] # 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("si5324_clkout"), - tx_pads=tx_pads, - rx_pads=rx_pads, + pads=data_pads, sys_clk_freq=self.clk_freq) self.csr_devices.append("drtio_transceiver") @@ -405,21 +401,16 @@ class _SatelliteBase(BaseSoC): platform.add_extension(_ams101_dac) self.comb += platform.request("sfp_tx_disable_n_33").eq(1) - tx_pads = [ - platform.request("sfp_tx"), platform.request("user_sma_mgt_tx") - ] - rx_pads = [ - platform.request("sfp_rx"), platform.request("user_sma_mgt_rx") + data_pads = [ + platform.request("sfp"), platform.request("user_sma_mgt") ] if sma_as_sat: - tx_pads = tx_pads[::-1] - rx_pads = rx_pads[::-1] + data_pads = data_pads[::-1] # 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("si5324_clkout"), - tx_pads=tx_pads, - rx_pads=rx_pads, + pads=data_pads, sys_clk_freq=self.clk_freq) self.csr_devices.append("drtio_transceiver") From 67847f98f47d1b4d6d238b43ae455f2c04de355d Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 11:37:45 +0800 Subject: [PATCH 036/238] artiq_run: fix multiarch --- artiq/frontend/artiq_run.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/artiq/frontend/artiq_run.py b/artiq/frontend/artiq_run.py index 4e6f2b7a3..98e3c8221 100755 --- a/artiq/frontend/artiq_run.py +++ b/artiq/frontend/artiq_run.py @@ -21,7 +21,6 @@ from artiq.master.databases import DeviceDB, DatasetDB from artiq.master.worker_db import DeviceManager, DatasetManager from artiq.coredevice.core import CompileError, host_only from artiq.compiler.embedding import EmbeddingMap -from artiq.compiler.targets import OR1KTarget from artiq.compiler import import_cache from artiq.tools import * @@ -53,7 +52,7 @@ class FileRunner(EnvExperiment): def build(self, file): self.setattr_device("core") self.file = file - self.target = OR1KTarget() + self.target = self.core.target_cls() def run(self): kernel_library = self.compile() From e3edb505e3662f553f86b9f50fc64f3e9aa7489a Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 11:38:24 +0800 Subject: [PATCH 037/238] setup.py: remove outdated dependency_links --- setup.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/setup.py b/setup.py index b8b5d7e1f..980e6b109 100755 --- a/setup.py +++ b/setup.py @@ -64,10 +64,6 @@ Topic :: System :: Hardware """.splitlines(), install_requires=requirements, extras_require={}, - dependency_links=[ - "git+https://github.com/m-labs/pyqtgraph.git@develop#egg=pyqtgraph", - "git+https://github.com/m-labs/llvmlite.git@artiq#egg=llvmlite_artiq" - ], packages=find_packages(), namespace_packages=[], include_package_data=True, From 477b1516d3671f678d862d145ce4990adc5d100b Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 11:43:19 +0800 Subject: [PATCH 038/238] remove profiler --- artiq/coredevice/comm_mgmt.py | 40 --- artiq/coredevice/profiler.py | 92 ------- artiq/firmware/libproto_artiq/mgmt_proto.rs | 21 -- artiq/firmware/runtime/main.rs | 10 +- artiq/firmware/runtime/mgmt.rs | 43 --- artiq/firmware/runtime/profiler.rs | 278 -------------------- artiq/frontend/artiq_coremgmt.py | 48 ---- 7 files changed, 1 insertion(+), 531 deletions(-) delete mode 100644 artiq/coredevice/profiler.py delete mode 100644 artiq/firmware/runtime/profiler.rs diff --git a/artiq/coredevice/comm_mgmt.py b/artiq/coredevice/comm_mgmt.py index 6a268c8e1..7d8ef6f38 100644 --- a/artiq/coredevice/comm_mgmt.py +++ b/artiq/coredevice/comm_mgmt.py @@ -20,10 +20,6 @@ class Request(Enum): ConfigRemove = 14 ConfigErase = 15 - StartProfiler = 9 - StopProfiler = 10 - GetProfile = 11 - Reboot = 5 DebugAllocator = 8 @@ -38,8 +34,6 @@ class Reply(Enum): ConfigData = 7 - Profile = 5 - RebootImminent = 3 @@ -189,40 +183,6 @@ class CommMgmt: self._write_header(Request.ConfigErase) self._read_expect(Reply.Success) - def start_profiler(self, interval, edges_size, hits_size): - self._write_header(Request.StartProfiler) - self._write_int32(interval) - self._write_int32(edges_size) - self._write_int32(hits_size) - self._read_expect(Reply.Success) - - def stop_profiler(self): - self._write_header(Request.StopProfiler) - self._read_expect(Reply.Success) - - def stop_profiler(self): - self._write_header(Request.StopProfiler) - self._read_expect(Reply.Success) - - def get_profile(self): - self._write_header(Request.GetProfile) - self._read_expect(Reply.Profile) - - hits = {} - for _ in range(self._read_int32()): - addr = self._read_int32() - count = self._read_int32() - hits[addr] = count - - edges = {} - for _ in range(self._read_int32()): - caller = self._read_int32() - callee = self._read_int32() - count = self._read_int32() - edges[(caller, callee)] = count - - return hits, edges - def reboot(self): self._write_header(Request.Reboot) self._read_expect(Reply.RebootImminent) diff --git a/artiq/coredevice/profiler.py b/artiq/coredevice/profiler.py deleted file mode 100644 index 5ed431915..000000000 --- a/artiq/coredevice/profiler.py +++ /dev/null @@ -1,92 +0,0 @@ -from collections import defaultdict -import subprocess - - -class Symbolizer: - def __init__(self, binary, triple, demangle=True): - cmdline = [ - triple + "-addr2line", "--exe=" + binary, - "--addresses", "--functions", "--inlines" - ] - if demangle: - cmdline.append("--demangle=rust") - self._addr2line = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - universal_newlines=True) - - def symbolize(self, addr): - self._addr2line.stdin.write("0x{:08x}\n0\n".format(addr)) - self._addr2line.stdin.flush() - self._addr2line.stdout.readline() # 0x[addr] - - result = [] - while True: - function = self._addr2line.stdout.readline().rstrip() - - # check for end marker - if function == "0x00000000": # 0x00000000 - self._addr2line.stdout.readline() # ?? - self._addr2line.stdout.readline() # ??:0 - return result - - file, line = self._addr2line.stdout.readline().rstrip().split(":") - - result.append((function, file, line, addr)) - - -class CallgrindWriter: - def __init__(self, output, binary, triple, compression=True, demangle=True): - self._output = output - self._binary = binary - self._current = defaultdict(lambda: None) - self._ids = defaultdict(lambda: {}) - self._compression = compression - self._symbolizer = Symbolizer(binary, triple, demangle=demangle) - - def _write(self, fmt, *args, **kwargs): - self._output.write(fmt.format(*args, **kwargs)) - self._output.write("\n") - - def _spec(self, spec, value): - if self._current[spec] == value: - return - self._current[spec] = value - - if not self._compression or value == "??": - self._write("{}={}", spec, value) - return - - spec_ids = self._ids[spec] - if value in spec_ids: - self._write("{}=({})", spec, spec_ids[value]) - else: - spec_ids[value] = len(spec_ids) + 1 - self._write("{}=({}) {}", spec, spec_ids[value], value) - - def header(self): - self._write("# callgrind format") - self._write("version: 1") - self._write("creator: ARTIQ") - self._write("positions: instr line") - self._write("events: Hits") - self._write("") - self._spec("ob", self._binary) - self._spec("cob", self._binary) - - def hit(self, addr, count): - for function, file, line, addr in self._symbolizer.symbolize(addr): - self._spec("fl", file) - self._spec("fn", function) - self._write("0x{:08x} {} {}", addr, line, count) - - def edge(self, caller, callee, count): - edges = self._symbolizer.symbolize(callee) + self._symbolizer.symbolize(caller) - for (callee, caller) in zip(edges, edges[1:]): - function, file, line, addr = callee - self._spec("cfl", file) - self._spec("cfn", function) - self._write("calls={} 0x{:08x} {}", count, addr, line) - - function, file, line, addr = caller - self._spec("fl", file) - self._spec("fn", function) - self._write("0x{:08x} {} {}", addr, line, count) diff --git a/artiq/firmware/libproto_artiq/mgmt_proto.rs b/artiq/firmware/libproto_artiq/mgmt_proto.rs index c5937fac6..5f13ffc96 100644 --- a/artiq/firmware/libproto_artiq/mgmt_proto.rs +++ b/artiq/firmware/libproto_artiq/mgmt_proto.rs @@ -63,14 +63,6 @@ pub enum Request { ConfigRemove { key: String }, ConfigErase, - StartProfiler { - interval_us: u32, - hits_size: u32, - edges_size: u32, - }, - StopProfiler, - GetProfile, - Reboot, DebugAllocator, @@ -129,14 +121,6 @@ impl Request { }, 15 => Request::ConfigErase, - 9 => Request::StartProfiler { - interval_us: reader.read_u32()?, - hits_size: reader.read_u32()?, - edges_size: reader.read_u32()?, - }, - 10 => Request::StopProfiler, - 11 => Request::GetProfile, - 5 => Request::Reboot, 8 => Request::DebugAllocator, @@ -172,11 +156,6 @@ impl<'a> Reply<'a> { writer.write_bytes(bytes)?; }, - Reply::Profile => { - writer.write_u8(5)?; - // profile data follows - } - Reply::RebootImminent => { writer.write_u8(3)?; } diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index e57e34f7a..0279395b1 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -50,7 +50,6 @@ mod cache; mod rtio_dma; mod mgmt; -mod profiler; mod kernel; mod kern_hwreq; mod session; @@ -263,14 +262,7 @@ pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) { let vect = irq::Exception::try_from(vect).expect("unknown exception"); match vect { irq::Exception::Interrupt => - while irq::pending_mask() != 0 { - match () { - #[cfg(has_timer1)] - () if irq::is_pending(csr::TIMER1_INTERRUPT) => - profiler::sample(pc as usize), - _ => panic!("spurious irq {}", irq::pending_mask().trailing_zeros()) - } - }, + panic!("spurious irq {}", irq::pending_mask().trailing_zeros()) _ => { fn hexdump(addr: u32) { let addr = (addr - addr % 4) as *const u32; diff --git a/artiq/firmware/runtime/mgmt.rs b/artiq/firmware/runtime/mgmt.rs index 2f632a7da..1073cb4fe 100644 --- a/artiq/firmware/runtime/mgmt.rs +++ b/artiq/firmware/runtime/mgmt.rs @@ -5,7 +5,6 @@ use board_misoc::{config, spiflash}; use logger_artiq::BufferLogger; use mgmt_proto::*; use sched::{Io, TcpListener, TcpStream, Error as SchedError}; -use profiler; impl From for Error { fn from(value: SchedError) -> Error { @@ -103,53 +102,11 @@ fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error> { }?; } - Request::StartProfiler { interval_us, hits_size, edges_size } => { - match profiler::start(interval_us as u64, - hits_size as usize, edges_size as usize) { - Ok(()) => Reply::Success.write_to(stream)?, - Err(()) => Reply::Unavailable.write_to(stream)? - } - } - Request::StopProfiler => { - profiler::stop(); - Reply::Success.write_to(stream)?; - } - Request::GetProfile => { - profiler::pause(|profile| { - let profile = match profile { - None => return Reply::Unavailable.write_to(stream), - Some(profile) => profile - }; - - Reply::Profile.write_to(stream)?; - { - let hits = profile.hits(); - stream.write_u32(hits.len() as u32)?; - for (&addr, &count) in hits.iter() { - stream.write_u32(addr.as_raw() as u32)?; - stream.write_u32(count)?; - } - } - { - let edges = profile.edges(); - stream.write_u32(edges.len() as u32)?; - for (&(caller, callee), &count) in edges.iter() { - stream.write_u32(caller.as_raw() as u32)?; - stream.write_u32(callee.as_raw() as u32)?; - stream.write_u32(count)?; - } - } - - Ok(()) - })?; - } - Request::Reboot => { Reply::RebootImminent.write_to(stream)?; stream.close()?; stream.flush()?; - profiler::stop(); warn!("restarting"); unsafe { spiflash::reload(); } } diff --git a/artiq/firmware/runtime/profiler.rs b/artiq/firmware/runtime/profiler.rs deleted file mode 100644 index 6df9c3f8c..000000000 --- a/artiq/firmware/runtime/profiler.rs +++ /dev/null @@ -1,278 +0,0 @@ -#![cfg_attr(not(has_timer1), allow(dead_code))] - -use core::mem; -use core::fmt; -use core::num::NonZeroUsize; -use alloc::Vec; -use managed::ManagedMap; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Address(NonZeroUsize); - -impl Address { - pub fn new(raw: usize) -> Address { - Address(NonZeroUsize::new(raw).expect("null address")) - } - - pub fn as_raw(&self) -> usize { - self.0.get() - } -} - -pub struct Profile { - hits: Vec>, - edges: Vec>, -} - -impl fmt::Debug for Profile { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Profile {{ hits: vec![...; {}], edges: vec![...; {}] }}", - self.hits.len(), self.edges.len()) - } -} - -impl Profile { - pub fn new(hits_size: usize, edges_size: usize) -> Profile { - let mut hits = vec![None; hits_size]; - hits.shrink_to_fit(); - let mut edges = vec![None; edges_size]; - edges.shrink_to_fit(); - Profile { - hits: hits.into(), - edges: edges.into(), - } - } - - pub fn overhead(&self) -> usize { - let hit_size = mem::size_of::>(); - let edge_size = mem::size_of::>(); - self.hits.capacity() * hit_size + - self.edges.capacity() * edge_size - } - - pub fn has_edges(&self) -> bool { - self.edges.is_empty() - } - - pub fn hits<'a>(&'a mut self) -> ManagedMap<'a, Address, u32> { - ManagedMap::Borrowed(&mut self.hits[..]) - } - - pub fn edges<'a>(&'a mut self) -> ManagedMap<'a, (Address, Address), u32> { - ManagedMap::Borrowed(&mut self.edges[..]) - } - - pub fn record_hit(&mut self, addr: Address) -> Result<(), ()> { - let mut hits = self.hits(); - if let Some(count) = hits.get_mut(&addr) { - return Ok(*count = count.saturating_add(1)) - } - if let Err(_) = hits.insert(addr, 1) { - return Err(()) - } - return Ok(()) - } - - #[allow(dead_code)] - pub fn record_edge(&mut self, caller: Address, callee: Address) -> Result<(), ()> { - let mut edges = self.edges(); - if let Some(count) = edges.get_mut(&(caller, callee)) { - return Ok(*count = count.saturating_add(1)) - } - if let Err(_) = edges.insert((caller, callee), 1) { - return Err(()) - } - Ok(()) - } -} - -#[cfg(has_timer1)] -mod imp { - use unwind_backtrace::backtrace; - use board_misoc::{csr, irq}; - use super::{Address, Profile}; - - static mut PROFILE: Option = None; - - mod lock { - use core::ops::{Deref, DerefMut}; - use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; - - static LOCKED: AtomicUsize = ATOMIC_USIZE_INIT; - - pub struct Lock; - - impl Lock { - pub fn take() -> Result { - if LOCKED.swap(1, Ordering::SeqCst) != 0 { - Err(()) - } else { - Ok(Lock) - } - } - } - - impl Deref for Lock { - type Target = Option; - - fn deref(&self) -> &Option { - unsafe { &super::PROFILE } - } - } - - impl DerefMut for Lock { - fn deref_mut(&mut self) -> &mut Option { - unsafe { &mut super::PROFILE } - } - } - - impl Drop for Lock { - fn drop(&mut self) { - LOCKED.store(0, Ordering::SeqCst) - } - } - } - - use self::lock::Lock; - - pub fn start(interval_us: u64, hits_size: usize, edges_size: usize) -> Result<(), ()> { - stop(); - - let profile = Profile::new(hits_size, edges_size); - info!("starting at {}us interval using {} heap bytes", - interval_us, profile.overhead()); - - *Lock::take().expect("cannot lock") = Some(profile); - - unsafe { - let reload = csr::CONFIG_CLOCK_FREQUENCY as u64 * interval_us / 1_000_000; - csr::timer1::load_write(reload); - csr::timer1::reload_write(reload); - csr::timer1::ev_pending_write(1); - csr::timer1::ev_enable_write(1); - irq::enable(csr::TIMER1_INTERRUPT); - csr::timer1::en_write(1); - } - - Ok(()) - } - - pub fn stop() { - unsafe { - if csr::timer1::en_read() == 0 || csr::timer1::ev_enable_read() == 0 { - return - } - - irq::disable(csr::TIMER1_INTERRUPT); - csr::timer1::en_write(0); - - *Lock::take().expect("cannot lock") = None; - - info!("stopped"); - } - } - - pub fn pause) -> R, R>(f: F) -> R { - unsafe { - if csr::timer1::en_read() == 0 { - return f(None) - } - - irq::disable(csr::TIMER1_INTERRUPT); - csr::timer1::en_write(0); - - let result = { - let mut profile = Lock::take().expect("cannot lock"); - f(profile.as_mut()) - }; - - irq::enable(csr::TIMER1_INTERRUPT); - csr::timer1::en_write(1); - - result - } - } - - // Skip frames: ::profiler::sample, ::exception, exception vector. - const SKIP_FRAMES: i32 = 3; - - #[inline(always)] // make the top of backtrace predictable - fn record(profile: &mut Profile, exn_pc: usize) -> Result<(), ()> { - let mut result = Ok(()); - let mut frame = -SKIP_FRAMES; - - // If we have storage for edges, use the DWARF unwinder. - // Otherwise, don't bother and use a much faster path that just looks at EPCR. - // Also, acquiring a meaningful backtrace requires libunwind - // with the https://reviews.llvm.org/D46971 patch applied. - if profile.has_edges() { - let mut prev_pc = 0; - let _ = backtrace(|pc| { - // Backtrace gives us the return address, i.e. the address after the delay slot, - // but we're interested in the call instruction, *except* when going through - // the frame directly below the exception frame, which has the address that's - // being executed. - let pc = if pc != exn_pc { pc - 2 * 4 } else { pc }; - - if frame == 0 { - result = result.and_then(|()| - profile.record_hit(Address::new(pc))); - prev_pc = pc; - } else if frame > 0 { - result = result.and_then(|()| - profile.record_edge(Address::new(pc), - Address::new(prev_pc))); - } - - prev_pc = pc; - frame += 1; - }); - } - - // If we couldn't get anything useful out of a backtrace, at least - // record a hit at the exception PC. - if frame <= 0 { - result = profile.record_hit(Address::new(exn_pc)); - } - - result - } - - #[inline(never)] // see above - pub fn sample(pc: usize) { - let result = { - let mut profile = Lock::take().expect("cannot lock"); - record(profile.as_mut().expect("profiler not running"), pc) - }; - - if result.is_err() { - warn!("out of space"); - stop(); - } else { - unsafe { - csr::timer1::ev_pending_write(1); - } - } - } -} - -#[cfg(not(has_timer1))] -mod imp { - #![allow(dead_code)] - - pub fn start(_interval_us: u64, _hits_size: usize, _edges_size: usize) -> Result<(), ()> { - error!("timer not available"); - - Err(()) - } - - pub fn stop() {} - - pub fn pause) -> R, R>(f: F) -> R { - f(None) - } - - pub fn sample(_pc: usize) {} -} - -pub use self::imp::*; diff --git a/artiq/frontend/artiq_coremgmt.py b/artiq/frontend/artiq_coremgmt.py index 39baf26cf..789c26bf7 100755 --- a/artiq/frontend/artiq_coremgmt.py +++ b/artiq/frontend/artiq_coremgmt.py @@ -9,7 +9,6 @@ from artiq import __version__ as artiq_version from artiq.master.databases import DeviceDB from artiq.coredevice.comm_kernel import CommKernel from artiq.coredevice.comm_mgmt import CommMgmt -from artiq.coredevice.profiler import CallgrindWriter def get_argparser(): @@ -86,38 +85,6 @@ def get_argparser(): t_boot = tools.add_parser("reboot", help="reboot the running system") - # profiling - t_profile = tools.add_parser("profile", - help="account for communications CPU time") - - subparsers = t_profile.add_subparsers(dest="action") - subparsers.required = True - - p_start = subparsers.add_parser("start", - help="start profiling") - p_start.add_argument("--interval", metavar="MICROS", type=int, default=2000, - help="sampling interval, in microseconds") - p_start.add_argument("--hits-size", metavar="ENTRIES", type=int, default=8192, - help="hit buffer size") - p_start.add_argument("--edges-size", metavar="ENTRIES", type=int, default=8192, - help="edge buffer size") - - p_stop = subparsers.add_parser("stop", - help="stop profiling") - - p_save = subparsers.add_parser("save", - help="save profile") - p_save.add_argument("output", metavar="OUTPUT", type=argparse.FileType("w"), - help="file to save profile to, in Callgrind format") - p_save.add_argument("firmware", metavar="FIRMWARE", type=str, - help="path to firmware ELF file") - p_save.add_argument("--no-compression", - dest="compression", default=True, action="store_false", - help="disable profile compression") - p_save.add_argument("--no-demangle", - dest="demangle", default=True, action="store_false", - help="disable symbol demangling") - # misc debug t_debug = tools.add_parser("debug", help="specialized debug functions") @@ -174,21 +141,6 @@ def main(): if args.tool == "reboot": mgmt.reboot() - if args.tool == "profile": - if args.action == "start": - mgmt.start_profiler(args.interval, args.hits_size, args.edges_size) - elif args.action == "stop": - mgmt.stop_profiler() - elif args.action == "save": - hits, edges = mgmt.get_profile() - writer = CallgrindWriter(args.output, args.firmware, "or1k-linux", - args.compression, args.demangle) - writer.header() - for addr, count in hits.items(): - writer.hit(addr, count) - for (caller, callee), count in edges.items(): - writer.edge(caller, callee, count) - if args.tool == "debug": if args.action == "allocator": mgmt.debug_allocator() From c69a1316ad438dcde49366cfe0efa5ed386f60a4 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 12:03:39 +0800 Subject: [PATCH 039/238] compiler: stop using sys.version_info for parser --- artiq/compiler/embedding.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/artiq/compiler/embedding.py b/artiq/compiler/embedding.py index 6fa6078f3..89866c7c8 100644 --- a/artiq/compiler/embedding.py +++ b/artiq/compiler/embedding.py @@ -5,7 +5,7 @@ the references to the host objects and translates the functions annotated as ``@kernel`` when they are referenced. """ -import sys, os, re, linecache, inspect, textwrap, types as pytypes, numpy +import os, re, linecache, inspect, textwrap, types as pytypes, numpy from collections import OrderedDict, defaultdict from pythonparser import ast, algorithm, source, diagnostic, parse_buffer @@ -967,13 +967,11 @@ class Stitcher: # Parse. source_buffer = source.Buffer(source_code, filename, first_line) - lexer = source_lexer.Lexer(source_buffer, version=sys.version_info[0:2], - diagnostic_engine=self.engine) + lexer = source_lexer.Lexer(source_buffer, version=(3, 6), diagnostic_engine=self.engine) lexer.indent = [(initial_indent, source.Range(source_buffer, 0, len(initial_whitespace)), initial_whitespace)] - parser = source_parser.Parser(lexer, version=sys.version_info[0:2], - diagnostic_engine=self.engine) + parser = source_parser.Parser(lexer, version=(3, 6), diagnostic_engine=self.engine) function_node = parser.file_input().body[0] # Mangle the name, since we put everything into a single module. From 9f94bc61ae9c80498376b2e15cd45d4d60393b48 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 12:55:37 +0800 Subject: [PATCH 040/238] missing part of 477b1516d --- artiq/firmware/libproto_artiq/mgmt_proto.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/artiq/firmware/libproto_artiq/mgmt_proto.rs b/artiq/firmware/libproto_artiq/mgmt_proto.rs index 5f13ffc96..93f81c40b 100644 --- a/artiq/firmware/libproto_artiq/mgmt_proto.rs +++ b/artiq/firmware/libproto_artiq/mgmt_proto.rs @@ -77,8 +77,6 @@ pub enum Reply<'a> { ConfigData(&'a [u8]), - Profile, - RebootImminent, } From 420891ba54cf7e4e1d0335a4d8ebc6c802f76fb1 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 13:01:35 +0800 Subject: [PATCH 041/238] syntax --- artiq/firmware/runtime/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 0279395b1..95e0f12e9 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -262,7 +262,7 @@ pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) { let vect = irq::Exception::try_from(vect).expect("unknown exception"); match vect { irq::Exception::Interrupt => - panic!("spurious irq {}", irq::pending_mask().trailing_zeros()) + panic!("spurious irq {}", irq::pending_mask().trailing_zeros()), _ => { fn hexdump(addr: u32) { let addr = (addr - addr % 4) as *const u32; From 898122f3e54e7187b2062f4754d5839cdebf9379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Sowi=C5=84ski?= Date: Mon, 16 Aug 2021 07:39:00 +0200 Subject: [PATCH 042/238] Added support for HVAMP_8CH (#1741) --- RELEASE_NOTES.rst | 2 ++ .../coredevice/coredevice_generic.schema.json | 24 ++++++++++++++++++- artiq/frontend/artiq_ddb_template.py | 15 ++++++++++++ artiq/gateware/eem.py | 21 ++++++++++++++++ artiq/gateware/eem_7series.py | 8 +++++++ 5 files changed, 69 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 37af7ed33..862ed148b 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -19,6 +19,8 @@ Highlights: - Expose the DAC coarse mixer and ``sif_sync`` - Exposes upconverter calibration and enabling/disabling of upconverter LO & RF outputs. * ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912 +* New hardware support: + - HVAMP_8CH 8 channel HV amplifier for Fastino / Zotino Breaking changes: diff --git a/artiq/coredevice/coredevice_generic.schema.json b/artiq/coredevice/coredevice_generic.schema.json index 47319fe3e..64e4a9251 100644 --- a/artiq/coredevice/coredevice_generic.schema.json +++ b/artiq/coredevice/coredevice_generic.schema.json @@ -127,7 +127,7 @@ "properties": { "type": { "type": "string", - "enum": ["dio", "urukul", "novogorny", "sampler", "suservo", "zotino", "grabber", "mirny", "fastino", "phaser"] + "enum": ["dio", "urukul", "novogorny", "sampler", "suservo", "zotino", "grabber", "mirny", "fastino", "phaser", "hvamp"] }, "board": { "type": "string" @@ -455,6 +455,28 @@ }, "required": ["ports"] } + }, { + "title": "HVAmp", + "if": { + "properties": { + "type": { + "const": "hvamp" + } + } + }, + "then": { + "properties": { + "ports": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1, + "maxItems": 1 + } + }, + "required": ["ports"] + } }] } } diff --git a/artiq/frontend/artiq_ddb_template.py b/artiq/frontend/artiq_ddb_template.py index 9d7359187..98b4bd5b9 100755 --- a/artiq/frontend/artiq_ddb_template.py +++ b/artiq/frontend/artiq_ddb_template.py @@ -515,6 +515,21 @@ class PeripheralManager: channel=rtio_offset) return 5 + def process_hvamp(self, rtio_offset, peripheral): + hvamp_name = self.get_name("hvamp") + for i in range(8): + self.gen(""" + device_db["ttl_{name}_sw{ch}"] = {{ + "type": "local", + "module": "artiq.coredevice.ttl", + "class": "TTLOut", + "arguments": {{"channel": 0x{channel:06x}}} + }}""", + name=hvamp_name, + ch=i, + channel=rtio_offset+i) + return 8 + def process(self, rtio_offset, peripheral): processor = getattr(self, "process_"+str(peripheral["type"])) return processor(rtio_offset, peripheral) diff --git a/artiq/gateware/eem.py b/artiq/gateware/eem.py index 0180989de..7f5fe3fdf 100644 --- a/artiq/gateware/eem.py +++ b/artiq/gateware/eem.py @@ -660,3 +660,24 @@ class Phaser(_EEM): rtio.Channel.from_phy(phy.ch1.frequency), rtio.Channel.from_phy(phy.ch1.phase_amplitude), ]) + + +class HVAmp(_EEM): + @staticmethod + def io(eem, iostandard): + return [ + ("hvamp{}_out_en".format(eem), i, + Subsignal("p", Pins(_eem_pin(eem, i, "p"))), + Subsignal("n", Pins(_eem_pin(eem, i, "n"))), + iostandard(eem) + ) for i in range(8)] + + @classmethod + def add_std(cls, target, eem, ttl_out_cls, iostandard=default_iostandard): + cls.add_extension(target, eem, iostandard=iostandard) + + for i in range(8): + pads = target.platform.request("hvamp{}_out_en".format(eem), i) + phy = ttl_out_cls(pads.p, pads.n) + target.submodules += phy + target.rtio_channels.append(rtio.Channel.from_phy(phy)) diff --git a/artiq/gateware/eem_7series.py b/artiq/gateware/eem_7series.py index bbd883a83..232150211 100644 --- a/artiq/gateware/eem_7series.py +++ b/artiq/gateware/eem_7series.py @@ -110,6 +110,13 @@ def peripheral_phaser(module, peripheral, **kwargs): eem.Phaser.add_std(module, peripheral["ports"][0], **kwargs) +def peripheral_hvamp(module, peripheral, **kwargs): + if len(peripheral["ports"]) != 1: + raise ValueError("wrong number of ports") + eem.HVAmp.add_std(module, peripheral["ports"][0], + ttl_simple.Output, **kwargs) + + peripheral_processors = { "dio": peripheral_dio, "urukul": peripheral_urukul, @@ -121,6 +128,7 @@ peripheral_processors = { "mirny": peripheral_mirny, "fastino": peripheral_fastino, "phaser": peripheral_phaser, + "hvamp": peripheral_hvamp, } From 4d21a72407bf7b2ef56d0c8f0acb7b2bcf2e8000 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Wed, 18 Aug 2021 15:01:11 +0000 Subject: [PATCH 043/238] Implement SUServo tester. --- artiq/frontend/artiq_sinara_tester.py | 99 ++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/artiq/frontend/artiq_sinara_tester.py b/artiq/frontend/artiq_sinara_tester.py index 5c88d5917..9ca1cb932 100755 --- a/artiq/frontend/artiq_sinara_tester.py +++ b/artiq/frontend/artiq_sinara_tester.py @@ -55,6 +55,8 @@ class SinaraTester(EnvExperiment): self.grabbers = dict() self.mirny_cplds = dict() self.mirnies = dict() + self.suservos = dict() + self.suschannels = dict() ddb = self.get_device_db() for name, desc in ddb.items(): @@ -88,9 +90,13 @@ class SinaraTester(EnvExperiment): self.mirny_cplds[name] = self.get_device(name) elif (module, cls) == ("artiq.coredevice.adf5356", "ADF5356"): self.mirnies[name] = self.get_device(name) + elif (module, cls) == ("artiq.coredevice.suservo", "SUServo"): + self.suservos[name] = self.get_device(name) + elif (module, cls) == ("artiq.coredevice.suservo", "Channel"): + self.suschannels[name] = self.get_device(name) # Remove Urukul, Sampler, Zotino and Mirny control signals - # from TTL outs (tested separately) + # from TTL outs (tested separately) and remove SUServo Urukuls ddb = self.get_device_db() for name, desc in ddb.items(): if isinstance(desc, dict) and desc["type"] == "local": @@ -101,8 +107,17 @@ class SinaraTester(EnvExperiment): sw_device = desc["arguments"]["sw_device"] del self.ttl_outs[sw_device] elif (module, cls) == ("artiq.coredevice.urukul", "CPLD"): - io_update_device = desc["arguments"]["io_update_device"] - del self.ttl_outs[io_update_device] + if "io_update_device" in desc["arguments"]: + io_update_device = desc["arguments"]["io_update_device"] + del self.ttl_outs[io_update_device] + # check for suservos and delete respective urukuls + elif (module, cls) == ("artiq.coredevice.suservo", "SUServo"): + del self.urukuls[desc["arguments"]["dds0_device"]] + del self.urukul_cplds[desc["arguments"]["cpld0_device"]] + if "dds1_device" in desc["arguments"]: + del self.urukuls[desc["arguments"]["dds1_device"]] + if "cpld1_device" in desc["arguments"]: + del self.urukul_cplds[desc["arguments"]["cpld1_device"]] elif (module, cls) == ("artiq.coredevice.sampler", "Sampler"): cnv_device = desc["arguments"]["cnv_device"] del self.ttl_outs[cnv_device] @@ -126,6 +141,8 @@ class SinaraTester(EnvExperiment): self.phasers = sorted(self.phasers.items(), key=lambda x: x[1].channel_base) self.grabbers = sorted(self.grabbers.items(), key=lambda x: x[1].channel_base) self.mirnies = sorted(self.mirnies.items(), key=lambda x: (x[1].cpld.bus.channel, x[1].channel)) + self.suservos = sorted(self.suservos.items(), key=lambda x: x[1].channel) + self.suschannels = sorted(self.suschannels.items(), key=lambda x: x[1].channel) @kernel def test_led(self, led): @@ -555,6 +572,80 @@ class SinaraTester(EnvExperiment): print(card_name) self.grabber_capture(card_dev, rois) + @kernel + def setup_suservo(self, channel): + self.core.break_realtime() + channel.init() + delay(1*us) + # ADC PGIA gain 0 + for i in range(8): + channel.set_pgia_mu(i, 0) + delay(10*us) + # DDS attenuator 10dB + for i in range(4): + channel.cpld0.set_att(i, 10.) + channel.cpld1.set_att(i, 10.) + delay(1*us) + # Servo is done and disabled + assert channel.get_status() & 0xff == 2 + delay(10*us) + + @kernel + def setup_suservo_loop(self, channel, loop_nr): + self.core.break_realtime() + channel.set_y( + profile=loop_nr, + y=0. # clear integrator + ) + channel.set_iir( + profile=loop_nr, + adc=loop_nr, # take data from Sampler channel + kp=-.1, # -0.1 P gain + ki=0./s, # low integrator gain + g=0., # no integrator gain limit + delay=0. # no IIR update delay after enabling + ) + # setpoint 0.5 (5 V with above PGIA gain setting) + # 0 phase + delay(100*us) + channel.set_dds( + profile=loop_nr, + offset=-.3, # 3 V with above PGIA settings + frequency=10*MHz, + phase=0.) + # enable RF, IIR updates and profile 0 + delay(10*us) + channel.set(en_out=1, en_iir=1, profile=loop_nr) + + @kernel + def setup_start_suservo(self, channel): + self.core.break_realtime() + channel.set_config(enable=1) + delay(10*us) + + # check servo enabled + assert channel.get_status() & 0x01 == 1 + delay(10*us) + + def test_suservos(self): + print("*** Testing SUServos.") + print("Initializing...") + for card_n, (card_name, card_dev) in enumerate(self.suservos): + print(card_name + "...") + self.setup_suservo(card_dev) + print("Setup SUServo loops.") + print("Urukul0 channels corresponds to Sampler channels 0-3 and Urukul1 channels correspont to Sampler channels 4-7.") + print("Only proportional gain and offset such that 1.5V on the input gives 6dB less output power than at 0V input. (open loop)") + print("Frequency: 10MHz. Output power at 0V input: ~-29dBm") + for card_n, channels in enumerate(chunker(self.suschannels, 8)): + for channel_n, (channel_name, channel_dev) in enumerate(channels): + self.setup_suservo_loop(channel_dev, channel_n) + print("Enabling...") + for card_n, (card_name, card_dev) in enumerate(self.suservos): + self.setup_start_suservo(card_dev) + print("Press ENTER when done.") + input() + def run(self): print("****** Sinara system tester ******") print("") @@ -579,6 +670,8 @@ class SinaraTester(EnvExperiment): self.test_phasers() if self.grabbers: self.test_grabbers() + if self.suservos: + self.test_suservos() def main(): From a53162d01dd3c952181f7d35b291430629248081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Thu, 19 Aug 2021 09:17:14 +0200 Subject: [PATCH 044/238] tester: tweak suservo * p gain 1 to get reasonable power * refine testing instructions and comments --- artiq/frontend/artiq_sinara_tester.py | 45 +++++++++++++++------------ 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/artiq/frontend/artiq_sinara_tester.py b/artiq/frontend/artiq_sinara_tester.py index 9ca1cb932..ec9f504ee 100755 --- a/artiq/frontend/artiq_sinara_tester.py +++ b/artiq/frontend/artiq_sinara_tester.py @@ -96,7 +96,8 @@ class SinaraTester(EnvExperiment): self.suschannels[name] = self.get_device(name) # Remove Urukul, Sampler, Zotino and Mirny control signals - # from TTL outs (tested separately) and remove SUServo Urukuls + # from TTL outs (tested separately) and remove Urukuls covered by + # SUServo ddb = self.get_device_db() for name, desc in ddb.items(): if isinstance(desc, dict) and desc["type"] == "local": @@ -116,7 +117,6 @@ class SinaraTester(EnvExperiment): del self.urukul_cplds[desc["arguments"]["cpld0_device"]] if "dds1_device" in desc["arguments"]: del self.urukuls[desc["arguments"]["dds1_device"]] - if "cpld1_device" in desc["arguments"]: del self.urukul_cplds[desc["arguments"]["cpld1_device"]] elif (module, cls) == ("artiq.coredevice.sampler", "Sampler"): cnv_device = desc["arguments"]["cnv_device"] @@ -600,20 +600,19 @@ class SinaraTester(EnvExperiment): channel.set_iir( profile=loop_nr, adc=loop_nr, # take data from Sampler channel - kp=-.1, # -0.1 P gain - ki=0./s, # low integrator gain - g=0., # no integrator gain limit - delay=0. # no IIR update delay after enabling + kp=-1., # -1 P gain + ki=0./s, # no integrator gain + g=0., # no integrator gain limit + delay=0. # no IIR update delay after enabling ) # setpoint 0.5 (5 V with above PGIA gain setting) - # 0 phase delay(100*us) channel.set_dds( profile=loop_nr, offset=-.3, # 3 V with above PGIA settings frequency=10*MHz, phase=0.) - # enable RF, IIR updates and profile 0 + # enable RF, IIR updates and set profile delay(10*us) channel.set(en_out=1, en_iir=1, profile=loop_nr) @@ -622,27 +621,33 @@ class SinaraTester(EnvExperiment): self.core.break_realtime() channel.set_config(enable=1) delay(10*us) - # check servo enabled assert channel.get_status() & 0x01 == 1 delay(10*us) def test_suservos(self): print("*** Testing SUServos.") - print("Initializing...") - for card_n, (card_name, card_dev) in enumerate(self.suservos): - print(card_name + "...") + print("Initializing modules...") + for card_name, card_dev in self.suservos: + print(card_name) self.setup_suservo(card_dev) - print("Setup SUServo loops.") - print("Urukul0 channels corresponds to Sampler channels 0-3 and Urukul1 channels correspont to Sampler channels 4-7.") - print("Only proportional gain and offset such that 1.5V on the input gives 6dB less output power than at 0V input. (open loop)") - print("Frequency: 10MHz. Output power at 0V input: ~-29dBm") - for card_n, channels in enumerate(chunker(self.suschannels, 8)): - for channel_n, (channel_name, channel_dev) in enumerate(channels): - self.setup_suservo_loop(channel_dev, channel_n) + print("...done") + print("Setting up SUServo channels...") + for channels in chunker(self.suschannels, 8): + for i, (channel_name, channel_dev) in enumerate(channels): + print(channel_name) + self.setup_suservo_loop(channel_dev, i) + print("...done") print("Enabling...") - for card_n, (card_name, card_dev) in enumerate(self.suservos): + for card_name, card_dev in enumerate(self.suservos): + print(card_name) self.setup_start_suservo(card_dev) + print("...done") + print("Each Sampler channel applies proportional amplitude control") + print("on the respective Urukul0 (ADC 0-3) and Urukul1 (ADC 4-7, if") + print("present) channels.") + print("Frequency: 10 MHz, output power: about -9 dBm at 0 V and about -15 dBm at 1.5 V") + print("Verify frequency and power behavior.") print("Press ENTER when done.") input() From 65f63e6927a6d636e6a67738312c30ac47e9ea30 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Thu, 19 Aug 2021 07:38:48 +0000 Subject: [PATCH 045/238] fix suservo start --- artiq/frontend/artiq_sinara_tester.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/frontend/artiq_sinara_tester.py b/artiq/frontend/artiq_sinara_tester.py index ec9f504ee..078d7db5e 100755 --- a/artiq/frontend/artiq_sinara_tester.py +++ b/artiq/frontend/artiq_sinara_tester.py @@ -639,7 +639,7 @@ class SinaraTester(EnvExperiment): self.setup_suservo_loop(channel_dev, i) print("...done") print("Enabling...") - for card_name, card_dev in enumerate(self.suservos): + for card_name, card_dev in self.suservos: print(card_name) self.setup_start_suservo(card_dev) print("...done") From 65f8a97b56656e321e3a36b7d187b805723034cb Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Wed, 1 Sep 2021 17:39:08 +0200 Subject: [PATCH 046/238] phaser: add helpers to align updates to the RTIO timeline Signed-off-by: Etienne Wodey --- RELEASE_NOTES.rst | 1 + artiq/coredevice/phaser.py | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 862ed148b..b1a762752 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -18,6 +18,7 @@ Highlights: - Improved documentation - Expose the DAC coarse mixer and ``sif_sync`` - Exposes upconverter calibration and enabling/disabling of upconverter LO & RF outputs. + - Add helpers to align Phaser updates to the RTIO timeline (``get_next_frame_timestamp()``) * ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912 * New hardware support: - HVAMP_8CH 8 channel HV amplifier for Fastino / Zotino diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index c8c3c0938..f6a84fd72 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -1,7 +1,8 @@ from numpy import int32, int64 from artiq.language.core import kernel, delay_mu, delay -from artiq.coredevice.rtio import rtio_output, rtio_input_data +from artiq.coredevice.rtio import rtio_output, rtio_input_data, rtio_input_timestamp +from artiq.coredevice.core import rtio_get_counter from artiq.language.units import us, ns, ms, MHz from artiq.language.types import TInt32 from artiq.coredevice.dac34h84 import DAC34H84 @@ -160,6 +161,7 @@ class Phaser: # self.core.seconds_to_mu(10*8*4*ns) # unfortunately this returns 319 assert self.core.ref_period == 1*ns self.t_frame = 10*8*4 + self.frame_tstamp = int64(0) self.clk_sel = clk_sel self.tune_fifo_offset = tune_fifo_offset self.sync_dly = sync_dly @@ -197,6 +199,9 @@ class Phaser: raise ValueError("large number of frame CRC errors") delay(.1*ms) # slack + # determine the origin for frame-aligned timestamps + self.measure_frame_timestamp() + # reset self.set_cfg(dac_resetb=0, dac_sleep=1, dac_txena=0, trf0_ps=1, trf1_ps=1, @@ -468,6 +473,32 @@ class Phaser: """ return self.read8(PHASER_ADDR_CRC_ERR) + @kernel + def measure_frame_timestamp(self): + """Perform a register read and record the exact frame timing in `self.frame_tstamp`. + + Deterministic timing requires updates to be schedule at multiples of `self.t_frame` later. + See `get_next_frame_timestamp()`. + """ + rtio_output((self.channel_base << 8) | (PHASER_ADDR_BOARD_ID & 0x7f), 0) # can read any register + delay_mu(int64(self.t_frame)) + self.frame_tstamp = rtio_input_timestamp(rtio_get_counter() + 0xffffff, self.channel_base) + delay(10*ms) + + @kernel + def get_next_frame_timestamp(self, after_timestamp_mu = int64(-1)): + """Return the RTIO timestamp of the next frame after `after_timestamp_mu`. + + If `after_timestamp_mu < 0`, return the next frame after `now_mu()`. + + Updates scheduled at this timestamp and multiples of `self.t_frame` later will + have deterministic latency with respect to the RTIO timeline. + """ + if after_timestamp_mu < 0: + after_timestamp_mu = now_mu() + n = int64((after_timestamp_mu - self.frame_tstamp) / self.t_frame) + return self.frame_tstamp + (n + 1) * self.t_frame + @kernel def set_sync_dly(self, dly): """Set SYNC delay. From 61b44d40ddb6c51debcb0ced6f49729ec2fa4b77 Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Wed, 1 Sep 2021 17:43:30 +0200 Subject: [PATCH 047/238] phaser: add labels to debug init prints Signed-off-by: Etienne Wodey --- artiq/coredevice/phaser.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index f6a84fd72..efd0a895f 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -190,7 +190,7 @@ class Phaser: gw_rev = self.read8(PHASER_ADDR_GW_REV) if debug: - print(gw_rev) + print("gw_rev:", gw_rev) self.core.break_realtime() delay(.1*ms) # slack @@ -267,7 +267,7 @@ class Phaser: if self.tune_fifo_offset: fifo_offset = self.dac_tune_fifo_offset() if debug: - print(fifo_offset) + print("fifo_offset:", fifo_offset) self.core.break_realtime() # self.dac_write(0x20, 0x0000) # stop fifo sync @@ -279,7 +279,7 @@ class Phaser: delay(.1*ms) # slack if alarms & ~0x0040: # ignore PLL alarms (see DS) if debug: - print(alarms) + print("alarms:", alarms) self.core.break_realtime() # ignore alarms else: From 7aebf02f8435e8c2c58c23b02ed6b75d8206fafb Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Wed, 1 Sep 2021 17:44:46 +0200 Subject: [PATCH 048/238] phaser: docs: add reference to get_next_frame_timestamps(), fix typo Signed-off-by: Etienne Wodey --- artiq/coredevice/phaser.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index efd0a895f..cd9bc8d74 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -93,7 +93,8 @@ class Phaser: The latency/group delay from the RTIO events setting :class:`PhaserOscillator` or :class:`PhaserChannel` DUC parameters all the way to the DAC outputs is deterministic. This enables deterministic - absolute phase with respect to other RTIO input and output events. + absolute phase with respect to other RTIO input and output events + (see `get_next_frame_timestamp()`). The four analog DAC outputs are passed through anti-aliasing filters. @@ -891,7 +892,7 @@ class PhaserChannel: By default, the new NCO phase applies on completion of the SPI transfer. This also causes a staged NCO frequency to be applied. - Different triggers for applying nco settings may be configured through + Different triggers for applying NCO settings may be configured through the `syncsel_mixerxx` fields in the `dac` configuration dictionary (see `__init__()`). @@ -909,7 +910,7 @@ class PhaserChannel: By default, the new NCO phase applies on completion of the SPI transfer. This also causes a staged NCO frequency to be applied. - Different triggers for applying nco settings may be configured through + Different triggers for applying NCO settings may be configured through the `syncsel_mixerxx` fields in the `dac` configuration dictionary (see `__init__()`). @@ -1046,7 +1047,7 @@ class PhaserOscillator: """Phaser IQ channel oscillator (NCO/DDS). .. note:: Latencies between oscillators within a channel and between - oscillator paramters (amplitude and phase/frequency) are deterministic + oscillator parameters (amplitude and phase/frequency) are deterministic (with respect to the 25 MS/s sample clock) but not matched. """ kernel_invariants = {"channel", "base_addr"} From 075cb26dd798383bdd99d447134d8dfc799d2341 Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Fri, 3 Sep 2021 09:58:01 +0200 Subject: [PATCH 049/238] phaser: rename get_next_frame_timestamp() to get_next_frame_mu() and implement review comments (PR #1749) Signed-off-by: Etienne Wodey --- artiq/coredevice/phaser.py | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index cd9bc8d74..782306208 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -94,7 +94,7 @@ class Phaser: :class:`PhaserOscillator` or :class:`PhaserChannel` DUC parameters all the way to the DAC outputs is deterministic. This enables deterministic absolute phase with respect to other RTIO input and output events - (see `get_next_frame_timestamp()`). + (see `get_next_frame_mu()`). The four analog DAC outputs are passed through anti-aliasing filters. @@ -476,28 +476,23 @@ class Phaser: @kernel def measure_frame_timestamp(self): - """Perform a register read and record the exact frame timing in `self.frame_tstamp`. + """Measure the timestamp of an arbitrary frame and store it in `self.frame_tstamp`. - Deterministic timing requires updates to be schedule at multiples of `self.t_frame` later. - See `get_next_frame_timestamp()`. + To be used as reference for aligning updates to the FastLink frames. + See `get_next_frame_mu()`. """ - rtio_output((self.channel_base << 8) | (PHASER_ADDR_BOARD_ID & 0x7f), 0) # can read any register - delay_mu(int64(self.t_frame)) - self.frame_tstamp = rtio_input_timestamp(rtio_get_counter() + 0xffffff, self.channel_base) - delay(10*ms) + rtio_output(self.channel_base << 8, 0) # read any register + self.frame_tstamp = rtio_input_timestamp(rtio_get_counter() + 125_000, self.channel_base) + delay(100 * us) @kernel - def get_next_frame_timestamp(self, after_timestamp_mu = int64(-1)): - """Return the RTIO timestamp of the next frame after `after_timestamp_mu`. + def get_next_frame_mu(self): + """Return the timestamp of the frame strictly after `now_mu()`. - If `after_timestamp_mu < 0`, return the next frame after `now_mu()`. - - Updates scheduled at this timestamp and multiples of `self.t_frame` later will - have deterministic latency with respect to the RTIO timeline. + Register updates (DUC, DAC, TRF, etc.) scheduled at this timestamp and multiples + of `self.t_frame` later will have deterministic latency to output. """ - if after_timestamp_mu < 0: - after_timestamp_mu = now_mu() - n = int64((after_timestamp_mu - self.frame_tstamp) / self.t_frame) + n = int64((now_mu() - self.frame_tstamp) / self.t_frame) return self.frame_tstamp + (n + 1) * self.t_frame @kernel From 4d7bd3ee32f0b21c13542457d6a14a04e4fcd2f9 Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Fri, 3 Sep 2021 10:58:11 +0200 Subject: [PATCH 050/238] phaser: fail init() if frame timestamp measurement times out Signed-off-by: Etienne Wodey --- RELEASE_NOTES.rst | 2 +- artiq/coredevice/phaser.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index b1a762752..e011739d8 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -18,7 +18,7 @@ Highlights: - Improved documentation - Expose the DAC coarse mixer and ``sif_sync`` - Exposes upconverter calibration and enabling/disabling of upconverter LO & RF outputs. - - Add helpers to align Phaser updates to the RTIO timeline (``get_next_frame_timestamp()``) + - Add helpers to align Phaser updates to the RTIO timeline (``get_next_frame_mu()``) * ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912 * New hardware support: - HVAMP_8CH 8 channel HV amplifier for Fastino / Zotino diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index 782306208..daaed659d 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -2,7 +2,6 @@ from numpy import int32, int64 from artiq.language.core import kernel, delay_mu, delay from artiq.coredevice.rtio import rtio_output, rtio_input_data, rtio_input_timestamp -from artiq.coredevice.core import rtio_get_counter from artiq.language.units import us, ns, ms, MHz from artiq.language.types import TInt32 from artiq.coredevice.dac34h84 import DAC34H84 @@ -202,6 +201,8 @@ class Phaser: # determine the origin for frame-aligned timestamps self.measure_frame_timestamp() + if self.frame_tstamp < 0: + raise ValueError("frame timestamp measurement timed out") # reset self.set_cfg(dac_resetb=0, dac_sleep=1, dac_txena=0, @@ -482,7 +483,7 @@ class Phaser: See `get_next_frame_mu()`. """ rtio_output(self.channel_base << 8, 0) # read any register - self.frame_tstamp = rtio_input_timestamp(rtio_get_counter() + 125_000, self.channel_base) + self.frame_tstamp = rtio_input_timestamp(now_mu() + 4 * self.t_frame, self.channel_base) delay(100 * us) @kernel From 2cf144a60ccca1f1306f6c422c0450967c98fb67 Mon Sep 17 00:00:00 2001 From: Leon Riesebos Date: Fri, 3 Sep 2021 18:03:52 -0400 Subject: [PATCH 051/238] ddb_template: edge counter keys correspond with according ttl keys previously ttl_counter_0 and ttl_0 could be on completely different physical ttl output channels with this change, ttl_0_counter (note the changed key format) is always on the same channel as ttl_0 Signed-off-by: Leon Riesebos --- RELEASE_NOTES.rst | 2 ++ artiq/frontend/artiq_ddb_template.py | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index e011739d8..390665643 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -22,6 +22,8 @@ Highlights: * ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912 * New hardware support: - HVAMP_8CH 8 channel HV amplifier for Fastino / Zotino +* ``artiq_ddb_template`` generates edge-counter keys that start with the key of the corresponding + TTL device (e.g. ``"ttl_0_counter"`` for the edge counter on TTL device``"ttl_0"``) Breaking changes: diff --git a/artiq/frontend/artiq_ddb_template.py b/artiq/frontend/artiq_ddb_template.py index 98b4bd5b9..c73680c8e 100755 --- a/artiq/frontend/artiq_ddb_template.py +++ b/artiq/frontend/artiq_ddb_template.py @@ -82,7 +82,7 @@ class PeripheralManager: def gen(self, string, **kwargs): print(textwrap.dedent(string).format(**kwargs), file=self.output) - def process_dio(self, rtio_offset, peripheral): + def process_dio(self, rtio_offset, peripheral, num_channels=8): class_names = { "input": "TTLInOut", "output": "TTLOut" @@ -92,7 +92,8 @@ class PeripheralManager: class_names[peripheral["bank_direction_high"]] ] channel = count(0) - for i in range(8): + name = [self.get_name("ttl") for _ in range(num_channels)] + for i in range(num_channels): self.gen(""" device_db["{name}"] = {{ "type": "local", @@ -101,23 +102,23 @@ class PeripheralManager: "arguments": {{"channel": 0x{channel:06x}}}, }} """, - name=self.get_name("ttl"), - class_name=classes[i//4], - channel=rtio_offset+next(channel)) + name=name[i], + class_name=classes[i // 4], + channel=rtio_offset + next(channel)) if peripheral.get("edge_counter", False): - for i in range(8): - class_name = classes[i//4] + for i in range(num_channels): + class_name = classes[i // 4] if class_name == "TTLInOut": self.gen(""" - device_db["{name}"] = {{ + device_db["{name}_counter"] = {{ "type": "local", "module": "artiq.coredevice.edge_counter", "class": "EdgeCounter", "arguments": {{"channel": 0x{channel:06x}}}, }} """, - name=self.get_name("ttl_counter"), - channel=rtio_offset+next(channel)) + name=name[i], + channel=rtio_offset + next(channel)) return next(channel) def process_urukul(self, rtio_offset, peripheral): From 82b4052cd6b357f640d36d300dbb7e27c7eaff20 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 14 Jul 2021 17:44:44 +0800 Subject: [PATCH 052/238] libboard_misoc: vexriscv integration Signed-off-by: occheung --- artiq/firmware/libboard_misoc/Cargo.toml | 2 + artiq/firmware/libboard_misoc/lib.rs | 12 +- .../libboard_misoc/riscv32imac/boot.rs | 48 +++++ .../libboard_misoc/riscv32imac/cache.rs | 35 ++++ .../libboard_misoc/riscv32imac/irq.rs | 46 +++++ .../libboard_misoc/riscv32imac/mod.rs | 3 + .../libboard_misoc/riscv32imac/vectors.S | 177 ++++++++++++++++++ 7 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 artiq/firmware/libboard_misoc/riscv32imac/boot.rs create mode 100644 artiq/firmware/libboard_misoc/riscv32imac/cache.rs create mode 100644 artiq/firmware/libboard_misoc/riscv32imac/irq.rs create mode 100644 artiq/firmware/libboard_misoc/riscv32imac/mod.rs create mode 100644 artiq/firmware/libboard_misoc/riscv32imac/vectors.S diff --git a/artiq/firmware/libboard_misoc/Cargo.toml b/artiq/firmware/libboard_misoc/Cargo.toml index 81ebf979f..2c817dd65 100644 --- a/artiq/firmware/libboard_misoc/Cargo.toml +++ b/artiq/firmware/libboard_misoc/Cargo.toml @@ -16,6 +16,8 @@ build_misoc = { path = "../libbuild_misoc" } byteorder = { version = "1.0", default-features = false } log = { version = "0.4", default-features = false, optional = true } smoltcp = { version = "0.6.0", default-features = false, optional = true } +riscv = { version = "0.6.0", features = ["inline-asm"] } +vexriscv = { git = "https://github.com/occheung/vexriscv-rust.git", features = ["inline-asm"] } [features] uart_console = [] diff --git a/artiq/firmware/libboard_misoc/lib.rs b/artiq/firmware/libboard_misoc/lib.rs index 5e8a92972..1d94270d8 100644 --- a/artiq/firmware/libboard_misoc/lib.rs +++ b/artiq/firmware/libboard_misoc/lib.rs @@ -1,5 +1,5 @@ #![no_std] -#![feature(asm, try_from)] +#![feature(llvm_asm)] extern crate byteorder; #[cfg(feature = "log")] @@ -11,6 +11,16 @@ extern crate smoltcp; #[path = "or1k/mod.rs"] mod arch; +#[cfg(target_arch = "riscv32")] +#[path = "riscv32imac/mod.rs"] +mod arch; + +#[cfg(target_arch = "riscv32")] +extern crate riscv; + +#[cfg(target_arch = "riscv32")] +extern crate vexriscv; + pub use arch::*; include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/mem.rs")); diff --git a/artiq/firmware/libboard_misoc/riscv32imac/boot.rs b/artiq/firmware/libboard_misoc/riscv32imac/boot.rs new file mode 100644 index 000000000..19f7b6fa6 --- /dev/null +++ b/artiq/firmware/libboard_misoc/riscv32imac/boot.rs @@ -0,0 +1,48 @@ +use super::{irq, cache}; + +pub unsafe fn reset() -> ! { + irq::set_ie(false); + llvm_asm!(r#" + j _reset_handler + nop + "# : : : : "volatile"); + loop {} +} + +pub unsafe fn jump(addr: usize) -> ! { + irq::set_ie(false); + cache::flush_cpu_icache(); + llvm_asm!(r#" + jalr x0, 0($0) + nop + "# : : "r"(addr) : : "volatile"); + loop {} +} + +pub unsafe fn hotswap(firmware: &[u8]) -> ! { + irq::set_ie(false); + llvm_asm!(r#" + # This loop overwrites itself, but it's structured in such a way + # that before that happens, it loads itself into I$$ fully. + lui a1, %hi(_reset_handler) + ori a1, a1, %lo(_reset_handler) + or a4, a1, zero + 0: bnez a2, 1f + nop + jr a4 + nop + 1: lw a3, 0(a0) + sw a3, 0(a1) + addi a0, a0, 4 + addi a1, a1, 4 + addi a2, a2, -4 + bnez a2, 0b + nop + "# + : + : "{a0}"(firmware.as_ptr() as usize), + "{a2}"(firmware.len()) + : + : "volatile"); + loop {} +} diff --git a/artiq/firmware/libboard_misoc/riscv32imac/cache.rs b/artiq/firmware/libboard_misoc/riscv32imac/cache.rs new file mode 100644 index 000000000..12fc9f3bb --- /dev/null +++ b/artiq/firmware/libboard_misoc/riscv32imac/cache.rs @@ -0,0 +1,35 @@ +#[cfg(has_ddrphy)] +use core::ptr; +#[cfg(has_ddrphy)] +use csr; +#[cfg(has_ddrphy)] +use mem; + +pub fn flush_cpu_icache() { + unsafe { + llvm_asm!(r#" + fence.i + nop + nop + nop + nop + nop + "# : : : : "volatile"); + } +} + +pub fn flush_cpu_dcache() { + unsafe { + llvm_asm!(".word(0x500F)" : : : : "volatile"); + } +} + +#[cfg(has_ddrphy)] +pub fn flush_l2_cache() { + unsafe { + for i in 0..2 * (csr::CONFIG_L2_SIZE as usize) / 4 { + let addr = mem::MAIN_RAM_BASE + i * 4; + ptr::read_volatile(addr as *const usize); + } + } +} diff --git a/artiq/firmware/libboard_misoc/riscv32imac/irq.rs b/artiq/firmware/libboard_misoc/riscv32imac/irq.rs new file mode 100644 index 000000000..4b4120fd1 --- /dev/null +++ b/artiq/firmware/libboard_misoc/riscv32imac/irq.rs @@ -0,0 +1,46 @@ +use core::{convert::TryFrom}; +use riscv::register::mstatus; +use vexriscv::register::{vmim, vmip}; + +#[inline] +pub fn get_ie() -> bool { + mstatus::read().mie() +} + +#[inline] +pub fn set_ie(ie: bool) { + unsafe { + if ie { + mstatus::set_mie() + } else { + mstatus::clear_mie() + } + } +} + +#[inline] +pub fn get_mask() -> u32 { + u32::try_from(vmim::read()).unwrap() +} + +#[inline] +pub fn set_mask(mask: u32) { + vmim::write(usize::try_from(mask).unwrap()) +} + +#[inline] +pub fn pending_mask() -> u32 { + u32::try_from(vmip::read()).unwrap() +} + +pub fn enable(irq: u32) { + set_mask(get_mask() | (1 << irq)) +} + +pub fn disable(irq: u32) { + set_mask(get_mask() & !(1 << irq)) +} + +pub fn is_pending(irq: u32) -> bool { + get_mask() & (1 << irq) != 0 +} diff --git a/artiq/firmware/libboard_misoc/riscv32imac/mod.rs b/artiq/firmware/libboard_misoc/riscv32imac/mod.rs new file mode 100644 index 000000000..8dd6e5b3c --- /dev/null +++ b/artiq/firmware/libboard_misoc/riscv32imac/mod.rs @@ -0,0 +1,3 @@ +pub mod irq; +pub mod cache; +pub mod boot; diff --git a/artiq/firmware/libboard_misoc/riscv32imac/vectors.S b/artiq/firmware/libboard_misoc/riscv32imac/vectors.S new file mode 100644 index 000000000..a571a4903 --- /dev/null +++ b/artiq/firmware/libboard_misoc/riscv32imac/vectors.S @@ -0,0 +1,177 @@ +# Adapted from riscv-rt project, with the following license: +# +# Copyright 2018 RISC-V team +# +# Permission to use, copy, modify, and/or distribute this software for any purpose +# with or without fee is hereby granted, provided that the above copyright notice and +# this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +# FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, +# OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA +# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +#if __riscv_xlen == 64 +# define STORE sd +# define LOAD ld +# define LOG_REGBYTES 3 +#else +# define STORE sw +# define LOAD lw +# define LOG_REGBYTES 2 +#endif +#define REGBYTES (1 << LOG_REGBYTES) + +/* + Entry point of all programs (_reset_handler). + + It initializes DWARF call frame information, the stack pointer, the + frame pointer (needed for closures to work in start_rust) and the global + pointer. Then it calls _start_rust. +*/ + +.section .vectors, "ax", @progbits +.global _reset_handler + +_reset_handler: + /* Jump to the absolute address defined by the linker script. */ + // for 32bit + .if __riscv_xlen == 32 + lui ra, %hi(_abs_start) + jr %lo(_abs_start)(ra) + .endif + + // for 64bit + .if __riscv_xlen == 64 +.option push +.option norelax // to prevent an unsupported R_RISCV_ALIGN relocation from being generated +1: + auipc ra, %pcrel_hi(1f) + ld ra, %pcrel_lo(1b)(ra) + jr ra + .align 3 +1: + .dword _abs_start +.option pop + .endif + +_abs_start: + .cfi_startproc + .cfi_undefined ra + + csrw mie, 0 + csrw mip, 0 + + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10,0 + li x11,0 + li x12,0 + li x13,0 + li x14,0 + li x15,0 + li x16,0 + li x17,0 + li x18,0 + li x19,0 + li x20,0 + li x21,0 + li x22,0 + li x23,0 + li x24,0 + li x25,0 + li x26,0 + li x27,0 + li x28,0 + li x29,0 + li x30,0 + li x31,0 + + // Check hart id + csrr a2, mhartid + + // Allocate stacks + la sp, _fstack + + // Set frame pointer + add s0, sp, zero + + // Set trap vector + la t0, _start_trap + csrw mtvec, t0 + + // Zero initialize .bss + la t0, _fbss + la t1, _ebss + beq t0, t1, 2f +1: STORE zero, 0(t0) + addi t0, t0, REGBYTES + bne t0, t1, 1b +2: + // Enter main firmware + jal zero, main + + .cfi_endproc + +/* + Trap entry point (_start_trap) + + Saves caller saved registers ra, t0..6, a0..7, calls exception, + restores caller saved registers and then returns. +*/ +.section .trap, "ax" +.global _start_trap +/* Make it .weak so PAC/HAL can provide their own if needed. */ +.weak _start_trap + +_start_trap: + addi sp, sp, -16*REGBYTES + + STORE ra, 0*REGBYTES(sp) + STORE t0, 1*REGBYTES(sp) + STORE t1, 2*REGBYTES(sp) + STORE t2, 3*REGBYTES(sp) + STORE t3, 4*REGBYTES(sp) + STORE t4, 5*REGBYTES(sp) + STORE t5, 6*REGBYTES(sp) + STORE t6, 7*REGBYTES(sp) + STORE a0, 8*REGBYTES(sp) + STORE a1, 9*REGBYTES(sp) + STORE a2, 10*REGBYTES(sp) + STORE a3, 11*REGBYTES(sp) + STORE a4, 12*REGBYTES(sp) + STORE a5, 13*REGBYTES(sp) + STORE a6, 14*REGBYTES(sp) + STORE a7, 15*REGBYTES(sp) + + add a0, sp, zero + jal ra, exception + + LOAD ra, 0*REGBYTES(sp) + LOAD t0, 1*REGBYTES(sp) + LOAD t1, 2*REGBYTES(sp) + LOAD t2, 3*REGBYTES(sp) + LOAD t3, 4*REGBYTES(sp) + LOAD t4, 5*REGBYTES(sp) + LOAD t5, 6*REGBYTES(sp) + LOAD t6, 7*REGBYTES(sp) + LOAD a0, 8*REGBYTES(sp) + LOAD a1, 9*REGBYTES(sp) + LOAD a2, 10*REGBYTES(sp) + LOAD a3, 11*REGBYTES(sp) + LOAD a4, 12*REGBYTES(sp) + LOAD a5, 13*REGBYTES(sp) + LOAD a6, 14*REGBYTES(sp) + LOAD a7, 15*REGBYTES(sp) + + addi sp, sp, 16*REGBYTES + mret From 9aee42f0f27ef121a156a0ae2730e747fc0040a9 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 15 Jul 2021 15:41:36 +0800 Subject: [PATCH 053/238] rv32/boot: remove hotswap Signed-off-by: occheung --- .../libboard_misoc/riscv32imac/boot.rs | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/artiq/firmware/libboard_misoc/riscv32imac/boot.rs b/artiq/firmware/libboard_misoc/riscv32imac/boot.rs index 19f7b6fa6..32e9cfbc3 100644 --- a/artiq/firmware/libboard_misoc/riscv32imac/boot.rs +++ b/artiq/firmware/libboard_misoc/riscv32imac/boot.rs @@ -1,7 +1,6 @@ -use super::{irq, cache}; +use super::cache; pub unsafe fn reset() -> ! { - irq::set_ie(false); llvm_asm!(r#" j _reset_handler nop @@ -10,7 +9,6 @@ pub unsafe fn reset() -> ! { } pub unsafe fn jump(addr: usize) -> ! { - irq::set_ie(false); cache::flush_cpu_icache(); llvm_asm!(r#" jalr x0, 0($0) @@ -18,31 +16,3 @@ pub unsafe fn jump(addr: usize) -> ! { "# : : "r"(addr) : : "volatile"); loop {} } - -pub unsafe fn hotswap(firmware: &[u8]) -> ! { - irq::set_ie(false); - llvm_asm!(r#" - # This loop overwrites itself, but it's structured in such a way - # that before that happens, it loads itself into I$$ fully. - lui a1, %hi(_reset_handler) - ori a1, a1, %lo(_reset_handler) - or a4, a1, zero - 0: bnez a2, 1f - nop - jr a4 - nop - 1: lw a3, 0(a0) - sw a3, 0(a1) - addi a0, a0, 4 - addi a1, a1, 4 - addi a2, a2, -4 - bnez a2, 0b - nop - "# - : - : "{a0}"(firmware.as_ptr() as usize), - "{a2}"(firmware.len()) - : - : "volatile"); - loop {} -} From b87ea79d5169080fc3cce63c1fba841a0ddc5ff8 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 15 Jul 2021 15:50:34 +0800 Subject: [PATCH 054/238] rv32: rm irq & vexriscv-rust Signed-off-by: occheung --- artiq/firmware/libboard_misoc/Cargo.toml | 1 - artiq/firmware/libboard_misoc/lib.rs | 3 -- .../libboard_misoc/riscv32imac/irq.rs | 46 ------------------- .../libboard_misoc/riscv32imac/mod.rs | 1 - 4 files changed, 51 deletions(-) delete mode 100644 artiq/firmware/libboard_misoc/riscv32imac/irq.rs diff --git a/artiq/firmware/libboard_misoc/Cargo.toml b/artiq/firmware/libboard_misoc/Cargo.toml index 2c817dd65..0d8d705cc 100644 --- a/artiq/firmware/libboard_misoc/Cargo.toml +++ b/artiq/firmware/libboard_misoc/Cargo.toml @@ -17,7 +17,6 @@ byteorder = { version = "1.0", default-features = false } log = { version = "0.4", default-features = false, optional = true } smoltcp = { version = "0.6.0", default-features = false, optional = true } riscv = { version = "0.6.0", features = ["inline-asm"] } -vexriscv = { git = "https://github.com/occheung/vexriscv-rust.git", features = ["inline-asm"] } [features] uart_console = [] diff --git a/artiq/firmware/libboard_misoc/lib.rs b/artiq/firmware/libboard_misoc/lib.rs index 1d94270d8..b9e0cec38 100644 --- a/artiq/firmware/libboard_misoc/lib.rs +++ b/artiq/firmware/libboard_misoc/lib.rs @@ -18,9 +18,6 @@ mod arch; #[cfg(target_arch = "riscv32")] extern crate riscv; -#[cfg(target_arch = "riscv32")] -extern crate vexriscv; - pub use arch::*; include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/mem.rs")); diff --git a/artiq/firmware/libboard_misoc/riscv32imac/irq.rs b/artiq/firmware/libboard_misoc/riscv32imac/irq.rs deleted file mode 100644 index 4b4120fd1..000000000 --- a/artiq/firmware/libboard_misoc/riscv32imac/irq.rs +++ /dev/null @@ -1,46 +0,0 @@ -use core::{convert::TryFrom}; -use riscv::register::mstatus; -use vexriscv::register::{vmim, vmip}; - -#[inline] -pub fn get_ie() -> bool { - mstatus::read().mie() -} - -#[inline] -pub fn set_ie(ie: bool) { - unsafe { - if ie { - mstatus::set_mie() - } else { - mstatus::clear_mie() - } - } -} - -#[inline] -pub fn get_mask() -> u32 { - u32::try_from(vmim::read()).unwrap() -} - -#[inline] -pub fn set_mask(mask: u32) { - vmim::write(usize::try_from(mask).unwrap()) -} - -#[inline] -pub fn pending_mask() -> u32 { - u32::try_from(vmip::read()).unwrap() -} - -pub fn enable(irq: u32) { - set_mask(get_mask() | (1 << irq)) -} - -pub fn disable(irq: u32) { - set_mask(get_mask() & !(1 << irq)) -} - -pub fn is_pending(irq: u32) -> bool { - get_mask() & (1 << irq) != 0 -} diff --git a/artiq/firmware/libboard_misoc/riscv32imac/mod.rs b/artiq/firmware/libboard_misoc/riscv32imac/mod.rs index 8dd6e5b3c..217ef713f 100644 --- a/artiq/firmware/libboard_misoc/riscv32imac/mod.rs +++ b/artiq/firmware/libboard_misoc/riscv32imac/mod.rs @@ -1,3 +1,2 @@ -pub mod irq; pub mod cache; pub mod boot; From 46102ee737faab90adbdf142bfd963014c740820 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 15 Jul 2021 15:51:57 +0800 Subject: [PATCH 055/238] board_misoc: build vectors.S with rv64 target in misoc Signed-off-by: occheung --- artiq/firmware/libboard_misoc/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/artiq/firmware/libboard_misoc/build.rs b/artiq/firmware/libboard_misoc/build.rs index c0a5971eb..efea565bf 100644 --- a/artiq/firmware/libboard_misoc/build.rs +++ b/artiq/firmware/libboard_misoc/build.rs @@ -13,6 +13,7 @@ fn main() { println!("cargo:rerun-if-changed={}", vectors_path.to_str().unwrap()); cc::Build::new() + .flag("--target=riscv64-unknown-elf") .file(vectors_path) .compile("vectors"); } From 13032272fdd02121d10189de355af98e1a56dd7d Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 15 Jul 2021 15:58:13 +0800 Subject: [PATCH 056/238] bootloader: add rv32 exception handler Signed-off-by: occheung --- artiq/firmware/bootloader/Cargo.toml | 1 + artiq/firmware/bootloader/main.rs | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/artiq/firmware/bootloader/Cargo.toml b/artiq/firmware/bootloader/Cargo.toml index e89902308..5c2a54ba5 100644 --- a/artiq/firmware/bootloader/Cargo.toml +++ b/artiq/firmware/bootloader/Cargo.toml @@ -17,3 +17,4 @@ byteorder = { version = "1.0", default-features = false } crc = { version = "1.7", default-features = false } board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp"] } smoltcp = { version = "0.6.0", default-features = false, features = ["ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } +riscv = { version = "0.6.0", features = ["inline-asm"] } diff --git a/artiq/firmware/bootloader/main.rs b/artiq/firmware/bootloader/main.rs index ad6479486..bb7030051 100644 --- a/artiq/firmware/bootloader/main.rs +++ b/artiq/firmware/bootloader/main.rs @@ -6,8 +6,9 @@ extern crate byteorder; extern crate smoltcp; #[macro_use] extern crate board_misoc; +extern crate riscv; -use core::{ptr, slice}; +use core::{ptr, slice, convert::TryFrom}; use crc::crc32; use byteorder::{ByteOrder, BigEndian}; use board_misoc::{ident, cache, sdram, config, boot, mem as board_mem}; @@ -16,6 +17,7 @@ use board_misoc::slave_fpga; #[cfg(has_ethmac)] use board_misoc::{clock, ethmac, net_settings}; use board_misoc::uart_console::Console; +use riscv::register::{mcause, mepc}; fn check_integrity() -> bool { extern { @@ -517,8 +519,10 @@ pub extern fn main() -> i32 { } #[no_mangle] -pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) { - panic!("exception {} at PC {:#08x}, EA {:#08x}", vect, pc, ea) +pub extern fn exception(_regs: *const u32) { + let pc = mepc::read(); + let cause = mcause::read().cause(); + panic!("{:?} at PC {:#08x}", cause, u32::try_from(pc).unwrap()) } #[no_mangle] From 8294d7fea560258cff04cea1192ee38900458bbb Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 15 Jul 2021 15:59:18 +0800 Subject: [PATCH 057/238] bootloader: swap endianness Signed-off-by: occheung --- artiq/firmware/bootloader/Makefile | 3 ++- artiq/firmware/bootloader/main.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/artiq/firmware/bootloader/Makefile b/artiq/firmware/bootloader/Makefile index ee70ff22f..d5a34f5ba 100644 --- a/artiq/firmware/bootloader/Makefile +++ b/artiq/firmware/bootloader/Makefile @@ -14,4 +14,5 @@ bootloader.elf: $(RUSTOUT)/libbootloader.a %.bin: %.elf $(objcopy) -O binary - $(MSCIMG) $@ + $(MSCIMG) $@ --little + objcopy -I binary -O binary --reverse-bytes=4 $@ diff --git a/artiq/firmware/bootloader/main.rs b/artiq/firmware/bootloader/main.rs index bb7030051..daa3a9be7 100644 --- a/artiq/firmware/bootloader/main.rs +++ b/artiq/firmware/bootloader/main.rs @@ -10,7 +10,7 @@ extern crate riscv; use core::{ptr, slice, convert::TryFrom}; use crc::crc32; -use byteorder::{ByteOrder, BigEndian}; +use byteorder::{ByteOrder, LittleEndian}; use board_misoc::{ident, cache, sdram, config, boot, mem as board_mem}; #[cfg(has_slave_fpga_cfg)] use board_misoc::slave_fpga; @@ -157,8 +157,8 @@ fn flash_boot() { println!("Booting from flash..."); let header = unsafe { slice::from_raw_parts(FIRMWARE, 8) }; - let length = BigEndian::read_u32(&header[0..]) as usize; - let expected_crc = BigEndian::read_u32(&header[4..]); + let length = LittleEndian::read_u32(&header[0..]) as usize; + let expected_crc = LittleEndian::read_u32(&header[4..]); if length == 0 || length == 0xffffffff { println!("No firmware present"); From 448fe0e8cf90d84022cf4f19be67becb76837a8a Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 15 Jul 2021 15:59:46 +0800 Subject: [PATCH 058/238] bootloader: fix panic Signed-off-by: occheung --- artiq/firmware/bootloader/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/bootloader/main.rs b/artiq/firmware/bootloader/main.rs index daa3a9be7..865293840 100644 --- a/artiq/firmware/bootloader/main.rs +++ b/artiq/firmware/bootloader/main.rs @@ -1,5 +1,5 @@ #![no_std] -#![feature(panic_implementation, panic_info_message)] +#![feature(panic_info_message)] extern crate crc; extern crate byteorder; @@ -532,7 +532,7 @@ pub extern fn abort() { } #[no_mangle] // https://github.com/rust-lang/rust/issues/{38281,51647} -#[panic_implementation] +#[panic_handler] pub fn panic_fmt(info: &core::panic::PanicInfo) -> ! { #[cfg(has_error_led)] unsafe { From 3ff74e0693a26e99c9f5ff74783198f9e332bd60 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 15 Jul 2021 16:00:23 +0800 Subject: [PATCH 059/238] bootloader: handle .sbss generation in .ld Signed-off-by: occheung --- artiq/firmware/bootloader/bootloader.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/bootloader/bootloader.ld b/artiq/firmware/bootloader/bootloader.ld index 22aea8cb6..b52abe930 100644 --- a/artiq/firmware/bootloader/bootloader.ld +++ b/artiq/firmware/bootloader/bootloader.ld @@ -38,7 +38,7 @@ SECTIONS .bss : { _fbss = .; - *(.bss .bss.*) + *(.sbss .sbss.* .bss .bss.*); . = ALIGN(4); _ebss = .; } > sram From 37ea8630043e7baf3dcd906b85b73211fd80e4a7 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 22 Jul 2021 16:24:06 +0800 Subject: [PATCH 060/238] libio: pin failure version --- artiq/firmware/libio/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/libio/Cargo.toml b/artiq/firmware/libio/Cargo.toml index 6aacf0c47..f4d1cbbb9 100644 --- a/artiq/firmware/libio/Cargo.toml +++ b/artiq/firmware/libio/Cargo.toml @@ -8,8 +8,8 @@ name = "io" path = "lib.rs" [dependencies] -failure = { version = "0.1", default-features = false } -failure_derive = { version = "0.1", default-features = false } +failure = { version = "=0.1.1", default-features = false } +failure_derive = { version = "=0.1.1", default-features = false } byteorder = { version = "1.0", default-features = false, optional = true } [features] From 97a0132f156d376dcbfd783fc0c1144859dba653 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 22 Jul 2021 16:25:13 +0800 Subject: [PATCH 061/238] libio: update alloc type path --- artiq/firmware/libio/cursor.rs | 2 +- artiq/firmware/libio/lib.rs | 2 +- artiq/firmware/libio/proto.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/artiq/firmware/libio/cursor.rs b/artiq/firmware/libio/cursor.rs index b820bdddc..85ff478fe 100644 --- a/artiq/firmware/libio/cursor.rs +++ b/artiq/firmware/libio/cursor.rs @@ -69,7 +69,7 @@ impl<'a> Write for Cursor<&'a mut [u8]> { } #[cfg(feature = "alloc")] -impl Write for Cursor<::alloc::Vec> { +impl Write for Cursor<::alloc::vec::Vec> { type WriteError = !; type FlushError = !; diff --git a/artiq/firmware/libio/lib.rs b/artiq/firmware/libio/lib.rs index b10c41345..235fd82c0 100644 --- a/artiq/firmware/libio/lib.rs +++ b/artiq/firmware/libio/lib.rs @@ -131,7 +131,7 @@ impl<'a> Write for &'a mut [u8] { } #[cfg(feature = "alloc")] -impl<'a> Write for alloc::Vec { +impl<'a> Write for alloc::vec::Vec { type WriteError = !; type FlushError = !; diff --git a/artiq/firmware/libio/proto.rs b/artiq/firmware/libio/proto.rs index 3df4a04aa..88b010e71 100644 --- a/artiq/firmware/libio/proto.rs +++ b/artiq/firmware/libio/proto.rs @@ -1,5 +1,5 @@ #[cfg(feature = "alloc")] -use {core::str::Utf8Error, alloc::String}; +use {core::str::Utf8Error, alloc::string::String}; use byteorder::{ByteOrder, NetworkEndian}; use ::{Read, Write, Error as IoError}; @@ -53,7 +53,7 @@ pub trait ProtoRead { #[cfg(feature = "alloc")] #[inline] - fn read_bytes(&mut self) -> Result<::alloc::Vec, Self::ReadError> { + fn read_bytes(&mut self) -> Result<::alloc::vec::Vec, Self::ReadError> { let length = self.read_u32()?; let mut value = vec![0; length as usize]; self.read_exact(&mut value)?; @@ -62,7 +62,7 @@ pub trait ProtoRead { #[cfg(feature = "alloc")] #[inline] - fn read_string(&mut self) -> Result<::alloc::String, ReadStringError> { + fn read_string(&mut self) -> Result<::alloc::string::String, ReadStringError> { let bytes = self.read_bytes().map_err(ReadStringError::Other)?; String::from_utf8(bytes).map_err(|err| ReadStringError::Utf8(err.utf8_error())) } From ebb9f298b5ce0c01c2c7b2472cd207d5b82f0cea Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 22 Jul 2021 16:26:19 +0800 Subject: [PATCH 062/238] proto_artiq: update alloc type path --- artiq/firmware/libproto_artiq/mgmt_proto.rs | 2 +- artiq/firmware/libproto_artiq/session_proto.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/libproto_artiq/mgmt_proto.rs b/artiq/firmware/libproto_artiq/mgmt_proto.rs index 93f81c40b..911799ef4 100644 --- a/artiq/firmware/libproto_artiq/mgmt_proto.rs +++ b/artiq/firmware/libproto_artiq/mgmt_proto.rs @@ -1,5 +1,5 @@ use core::str::Utf8Error; -use alloc::{Vec, String}; +use alloc::{vec::Vec, string::String}; #[cfg(feature = "log")] use log; diff --git a/artiq/firmware/libproto_artiq/session_proto.rs b/artiq/firmware/libproto_artiq/session_proto.rs index db353e874..99412de10 100644 --- a/artiq/firmware/libproto_artiq/session_proto.rs +++ b/artiq/firmware/libproto_artiq/session_proto.rs @@ -1,5 +1,5 @@ use core::str::Utf8Error; -use alloc::{Vec, String}; +use alloc::{vec::Vec, string::String}; use io::{Read, ProtoRead, Write, ProtoWrite, Error as IoError, ReadStringError}; From 869a28241079d1f98822b5033681fa808abedcfe Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 22 Jul 2021 16:28:18 +0800 Subject: [PATCH 063/238] satman: use riscv --- artiq/firmware/satman/Cargo.toml | 1 + artiq/firmware/satman/main.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/artiq/firmware/satman/Cargo.toml b/artiq/firmware/satman/Cargo.toml index fdccaf27a..0db54cd40 100644 --- a/artiq/firmware/satman/Cargo.toml +++ b/artiq/firmware/satman/Cargo.toml @@ -16,3 +16,4 @@ build_misoc = { path = "../libbuild_misoc" } log = { version = "0.4", default-features = false } board_misoc = { path = "../libboard_misoc", features = ["uart_console", "log"] } board_artiq = { path = "../libboard_artiq" } +riscv = { version = "0.6.0", features = ["inline-asm"] } diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 0b6d1cccb..38e321da4 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -6,6 +6,7 @@ extern crate log; #[macro_use] extern crate board_misoc; extern crate board_artiq; +extern crate riscv; use core::convert::TryFrom; use board_misoc::{csr, irq, ident, clock, uart_logger, i2c}; From 45adaa1d98c180cf60717da69c2c3c44b8e45561 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 22 Jul 2021 16:30:05 +0800 Subject: [PATCH 064/238] satman: add riscv exception handling --- artiq/firmware/satman/main.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 38e321da4..aed7c1890 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -9,7 +9,7 @@ extern crate board_artiq; extern crate riscv; use core::convert::TryFrom; -use board_misoc::{csr, irq, ident, clock, uart_logger, i2c}; +use board_misoc::{csr, ident, clock, uart_logger, i2c}; #[cfg(has_si5324)] use board_artiq::si5324; #[cfg(has_wrpll)] @@ -18,6 +18,7 @@ use board_artiq::{spi, drtioaux}; use board_artiq::drtio_routing; #[cfg(has_hmc830_7043)] use board_artiq::hmc830_7043; +use riscv::register::{mcause, mepc}; mod repeater; #[cfg(has_jdcg)] @@ -643,8 +644,9 @@ pub extern fn main() -> i32 { } #[no_mangle] -pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) { - let vect = irq::Exception::try_from(vect).expect("unknown exception"); +pub extern fn exception(_regs: *const u32) { + let pc = mepc::read(); + let cause = mcause::read().cause(); fn hexdump(addr: u32) { let addr = (addr - addr % 4) as *const u32; @@ -659,9 +661,8 @@ pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) { } } - hexdump(pc); - hexdump(ea); - panic!("exception {:?} at PC 0x{:x}, EA 0x{:x}", vect, pc, ea) + hexdump(u32::try_from(pc).unwrap()); + panic!("exception {:?} at PC 0x{:x}", cause, u32::try_from(pc).unwrap()) } #[no_mangle] From 6535b2f08936ee53b378ab7824936e68833c12a0 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 22 Jul 2021 16:30:33 +0800 Subject: [PATCH 065/238] satman: fix feature --- artiq/firmware/satman/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index aed7c1890..4d1869bcd 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -1,4 +1,4 @@ -#![feature(never_type, panic_implementation, panic_info_message, const_slice_len, try_from)] +#![feature(never_type, panic_info_message, llvm_asm)] #![no_std] #[macro_use] @@ -647,7 +647,7 @@ pub extern fn main() -> i32 { pub extern fn exception(_regs: *const u32) { let pc = mepc::read(); let cause = mcause::read().cause(); - + fn hexdump(addr: u32) { let addr = (addr - addr % 4) as *const u32; let mut ptr = addr; @@ -672,7 +672,7 @@ pub extern fn abort() { } #[no_mangle] // https://github.com/rust-lang/rust/issues/{38281,51647} -#[panic_implementation] +#[panic_handler] pub fn panic_fmt(info: &core::panic::PanicInfo) -> ! { #[cfg(has_error_led)] unsafe { From 96438c9da75de2207868cb1f6f36685847230731 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 22 Jul 2021 16:31:21 +0800 Subject: [PATCH 066/238] satman: make fbi big-endian --- artiq/firmware/satman/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/artiq/firmware/satman/Makefile b/artiq/firmware/satman/Makefile index b96938d1b..3d6974cf1 100644 --- a/artiq/firmware/satman/Makefile +++ b/artiq/firmware/satman/Makefile @@ -18,4 +18,5 @@ satman.elf: $(RUSTOUT)/libsatman.a $(objcopy) -O binary %.fbi: %.bin - $(mscimg) -f + $(mscimg) -f --little + objcopy -I binary -O binary --reverse-bytes=4 $@ From 6d9cebfd4217c4a4d2c1bd00cc2766492e305cd7 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 22 Jul 2021 16:32:03 +0800 Subject: [PATCH 067/238] satman: handle .sbss generation --- artiq/firmware/satman/satman.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/satman/satman.ld b/artiq/firmware/satman/satman.ld index 69cc737d2..927af6022 100644 --- a/artiq/firmware/satman/satman.ld +++ b/artiq/firmware/satman/satman.ld @@ -41,7 +41,7 @@ SECTIONS .bss ALIGN(4) : { _fbss = .; - *(.bss .bss.*) + *(.sbss .sbss.* .bss .bss.*); . = ALIGN(4); _ebss = .; } > main_ram From daaf6c3401e80f5dbcbe7a0fc4338f9b87f3a647 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 10:50:04 +0800 Subject: [PATCH 068/238] libunwind: add rust interface --- artiq/firmware/libunwind/Cargo.toml | 30 +++ artiq/firmware/libunwind/src/lib.rs | 11 + artiq/firmware/libunwind/src/libunwind.rs | 282 ++++++++++++++++++++++ 3 files changed, 323 insertions(+) create mode 100644 artiq/firmware/libunwind/Cargo.toml create mode 100644 artiq/firmware/libunwind/src/lib.rs create mode 100644 artiq/firmware/libunwind/src/libunwind.rs diff --git a/artiq/firmware/libunwind/Cargo.toml b/artiq/firmware/libunwind/Cargo.toml new file mode 100644 index 000000000..6760102d5 --- /dev/null +++ b/artiq/firmware/libunwind/Cargo.toml @@ -0,0 +1,30 @@ +[package] +authors = ["The Rust Project Developers"] +name = "unwind" +version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +edition = "2018" +include = [ + '/libunwind/*', +] + +[lib] +test = false +bench = false +doc = false + +[dependencies] +libc = { path = "../libc" } +cfg-if = "0.1.8" + +[features] + +# Only applies for Linux and Fuchsia targets +# Static link to the in-tree build of llvm libunwind +llvm-libunwind = [] + +# Only applies for Linux and Fuchsia targets +# If crt-static is enabled, static link to `libunwind.a` provided by system +# If crt-static is disabled, dynamic link to `libunwind.so` provided by system +system-llvm-libunwind = [] \ No newline at end of file diff --git a/artiq/firmware/libunwind/src/lib.rs b/artiq/firmware/libunwind/src/lib.rs new file mode 100644 index 000000000..a087a59ec --- /dev/null +++ b/artiq/firmware/libunwind/src/lib.rs @@ -0,0 +1,11 @@ +#![no_std] +#![unstable(feature = "panic_unwind", issue = "32837")] +#![feature(link_cfg)] +#![feature(nll)] +#![feature(staged_api)] +#![feature(unwind_attributes)] +#![feature(static_nobundle)] +#![cfg_attr(not(target_env = "msvc"), feature(libc))] + +mod libunwind; +pub use libunwind::*; diff --git a/artiq/firmware/libunwind/src/libunwind.rs b/artiq/firmware/libunwind/src/libunwind.rs new file mode 100644 index 000000000..646bf912e --- /dev/null +++ b/artiq/firmware/libunwind/src/libunwind.rs @@ -0,0 +1,282 @@ +#![allow(nonstandard_style)] + +use libc::{c_int, c_void, uintptr_t}; + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum _Unwind_Reason_Code { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8, + _URC_FAILURE = 9, // used only by ARM EHABI +} +pub use _Unwind_Reason_Code::*; + +pub type _Unwind_Exception_Class = u64; +pub type _Unwind_Word = uintptr_t; +pub type _Unwind_Ptr = uintptr_t; +pub type _Unwind_Trace_Fn = + extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code; + +#[cfg(target_arch = "x86")] +pub const unwinder_private_data_size: usize = 5; + +#[cfg(target_arch = "x86_64")] +pub const unwinder_private_data_size: usize = 6; + +#[cfg(all(target_arch = "arm", not(target_os = "ios")))] +pub const unwinder_private_data_size: usize = 20; + +#[cfg(all(target_arch = "arm", target_os = "ios"))] +pub const unwinder_private_data_size: usize = 5; + +#[cfg(all(target_arch = "aarch64", target_pointer_width = "64"))] +pub const unwinder_private_data_size: usize = 2; + +#[cfg(all(target_arch = "aarch64", target_pointer_width = "32"))] +pub const unwinder_private_data_size: usize = 5; + +#[cfg(target_arch = "mips")] +pub const unwinder_private_data_size: usize = 2; + +#[cfg(target_arch = "mips64")] +pub const unwinder_private_data_size: usize = 2; + +#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] +pub const unwinder_private_data_size: usize = 2; + +#[cfg(target_arch = "s390x")] +pub const unwinder_private_data_size: usize = 2; + +#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] +pub const unwinder_private_data_size: usize = 2; + +#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] +pub const unwinder_private_data_size: usize = 2; + +#[cfg(target_os = "emscripten")] +pub const unwinder_private_data_size: usize = 20; + +#[cfg(all(target_arch = "hexagon", target_os = "linux"))] +pub const unwinder_private_data_size: usize = 35; + +#[repr(C)] +pub struct _Unwind_Exception { + pub exception_class: _Unwind_Exception_Class, + pub exception_cleanup: _Unwind_Exception_Cleanup_Fn, + pub private: [_Unwind_Word; unwinder_private_data_size], +} + +pub enum _Unwind_Context {} + +pub type _Unwind_Exception_Cleanup_Fn = + extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception); +#[cfg_attr( + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + link(name = "unwind", kind = "static") +)] +extern "C" { + #[unwind(allowed)] + pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; + pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception); + pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void; + pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr; + pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr; + pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr; +} + +cfg_if::cfg_if! { +if #[cfg(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm")))] { + // Not ARM EHABI + #[repr(C)] + #[derive(Copy, Clone, PartialEq)] + pub enum _Unwind_Action { + _UA_SEARCH_PHASE = 1, + _UA_CLEANUP_PHASE = 2, + _UA_HANDLER_FRAME = 4, + _UA_FORCE_UNWIND = 8, + _UA_END_OF_STACK = 16, + } + pub use _Unwind_Action::*; + + #[cfg_attr(all(feature = "llvm-libunwind", + any(target_os = "fuchsia", target_os = "linux")), + link(name = "unwind", kind = "static"))] + extern "C" { + pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word; + pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word); + pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word; + pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word); + pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int) + -> _Unwind_Word; + pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void; + } + +} else { + // ARM EHABI + #[repr(C)] + #[derive(Copy, Clone, PartialEq)] + pub enum _Unwind_State { + _US_VIRTUAL_UNWIND_FRAME = 0, + _US_UNWIND_FRAME_STARTING = 1, + _US_UNWIND_FRAME_RESUME = 2, + _US_ACTION_MASK = 3, + _US_FORCE_UNWIND = 8, + _US_END_OF_STACK = 16, + } + pub use _Unwind_State::*; + + #[repr(C)] + enum _Unwind_VRS_Result { + _UVRSR_OK = 0, + _UVRSR_NOT_IMPLEMENTED = 1, + _UVRSR_FAILED = 2, + } + #[repr(C)] + enum _Unwind_VRS_RegClass { + _UVRSC_CORE = 0, + _UVRSC_VFP = 1, + _UVRSC_FPA = 2, + _UVRSC_WMMXD = 3, + _UVRSC_WMMXC = 4, + } + use _Unwind_VRS_RegClass::*; + #[repr(C)] + enum _Unwind_VRS_DataRepresentation { + _UVRSD_UINT32 = 0, + _UVRSD_VFPX = 1, + _UVRSD_FPAX = 2, + _UVRSD_UINT64 = 3, + _UVRSD_FLOAT = 4, + _UVRSD_DOUBLE = 5, + } + use _Unwind_VRS_DataRepresentation::*; + + pub const UNWIND_POINTER_REG: c_int = 12; + pub const UNWIND_SP_REG: c_int = 13; + pub const UNWIND_IP_REG: c_int = 15; + + #[cfg_attr(all(feature = "llvm-libunwind", + any(target_os = "fuchsia", target_os = "linux")), + link(name = "unwind", kind = "static"))] + extern "C" { + fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context, + regclass: _Unwind_VRS_RegClass, + regno: _Unwind_Word, + repr: _Unwind_VRS_DataRepresentation, + data: *mut c_void) + -> _Unwind_VRS_Result; + + fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context, + regclass: _Unwind_VRS_RegClass, + regno: _Unwind_Word, + repr: _Unwind_VRS_DataRepresentation, + data: *mut c_void) + -> _Unwind_VRS_Result; + } + + // On Android or ARM/Linux, these are implemented as macros: + + pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word { + let mut val: _Unwind_Word = 0; + _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32, + &mut val as *mut _ as *mut c_void); + val + } + + pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) { + let mut value = value; + _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32, + &mut value as *mut _ as *mut c_void); + } + + pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) + -> _Unwind_Word { + let val = _Unwind_GetGR(ctx, UNWIND_IP_REG); + (val & !1) as _Unwind_Word + } + + pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context, + value: _Unwind_Word) { + // Propagate thumb bit to instruction pointer + let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1; + let value = value | thumb_state; + _Unwind_SetGR(ctx, UNWIND_IP_REG, value); + } + + pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, + ip_before_insn: *mut c_int) + -> _Unwind_Word { + *ip_before_insn = 0; + _Unwind_GetIP(ctx) + } + + // This function also doesn't exist on Android or ARM/Linux, so make it a no-op + pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void { + pc + } +} +} // cfg_if! + +cfg_if::cfg_if! { +if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { + // Not 32-bit iOS + #[cfg_attr(all(feature = "llvm-libunwind", + any(target_os = "fuchsia", target_os = "linux")), + link(name = "unwind", kind = "static"))] + extern "C" { + #[unwind(allowed)] + pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, + trace_argument: *mut c_void) + -> _Unwind_Reason_Code; + } +} else { + // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace() + #[cfg_attr(all(feature = "llvm-libunwind", + any(target_os = "fuchsia", target_os = "linux")), + link(name = "unwind", kind = "static"))] + extern "C" { + #[unwind(allowed)] + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + } + + #[inline] + pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code { + _Unwind_SjLj_RaiseException(exc) + } +} +} // cfg_if! + +cfg_if::cfg_if! { +if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] { + // We declare these as opaque types. This is fine since you just need to + // pass them to _GCC_specific_handler and forget about them. + pub enum EXCEPTION_RECORD {} + pub type LPVOID = *mut c_void; + pub enum CONTEXT {} + pub enum DISPATCHER_CONTEXT {} + pub type EXCEPTION_DISPOSITION = c_int; + type PersonalityFn = unsafe extern "C" fn(version: c_int, + actions: _Unwind_Action, + exception_class: _Unwind_Exception_Class, + exception_object: *mut _Unwind_Exception, + context: *mut _Unwind_Context) + -> _Unwind_Reason_Code; + + extern "C" { + pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: LPVOID, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT, + personality: PersonalityFn) + -> EXCEPTION_DISPOSITION; + } +} +} // cfg_if! \ No newline at end of file From ad3037d0f6bdf06314103650532e015b7506614c Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 10:51:13 +0800 Subject: [PATCH 069/238] libc: add minimal C types --- artiq/firmware/libc/Cargo.toml | 5 +++++ artiq/firmware/libc/src/lib.rs | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 artiq/firmware/libc/Cargo.toml create mode 100644 artiq/firmware/libc/src/lib.rs diff --git a/artiq/firmware/libc/Cargo.toml b/artiq/firmware/libc/Cargo.toml new file mode 100644 index 000000000..7231c77c4 --- /dev/null +++ b/artiq/firmware/libc/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "libc" +version = "0.1.0" +authors = ["M-Labs"] +edition = "2018" diff --git a/artiq/firmware/libc/src/lib.rs b/artiq/firmware/libc/src/lib.rs new file mode 100644 index 000000000..e5eb97a23 --- /dev/null +++ b/artiq/firmware/libc/src/lib.rs @@ -0,0 +1,8 @@ +// Helper crate for dealing with c ffi +#![allow(non_camel_case_types)] +#![no_std] +pub type c_char = i8; +pub type c_int = i32; +pub type size_t = usize; +pub type uintptr_t = usize; +pub type c_void = core::ffi::c_void; From bfddd8a30f7b282f140295a9a09a438508e10e9c Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 10:52:14 +0800 Subject: [PATCH 070/238] libdyld: add riscv support --- artiq/firmware/libdyld/elf.rs | 56 ++++++++++++++++++++++++++++++ artiq/firmware/libdyld/lib.rs | 65 ++++++++++++++++++++++++----------- 2 files changed, 101 insertions(+), 20 deletions(-) diff --git a/artiq/firmware/libdyld/elf.rs b/artiq/firmware/libdyld/elf.rs index 0385bc768..d8712b9fd 100644 --- a/artiq/firmware/libdyld/elf.rs +++ b/artiq/firmware/libdyld/elf.rs @@ -131,6 +131,7 @@ pub const EM_TILEPRO: u16 = 188; pub const EM_MICROBLAZE: u16 = 189; pub const EM_TILEGX: u16 = 191; pub const EM_NUM: u16 = 192; +pub const EM_RISCV: u16 = 243; pub const EM_ALPHA: u16 = 36902; pub const EV_NONE: u8 = 0; pub const EV_CURRENT: u8 = 1; @@ -2229,6 +2230,61 @@ pub const R_OR1K_TLS_TPOFF: u8 = 32; pub const R_OR1K_TLS_DTPOFF: u8 = 33; pub const R_OR1K_TLS_DTPMOD: u8 = 34; pub const R_OR1K_NUM: u8 = 35; +pub const R_RISCV_NONE: u8 = 0; +pub const R_RISCV_32: u8 = 1; +pub const R_RISCV_64: u8 = 2; +pub const R_RISCV_RELATIVE: u8 = 3; +pub const R_RISCV_COPY: u8 = 4; +pub const R_RISCV_JUMP_SLOT: u8 = 5; +pub const R_RISCV_TLS_DTPMOD32: u8 = 6; +pub const R_RISCV_TLS_DTPMOD64: u8 = 7; +pub const R_RISCV_TLS_DTPREL32: u8 = 8; +pub const R_RISCV_TLS_DTPREL64: u8 = 9; +pub const R_RISCV_TLS_TPREL32: u8 = 10; +pub const R_RISCV_TLS_TPREL64: u8 = 11; +pub const R_RISCV_BRANCH: u8 = 16; +pub const R_RISCV_JAL: u8 = 17; +pub const R_RISCV_CALL: u8 = 18; +pub const R_RISCV_CALL_PLT: u8 = 19; +pub const R_RISCV_GOT_HI20: u8 = 20; +pub const R_RISCV_TLS_GOT_HI20: u8 = 21; +pub const R_RISCV_TLS_GD_HI20: u8 = 22; +pub const R_RISCV_PCREL_HI20: u8 = 23; +pub const R_RISCV_PCREL_LO12_I: u8 = 24; +pub const R_RISCV_PCREL_LO12_S: u8 = 25; +pub const R_RISCV_HI20: u8 = 26; +pub const R_RISCV_LO12_I: u8 = 27; +pub const R_RISCV_LO12_S: u8 = 28; +pub const R_RISCV_TPREL_HI20: u8 = 29; +pub const R_RISCV_TPREL_LO12_I: u8 = 30; +pub const R_RISCV_TPREL_LO12_S: u8 = 31; +pub const R_RISCV_TPREL_ADD: u8 = 32; +pub const R_RISCV_ADD8: u8 = 33; +pub const R_RISCV_ADD16: u8 = 34; +pub const R_RISCV_ADD32: u8 = 35; +pub const R_RISCV_ADD64: u8 = 36; +pub const R_RISCV_SUB8: u8 = 37; +pub const R_RISCV_SUB16: u8 = 38; +pub const R_RISCV_SUB32: u8 = 39; +pub const R_RISCV_SUB64: u8 = 40; +pub const R_RISCV_GNU_VTINHERIT: u8 = 41; +pub const R_RISCV_GNU_VTENTRY: u8 = 42; +pub const R_RISCV_ALIGN: u8 = 43; +pub const R_RISCV_RVC_BRANCH: u8 = 44; +pub const R_RISCV_RVC_JUMP: u8 = 45; +pub const R_RISCV_RVC_LUI: u8 = 46; +pub const R_RISCV_GPREL_I: u8 = 47; +pub const R_RISCV_GPREL_S: u8 = 48; +pub const R_RISCV_TPREL_I: u8 = 49; +pub const R_RISCV_TPREL_S: u8 = 50; +pub const R_RISCV_RELAX: u8 = 51; +pub const R_RISCV_SUB6: u8 = 52; +pub const R_RISCV_SET6: u8 = 53; +pub const R_RISCV_SET8: u8 = 54; +pub const R_RISCV_SET16: u8 = 55; +pub const R_RISCV_SET32: u8 = 56; +pub const R_RISCV_32_PCREL: u8 = 57; +pub const R_RISCV_NUM: u8 = 58; pub type Elf32_Half = u16; pub type Elf64_Half = u16; diff --git a/artiq/firmware/libdyld/lib.rs b/artiq/firmware/libdyld/lib.rs index bbf4f59c5..0788c38d4 100644 --- a/artiq/firmware/libdyld/lib.rs +++ b/artiq/firmware/libdyld/lib.rs @@ -75,9 +75,16 @@ impl<'a> fmt::Display for Error<'a> { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Arch { + RiscV, + OpenRisc, +} + pub struct Library<'a> { image_off: Elf32_Addr, image_sz: usize, + arch: Arch, strtab: &'a [u8], symtab: &'a [Elf32_Sym], pltrel: &'a [Elf32_Rela], @@ -133,8 +140,12 @@ impl<'a> Library<'a> { // This is unsafe because it mutates global data (the PLT). pub unsafe fn rebind(&self, name: &[u8], addr: Elf32_Word) -> Result<(), Error<'a>> { for rela in self.pltrel.iter() { - match ELF32_R_TYPE(rela.r_info) { - R_OR1K_32 | R_OR1K_GLOB_DAT | R_OR1K_JMP_SLOT => { + match (ELF32_R_TYPE(rela.r_info), self.arch) { + (R_OR1K_32, Arch::OpenRisc) | + (R_OR1K_GLOB_DAT, Arch::OpenRisc) | + (R_OR1K_JMP_SLOT, Arch::OpenRisc) | + (R_RISCV_32, Arch::RiscV) | + (R_RISCV_JUMP_SLOT, Arch::RiscV) => { let sym = self.symtab.get(ELF32_R_SYM(rela.r_info) as usize) .ok_or("symbol out of bounds of symbol table")?; let sym_name = self.name_starting_at(sym.st_name as usize)?; @@ -162,14 +173,18 @@ impl<'a> Library<'a> { } let value; - match ELF32_R_TYPE(rela.r_info) { - R_OR1K_NONE => + match (ELF32_R_TYPE(rela.r_info), self.arch) { + (R_OR1K_NONE, Arch::OpenRisc) | (R_RISCV_NONE, Arch::RiscV) => return Ok(()), - R_OR1K_RELATIVE => + (R_OR1K_RELATIVE, Arch::OpenRisc) | (R_RISCV_RELATIVE, Arch::RiscV) => value = self.image_off + rela.r_addend as Elf32_Word, - R_OR1K_32 | R_OR1K_GLOB_DAT | R_OR1K_JMP_SLOT => { + (R_OR1K_32, Arch::OpenRisc) | + (R_OR1K_GLOB_DAT, Arch::OpenRisc) | + (R_OR1K_JMP_SLOT, Arch::OpenRisc) | + (R_RISCV_32, Arch::RiscV) | + (R_RISCV_JUMP_SLOT, Arch::RiscV) => { let sym = sym.ok_or("relocation requires an associated symbol")?; let sym_name = self.name_starting_at(sym.st_name as usize)?; @@ -202,20 +217,7 @@ impl<'a> Library<'a> { let ehdr = read_unaligned::(data, 0) .map_err(|()| "cannot read ELF header")?; - const IDENT: [u8; EI_NIDENT] = [ - ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, - ELFCLASS32, ELFDATA2MSB, EV_CURRENT, ELFOSABI_NONE, - /* ABI version */ 0, /* padding */ 0, 0, 0, 0, 0, 0, 0 - ]; - - #[cfg(target_arch = "or1k")] - const ARCH: u16 = EM_OPENRISC; - #[cfg(not(target_arch = "or1k"))] - const ARCH: u16 = EM_NONE; - - if ehdr.e_ident != IDENT || ehdr.e_type != ET_DYN || ehdr.e_machine != ARCH { - return Err("not a shared library for current architecture")? - } + let arch = arch(&ehdr).ok_or("not a shared library for current architecture")?; let mut dyn_off = None; for i in 0..ehdr.e_phnum { @@ -314,6 +316,7 @@ impl<'a> Library<'a> { let library = Library { image_off: image.as_ptr() as Elf32_Word, image_sz: image.len(), + arch: arch, strtab: strtab, symtab: symtab, pltrel: pltrel, @@ -337,3 +340,25 @@ impl<'a> Library<'a> { Ok(library) } } + +fn arch(ehdr: &Elf32_Ehdr) -> Option { + const IDENT_OPENRISC: [u8; EI_NIDENT] = [ + ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, + ELFCLASS32, ELFDATA2MSB, EV_CURRENT, ELFOSABI_NONE, + /* ABI version */ 0, /* padding */ 0, 0, 0, 0, 0, 0, 0 + ]; + const IDENT_RISCV: [u8; EI_NIDENT] = [ + ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, + ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, + /* ABI version */ 0, /* padding */ 0, 0, 0, 0, 0, 0, 0 + ]; + match (ehdr.e_ident, ehdr.e_machine) { + #[cfg(target_arch = "riscv32")] + (IDENT_RISCV, EM_RISCV) => Some(Arch::RiscV), + + #[cfg(target_arch = "or1k")] + (IDENT_OPENRISC, EM_OPENRISC) => Some(Arch::OpenRisc), + + _ => None, + } +} From 31bf17563c59599e2cfc438e9f0c5844f49faace Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 10:55:09 +0800 Subject: [PATCH 071/238] personality: update from rust/panic_unwind --- artiq/firmware/ksupport/eh_artiq.rs | 23 ++- artiq/firmware/libeh/dwarf.rs | 307 ++++++++++++++-------------- artiq/firmware/libeh/eh_rust.rs | 23 ++- 3 files changed, 192 insertions(+), 161 deletions(-) diff --git a/artiq/firmware/ksupport/eh_artiq.rs b/artiq/firmware/ksupport/eh_artiq.rs index 8bfc171a0..471510930 100644 --- a/artiq/firmware/ksupport/eh_artiq.rs +++ b/artiq/firmware/ksupport/eh_artiq.rs @@ -15,7 +15,7 @@ use cslice::CSlice; use unwind as uw; use libc::{c_int, c_void}; -use eh::dwarf::{self, EHAction}; +use eh::dwarf::{self, EHAction, EHContext}; type _Unwind_Stop_Fn = extern "C" fn(version: c_int, actions: uw::_Unwind_Action, @@ -61,6 +61,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX #[cfg(any(target_arch = "or1k"))] const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 +#[cfg(any(target_arch = "riscv32"))] +const UNWIND_DATA_REG: (i32, i32) = (10, 11); // X10, X11 + #[export_name="__artiq_personality"] pub extern fn personality(version: c_int, actions: uw::_Unwind_Action, @@ -74,13 +77,25 @@ pub extern fn personality(version: c_int, } let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8; - let ip = uw::_Unwind_GetIP(context) - 1; - let func_start = uw::_Unwind_GetRegionStart(context); + let mut ip_before_instr: c_int = 0; + let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr); + let eh_context = EHContext { + // The return address points 1 byte past the call instruction, + // which could be in the next IP range in LSDA range table. + ip: if ip_before_instr != 0 { ip } else { ip - 1 }, + func_start: uw::_Unwind_GetRegionStart(context), + get_text_start: &|| uw::_Unwind_GetTextRelBase(context), + get_data_start: &|| uw::_Unwind_GetDataRelBase(context), + }; let exception_info = &mut *(uw_exception as *mut ExceptionInfo); let exception = &exception_info.exception.unwrap(); - let eh_action = dwarf::find_eh_action(lsda, func_start, ip, exception.name); + let eh_action = match dwarf::find_eh_action(lsda, &eh_context) { + Ok(action) => action, + Err(_) => return uw::_URC_FATAL_PHASE1_ERROR, + }; + if actions as u32 & uw::_UA_SEARCH_PHASE as u32 != 0 { match eh_action { EHAction::None | diff --git a/artiq/firmware/libeh/dwarf.rs b/artiq/firmware/libeh/dwarf.rs index 0956dc267..4dfc04a67 100644 --- a/artiq/firmware/libeh/dwarf.rs +++ b/artiq/firmware/libeh/dwarf.rs @@ -1,51 +1,71 @@ -#![allow(non_upper_case_globals, dead_code)] +//! Parsing of GCC-style Language-Specific Data Area (LSDA) +//! For details see: +//! * +//! * +//! * +//! * +//! +//! A reference implementation may be found in the GCC source tree +//! (`/libgcc/unwind-c.c` as of this writing). -use core::{ptr, mem}; -use cslice::CSlice; +#![allow(non_upper_case_globals)] +#![allow(unused)] -const DW_EH_PE_omit: u8 = 0xFF; -const DW_EH_PE_absptr: u8 = 0x00; +use core::mem; -const DW_EH_PE_uleb128: u8 = 0x01; -const DW_EH_PE_udata2: u8 = 0x02; -const DW_EH_PE_udata4: u8 = 0x03; -const DW_EH_PE_udata8: u8 = 0x04; -const DW_EH_PE_sleb128: u8 = 0x09; -const DW_EH_PE_sdata2: u8 = 0x0A; -const DW_EH_PE_sdata4: u8 = 0x0B; -const DW_EH_PE_sdata8: u8 = 0x0C; +pub const DW_EH_PE_omit: u8 = 0xFF; +pub const DW_EH_PE_absptr: u8 = 0x00; -const DW_EH_PE_pcrel: u8 = 0x10; -const DW_EH_PE_textrel: u8 = 0x20; -const DW_EH_PE_datarel: u8 = 0x30; -const DW_EH_PE_funcrel: u8 = 0x40; -const DW_EH_PE_aligned: u8 = 0x50; +pub const DW_EH_PE_uleb128: u8 = 0x01; +pub const DW_EH_PE_udata2: u8 = 0x02; +pub const DW_EH_PE_udata4: u8 = 0x03; +pub const DW_EH_PE_udata8: u8 = 0x04; +pub const DW_EH_PE_sleb128: u8 = 0x09; +pub const DW_EH_PE_sdata2: u8 = 0x0A; +pub const DW_EH_PE_sdata4: u8 = 0x0B; +pub const DW_EH_PE_sdata8: u8 = 0x0C; -const DW_EH_PE_indirect: u8 = 0x80; +pub const DW_EH_PE_pcrel: u8 = 0x10; +pub const DW_EH_PE_textrel: u8 = 0x20; +pub const DW_EH_PE_datarel: u8 = 0x30; +pub const DW_EH_PE_funcrel: u8 = 0x40; +pub const DW_EH_PE_aligned: u8 = 0x50; -#[derive(Clone)] -struct DwarfReader { +pub const DW_EH_PE_indirect: u8 = 0x80; + +#[derive(Copy, Clone)] +pub struct EHContext<'a> { + pub ip: usize, // Current instruction pointer + pub func_start: usize, // Address of the current function + pub get_text_start: &'a dyn Fn() -> usize, // Get address of the code section + pub get_data_start: &'a dyn Fn() -> usize, // Get address of the data section +} + +pub struct DwarfReader { pub ptr: *const u8, } +#[repr(C, packed)] +struct Unaligned(T); + impl DwarfReader { - fn new(ptr: *const u8) -> DwarfReader { - DwarfReader { ptr: ptr } + pub fn new(ptr: *const u8) -> DwarfReader { + DwarfReader { ptr } } - // DWARF streams are packed, so e.g. a u32 would not necessarily be aligned + // DWARF streams are packed, so e.g., a u32 would not necessarily be aligned // on a 4-byte boundary. This may cause problems on platforms with strict // alignment requirements. By wrapping data in a "packed" struct, we are // telling the backend to generate "misalignment-safe" code. - unsafe fn read(&mut self) -> T { - let result = ptr::read_unaligned(self.ptr as *const T); - self.ptr = self.ptr.offset(mem::size_of::() as isize); + pub unsafe fn read(&mut self) -> T { + let Unaligned(result) = *(self.ptr as *const Unaligned); + self.ptr = self.ptr.add(mem::size_of::()); result } // ULEB128 and SLEB128 encodings are defined in Section 7.6 - "Variable // Length Data". - unsafe fn read_uleb128(&mut self) -> u64 { + pub unsafe fn read_uleb128(&mut self) -> u64 { let mut shift: usize = 0; let mut result: u64 = 0; let mut byte: u8; @@ -60,8 +80,8 @@ impl DwarfReader { result } - unsafe fn read_sleb128(&mut self) -> i64 { - let mut shift: usize = 0; + pub unsafe fn read_sleb128(&mut self) -> i64 { + let mut shift: u32 = 0; let mut result: u64 = 0; let mut byte: u8; loop { @@ -73,70 +93,61 @@ impl DwarfReader { } } // sign-extend - if shift < 8 * mem::size_of::() && (byte & 0x40) != 0 { + if shift < u64::BITS && (byte & 0x40) != 0 { result |= (!0 as u64) << shift; } result as i64 } - - unsafe fn read_encoded_pointer(&mut self, encoding: u8) -> usize { - fn round_up(unrounded: usize, align: usize) -> usize { - debug_assert!(align.is_power_of_two()); - (unrounded + align - 1) & !(align - 1) - } - - debug_assert!(encoding != DW_EH_PE_omit); - - // DW_EH_PE_aligned implies it's an absolute pointer value - if encoding == DW_EH_PE_aligned { - self.ptr = round_up(self.ptr as usize, mem::size_of::()) as *const u8; - return self.read::() - } - - let value_ptr = self.ptr; - let mut result = match encoding & 0x0F { - DW_EH_PE_absptr => self.read::(), - DW_EH_PE_uleb128 => self.read_uleb128() as usize, - DW_EH_PE_udata2 => self.read::() as usize, - DW_EH_PE_udata4 => self.read::() as usize, - DW_EH_PE_udata8 => self.read::() as usize, - DW_EH_PE_sleb128 => self.read_sleb128() as usize, - DW_EH_PE_sdata2 => self.read::() as usize, - DW_EH_PE_sdata4 => self.read::() as usize, - DW_EH_PE_sdata8 => self.read::() as usize, - _ => panic!(), - }; - - result += match encoding & 0x70 { - DW_EH_PE_absptr => 0, - // relative to address of the encoded value, despite the name - DW_EH_PE_pcrel => value_ptr as usize, - _ => panic!(), - }; - - if encoding & DW_EH_PE_indirect != 0 { - result = *(result as *const usize); - } - - result - } } -fn encoding_size(encoding: u8) -> usize { +unsafe fn read_encoded_pointer( + reader: &mut DwarfReader, + context: &EHContext<'_>, + encoding: u8, +) -> Result { if encoding == DW_EH_PE_omit { - return 0 + return Err(()); } - match encoding & 0x0F { - DW_EH_PE_absptr => mem::size_of::(), - DW_EH_PE_udata2 => 2, - DW_EH_PE_udata4 => 4, - DW_EH_PE_udata8 => 8, - DW_EH_PE_sdata2 => 2, - DW_EH_PE_sdata4 => 4, - DW_EH_PE_sdata8 => 8, - _ => panic!() + // DW_EH_PE_aligned implies it's an absolute pointer value + if encoding == DW_EH_PE_aligned { + reader.ptr = round_up(reader.ptr as usize, mem::size_of::())? as *const u8; + return Ok(reader.read::()); } + + let mut result = match encoding & 0x0F { + DW_EH_PE_absptr => reader.read::(), + DW_EH_PE_uleb128 => reader.read_uleb128() as usize, + DW_EH_PE_udata2 => reader.read::() as usize, + DW_EH_PE_udata4 => reader.read::() as usize, + DW_EH_PE_udata8 => reader.read::() as usize, + DW_EH_PE_sleb128 => reader.read_sleb128() as usize, + DW_EH_PE_sdata2 => reader.read::() as usize, + DW_EH_PE_sdata4 => reader.read::() as usize, + DW_EH_PE_sdata8 => reader.read::() as usize, + _ => return Err(()), + }; + + result += match encoding & 0x70 { + DW_EH_PE_absptr => 0, + // relative to address of the encoded value, despite the name + DW_EH_PE_pcrel => reader.ptr as usize, + DW_EH_PE_funcrel => { + if context.func_start == 0 { + return Err(()); + } + context.func_start + } + DW_EH_PE_textrel => (*context.get_text_start)(), + DW_EH_PE_datarel => (*context.get_data_start)(), + _ => return Err(()), + }; + + if encoding & DW_EH_PE_indirect != 0 { + result = *(result as *const usize); + } + + Ok(result) } pub enum EHAction { @@ -146,98 +157,94 @@ pub enum EHAction { Terminate, } -pub unsafe fn find_eh_action(lsda: *const u8, func_start: usize, ip: usize, - exn_name: CSlice) -> EHAction { +pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm")); + +pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result { if lsda.is_null() { - return EHAction::None + return Ok(EHAction::None); } + let func_start = context.func_start; let mut reader = DwarfReader::new(lsda); let start_encoding = reader.read::(); // base address for landing pad offsets let lpad_base = if start_encoding != DW_EH_PE_omit { - reader.read_encoded_pointer(start_encoding) + read_encoded_pointer(&mut reader, context, start_encoding)? } else { func_start }; let ttype_encoding = reader.read::(); - let ttype_encoding_size = encoding_size(ttype_encoding) as isize; - - let class_info; if ttype_encoding != DW_EH_PE_omit { - let class_info_offset = reader.read_uleb128(); - class_info = reader.ptr.offset(class_info_offset as isize); - } else { - class_info = ptr::null(); + // Rust doesn't analyze exception types, so we don't care about the type table + reader.read_uleb128(); } - assert!(!class_info.is_null()); let call_site_encoding = reader.read::(); let call_site_table_length = reader.read_uleb128(); let action_table = reader.ptr.offset(call_site_table_length as isize); + let ip = context.ip; - while reader.ptr < action_table { - let cs_start = reader.read_encoded_pointer(call_site_encoding); - let cs_len = reader.read_encoded_pointer(call_site_encoding); - let cs_lpad = reader.read_encoded_pointer(call_site_encoding); - let cs_action = reader.read_uleb128(); - - if ip < func_start + cs_start { + if !USING_SJLJ_EXCEPTIONS { + while reader.ptr < action_table { + let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?; + let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?; + let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?; + let cs_action = reader.read_uleb128(); // Callsite table is sorted by cs_start, so if we've passed the ip, we // may stop searching. - break + if ip < func_start + cs_start { + break; + } + if ip < func_start + cs_start + cs_len { + if cs_lpad == 0 { + return Ok(EHAction::None); + } else { + let lpad = lpad_base + cs_lpad; + return Ok(interpret_cs_action(cs_action, lpad)); + } + } } - if ip > func_start + cs_start + cs_len { - continue + // Ip is not present in the table. This should not happen... but it does: issue #35011. + // So rather than returning EHAction::Terminate, we do this. + Ok(EHAction::None) + } else { + // SjLj version: + // The "IP" is an index into the call-site table, with two exceptions: + // -1 means 'no-action', and 0 means 'terminate'. + match ip as isize { + -1 => return Ok(EHAction::None), + 0 => return Ok(EHAction::Terminate), + _ => (), } - - if cs_lpad == 0 { - return EHAction::None - } - - let lpad = lpad_base + cs_lpad; - if cs_action == 0 { - return EHAction::Cleanup(lpad) - } - - let action_entry = action_table.offset((cs_action - 1) as isize); - let mut action_reader = DwarfReader::new(action_entry); + let mut idx = ip; loop { - let type_info_offset = action_reader.read_sleb128() as isize; - let action_offset = action_reader.clone().read_sleb128() as isize; - assert!(type_info_offset >= 0); - - if type_info_offset > 0 { - let type_info_ptr_ptr = class_info.offset(-type_info_offset * ttype_encoding_size); - let type_info_ptr = DwarfReader::new(type_info_ptr_ptr) - .read_encoded_pointer(ttype_encoding); - let type_info = *(type_info_ptr as *const CSlice); - - if type_info.as_ref() == exn_name.as_ref() { - return EHAction::Catch(lpad) - } - - if type_info.len() == 0 { - // This is a catch-all clause. We don't compare type_info_ptr with null here - // because, in PIC mode, the OR1K LLVM backend emits a literal zero - // encoded with DW_EH_PE_pcrel, which of course doesn't result in - // a proper null pointer. - return EHAction::Catch(lpad) - } - } - - if action_offset == 0 { - break - } else { - action_reader.ptr = action_reader.ptr.offset(action_offset) + let cs_lpad = reader.read_uleb128(); + let cs_action = reader.read_uleb128(); + idx -= 1; + if idx == 0 { + // Can never have null landing pad for sjlj -- that would have + // been indicated by a -1 call site index. + let lpad = (cs_lpad + 1) as usize; + return Ok(interpret_cs_action(cs_action, lpad)); } } - - return EHAction::None } - - // the function has a personality but no landing pads; this is fine - EHAction::None +} + +fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction { + if cs_action == 0 { + // If cs_action is 0 then this is a cleanup (Drop::drop). We run these + // for both Rust panics and foreign exceptions. + EHAction::Cleanup(lpad) + } else { + // Stop unwinding Rust panics at catch_unwind. + EHAction::Catch(lpad) + } +} + +#[inline] +fn round_up(unrounded: usize, align: usize) -> Result { + if align.is_power_of_two() { Ok((unrounded + align - 1) & !(align - 1)) } else { Err(()) } } diff --git a/artiq/firmware/libeh/eh_rust.rs b/artiq/firmware/libeh/eh_rust.rs index 7fb14193d..5692beb54 100644 --- a/artiq/firmware/libeh/eh_rust.rs +++ b/artiq/firmware/libeh/eh_rust.rs @@ -20,7 +20,7 @@ use unwind as uw; use libc::{c_int, uintptr_t}; use cslice::AsCSlice; -use dwarf::{self, EHAction}; +use dwarf::{self, EHAction, EHContext}; // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister() // and TargetLowering::getExceptionSelectorRegister() for each architecture, @@ -37,6 +37,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX #[cfg(any(target_arch = "or1k"))] const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 +#[cfg(any(target_arch = "riscv32"))] +const UNWIND_DATA_REG: (i32, i32) = (10, 11); // X10, X11 + // The following code is based on GCC's C and C++ personality routines. For reference, see: // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c @@ -78,11 +81,17 @@ unsafe extern "C" fn rust_eh_personality(version: c_int, } } -unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) - -> Result -{ +unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result { let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8; - let func = uw::_Unwind_GetRegionStart(context); - let ip = uw::_Unwind_GetIP(context); - Ok(dwarf::find_eh_action(lsda, func, ip, [].as_c_slice())) + let mut ip_before_instr: c_int = 0; + let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr); + let eh_context = EHContext { + // The return address points 1 byte past the call instruction, + // which could be in the next IP range in LSDA range table. + ip: if ip_before_instr != 0 { ip } else { ip - 1 }, + func_start: uw::_Unwind_GetRegionStart(context), + get_text_start: &|| uw::_Unwind_GetTextRelBase(context), + get_data_start: &|| uw::_Unwind_GetDataRelBase(context), + }; + dwarf::find_eh_action(lsda, &eh_context) } From 252594a606b6a77dbb64bb595f9d4054e9f048b7 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 10:57:38 +0800 Subject: [PATCH 072/238] runtime: impl riscv panic handler --- artiq/firmware/runtime/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 95e0f12e9..8d20f18aa 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -297,9 +297,9 @@ pub fn oom(layout: core::alloc::Layout) -> ! { } #[no_mangle] // https://github.com/rust-lang/rust/issues/{38281,51647} -#[panic_implementation] +#[panic_handler] pub fn panic_impl(info: &core::panic::PanicInfo) -> ! { - irq::set_ie(false); + // irq::set_ie(false); #[cfg(has_error_led)] unsafe { @@ -319,9 +319,9 @@ pub fn panic_impl(info: &core::panic::PanicInfo) -> ! { println!("backtrace for software version {}:", csr::CONFIG_IDENTIFIER_STR); let _ = unwind_backtrace::backtrace(|ip| { - // Backtrace gives us the return address, i.e. the address after the delay slot, + // Backtrace gives us the return address, i.e. the address after jal(r) insn, // but we're interested in the call instruction. - println!("{:#08x}", ip - 2 * 4); + println!("{:#08x}", ip - 4); }); if config::read_str("panic_reset", |r| r == Ok("1")) && From ecedec577c90d1dc78ab83e9026526636faddff0 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 11:02:38 +0800 Subject: [PATCH 073/238] runtime: impl riscv exception handling --- artiq/firmware/runtime/main.rs | 82 +++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 8d20f18aa..089a1c1b0 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -257,29 +257,67 @@ pub extern fn main() -> i32 { } } -#[no_mangle] -pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) { - let vect = irq::Exception::try_from(vect).expect("unknown exception"); - match vect { - irq::Exception::Interrupt => - panic!("spurious irq {}", irq::pending_mask().trailing_zeros()), - _ => { - fn hexdump(addr: u32) { - let addr = (addr - addr % 4) as *const u32; - let mut ptr = addr; - println!("@ {:08p}", ptr); - for _ in 0..4 { - print!("+{:04x}: ", ptr as usize - addr as usize); - print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); - print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); - print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); - print!("{:08x}\n", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); - } - } +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct TrapFrame { + pub ra: usize, + pub t0: usize, + pub t1: usize, + pub t2: usize, + pub t3: usize, + pub t4: usize, + pub t5: usize, + pub t6: usize, + pub a0: usize, + pub a1: usize, + pub a2: usize, + pub a3: usize, + pub a4: usize, + pub a5: usize, + pub a6: usize, + pub a7: usize, +} - hexdump(pc); - hexdump(ea); - panic!("exception {:?} at PC 0x{:x}, EA 0x{:x}", vect, pc, ea) +#[no_mangle] +pub extern fn exception(regs: *const TrapFrame) { + unsafe { + let pc = mepc::read(); + let cause = mcause::read().cause(); + match cause { + mcause::Trap::Interrupt(source) => { + info!("Called interrupt with {:?}", source); + // while irq::pending_mask() != 0 { + // match () { + // #[cfg(has_timer1)] + // () if irq::is_pending(csr::TIMER1_INTERRUPT) => + // profiler::sample(pc as usize), + // _ => { + // panic!("spurious irq {}", irq::pending_mask().trailing_zeros()) + // } + // } + // } + panic!("Interrupt not present"); + }, + mcause::Trap::Exception(e) => { + println!("Stack pointer: {:p}", regs); + println!("Trap frame: {:x?}", unsafe { *regs }); + + fn hexdump(addr: u32) { + let addr = (addr - addr % 4) as *const u32; + let mut ptr = addr; + println!("@ {:08p}", ptr); + for _ in 0..4 { + print!("+{:04x}: ", ptr as usize - addr as usize); + print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); + print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); + print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); + print!("{:08x}\n", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); + } + } + + hexdump(u32::try_from(pc).unwrap()); + panic!("exception {:?} at PC 0x{:x}", e, u32::try_from(pc).unwrap()) + } } } } From e99061b0134499c292ebdc67d14d95fb6bb69879 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 11:05:17 +0800 Subject: [PATCH 074/238] runtime: add riscv --- artiq/firmware/runtime/Cargo.toml | 1 + artiq/firmware/runtime/main.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index bbb9877bb..f8139cc57 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -28,6 +28,7 @@ logger_artiq = { path = "../liblogger_artiq" } board_artiq = { path = "../libboard_artiq" } proto_artiq = { path = "../libproto_artiq", features = ["log", "alloc"] } smoltcp = { version = "0.6.0", default-features = false, features = ["rust-1_28", "alloc", "ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } +riscv = { version = "0.6.0", features = ["inline-asm"] } [dependencies.fringe] git = "https://github.com/m-labs/libfringe" diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 089a1c1b0..590f99564 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -25,6 +25,7 @@ extern crate board_misoc; extern crate board_artiq; extern crate logger_artiq; extern crate proto_artiq; +extern crate riscv; use core::cell::RefCell; use core::convert::TryFrom; @@ -41,6 +42,8 @@ use proto_artiq::{mgmt_proto, moninj_proto, rpc_proto, session_proto, kernel_pro #[cfg(has_rtio_analyzer)] use proto_artiq::analyzer_proto; +use riscv::register::{mcause, mepc}; + mod rtio_clocking; mod rtio_mgt; From c800b6c8d3db08b11efaf761c6eb94af5a09d309 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 11:07:47 +0800 Subject: [PATCH 075/238] runtime: update rust alloc, managed --- artiq/firmware/runtime/Cargo.toml | 2 +- artiq/firmware/runtime/cache.rs | 2 +- artiq/firmware/runtime/main.rs | 2 +- artiq/firmware/runtime/moninj.rs | 2 +- artiq/firmware/runtime/rtio_dma.rs | 2 +- artiq/firmware/runtime/sched.rs | 2 +- artiq/firmware/runtime/session.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index f8139cc57..f96d4d29d 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -18,7 +18,7 @@ failure_derive = { version = "0.1", default-features = false } byteorder = { version = "1.0", default-features = false } cslice = { version = "0.3" } log = { version = "0.4", default-features = false } -managed = { version = "= 0.7.0", default-features = false, features = ["alloc", "map"] } +managed = { version = "^0.7.1", default-features = false, features = ["alloc", "map"] } eh = { path = "../libeh" } unwind_backtrace = { path = "../libunwind_backtrace" } io = { path = "../libio", features = ["byteorder"] } diff --git a/artiq/firmware/runtime/cache.rs b/artiq/firmware/runtime/cache.rs index 2f1948924..a950fab3b 100644 --- a/artiq/firmware/runtime/cache.rs +++ b/artiq/firmware/runtime/cache.rs @@ -1,4 +1,4 @@ -use alloc::{Vec, String, BTreeMap}; +use alloc::{vec::Vec, string::String, collections::btree_map::BTreeMap}; #[derive(Debug)] struct Entry { diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 590f99564..968aba156 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -147,7 +147,7 @@ fn startup() { }; let neighbor_cache = - smoltcp::iface::NeighborCache::new(alloc::btree_map::BTreeMap::new()); + smoltcp::iface::NeighborCache::new(alloc::collections::btree_map::BTreeMap::new()); let net_addresses = net_settings::get_adresses(); info!("network addresses: {}", net_addresses); let mut interface = match net_addresses.ipv6_addr { diff --git a/artiq/firmware/runtime/moninj.rs b/artiq/firmware/runtime/moninj.rs index 3d3d06c40..44a138bc0 100644 --- a/artiq/firmware/runtime/moninj.rs +++ b/artiq/firmware/runtime/moninj.rs @@ -1,4 +1,4 @@ -use alloc::btree_map::BTreeMap; +use alloc::collections::btree_map::BTreeMap; use core::cell::RefCell; use io::Error as IoError; diff --git a/artiq/firmware/runtime/rtio_dma.rs b/artiq/firmware/runtime/rtio_dma.rs index 39e61d621..292874047 100644 --- a/artiq/firmware/runtime/rtio_dma.rs +++ b/artiq/firmware/runtime/rtio_dma.rs @@ -1,5 +1,5 @@ use core::mem; -use alloc::{Vec, String, BTreeMap}; +use alloc::{vec::Vec, string::String, collections::btree_map::BTreeMap}; const ALIGNMENT: usize = 64; diff --git a/artiq/firmware/runtime/sched.rs b/artiq/firmware/runtime/sched.rs index 7a2a85723..a63ad3332 100644 --- a/artiq/firmware/runtime/sched.rs +++ b/artiq/firmware/runtime/sched.rs @@ -3,7 +3,7 @@ use core::mem; use core::result; use core::cell::{Cell, RefCell}; -use alloc::Vec; +use alloc::vec::Vec; use fringe::OwnedStack; use fringe::generator::{Generator, Yielder, State as GeneratorState}; use smoltcp::time::Duration; diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index 08bc5f188..bae438969 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -1,5 +1,5 @@ use core::{mem, str, cell::{Cell, RefCell}, fmt::Write as FmtWrite}; -use alloc::{Vec, String}; +use alloc::{vec::Vec, string::String}; use byteorder::{ByteOrder, NetworkEndian}; use io::{Read, Write, Error as IoError}; From f56152e72f4e13322ebc6141af7648e43cb86a84 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 11:10:43 +0800 Subject: [PATCH 076/238] rust: fix dependencies --- artiq/firmware/libeh/Cargo.toml | 2 ++ artiq/firmware/libeh/lib.rs | 2 +- artiq/firmware/libunwind_backtrace/Cargo.toml | 4 ++++ artiq/firmware/runtime/Cargo.toml | 2 +- artiq/firmware/runtime/main.rs | 3 +-- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/artiq/firmware/libeh/Cargo.toml b/artiq/firmware/libeh/Cargo.toml index c1bea6f4f..6908c14b9 100644 --- a/artiq/firmware/libeh/Cargo.toml +++ b/artiq/firmware/libeh/Cargo.toml @@ -9,3 +9,5 @@ path = "lib.rs" [dependencies] cslice = { version = "0.3" } +libc = { path = "../libc" } +unwind = { path = "../libunwind" } diff --git a/artiq/firmware/libeh/lib.rs b/artiq/firmware/libeh/lib.rs index da209ea25..b1a200da3 100644 --- a/artiq/firmware/libeh/lib.rs +++ b/artiq/firmware/libeh/lib.rs @@ -1,4 +1,4 @@ -#![feature(lang_items, panic_unwind, libc, unwind_attributes)] +#![feature(lang_items, panic_unwind, libc, unwind_attributes, int_bits_const)] #![no_std] extern crate cslice; diff --git a/artiq/firmware/libunwind_backtrace/Cargo.toml b/artiq/firmware/libunwind_backtrace/Cargo.toml index 637e55bc6..1925f4f1e 100644 --- a/artiq/firmware/libunwind_backtrace/Cargo.toml +++ b/artiq/firmware/libunwind_backtrace/Cargo.toml @@ -6,3 +6,7 @@ version = "0.0.0" [lib] name = "unwind_backtrace" path = "lib.rs" + +[dependencies] +unwind = { path = "../libunwind" } +libc = { path = "../libc" } diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index f96d4d29d..ca624e3b6 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -27,7 +27,7 @@ board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp logger_artiq = { path = "../liblogger_artiq" } board_artiq = { path = "../libboard_artiq" } proto_artiq = { path = "../libproto_artiq", features = ["log", "alloc"] } -smoltcp = { version = "0.6.0", default-features = false, features = ["rust-1_28", "alloc", "ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } +smoltcp = { version = "0.6.0", default-features = false, features = ["alloc", "ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } riscv = { version = "0.6.0", features = ["inline-asm"] } [dependencies.fringe] diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 968aba156..c6cd088e1 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -1,6 +1,5 @@ #![feature(lang_items, alloc, try_from, nonzero, asm, - panic_implementation, panic_info_message, - const_slice_len)] + panic_handler, panic_info_message)] #![no_std] extern crate eh; From c42adfe6fd8d52d03aeb3bbecf6ddba2f07e6d56 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 11:11:25 +0800 Subject: [PATCH 077/238] runtime.ld: merge .sbss & .bss --- artiq/firmware/runtime/runtime.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/runtime/runtime.ld b/artiq/firmware/runtime/runtime.ld index a7bcc5a0d..c93a5e4b1 100644 --- a/artiq/firmware/runtime/runtime.ld +++ b/artiq/firmware/runtime/runtime.ld @@ -61,7 +61,7 @@ SECTIONS .bss ALIGN(4) : { _fbss = .; - *(.bss .bss.*) + *(.sbss .sbss.* .bss .bss.*); _ebss = .; } > runtime From 7f0bc9f7f0f97dbab8924640926a24d84cdba60e Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 6 Aug 2021 11:12:27 +0800 Subject: [PATCH 078/238] runtime/makefile: specify emulation, flip endianness --- artiq/firmware/runtime/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/runtime/Makefile b/artiq/firmware/runtime/Makefile index 5fa6dbdf8..2b98acc43 100644 --- a/artiq/firmware/runtime/Makefile +++ b/artiq/firmware/runtime/Makefile @@ -21,10 +21,11 @@ runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o -lunwind-bare ksupport_data.o: ../ksupport/ksupport.elf - $(LD) -r -b binary -o $@ $< + $(LD) -m elf32lriscv -b binary -o $@ $< %.bin: %.elf $(objcopy) -O binary %.fbi: %.bin - $(mscimg) -f + $(mscimg) -f --little + objcopy -I binary -O binary --reverse-bytes=4 $@ From 50a62b3d4233b580b83fcba417bcc6c1ff2ad0b3 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 11 Aug 2021 12:18:13 +0800 Subject: [PATCH 079/238] liballoc: change align to 16 bytes --- artiq/firmware/liballoc_list/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/liballoc_list/lib.rs b/artiq/firmware/liballoc_list/lib.rs index f01262007..8af134b0e 100644 --- a/artiq/firmware/liballoc_list/lib.rs +++ b/artiq/firmware/liballoc_list/lib.rs @@ -4,7 +4,7 @@ use core::{ptr, mem, fmt}; use core::alloc::{GlobalAlloc, Layout}; // The minimum alignment guaranteed by the architecture. -const MIN_ALIGN: usize = 4; +const MIN_ALIGN: usize = 16; const MAGIC_FREE: usize = 0xDEADDEAD; const MAGIC_BUSY: usize = 0xFEEDFEED; From 905330b0f1c5ba19ca27b55be881e89067e2e57b Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 11 Aug 2021 12:20:41 +0800 Subject: [PATCH 080/238] ksupport: handle riscv exceptions --- artiq/firmware/ksupport/Cargo.toml | 2 +- artiq/firmware/ksupport/lib.rs | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/artiq/firmware/ksupport/Cargo.toml b/artiq/firmware/ksupport/Cargo.toml index ba53a7c9a..fbedbd792 100644 --- a/artiq/firmware/ksupport/Cargo.toml +++ b/artiq/firmware/ksupport/Cargo.toml @@ -19,4 +19,4 @@ io = { path = "../libio", features = ["byteorder"] } dyld = { path = "../libdyld" } board_misoc = { path = "../libboard_misoc" } board_artiq = { path = "../libboard_artiq" } -proto_artiq = { path = "../libproto_artiq" } +riscv = { version = "0.6.0", features = ["inline-asm"] } diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 5e42fd100..b4a430289 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -12,8 +12,9 @@ extern crate dyld; extern crate board_misoc; extern crate board_artiq; extern crate proto_artiq; +extern crate riscv; -use core::{mem, ptr, slice, str}; +use core::{mem, ptr, slice, str, convert::TryFrom}; use cslice::{CSlice, AsCSlice}; use io::Cursor; use dyld::Library; @@ -22,6 +23,7 @@ use proto_artiq::{kernel_proto, rpc_proto}; use kernel_proto::*; #[cfg(has_rtio_dma)] use board_misoc::csr; +use riscv::register::{mcause, mepc}; fn send(request: &Message) { unsafe { mailbox::send(request as *const _ as usize) } @@ -519,8 +521,10 @@ pub unsafe fn main() { #[no_mangle] #[unwind(allowed)] -pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) { - panic!("exception {:?} at PC 0x{:x}, EA 0x{:x}", vect, pc, ea) +pub extern fn exception(_regs: *const u32) { + let pc = mepc::read(); + let cause = mcause::read().cause(); + panic!("{:?} at PC {:#08x}", cause, u32::try_from(pc).unwrap()) } #[no_mangle] From 1b8b4baf6af53c22b3571765b4e18dd03c0cfb53 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 11 Aug 2021 12:21:56 +0800 Subject: [PATCH 081/238] ksupport: fix panic, libc, unwind --- artiq/firmware/ksupport/Cargo.toml | 2 ++ artiq/firmware/ksupport/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/ksupport/Cargo.toml b/artiq/firmware/ksupport/Cargo.toml index fbedbd792..5556eb15e 100644 --- a/artiq/firmware/ksupport/Cargo.toml +++ b/artiq/firmware/ksupport/Cargo.toml @@ -20,3 +20,5 @@ dyld = { path = "../libdyld" } board_misoc = { path = "../libboard_misoc" } board_artiq = { path = "../libboard_artiq" } riscv = { version = "0.6.0", features = ["inline-asm"] } +libc = { path = "../libc" } +unwind = { path = "../libunwind" } diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index b4a430289..bbbea4c02 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -1,5 +1,5 @@ #![feature(lang_items, asm, panic_unwind, libc, unwind_attributes, - panic_implementation, panic_info_message, nll)] + panic_handler, panic_info_message, nll)] #![no_std] extern crate libc; @@ -51,7 +51,7 @@ macro_rules! recv { } #[no_mangle] // https://github.com/rust-lang/rust/issues/{38281,51647} -#[panic_implementation] +#[panic_handler] pub fn panic_fmt(info: &core::panic::PanicInfo) -> ! { if let Some(location) = info.location() { send(&Log(format_args!("panic at {}:{}:{}", From 5656e5258134e9ac4f202a9966172b0c6dc7c244 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 11:43:19 +0800 Subject: [PATCH 082/238] remove profiler --- artiq/firmware/runtime/main.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index c6cd088e1..df1f2874e 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -288,17 +288,6 @@ pub extern fn exception(regs: *const TrapFrame) { match cause { mcause::Trap::Interrupt(source) => { info!("Called interrupt with {:?}", source); - // while irq::pending_mask() != 0 { - // match () { - // #[cfg(has_timer1)] - // () if irq::is_pending(csr::TIMER1_INTERRUPT) => - // profiler::sample(pc as usize), - // _ => { - // panic!("spurious irq {}", irq::pending_mask().trailing_zeros()) - // } - // } - // } - panic!("Interrupt not present"); }, mcause::Trap::Exception(e) => { println!("Stack pointer: {:p}", regs); From 43d120359d5e63ded08ad7de99893f754b55e2e1 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 11:54:36 +0800 Subject: [PATCH 083/238] compiler: switch to upstream llvmlite and RISC-V target --- artiq/compiler/targets.py | 21 +++++++++---------- artiq/compiler/testbench/jit.py | 2 +- artiq/compiler/testbench/llvmgen.py | 2 +- artiq/compiler/testbench/perf.py | 4 ++-- artiq/compiler/testbench/perf_embedding.py | 4 ++-- artiq/compiler/testbench/shlib.py | 4 ++-- .../compiler/transforms/llvm_ir_generator.py | 2 +- artiq/coredevice/core.py | 8 +++---- artiq/frontend/artiq_ddb_template.py | 2 +- artiq/frontend/artiq_run.py | 2 +- doc/manual/conf.py | 2 +- setup.py | 2 +- 12 files changed, 27 insertions(+), 28 deletions(-) diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index 9ebc7907d..745dede81 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -1,6 +1,6 @@ import os, sys, tempfile, subprocess, io from artiq.compiler import types, ir -from llvmlite_artiq import ir as ll, binding as llvm +from llvmlite import ir as ll, binding as llvm llvm.initialize() llvm.initialize_all_targets() @@ -67,7 +67,7 @@ class Target: generated by the ARTIQ compiler will be deployed. :var triple: (string) - LLVM target triple, e.g. ``"or1k"`` + LLVM target triple, e.g. ``"riscv32"`` :var data_layout: (string) LLVM target data layout, e.g. ``"E-m:e-p:32:32-i64:32-f64:32-v64:32-v128:32-a:0:32-n32"`` :var features: (list of string) @@ -255,19 +255,18 @@ class NativeTarget(Target): assert host_data_layout[0] in "eE" self.little_endian = host_data_layout[0] == "e" -class OR1KTarget(Target): - triple = "or1k-linux" - data_layout = "E-m:e-p:32:32-i8:8:8-i16:16:16-i64:32:32-" \ - "f64:32:32-v64:32:32-v128:32:32-a0:0:32-n32" - features = ["mul", "div", "ffl1", "cmov", "addc"] +class RISCVTarget(Target): + triple = "riscv32-unknown-linux" + data_layout = "e-m:e-p:32:32-i64:64-n32-S128" + features = [] print_function = "core_log" little_endian = False now_pinning = True - tool_ld = "or1k-linux-ld" - tool_strip = "or1k-linux-strip" - tool_addr2line = "or1k-linux-addr2line" - tool_cxxfilt = "or1k-linux-c++filt" + tool_ld = "ld.lld" + tool_strip = "llvm-strip" + tool_addr2line = "llvm-addr2line" + tool_cxxfilt = "llvm-cxxfilt" class CortexA9Target(Target): triple = "armv7-unknown-linux-gnueabihf" diff --git a/artiq/compiler/testbench/jit.py b/artiq/compiler/testbench/jit.py index 309073404..67a43c008 100644 --- a/artiq/compiler/testbench/jit.py +++ b/artiq/compiler/testbench/jit.py @@ -1,6 +1,6 @@ import os, sys, fileinput, ctypes from pythonparser import diagnostic -from llvmlite_artiq import binding as llvm +from llvmlite import binding as llvm from ..module import Module, Source from ..targets import NativeTarget diff --git a/artiq/compiler/testbench/llvmgen.py b/artiq/compiler/testbench/llvmgen.py index ed318b897..6bcf031c9 100644 --- a/artiq/compiler/testbench/llvmgen.py +++ b/artiq/compiler/testbench/llvmgen.py @@ -1,6 +1,6 @@ import sys, fileinput from pythonparser import diagnostic -from llvmlite_artiq import ir as ll +from llvmlite import ir as ll from ..module import Module, Source from ..targets import NativeTarget diff --git a/artiq/compiler/testbench/perf.py b/artiq/compiler/testbench/perf.py index cee4e3c2a..363c88840 100644 --- a/artiq/compiler/testbench/perf.py +++ b/artiq/compiler/testbench/perf.py @@ -1,7 +1,7 @@ import sys, os from pythonparser import diagnostic from ..module import Module, Source -from ..targets import OR1KTarget +from ..targets import RISCVTarget from . import benchmark def main(): @@ -30,7 +30,7 @@ def main(): benchmark(lambda: Module(source), "ARTIQ transforms and validators") - benchmark(lambda: OR1KTarget().compile_and_link([module]), + benchmark(lambda: RISCVTarget().compile_and_link([module]), "LLVM optimization and linking") if __name__ == "__main__": diff --git a/artiq/compiler/testbench/perf_embedding.py b/artiq/compiler/testbench/perf_embedding.py index 41f09cb04..d626d5534 100644 --- a/artiq/compiler/testbench/perf_embedding.py +++ b/artiq/compiler/testbench/perf_embedding.py @@ -5,7 +5,7 @@ from ...master.databases import DeviceDB, DatasetDB from ...master.worker_db import DeviceManager, DatasetManager from ..module import Module from ..embedding import Stitcher -from ..targets import OR1KTarget +from ..targets import RISCVTarget from . import benchmark @@ -45,7 +45,7 @@ def main(): stitcher = embed() module = Module(stitcher) - target = OR1KTarget() + target = RISCVTarget() llvm_ir = target.compile(module) elf_obj = target.assemble(llvm_ir) elf_shlib = target.link([elf_obj]) diff --git a/artiq/compiler/testbench/shlib.py b/artiq/compiler/testbench/shlib.py index 47209a979..0aa6386d3 100644 --- a/artiq/compiler/testbench/shlib.py +++ b/artiq/compiler/testbench/shlib.py @@ -1,7 +1,7 @@ import sys, os from pythonparser import diagnostic from ..module import Module, Source -from ..targets import OR1KTarget +from ..targets import RISCVTarget def main(): if not len(sys.argv) > 1: @@ -20,7 +20,7 @@ def main(): for filename in sys.argv[1:]: modules.append(Module(Source.from_filename(filename, engine=engine))) - llobj = OR1KTarget().compile_and_link(modules) + llobj = RISCVTarget().compile_and_link(modules) basename, ext = os.path.splitext(sys.argv[-1]) with open(basename + ".so", "wb") as f: diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 49fc339bd..10b83f3a7 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -6,7 +6,7 @@ into LLVM intermediate representation. import os, re, types as pytypes, numpy from collections import defaultdict from pythonparser import ast, diagnostic -from llvmlite_artiq import ir as ll, binding as llvm +from llvmlite import ir as ll, binding as llvm from ...language import core as language_core from .. import types, builtins, ir from ..embedding import SpecializedFunction diff --git a/artiq/coredevice/core.py b/artiq/coredevice/core.py index d150df596..dc8207266 100644 --- a/artiq/coredevice/core.py +++ b/artiq/coredevice/core.py @@ -11,7 +11,7 @@ from artiq.language.units import * from artiq.compiler.module import Module from artiq.compiler.embedding import Stitcher -from artiq.compiler.targets import OR1KTarget, CortexA9Target +from artiq.compiler.targets import RISCVTarget, CortexA9Target from artiq.coredevice.comm_kernel import CommKernel, CommKernelDummy # Import for side effects (creating the exception classes). @@ -71,11 +71,11 @@ class Core: "core", "ref_period", "coarse_ref_period", "ref_multiplier", } - def __init__(self, dmgr, host, ref_period, ref_multiplier=8, target="or1k"): + def __init__(self, dmgr, host, ref_period, ref_multiplier=8, target="riscv"): self.ref_period = ref_period self.ref_multiplier = ref_multiplier - if target == "or1k": - self.target_cls = OR1KTarget + if target == "riscv": + self.target_cls = RISCVTarget elif target == "cortexa9": self.target_cls = CortexA9Target else: diff --git a/artiq/frontend/artiq_ddb_template.py b/artiq/frontend/artiq_ddb_template.py index c73680c8e..4dfba4f93 100755 --- a/artiq/frontend/artiq_ddb_template.py +++ b/artiq/frontend/artiq_ddb_template.py @@ -15,7 +15,7 @@ def process_header(output, description): raise NotImplementedError cpu_target = { - "kasli": "or1k", + "kasli": "riscv", "kasli_soc": "cortexa9" }[description["target"]] diff --git a/artiq/frontend/artiq_run.py b/artiq/frontend/artiq_run.py index 98e3c8221..21baf3f05 100755 --- a/artiq/frontend/artiq_run.py +++ b/artiq/frontend/artiq_run.py @@ -10,7 +10,7 @@ from collections import defaultdict import h5py -from llvmlite_artiq import binding as llvm +from llvmlite import binding as llvm from sipyco import common_args diff --git a/doc/manual/conf.py b/doc/manual/conf.py index 509816e80..bc092928f 100644 --- a/doc/manual/conf.py +++ b/doc/manual/conf.py @@ -37,7 +37,7 @@ mock_modules = ["artiq.gui.waitingspinnerwidget", "qasync", "pyqtgraph", "matplotlib", "numpy", "dateutil", "dateutil.parser", "prettytable", "PyQt5", "h5py", "serial", "scipy", "scipy.interpolate", - "llvmlite_artiq", "Levenshtein", "pythonparser", + "llvmlite", "Levenshtein", "pythonparser", "sipyco", "sipyco.pc_rpc", "sipyco.sync_struct", "sipyco.asyncio_tools", "sipyco.logging_tools", "sipyco.broadcast", "sipyco.packed_exceptions"] diff --git a/setup.py b/setup.py index 980e6b109..ed3ef26d2 100755 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ requirements = [ "numpy", "scipy", "python-dateutil", "prettytable", "h5py", "qasync", "pyqtgraph", "pygit2", - "llvmlite_artiq", "pythonparser", "python-Levenshtein", + "llvmlite", "pythonparser", "python-Levenshtein", ] console_scripts = [ From 6629a49e86bb32264a14163a2b6349ded38e710f Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 11:54:55 +0800 Subject: [PATCH 084/238] compiler: use LLVM binutils/linker for Arm as well Previously we kept GNU Binutils because they are less of a pain to support on Windoze - the source of so many problems - but with RISC-V we need to update LLVM anyway. --- artiq/compiler/targets.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index 745dede81..b6e33e8ca 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -276,7 +276,7 @@ class CortexA9Target(Target): little_endian = True now_pinning = False - tool_ld = "armv7-unknown-linux-gnueabihf-ld" - tool_strip = "armv7-unknown-linux-gnueabihf-strip" - tool_addr2line = "armv7-unknown-linux-gnueabihf-addr2line" - tool_cxxfilt = "armv7-unknown-linux-gnueabihf-c++filt" + tool_ld = "ld.lld" + tool_strip = "llvm-strip" + tool_addr2line = "llvm-addr2line" + tool_cxxfilt = "llvm-cxxfilt" From cabe5ace8e54a91eca996a62e0a71d42cd99e320 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 12:13:39 +0800 Subject: [PATCH 085/238] compiler: remove DebugInfoEmitter for now Causes problems with LLVM 9 and not needed at first. --- .../compiler/transforms/llvm_ir_generator.py | 96 ------------------- 1 file changed, 96 deletions(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 10b83f3a7..7d7ca6344 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -37,93 +37,6 @@ def memoize(generator): return result return memoized -class DebugInfoEmitter: - def __init__(self, llmodule): - self.llmodule = llmodule - self.llcompileunit = None - self.cache = {} - - llident = self.llmodule.add_named_metadata('llvm.ident') - llident.add(self.emit_metadata(["ARTIQ"])) - - llflags = self.llmodule.add_named_metadata('llvm.module.flags') - llflags.add(self.emit_metadata([2, "Debug Info Version", 3])) - llflags.add(self.emit_metadata([2, "Dwarf Version", 4])) - - def emit_metadata(self, operands): - def map_operand(operand): - if operand is None: - return ll.Constant(llmetadata, None) - elif isinstance(operand, str): - return ll.MetaDataString(self.llmodule, operand) - elif isinstance(operand, int): - return ll.Constant(lli32, operand) - elif isinstance(operand, (list, tuple)): - return self.emit_metadata(operand) - else: - assert isinstance(operand, ll.NamedValue) - return operand - return self.llmodule.add_metadata(list(map(map_operand, operands))) - - def emit_debug_info(self, kind, operands, is_distinct=False): - return self.llmodule.add_debug_info(kind, operands, is_distinct) - - @memoize - def emit_file(self, source_buffer): - source_dir, source_file = os.path.split(source_buffer.name) - return self.emit_debug_info("DIFile", { - "filename": source_file, - "directory": source_dir, - }) - - @memoize - def emit_compile_unit(self, source_buffer): - return self.emit_debug_info("DICompileUnit", { - "language": ll.DIToken("DW_LANG_Python"), - "file": self.emit_file(source_buffer), - "producer": "ARTIQ", - "runtimeVersion": 0, - "emissionKind": 2, # full=1, lines only=2 - }, is_distinct=True) - - @memoize - def emit_subroutine_type(self, typ): - return self.emit_debug_info("DISubroutineType", { - "types": self.emit_metadata([None]) - }) - - @memoize - def emit_subprogram(self, func, llfunc): - source_buffer = func.loc.source_buffer - - if self.llcompileunit is None: - self.llcompileunit = self.emit_compile_unit(source_buffer) - llcompileunits = self.llmodule.add_named_metadata('llvm.dbg.cu') - llcompileunits.add(self.llcompileunit) - - display_name = "{}{}".format(func.name, types.TypePrinter().name(func.type)) - return self.emit_debug_info("DISubprogram", { - "name": func.name, - "linkageName": llfunc.name, - "type": self.emit_subroutine_type(func.type), - "file": self.emit_file(source_buffer), - "line": func.loc.line(), - "unit": self.llcompileunit, - "scope": self.emit_file(source_buffer), - "scopeLine": func.loc.line(), - "isLocal": func.is_internal, - "isDefinition": True, - "variables": self.emit_metadata([]) - }, is_distinct=True) - - @memoize - def emit_loc(self, loc, scope): - return self.emit_debug_info("DILocation", { - "line": loc.line(), - "column": loc.column(), - "scope": scope - }) - class ABILayoutInfo: """Caches DataLayout size/alignment lookup results. @@ -170,7 +83,6 @@ class LLVMIRGenerator: self.llmap = {} self.llobject_map = {} self.phis = [] - self.debug_info_emitter = DebugInfoEmitter(self.llmodule) self.empty_metadata = self.llmodule.add_metadata([]) self.tbaa_tree = self.llmodule.add_metadata([ ll.MetaDataString(self.llmodule, "ARTIQ TBAA") @@ -659,10 +571,6 @@ class LLVMIRGenerator: self.llbuilder = ll.IRBuilder() llblock_map = {} - if not func.is_generated: - lldisubprogram = self.debug_info_emitter.emit_subprogram(func, self.llfunction) - self.llfunction.set_metadata('dbg', lldisubprogram) - # First, map arguments. if self.has_sret(func.type): llactualargs = self.llfunction.args[1:] @@ -682,10 +590,6 @@ class LLVMIRGenerator: for block in func.basic_blocks: self.llbuilder.position_at_end(self.llmap[block]) for insn in block.instructions: - if insn.loc is not None and not func.is_generated: - self.llbuilder.debug_metadata = \ - self.debug_info_emitter.emit_loc(insn.loc, lldisubprogram) - llinsn = getattr(self, "process_" + type(insn).__name__)(insn) assert llinsn is not None self.llmap[insn] = llinsn From e8fe8409b2c62e1ef16029d6e861b7009a70ce85 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 12:33:58 +0800 Subject: [PATCH 086/238] libartiq_support: compatibility with recent stable rustc --- artiq/test/libartiq_support/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/test/libartiq_support/lib.rs b/artiq/test/libartiq_support/lib.rs index 77e8f4160..8f06852ba 100644 --- a/artiq/test/libartiq_support/lib.rs +++ b/artiq/test/libartiq_support/lib.rs @@ -1,4 +1,4 @@ -#![feature(libc, panic_unwind, unwind_attributes)] +#![feature(libc, panic_unwind, unwind_attributes, rustc_private, int_bits_const)] #![crate_name = "artiq_support"] #![crate_type = "cdylib"] From d13efd6587fd63eb84b2dbacf74a56c65ad9f471 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 12:44:42 +0800 Subject: [PATCH 087/238] add Nix flake --- flake.lock | 61 ++++++++++++++++++++++++++++++ flake.nix | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..5e5b1013f --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1628696776, + "narHash": "sha256-K8+/IQNZDZltIu/KSf+Tz01OwNzTGgTch0ktMOWcxLg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "927ce1afc1db40869a463a37ea2738c27d425f80", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-21.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "src-pythonparser": "src-pythonparser", + "src-sipyco": "src-sipyco" + } + }, + "src-pythonparser": { + "flake": false, + "locked": { + "lastModified": 1628731931, + "narHash": "sha256-eaGuXyrkvpBPNJVKoihnoqvhoWvqaTvztTdKb+7BJfc=", + "owner": "m-labs", + "repo": "pythonparser", + "rev": "f6be5a1bfe44c05ffd36c8016858175954b9722d", + "type": "github" + }, + "original": { + "owner": "m-labs", + "repo": "pythonparser", + "type": "github" + } + }, + "src-sipyco": { + "flake": false, + "locked": { + "lastModified": 1623807309, + "narHash": "sha256-FTRAS4RjqDOygu6+cP8mKbZHu/YZ7YKpEe2gSzJc9rk=", + "owner": "m-labs", + "repo": "sipyco", + "rev": "20c946aad78872fe60b78d9b57a624d69f3eea47", + "type": "github" + }, + "original": { + "owner": "m-labs", + "repo": "sipyco", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..800212727 --- /dev/null +++ b/flake.nix @@ -0,0 +1,107 @@ +{ + description = "A leading-edge control system for quantum information experiments"; + + inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-21.05; + inputs.src-sipyco = { url = github:m-labs/sipyco; flake = false; }; + inputs.src-pythonparser = { url = github:m-labs/pythonparser; flake = false; }; + + outputs = { self, nixpkgs, src-sipyco, src-pythonparser }: with import nixpkgs { system = "x86_64-linux"; }; rec { + packages.x86_64-linux = rec { + sipyco = python3Packages.buildPythonPackage { + name = "sipyco"; + src = src-sipyco; + propagatedBuildInputs = with python3Packages; [ pybase64 numpy ]; + }; + + pythonparser = python3Packages.buildPythonPackage { + name = "pythonparser"; + src = src-pythonparser; + doCheck = false; + propagatedBuildInputs = with python3Packages; [ regex ]; + }; + + qasync = python3Packages.buildPythonPackage rec { + pname = "qasync"; + version = "0.10.0"; + src = fetchFromGitHub { + owner = "CabbageDevelopment"; + repo = "qasync"; + rev = "v${version}"; + sha256 = "1zga8s6dr7gk6awmxkh4pf25gbg8n6dv1j4b0by7y0fhi949qakq"; + }; + propagatedBuildInputs = [ python3Packages.pyqt5 ]; + checkInputs = [ python3Packages.pytest ]; + checkPhase = '' + pytest -k 'test_qthreadexec.py' # the others cause the test execution to be aborted, I think because of asyncio + ''; + }; + + outputcheck = python3Packages.buildPythonApplication rec { + pname = "outputcheck"; + version = "0.4.2"; + src = fetchFromGitHub { + owner = "stp"; + repo = "OutputCheck"; + rev = "e0f533d3c5af2949349856c711bf4bca50022b48"; + sha256 = "1y27vz6jq6sywas07kz3v01sqjd0sga9yv9w2cksqac3v7wmf2a0"; + }; + prePatch = "echo ${version} > RELEASE-VERSION"; + }; + + libartiq-support = stdenv.mkDerivation { + name = "libartiq-support"; + src = self; + buildInputs = [ rustc ]; + buildPhase = '' + # Obviously, #[feature()] can in fact be used on the stable channel, contrary to what the rustc error message says. + # You just need to set this obscure RUSTC_BOOTSTRAP environment variable. + RUSTC_BOOTSTRAP=1 rustc $src/artiq/test/libartiq_support/lib.rs -Cpanic=unwind -g + ''; + installPhase = '' + mkdir $out + cp libartiq_support.so $out + ''; + }; + + artiq = python3Packages.buildPythonPackage rec { + pname = "artiq"; + version = "7.0-dev"; + src = self; + + preBuild = "export VERSIONEER_OVERRIDE=${version}"; + + nativeBuildInputs = [ qt5.wrapQtAppsHook ]; + # keep llvm_x and lld_x in sync with llvmlite + propagatedBuildInputs = [ llvm_9 lld_9 sipyco pythonparser ] + ++ (with python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial python-Levenshtein h5py pyqt5 qasync llvmlite ]); + + dontWrapQtApps = true; + postFixup = '' + wrapQtApp "$out/bin/artiq_dashboard" + wrapQtApp "$out/bin/artiq_browser" + wrapQtApp "$out/bin/artiq_session" + ''; + + # Modifies PATH to pass the wrapped python environment (i.e. python3.withPackages(...) to subprocesses. + # Allows subprocesses using python to find all packages you have installed + makeWrapperArgs = [ + ''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' '' + "--set FONTCONFIG_FILE ${fontconfig.out}/etc/fonts/fonts.conf" + ]; + + # FIXME: automatically propagate lld_9 llvm_9 dependencies + checkInputs = [ lld_9 llvm_9 outputcheck lit ]; + checkPhase = '' + python -m unittest discover -v artiq.test + + TESTDIR=`mktemp -d` + cp --no-preserve=mode,ownership -R $src/artiq/test/lit $TESTDIR + # FIXME: some tests fail + #LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so lit -v $TESTDIR/lit + ''; + }; + }; + + defaultPackage.x86_64-linux = python3.withPackages(ps: [ packages.x86_64-linux.artiq ]); + }; +} From be5ae5c5b4cd28e3254b7ee5c693889579a153ab Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 12 Aug 2021 15:22:23 +0800 Subject: [PATCH 088/238] flake: configure binary cache --- flake.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/flake.nix b/flake.nix index 800212727..b276c11b5 100644 --- a/flake.nix +++ b/flake.nix @@ -104,4 +104,9 @@ defaultPackage.x86_64-linux = python3.withPackages(ps: [ packages.x86_64-linux.artiq ]); }; + + nixConfig = { + binaryCachePublicKeys = ["nixbld.m-labs.hk-1:5aSRVA5b320xbNvu30tqxVPXpld73bhtOeH6uAjRyHc="]; + binaryCaches = ["https://nixbld.m-labs.hk" "https://cache.nixos.org"]; + }; } From 1b516b16e266e2a22f3387adefe41906f3066e55 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 16 Aug 2021 15:42:58 +0800 Subject: [PATCH 089/238] targets: default to vexriscv cpu --- artiq/gateware/targets/kasli.py | 6 +++--- artiq/gateware/targets/kc705.py | 6 +++--- artiq/gateware/targets/metlino.py | 2 +- artiq/gateware/targets/sayma_amc.py | 2 +- artiq/gateware/targets/sayma_rtm.py | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 91c6fb9a0..131d75a79 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -116,7 +116,7 @@ class StandaloneBase(MiniSoC, AMPSoC): def __init__(self, gateware_identifier_str=None, **kwargs): MiniSoC.__init__(self, - cpu_type="or1k", + cpu_type="vexriscv", sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, @@ -298,7 +298,7 @@ class MasterBase(MiniSoC, AMPSoC): def __init__(self, rtio_clk_freq=125e6, enable_sata=False, gateware_identifier_str=None, **kwargs): MiniSoC.__init__(self, - cpu_type="or1k", + cpu_type="vexriscv", sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, @@ -474,7 +474,7 @@ class SatelliteBase(BaseSoC): def __init__(self, rtio_clk_freq=125e6, enable_sata=False, *, with_wrpll=False, gateware_identifier_str=None, **kwargs): BaseSoC.__init__(self, - cpu_type="or1k", + cpu_type="vexriscv", sdram_controller_type="minicon", l2_size=128*1024, **kwargs) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 9d167b566..0b69c18b1 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -172,7 +172,7 @@ class _StandaloneBase(MiniSoC, AMPSoC): def __init__(self, gateware_identifier_str=None, **kwargs): MiniSoC.__init__(self, - cpu_type="or1k", + cpu_type="vexriscv", sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, @@ -249,7 +249,7 @@ class _MasterBase(MiniSoC, AMPSoC): def __init__(self, gateware_identifier_str=None, **kwargs): MiniSoC.__init__(self, - cpu_type="or1k", + cpu_type="vexriscv", sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, @@ -382,7 +382,7 @@ class _SatelliteBase(BaseSoC): def __init__(self, gateware_identifier_str=None, sma_as_sat=False, **kwargs): BaseSoC.__init__(self, - cpu_type="or1k", + cpu_type="vexriscv", sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, diff --git a/artiq/gateware/targets/metlino.py b/artiq/gateware/targets/metlino.py index 4f609e1c7..74c2e35f0 100755 --- a/artiq/gateware/targets/metlino.py +++ b/artiq/gateware/targets/metlino.py @@ -42,7 +42,7 @@ class Master(MiniSoC, AMPSoC): def __init__(self, gateware_identifier_str=None, **kwargs): MiniSoC.__init__(self, - cpu_type="or1k", + cpu_type="vexriscv", sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, diff --git a/artiq/gateware/targets/sayma_amc.py b/artiq/gateware/targets/sayma_amc.py index f46942e67..6155eb31f 100755 --- a/artiq/gateware/targets/sayma_amc.py +++ b/artiq/gateware/targets/sayma_amc.py @@ -56,7 +56,7 @@ class SatelliteBase(MiniSoC): def __init__(self, rtio_clk_freq=125e6, identifier_suffix="", gateware_identifier_str=None, with_sfp=False, *, with_wrpll, **kwargs): MiniSoC.__init__(self, - cpu_type="or1k", + cpu_type="vexriscv", sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, diff --git a/artiq/gateware/targets/sayma_rtm.py b/artiq/gateware/targets/sayma_rtm.py index 294a17823..a302a795f 100755 --- a/artiq/gateware/targets/sayma_rtm.py +++ b/artiq/gateware/targets/sayma_rtm.py @@ -77,7 +77,7 @@ class _SatelliteBase(BaseSoC): def __init__(self, rtio_clk_freq, *, with_wrpll, gateware_identifier_str, **kwargs): BaseSoC.__init__(self, - cpu_type="or1k", + cpu_type="vexriscv", **kwargs) add_identifier(self, gateware_identifier_str=gateware_identifier_str) self.rtio_clk_freq = rtio_clk_freq From 8c468d03467f921cfaf6b5cecefd8a03409752c1 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 16 Aug 2021 14:53:15 +0800 Subject: [PATCH 090/238] flake: switch to nightly rust with mozilla overlay --- flake.lock | 17 +++++ flake.nix | 203 +++++++++++++++++++++++++++++------------------------ 2 files changed, 128 insertions(+), 92 deletions(-) diff --git a/flake.lock b/flake.lock index 5e5b1013f..88da8fb30 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "mozilla-overlay": { + "flake": false, + "locked": { + "lastModified": 1627922300, + "narHash": "sha256-/5fyO/265Wrli2pHpe1/i9Lu8XnQ5K+2YLz9Sz568cI=", + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "rev": "b1001ed670666ca4ce1c1b064481f88694315c1d", + "type": "github" + }, + "original": { + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1628696776, @@ -18,6 +34,7 @@ }, "root": { "inputs": { + "mozilla-overlay": "mozilla-overlay", "nixpkgs": "nixpkgs", "src-pythonparser": "src-pythonparser", "src-sipyco": "src-sipyco" diff --git a/flake.nix b/flake.nix index b276c11b5..4a3d55b40 100644 --- a/flake.nix +++ b/flake.nix @@ -2,108 +2,127 @@ description = "A leading-edge control system for quantum information experiments"; inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-21.05; + inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; }; inputs.src-sipyco = { url = github:m-labs/sipyco; flake = false; }; inputs.src-pythonparser = { url = github:m-labs/pythonparser; flake = false; }; - outputs = { self, nixpkgs, src-sipyco, src-pythonparser }: with import nixpkgs { system = "x86_64-linux"; }; rec { - packages.x86_64-linux = rec { - sipyco = python3Packages.buildPythonPackage { - name = "sipyco"; - src = src-sipyco; - propagatedBuildInputs = with python3Packages; [ pybase64 numpy ]; + outputs = { self, nixpkgs, mozilla-overlay, src-sipyco, src-pythonparser }: + let + pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) ]; }; + rustManifest = pkgs.fetchurl { + url = "https://static.rust-lang.org/dist/2021-01-29/channel-rust-nightly.toml"; + sha256 = "sha256-EZKgw89AH4vxaJpUHmIMzMW/80wAFQlfcxRoBD9nz0c="; }; - - pythonparser = python3Packages.buildPythonPackage { - name = "pythonparser"; - src = src-pythonparser; - doCheck = false; - propagatedBuildInputs = with python3Packages; [ regex ]; - }; - - qasync = python3Packages.buildPythonPackage rec { - pname = "qasync"; - version = "0.10.0"; - src = fetchFromGitHub { - owner = "CabbageDevelopment"; - repo = "qasync"; - rev = "v${version}"; - sha256 = "1zga8s6dr7gk6awmxkh4pf25gbg8n6dv1j4b0by7y0fhi949qakq"; + targets = []; + rustChannelOfTargets = _channel: _date: targets: + (pkgs.lib.rustLib.fromManifestFile rustManifest { + inherit (pkgs) stdenv lib fetchurl patchelf; + }).rust.override { + inherit targets; + extensions = ["rust-src"]; }; - propagatedBuildInputs = [ python3Packages.pyqt5 ]; - checkInputs = [ python3Packages.pytest ]; - checkPhase = '' - pytest -k 'test_qthreadexec.py' # the others cause the test execution to be aborted, I think because of asyncio - ''; - }; - - outputcheck = python3Packages.buildPythonApplication rec { - pname = "outputcheck"; - version = "0.4.2"; - src = fetchFromGitHub { - owner = "stp"; - repo = "OutputCheck"; - rev = "e0f533d3c5af2949349856c711bf4bca50022b48"; - sha256 = "1y27vz6jq6sywas07kz3v01sqjd0sga9yv9w2cksqac3v7wmf2a0"; + rust = rustChannelOfTargets "nightly" null targets; + rustPlatform = pkgs.recurseIntoAttrs (pkgs.makeRustPlatform { + rustc = rust; + cargo = rust; + }); + in rec { + packages.x86_64-linux = rec { + sipyco = pkgs.python3Packages.buildPythonPackage { + name = "sipyco"; + src = src-sipyco; + propagatedBuildInputs = with pkgs.python3Packages; [ pybase64 numpy ]; }; - prePatch = "echo ${version} > RELEASE-VERSION"; - }; - libartiq-support = stdenv.mkDerivation { - name = "libartiq-support"; - src = self; - buildInputs = [ rustc ]; - buildPhase = '' - # Obviously, #[feature()] can in fact be used on the stable channel, contrary to what the rustc error message says. - # You just need to set this obscure RUSTC_BOOTSTRAP environment variable. - RUSTC_BOOTSTRAP=1 rustc $src/artiq/test/libartiq_support/lib.rs -Cpanic=unwind -g - ''; - installPhase = '' - mkdir $out - cp libartiq_support.so $out - ''; - }; + pythonparser = pkgs.python3Packages.buildPythonPackage { + name = "pythonparser"; + src = src-pythonparser; + doCheck = false; + propagatedBuildInputs = with pkgs.python3Packages; [ regex ]; + }; - artiq = python3Packages.buildPythonPackage rec { - pname = "artiq"; - version = "7.0-dev"; - src = self; - - preBuild = "export VERSIONEER_OVERRIDE=${version}"; - - nativeBuildInputs = [ qt5.wrapQtAppsHook ]; - # keep llvm_x and lld_x in sync with llvmlite - propagatedBuildInputs = [ llvm_9 lld_9 sipyco pythonparser ] - ++ (with python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial python-Levenshtein h5py pyqt5 qasync llvmlite ]); - - dontWrapQtApps = true; - postFixup = '' - wrapQtApp "$out/bin/artiq_dashboard" - wrapQtApp "$out/bin/artiq_browser" - wrapQtApp "$out/bin/artiq_session" - ''; - - # Modifies PATH to pass the wrapped python environment (i.e. python3.withPackages(...) to subprocesses. - # Allows subprocesses using python to find all packages you have installed - makeWrapperArgs = [ - ''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' '' - "--set FONTCONFIG_FILE ${fontconfig.out}/etc/fonts/fonts.conf" - ]; - - # FIXME: automatically propagate lld_9 llvm_9 dependencies - checkInputs = [ lld_9 llvm_9 outputcheck lit ]; - checkPhase = '' - python -m unittest discover -v artiq.test - - TESTDIR=`mktemp -d` - cp --no-preserve=mode,ownership -R $src/artiq/test/lit $TESTDIR - # FIXME: some tests fail - #LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so lit -v $TESTDIR/lit + qasync = pkgs.python3Packages.buildPythonPackage rec { + pname = "qasync"; + version = "0.10.0"; + src = pkgs.fetchFromGitHub { + owner = "CabbageDevelopment"; + repo = "qasync"; + rev = "v${version}"; + sha256 = "1zga8s6dr7gk6awmxkh4pf25gbg8n6dv1j4b0by7y0fhi949qakq"; + }; + propagatedBuildInputs = [ pkgs.python3Packages.pyqt5 ]; + checkInputs = [ pkgs.python3Packages.pytest ]; + checkPhase = '' + pytest -k 'test_qthreadexec.py' # the others cause the test execution to be aborted, I think because of asyncio ''; - }; - }; + }; - defaultPackage.x86_64-linux = python3.withPackages(ps: [ packages.x86_64-linux.artiq ]); - }; + outputcheck = pkgs.python3Packages.buildPythonApplication rec { + pname = "outputcheck"; + version = "0.4.2"; + src = pkgs.fetchFromGitHub { + owner = "stp"; + repo = "OutputCheck"; + rev = "e0f533d3c5af2949349856c711bf4bca50022b48"; + sha256 = "1y27vz6jq6sywas07kz3v01sqjd0sga9yv9w2cksqac3v7wmf2a0"; + }; + prePatch = "echo ${version} > RELEASE-VERSION"; + }; + + libartiq-support = pkgs.stdenv.mkDerivation { + name = "libartiq-support"; + src = self; + buildInputs = [ rustPlatform.rust.rustc ]; + buildPhase = '' + rustc $src/artiq/test/libartiq_support/lib.rs -Cpanic=unwind -g + ''; + installPhase = '' + mkdir $out + cp libartiq_support.so $out + ''; + }; + + artiq = pkgs.python3Packages.buildPythonPackage rec { + pname = "artiq"; + version = "7.0-dev"; + src = self; + + preBuild = "export VERSIONEER_OVERRIDE=${version}"; + + nativeBuildInputs = [ pkgs.qt5.wrapQtAppsHook ]; + # keep llvm_x and lld_x in sync with llvmlite + propagatedBuildInputs = [ pkgs.llvm_9 pkgs.lld_9 sipyco pythonparser ] + ++ (with pkgs.python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial python-Levenshtein h5py pyqt5 qasync llvmlite ]); + + dontWrapQtApps = true; + postFixup = '' + wrapQtApp "$out/bin/artiq_dashboard" + wrapQtApp "$out/bin/artiq_browser" + wrapQtApp "$out/bin/artiq_session" + ''; + + # Modifies PATH to pass the wrapped python environment (i.e. python3.withPackages(...) to subprocesses. + # Allows subprocesses using python to find all packages you have installed + makeWrapperArgs = [ + ''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' '' + "--set FONTCONFIG_FILE ${pkgs.fontconfig.out}/etc/fonts/fonts.conf" + ]; + + # FIXME: automatically propagate lld_9 llvm_9 dependencies + checkInputs = [ pkgs.lld_9 pkgs.llvm_9 pkgs.lit outputcheck ]; + checkPhase = '' + python -m unittest discover -v artiq.test + + TESTDIR=`mktemp -d` + cp --no-preserve=mode,ownership -R $src/artiq/test/lit $TESTDIR + # FIXME: some tests fail + #LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so lit -v $TESTDIR/lit + ''; + }; + }; + + defaultPackage.x86_64-linux = pkgs.python3.withPackages(ps: [ packages.x86_64-linux.artiq ]); + }; nixConfig = { binaryCachePublicKeys = ["nixbld.m-labs.hk-1:5aSRVA5b320xbNvu30tqxVPXpld73bhtOeH6uAjRyHc="]; From 9adab6c817303730c5bcdf83b87a48b51ba80763 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 16 Aug 2021 16:38:55 +0800 Subject: [PATCH 091/238] flake: add devshell --- flake.lock | 34 ++++++++++++++++++++++++++ flake.nix | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 101 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index 88da8fb30..3ae9c5a3e 100644 --- a/flake.lock +++ b/flake.lock @@ -36,10 +36,44 @@ "inputs": { "mozilla-overlay": "mozilla-overlay", "nixpkgs": "nixpkgs", + "src-migen": "src-migen", + "src-misoc": "src-misoc", "src-pythonparser": "src-pythonparser", "src-sipyco": "src-sipyco" } }, + "src-migen": { + "flake": false, + "locked": { + "lastModified": 1628592379, + "narHash": "sha256-TQV6p0+Ri9HVge4qUKOCXe96cmcimNZ3R4sVwNY67DA=", + "owner": "m-labs", + "repo": "migen", + "rev": "27dbf03edd75c32dc1706e2a1316950c3a8d452a", + "type": "github" + }, + "original": { + "owner": "m-labs", + "repo": "migen", + "type": "github" + } + }, + "src-misoc": { + "flake": false, + "locked": { + "lastModified": 1628657477, + "narHash": "sha256-fHlyHvUJFDLZ62QfehcUqVNdQh5hfVXJ4Hq1bQE4oDE=", + "owner": "m-labs", + "repo": "misoc", + "rev": "e07538743427414d323225217f0737381ef27ec6", + "type": "github" + }, + "original": { + "owner": "m-labs", + "repo": "misoc", + "type": "github" + } + }, "src-pythonparser": { "flake": false, "locked": { diff --git a/flake.nix b/flake.nix index 4a3d55b40..29d0042dd 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,10 @@ inputs.src-sipyco = { url = github:m-labs/sipyco; flake = false; }; inputs.src-pythonparser = { url = github:m-labs/pythonparser; flake = false; }; - outputs = { self, nixpkgs, mozilla-overlay, src-sipyco, src-pythonparser }: + inputs.src-migen = { url = github:m-labs/migen; flake = false; }; + inputs.src-misoc = { url = github:m-labs/misoc; flake = false; }; + + outputs = { self, nixpkgs, mozilla-overlay, src-sipyco, src-pythonparser, src-migen, src-misoc }: let pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) ]; }; rustManifest = pkgs.fetchurl { @@ -82,6 +85,27 @@ ''; }; + llvmlite-new = pkgs.python3Packages.buildPythonPackage rec { + pname = "llvmlite"; + version = "0.37.0rc2"; + src = pkgs.python3Packages.fetchPypi { + inherit pname version; + sha256 = "sha256-F1quz+76JOt1jaQPVzdKe7RfN6gWG2lyE82qTvgyY/c="; + }; + nativeBuildInputs = [ pkgs.llvm_11 ]; + # Disable static linking + # https://github.com/numba/llvmlite/issues/93 + postPatch = '' + substituteInPlace ffi/Makefile.linux --replace "-static-libstdc++" "" + substituteInPlace llvmlite/tests/test_binding.py --replace "test_linux" "nope" + ''; + # Set directory containing llvm-config binary + preConfigure = '' + export LLVM_CONFIG=${pkgs.llvm_11.dev}/bin/llvm-config + ''; + doCheck = false; # FIXME + }; + artiq = pkgs.python3Packages.buildPythonPackage rec { pname = "artiq"; version = "7.0-dev"; @@ -91,8 +115,8 @@ nativeBuildInputs = [ pkgs.qt5.wrapQtAppsHook ]; # keep llvm_x and lld_x in sync with llvmlite - propagatedBuildInputs = [ pkgs.llvm_9 pkgs.lld_9 sipyco pythonparser ] - ++ (with pkgs.python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial python-Levenshtein h5py pyqt5 qasync llvmlite ]); + propagatedBuildInputs = [ pkgs.llvm_11 pkgs.lld_11 llvmlite-new sipyco pythonparser ] + ++ (with pkgs.python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial python-Levenshtein h5py pyqt5 qasync ]); dontWrapQtApps = true; postFixup = '' @@ -108,8 +132,8 @@ "--set FONTCONFIG_FILE ${pkgs.fontconfig.out}/etc/fonts/fonts.conf" ]; - # FIXME: automatically propagate lld_9 llvm_9 dependencies - checkInputs = [ pkgs.lld_9 pkgs.llvm_9 pkgs.lit outputcheck ]; + # FIXME: automatically propagate lld_11 llvm_11 dependencies + checkInputs = [ pkgs.lld_11 pkgs.llvm_11 pkgs.lit outputcheck ]; checkPhase = '' python -m unittest discover -v artiq.test @@ -119,9 +143,47 @@ #LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so lit -v $TESTDIR/lit ''; }; + + migen = pkgs.python3Packages.buildPythonPackage rec { + name = "migen"; + src = src-migen; + propagatedBuildInputs = [ pkgs.python3Packages.colorama ]; + }; + + asyncserial = pkgs.python3Packages.buildPythonPackage rec { + pname = "asyncserial"; + version = "0.1"; + src = pkgs.fetchFromGitHub { + owner = "m-labs"; + repo = "asyncserial"; + rev = "d95bc1d6c791b0e9785935d2f62f628eb5cdf98d"; + sha256 = "0yzkka9jk3612v8gx748x6ziwykq5lr7zmr9wzkcls0v2yilqx9k"; + }; + propagatedBuildInputs = [ pkgs.python3Packages.pyserial ]; + }; + + misoc = pkgs.python3Packages.buildPythonPackage { + name = "misoc"; + src = src-misoc; + doCheck = false; # TODO: fix misoc bitrot and re-enable tests + propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ]; + }; }; defaultPackage.x86_64-linux = pkgs.python3.withPackages(ps: [ packages.x86_64-linux.artiq ]); + + devShell.x86_64-linux = pkgs.mkShell { + name = "artiq-dev-shell"; + buildInputs = [ + (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ])) + rustPlatform.rust.rustc + rustPlatform.rust.cargo + pkgs.llvmPackages_11.clang-unwrapped + pkgs.llvm_11 + pkgs.lld_11 + ]; + TARGET_AR="llvm-ar"; + }; }; nixConfig = { From fc42d053d9b04dea54d2117f7c1ca958dbcc8f41 Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 17 Aug 2021 11:07:18 +0800 Subject: [PATCH 092/238] kernel: use vexriscv --- artiq/gateware/amp/kernel_cpu.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/artiq/gateware/amp/kernel_cpu.py b/artiq/gateware/amp/kernel_cpu.py index 9294cb353..a770b4326 100644 --- a/artiq/gateware/amp/kernel_cpu.py +++ b/artiq/gateware/amp/kernel_cpu.py @@ -1,7 +1,7 @@ from migen import * from misoc.interconnect.csr import * from misoc.interconnect import wishbone -from misoc.cores import mor1kx +from misoc.cores import vexriscv from misoc.integration.wb_slaves import WishboneSlaveManager @@ -23,9 +23,9 @@ class KernelCPU(Module): self.cd_sys_kernel.rst.eq(self._reset.storage) ] self.submodules.cpu = ClockDomainsRenamer("sys_kernel")( - mor1kx.MOR1KX( + vexriscv.VexRiscv( platform, - OPTION_RESET_PC=exec_address)) + exec_address)) # DRAM access self.wb_sdram = wishbone.Interface() From 1293e0750e6769b66a712c47275a3bd2a707125d Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 17 Aug 2021 11:42:04 +0800 Subject: [PATCH 093/238] ld, makefiles: use ld.lld --- artiq/firmware/bootloader/bootloader.ld | 20 +++++++++---------- artiq/firmware/ksupport/ksupport.ld | 8 ++++---- .../libboard_misoc/riscv32imac/vectors.S | 1 - artiq/firmware/runtime/Makefile | 4 ++-- artiq/firmware/runtime/runtime.ld | 14 ++++++++----- artiq/firmware/satman/satman.ld | 18 ++++++++++++++--- 6 files changed, 39 insertions(+), 26 deletions(-) diff --git a/artiq/firmware/bootloader/bootloader.ld b/artiq/firmware/bootloader/bootloader.ld index b52abe930..3837f3408 100644 --- a/artiq/firmware/bootloader/bootloader.ld +++ b/artiq/firmware/bootloader/bootloader.ld @@ -15,12 +15,10 @@ SECTIONS *(.text .text.*) } > rom - /* - * The compiler_builtins crate includes some GOTPC relocations, which require a GOT symbol, - * but don't actually need a GOT. This really ought to be fixed on rustc level, but I'm afraid - * it will add further complications to our build system that aren't pulling their weight. - */ - _GLOBAL_OFFSET_TABLE_ = .; + .eh_frame : + { + *(.eh_frame.*) + } > rom .rodata : { @@ -29,13 +27,13 @@ SECTIONS _end = .; } > rom - .crc ALIGN(4) : + .crc (NOLOAD) : ALIGN(4) { _crc = .; . += 4; - } + } > rom - .bss : + .bss (NOLOAD) : { _fbss = .; *(.sbss .sbss.* .bss .bss.*); @@ -43,11 +41,11 @@ SECTIONS _ebss = .; } > sram - .stack : + .stack (NOLOAD) : ALIGN(16) { /* Ensure we have a certain amount of space available for stack. */ /*. = ORIGIN(sram) + LENGTH(sram) - 0x1a00; */ - . = ORIGIN(sram) + LENGTH(sram) - 4; + . = ORIGIN(sram) + LENGTH(sram) - 16; _fstack = .; } > sram } diff --git a/artiq/firmware/ksupport/ksupport.ld b/artiq/firmware/ksupport/ksupport.ld index b139833f3..62fbd3518 100644 --- a/artiq/firmware/ksupport/ksupport.ld +++ b/artiq/firmware/ksupport/ksupport.ld @@ -15,7 +15,7 @@ MEMORY { } /* Kernel stack is at the end of main RAM. */ -_fstack = ORIGIN(main_ram) + LENGTH(main_ram) - 4; +_fstack = ORIGIN(main_ram) + LENGTH(main_ram) - 16; /* Force ld to make the ELF header as loadable. */ PHDRS @@ -53,19 +53,19 @@ SECTIONS .eh_frame : { KEEP(*(.eh_frame)) - } :text + } > ksupport :text .eh_frame_hdr : { KEEP(*(.eh_frame_hdr)) - } :text :eh_frame + } > ksupport :text :eh_frame .data : { *(.data .data.*) } - .bss : + .bss (NOLOAD) : { _fbss = .; *(.bss .bss.*) diff --git a/artiq/firmware/libboard_misoc/riscv32imac/vectors.S b/artiq/firmware/libboard_misoc/riscv32imac/vectors.S index a571a4903..19b6c5c3f 100644 --- a/artiq/firmware/libboard_misoc/riscv32imac/vectors.S +++ b/artiq/firmware/libboard_misoc/riscv32imac/vectors.S @@ -128,7 +128,6 @@ _abs_start: Saves caller saved registers ra, t0..6, a0..7, calls exception, restores caller saved registers and then returns. */ -.section .trap, "ax" .global _start_trap /* Make it .weak so PAC/HAL can provide their own if needed. */ .weak _start_trap diff --git a/artiq/firmware/runtime/Makefile b/artiq/firmware/runtime/Makefile index 2b98acc43..766804e68 100644 --- a/artiq/firmware/runtime/Makefile +++ b/artiq/firmware/runtime/Makefile @@ -18,10 +18,10 @@ $(RUSTOUT)/libruntime.a: runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o $(link) -T $(RUNTIME_DIRECTORY)/runtime.ld \ - -lunwind-bare + -lunwind-bare -m elf32lriscv ksupport_data.o: ../ksupport/ksupport.elf - $(LD) -m elf32lriscv -b binary -o $@ $< + $(LD) -r -m elf32lriscv -b binary -o $@ $< %.bin: %.elf $(objcopy) -O binary diff --git a/artiq/firmware/runtime/runtime.ld b/artiq/firmware/runtime/runtime.ld index c93a5e4b1..57d76ee45 100644 --- a/artiq/firmware/runtime/runtime.ld +++ b/artiq/firmware/runtime/runtime.ld @@ -36,10 +36,14 @@ SECTIONS __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; + .gcc_except_table : + { + *(.gcc_except_table) + } > runtime + /* https://sourceware.org/bugzilla/show_bug.cgi?id=20475 */ .got : { - _GLOBAL_OFFSET_TABLE_ = .; *(.got) } > runtime @@ -58,20 +62,20 @@ SECTIONS *(.data .data.*) } > runtime - .bss ALIGN(4) : + .bss (NOLOAD) : ALIGN(4) { _fbss = .; *(.sbss .sbss.* .bss .bss.*); _ebss = .; } > runtime - .stack : + .stack (NOLOAD) : ALIGN(16) { . += 0x4000; - _fstack = . - 4; + _fstack = . - 16; } > runtime - .heap : + .heap (NOLOAD) : { _fheap = .; . = ORIGIN(runtime) + LENGTH(runtime); diff --git a/artiq/firmware/satman/satman.ld b/artiq/firmware/satman/satman.ld index 927af6022..bf7ef51d0 100644 --- a/artiq/firmware/satman/satman.ld +++ b/artiq/firmware/satman/satman.ld @@ -14,6 +14,13 @@ SECTIONS *(.text .text.*) } > main_ram + .eh_frame : + { + __eh_frame_start = .; + KEEP(*(.eh_frame)) + __eh_frame_end = .; + } > main_ram + /* https://sourceware.org/bugzilla/show_bug.cgi?id=20475 */ .got : { @@ -38,7 +45,12 @@ SECTIONS *(.data .data.*) } > main_ram - .bss ALIGN(4) : + .sdata : + { + *(.sdata .sdata.*) + } > main_ram + + .bss (NOLOAD) : ALIGN(4) { _fbss = .; *(.sbss .sbss.* .bss .bss.*); @@ -46,10 +58,10 @@ SECTIONS _ebss = .; } > main_ram - .stack : + .stack (NOLOAD) : ALIGN(16) { _estack = .; . += 0x10000; - _fstack = . - 4; + _fstack = . - 16; } > main_ram } From f77b607b56b5d63e100e338d4d9519c07b81a9f5 Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 17 Aug 2021 11:44:05 +0800 Subject: [PATCH 094/238] compiler: generate symbols --- MANIFEST.in | 1 + artiq/compiler/kernel.ld | 9 +++++++++ artiq/compiler/targets.py | 5 +++-- 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 artiq/compiler/kernel.ld diff --git a/MANIFEST.in b/MANIFEST.in index 52fac08ba..27aa85a93 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,3 +4,4 @@ include artiq/gui/logo*.svg include versioneer.py include artiq/_version.py include artiq/coredevice/coredevice_generic.schema.json +include artiq/compiler/kernel.ld diff --git a/artiq/compiler/kernel.ld b/artiq/compiler/kernel.ld new file mode 100644 index 000000000..4147026a2 --- /dev/null +++ b/artiq/compiler/kernel.ld @@ -0,0 +1,9 @@ +SECTIONS { + .bss ALIGN(4) : + { + __bss_start = .; + *(.sbss .sbss.* .bss .bss.*); + . = ALIGN(4); + _end = .; + } +} \ No newline at end of file diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index b6e33e8ca..0c6ee3ee4 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -182,6 +182,7 @@ class Target: def link(self, objects): """Link the relocatable objects into a shared library for this target.""" with RunTool([self.tool_ld, "-shared", "--eh-frame-hdr"] + + ["-T" + os.path.join(os.path.dirname(__file__), "kernel.ld")] + ["{{obj{}}}".format(index) for index in range(len(objects))] + ["-x"] + ["-o", "{output}"], @@ -258,9 +259,9 @@ class NativeTarget(Target): class RISCVTarget(Target): triple = "riscv32-unknown-linux" data_layout = "e-m:e-p:32:32-i64:64-n32-S128" - features = [] + features = ["m", "a"] print_function = "core_log" - little_endian = False + little_endian = True now_pinning = True tool_ld = "ld.lld" From 01e357e5d3c1f31caa5269ccf57688646fded46d Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 17 Aug 2021 11:45:32 +0800 Subject: [PATCH 095/238] ksupport.ld: reduce load section alignment --- artiq/firmware/ksupport/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/artiq/firmware/ksupport/Makefile b/artiq/firmware/ksupport/Makefile index 297bad7bd..cfb79b3d6 100644 --- a/artiq/firmware/ksupport/Makefile +++ b/artiq/firmware/ksupport/Makefile @@ -7,6 +7,7 @@ CFLAGS += \ -I$(MISOC_DIRECTORY)/software/include/dyld LDFLAGS += --eh-frame-hdr \ + --nmagic \ -L../libm \ -L../libprintf \ -L../libunwind From 36171f2c61e868c1a4af451f218329f2bce3d337 Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 17 Aug 2021 11:46:33 +0800 Subject: [PATCH 096/238] runtime: remove inaccurate sp on panic --- artiq/firmware/runtime/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index df1f2874e..b6d33cf00 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -290,7 +290,6 @@ pub extern fn exception(regs: *const TrapFrame) { info!("Called interrupt with {:?}", source); }, mcause::Trap::Exception(e) => { - println!("Stack pointer: {:p}", regs); println!("Trap frame: {:x?}", unsafe { *regs }); fn hexdump(addr: u32) { From 01ca114c66b885f0f00fd70ac0d6436ed72cfac2 Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 17 Aug 2021 11:46:49 +0800 Subject: [PATCH 097/238] runtime: remove irq dependency --- artiq/firmware/runtime/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index b6d33cf00..1aa92576e 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -30,7 +30,7 @@ use core::cell::RefCell; use core::convert::TryFrom; use smoltcp::wire::IpCidr; -use board_misoc::{csr, irq, ident, clock, spiflash, config, net_settings}; +use board_misoc::{csr, ident, clock, spiflash, config, net_settings}; #[cfg(has_ethmac)] use board_misoc::ethmac; #[cfg(has_drtio)] From 7542105f0f8071c4b12e1682b6b5563284bdbc29 Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 17 Aug 2021 11:49:07 +0800 Subject: [PATCH 098/238] board_misoc: remove pcr VexRiscv seems to not support additional hardware performance counter, at least I have not seen any documentation on how to use it. --- artiq/firmware/ksupport/api.rs | 3 --- artiq/firmware/libboard_artiq/lib.rs | 2 -- 2 files changed, 5 deletions(-) diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index 84e69dad5..7b219562c 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -131,9 +131,6 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(cache_get = ::cache_get), api!(cache_put = ::cache_put), - api!(mfspr = ::board_misoc::spr::mfspr), - api!(mtspr = ::board_misoc::spr::mtspr), - /* direct syscalls */ api!(rtio_init = ::rtio::init), api!(rtio_get_destination_status = ::rtio::get_destination_status), diff --git a/artiq/firmware/libboard_artiq/lib.rs b/artiq/firmware/libboard_artiq/lib.rs index 448b10f9e..1550db7dd 100644 --- a/artiq/firmware/libboard_artiq/lib.rs +++ b/artiq/firmware/libboard_artiq/lib.rs @@ -15,8 +15,6 @@ extern crate io; extern crate board_misoc; extern crate proto_artiq; -pub mod pcr; - pub mod spi; #[cfg(has_kernel_cpu)] From 3d629006dfeea9f62cfe85b53bde53b0b2f2be70 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 18 Aug 2021 12:09:49 +0800 Subject: [PATCH 099/238] makefiles: revert byte-swaps --- artiq/firmware/bootloader/Makefile | 1 - artiq/firmware/runtime/Makefile | 1 - artiq/firmware/satman/Makefile | 1 - 3 files changed, 3 deletions(-) diff --git a/artiq/firmware/bootloader/Makefile b/artiq/firmware/bootloader/Makefile index d5a34f5ba..482aa3291 100644 --- a/artiq/firmware/bootloader/Makefile +++ b/artiq/firmware/bootloader/Makefile @@ -15,4 +15,3 @@ bootloader.elf: $(RUSTOUT)/libbootloader.a %.bin: %.elf $(objcopy) -O binary $(MSCIMG) $@ --little - objcopy -I binary -O binary --reverse-bytes=4 $@ diff --git a/artiq/firmware/runtime/Makefile b/artiq/firmware/runtime/Makefile index 766804e68..24ac19741 100644 --- a/artiq/firmware/runtime/Makefile +++ b/artiq/firmware/runtime/Makefile @@ -28,4 +28,3 @@ ksupport_data.o: ../ksupport/ksupport.elf %.fbi: %.bin $(mscimg) -f --little - objcopy -I binary -O binary --reverse-bytes=4 $@ diff --git a/artiq/firmware/satman/Makefile b/artiq/firmware/satman/Makefile index 3d6974cf1..59f0f78f6 100644 --- a/artiq/firmware/satman/Makefile +++ b/artiq/firmware/satman/Makefile @@ -19,4 +19,3 @@ satman.elf: $(RUSTOUT)/libsatman.a %.fbi: %.bin $(mscimg) -f --little - objcopy -I binary -O binary --reverse-bytes=4 $@ From 942bd1a95d7302bd850a30ec6d4164d5807828a9 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 18 Aug 2021 14:48:10 +0800 Subject: [PATCH 100/238] flake: add hydraJobs --- flake.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flake.nix b/flake.nix index 29d0042dd..4c031cf7b 100644 --- a/flake.nix +++ b/flake.nix @@ -184,6 +184,10 @@ ]; TARGET_AR="llvm-ar"; }; + + hydraJobs = { + artiq = packages.x86_64-linux.artiq; + }; }; nixConfig = { From 1ba8c8dfee69a1600438e34bb86299d098fd18a2 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 20 Aug 2021 15:59:57 +0800 Subject: [PATCH 101/238] runtime: remove irq again --- artiq/firmware/runtime/main.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 1aa92576e..17e4c0a42 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -89,8 +89,6 @@ fn setup_log_levels() { } fn startup() { - irq::set_mask(0); - irq::set_ie(true); clock::init(); info!("ARTIQ runtime starting..."); info!("software ident {}", csr::CONFIG_IDENTIFIER_STR); From 279593f98473bc22935f14db695bed9f3ec4035f Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 20 Aug 2021 16:01:24 +0800 Subject: [PATCH 102/238] ksupport.ld: merge sbss with bss --- artiq/firmware/ksupport/ksupport.ld | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/ksupport/ksupport.ld b/artiq/firmware/ksupport/ksupport.ld index 62fbd3518..23e84a781 100644 --- a/artiq/firmware/ksupport/ksupport.ld +++ b/artiq/firmware/ksupport/ksupport.ld @@ -65,10 +65,10 @@ SECTIONS *(.data .data.*) } - .bss (NOLOAD) : + .bss (NOLOAD) : ALIGN(4) { _fbss = .; - *(.bss .bss.*) + *(.sbss .sbss.* .bss .bss.*); . = ALIGN(4); _ebss = .; } From b30ed75e694d951f530342bb44fe8911001cbb81 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 20 Aug 2021 16:03:21 +0800 Subject: [PATCH 103/238] kernel.ld: load elf header and prog headers ld.lld has a habit of not putting the headers under any load sections. However, the headers are needed by libunwind to handle exception raised by the kernel. Creating PT_LOAD section with FILEHDR and PHDRS solves this issue. Other PHDRS are also specified as linkers (not limited to ld.lld) will not create additional unspecified headers even when necessary. --- artiq/compiler/kernel.ld | 62 ++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/artiq/compiler/kernel.ld b/artiq/compiler/kernel.ld index 4147026a2..6523d631a 100644 --- a/artiq/compiler/kernel.ld +++ b/artiq/compiler/kernel.ld @@ -1,9 +1,53 @@ -SECTIONS { - .bss ALIGN(4) : - { - __bss_start = .; - *(.sbss .sbss.* .bss .bss.*); - . = ALIGN(4); - _end = .; - } -} \ No newline at end of file +/* Force ld to make the ELF header as loadable. */ +PHDRS +{ + headers PT_LOAD FILEHDR PHDRS ; + text PT_LOAD ; + data PT_LOAD ; + dynamic PT_DYNAMIC ; + eh_frame PT_GNU_EH_FRAME ; +} + +SECTIONS +{ + /* Push back .text section enough so that ld.lld not complain */ + . = SIZEOF_HEADERS; + + .text : + { + *(.text .text.*) + } : text + + .rodata : + { + *(.rodata .rodata.*) + } + + .eh_frame : + { + KEEP(*(.eh_frame)) + } : text + + .eh_frame_hdr : + { + KEEP(*(.eh_frame_hdr)) + } : text : eh_frame + + .data : + { + *(.data) + } : data + + .dynamic : + { + *(.dynamic) + } : data : dynamic + + .bss (NOLOAD) : ALIGN(4) + { + __bss_start = .; + *(.sbss .sbss.* .bss .bss.*); + . = ALIGN(4); + _end = .; + } +} From 29a2f106d1554bac4af89b7697d736e7b5a362a7 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 20 Aug 2021 16:14:33 +0800 Subject: [PATCH 104/238] ksupport: replace asm with llvm_asm --- artiq/firmware/ksupport/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index bbbea4c02..13f9d0518 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -1,4 +1,4 @@ -#![feature(lang_items, asm, panic_unwind, libc, unwind_attributes, +#![feature(lang_items, llvm_asm, panic_unwind, libc, unwind_attributes, panic_handler, panic_info_message, nll)] #![no_std] From 9afe63c08a4722eaa8ee31920420e6a9a530f8ce Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 23 Aug 2021 11:29:18 +0800 Subject: [PATCH 105/238] ksupport: fix proto_artiq dependency --- artiq/firmware/ksupport/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/artiq/firmware/ksupport/Cargo.toml b/artiq/firmware/ksupport/Cargo.toml index 5556eb15e..a3c038f2e 100644 --- a/artiq/firmware/ksupport/Cargo.toml +++ b/artiq/firmware/ksupport/Cargo.toml @@ -19,6 +19,7 @@ io = { path = "../libio", features = ["byteorder"] } dyld = { path = "../libdyld" } board_misoc = { path = "../libboard_misoc" } board_artiq = { path = "../libboard_artiq" } +proto_artiq = { path = "../libproto_artiq" } riscv = { version = "0.6.0", features = ["inline-asm"] } libc = { path = "../libc" } unwind = { path = "../libunwind" } From de0f2d4a28a940c5c38ddb52b906b42496b3eefe Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 24 Aug 2021 16:56:05 +0800 Subject: [PATCH 106/238] firmware: adopt endianness protocol in artiq-zynq Related: artiq-zynq: https://git.m-labs.hk/M-Labs/artiq-zynq/pulls/126 artiq: #1588 --- artiq/firmware/libio/proto.rs | 20 ++++++++++---------- artiq/firmware/libproto_artiq/rpc_proto.rs | 18 +++++++++--------- artiq/firmware/runtime/analyzer.rs | 2 +- artiq/firmware/runtime/mgmt.rs | 2 +- artiq/firmware/runtime/moninj.rs | 2 +- artiq/firmware/runtime/session.rs | 6 +++--- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/artiq/firmware/libio/proto.rs b/artiq/firmware/libio/proto.rs index 88b010e71..377a51383 100644 --- a/artiq/firmware/libio/proto.rs +++ b/artiq/firmware/libio/proto.rs @@ -1,6 +1,6 @@ #[cfg(feature = "alloc")] use {core::str::Utf8Error, alloc::string::String}; -use byteorder::{ByteOrder, NetworkEndian}; +use byteorder::{ByteOrder, NativeEndian}; use ::{Read, Write, Error as IoError}; @@ -29,21 +29,21 @@ pub trait ProtoRead { fn read_u16(&mut self) -> Result { let mut bytes = [0; 2]; self.read_exact(&mut bytes)?; - Ok(NetworkEndian::read_u16(&bytes)) + Ok(NativeEndian::read_u16(&bytes)) } #[inline] fn read_u32(&mut self) -> Result { let mut bytes = [0; 4]; self.read_exact(&mut bytes)?; - Ok(NetworkEndian::read_u32(&bytes)) + Ok(NativeEndian::read_u32(&bytes)) } #[inline] fn read_u64(&mut self) -> Result { let mut bytes = [0; 8]; self.read_exact(&mut bytes)?; - Ok(NetworkEndian::read_u64(&bytes)) + Ok(NativeEndian::read_u64(&bytes)) } #[inline] @@ -88,42 +88,42 @@ pub trait ProtoWrite { #[inline] fn write_u16(&mut self, value: u16) -> Result<(), Self::WriteError> { let mut bytes = [0; 2]; - NetworkEndian::write_u16(&mut bytes, value); + NativeEndian::write_u16(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_i16(&mut self, value: i16) -> Result<(), Self::WriteError> { let mut bytes = [0; 2]; - NetworkEndian::write_i16(&mut bytes, value); + NativeEndian::write_i16(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_u32(&mut self, value: u32) -> Result<(), Self::WriteError> { let mut bytes = [0; 4]; - NetworkEndian::write_u32(&mut bytes, value); + NativeEndian::write_u32(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_i32(&mut self, value: i32) -> Result<(), Self::WriteError> { let mut bytes = [0; 4]; - NetworkEndian::write_i32(&mut bytes, value); + NativeEndian::write_i32(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_u64(&mut self, value: u64) -> Result<(), Self::WriteError> { let mut bytes = [0; 8]; - NetworkEndian::write_u64(&mut bytes, value); + NativeEndian::write_u64(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_i64(&mut self, value: i64) -> Result<(), Self::WriteError> { let mut bytes = [0; 8]; - NetworkEndian::write_i64(&mut bytes, value); + NativeEndian::write_i64(&mut bytes, value); self.write_all(&bytes) } diff --git a/artiq/firmware/libproto_artiq/rpc_proto.rs b/artiq/firmware/libproto_artiq/rpc_proto.rs index afc98e101..5e7b12010 100644 --- a/artiq/firmware/libproto_artiq/rpc_proto.rs +++ b/artiq/firmware/libproto_artiq/rpc_proto.rs @@ -1,7 +1,7 @@ use core::str; use core::slice; use cslice::{CSlice, CMutSlice}; -use byteorder::{NetworkEndian, ByteOrder}; +use byteorder::{NativeEndian, ByteOrder}; use io::{ProtoRead, Read, Write, ProtoWrite, Error}; use self::tag::{Tag, TagIterator, split_tag}; @@ -69,13 +69,13 @@ unsafe fn recv_value(reader: &mut R, tag: Tag, data: &mut *mut (), let dest = slice::from_raw_parts_mut(data as *mut u8, length * 4); reader.read_exact(dest)?; let dest = slice::from_raw_parts_mut(data as *mut i32, length); - NetworkEndian::from_slice_i32(dest); + NativeEndian::from_slice_i32(dest); }, Tag::Int64 | Tag::Float64 => { let dest = slice::from_raw_parts_mut(data as *mut u8, length * 8); reader.read_exact(dest)?; let dest = slice::from_raw_parts_mut(data as *mut i64, length); - NetworkEndian::from_slice_i64(dest); + NativeEndian::from_slice_i64(dest); }, _ => { for _ in 0..length { @@ -109,13 +109,13 @@ unsafe fn recv_value(reader: &mut R, tag: Tag, data: &mut *mut (), let dest = slice::from_raw_parts_mut(data as *mut u8, length * 4); reader.read_exact(dest)?; let dest = slice::from_raw_parts_mut(data as *mut i32, length); - NetworkEndian::from_slice_i32(dest); + NativeEndian::from_slice_i32(dest); }, Tag::Int64 | Tag::Float64 => { let dest = slice::from_raw_parts_mut(data as *mut u8, length * 8); reader.read_exact(dest)?; let dest = slice::from_raw_parts_mut(data as *mut i64, length); - NetworkEndian::from_slice_i64(dest); + NativeEndian::from_slice_i64(dest); }, _ => { for _ in 0..length { @@ -204,8 +204,8 @@ unsafe fn send_value(writer: &mut W, tag: Tag, data: &mut *const ()) let mut data = (*ptr).elements; writer.write_u8(tag.as_u8())?; match tag { - // we cannot use NetworkEndian::from_slice_i32 as the data is not mutable, - // and that is not needed as the data is already in network endian + // we cannot use NativeEndian::from_slice_i32 as the data is not mutable, + // and that is not needed as the data is already in native endian Tag::Bool => { let slice = slice::from_raw_parts(data as *const u8, length); writer.write_all(slice)?; @@ -243,8 +243,8 @@ unsafe fn send_value(writer: &mut W, tag: Tag, data: &mut *const ()) let mut data = *buffer; writer.write_u8(elt_tag.as_u8())?; match elt_tag { - // we cannot use NetworkEndian::from_slice_i32 as the data is not mutable, - // and that is not needed as the data is already in network endian + // we cannot use NativeEndian::from_slice_i32 as the data is not mutable, + // and that is not needed as the data is already in native endian Tag::Bool => { let slice = slice::from_raw_parts(data as *const u8, length); writer.write_all(slice)?; diff --git a/artiq/firmware/runtime/analyzer.rs b/artiq/firmware/runtime/analyzer.rs index 23abdba41..2e9d74c14 100644 --- a/artiq/firmware/runtime/analyzer.rs +++ b/artiq/firmware/runtime/analyzer.rs @@ -51,7 +51,7 @@ fn worker(stream: &mut TcpStream) -> Result<(), IoError> { }; debug!("{:?}", header); - stream.write_all("E".as_bytes())?; + stream.write_all("e".as_bytes())?; header.write_to(stream)?; if wraparound { stream.write_all(&data[pointer..])?; diff --git a/artiq/firmware/runtime/mgmt.rs b/artiq/firmware/runtime/mgmt.rs index 1073cb4fe..c100df05f 100644 --- a/artiq/firmware/runtime/mgmt.rs +++ b/artiq/firmware/runtime/mgmt.rs @@ -14,7 +14,7 @@ impl From for Error { fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error> { read_magic(stream)?; - Write::write_all(stream, "E".as_bytes())?; + Write::write_all(stream, "e".as_bytes())?; info!("new connection from {}", stream.remote_endpoint()); loop { diff --git a/artiq/firmware/runtime/moninj.rs b/artiq/firmware/runtime/moninj.rs index 44a138bc0..c1bba04fc 100644 --- a/artiq/firmware/runtime/moninj.rs +++ b/artiq/firmware/runtime/moninj.rs @@ -123,7 +123,7 @@ fn connection_worker(io: &Io, _aux_mutex: &Mutex, _routing_table: &drtio_routing let mut next_check = 0; read_magic(&mut stream)?; - stream.write_all("E".as_bytes())?; + stream.write_all("e".as_bytes())?; info!("new connection from {}", stream.remote_endpoint()); loop { diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index bae438969..7d0935667 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -1,6 +1,6 @@ use core::{mem, str, cell::{Cell, RefCell}, fmt::Write as FmtWrite}; use alloc::{vec::Vec, string::String}; -use byteorder::{ByteOrder, NetworkEndian}; +use byteorder::{ByteOrder, NativeEndian}; use io::{Read, Write, Error as IoError}; use board_misoc::{ident, cache, config}; @@ -473,7 +473,7 @@ fn process_kern_queued_rpc(stream: &mut TcpStream, _session: &mut Session) -> Result<(), Error> { rpc_queue::dequeue(|slice| { debug!("comm<-kern (async RPC)"); - let length = NetworkEndian::read_u32(slice) as usize; + let length = NativeEndian::read_u32(slice) as usize; host_write(stream, host::Reply::RpcRequest { async: true })?; debug!("{:?}", &slice[4..][..length]); stream.write_all(&slice[4..][..length])?; @@ -615,7 +615,7 @@ pub fn thread(io: Io, aux_mutex: &Mutex, continue } } - match stream.write_all("E".as_bytes()) { + match stream.write_all("e".as_bytes()) { Ok(()) => (), Err(_) => { warn!("cannot send endian byte"); From 8fa47b811996eae8d04729856b4be9aa5c8fcda4 Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 24 Aug 2021 17:00:28 +0800 Subject: [PATCH 107/238] rpc: enforce alignment --- artiq/firmware/libproto_artiq/rpc_proto.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/libproto_artiq/rpc_proto.rs b/artiq/firmware/libproto_artiq/rpc_proto.rs index 5e7b12010..bff4d46b0 100644 --- a/artiq/firmware/libproto_artiq/rpc_proto.rs +++ b/artiq/firmware/libproto_artiq/rpc_proto.rs @@ -5,6 +5,18 @@ use byteorder::{NativeEndian, ByteOrder}; use io::{ProtoRead, Read, Write, ProtoWrite, Error}; use self::tag::{Tag, TagIterator, split_tag}; +unsafe fn align_ptr(ptr: *const ()) -> *const T { + let alignment = core::mem::align_of::() as isize; + let fix = (alignment - (ptr as isize) % alignment) % alignment; + ((ptr as isize) + fix) as *const T +} + +unsafe fn align_ptr_mut(ptr: *mut ()) -> *mut T { + let alignment = core::mem::align_of::() as isize; + let fix = (alignment - (ptr as isize) % alignment) % alignment; + ((ptr as isize) + fix) as *mut T +} + unsafe fn recv_value(reader: &mut R, tag: Tag, data: &mut *mut (), alloc: &Fn(usize) -> Result<*mut (), E>) -> Result<(), E> @@ -13,7 +25,7 @@ unsafe fn recv_value(reader: &mut R, tag: Tag, data: &mut *mut (), { macro_rules! consume_value { ($ty:ty, |$ptr:ident| $map:expr) => ({ - let $ptr = (*data) as *mut $ty; + let $ptr = align_ptr_mut::<$ty>(*data) as *mut $ty; *data = $ptr.offset(1) as *mut (); $map }) @@ -161,7 +173,7 @@ unsafe fn send_value(writer: &mut W, tag: Tag, data: &mut *const ()) { macro_rules! consume_value { ($ty:ty, |$ptr:ident| $map:expr) => ({ - let $ptr = (*data) as *const $ty; + let $ptr = align_ptr::<$ty>(*data); *data = $ptr.offset(1) as *const (); $map }) From d623acc29d0276e9748f7faf923d38e2f94f069d Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 24 Aug 2021 17:08:34 +0800 Subject: [PATCH 108/238] llvm_ir_gen: fix now with now_pinning & little-endian target --- artiq/compiler/transforms/llvm_ir_generator.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 7d7ca6344..149d45f4a 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1103,6 +1103,14 @@ class LLVMIRGenerator: return self.map(insn.operands[0]) elif insn.op == "now_mu": if self.target.now_pinning: + # Word swap now.old for little endian target + # Most significant word is stored in lower address (see generated csr.rs) + if self.target.little_endian: + llnow_raw = self.llbuilder.load(self.llbuiltin("now"), name=insn.name) + llnow_lo = self.llbuilder.shl(llnow_raw, ll.Constant(lli64, 32)) + llnow_hi = self.llbuilder.lshr(llnow_raw, ll.Constant(lli64, 32)) + return self.llbuilder.or_(llnow_lo, llnow_hi) + else: return self.llbuilder.load(self.llbuiltin("now"), name=insn.name) else: return self.llbuilder.call(self.llbuiltin("now_mu"), []) @@ -1114,8 +1122,6 @@ class LLVMIRGenerator: lltime_lo = self.llbuilder.trunc(lltime, lli32) llnow_hiptr = self.llbuilder.bitcast(self.llbuiltin("now"), lli32.as_pointer()) llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(1)]) - if self.target.little_endian: - lltime_hi, lltime_lo = lltime_lo, lltime_hi llstore_hi = self.llbuilder.store_atomic(lltime_hi, llnow_hiptr, ordering="seq_cst", align=4) llstore_lo = self.llbuilder.store_atomic(lltime_lo, llnow_loptr, ordering="seq_cst", align=4) return llstore_lo @@ -1127,13 +1133,17 @@ class LLVMIRGenerator: if self.target.now_pinning: llnowptr = self.llbuiltin("now") llnow = self.llbuilder.load(llnowptr, name="now.old") + # Word swap now.old for little endian target + # Most significant word is stored in lower address (see generated csr.rs) + if self.target.little_endian: + llnow_lo = self.llbuilder.shl(llnow, ll.Constant(lli64, 32)) + llnow_hi = self.llbuilder.lshr(llnow, ll.Constant(lli64, 32)) + llnow = self.llbuilder.or_(llnow_lo, llnow_hi) lladjusted = self.llbuilder.add(llnow, llinterval, name="now.new") lladjusted_hi = self.llbuilder.trunc(self.llbuilder.lshr(lladjusted, ll.Constant(lli64, 32)), lli32) lladjusted_lo = self.llbuilder.trunc(lladjusted, lli32) llnow_hiptr = self.llbuilder.bitcast(llnowptr, lli32.as_pointer()) llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(1)]) - if self.target.little_endian: - lladjusted_hi, lladjusted_lo = lladjusted_lo, lladjusted_hi llstore_hi = self.llbuilder.store_atomic(lladjusted_hi, llnow_hiptr, ordering="seq_cst", align=4) llstore_lo = self.llbuilder.store_atomic(lladjusted_lo, llnow_loptr, ordering="seq_cst", align=4) return llstore_lo From a833974b5067d66ab9fdf61fb928ac3f4e8ba991 Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 24 Aug 2021 17:11:24 +0800 Subject: [PATCH 109/238] analyzer: fix endianness --- artiq/gateware/rtio/analyzer.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/artiq/gateware/rtio/analyzer.py b/artiq/gateware/rtio/analyzer.py index 342da2acf..1818d3c43 100644 --- a/artiq/gateware/rtio/analyzer.py +++ b/artiq/gateware/rtio/analyzer.py @@ -42,6 +42,20 @@ assert layout_len(exception_layout) == message_len assert layout_len(stopped_layout) == message_len +def convert_signal(signal): + assert len(signal) % 8 == 0 + nbytes = len(signal)//8 + assert nbytes % 4 == 0 + nwords = nbytes//4 + signal_words = [] + for i in range(nwords): + signal_bytes = [] + for j in range(4): + signal_bytes.append(signal[8*(j+i*4):8*((j+i*4)+1)]) + signal_words.extend(reversed(signal_bytes)) + return Cat(*signal_words) + + class MessageEncoder(Module, AutoCSR): def __init__(self, tsc, cri, enable): self.source = stream.Endpoint([("data", message_len)]) @@ -161,7 +175,7 @@ class DMAWriter(Module, AutoCSR): membus.stb.eq(self.sink.stb), self.sink.ack.eq(membus.ack), membus.we.eq(1), - membus.dat_w.eq(self.sink.data) + membus.dat_w.eq(convert_signal(self.sink.data)) ] if messages_per_dw > 1: for i in range(dw//8): From af263ffe1fa5fcc94e4a55a068ce525de720724e Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 24 Aug 2021 17:15:16 +0800 Subject: [PATCH 110/238] ksupport: fix rpc, cache signature (FFI) The reason of the borrow stuff is explained in https://git.m-labs.hk/M-Labs/artiq-zynq/issues/76 (artiq-zyna repo). As for `cache_get()`, compiler will perform stack allocation to pre-allocate the returned structure, and pass to cache_get alongside the `key`. However, ksupport fails to recognize the passed memory, so it will always assume the passed memory as the key. --- artiq/firmware/ksupport/lib.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 13f9d0518..cf030b3a7 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -122,7 +122,7 @@ pub extern fn send_to_rtio_log(text: CSlice) { } #[unwind(aborts)] -extern fn rpc_send(service: u32, tag: CSlice, data: *const *const ()) { +extern fn rpc_send(service: u32, tag: &CSlice, data: *const *const ()) { while !rpc_queue::empty() {} send(&RpcSend { async: false, @@ -133,7 +133,7 @@ extern fn rpc_send(service: u32, tag: CSlice, data: *const *const ()) { } #[unwind(aborts)] -extern fn rpc_send_async(service: u32, tag: CSlice, data: *const *const ()) { +extern fn rpc_send_async(service: u32, tag: &CSlice, data: *const *const ()) { while rpc_queue::full() {} rpc_queue::enqueue(|mut slice| { let length = { @@ -203,15 +203,20 @@ fn terminate(exception: &eh_artiq::Exception, backtrace: &mut [usize]) -> ! { } #[unwind(aborts)] -extern fn cache_get(key: CSlice) -> CSlice<'static, i32> { - send(&CacheGetRequest { - key: str::from_utf8(key.as_ref()).unwrap() - }); - recv!(&CacheGetReply { value } => value.as_c_slice()) +extern fn cache_get<'a>(ret: &'a mut CSlice, key: &CSlice) -> &'a CSlice<'a, i32> { + unsafe { + send(&CacheGetRequest { + key: str::from_utf8(key.as_ref()).unwrap() + }); + recv!(&CacheGetReply { value } => { + *ret = value.as_c_slice(); + ret + }) + } } #[unwind(allowed)] -extern fn cache_put(key: CSlice, list: CSlice) { +extern fn cache_put(key: &CSlice, list: &CSlice) { send(&CachePutRequest { key: str::from_utf8(key.as_ref()).unwrap(), value: list.as_ref() @@ -456,7 +461,7 @@ unsafe fn attribute_writeback(typeinfo: *const ()) { attributes = attributes.offset(1); if (*attribute).tag.len() > 0 { - rpc_send_async(0, (*attribute).tag, [ + rpc_send_async(0, &(*attribute).tag, [ &object as *const _ as *const (), &(*attribute).name as *const _ as *const (), (object as usize + (*attribute).offset) as *const () From 61b0170a12351c1320a3b8831cb69293c5f5d495 Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 24 Aug 2021 17:43:36 +0800 Subject: [PATCH 111/238] firmware: purge or1k --- artiq/firmware/libboard_misoc/lib.rs | 4 - artiq/firmware/libboard_misoc/or1k/boot.rs | 11 - artiq/firmware/libboard_misoc/or1k/cache.rs | 49 --- artiq/firmware/libboard_misoc/or1k/irq.rs | 107 ----- artiq/firmware/libboard_misoc/or1k/mod.rs | 4 - artiq/firmware/libboard_misoc/or1k/spr.rs | 231 ----------- artiq/firmware/libboard_misoc/or1k/vectors.S | 413 ------------------- artiq/firmware/libdyld/lib.rs | 18 +- 8 files changed, 2 insertions(+), 835 deletions(-) delete mode 100644 artiq/firmware/libboard_misoc/or1k/boot.rs delete mode 100644 artiq/firmware/libboard_misoc/or1k/cache.rs delete mode 100644 artiq/firmware/libboard_misoc/or1k/irq.rs delete mode 100644 artiq/firmware/libboard_misoc/or1k/mod.rs delete mode 100644 artiq/firmware/libboard_misoc/or1k/spr.rs delete mode 100644 artiq/firmware/libboard_misoc/or1k/vectors.S diff --git a/artiq/firmware/libboard_misoc/lib.rs b/artiq/firmware/libboard_misoc/lib.rs index b9e0cec38..7057f10f2 100644 --- a/artiq/firmware/libboard_misoc/lib.rs +++ b/artiq/firmware/libboard_misoc/lib.rs @@ -7,10 +7,6 @@ extern crate log; #[cfg(feature = "smoltcp")] extern crate smoltcp; -#[cfg(target_arch = "or1k")] -#[path = "or1k/mod.rs"] -mod arch; - #[cfg(target_arch = "riscv32")] #[path = "riscv32imac/mod.rs"] mod arch; diff --git a/artiq/firmware/libboard_misoc/or1k/boot.rs b/artiq/firmware/libboard_misoc/or1k/boot.rs deleted file mode 100644 index a967c3e66..000000000 --- a/artiq/firmware/libboard_misoc/or1k/boot.rs +++ /dev/null @@ -1,11 +0,0 @@ -use super::{irq, cache}; - -pub unsafe fn jump(addr: usize) -> ! { - irq::set_ie(false); - cache::flush_cpu_icache(); - asm!(r#" - l.jr $0 - l.nop - "# : : "r"(addr) : : "volatile"); - loop {} -} diff --git a/artiq/firmware/libboard_misoc/or1k/cache.rs b/artiq/firmware/libboard_misoc/or1k/cache.rs deleted file mode 100644 index 9357917c9..000000000 --- a/artiq/firmware/libboard_misoc/or1k/cache.rs +++ /dev/null @@ -1,49 +0,0 @@ -#[cfg(has_ddrphy)] -use core::ptr; -use super::spr::*; -#[cfg(has_ddrphy)] -use csr; -#[cfg(has_ddrphy)] -use mem; - -pub fn flush_cpu_icache() { - unsafe { - let iccfgr = mfspr(SPR_ICCFGR); - let ways = 1 << (iccfgr & SPR_ICCFGR_NCW); - let set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3); - let block_size = if iccfgr & SPR_ICCFGR_CBS != 0 { 32 } else { 16 }; - let size = set_size * ways * block_size; - - let mut i = 0; - while i < size { - mtspr(SPR_ICBIR, i); - i += block_size; - } - } -} - -pub fn flush_cpu_dcache() { - unsafe { - let dccfgr = mfspr(SPR_DCCFGR); - let ways = 1 << (dccfgr & SPR_ICCFGR_NCW); - let set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3); - let block_size = if dccfgr & SPR_DCCFGR_CBS != 0 { 32 } else { 16 }; - let size = set_size * ways * block_size; - - let mut i = 0; - while i < size { - mtspr(SPR_DCBIR, i); - i += block_size; - } - } -} - -#[cfg(has_ddrphy)] -pub fn flush_l2_cache() { - unsafe { - for i in 0..2 * (csr::CONFIG_L2_SIZE as usize) / 4 { - let addr = mem::MAIN_RAM_BASE + i * 4; - ptr::read_volatile(addr as *const usize); - } - } -} diff --git a/artiq/firmware/libboard_misoc/or1k/irq.rs b/artiq/firmware/libboard_misoc/or1k/irq.rs deleted file mode 100644 index bc745ae02..000000000 --- a/artiq/firmware/libboard_misoc/or1k/irq.rs +++ /dev/null @@ -1,107 +0,0 @@ -use core::{fmt, convert}; - -use super::spr::*; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum Exception { - Reset = 0x1, - BusError = 0x2, - DataPageFault = 0x3, - InsnPageFault = 0x4, - Tick = 0x5, - Alignment = 0x6, - IllegalInsn = 0x7, - Interrupt = 0x8, - DtlbMiss = 0x9, - ItlbMiss = 0xa, - Range = 0xb, - Syscall = 0xc, - FloatingPoint = 0xd, - Trap = 0xe, -} - -impl fmt::Display for Exception { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Exception::Reset => write!(f, "reset"), - Exception::BusError => write!(f, "bus error"), - Exception::DataPageFault => write!(f, "data page fault"), - Exception::InsnPageFault => write!(f, "instruction page fault"), - Exception::Tick => write!(f, "tick"), - Exception::Alignment => write!(f, "alignment"), - Exception::IllegalInsn => write!(f, "illegal instruction"), - Exception::Interrupt => write!(f, "interrupt"), - Exception::DtlbMiss => write!(f, "D-TLB miss"), - Exception::ItlbMiss => write!(f, "I-TLB miss"), - Exception::Range => write!(f, "range"), - Exception::Syscall => write!(f, "system call"), - Exception::FloatingPoint => write!(f, "floating point"), - Exception::Trap => write!(f, "trap"), - } - } -} - -impl convert::TryFrom for Exception { - type Error = (); - - fn try_from(num: u32) -> Result { - match num { - 0x1 => Ok(Exception::Reset), - 0x2 => Ok(Exception::BusError), - 0x3 => Ok(Exception::DataPageFault), - 0x4 => Ok(Exception::InsnPageFault), - 0x5 => Ok(Exception::Tick), - 0x6 => Ok(Exception::Alignment), - 0x7 => Ok(Exception::IllegalInsn), - 0x8 => Ok(Exception::Interrupt), - 0x9 => Ok(Exception::DtlbMiss), - 0xa => Ok(Exception::ItlbMiss), - 0xb => Ok(Exception::Range), - 0xc => Ok(Exception::Syscall), - 0xd => Ok(Exception::FloatingPoint), - 0xe => Ok(Exception::Trap), - _ => Err(()) - } - } -} - -#[inline] -pub fn get_ie() -> bool { - unsafe { mfspr(SPR_SR) & SPR_SR_IEE != 0 } -} - -#[inline] -pub fn set_ie(ie: bool) { - if ie { - unsafe { mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE) } - } else { - unsafe { mtspr(SPR_SR, mfspr(SPR_SR) & !SPR_SR_IEE) } - } -} - -#[inline] -pub fn get_mask() -> u32 { - unsafe { mfspr(SPR_PICMR) } -} - -#[inline] -pub fn set_mask(mask: u32) { - unsafe { mtspr(SPR_PICMR, mask) } -} - -#[inline] -pub fn pending_mask() -> u32 { - unsafe { mfspr(SPR_PICSR) } -} - -pub fn enable(irq: u32) { - set_mask(get_mask() | (1 << irq)) -} - -pub fn disable(irq: u32) { - set_mask(get_mask() & !(1 << irq)) -} - -pub fn is_pending(irq: u32) -> bool { - get_mask() & (1 << irq) != 0 -} diff --git a/artiq/firmware/libboard_misoc/or1k/mod.rs b/artiq/firmware/libboard_misoc/or1k/mod.rs deleted file mode 100644 index 52a619d1b..000000000 --- a/artiq/firmware/libboard_misoc/or1k/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod spr; -pub mod irq; -pub mod cache; -pub mod boot; diff --git a/artiq/firmware/libboard_misoc/or1k/spr.rs b/artiq/firmware/libboard_misoc/or1k/spr.rs deleted file mode 100644 index 14bb5ae3d..000000000 --- a/artiq/firmware/libboard_misoc/or1k/spr.rs +++ /dev/null @@ -1,231 +0,0 @@ -#[inline(always)] -pub unsafe fn mfspr(reg: u32) -> u32 { - let value: u32; - asm!("l.mfspr $0, $1, 0" : "=r"(value) : "r"(reg) : : "volatile"); - value -} - -#[inline(always)] -pub unsafe fn mtspr(reg: u32, value: u32) { - asm!("l.mtspr $0, $1, 0" : : "r"(reg), "r"(value) : : "volatile") -} - -/* Definition of special-purpose registers (SPRs). */ - -pub const MAX_GRPS: u32 = 32; -pub const MAX_SPRS_PER_GRP_BITS: u32 = 11; -pub const MAX_SPRS_PER_GRP: u32 = 1 << MAX_SPRS_PER_GRP_BITS; -pub const MAX_SPRS: u32 = 0x10000; - -/* Base addresses for the groups */ -pub const SPRGROUP_SYS: u32 = 0 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_DMMU: u32 = 1 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_IMMU: u32 = 2 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_DC: u32 = 3 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_IC: u32 = 4 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_MAC: u32 = 5 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_D: u32 = 6 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_PC: u32 = 7 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_PM: u32 = 8 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_PIC: u32 = 9 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_TT: u32 = 10 << MAX_SPRS_PER_GRP_BITS; -pub const SPRGROUP_FP: u32 = 11 << MAX_SPRS_PER_GRP_BITS; - -/* System control and status group */ -pub const SPR_VR: u32 = SPRGROUP_SYS + 0; -pub const SPR_UPR: u32 = SPRGROUP_SYS + 1; -pub const SPR_CPUCFGR: u32 = SPRGROUP_SYS + 2; -pub const SPR_DMMUCFGR: u32 = SPRGROUP_SYS + 3; -pub const SPR_IMMUCFGR: u32 = SPRGROUP_SYS + 4; -pub const SPR_DCCFGR: u32 = SPRGROUP_SYS + 5; -pub const SPR_ICCFGR: u32 = SPRGROUP_SYS + 6; -pub const SPR_DCFGR: u32 = SPRGROUP_SYS + 7; -pub const SPR_PCCFGR: u32 = SPRGROUP_SYS + 8; -pub const SPR_VR2: u32 = SPRGROUP_SYS + 9; -pub const SPR_AVR: u32 = SPRGROUP_SYS + 10; -pub const SPR_EVBAR: u32 = SPRGROUP_SYS + 11; -pub const SPR_AECR: u32 = SPRGROUP_SYS + 12; -pub const SPR_AESR: u32 = SPRGROUP_SYS + 13; -pub const SPR_NPC: u32 = SPRGROUP_SYS + 16; /* CZ 21/06/01 */ -pub const SPR_SR: u32 = SPRGROUP_SYS + 17; /* CZ 21/06/01 */ -pub const SPR_PPC: u32 = SPRGROUP_SYS + 18; /* CZ 21/06/01 */ -pub const SPR_FPCSR: u32 = SPRGROUP_SYS + 20; /* CZ 21/06/01 */ -pub const SPR_ISR_BASE: u32 = SPRGROUP_SYS + 21; -pub const SPR_EPCR_BASE: u32 = SPRGROUP_SYS + 32; /* CZ 21/06/01 */ -pub const SPR_EPCR_LAST: u32 = SPRGROUP_SYS + 47; /* CZ 21/06/01 */ -pub const SPR_EEAR_BASE: u32 = SPRGROUP_SYS + 48; -pub const SPR_EEAR_LAST: u32 = SPRGROUP_SYS + 63; -pub const SPR_ESR_BASE: u32 = SPRGROUP_SYS + 64; -pub const SPR_ESR_LAST: u32 = SPRGROUP_SYS + 79; -pub const SPR_GPR_BASE: u32 = SPRGROUP_SYS + 1024; - -/* Data MMU group */ -pub const SPR_DMMUCR: u32 = SPRGROUP_DMMU + 0; -pub const SPR_DTLBEIR: u32 = SPRGROUP_DMMU + 2; - -/* Instruction MMU group */ -pub const SPR_IMMUCR: u32 = SPRGROUP_IMMU + 0; -pub const SPR_ITLBEIR: u32 = SPRGROUP_IMMU + 2; - -/* Data cache group */ -pub const SPR_DCCR: u32 = SPRGROUP_DC + 0; -pub const SPR_DCBPR: u32 = SPRGROUP_DC + 1; -pub const SPR_DCBFR: u32 = SPRGROUP_DC + 2; -pub const SPR_DCBIR: u32 = SPRGROUP_DC + 3; -pub const SPR_DCBWR: u32 = SPRGROUP_DC + 4; -pub const SPR_DCBLR: u32 = SPRGROUP_DC + 5; - -/* Instruction cache group */ -pub const SPR_ICCR: u32 = SPRGROUP_IC + 0; -pub const SPR_ICBPR: u32 = SPRGROUP_IC + 1; -pub const SPR_ICBIR: u32 = SPRGROUP_IC + 2; -pub const SPR_ICBLR: u32 = SPRGROUP_IC + 3; - -// [snip] - -/* Performance counters group */ -pub const SPR_PCCR0: u32 = SPRGROUP_PC + 0; -pub const SPR_PCCR1: u32 = SPRGROUP_PC + 1; -pub const SPR_PCCR2: u32 = SPRGROUP_PC + 2; -pub const SPR_PCCR3: u32 = SPRGROUP_PC + 3; -pub const SPR_PCCR4: u32 = SPRGROUP_PC + 4; -pub const SPR_PCCR5: u32 = SPRGROUP_PC + 5; -pub const SPR_PCCR6: u32 = SPRGROUP_PC + 6; -pub const SPR_PCCR7: u32 = SPRGROUP_PC + 7; -pub const SPR_PCMR0: u32 = SPRGROUP_PC + 8; -pub const SPR_PCMR1: u32 = SPRGROUP_PC + 9; -pub const SPR_PCMR2: u32 = SPRGROUP_PC + 10; -pub const SPR_PCMR3: u32 = SPRGROUP_PC + 11; -pub const SPR_PCMR4: u32 = SPRGROUP_PC + 12; -pub const SPR_PCMR5: u32 = SPRGROUP_PC + 13; -pub const SPR_PCMR6: u32 = SPRGROUP_PC + 14; -pub const SPR_PCMR7: u32 = SPRGROUP_PC + 15; - -/* PIC group */ -pub const SPR_PICMR: u32 = SPRGROUP_PIC + 0; -pub const SPR_PICPR: u32 = SPRGROUP_PIC + 1; -pub const SPR_PICSR: u32 = SPRGROUP_PIC + 2; - -// [snip] - -/* - * Bit definitions for the Supervision Register - * - */ -pub const SPR_SR_SM: u32 = 0x00000001; /* Supervisor Mode */ -pub const SPR_SR_TEE: u32 = 0x00000002; /* Tick timer Exception Enable */ -pub const SPR_SR_IEE: u32 = 0x00000004; /* Interrupt Exception Enable */ -pub const SPR_SR_DCE: u32 = 0x00000008; /* Data Cache Enable */ -pub const SPR_SR_ICE: u32 = 0x00000010; /* Instruction Cache Enable */ -pub const SPR_SR_DME: u32 = 0x00000020; /* Data MMU Enable */ -pub const SPR_SR_IME: u32 = 0x00000040; /* Instruction MMU Enable */ -pub const SPR_SR_LEE: u32 = 0x00000080; /* Little Endian Enable */ -pub const SPR_SR_CE: u32 = 0x00000100; /* CID Enable */ -pub const SPR_SR_F: u32 = 0x00000200; /* Condition Flag */ -pub const SPR_SR_CY: u32 = 0x00000400; /* Carry flag */ -pub const SPR_SR_OV: u32 = 0x00000800; /* Overflow flag */ -pub const SPR_SR_OVE: u32 = 0x00001000; /* Overflow flag Exception */ -pub const SPR_SR_DSX: u32 = 0x00002000; /* Delay Slot Exception */ -pub const SPR_SR_EPH: u32 = 0x00004000; /* Exception Prefix High */ -pub const SPR_SR_FO: u32 = 0x00008000; /* Fixed one */ -pub const SPR_SR_SUMRA: u32 = 0x00010000; /* Supervisor SPR read access */ -pub const SPR_SR_RES: u32 = 0x0ffe0000; /* Reserved */ -pub const SPR_SR_CID: u32 = 0xf0000000; /* Context ID */ - -/* - * Bit definitions for Data Cache Control register - * - */ -pub const SPR_DCCR_EW: u32 = 0x000000ff; /* Enable ways */ - -/* - * Bit definitions for Insn Cache Control register - * - */ -pub const SPR_ICCR_EW: u32 = 0x000000ff; /* Enable ways */ - -/* - * Bit definitions for Data Cache Configuration Register - * - */ -pub const SPR_DCCFGR_NCW: u32 = 0x00000007; -pub const SPR_DCCFGR_NCS: u32 = 0x00000078; -pub const SPR_DCCFGR_CBS: u32 = 0x00000080; -pub const SPR_DCCFGR_CWS: u32 = 0x00000100; -pub const SPR_DCCFGR_CCRI: u32 = 0x00000200; -pub const SPR_DCCFGR_CBIRI: u32 = 0x00000400; -pub const SPR_DCCFGR_CBPRI: u32 = 0x00000800; -pub const SPR_DCCFGR_CBLRI: u32 = 0x00001000; -pub const SPR_DCCFGR_CBFRI: u32 = 0x00002000; -pub const SPR_DCCFGR_CBWBRI: u32 = 0x00004000; - -pub const SPR_DCCFGR_NCW_OFF: u32 = 0; -pub const SPR_DCCFGR_NCS_OFF: u32 = 3; -pub const SPR_DCCFGR_CBS_OFF: u32 = 7; - -/* - * Bit definitions for Instruction Cache Configuration Register - * - */ -pub const SPR_ICCFGR_NCW: u32 = 0x00000007; -pub const SPR_ICCFGR_NCS: u32 = 0x00000078; -pub const SPR_ICCFGR_CBS: u32 = 0x00000080; -pub const SPR_ICCFGR_CCRI: u32 = 0x00000200; -pub const SPR_ICCFGR_CBIRI: u32 = 0x00000400; -pub const SPR_ICCFGR_CBPRI: u32 = 0x00000800; -pub const SPR_ICCFGR_CBLRI: u32 = 0x00001000; - -pub const SPR_ICCFGR_NCW_OFF: u32 = 0; -pub const SPR_ICCFGR_NCS_OFF: u32 = 3; -pub const SPR_ICCFGR_CBS_OFF: u32 = 7; - -/* - * Bit definitions for Data MMU Configuration Register - * - */ -pub const SPR_DMMUCFGR_NTW: u32 = 0x00000003; -pub const SPR_DMMUCFGR_NTS: u32 = 0x0000001C; -pub const SPR_DMMUCFGR_NAE: u32 = 0x000000E0; -pub const SPR_DMMUCFGR_CRI: u32 = 0x00000100; -pub const SPR_DMMUCFGR_PRI: u32 = 0x00000200; -pub const SPR_DMMUCFGR_TEIRI: u32 = 0x00000400; -pub const SPR_DMMUCFGR_HTR: u32 = 0x00000800; - -pub const SPR_DMMUCFGR_NTW_OFF: u32 = 0; -pub const SPR_DMMUCFGR_NTS_OFF: u32 = 2; - -/* - * Bit definitions for Instruction MMU Configuration Register - * - */ -pub const SPR_IMMUCFGR_NTW: u32 = 0x00000003; -pub const SPR_IMMUCFGR_NTS: u32 = 0x0000001C; -pub const SPR_IMMUCFGR_NAE: u32 = 0x000000E0; -pub const SPR_IMMUCFGR_CRI: u32 = 0x00000100; -pub const SPR_IMMUCFGR_PRI: u32 = 0x00000200; -pub const SPR_IMMUCFGR_TEIRI: u32 = 0x00000400; -pub const SPR_IMMUCFGR_HTR: u32 = 0x00000800; - -pub const SPR_IMMUCFGR_NTW_OFF: u32 = 0; -pub const SPR_IMMUCFGR_NTS_OFF: u32 = 2; - -/* - * Bit definitions for Performance counters mode registers - * - */ -pub const SPR_PCMR_CP: u32 = 0x00000001; /* Counter present */ -pub const SPR_PCMR_UMRA: u32 = 0x00000002; /* User mode read access */ -pub const SPR_PCMR_CISM: u32 = 0x00000004; /* Count in supervisor mode */ -pub const SPR_PCMR_CIUM: u32 = 0x00000008; /* Count in user mode */ -pub const SPR_PCMR_LA: u32 = 0x00000010; /* Load access event */ -pub const SPR_PCMR_SA: u32 = 0x00000020; /* Store access event */ -pub const SPR_PCMR_IF: u32 = 0x00000040; /* Instruction fetch event*/ -pub const SPR_PCMR_DCM: u32 = 0x00000080; /* Data cache miss event */ -pub const SPR_PCMR_ICM: u32 = 0x00000100; /* Insn cache miss event */ -pub const SPR_PCMR_IFS: u32 = 0x00000200; /* Insn fetch stall event */ -pub const SPR_PCMR_LSUS: u32 = 0x00000400; /* LSU stall event */ -pub const SPR_PCMR_BS: u32 = 0x00000800; /* Branch stall event */ -pub const SPR_PCMR_DTLBM: u32 = 0x00001000; /* DTLB miss event */ -pub const SPR_PCMR_ITLBM: u32 = 0x00002000; /* ITLB miss event */ -pub const SPR_PCMR_DDS: u32 = 0x00004000; /* Data dependency stall event */ -pub const SPR_PCMR_WPE: u32 = 0x03ff8000; /* Watchpoint events */ diff --git a/artiq/firmware/libboard_misoc/or1k/vectors.S b/artiq/firmware/libboard_misoc/or1k/vectors.S deleted file mode 100644 index 708aed9df..000000000 --- a/artiq/firmware/libboard_misoc/or1k/vectors.S +++ /dev/null @@ -1,413 +0,0 @@ -/* - * (C) Copyright 2012, Stefan Kristiansson - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -/* - * OR1K Architecture has a 128 byte "red zone" after the stack that can not be - * touched by exception handlers. GCC uses this red zone for locals and - * temps without needing to change the stack pointer. - */ -#define OR1K_RED_ZONE_SIZE 128 - -/* - * We need 4 bytes (32 bits) * 32 registers space on the stack to save all the - * registers. - */ -#define EXCEPTION_STACK_SIZE ((4*32) + OR1K_RED_ZONE_SIZE) - -#define HANDLE_EXCEPTION ; \ - l.addi r1, r1, -EXCEPTION_STACK_SIZE ; \ - l.sw 0x1c(r1), r9 ; \ - l.jal _exception_handler ; \ - l.nop ; \ - l.lwz r9, 0x1c(r1) ; \ - l.addi r1, r1, EXCEPTION_STACK_SIZE ; \ - l.rfe ; \ - l.nop - - -.section .vectors, "ax", @progbits -.global _reset_handler -_reset_handler: - l.movhi r0, 0 - l.movhi r1, 0 - l.movhi r2, 0 - l.movhi r3, 0 - l.movhi r4, 0 - l.movhi r5, 0 - l.movhi r6, 0 - l.movhi r7, 0 - l.movhi r8, 0 - l.movhi r9, 0 - l.movhi r10, 0 - l.movhi r11, 0 - l.movhi r12, 0 - l.movhi r13, 0 - l.movhi r14, 0 - l.movhi r15, 0 - l.movhi r16, 0 - l.movhi r17, 0 - l.movhi r18, 0 - l.movhi r19, 0 - l.movhi r20, 0 - l.movhi r21, 0 - l.movhi r22, 0 - l.movhi r23, 0 - l.movhi r24, 0 - l.movhi r25, 0 - l.movhi r26, 0 - l.movhi r27, 0 - l.movhi r28, 0 - l.movhi r29, 0 - l.movhi r30, 0 - l.movhi r31, 0 - - l.ori r21, r0, SPR_SR_SM - l.mtspr r0, r21, SPR_SR - l.movhi r21, hi(_reset_handler) - l.ori r21, r21, lo(_reset_handler) - l.mtspr r0, r21, SPR_EVBAR - /* enable caches */ - l.jal _cache_init - l.nop - l.j _crt0 - l.nop - - /* bus error */ - .org 0x200 - HANDLE_EXCEPTION - - /* data page fault */ - .org 0x300 - HANDLE_EXCEPTION - - /* instruction page fault */ - .org 0x400 - HANDLE_EXCEPTION - - /* tick timer */ - .org 0x500 - HANDLE_EXCEPTION - - /* alignment */ - .org 0x600 - HANDLE_EXCEPTION - - /* illegal instruction */ - .org 0x700 - HANDLE_EXCEPTION - - /* external interrupt */ - .org 0x800 - HANDLE_EXCEPTION - - /* D-TLB miss */ - .org 0x900 - HANDLE_EXCEPTION - - /* I-TLB miss */ - .org 0xa00 - HANDLE_EXCEPTION - - /* range */ - .org 0xb00 - HANDLE_EXCEPTION - - /* system call */ - .org 0xc00 - HANDLE_EXCEPTION - - /* floating point */ - .org 0xd00 - HANDLE_EXCEPTION - - /* trap */ - .org 0xe00 - HANDLE_EXCEPTION - - /* reserved */ - .org 0xf00 - HANDLE_EXCEPTION - - .org 0x1000 -_crt0: - /* Setup stack and global pointer */ - l.movhi r1, hi(_fstack) - l.ori r1, r1, lo(_fstack) - - /* Clear BSS */ - l.movhi r21, hi(_fbss) - l.ori r21, r21, lo(_fbss) - l.movhi r3, hi(_ebss) - l.ori r3, r3, lo(_ebss) -.clearBSS: - l.sfeq r21, r3 - l.bf .callMain - l.nop - l.sw 0(r21), r0 - l.addi r21, r21, 4 - l.j .clearBSS - l.nop - -.callMain: - l.j main - l.nop - -_exception_handler: - .cfi_startproc - .cfi_return_column 32 - .cfi_signal_frame - .cfi_def_cfa_offset EXCEPTION_STACK_SIZE - l.sw 0x00(r1), r2 - .cfi_offset 2, 0x00-EXCEPTION_STACK_SIZE - l.sw 0x04(r1), r3 - .cfi_offset 3, 0x04-EXCEPTION_STACK_SIZE - l.sw 0x08(r1), r4 - .cfi_offset 4, 0x08-EXCEPTION_STACK_SIZE - l.sw 0x0c(r1), r5 - .cfi_offset 5, 0x0c-EXCEPTION_STACK_SIZE - l.sw 0x10(r1), r6 - .cfi_offset 6, 0x10-EXCEPTION_STACK_SIZE - l.sw 0x14(r1), r7 - .cfi_offset 7, 0x14-EXCEPTION_STACK_SIZE - l.sw 0x18(r1), r8 - .cfi_offset 8, 0x18-EXCEPTION_STACK_SIZE - /* r9 saved in HANDLE_EXCEPTION */ - .cfi_offset 9, 0x1c-EXCEPTION_STACK_SIZE - l.sw 0x20(r1), r10 - .cfi_offset 10, 0x20-EXCEPTION_STACK_SIZE - l.sw 0x24(r1), r11 - .cfi_offset 11, 0x24-EXCEPTION_STACK_SIZE - l.sw 0x28(r1), r12 - .cfi_offset 12, 0x28-EXCEPTION_STACK_SIZE - l.sw 0x2c(r1), r13 - .cfi_offset 13, 0x2c-EXCEPTION_STACK_SIZE - l.sw 0x30(r1), r14 - .cfi_offset 14, 0x30-EXCEPTION_STACK_SIZE - l.sw 0x34(r1), r15 - .cfi_offset 15, 0x34-EXCEPTION_STACK_SIZE - l.sw 0x38(r1), r16 - .cfi_offset 16, 0x38-EXCEPTION_STACK_SIZE - l.sw 0x3c(r1), r17 - .cfi_offset 17, 0x3c-EXCEPTION_STACK_SIZE - l.sw 0x40(r1), r18 - .cfi_offset 18, 0x40-EXCEPTION_STACK_SIZE - l.sw 0x44(r1), r19 - .cfi_offset 19, 0x44-EXCEPTION_STACK_SIZE - l.sw 0x48(r1), r20 - .cfi_offset 20, 0x48-EXCEPTION_STACK_SIZE - l.sw 0x4c(r1), r21 - .cfi_offset 21, 0x4c-EXCEPTION_STACK_SIZE - l.sw 0x50(r1), r22 - .cfi_offset 22, 0x50-EXCEPTION_STACK_SIZE - l.sw 0x54(r1), r23 - .cfi_offset 23, 0x54-EXCEPTION_STACK_SIZE - l.sw 0x58(r1), r24 - .cfi_offset 24, 0x58-EXCEPTION_STACK_SIZE - l.sw 0x5c(r1), r25 - .cfi_offset 25, 0x5c-EXCEPTION_STACK_SIZE - l.sw 0x60(r1), r26 - .cfi_offset 26, 0x60-EXCEPTION_STACK_SIZE - l.sw 0x64(r1), r27 - .cfi_offset 27, 0x64-EXCEPTION_STACK_SIZE - l.sw 0x68(r1), r28 - .cfi_offset 28, 0x68-EXCEPTION_STACK_SIZE - l.sw 0x6c(r1), r29 - .cfi_offset 29, 0x6c-EXCEPTION_STACK_SIZE - l.sw 0x70(r1), r30 - .cfi_offset 30, 0x70-EXCEPTION_STACK_SIZE - l.sw 0x74(r1), r31 - .cfi_offset 31, 0x74-EXCEPTION_STACK_SIZE - - /* Save return address */ - l.or r14, r0, r9 - /* Calculate exception vector from handler address */ - l.andi r3, r9, 0xf00 - l.srli r3, r3, 8 - /* Pass saved register state */ - l.or r4, r0, r1 - /* Extract exception PC */ - l.mfspr r5, r0, SPR_EPCR_BASE - /* Tell exception PC to the unwinder */ - l.sw 0x78(r1), r5 - .cfi_offset 32, 0x78-EXCEPTION_STACK_SIZE - /* Extract exception effective address */ - l.mfspr r6, r0, SPR_EEAR_BASE - /* Extract exception SR */ - l.mfspr r7, r0, SPR_ESR_BASE - /* Call exception handler with the link address as argument */ - l.jal exception - l.nop - - /* Load return address */ - l.or r9, r0, r14 - /* Restore state */ - l.lwz r2, 0x00(r1) - l.lwz r3, 0x04(r1) - l.lwz r4, 0x08(r1) - l.lwz r5, 0x0c(r1) - l.lwz r6, 0x10(r1) - l.lwz r7, 0x14(r1) - l.lwz r8, 0x18(r1) - l.lwz r10, 0x20(r1) - l.lwz r11, 0x24(r1) - l.lwz r12, 0x28(r1) - l.lwz r13, 0x2c(r1) - l.lwz r14, 0x30(r1) - l.lwz r15, 0x34(r1) - l.lwz r16, 0x38(r1) - l.lwz r17, 0x3c(r1) - l.lwz r18, 0x40(r1) - l.lwz r19, 0x44(r1) - l.lwz r20, 0x48(r1) - l.lwz r21, 0x4c(r1) - l.lwz r22, 0x50(r1) - l.lwz r23, 0x54(r1) - l.lwz r24, 0x58(r1) - l.lwz r25, 0x5c(r1) - l.lwz r26, 0x60(r1) - l.lwz r27, 0x64(r1) - l.lwz r28, 0x68(r1) - l.lwz r29, 0x6c(r1) - l.lwz r30, 0x70(r1) - l.lwz r31, 0x74(r1) - l.jr r9 - l.nop - .cfi_endproc - -.global _cache_init -_cache_init: - /* - This function is to be used ONLY during reset, before main() is called. - TODO: Perhaps break into individual enable instruction/data cache - sections functions, and provide disable functions, also, all - callable from C - */ - - /* Instruction cache enable */ - /* Check if IC present and skip enabling otherwise */ -#if 1 -.L6: - l.mfspr r3,r0,SPR_UPR - l.andi r7,r3,SPR_UPR_ICP - l.sfeq r7,r0 - l.bf .L8 - l.nop - - /* Disable IC */ - l.mfspr r6,r0,SPR_SR - l.addi r5,r0,-1 - l.xori r5,r5,SPR_SR_ICE - l.and r5,r6,r5 - l.mtspr r0,r5,SPR_SR - - /* Establish cache block size - If BS=0, 16; - If BS=1, 32; - r14 contain block size - */ - l.mfspr r3,r0,SPR_ICCFGR - l.andi r7,r3,SPR_ICCFGR_CBS - l.srli r8,r7,7 - l.ori r4,r0,16 - l.sll r14,r4,r8 - - /* Establish number of cache sets - r10 contains number of cache sets - r8 contains log(# of cache sets) - */ - l.andi r7,r3,SPR_ICCFGR_NCS - l.srli r8,r7,3 - l.ori r4,r0,1 - l.sll r10,r4,r8 - - /* Invalidate IC */ - l.addi r6,r0,0 - l.sll r5,r14,r8 - -.L7: l.mtspr r0,r6,SPR_ICBIR - l.sfne r6,r5 - l.bf .L7 - l.add r6,r6,r14 - - /* Enable IC */ - l.mfspr r6,r0,SPR_SR - l.ori r6,r6,SPR_SR_ICE - l.mtspr r0,r6,SPR_SR - l.nop - l.nop - l.nop - l.nop - l.nop - l.nop - l.nop - l.nop - /* Data cache enable */ - /* Check if DC present and skip enabling otherwise */ -#endif -.L8: -#if 1 - l.mfspr r3,r0,SPR_UPR - l.andi r7,r3,SPR_UPR_DCP - l.sfeq r7,r0 - l.bf .L10 - l.nop - /* Disable DC */ - l.mfspr r6,r0,SPR_SR - l.addi r5,r0,-1 - l.xori r5,r5,SPR_SR_DCE - l.and r5,r6,r5 - l.mtspr r0,r5,SPR_SR - /* Establish cache block size - If BS=0, 16; - If BS=1, 32; - r14 contain block size - */ - l.mfspr r3,r0,SPR_DCCFGR - l.andi r7,r3,SPR_DCCFGR_CBS - l.srli r8,r7,7 - l.ori r4,r0,16 - l.sll r14,r4,r8 - /* Establish number of cache sets - r10 contains number of cache sets - r8 contains log(# of cache sets) - */ - l.andi r7,r3,SPR_DCCFGR_NCS - l.srli r8,r7,3 - l.ori r4,r0,1 - l.sll r10,r4,r8 - /* Invalidate DC */ - l.addi r6,r0,0 - l.sll r5,r14,r8 - -.L9: - l.mtspr r0,r6,SPR_DCBIR - l.sfne r6,r5 - l.bf .L9 - l.add r6,r6,r14 - /* Enable DC */ - l.mfspr r6,r0,SPR_SR - l.ori r6,r6,SPR_SR_DCE - l.mtspr r0,r6,SPR_SR -#endif -.L10: - /* Return */ - l.jr r9 - l.nop diff --git a/artiq/firmware/libdyld/lib.rs b/artiq/firmware/libdyld/lib.rs index 0788c38d4..8626b2920 100644 --- a/artiq/firmware/libdyld/lib.rs +++ b/artiq/firmware/libdyld/lib.rs @@ -141,9 +141,6 @@ impl<'a> Library<'a> { pub unsafe fn rebind(&self, name: &[u8], addr: Elf32_Word) -> Result<(), Error<'a>> { for rela in self.pltrel.iter() { match (ELF32_R_TYPE(rela.r_info), self.arch) { - (R_OR1K_32, Arch::OpenRisc) | - (R_OR1K_GLOB_DAT, Arch::OpenRisc) | - (R_OR1K_JMP_SLOT, Arch::OpenRisc) | (R_RISCV_32, Arch::RiscV) | (R_RISCV_JUMP_SLOT, Arch::RiscV) => { let sym = self.symtab.get(ELF32_R_SYM(rela.r_info) as usize) @@ -174,15 +171,12 @@ impl<'a> Library<'a> { let value; match (ELF32_R_TYPE(rela.r_info), self.arch) { - (R_OR1K_NONE, Arch::OpenRisc) | (R_RISCV_NONE, Arch::RiscV) => + (R_RISCV_NONE, Arch::RiscV) => return Ok(()), - (R_OR1K_RELATIVE, Arch::OpenRisc) | (R_RISCV_RELATIVE, Arch::RiscV) => + (R_RISCV_RELATIVE, Arch::RiscV) => value = self.image_off + rela.r_addend as Elf32_Word, - (R_OR1K_32, Arch::OpenRisc) | - (R_OR1K_GLOB_DAT, Arch::OpenRisc) | - (R_OR1K_JMP_SLOT, Arch::OpenRisc) | (R_RISCV_32, Arch::RiscV) | (R_RISCV_JUMP_SLOT, Arch::RiscV) => { let sym = sym.ok_or("relocation requires an associated symbol")?; @@ -342,11 +336,6 @@ impl<'a> Library<'a> { } fn arch(ehdr: &Elf32_Ehdr) -> Option { - const IDENT_OPENRISC: [u8; EI_NIDENT] = [ - ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, - ELFCLASS32, ELFDATA2MSB, EV_CURRENT, ELFOSABI_NONE, - /* ABI version */ 0, /* padding */ 0, 0, 0, 0, 0, 0, 0 - ]; const IDENT_RISCV: [u8; EI_NIDENT] = [ ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, @@ -356,9 +345,6 @@ fn arch(ehdr: &Elf32_Ehdr) -> Option { #[cfg(target_arch = "riscv32")] (IDENT_RISCV, EM_RISCV) => Some(Arch::RiscV), - #[cfg(target_arch = "or1k")] - (IDENT_OPENRISC, EM_OPENRISC) => Some(Arch::OpenRisc), - _ => None, } } From 251cd4dcc60bf0f7b3c230cc10ba8bfd206b5379 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 25 Aug 2021 10:47:01 +0800 Subject: [PATCH 112/238] flake: update dependencies --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 3ae9c5a3e..eeb43998d 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "mozilla-overlay": { "flake": false, "locked": { - "lastModified": 1627922300, - "narHash": "sha256-/5fyO/265Wrli2pHpe1/i9Lu8XnQ5K+2YLz9Sz568cI=", + "lastModified": 1629225446, + "narHash": "sha256-HJX4Pc5ZUAg4apxB/XHuJ+6ukzvRQqeZMjscOBst2bA=", "owner": "mozilla", "repo": "nixpkgs-mozilla", - "rev": "b1001ed670666ca4ce1c1b064481f88694315c1d", + "rev": "0510159186dd2ef46e5464484fbdf119393afa58", "type": "github" }, "original": { @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1628696776, - "narHash": "sha256-K8+/IQNZDZltIu/KSf+Tz01OwNzTGgTch0ktMOWcxLg=", + "lastModified": 1629772723, + "narHash": "sha256-/BQRsa1FsGb7v4xylPnHhU2/chw3EFbCv5/ZaY/eNsE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "927ce1afc1db40869a463a37ea2738c27d425f80", + "rev": "d5aadbefd650cb0a05ba9c788a26327afce2396c", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1628657477, - "narHash": "sha256-fHlyHvUJFDLZ62QfehcUqVNdQh5hfVXJ4Hq1bQE4oDE=", + "lastModified": 1629858538, + "narHash": "sha256-jdrZPKYqdn0A1GfLBUIhwZ7j5Rj+e5ablHotsK8SXbY=", "owner": "m-labs", "repo": "misoc", - "rev": "e07538743427414d323225217f0737381ef27ec6", + "rev": "51830eab6849c15210825636fe2389cccebda493", "type": "github" }, "original": { @@ -77,11 +77,11 @@ "src-pythonparser": { "flake": false, "locked": { - "lastModified": 1628731931, - "narHash": "sha256-eaGuXyrkvpBPNJVKoihnoqvhoWvqaTvztTdKb+7BJfc=", + "lastModified": 1628745371, + "narHash": "sha256-p6TgeeaK4NEmbhimEXp31W8hVRo4DgWmcCoqZ+UdN60=", "owner": "m-labs", "repo": "pythonparser", - "rev": "f6be5a1bfe44c05ffd36c8016858175954b9722d", + "rev": "5413ee5c9f8760e95c6acd5d6e88dabb831ad201", "type": "github" }, "original": { From c113cd6bf5c0462df340d5b10f0c8f890f560e94 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 25 Aug 2021 12:03:04 +0800 Subject: [PATCH 113/238] libfringe: bump --- artiq/firmware/runtime/Cargo.toml | 4 ++-- artiq/firmware/runtime/sched.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index ca624e3b6..a29acbb86 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -31,7 +31,7 @@ smoltcp = { version = "0.6.0", default-features = false, features = ["alloc", "e riscv = { version = "0.6.0", features = ["inline-asm"] } [dependencies.fringe] -git = "https://github.com/m-labs/libfringe" -rev = "b8a6d8f" +git = "https://git.m-labs.hk/M-Labs/libfringe.git" +rev = "9748bb" default-features = false features = ["alloc"] diff --git a/artiq/firmware/runtime/sched.rs b/artiq/firmware/runtime/sched.rs index a63ad3332..43dae0f55 100644 --- a/artiq/firmware/runtime/sched.rs +++ b/artiq/firmware/runtime/sched.rs @@ -50,7 +50,7 @@ enum WaitResult { #[derive(Debug)] struct Thread { - generator: Generator, + generator: Generator<'static, WaitResult, WaitRequest, OwnedStack>, waiting_for: WaitRequest, interrupted: bool } @@ -194,7 +194,7 @@ impl Scheduler { #[derive(Clone)] pub struct Io<'a> { - yielder: Option<&'a Yielder>, + yielder: Option<&'a Yielder>, spawned: Urc>>, sockets: Urc>, } @@ -207,7 +207,7 @@ impl<'a> Io<'a> { handle } - fn yielder(&self) -> &'a Yielder { + fn yielder(&self) -> &'a Yielder { self.yielder.expect("cannot suspend the scheduler thread") } From 70507e1b72216a8389487a9021b7bd8bb42b9fc6 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 25 Aug 2021 12:03:37 +0800 Subject: [PATCH 114/238] Cargo.lock: update --- artiq/firmware/Cargo.lock | 350 ++++++++++++++++++++++++++------------ 1 file changed, 238 insertions(+), 112 deletions(-) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 2874347c8..4d390505a 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -1,56 +1,84 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "alloc_list" version = "0.0.0" [[package]] -name = "bitflags" -version = "1.0.3" +name = "bare-metal" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bit_field" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "board_artiq" version = "0.0.0" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "board_misoc 0.0.0", - "build_misoc 0.0.0", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "io 0.0.0", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proto_artiq 0.0.0", + "bitflags", + "board_misoc", + "build_misoc", + "byteorder", + "crc", + "failure", + "failure_derive", + "io", + "log", + "proto_artiq", ] [[package]] name = "board_misoc" version = "0.0.0" dependencies = [ - "build_misoc 0.0.0", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "build_misoc", + "byteorder", + "cc", + "log", + "riscv", + "smoltcp", ] [[package]] name = "bootloader" version = "0.0.0" dependencies = [ - "board_misoc 0.0.0", - "build_misoc 0.0.0", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "board_misoc", + "build_misoc", + "byteorder", + "crc", + "riscv", + "smoltcp", ] [[package]] name = "build_const" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" [[package]] name = "build_misoc" @@ -58,31 +86,42 @@ version = "0.0.0" [[package]] name = "byteorder" -version = "1.2.3" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cc" -version = "1.0.15" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" [[package]] name = "cfg-if" -version = "0.1.3" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "crc" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" dependencies = [ - "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "build_const", ] [[package]] name = "cslice" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a" [[package]] name = "dyld" @@ -92,202 +131,289 @@ version = "0.0.0" name = "eh" version = "0.0.0" dependencies = [ - "cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cslice", + "libc 0.1.0", + "unwind", ] [[package]] name = "failure" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" [[package]] name = "failure_derive" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", + "synstructure", ] [[package]] name = "fringe" -version = "1.1.0" -source = "git+https://github.com/m-labs/libfringe?rev=b8a6d8f#b8a6d8f68df0edaa3d67d9f3b7b62af9d3bb64a5" +version = "1.2.1" +source = "git+https://git.m-labs.hk/M-Labs/libfringe.git?rev=9748bb#9748bb8af86c131d45be1238ea4d5f965a974630" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.100", ] [[package]] name = "io" version = "0.0.0" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "failure", + "failure_derive", ] [[package]] name = "ksupport" version = "0.0.0" dependencies = [ - "board_artiq 0.0.0", - "board_misoc 0.0.0", - "build_misoc 0.0.0", - "cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dyld 0.0.0", - "eh 0.0.0", - "io 0.0.0", - "proto_artiq 0.0.0", + "board_artiq", + "board_misoc", + "build_misoc", + "cslice", + "dyld", + "eh", + "io", + "libc 0.1.0", + "proto_artiq", + "riscv", + "unwind", ] [[package]] -name = "libc" -version = "0.2.40" +name = "lazy_static" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.1.0" + +[[package]] +name = "libc" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" [[package]] name = "log" -version = "0.4.1" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 1.0.0", ] [[package]] name = "log_buffer" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f033173c9486b7fe97a79c895c0a3483ae395ab6744c985d10078950e2492419" [[package]] name = "logger_artiq" version = "0.0.0" dependencies = [ - "board_misoc 0.0.0", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log_buffer 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "board_misoc", + "log", + "log_buffer", ] [[package]] name = "managed" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "proto_artiq" version = "0.0.0" dependencies = [ - "byteorder 1.2.3 (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", - "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "io 0.0.0", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "cslice", + "dyld", + "failure", + "failure_derive", + "io", + "log", ] [[package]] name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "riscv" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2f0b705d428e9d0f78e2bb73093887ee58a83c9688de3faedbb4c0631c4618e" +dependencies = [ + "bare-metal", + "bit_field", + "riscv-target", +] + +[[package]] +name = "riscv-target" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" +dependencies = [ + "lazy_static", + "regex", +] [[package]] name = "runtime" version = "0.0.0" dependencies = [ - "alloc_list 0.0.0", - "board_artiq 0.0.0", - "board_misoc 0.0.0", - "build_misoc 0.0.0", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "eh 0.0.0", - "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=b8a6d8f)", - "io 0.0.0", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "logger_artiq 0.0.0", - "managed 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proto_artiq 0.0.0", - "smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unwind_backtrace 0.0.0", + "alloc_list", + "board_artiq", + "board_misoc", + "build_misoc", + "byteorder", + "cslice", + "eh", + "failure", + "failure_derive", + "fringe", + "io", + "log", + "logger_artiq", + "managed", + "proto_artiq", + "riscv", + "smoltcp", + "unwind_backtrace", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", ] [[package]] name = "satman" version = "0.0.0" dependencies = [ - "board_artiq 0.0.0", - "board_misoc 0.0.0", - "build_misoc 0.0.0", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "board_artiq", + "board_misoc", + "build_misoc", + "log", + "riscv", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "smoltcp" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe46639fd2ec79eadf8fe719f237a7a0bd4dac5d957f1ca5bbdbc1c3c39e53a" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "managed 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "byteorder", + "managed", ] [[package]] name = "syn" version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "synom", + "unicode-xid", ] [[package]] name = "synom" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" dependencies = [ - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid", ] [[package]] name = "synstructure" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", ] [[package]] name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" + +[[package]] +name = "unwind" +version = "0.0.0" +dependencies = [ + "cfg-if 0.1.10", + "libc 0.1.0", +] [[package]] name = "unwind_backtrace" version = "0.0.0" - -[metadata] -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" -"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" -"checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba" -"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" -"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -"checksum cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a" -"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" -"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" -"checksum fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=b8a6d8f)" = "" -"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" -"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" -"checksum log_buffer 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f033173c9486b7fe97a79c895c0a3483ae395ab6744c985d10078950e2492419" -"checksum managed 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba6713e624266d7600e9feae51b1926c6a6a6bebb18ec5a8e11a5f1d5661baba" -"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0fe46639fd2ec79eadf8fe719f237a7a0bd4dac5d957f1ca5bbdbc1c3c39e53a" -"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" -"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +dependencies = [ + "libc 0.1.0", + "unwind", +] From 5d0a8cf9ac918cf4f8b8269e07093679499bb8a6 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 25 Aug 2021 12:17:38 +0800 Subject: [PATCH 115/238] llvm_ir_gen: fix indent --- artiq/compiler/transforms/llvm_ir_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 149d45f4a..180560f47 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1111,7 +1111,7 @@ class LLVMIRGenerator: llnow_hi = self.llbuilder.lshr(llnow_raw, ll.Constant(lli64, 32)) return self.llbuilder.or_(llnow_lo, llnow_hi) else: - return self.llbuilder.load(self.llbuiltin("now"), name=insn.name) + return self.llbuilder.load(self.llbuiltin("now"), name=insn.name) else: return self.llbuilder.call(self.llbuiltin("now_mu"), []) elif insn.op == "at_mu": From 3e09e48152b0d6d4db2fc28bd3b49db5b58daa25 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 25 Aug 2021 12:49:05 +0800 Subject: [PATCH 116/238] flake: set up Vivado --- flake.nix | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/flake.nix b/flake.nix index 4c031cf7b..d72123cf6 100644 --- a/flake.nix +++ b/flake.nix @@ -170,6 +170,26 @@ }; }; + vivado = pkgs.buildFHSUserEnv { + name = "vivado"; + targetPkgs = pkgs: ( + with pkgs; [ + ncurses5 + zlib + libuuid + xorg.libSM + xorg.libICE + xorg.libXrender + xorg.libX11 + xorg.libXext + xorg.libXtst + xorg.libXi + ] + ); + profile = "source /opt/Xilinx/Vivado/2020.1/settings64.sh"; + runScript = "vivado"; + }; + defaultPackage.x86_64-linux = pkgs.python3.withPackages(ps: [ packages.x86_64-linux.artiq ]); devShell.x86_64-linux = pkgs.mkShell { @@ -181,6 +201,7 @@ pkgs.llvmPackages_11.clang-unwrapped pkgs.llvm_11 pkgs.lld_11 + vivado ]; TARGET_AR="llvm-ar"; }; @@ -193,5 +214,6 @@ nixConfig = { binaryCachePublicKeys = ["nixbld.m-labs.hk-1:5aSRVA5b320xbNvu30tqxVPXpld73bhtOeH6uAjRyHc="]; binaryCaches = ["https://nixbld.m-labs.hk" "https://cache.nixos.org"]; + sandboxPaths = ["/opt"]; }; } From 9addd08587a6c9d38ee2caf9afc1468c288bffa1 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 25 Aug 2021 12:49:18 +0800 Subject: [PATCH 117/238] flake: fetch MiSoC submodules --- flake.lock | 16 +++++++++------- flake.nix | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/flake.lock b/flake.lock index eeb43998d..7d76d397a 100644 --- a/flake.lock +++ b/flake.lock @@ -62,16 +62,18 @@ "flake": false, "locked": { "lastModified": 1629858538, - "narHash": "sha256-jdrZPKYqdn0A1GfLBUIhwZ7j5Rj+e5ablHotsK8SXbY=", - "owner": "m-labs", - "repo": "misoc", + "narHash": "sha256-5i0Q71OPJN7poredqT5bTNv10BUqNaoAmnr7nV8cODA=", + "ref": "master", "rev": "51830eab6849c15210825636fe2389cccebda493", - "type": "github" + "revCount": 2368, + "submodules": true, + "type": "git", + "url": "https://github.com/m-labs/misoc.git" }, "original": { - "owner": "m-labs", - "repo": "misoc", - "type": "github" + "submodules": true, + "type": "git", + "url": "https://github.com/m-labs/misoc.git" } }, "src-pythonparser": { diff --git a/flake.nix b/flake.nix index d72123cf6..49c2bc6f4 100644 --- a/flake.nix +++ b/flake.nix @@ -7,7 +7,7 @@ inputs.src-pythonparser = { url = github:m-labs/pythonparser; flake = false; }; inputs.src-migen = { url = github:m-labs/migen; flake = false; }; - inputs.src-misoc = { url = github:m-labs/misoc; flake = false; }; + inputs.src-misoc = { type = "git"; url = "https://github.com/m-labs/misoc.git"; submodules = true; flake = false; }; outputs = { self, nixpkgs, mozilla-overlay, src-sipyco, src-pythonparser, src-migen, src-misoc }: let From 035d15af9d9477b230523293d70de31cae2e9bbb Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 25 Aug 2021 13:22:44 +0800 Subject: [PATCH 118/238] flake: clean up vivado, add installer environment --- flake.nix | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/flake.nix b/flake.nix index 49c2bc6f4..a8ca18971 100644 --- a/flake.nix +++ b/flake.nix @@ -29,6 +29,18 @@ rustc = rust; cargo = rust; }); + vivadoDeps = pkgs: with pkgs; [ + ncurses5 + zlib + libuuid + xorg.libSM + xorg.libICE + xorg.libXrender + xorg.libX11 + xorg.libXext + xorg.libXtst + xorg.libXi + ]; in rec { packages.x86_64-linux = rec { sipyco = pkgs.python3Packages.buildPythonPackage { @@ -168,26 +180,18 @@ doCheck = false; # TODO: fix misoc bitrot and re-enable tests propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ]; }; - }; - vivado = pkgs.buildFHSUserEnv { - name = "vivado"; - targetPkgs = pkgs: ( - with pkgs; [ - ncurses5 - zlib - libuuid - xorg.libSM - xorg.libICE - xorg.libXrender - xorg.libX11 - xorg.libXext - xorg.libXtst - xorg.libXi - ] - ); - profile = "source /opt/Xilinx/Vivado/2020.1/settings64.sh"; - runScript = "vivado"; + vivadoEnv = pkgs.buildFHSUserEnv { + name = "vivado-env"; + targetPkgs = vivadoDeps; + }; + + vivado = pkgs.buildFHSUserEnv { + name = "vivado"; + targetPkgs = vivadoDeps; + profile = "source /opt/Xilinx/Vivado/2020.1/settings64.sh"; + runScript = "vivado"; + }; }; defaultPackage.x86_64-linux = pkgs.python3.withPackages(ps: [ packages.x86_64-linux.artiq ]); @@ -201,7 +205,9 @@ pkgs.llvmPackages_11.clang-unwrapped pkgs.llvm_11 pkgs.lld_11 - vivado + # use the vivado-env command to enter a FHS shell that lets you run the Vivado installer + packages.x86_64-linux.vivadoEnv + packages.x86_64-linux.vivado ]; TARGET_AR="llvm-ar"; }; From 1da0554a497552346a506cefaddc2458f94b0430 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 25 Aug 2021 15:11:58 +0800 Subject: [PATCH 119/238] pcr: purge --- artiq/coredevice/pcu.py | 77 ---------------------------- artiq/coredevice/spr.py | 12 ----- artiq/firmware/libboard_artiq/pcr.rs | 44 ---------------- 3 files changed, 133 deletions(-) delete mode 100644 artiq/coredevice/pcu.py delete mode 100644 artiq/coredevice/spr.py delete mode 100644 artiq/firmware/libboard_artiq/pcr.rs diff --git a/artiq/coredevice/pcu.py b/artiq/coredevice/pcu.py deleted file mode 100644 index 6dd1ff150..000000000 --- a/artiq/coredevice/pcu.py +++ /dev/null @@ -1,77 +0,0 @@ -from .spr import mtspr, mfspr -from artiq.language.core import kernel - - -_MAX_SPRS_PER_GRP_BITS = 11 -_SPRGROUP_PC = 7 << _MAX_SPRS_PER_GRP_BITS -_SPR_PCMR_CP = 0x00000001 # Counter present -_SPR_PCMR_CISM = 0x00000004 # Count in supervisor mode -_SPR_PCMR_CIUM = 0x00000008 # Count in user mode -_SPR_PCMR_LA = 0x00000010 # Load access event -_SPR_PCMR_SA = 0x00000020 # Store access event -_SPR_PCMR_IF = 0x00000040 # Instruction fetch event -_SPR_PCMR_DCM = 0x00000080 # Data cache miss event -_SPR_PCMR_ICM = 0x00000100 # Insn cache miss event -_SPR_PCMR_IFS = 0x00000200 # Insn fetch stall event -_SPR_PCMR_LSUS = 0x00000400 # LSU stall event -_SPR_PCMR_BS = 0x00000800 # Branch stall event -_SPR_PCMR_DTLBM = 0x00001000 # DTLB miss event -_SPR_PCMR_ITLBM = 0x00002000 # ITLB miss event -_SPR_PCMR_DDS = 0x00004000 # Data dependency stall event -_SPR_PCMR_WPE = 0x03ff8000 # Watchpoint events - - -@kernel(flags={"nowrite", "nounwind"}) -def _PCCR(n): - return _SPRGROUP_PC + n - - -@kernel(flags={"nowrite", "nounwind"}) -def _PCMR(n): - return _SPRGROUP_PC + 8 + n - - -class CorePCU: - """Core device performance counter unit (PCU) access""" - def __init__(self, dmgr, core_device="core"): - self.core = dmgr.get(core_device) - - @kernel - def start(self): - """ - Configure and clear the kernel CPU performance counters. - - The eight counters are configured to count the following events: - * Load or store - * Instruction fetch - * Data cache miss - * Instruction cache miss - * Instruction fetch stall - * Load-store-unit stall - * Branch stall - * Data dependency stall - """ - for i in range(8): - if not mfspr(_PCMR(i)) & _SPR_PCMR_CP: - raise ValueError("counter not present") - mtspr(_PCMR(i), 0) - mtspr(_PCCR(i), 0) - mtspr(_PCMR(0), _SPR_PCMR_CISM | _SPR_PCMR_LA | _SPR_PCMR_SA) - mtspr(_PCMR(1), _SPR_PCMR_CISM | _SPR_PCMR_IF) - mtspr(_PCMR(2), _SPR_PCMR_CISM | _SPR_PCMR_DCM) - mtspr(_PCMR(3), _SPR_PCMR_CISM | _SPR_PCMR_ICM) - mtspr(_PCMR(4), _SPR_PCMR_CISM | _SPR_PCMR_IFS) - mtspr(_PCMR(5), _SPR_PCMR_CISM | _SPR_PCMR_LSUS) - mtspr(_PCMR(6), _SPR_PCMR_CISM | _SPR_PCMR_BS) - mtspr(_PCMR(7), _SPR_PCMR_CISM | _SPR_PCMR_DDS) - - @kernel - def get(self, r): - """ - Read the performance counters and store the counts in the - array provided. - - :param list[int] r: array to store the counter values - """ - for i in range(8): - r[i] = mfspr(_PCCR(i)) diff --git a/artiq/coredevice/spr.py b/artiq/coredevice/spr.py deleted file mode 100644 index 4f968d794..000000000 --- a/artiq/coredevice/spr.py +++ /dev/null @@ -1,12 +0,0 @@ -from artiq.language.core import syscall -from artiq.language.types import TInt32, TNone - - -@syscall(flags={"nounwind", "nowrite"}) -def mfspr(spr: TInt32) -> TInt32: - raise NotImplementedError("syscall not simulated") - - -@syscall(flags={"nowrite", "nowrite"}) -def mtspr(spr: TInt32, value: TInt32) -> TNone: - raise NotImplementedError("syscall not simulated") diff --git a/artiq/firmware/libboard_artiq/pcr.rs b/artiq/firmware/libboard_artiq/pcr.rs deleted file mode 100644 index d16575398..000000000 --- a/artiq/firmware/libboard_artiq/pcr.rs +++ /dev/null @@ -1,44 +0,0 @@ -use board_misoc::spr::*; - -bitflags! { - pub struct Counters: u32 { - const LA = SPR_PCMR_LA; - const SA = SPR_PCMR_SA; - const IF = SPR_PCMR_IF; - const DCM = SPR_PCMR_DCM; - const ICM = SPR_PCMR_ICM; - const IFS = SPR_PCMR_IFS; - const LSUS = SPR_PCMR_LSUS; - const BS = SPR_PCMR_BS; - const DTLBM = SPR_PCMR_DTLBM; - const ITLBM = SPR_PCMR_ITLBM; - const DDS = SPR_PCMR_DDS; - - const INSTRN = Self::IF.bits; - const MEMORY = Self::LA.bits | Self::SA.bits; - const STALL = Self::DCM.bits | Self::ICM.bits | Self::IFS.bits | - Self::LSUS.bits | Self::BS.bits | Self::DDS.bits ; - const MISS = Self::DTLBM.bits | Self::ITLBM.bits ; - } -} - -fn is_valid(index: u32) -> bool { - index < 8 && unsafe { mfspr(SPR_PCMR0 + index) } & SPR_PCMR_CP != 0 -} - -#[inline] -pub fn setup(index: u32, counters: Counters) { - debug_assert!(is_valid(index)); - - unsafe { - mtspr(SPR_PCMR0 + index, SPR_PCMR_CISM | SPR_PCMR_CIUM | counters.bits); - mtspr(SPR_PCCR0 + index, 0); - } -} - -#[inline] -pub fn read(index: u32) -> u32 { - unsafe { - mfspr(SPR_PCCR0 + index) - } -} From eecd825d23f999a3891069cabff4f4ca1bbfcc20 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 25 Aug 2021 15:22:19 +0800 Subject: [PATCH 120/238] firmware: suppress warning --- artiq/firmware/bootloader/main.rs | 4 +- artiq/firmware/ksupport/eh_artiq.rs | 2 +- artiq/firmware/ksupport/lib.rs | 18 ++++----- artiq/firmware/libboard_artiq/lib.rs | 4 +- artiq/firmware/libboard_misoc/config.rs | 6 +-- artiq/firmware/libboard_misoc/sdram.rs | 14 +++---- artiq/firmware/libdyld/lib.rs | 4 +- artiq/firmware/libeh/eh_rust.rs | 3 -- artiq/firmware/libio/lib.rs | 1 - artiq/firmware/libproto_artiq/lib.rs | 1 - artiq/firmware/libproto_artiq/rpc_proto.rs | 12 +++--- artiq/firmware/runtime/main.rs | 47 ++++++++++------------ artiq/firmware/runtime/sched.rs | 4 +- artiq/firmware/satman/main.rs | 4 +- 14 files changed, 56 insertions(+), 68 deletions(-) diff --git a/artiq/firmware/bootloader/main.rs b/artiq/firmware/bootloader/main.rs index 865293840..b33722d5a 100644 --- a/artiq/firmware/bootloader/main.rs +++ b/artiq/firmware/bootloader/main.rs @@ -47,7 +47,7 @@ fn memory_test(total: &mut usize, wrong: &mut usize) -> bool { MEMORY[$index:expr] = $data:expr } ) => ({ - $prepare; + $prepare for $i in $range { unsafe { ptr::write_volatile(MEMORY.offset($index as isize), $data) }; *total += 1; @@ -56,7 +56,7 @@ fn memory_test(total: &mut usize, wrong: &mut usize) -> bool { cache::flush_cpu_dcache(); cache::flush_l2_cache(); - $prepare; + $prepare for $i in $range { if unsafe { ptr::read_volatile(MEMORY.offset($index as isize)) } != $data { *wrong += 1; diff --git a/artiq/firmware/ksupport/eh_artiq.rs b/artiq/firmware/ksupport/eh_artiq.rs index 471510930..f7923807a 100644 --- a/artiq/firmware/ksupport/eh_artiq.rs +++ b/artiq/firmware/ksupport/eh_artiq.rs @@ -8,7 +8,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(private_no_mangle_fns, non_camel_case_types)] +#![allow(non_camel_case_types)] use core::{ptr, mem}; use cslice::CSlice; diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index cf030b3a7..e3613d1dc 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -1,5 +1,5 @@ #![feature(lang_items, llvm_asm, panic_unwind, libc, unwind_attributes, - panic_handler, panic_info_message, nll)] + panic_info_message, nll)] #![no_std] extern crate libc; @@ -204,15 +204,13 @@ fn terminate(exception: &eh_artiq::Exception, backtrace: &mut [usize]) -> ! { #[unwind(aborts)] extern fn cache_get<'a>(ret: &'a mut CSlice, key: &CSlice) -> &'a CSlice<'a, i32> { - unsafe { - send(&CacheGetRequest { - key: str::from_utf8(key.as_ref()).unwrap() - }); - recv!(&CacheGetReply { value } => { - *ret = value.as_c_slice(); - ret - }) - } + send(&CacheGetRequest { + key: str::from_utf8(key.as_ref()).unwrap() + }); + recv!(&CacheGetReply { value } => { + *ret = value.as_c_slice(); + ret + }) } #[unwind(allowed)] diff --git a/artiq/firmware/libboard_artiq/lib.rs b/artiq/firmware/libboard_artiq/lib.rs index 1550db7dd..694805cfa 100644 --- a/artiq/firmware/libboard_artiq/lib.rs +++ b/artiq/firmware/libboard_artiq/lib.rs @@ -1,12 +1,10 @@ -#![feature(asm, lang_items, never_type)] +#![feature(lang_items, never_type)] #![no_std] extern crate failure; #[cfg(has_drtio)] #[macro_use] extern crate failure_derive; -#[macro_use] -extern crate bitflags; extern crate byteorder; extern crate crc; #[macro_use] diff --git a/artiq/firmware/libboard_misoc/config.rs b/artiq/firmware/libboard_misoc/config.rs index 7ed368efd..9a737e303 100644 --- a/artiq/firmware/libboard_misoc/config.rs +++ b/artiq/firmware/libboard_misoc/config.rs @@ -77,10 +77,10 @@ mod imp { mod lock { use core::slice; - use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; + use core::sync::atomic::{AtomicUsize, Ordering}; use super::Error; - static LOCKED: AtomicUsize = ATOMIC_USIZE_INIT; + static LOCKED: AtomicUsize = AtomicUsize::new(0); pub struct Lock; @@ -216,7 +216,7 @@ mod imp { let mut offset = 0; let mut iter = Iter::new(old_data); 'iter: while let Some(result) = iter.next() { - let (key, mut value) = result?; + let (key, value) = result?; if value.is_empty() { // This is a removed entry, ignore it. continue diff --git a/artiq/firmware/libboard_misoc/sdram.rs b/artiq/firmware/libboard_misoc/sdram.rs index 6e3071c4b..61951e725 100644 --- a/artiq/firmware/libboard_misoc/sdram.rs +++ b/artiq/firmware/libboard_misoc/sdram.rs @@ -31,7 +31,7 @@ mod ddr { } #[cfg(ddrphy_wlevel)] - unsafe fn write_level_scan(logger: &mut Option<&mut fmt::Write>) { + unsafe fn write_level_scan(logger: &mut Option<&mut dyn fmt::Write>) { #[cfg(kusddrphy)] log!(logger, "DQS initial delay: {} taps\n", ddrphy::wdly_dqs_taps_read()); log!(logger, "Write leveling scan:\n"); @@ -82,7 +82,7 @@ mod ddr { } #[cfg(ddrphy_wlevel)] - unsafe fn write_level(logger: &mut Option<&mut fmt::Write>, + unsafe fn write_level(logger: &mut Option<&mut dyn fmt::Write>, delay: &mut [u16; DQS_SIGNAL_COUNT], high_skew: &mut [bool; DQS_SIGNAL_COUNT]) -> bool { #[cfg(kusddrphy)] @@ -172,7 +172,7 @@ mod ddr { } #[cfg(ddrphy_wlevel)] - unsafe fn read_bitslip(logger: &mut Option<&mut fmt::Write>, + unsafe fn read_bitslip(logger: &mut Option<&mut dyn fmt::Write>, delay: &[u16; DQS_SIGNAL_COUNT], high_skew: &[bool; DQS_SIGNAL_COUNT]) { let threshold_opt = delay.iter().zip(high_skew.iter()) @@ -203,7 +203,7 @@ mod ddr { } } - unsafe fn read_level_scan(logger: &mut Option<&mut fmt::Write>) { + unsafe fn read_level_scan(logger: &mut Option<&mut dyn fmt::Write>) { log!(logger, "Read leveling scan:\n"); // Generate pseudo-random sequence @@ -286,7 +286,7 @@ mod ddr { spin_cycles(15); } - unsafe fn read_level(logger: &mut Option<&mut fmt::Write>) -> bool { + unsafe fn read_level(logger: &mut Option<&mut dyn fmt::Write>) -> bool { log!(logger, "Read leveling: "); // Generate pseudo-random sequence @@ -417,7 +417,7 @@ mod ddr { true } - pub unsafe fn level(logger: &mut Option<&mut fmt::Write>) -> bool { + pub unsafe fn level(logger: &mut Option<&mut dyn fmt::Write>) -> bool { #[cfg(ddrphy_wlevel)] { let mut delay = [0; DQS_SIGNAL_COUNT]; @@ -442,7 +442,7 @@ use core::fmt; use csr; use sdram_phy; -pub unsafe fn init(mut _logger: Option<&mut fmt::Write>) -> bool { +pub unsafe fn init(mut _logger: Option<&mut dyn fmt::Write>) -> bool { sdram_phy::initialize(); #[cfg(has_ddrphy)] diff --git a/artiq/firmware/libdyld/lib.rs b/artiq/firmware/libdyld/lib.rs index 8626b2920..5137b257b 100644 --- a/artiq/firmware/libdyld/lib.rs +++ b/artiq/firmware/libdyld/lib.rs @@ -159,7 +159,7 @@ impl<'a> Library<'a> { Ok(()) } - fn resolve_rela(&self, rela: &Elf32_Rela, resolve: &Fn(&[u8]) -> Option) + fn resolve_rela(&self, rela: &Elf32_Rela, resolve: &dyn Fn(&[u8]) -> Option) -> Result<(), Error<'a>> { let sym; if ELF32_R_SYM(rela.r_info) == 0 { @@ -204,7 +204,7 @@ impl<'a> Library<'a> { self.update_rela(rela, value) } - pub fn load(data: &[u8], image: &'a mut [u8], resolve: &Fn(&[u8]) -> Option) + pub fn load(data: &[u8], image: &'a mut [u8], resolve: &dyn Fn(&[u8]) -> Option) -> Result, Error<'a>> { #![allow(unused_assignments)] diff --git a/artiq/firmware/libeh/eh_rust.rs b/artiq/firmware/libeh/eh_rust.rs index 5692beb54..399ccdf6b 100644 --- a/artiq/firmware/libeh/eh_rust.rs +++ b/artiq/firmware/libeh/eh_rust.rs @@ -14,11 +14,8 @@ // // By design, this personality function is only ever called in the search phase, although // to keep things simple and close to upstream, it is not modified -#![allow(private_no_mangle_fns)] - use unwind as uw; use libc::{c_int, uintptr_t}; -use cslice::AsCSlice; use dwarf::{self, EHAction, EHContext}; diff --git a/artiq/firmware/libio/lib.rs b/artiq/firmware/libio/lib.rs index 235fd82c0..cb1c34002 100644 --- a/artiq/firmware/libio/lib.rs +++ b/artiq/firmware/libio/lib.rs @@ -1,6 +1,5 @@ #![no_std] #![feature(never_type)] -#![cfg_attr(feature = "alloc", feature(alloc))] extern crate failure; #[macro_use] diff --git a/artiq/firmware/libproto_artiq/lib.rs b/artiq/firmware/libproto_artiq/lib.rs index 66c04d5e6..d343d7d61 100644 --- a/artiq/firmware/libproto_artiq/lib.rs +++ b/artiq/firmware/libproto_artiq/lib.rs @@ -1,5 +1,4 @@ #![no_std] -#![cfg_attr(feature = "alloc", feature(alloc))] extern crate failure; #[macro_use] diff --git a/artiq/firmware/libproto_artiq/rpc_proto.rs b/artiq/firmware/libproto_artiq/rpc_proto.rs index bff4d46b0..0295b5297 100644 --- a/artiq/firmware/libproto_artiq/rpc_proto.rs +++ b/artiq/firmware/libproto_artiq/rpc_proto.rs @@ -18,7 +18,7 @@ unsafe fn align_ptr_mut(ptr: *mut ()) -> *mut T { } unsafe fn recv_value(reader: &mut R, tag: Tag, data: &mut *mut (), - alloc: &Fn(usize) -> Result<*mut (), E>) + alloc: &dyn Fn(usize) -> Result<*mut (), E>) -> Result<(), E> where R: Read + ?Sized, E: From> @@ -63,7 +63,7 @@ unsafe fn recv_value(reader: &mut R, tag: Tag, data: &mut *mut (), } Tag::List(it) => { #[repr(C)] - struct List { elements: *mut (), length: u32 }; + struct List { elements: *mut (), length: u32 } consume_value!(List, |ptr| { (*ptr).length = reader.read_u32()?; let length = (*ptr).length as usize; @@ -151,7 +151,7 @@ unsafe fn recv_value(reader: &mut R, tag: Tag, data: &mut *mut (), } pub fn recv_return(reader: &mut R, tag_bytes: &[u8], data: *mut (), - alloc: &Fn(usize) -> Result<*mut (), E>) + alloc: &dyn Fn(usize) -> Result<*mut (), E>) -> Result<(), E> where R: Read + ?Sized, E: From> @@ -208,7 +208,7 @@ unsafe fn send_value(writer: &mut W, tag: Tag, data: &mut *const ()) } Tag::List(it) => { #[repr(C)] - struct List { elements: *const (), length: u32 }; + struct List { elements: *const (), length: u32 } consume_value!(List, |ptr| { let length = (*ptr).length as usize; writer.write_u32((*ptr).length)?; @@ -287,7 +287,7 @@ unsafe fn send_value(writer: &mut W, tag: Tag, data: &mut *const ()) } Tag::Keyword(it) => { #[repr(C)] - struct Keyword<'a> { name: CSlice<'a, u8> }; + struct Keyword<'a> { name: CSlice<'a, u8> } consume_value!(Keyword, |ptr| { writer.write_string(str::from_utf8((*ptr).name.as_ref()).unwrap())?; let tag = it.clone().next().expect("truncated tag"); @@ -299,7 +299,7 @@ unsafe fn send_value(writer: &mut W, tag: Tag, data: &mut *const ()) } Tag::Object => { #[repr(C)] - struct Object { id: u32 }; + struct Object { id: u32 } consume_value!(*const Object, |ptr| writer.write_u32((**ptr).id)) } diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 17e4c0a42..5a8fdf3d7 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -1,5 +1,4 @@ -#![feature(lang_items, alloc, try_from, nonzero, asm, - panic_handler, panic_info_message)] +#![feature(lang_items, panic_info_message)] #![no_std] extern crate eh; @@ -280,32 +279,30 @@ pub struct TrapFrame { #[no_mangle] pub extern fn exception(regs: *const TrapFrame) { - unsafe { - let pc = mepc::read(); - let cause = mcause::read().cause(); - match cause { - mcause::Trap::Interrupt(source) => { - info!("Called interrupt with {:?}", source); - }, - mcause::Trap::Exception(e) => { - println!("Trap frame: {:x?}", unsafe { *regs }); + let pc = mepc::read(); + let cause = mcause::read().cause(); + match cause { + mcause::Trap::Interrupt(source) => { + info!("Called interrupt with {:?}", source); + }, + mcause::Trap::Exception(e) => { + println!("Trap frame: {:x?}", unsafe { *regs }); - fn hexdump(addr: u32) { - let addr = (addr - addr % 4) as *const u32; - let mut ptr = addr; - println!("@ {:08p}", ptr); - for _ in 0..4 { - print!("+{:04x}: ", ptr as usize - addr as usize); - print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); - print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); - print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); - print!("{:08x}\n", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); - } + fn hexdump(addr: u32) { + let addr = (addr - addr % 4) as *const u32; + let mut ptr = addr; + println!("@ {:08p}", ptr); + for _ in 0..4 { + print!("+{:04x}: ", ptr as usize - addr as usize); + print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); + print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); + print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); + print!("{:08x}\n", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); } - - hexdump(u32::try_from(pc).unwrap()); - panic!("exception {:?} at PC 0x{:x}", e, u32::try_from(pc).unwrap()) } + + hexdump(u32::try_from(pc).unwrap()); + panic!("exception {:?} at PC 0x{:x}", e, u32::try_from(pc).unwrap()) } } } diff --git a/artiq/firmware/runtime/sched.rs b/artiq/firmware/runtime/sched.rs index 43dae0f55..7b182a3e4 100644 --- a/artiq/firmware/runtime/sched.rs +++ b/artiq/firmware/runtime/sched.rs @@ -35,7 +35,7 @@ type SocketSet = ::smoltcp::socket::SocketSet<'static, 'static, 'static>; #[derive(Debug)] struct WaitRequest { - event: Option<*mut FnMut() -> bool>, + event: Option<*mut dyn FnMut() -> bool>, timeout: Option } @@ -240,7 +240,7 @@ impl<'a> Io<'a> { } pub fn until bool>(&self, mut f: F) -> Result<(), Error> { - let f = unsafe { mem::transmute::<&mut FnMut() -> bool, *mut FnMut() -> bool>(&mut f) }; + let f = unsafe { mem::transmute::<&mut dyn FnMut() -> bool, *mut dyn FnMut() -> bool>(&mut f) }; self.suspend(WaitRequest { timeout: None, event: Some(f) diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 4d1869bcd..f9e3d9e7c 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -539,7 +539,7 @@ pub extern fn main() -> i32 { } while !drtiosat_link_rx_up() { drtiosat_process_errors(); - for mut rep in repeaters.iter_mut() { + for rep in repeaters.iter_mut() { rep.service(&routing_table, rank); } #[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))] @@ -568,7 +568,7 @@ pub extern fn main() -> i32 { while drtiosat_link_rx_up() { drtiosat_process_errors(); process_aux_packets(&mut repeaters, &mut routing_table, &mut rank); - for mut rep in repeaters.iter_mut() { + for rep in repeaters.iter_mut() { rep.service(&routing_table, rank); } #[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))] From 798774192dc69a6e2963f1cbe1ee431269d8ce74 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 25 Aug 2021 15:23:22 +0800 Subject: [PATCH 121/238] slave_fpga/bootloader: read in little endian --- artiq/firmware/bootloader/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/bootloader/main.rs b/artiq/firmware/bootloader/main.rs index b33722d5a..1ef7426a1 100644 --- a/artiq/firmware/bootloader/main.rs +++ b/artiq/firmware/bootloader/main.rs @@ -121,8 +121,8 @@ fn load_slave_fpga() { const GATEWARE: *mut u8 = board_misoc::csr::CONFIG_SLAVE_FPGA_GATEWARE as *mut u8; let header = unsafe { slice::from_raw_parts(GATEWARE, 8) }; - let magic = BigEndian::read_u32(&header[0..]); - let length = BigEndian::read_u32(&header[4..]) as usize; + let magic = LittleEndian::read_u32(&header[0..]); + let length = LittleEndian::read_u32(&header[4..]) as usize; println!(" magic: 0x{:08x}, length: 0x{:08x}", magic, length); if magic != 0x5352544d { println!(" ...Error: bad magic"); From d8ac429059c9830245671c617cbbb071a3e6703a Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 27 Aug 2021 17:54:58 +0800 Subject: [PATCH 122/238] dyld: streamline lib.rs Only riscv32 is supported anyway, no need to have excessive architecture check. --- artiq/firmware/libdyld/lib.rs | 45 ++++++++++++++++------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/artiq/firmware/libdyld/lib.rs b/artiq/firmware/libdyld/lib.rs index 5137b257b..1fec38959 100644 --- a/artiq/firmware/libdyld/lib.rs +++ b/artiq/firmware/libdyld/lib.rs @@ -84,7 +84,6 @@ pub enum Arch { pub struct Library<'a> { image_off: Elf32_Addr, image_sz: usize, - arch: Arch, strtab: &'a [u8], symtab: &'a [Elf32_Sym], pltrel: &'a [Elf32_Rela], @@ -140,9 +139,8 @@ impl<'a> Library<'a> { // This is unsafe because it mutates global data (the PLT). pub unsafe fn rebind(&self, name: &[u8], addr: Elf32_Word) -> Result<(), Error<'a>> { for rela in self.pltrel.iter() { - match (ELF32_R_TYPE(rela.r_info), self.arch) { - (R_RISCV_32, Arch::RiscV) | - (R_RISCV_JUMP_SLOT, Arch::RiscV) => { + match ELF32_R_TYPE(rela.r_info) { + R_RISCV_32 | R_RISCV_JUMP_SLOT => { let sym = self.symtab.get(ELF32_R_SYM(rela.r_info) as usize) .ok_or("symbol out of bounds of symbol table")?; let sym_name = self.name_starting_at(sym.st_name as usize)?; @@ -170,15 +168,14 @@ impl<'a> Library<'a> { } let value; - match (ELF32_R_TYPE(rela.r_info), self.arch) { - (R_RISCV_NONE, Arch::RiscV) => + match ELF32_R_TYPE(rela.r_info) { + R_RISCV_NONE => return Ok(()), - (R_RISCV_RELATIVE, Arch::RiscV) => + R_RISCV_RELATIVE => value = self.image_off + rela.r_addend as Elf32_Word, - (R_RISCV_32, Arch::RiscV) | - (R_RISCV_JUMP_SLOT, Arch::RiscV) => { + R_RISCV_32 | R_RISCV_JUMP_SLOT => { let sym = sym.ok_or("relocation requires an associated symbol")?; let sym_name = self.name_starting_at(sym.st_name as usize)?; @@ -211,7 +208,20 @@ impl<'a> Library<'a> { let ehdr = read_unaligned::(data, 0) .map_err(|()| "cannot read ELF header")?; - let arch = arch(&ehdr).ok_or("not a shared library for current architecture")?; + const IDENT: [u8; EI_NIDENT] = [ + ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, + ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, + /* ABI version */ 0, /* padding */ 0, 0, 0, 0, 0, 0, 0 + ]; + + #[cfg(target_arch = "riscv32")] + const ARCH: u16 = EM_RISCV; + #[cfg(not(target_arch = "riscv32"))] + const ARCH: u16 = EM_NONE; + + if ehdr.e_ident != IDENT || ehdr.e_type != ET_DYN || ehdr.e_machine != ARCH { + return Err("not a shared library for current architecture")? + } let mut dyn_off = None; for i in 0..ehdr.e_phnum { @@ -310,7 +320,6 @@ impl<'a> Library<'a> { let library = Library { image_off: image.as_ptr() as Elf32_Word, image_sz: image.len(), - arch: arch, strtab: strtab, symtab: symtab, pltrel: pltrel, @@ -334,17 +343,3 @@ impl<'a> Library<'a> { Ok(library) } } - -fn arch(ehdr: &Elf32_Ehdr) -> Option { - const IDENT_RISCV: [u8; EI_NIDENT] = [ - ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, - ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, - /* ABI version */ 0, /* padding */ 0, 0, 0, 0, 0, 0, 0 - ]; - match (ehdr.e_ident, ehdr.e_machine) { - #[cfg(target_arch = "riscv32")] - (IDENT_RISCV, EM_RISCV) => Some(Arch::RiscV), - - _ => None, - } -} From 6db7280b092f861932ca79d41b36f4f2cd152635 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 29 Aug 2021 23:15:37 +0800 Subject: [PATCH 123/238] flake: board package WIP --- artiq/firmware/cargosha256.nix | 1 - flake.nix | 91 ++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) delete mode 100644 artiq/firmware/cargosha256.nix diff --git a/artiq/firmware/cargosha256.nix b/artiq/firmware/cargosha256.nix deleted file mode 100644 index 2bf5725cf..000000000 --- a/artiq/firmware/cargosha256.nix +++ /dev/null @@ -1 +0,0 @@ -"0ml6j4sxqrayqk25xkrikwg713mahfqa60nrx1jhrj8c2h3p07yk" diff --git a/flake.nix b/flake.nix index a8ca18971..97809bb63 100644 --- a/flake.nix +++ b/flake.nix @@ -41,6 +41,43 @@ xorg.libXtst xorg.libXi ]; + # TODO: cargo-vendor-normalise + fetchcargo = { name, src, sha256 }: + pkgs.stdenv.mkDerivation { + name = "${name}-vendor"; + strictDeps = true; + nativeBuildInputs = with pkgs; [ cacert git cargo ]; + inherit src; + + phases = "unpackPhase patchPhase installPhase"; + + installPhase = '' + if [[ ! -f Cargo.lock ]]; then + echo + echo "ERROR: The Cargo.lock file doesn't exist" + echo + echo "Cargo.lock is needed to make sure that cargoSha256 doesn't change" + echo "when the registry is updated." + echo + + exit 1 + fi + + mkdir -p $out + export CARGO_HOME=$(mktemp -d cargo-home.XXX) + + cargo vendor > $out/config + + cp -ar vendor $out/vendor + ''; + + outputHashAlgo = "sha256"; + outputHashMode = "recursive"; + outputHash = sha256; + + impureEnvVars = pkgs.lib.fetchers.proxyImpureEnvVars; + preferLocalBuild = true; + }; in rec { packages.x86_64-linux = rec { sipyco = pkgs.python3Packages.buildPythonPackage { @@ -192,6 +229,60 @@ profile = "source /opt/Xilinx/Vivado/2020.1/settings64.sh"; runScript = "vivado"; }; + + artiq-board-kc705-nist-clock = let + cargoVendored = fetchcargo { + name = "artiq-firmware-cargo-deps"; + src = "${self}/artiq/firmware"; + sha256 = "0vbh18v72y2qirba8sfg08kzx0crykg28jyi65mjpqacavfz89d8"; + }; + makeArtiqBoardPackage = { target, variant, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}" }: + pkgs.stdenv.mkDerivation { + name = "artiq-board-${target}-${variant}"; + phases = [ "buildPhase" "checkPhase" "installPhase" ]; + nativeBuildInputs = [ + (pkgs.python3.withPackages(ps: [ migen misoc artiq ])) + rustPlatform.rust.rustc + rustPlatform.rust.cargo + pkgs.llvmPackages_11.clang-unwrapped + pkgs.llvm_11 + pkgs.lld_11 + vivado + ]; + buildPhase = + '' + export CARGO_HOME=${cargoVendored} + export TARGET_AR=llvm-ar + ${buildCommand} + ''; + checkPhase = '' + # Search for PCREs in the Vivado output to check for errors + check_log() { + grep -Pe "$1" artiq_${target}/${variant}/gateware/vivado.log && exit 1 || true + } + check_log "\d+ constraint not met\." + check_log "Timing constraints are not met\." + ''; + installPhase = + '' + TARGET_DIR=$out + mkdir -p $TARGET_DIR + cp artiq_${target}/${variant}/gateware/top.bit $TARGET_DIR + if [ -e artiq_${target}/${variant}/software/bootloader/bootloader.bin ] + then cp artiq_${target}/${variant}/software/bootloader/bootloader.bin $TARGET_DIR + fi + if [ -e artiq_${target}/${variant}/software/runtime ] + then cp artiq_${target}/${variant}/software/runtime/runtime.{elf,fbi} $TARGET_DIR + else cp artiq_${target}/${variant}/software/satman/satman.{elf,fbi} $TARGET_DIR + fi + ''; + # don't mangle ELF files as they are not for NixOS + dontFixup = true; + }; + in makeArtiqBoardPackage { + target = "kc705"; + variant = "nist_clock"; + }; }; defaultPackage.x86_64-linux = pkgs.python3.withPackages(ps: [ packages.x86_64-linux.artiq ]); From 5985f7efb519a8111ffd1777bfa79a24e3abf5bf Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 30 Aug 2021 10:53:42 +0800 Subject: [PATCH 124/238] syscall: lower nowrite to inaccessiblememonly In the origin implementation, the `nowrite` flag literally means not writing memory at all. Due to the usage of flags on certain functions, it results in the same issues found in artiq-zynq after optimization passes. (https://git.m-labs.hk/M-Labs/artiq-zynq/issues/119) A fix wrote by @dnadlinger can resolve this issue. (https://github.com/dnadlinger/artiq/commit/c1e46cc7c8d9b2a4b58a45d6f5dabe65a127fb61) --- artiq/compiler/transforms/llvm_ir_generator.py | 15 ++------------- artiq/compiler/types.py | 2 +- artiq/coredevice/cache.py | 4 ++-- artiq/test/lit/embedding/syscall_flags.py | 4 ++-- 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 180560f47..970ade340 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -84,14 +84,6 @@ class LLVMIRGenerator: self.llobject_map = {} self.phis = [] self.empty_metadata = self.llmodule.add_metadata([]) - self.tbaa_tree = self.llmodule.add_metadata([ - ll.MetaDataString(self.llmodule, "ARTIQ TBAA") - ]) - self.tbaa_nowrite_call = self.llmodule.add_metadata([ - ll.MetaDataString(self.llmodule, "ref-only function call"), - self.tbaa_tree, - ll.Constant(lli64, 1) - ]) self.quote_fail_msg = None def needs_sret(self, lltyp, may_be_large=True): @@ -1207,6 +1199,8 @@ class LLVMIRGenerator: llfun.args[i].add_attribute('byval') if 'nounwind' in insn.target_function().type.flags: llfun.attributes.add('nounwind') + if 'nowrite' in insn.target_function().type.flags: + llfun.attributes.add('inaccessiblememonly') return llfun, list(llargs) @@ -1364,11 +1358,6 @@ class LLVMIRGenerator: # {} elsewhere. llresult = ll.Constant(llunit, []) - # Never add TBAA nowrite metadata to a functon with sret! - # This leads to miscompilations. - if types.is_external_function(functiontyp) and 'nowrite' in functiontyp.flags: - llcall.set_metadata('tbaa', self.tbaa_nowrite_call) - return llresult def process_Invoke(self, insn): diff --git a/artiq/compiler/types.py b/artiq/compiler/types.py index b5a220aeb..1d9336b4d 100644 --- a/artiq/compiler/types.py +++ b/artiq/compiler/types.py @@ -304,7 +304,7 @@ class TExternalFunction(TFunction): mangling rules). :ivar flags: (set of str) function flags. Flag ``nounwind`` means the function never raises an exception. - Flag ``nowrite`` means the function never writes any memory + Flag ``nowrite`` means the function never accesses any memory that the ARTIQ Python code can observe. :ivar broadcast_across_arrays: (bool) If True, the function is transparently applied element-wise when called diff --git a/artiq/coredevice/cache.py b/artiq/coredevice/cache.py index 7b01e96b9..6c222bb6f 100644 --- a/artiq/coredevice/cache.py +++ b/artiq/coredevice/cache.py @@ -2,11 +2,11 @@ from artiq.language.core import * from artiq.language.types import * -@syscall(flags={"nounwind", "nowrite"}) +@syscall(flags={"nounwind"}) def cache_get(key: TStr) -> TList(TInt32): raise NotImplementedError("syscall not simulated") -@syscall(flags={"nowrite"}) +@syscall def cache_put(key: TStr, value: TList(TInt32)) -> TNone: raise NotImplementedError("syscall not simulated") diff --git a/artiq/test/lit/embedding/syscall_flags.py b/artiq/test/lit/embedding/syscall_flags.py index 7d2a10341..f8c618c3f 100644 --- a/artiq/test/lit/embedding/syscall_flags.py +++ b/artiq/test/lit/embedding/syscall_flags.py @@ -4,9 +4,9 @@ from artiq.language.core import * from artiq.language.types import * -# CHECK: call void @foo\(\)(, !dbg !\d+)?, !tbaa !\d+ +# CHECK: call void @foo\(\)(, !dbg !\d+)? -# CHECK-L: ; Function Attrs: nounwind +# CHECK-L: ; Function Attrs: inaccessiblememonly nounwind # CHECK-NEXT-L: declare void @foo() @syscall(flags={"nounwind", "nowrite"}) From 4619a33db48c94f3312f31459050dbb83b1bacea Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 30 Aug 2021 13:10:02 +0800 Subject: [PATCH 125/238] test: remove broken array return tests Removed test cases that do not respect lifetime/scope constraint. See discussion in artiq-zynq repo: https://git.m-labs.hk/M-Labs/artiq-zynq/issues/119 Referred to the patch from @dnadlinger. https://github.com/dnadlinger/artiq/commit/5faa30a837790f373ab2c4063a298e2b9f818f62 --- artiq/test/coredevice/test_embedding.py | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/artiq/test/coredevice/test_embedding.py b/artiq/test/coredevice/test_embedding.py index cd8d4daab..8f5e4e3bc 100644 --- a/artiq/test/coredevice/test_embedding.py +++ b/artiq/test/coredevice/test_embedding.py @@ -261,19 +261,7 @@ class _RPCCalls(EnvExperiment): @kernel def numpy_things(self): - return (numpy.int32(10), numpy.int64(20), numpy.array([42,])) - - @kernel - def numpy_full(self): - return numpy.full(10, 20) - - @kernel - def numpy_full_matrix(self): - return numpy.full((3, 2), 13) - - @kernel - def numpy_nan(self): - return numpy.full(10, numpy.nan) + return (numpy.int32(10), numpy.int64(20)) @kernel def builtin(self): @@ -302,14 +290,11 @@ class RPCCallsTest(ExperimentCase): self.assertEqual(exp.kwargs2(), 2) self.assertEqual(exp.args1kwargs2(), 2) self.assertEqual(exp.numpy_things(), - (numpy.int32(10), numpy.int64(20), numpy.array([42,]))) + (numpy.int32(10), numpy.int64(20))) # Ensure lists of int64s don't decay to variable-length builtin integers. list_int64 = exp.list_int64() self.assertEqual(list_int64, [numpy.int64(1)]) self.assertTrue(isinstance(list_int64[0], numpy.int64)) - self.assertTrue((exp.numpy_full() == numpy.full(10, 20)).all()) - self.assertTrue((exp.numpy_full_matrix() == numpy.full((3, 2), 13)).all()) - self.assertTrue(numpy.isnan(exp.numpy_nan()).all()) exp.builtin() exp.async_in_try() From 9ee03bd4382259f1e49d1de8f1bc89bd0caf22b1 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 30 Aug 2021 13:25:50 +0800 Subject: [PATCH 126/238] flake: reenable lit test --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 97809bb63..0bde1c1f1 100644 --- a/flake.nix +++ b/flake.nix @@ -189,7 +189,7 @@ TESTDIR=`mktemp -d` cp --no-preserve=mode,ownership -R $src/artiq/test/lit $TESTDIR # FIXME: some tests fail - #LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so lit -v $TESTDIR/lit + LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so lit -v $TESTDIR/lit ''; }; From b7efb2f633aac6da76bd377ef77bfead24155067 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 30 Aug 2021 13:33:41 +0800 Subject: [PATCH 127/238] flake: remove outdated comment --- flake.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/flake.nix b/flake.nix index 0bde1c1f1..9885818ad 100644 --- a/flake.nix +++ b/flake.nix @@ -188,7 +188,6 @@ TESTDIR=`mktemp -d` cp --no-preserve=mode,ownership -R $src/artiq/test/lit $TESTDIR - # FIXME: some tests fail LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so lit -v $TESTDIR/lit ''; }; From eee80c7697ec4d374ba47d158b276ca139619a40 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 30 Aug 2021 13:52:56 +0800 Subject: [PATCH 128/238] flake: use improved Rust support in nixpkgs --- flake.nix | 53 ++++++++++------------------------------------------- 1 file changed, 10 insertions(+), 43 deletions(-) diff --git a/flake.nix b/flake.nix index 9885818ad..dc192e57b 100644 --- a/flake.nix +++ b/flake.nix @@ -41,43 +41,6 @@ xorg.libXtst xorg.libXi ]; - # TODO: cargo-vendor-normalise - fetchcargo = { name, src, sha256 }: - pkgs.stdenv.mkDerivation { - name = "${name}-vendor"; - strictDeps = true; - nativeBuildInputs = with pkgs; [ cacert git cargo ]; - inherit src; - - phases = "unpackPhase patchPhase installPhase"; - - installPhase = '' - if [[ ! -f Cargo.lock ]]; then - echo - echo "ERROR: The Cargo.lock file doesn't exist" - echo - echo "Cargo.lock is needed to make sure that cargoSha256 doesn't change" - echo "when the registry is updated." - echo - - exit 1 - fi - - mkdir -p $out - export CARGO_HOME=$(mktemp -d cargo-home.XXX) - - cargo vendor > $out/config - - cp -ar vendor $out/vendor - ''; - - outputHashAlgo = "sha256"; - outputHashMode = "recursive"; - outputHash = sha256; - - impureEnvVars = pkgs.lib.fetchers.proxyImpureEnvVars; - preferLocalBuild = true; - }; in rec { packages.x86_64-linux = rec { sipyco = pkgs.python3Packages.buildPythonPackage { @@ -230,15 +193,15 @@ }; artiq-board-kc705-nist-clock = let - cargoVendored = fetchcargo { - name = "artiq-firmware-cargo-deps"; - src = "${self}/artiq/firmware"; - sha256 = "0vbh18v72y2qirba8sfg08kzx0crykg28jyi65mjpqacavfz89d8"; - }; makeArtiqBoardPackage = { target, variant, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}" }: pkgs.stdenv.mkDerivation { name = "artiq-board-${target}-${variant}"; phases = [ "buildPhase" "checkPhase" "installPhase" ]; + cargoDeps = rustPlatform.fetchCargoTarball { + name = "artiq-firmware-cargo-deps"; + src = "${self}/artiq/firmware"; + sha256 = "sha256-ugTT1Vp/87rzAaZzFMMKadAM4UxBfXOwCEtrF6wU7Kc="; + }; nativeBuildInputs = [ (pkgs.python3.withPackages(ps: [ migen misoc artiq ])) rustPlatform.rust.rustc @@ -247,10 +210,14 @@ pkgs.llvm_11 pkgs.lld_11 vivado + rustPlatform.cargoSetupHook ]; buildPhase = '' - export CARGO_HOME=${cargoVendored} + ARTIQ_PATH=`python -c "import artiq; print(artiq.__path__[0])"` + ln -s $ARTIQ_PATH/firmware/Cargo.lock . + cargoSetupPostUnpackHook + cargoSetupPostPatchHook export TARGET_AR=llvm-ar ${buildCommand} ''; From 9697ec33eb25b00d0b505bf71a297489e7da8c5a Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 30 Aug 2021 14:14:34 +0800 Subject: [PATCH 129/238] flake: update dependencies --- flake.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index 7d76d397a..16acc6292 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1629772723, - "narHash": "sha256-/BQRsa1FsGb7v4xylPnHhU2/chw3EFbCv5/ZaY/eNsE=", + "lastModified": 1630076329, + "narHash": "sha256-mkxPL5pXZv8cfHgjSW0oWfZRGSSlGwXy/7KR+2Mgf3M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d5aadbefd650cb0a05ba9c788a26327afce2396c", + "rev": "74d017edb6717ad76d38edc02ad3210d4ad66b96", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1629858538, - "narHash": "sha256-5i0Q71OPJN7poredqT5bTNv10BUqNaoAmnr7nV8cODA=", + "lastModified": 1630291131, + "narHash": "sha256-28y+h7DKAlDjJohkcTVQNIr+r3BMV4R8V1BZkJ0aEx0=", "ref": "master", - "rev": "51830eab6849c15210825636fe2389cccebda493", - "revCount": 2368, + "rev": "354e1f3db04e28bcf6a002b4df6d4623fcc6265d", + "revCount": 2369, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From 9f6b3f6014ca53da669aeb0344195534efebf631 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 1 Sep 2021 17:43:41 +0800 Subject: [PATCH 130/238] firmware: clarify target triple The lack of compressed instruction support can be inferred from the target triple, literally. --- artiq/firmware/libboard_misoc/lib.rs | 2 +- .../{riscv32imac => riscv32ima}/boot.rs | 0 .../{riscv32imac => riscv32ima}/cache.rs | 0 .../{riscv32imac => riscv32ima}/mod.rs | 0 .../{riscv32imac => riscv32ima}/vectors.S | 0 .../firmware/riscv32ima-unknown-none-elf.json | 32 +++++++++++++++++++ 6 files changed, 33 insertions(+), 1 deletion(-) rename artiq/firmware/libboard_misoc/{riscv32imac => riscv32ima}/boot.rs (100%) rename artiq/firmware/libboard_misoc/{riscv32imac => riscv32ima}/cache.rs (100%) rename artiq/firmware/libboard_misoc/{riscv32imac => riscv32ima}/mod.rs (100%) rename artiq/firmware/libboard_misoc/{riscv32imac => riscv32ima}/vectors.S (100%) create mode 100644 artiq/firmware/riscv32ima-unknown-none-elf.json diff --git a/artiq/firmware/libboard_misoc/lib.rs b/artiq/firmware/libboard_misoc/lib.rs index 7057f10f2..729f4d63b 100644 --- a/artiq/firmware/libboard_misoc/lib.rs +++ b/artiq/firmware/libboard_misoc/lib.rs @@ -8,7 +8,7 @@ extern crate log; extern crate smoltcp; #[cfg(target_arch = "riscv32")] -#[path = "riscv32imac/mod.rs"] +#[path = "riscv32ima/mod.rs"] mod arch; #[cfg(target_arch = "riscv32")] diff --git a/artiq/firmware/libboard_misoc/riscv32imac/boot.rs b/artiq/firmware/libboard_misoc/riscv32ima/boot.rs similarity index 100% rename from artiq/firmware/libboard_misoc/riscv32imac/boot.rs rename to artiq/firmware/libboard_misoc/riscv32ima/boot.rs diff --git a/artiq/firmware/libboard_misoc/riscv32imac/cache.rs b/artiq/firmware/libboard_misoc/riscv32ima/cache.rs similarity index 100% rename from artiq/firmware/libboard_misoc/riscv32imac/cache.rs rename to artiq/firmware/libboard_misoc/riscv32ima/cache.rs diff --git a/artiq/firmware/libboard_misoc/riscv32imac/mod.rs b/artiq/firmware/libboard_misoc/riscv32ima/mod.rs similarity index 100% rename from artiq/firmware/libboard_misoc/riscv32imac/mod.rs rename to artiq/firmware/libboard_misoc/riscv32ima/mod.rs diff --git a/artiq/firmware/libboard_misoc/riscv32imac/vectors.S b/artiq/firmware/libboard_misoc/riscv32ima/vectors.S similarity index 100% rename from artiq/firmware/libboard_misoc/riscv32imac/vectors.S rename to artiq/firmware/libboard_misoc/riscv32ima/vectors.S diff --git a/artiq/firmware/riscv32ima-unknown-none-elf.json b/artiq/firmware/riscv32ima-unknown-none-elf.json new file mode 100644 index 000000000..ddacc0247 --- /dev/null +++ b/artiq/firmware/riscv32ima-unknown-none-elf.json @@ -0,0 +1,32 @@ +{ + "arch": "riscv32", + "cpu": "generic-rv32", + "data-layout": "e-m:e-p:32:32-i64:64-n32-S128", + "eh-frame-header": false, + "emit-debug-gdb-scripts": false, + "executables": true, + "features": "+m,+a,-c", + "is-builtin": false, + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "llvm-target": "riscv32", + "max-atomic-width": 32, + "panic-strategy": "unwind", + "relocation-model": "static", + "target-pointer-width": "32", + "unsupported-abis": [ + "cdecl", + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "aapcs", + "win64", + "sysv64", + "ptx-kernel", + "msp430-interrupt", + "x86-interrupt", + "amdgpu-kernel" + ] + } + \ No newline at end of file From dcbd9f905c3ea9b221eb94fe6c838c375a71ca4b Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 1 Sep 2021 17:45:27 +0800 Subject: [PATCH 131/238] cargo: use cargo xbuild --- artiq/firmware/bootloader/Makefile | 6 +++++- artiq/firmware/ksupport/Makefile | 6 +++++- artiq/firmware/runtime/Makefile | 6 +++++- artiq/firmware/satman/Makefile | 4 +++- flake.nix | 15 +++++++++++++++ 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/artiq/firmware/bootloader/Makefile b/artiq/firmware/bootloader/Makefile index 482aa3291..4dbd7b608 100644 --- a/artiq/firmware/bootloader/Makefile +++ b/artiq/firmware/bootloader/Makefile @@ -3,11 +3,15 @@ include $(MISOC_DIRECTORY)/software/common.mak RUSTFLAGS += -Cpanic=abort +export XBUILD_SYSROOT_PATH=$(BUILDINC_DIRECTORY)/../sysroot + all:: bootloader.bin .PHONY: $(RUSTOUT)/libbootloader.a $(RUSTOUT)/libbootloader.a: - $(cargo) --manifest-path $(BOOTLOADER_DIRECTORY)/Cargo.toml + $(cargo) --target-dir ./cargo \ + --manifest-path $(BOOTLOADER_DIRECTORY)/Cargo.toml \ + --target $(BOOTLOADER_DIRECTORY)/../riscv32ima-unknown-none-elf.json bootloader.elf: $(RUSTOUT)/libbootloader.a $(link) -T $(BOOTLOADER_DIRECTORY)/bootloader.ld diff --git a/artiq/firmware/ksupport/Makefile b/artiq/firmware/ksupport/Makefile index cfb79b3d6..f1fbfc19a 100644 --- a/artiq/firmware/ksupport/Makefile +++ b/artiq/firmware/ksupport/Makefile @@ -14,11 +14,15 @@ LDFLAGS += --eh-frame-hdr \ RUSTFLAGS += -Cpanic=unwind +export XBUILD_SYSROOT_PATH=$(BUILDINC_DIRECTORY)/../sysroot + all:: ksupport.elf .PHONY: $(RUSTOUT)/libksupport.a $(RUSTOUT)/libksupport.a: - $(cargo) --manifest-path $(KSUPPORT_DIRECTORY)/Cargo.toml + $(cargo) --target-dir ./cargo \ + --manifest-path $(KSUPPORT_DIRECTORY)/Cargo.toml \ + --target $(KSUPPORT_DIRECTORY)/../riscv32ima-unknown-none-elf.json ksupport.elf: $(RUSTOUT)/libksupport.a glue.o $(link) -T $(KSUPPORT_DIRECTORY)/ksupport.ld \ diff --git a/artiq/firmware/runtime/Makefile b/artiq/firmware/runtime/Makefile index 24ac19741..00506b2f3 100644 --- a/artiq/firmware/runtime/Makefile +++ b/artiq/firmware/runtime/Makefile @@ -10,11 +10,15 @@ LDFLAGS += \ RUSTFLAGS += -Cpanic=unwind +export XBUILD_SYSROOT_PATH=$(BUILDINC_DIRECTORY)/../sysroot + all:: runtime.bin runtime.fbi .PHONY: $(RUSTOUT)/libruntime.a $(RUSTOUT)/libruntime.a: - $(cargo) --manifest-path $(RUNTIME_DIRECTORY)/Cargo.toml + $(cargo) --target-dir ./cargo \ + --manifest-path $(RUNTIME_DIRECTORY)/Cargo.toml \ + --target $(RUNTIME_DIRECTORY)/../riscv32ima-unknown-none-elf.json runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o $(link) -T $(RUNTIME_DIRECTORY)/runtime.ld \ diff --git a/artiq/firmware/satman/Makefile b/artiq/firmware/satman/Makefile index 59f0f78f6..1f441c018 100644 --- a/artiq/firmware/satman/Makefile +++ b/artiq/firmware/satman/Makefile @@ -9,7 +9,9 @@ all:: satman.bin satman.fbi .PHONY: $(RUSTOUT)/libsatman.a $(RUSTOUT)/libsatman.a: - $(cargo) --manifest-path $(SATMAN_DIRECTORY)/Cargo.toml + $(cargo) --target-dir ./cargo \ + --manifest-path $(SATMAN_DIRECTORY)/Cargo.toml \ + --target $(SATMAN_DIRECTORY)/../riscv32ima-unknown-none-elf.json satman.elf: $(RUSTOUT)/libsatman.a $(link) -T $(SATMAN_DIRECTORY)/satman.ld diff --git a/flake.nix b/flake.nix index dc192e57b..3ad177a03 100644 --- a/flake.nix +++ b/flake.nix @@ -180,6 +180,20 @@ propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ]; }; + cargo-xbuild = rustPlatform.buildRustPackage rec { + pname = "cargo-xbuild"; + version = "0.6.5"; + + src = pkgs.fetchFromGitHub { + owner = "rust-osdev"; + repo = pname; + rev = "v${version}"; + sha256 = "18djvygq9v8rmfchvi2hfj0i6fhn36m716vqndqnj56fiqviwxvf"; + }; + + cargoSha256 = "13sj9j9kl6js75h9xq0yidxy63vixxm9q3f8jil6ymarml5wkhx8"; + }; + vivadoEnv = pkgs.buildFHSUserEnv { name = "vivado-env"; targetPkgs = vivadoDeps; @@ -211,6 +225,7 @@ pkgs.lld_11 vivado rustPlatform.cargoSetupHook + cargo-xbuild ]; buildPhase = '' From 4fab267593324d02431c22981b90d94a05d2b521 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 1 Sep 2021 17:48:18 +0800 Subject: [PATCH 132/238] cargo: std dependency hack --- artiq/firmware/Cargo.lock | 17 ++++++++++++----- artiq/firmware/libeh/Cargo.toml | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 4d390505a..194952672 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -92,9 +92,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cc" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" [[package]] name = "cfg-if" @@ -108,6 +108,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "compiler_builtins" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b" + [[package]] name = "crc" version = "1.8.1" @@ -131,6 +137,7 @@ version = "0.0.0" name = "eh" version = "0.0.0" dependencies = [ + "compiler_builtins", "cslice", "libc 0.1.0", "unwind", @@ -158,7 +165,7 @@ name = "fringe" version = "1.2.1" source = "git+https://git.m-labs.hk/M-Labs/libfringe.git?rev=9748bb#9748bb8af86c131d45be1238ea4d5f965a974630" dependencies = [ - "libc 0.2.100", + "libc 0.2.101", ] [[package]] @@ -199,9 +206,9 @@ version = "0.1.0" [[package]] name = "libc" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" +checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" [[package]] name = "log" diff --git a/artiq/firmware/libeh/Cargo.toml b/artiq/firmware/libeh/Cargo.toml index 6908c14b9..6998fcd35 100644 --- a/artiq/firmware/libeh/Cargo.toml +++ b/artiq/firmware/libeh/Cargo.toml @@ -11,3 +11,4 @@ path = "lib.rs" cslice = { version = "0.3" } libc = { path = "../libc" } unwind = { path = "../libunwind" } +compiler_builtins = "=0.1.39" # A dependency of alloc, libeh doesn't need it From ce0964e25f892136daf8cab5babe28dd066e717a Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 1 Sep 2021 18:40:32 +0800 Subject: [PATCH 133/238] flake: fix cargo sha256 --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 3ad177a03..dc709d245 100644 --- a/flake.nix +++ b/flake.nix @@ -214,7 +214,7 @@ cargoDeps = rustPlatform.fetchCargoTarball { name = "artiq-firmware-cargo-deps"; src = "${self}/artiq/firmware"; - sha256 = "sha256-ugTT1Vp/87rzAaZzFMMKadAM4UxBfXOwCEtrF6wU7Kc="; + sha256 = "0hh9x34gs81a8g15abka6a0z1wlankra13rbap5j7ba2r8cz4962"; }; nativeBuildInputs = [ (pkgs.python3.withPackages(ps: [ migen misoc artiq ])) From 7ae4b2d9bb7183e9a5b428dd573cd41bef5807ad Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 1 Sep 2021 18:40:49 +0800 Subject: [PATCH 134/238] flake: update dependencies --- flake.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index 16acc6292..19d65a762 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1630076329, - "narHash": "sha256-mkxPL5pXZv8cfHgjSW0oWfZRGSSlGwXy/7KR+2Mgf3M=", + "lastModified": 1630424636, + "narHash": "sha256-TKzxyJ1r5zflL0yewsA3tHq/2A64eNm5hkgO/nhwbFg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "74d017edb6717ad76d38edc02ad3210d4ad66b96", + "rev": "4b7e51865e44d3afc564e3a3111af12be1003251", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1630291131, - "narHash": "sha256-28y+h7DKAlDjJohkcTVQNIr+r3BMV4R8V1BZkJ0aEx0=", + "lastModified": 1630492353, + "narHash": "sha256-U5Boja6zmoUzL8idMuLKLU+zhcqo0GXWzQgmdsncSFU=", "ref": "master", - "rev": "354e1f3db04e28bcf6a002b4df6d4623fcc6265d", - "revCount": 2369, + "rev": "1775078bb42f7db7a5172c4603017dce55e302e5", + "revCount": 2370, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From 952acce65ba81a6c89fc07c36a55bcd40cba6bb4 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 1 Sep 2021 18:41:54 +0800 Subject: [PATCH 135/238] flake: build board package on Hydra --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index dc709d245..a94290e69 100644 --- a/flake.nix +++ b/flake.nix @@ -285,7 +285,7 @@ }; hydraJobs = { - artiq = packages.x86_64-linux.artiq; + inherit (packages.x86_64-linux) artiq artiq-board-kc705-nist-clock; }; }; From 64ce7e498be29b2b8c32f02c988868babdc58c99 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 1 Sep 2021 18:46:23 +0800 Subject: [PATCH 136/238] flake: make board package a Python package --- flake.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index a94290e69..0ac1723f8 100644 --- a/flake.nix +++ b/flake.nix @@ -208,7 +208,7 @@ artiq-board-kc705-nist-clock = let makeArtiqBoardPackage = { target, variant, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}" }: - pkgs.stdenv.mkDerivation { + pkgs.python3Packages.toPythonModule (pkgs.stdenv.mkDerivation { name = "artiq-board-${target}-${variant}"; phases = [ "buildPhase" "checkPhase" "installPhase" ]; cargoDeps = rustPlatform.fetchCargoTarball { @@ -246,7 +246,7 @@ ''; installPhase = '' - TARGET_DIR=$out + TARGET_DIR=$out/${pkgs.python3Packages.python.sitePackages}/artiq/board-support/${target}-${variant} mkdir -p $TARGET_DIR cp artiq_${target}/${variant}/gateware/top.bit $TARGET_DIR if [ -e artiq_${target}/${variant}/software/bootloader/bootloader.bin ] @@ -259,7 +259,7 @@ ''; # don't mangle ELF files as they are not for NixOS dontFixup = true; - }; + }); in makeArtiqBoardPackage { target = "kc705"; variant = "nist_clock"; From 5e2664ae7e7e2dd319110548818c65967d1034af Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 2 Sep 2021 11:18:58 +0800 Subject: [PATCH 137/238] flake: add openocd --- flake.nix | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 0ac1723f8..d67076f9b 100644 --- a/flake.nix +++ b/flake.nix @@ -264,6 +264,36 @@ target = "kc705"; variant = "nist_clock"; }; + + openocd-bscanspi = let + bscan_spi_bitstreams-pkg = pkgs.stdenv.mkDerivation { + name = "bscan_spi_bitstreams"; + src = pkgs.fetchFromGitHub { + owner = "quartiq"; + repo = "bscan_spi_bitstreams"; + rev = "01d8f819f15baf9a8cc5d96945a51e4d267ff564"; + sha256 = "1zqv47kzgvbn4c8cr019a6wcja7gn5h1z4kvw5bhpc72fyhagal9"; + }; + phases = ["installPhase"]; + installPhase = + '' + mkdir -p $out/share/bscan-spi-bitstreams + cp $src/*.bit $out/share/bscan-spi-bitstreams + ''; + }; + # https://docs.lambdaconcept.com/screamer/troubleshooting.html#error-contents-differ + openocd-fixed = pkgs.openocd.overrideAttrs(oa: { + patches = oa.patches or [] ++ [ + (pkgs.fetchurl { + url = "https://docs.lambdaconcept.com/screamer/_downloads/f0357c5f44c3c8c49f575cee5b6634a8/flashid.patch"; + sha256 = "015h4fzdrpwy5ssqbpk826snnfkkqijkmjzr5ws0a2v0ci97jzm9"; + }) + ]; + }); + in pkgs.buildEnv { + name = "openocd-bscanspi"; + paths = [ openocd-fixed bscan_spi_bitstreams-pkg ]; + }; }; defaultPackage.x86_64-linux = pkgs.python3.withPackages(ps: [ packages.x86_64-linux.artiq ]); @@ -271,7 +301,7 @@ devShell.x86_64-linux = pkgs.mkShell { name = "artiq-dev-shell"; buildInputs = [ - (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ])) + (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ps.paramiko ])) rustPlatform.rust.rustc rustPlatform.rust.cargo pkgs.llvmPackages_11.clang-unwrapped @@ -280,12 +310,13 @@ # use the vivado-env command to enter a FHS shell that lets you run the Vivado installer packages.x86_64-linux.vivadoEnv packages.x86_64-linux.vivado + packages.x86_64-linux.openocd-bscanspi ]; TARGET_AR="llvm-ar"; }; hydraJobs = { - inherit (packages.x86_64-linux) artiq artiq-board-kc705-nist-clock; + inherit (packages.x86_64-linux) artiq artiq-board-kc705-nist-clock openocd-bscanspi; }; }; From 17b9d2fc5a121b3357bfd2597bc57da02ba73869 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 2 Sep 2021 11:30:22 +0800 Subject: [PATCH 138/238] flake: add KC705 HITL test --- flake.nix | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index d67076f9b..d9757df96 100644 --- a/flake.nix +++ b/flake.nix @@ -206,7 +206,7 @@ runScript = "vivado"; }; - artiq-board-kc705-nist-clock = let + artiq-board-kc705-nist_clock = let makeArtiqBoardPackage = { target, variant, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}" }: pkgs.python3Packages.toPythonModule (pkgs.stdenv.mkDerivation { name = "artiq-board-${target}-${variant}"; @@ -316,7 +316,56 @@ }; hydraJobs = { - inherit (packages.x86_64-linux) artiq artiq-board-kc705-nist-clock openocd-bscanspi; + inherit (packages.x86_64-linux) artiq artiq-board-kc705-nist_clock openocd-bscanspi; + kc705-hitl = pkgs.stdenv.mkDerivation { + name = "kc705-hitl"; + + # requires patched Nix + __networked = true; + + buildInputs = [ + (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ artiq artiq-board-kc705-nist_clock ps.paramiko ])) + pkgs.lld_11 + pkgs.openssh + ]; + phases = [ "buildPhase" ]; + buildPhase = + '' + export HOME=`mktemp -d` + mkdir $HOME/.ssh + cp /opt/hydra_id_rsa $HOME/.ssh/id_rsa + cp /opt/hydra_id_rsa.pub $HOME/.ssh/id_rsa.pub + echo "rpi-1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPOBQVcsvk6WgRj18v4m0zkFeKrcN9gA+r6sxQxNwFpv" > $HOME/.ssh/known_hosts + chmod 600 $HOME/.ssh/id_rsa + LOCKCTL=$(mktemp -d) + mkfifo $LOCKCTL/lockctl + + cat $LOCKCTL/lockctl | ${pkgs.openssh}/bin/ssh \ + -i $HOME/.ssh/id_rsa \ + -o UserKnownHostsFile=$HOME/.ssh/known_hosts \ + rpi-1 \ + 'mkdir -p /tmp/board_lock && flock /tmp/board_lock/kc705-1 -c "echo Ok; cat"' \ + | ( + # End remote flock via FIFO + atexit_unlock() { + echo > $LOCKCTL/lockctl + } + trap atexit_unlock EXIT + + # Read "Ok" line when remote successfully locked + read LOCK_OK + + artiq_flash -t kc705 -H rpi-1 + sleep 15 + + export ARTIQ_ROOT=`python -c "import artiq; print(artiq.__path__[0])"`/examples/kc705_nist_clock + export ARTIQ_LOW_LATENCY=1 + python -m unittest discover -v artiq.test.coredevice + ) + + touch $out + ''; + }; }; }; From c78fbe9bd23733d97ac5e778698aafdc0038fe08 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 2 Sep 2021 11:31:34 +0800 Subject: [PATCH 139/238] flake: make bscanspi bitstreams available in HITL test --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index d9757df96..719be5abe 100644 --- a/flake.nix +++ b/flake.nix @@ -327,6 +327,7 @@ (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ artiq artiq-board-kc705-nist_clock ps.paramiko ])) pkgs.lld_11 pkgs.openssh + packages.x86_64-linux.openocd-bscanspi # for the bscanspi bitstreams ]; phases = [ "buildPhase" ]; buildPhase = From eff7ae5aff3aef4c11a4ad44f7d89693c14115d4 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 2 Sep 2021 11:42:01 +0800 Subject: [PATCH 140/238] flake: make llvm-strip in HITL test --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 719be5abe..fa984ea53 100644 --- a/flake.nix +++ b/flake.nix @@ -325,6 +325,7 @@ buildInputs = [ (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ artiq artiq-board-kc705-nist_clock ps.paramiko ])) + pkgs.llvm_11 pkgs.lld_11 pkgs.openssh packages.x86_64-linux.openocd-bscanspi # for the bscanspi bitstreams From a596db404dc77085ced2279ecb62adad29458147 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 2 Sep 2021 14:13:22 +0800 Subject: [PATCH 141/238] satman: fix cargo xbuild sysroot --- artiq/firmware/satman/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/artiq/firmware/satman/Makefile b/artiq/firmware/satman/Makefile index 1f441c018..7c3885c87 100644 --- a/artiq/firmware/satman/Makefile +++ b/artiq/firmware/satman/Makefile @@ -5,6 +5,8 @@ LDFLAGS += -L../libbase RUSTFLAGS += -Cpanic=abort +export XBUILD_SYSROOT_PATH=$(BUILDINC_DIRECTORY)/../sysroot + all:: satman.bin satman.fbi .PHONY: $(RUSTOUT)/libsatman.a From c812a837ab9a4b4332673f20103170c645a2c29e Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 2 Sep 2021 14:13:52 +0800 Subject: [PATCH 142/238] runtime: enlarge stack size --- artiq/firmware/runtime/runtime.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/runtime/runtime.ld b/artiq/firmware/runtime/runtime.ld index 57d76ee45..b1a7ad7e3 100644 --- a/artiq/firmware/runtime/runtime.ld +++ b/artiq/firmware/runtime/runtime.ld @@ -71,7 +71,7 @@ SECTIONS .stack (NOLOAD) : ALIGN(16) { - . += 0x4000; + . += 0x10000; _fstack = . - 16; } > runtime From c6ba0f3cf4413e8b35f4598c7bb42ac9ad83e274 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 2 Sep 2021 14:18:22 +0800 Subject: [PATCH 143/238] ksupport: fix dma cslice (ffi) --- artiq/firmware/ksupport/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index e3613d1dc..227816049 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -248,7 +248,7 @@ fn dma_record_flush() { } #[unwind(allowed)] -extern fn dma_record_start(name: CSlice) { +extern fn dma_record_start(name: &CSlice) { let name = str::from_utf8(name.as_ref()).unwrap(); unsafe { @@ -360,7 +360,7 @@ extern fn dma_record_output_wide(target: i32, words: CSlice) { } #[unwind(aborts)] -extern fn dma_erase(name: CSlice) { +extern fn dma_erase(name: &CSlice) { let name = str::from_utf8(name.as_ref()).unwrap(); send(&DmaEraseRequest { name: name }); @@ -373,7 +373,7 @@ struct DmaTrace { } #[unwind(allowed)] -extern fn dma_retrieve(name: CSlice) -> DmaTrace { +extern fn dma_retrieve(name: &CSlice) -> DmaTrace { let name = str::from_utf8(name.as_ref()).unwrap(); send(&DmaRetrieveRequest { name: name }); From 051a14abf22395cd7d80defa5d0eb4c799921b54 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 3 Sep 2021 16:05:17 +0800 Subject: [PATCH 144/238] rtio/dma: fix endianness --- artiq/gateware/rtio/dma.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/artiq/gateware/rtio/dma.py b/artiq/gateware/rtio/dma.py index 20d558672..84f79dfa8 100644 --- a/artiq/gateware/rtio/dma.py +++ b/artiq/gateware/rtio/dma.py @@ -11,6 +11,26 @@ def _reverse_bytes(s, g): return Cat(reversed(list(s[i*g:(i+1)*g] for i in range(len(s)//g)))) +def reverse_bytes(s): + n = (len(s) + 7)//8 + return Cat(*[s[i*8:min((i + 1)*8, len(s))] + for i in reversed(range(n))]) + + +def convert_signal(signal): + assert len(signal) % 8 == 0 + nbytes = len(signal)//8 + assert nbytes % 4 == 0 + nwords = nbytes//4 + signal_words = [] + for i in range(nwords): + signal_bytes = [] + for j in range(4): + signal_bytes.append(signal[8*(j+i*4):8*((j+i*4)+1)]) + signal_words.extend(reversed(signal_bytes)) + return Cat(*signal_words) + + class WishboneReader(Module): def __init__(self, bus): self.bus = bus @@ -37,7 +57,7 @@ class WishboneReader(Module): If(self.source.ack, data_reg_loaded.eq(0)), If(bus.ack, data_reg_loaded.eq(1), - self.source.data.eq(bus.dat_r), + self.source.data.eq(convert_signal(bus.dat_r)), self.source.eop.eq(self.sink.eop) ) ] From 09ffd9de1e7192b1888ddfa76b1055b79e0a70f7 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 3 Sep 2021 16:05:58 +0800 Subject: [PATCH 145/238] dma: fix timestamp fetch --- artiq/firmware/ksupport/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 227816049..73bc3d284 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -329,7 +329,7 @@ unsafe fn dma_record_output_prepare(timestamp: i64, target: i32, #[unwind(aborts)] extern fn dma_record_output(target: i32, word: i32) { unsafe { - let timestamp = *(csr::rtio::NOW_HI_ADDR as *const i64); + let timestamp = ((csr::rtio::now_hi_read() as i64) << 32) | (csr::rtio::now_lo_read() as i64); let data = dma_record_output_prepare(timestamp, target, 1); data.copy_from_slice(&[ (word >> 0) as u8, @@ -345,7 +345,7 @@ extern fn dma_record_output_wide(target: i32, words: CSlice) { assert!(words.len() <= 16); // enforce the hardware limit unsafe { - let timestamp = *(csr::rtio::NOW_HI_ADDR as *const i64); + let timestamp = ((csr::rtio::now_hi_read() as i64) << 32) | (csr::rtio::now_lo_read() as i64); let mut data = dma_record_output_prepare(timestamp, target, words.len()); for word in words.as_ref().iter() { data[..4].copy_from_slice(&[ From 2213e7ffac275c724d13f093cbeba7a581b2aa4b Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 7 Sep 2021 13:16:00 +0800 Subject: [PATCH 146/238] ksupp/rtio/exception: fix timestamp --- artiq/firmware/ksupport/rtio.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/ksupport/rtio.rs b/artiq/firmware/ksupport/rtio.rs index a83a45ec1..8736e33f5 100644 --- a/artiq/firmware/ksupport/rtio.rs +++ b/artiq/firmware/ksupport/rtio.rs @@ -59,7 +59,7 @@ mod imp { #[inline(never)] unsafe fn process_exceptional_status(channel: i32, status: u8) { - let timestamp = *(csr::rtio::NOW_HI_ADDR as *const i64); + let timestamp = ((csr::rtio::now_hi_read() as i64) << 32) | (csr::rtio::now_lo_read() as i64); if status & RTIO_O_STATUS_WAIT != 0 { while csr::rtio::o_status_read() & RTIO_O_STATUS_WAIT != 0 {} } From b8ed5a0d917401d9efa45af6849654ed1874e34a Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 9 Sep 2021 10:20:04 +0800 Subject: [PATCH 147/238] alloc: fix alignment for riscv32 arch --- artiq/firmware/liballoc_list/lib.rs | 1 + artiq/firmware/runtime/runtime.ld | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/artiq/firmware/liballoc_list/lib.rs b/artiq/firmware/liballoc_list/lib.rs index 8af134b0e..f4d93310a 100644 --- a/artiq/firmware/liballoc_list/lib.rs +++ b/artiq/firmware/liballoc_list/lib.rs @@ -13,6 +13,7 @@ const MAGIC_BUSY: usize = 0xFEEDFEED; struct Header { magic: usize, size: usize, + _pad: usize, next: *mut Header } diff --git a/artiq/firmware/runtime/runtime.ld b/artiq/firmware/runtime/runtime.ld index b1a7ad7e3..81138fea3 100644 --- a/artiq/firmware/runtime/runtime.ld +++ b/artiq/firmware/runtime/runtime.ld @@ -75,7 +75,7 @@ SECTIONS _fstack = . - 16; } > runtime - .heap (NOLOAD) : + .heap (NOLOAD) : ALIGN(16) { _fheap = .; . = ORIGIN(runtime) + LENGTH(runtime); From 5394d0466974179c73aff42f905cfae71d56f897 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 9 Sep 2021 10:34:44 +0800 Subject: [PATCH 148/238] test_spi: add delay --- artiq/test/coredevice/test_spi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/artiq/test/coredevice/test_spi.py b/artiq/test/coredevice/test_spi.py index 17bf6eeb6..0faf4677f 100644 --- a/artiq/test/coredevice/test_spi.py +++ b/artiq/test/coredevice/test_spi.py @@ -20,6 +20,7 @@ class CardTest(EnvExperiment): @kernel def run(self): self.core.reset() + delay(1*ms) freq = 1*MHz cs = 1 From d50e24acb1404b8f2021ed6af530e96436597dfb Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 10 Sep 2021 10:32:19 +0800 Subject: [PATCH 149/238] update dependencies --- flake.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index 19d65a762..e97a38179 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1630424636, - "narHash": "sha256-TKzxyJ1r5zflL0yewsA3tHq/2A64eNm5hkgO/nhwbFg=", + "lastModified": 1631098960, + "narHash": "sha256-6j6G/omHEFAnI2x7UvdrviGDNqiq1Fjd1A58Q6uc4sQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4b7e51865e44d3afc564e3a3111af12be1003251", + "rev": "12eb1d16ae3b6cbf0ea83e9228bca8ffd7cfe347", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1630492353, - "narHash": "sha256-U5Boja6zmoUzL8idMuLKLU+zhcqo0GXWzQgmdsncSFU=", + "lastModified": 1631240866, + "narHash": "sha256-dal999XLFvS8Ol1hZnQjx7q/UfAXkzSMhAWcZKCDPx4=", "ref": "master", - "rev": "1775078bb42f7db7a5172c4603017dce55e302e5", - "revCount": 2370, + "rev": "c9572e777febf7abcfbebf624e0323d82600f267", + "revCount": 2371, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From b091d8cb660bcfb48cb7b5d1672fed12ef330cbd Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 10 Sep 2021 11:07:51 +0800 Subject: [PATCH 150/238] kernel: flush cache before mod_init This could be necessary as redirecting instructions from D$ directly to I$ as it seems. Related: https://github.com/SpinalHDL/VexRiscv/issues/137 --- artiq/firmware/ksupport/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 73bc3d284..aaedbd018 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -498,6 +498,9 @@ pub unsafe fn main() { ptr::write_bytes(__bss_start as *mut u8, 0, (_end - __bss_start) as usize); + board_misoc::cache::flush_cpu_dcache(); + board_misoc::cache::flush_cpu_icache(); + (mem::transmute::(__modinit__))(); if let Some(typeinfo) = typeinfo { From 448974fe111cea91efa3223d3ddbc5ab68aea6a5 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 10 Sep 2021 13:59:53 +0800 Subject: [PATCH 151/238] runtime/main: cleanup --- artiq/firmware/runtime/main.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 5a8fdf3d7..c04ec3a05 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -322,8 +322,6 @@ pub fn oom(layout: core::alloc::Layout) -> ! { #[no_mangle] // https://github.com/rust-lang/rust/issues/{38281,51647} #[panic_handler] pub fn panic_impl(info: &core::panic::PanicInfo) -> ! { - // irq::set_ie(false); - #[cfg(has_error_led)] unsafe { csr::error_led::out_write(1); From a573dcf3f9a141204d287ed9effac2d1a119db59 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 10 Sep 2021 14:11:20 +0800 Subject: [PATCH 152/238] board_misoc/build: use rv32 as target arg The original rv64 argument was only to match the misoc counterpart. --- artiq/firmware/libboard_misoc/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/libboard_misoc/build.rs b/artiq/firmware/libboard_misoc/build.rs index efea565bf..8160db88a 100644 --- a/artiq/firmware/libboard_misoc/build.rs +++ b/artiq/firmware/libboard_misoc/build.rs @@ -13,7 +13,7 @@ fn main() { println!("cargo:rerun-if-changed={}", vectors_path.to_str().unwrap()); cc::Build::new() - .flag("--target=riscv64-unknown-elf") + .flag("--target=riscv32-unknown-elf") .file(vectors_path) .compile("vectors"); } From 2e5c32878fbe6ea3e6900ba088707238b74122a0 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 10 Sep 2021 17:19:32 +0800 Subject: [PATCH 153/238] flake: add other KC705 NIST builds --- flake.nix | 517 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 270 insertions(+), 247 deletions(-) diff --git a/flake.nix b/flake.nix index fa984ea53..69e07baa7 100644 --- a/flake.nix +++ b/flake.nix @@ -16,6 +16,7 @@ url = "https://static.rust-lang.org/dist/2021-01-29/channel-rust-nightly.toml"; sha256 = "sha256-EZKgw89AH4vxaJpUHmIMzMW/80wAFQlfcxRoBD9nz0c="; }; + targets = []; rustChannelOfTargets = _channel: _date: targets: (pkgs.lib.rustLib.fromManifestFile rustManifest { @@ -29,6 +30,7 @@ rustc = rust; cargo = rust; }); + vivadoDeps = pkgs: with pkgs; [ ncurses5 zlib @@ -41,258 +43,279 @@ xorg.libXtst xorg.libXi ]; + + sipyco = pkgs.python3Packages.buildPythonPackage { + name = "sipyco"; + src = src-sipyco; + propagatedBuildInputs = with pkgs.python3Packages; [ pybase64 numpy ]; + }; + + pythonparser = pkgs.python3Packages.buildPythonPackage { + name = "pythonparser"; + src = src-pythonparser; + doCheck = false; + propagatedBuildInputs = with pkgs.python3Packages; [ regex ]; + }; + + qasync = pkgs.python3Packages.buildPythonPackage rec { + pname = "qasync"; + version = "0.10.0"; + src = pkgs.fetchFromGitHub { + owner = "CabbageDevelopment"; + repo = "qasync"; + rev = "v${version}"; + sha256 = "1zga8s6dr7gk6awmxkh4pf25gbg8n6dv1j4b0by7y0fhi949qakq"; + }; + propagatedBuildInputs = [ pkgs.python3Packages.pyqt5 ]; + checkInputs = [ pkgs.python3Packages.pytest ]; + checkPhase = '' + pytest -k 'test_qthreadexec.py' # the others cause the test execution to be aborted, I think because of asyncio + ''; + }; + + outputcheck = pkgs.python3Packages.buildPythonApplication rec { + pname = "outputcheck"; + version = "0.4.2"; + src = pkgs.fetchFromGitHub { + owner = "stp"; + repo = "OutputCheck"; + rev = "e0f533d3c5af2949349856c711bf4bca50022b48"; + sha256 = "1y27vz6jq6sywas07kz3v01sqjd0sga9yv9w2cksqac3v7wmf2a0"; + }; + prePatch = "echo ${version} > RELEASE-VERSION"; + }; + + libartiq-support = pkgs.stdenv.mkDerivation { + name = "libartiq-support"; + src = self; + buildInputs = [ rustPlatform.rust.rustc ]; + buildPhase = '' + rustc $src/artiq/test/libartiq_support/lib.rs -Cpanic=unwind -g + ''; + installPhase = '' + mkdir $out + cp libartiq_support.so $out + ''; + }; + + llvmlite-new = pkgs.python3Packages.buildPythonPackage rec { + pname = "llvmlite"; + version = "0.37.0rc2"; + src = pkgs.python3Packages.fetchPypi { + inherit pname version; + sha256 = "sha256-F1quz+76JOt1jaQPVzdKe7RfN6gWG2lyE82qTvgyY/c="; + }; + nativeBuildInputs = [ pkgs.llvm_11 ]; + # Disable static linking + # https://github.com/numba/llvmlite/issues/93 + postPatch = '' + substituteInPlace ffi/Makefile.linux --replace "-static-libstdc++" "" + substituteInPlace llvmlite/tests/test_binding.py --replace "test_linux" "nope" + ''; + # Set directory containing llvm-config binary + preConfigure = '' + export LLVM_CONFIG=${pkgs.llvm_11.dev}/bin/llvm-config + ''; + doCheck = false; # FIXME + }; + + artiq = pkgs.python3Packages.buildPythonPackage rec { + pname = "artiq"; + version = "7.0-dev"; + src = self; + + preBuild = "export VERSIONEER_OVERRIDE=${version}"; + + nativeBuildInputs = [ pkgs.qt5.wrapQtAppsHook ]; + # keep llvm_x and lld_x in sync with llvmlite + propagatedBuildInputs = [ pkgs.llvm_11 pkgs.lld_11 llvmlite-new sipyco pythonparser ] + ++ (with pkgs.python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial python-Levenshtein h5py pyqt5 qasync ]); + + dontWrapQtApps = true; + postFixup = '' + wrapQtApp "$out/bin/artiq_dashboard" + wrapQtApp "$out/bin/artiq_browser" + wrapQtApp "$out/bin/artiq_session" + ''; + + # Modifies PATH to pass the wrapped python environment (i.e. python3.withPackages(...) to subprocesses. + # Allows subprocesses using python to find all packages you have installed + makeWrapperArgs = [ + ''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' '' + "--set FONTCONFIG_FILE ${pkgs.fontconfig.out}/etc/fonts/fonts.conf" + ]; + + # FIXME: automatically propagate lld_11 llvm_11 dependencies + checkInputs = [ pkgs.lld_11 pkgs.llvm_11 pkgs.lit outputcheck ]; + checkPhase = '' + python -m unittest discover -v artiq.test + + TESTDIR=`mktemp -d` + cp --no-preserve=mode,ownership -R $src/artiq/test/lit $TESTDIR + LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so lit -v $TESTDIR/lit + ''; + }; + + migen = pkgs.python3Packages.buildPythonPackage rec { + name = "migen"; + src = src-migen; + propagatedBuildInputs = [ pkgs.python3Packages.colorama ]; + }; + + asyncserial = pkgs.python3Packages.buildPythonPackage rec { + pname = "asyncserial"; + version = "0.1"; + src = pkgs.fetchFromGitHub { + owner = "m-labs"; + repo = "asyncserial"; + rev = "d95bc1d6c791b0e9785935d2f62f628eb5cdf98d"; + sha256 = "0yzkka9jk3612v8gx748x6ziwykq5lr7zmr9wzkcls0v2yilqx9k"; + }; + propagatedBuildInputs = [ pkgs.python3Packages.pyserial ]; + }; + + misoc = pkgs.python3Packages.buildPythonPackage { + name = "misoc"; + src = src-misoc; + doCheck = false; # TODO: fix misoc bitrot and re-enable tests + propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ]; + }; + + cargo-xbuild = rustPlatform.buildRustPackage rec { + pname = "cargo-xbuild"; + version = "0.6.5"; + + src = pkgs.fetchFromGitHub { + owner = "rust-osdev"; + repo = pname; + rev = "v${version}"; + sha256 = "18djvygq9v8rmfchvi2hfj0i6fhn36m716vqndqnj56fiqviwxvf"; + }; + + cargoSha256 = "13sj9j9kl6js75h9xq0yidxy63vixxm9q3f8jil6ymarml5wkhx8"; + }; + + vivadoEnv = pkgs.buildFHSUserEnv { + name = "vivado-env"; + targetPkgs = vivadoDeps; + }; + + vivado = pkgs.buildFHSUserEnv { + name = "vivado"; + targetPkgs = vivadoDeps; + profile = "source /opt/Xilinx/Vivado/2020.1/settings64.sh"; + runScript = "vivado"; + }; + + makeArtiqBoardPackage = { target, variant, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}" }: + pkgs.python3Packages.toPythonModule (pkgs.stdenv.mkDerivation { + name = "artiq-board-${target}-${variant}"; + phases = [ "buildPhase" "checkPhase" "installPhase" ]; + cargoDeps = rustPlatform.fetchCargoTarball { + name = "artiq-firmware-cargo-deps"; + src = "${self}/artiq/firmware"; + sha256 = "0hh9x34gs81a8g15abka6a0z1wlankra13rbap5j7ba2r8cz4962"; + }; + nativeBuildInputs = [ + (pkgs.python3.withPackages(ps: [ migen misoc artiq ])) + rustPlatform.rust.rustc + rustPlatform.rust.cargo + pkgs.llvmPackages_11.clang-unwrapped + pkgs.llvm_11 + pkgs.lld_11 + vivado + rustPlatform.cargoSetupHook + cargo-xbuild + ]; + buildPhase = + '' + ARTIQ_PATH=`python -c "import artiq; print(artiq.__path__[0])"` + ln -s $ARTIQ_PATH/firmware/Cargo.lock . + cargoSetupPostUnpackHook + cargoSetupPostPatchHook + export TARGET_AR=llvm-ar + ${buildCommand} + ''; + checkPhase = '' + # Search for PCREs in the Vivado output to check for errors + check_log() { + grep -Pe "$1" artiq_${target}/${variant}/gateware/vivado.log && exit 1 || true + } + check_log "\d+ constraint not met\." + check_log "Timing constraints are not met\." + ''; + installPhase = + '' + TARGET_DIR=$out/${pkgs.python3Packages.python.sitePackages}/artiq/board-support/${target}-${variant} + mkdir -p $TARGET_DIR + cp artiq_${target}/${variant}/gateware/top.bit $TARGET_DIR + if [ -e artiq_${target}/${variant}/software/bootloader/bootloader.bin ] + then cp artiq_${target}/${variant}/software/bootloader/bootloader.bin $TARGET_DIR + fi + if [ -e artiq_${target}/${variant}/software/runtime ] + then cp artiq_${target}/${variant}/software/runtime/runtime.{elf,fbi} $TARGET_DIR + else cp artiq_${target}/${variant}/software/satman/satman.{elf,fbi} $TARGET_DIR + fi + ''; + # don't mangle ELF files as they are not for NixOS + dontFixup = true; + }); + + openocd-bscanspi = let + bscan_spi_bitstreams-pkg = pkgs.stdenv.mkDerivation { + name = "bscan_spi_bitstreams"; + src = pkgs.fetchFromGitHub { + owner = "quartiq"; + repo = "bscan_spi_bitstreams"; + rev = "01d8f819f15baf9a8cc5d96945a51e4d267ff564"; + sha256 = "1zqv47kzgvbn4c8cr019a6wcja7gn5h1z4kvw5bhpc72fyhagal9"; + }; + phases = ["installPhase"]; + installPhase = + '' + mkdir -p $out/share/bscan-spi-bitstreams + cp $src/*.bit $out/share/bscan-spi-bitstreams + ''; + }; + # https://docs.lambdaconcept.com/screamer/troubleshooting.html#error-contents-differ + openocd-fixed = pkgs.openocd.overrideAttrs(oa: { + patches = oa.patches or [] ++ [ + (pkgs.fetchurl { + url = "https://docs.lambdaconcept.com/screamer/_downloads/f0357c5f44c3c8c49f575cee5b6634a8/flashid.patch"; + sha256 = "015h4fzdrpwy5ssqbpk826snnfkkqijkmjzr5ws0a2v0ci97jzm9"; + }) + ]; + }); + in pkgs.buildEnv { + name = "openocd-bscanspi"; + paths = [ openocd-fixed bscan_spi_bitstreams-pkg ]; + }; in rec { packages.x86_64-linux = rec { - sipyco = pkgs.python3Packages.buildPythonPackage { - name = "sipyco"; - src = src-sipyco; - propagatedBuildInputs = with pkgs.python3Packages; [ pybase64 numpy ]; - }; - - pythonparser = pkgs.python3Packages.buildPythonPackage { - name = "pythonparser"; - src = src-pythonparser; - doCheck = false; - propagatedBuildInputs = with pkgs.python3Packages; [ regex ]; - }; - - qasync = pkgs.python3Packages.buildPythonPackage rec { - pname = "qasync"; - version = "0.10.0"; - src = pkgs.fetchFromGitHub { - owner = "CabbageDevelopment"; - repo = "qasync"; - rev = "v${version}"; - sha256 = "1zga8s6dr7gk6awmxkh4pf25gbg8n6dv1j4b0by7y0fhi949qakq"; - }; - propagatedBuildInputs = [ pkgs.python3Packages.pyqt5 ]; - checkInputs = [ pkgs.python3Packages.pytest ]; - checkPhase = '' - pytest -k 'test_qthreadexec.py' # the others cause the test execution to be aborted, I think because of asyncio - ''; - }; - - outputcheck = pkgs.python3Packages.buildPythonApplication rec { - pname = "outputcheck"; - version = "0.4.2"; - src = pkgs.fetchFromGitHub { - owner = "stp"; - repo = "OutputCheck"; - rev = "e0f533d3c5af2949349856c711bf4bca50022b48"; - sha256 = "1y27vz6jq6sywas07kz3v01sqjd0sga9yv9w2cksqac3v7wmf2a0"; - }; - prePatch = "echo ${version} > RELEASE-VERSION"; - }; - - libartiq-support = pkgs.stdenv.mkDerivation { - name = "libartiq-support"; - src = self; - buildInputs = [ rustPlatform.rust.rustc ]; - buildPhase = '' - rustc $src/artiq/test/libartiq_support/lib.rs -Cpanic=unwind -g - ''; - installPhase = '' - mkdir $out - cp libartiq_support.so $out - ''; - }; - - llvmlite-new = pkgs.python3Packages.buildPythonPackage rec { - pname = "llvmlite"; - version = "0.37.0rc2"; - src = pkgs.python3Packages.fetchPypi { - inherit pname version; - sha256 = "sha256-F1quz+76JOt1jaQPVzdKe7RfN6gWG2lyE82qTvgyY/c="; - }; - nativeBuildInputs = [ pkgs.llvm_11 ]; - # Disable static linking - # https://github.com/numba/llvmlite/issues/93 - postPatch = '' - substituteInPlace ffi/Makefile.linux --replace "-static-libstdc++" "" - substituteInPlace llvmlite/tests/test_binding.py --replace "test_linux" "nope" - ''; - # Set directory containing llvm-config binary - preConfigure = '' - export LLVM_CONFIG=${pkgs.llvm_11.dev}/bin/llvm-config - ''; - doCheck = false; # FIXME - }; - - artiq = pkgs.python3Packages.buildPythonPackage rec { - pname = "artiq"; - version = "7.0-dev"; - src = self; - - preBuild = "export VERSIONEER_OVERRIDE=${version}"; - - nativeBuildInputs = [ pkgs.qt5.wrapQtAppsHook ]; - # keep llvm_x and lld_x in sync with llvmlite - propagatedBuildInputs = [ pkgs.llvm_11 pkgs.lld_11 llvmlite-new sipyco pythonparser ] - ++ (with pkgs.python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial python-Levenshtein h5py pyqt5 qasync ]); - - dontWrapQtApps = true; - postFixup = '' - wrapQtApp "$out/bin/artiq_dashboard" - wrapQtApp "$out/bin/artiq_browser" - wrapQtApp "$out/bin/artiq_session" - ''; - - # Modifies PATH to pass the wrapped python environment (i.e. python3.withPackages(...) to subprocesses. - # Allows subprocesses using python to find all packages you have installed - makeWrapperArgs = [ - ''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' '' - "--set FONTCONFIG_FILE ${pkgs.fontconfig.out}/etc/fonts/fonts.conf" - ]; - - # FIXME: automatically propagate lld_11 llvm_11 dependencies - checkInputs = [ pkgs.lld_11 pkgs.llvm_11 pkgs.lit outputcheck ]; - checkPhase = '' - python -m unittest discover -v artiq.test - - TESTDIR=`mktemp -d` - cp --no-preserve=mode,ownership -R $src/artiq/test/lit $TESTDIR - LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so lit -v $TESTDIR/lit - ''; - }; - - migen = pkgs.python3Packages.buildPythonPackage rec { - name = "migen"; - src = src-migen; - propagatedBuildInputs = [ pkgs.python3Packages.colorama ]; - }; - - asyncserial = pkgs.python3Packages.buildPythonPackage rec { - pname = "asyncserial"; - version = "0.1"; - src = pkgs.fetchFromGitHub { - owner = "m-labs"; - repo = "asyncserial"; - rev = "d95bc1d6c791b0e9785935d2f62f628eb5cdf98d"; - sha256 = "0yzkka9jk3612v8gx748x6ziwykq5lr7zmr9wzkcls0v2yilqx9k"; - }; - propagatedBuildInputs = [ pkgs.python3Packages.pyserial ]; - }; - - misoc = pkgs.python3Packages.buildPythonPackage { - name = "misoc"; - src = src-misoc; - doCheck = false; # TODO: fix misoc bitrot and re-enable tests - propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ]; - }; - - cargo-xbuild = rustPlatform.buildRustPackage rec { - pname = "cargo-xbuild"; - version = "0.6.5"; - - src = pkgs.fetchFromGitHub { - owner = "rust-osdev"; - repo = pname; - rev = "v${version}"; - sha256 = "18djvygq9v8rmfchvi2hfj0i6fhn36m716vqndqnj56fiqviwxvf"; - }; - - cargoSha256 = "13sj9j9kl6js75h9xq0yidxy63vixxm9q3f8jil6ymarml5wkhx8"; - }; - - vivadoEnv = pkgs.buildFHSUserEnv { - name = "vivado-env"; - targetPkgs = vivadoDeps; - }; - - vivado = pkgs.buildFHSUserEnv { - name = "vivado"; - targetPkgs = vivadoDeps; - profile = "source /opt/Xilinx/Vivado/2020.1/settings64.sh"; - runScript = "vivado"; - }; - - artiq-board-kc705-nist_clock = let - makeArtiqBoardPackage = { target, variant, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}" }: - pkgs.python3Packages.toPythonModule (pkgs.stdenv.mkDerivation { - name = "artiq-board-${target}-${variant}"; - phases = [ "buildPhase" "checkPhase" "installPhase" ]; - cargoDeps = rustPlatform.fetchCargoTarball { - name = "artiq-firmware-cargo-deps"; - src = "${self}/artiq/firmware"; - sha256 = "0hh9x34gs81a8g15abka6a0z1wlankra13rbap5j7ba2r8cz4962"; - }; - nativeBuildInputs = [ - (pkgs.python3.withPackages(ps: [ migen misoc artiq ])) - rustPlatform.rust.rustc - rustPlatform.rust.cargo - pkgs.llvmPackages_11.clang-unwrapped - pkgs.llvm_11 - pkgs.lld_11 - vivado - rustPlatform.cargoSetupHook - cargo-xbuild - ]; - buildPhase = - '' - ARTIQ_PATH=`python -c "import artiq; print(artiq.__path__[0])"` - ln -s $ARTIQ_PATH/firmware/Cargo.lock . - cargoSetupPostUnpackHook - cargoSetupPostPatchHook - export TARGET_AR=llvm-ar - ${buildCommand} - ''; - checkPhase = '' - # Search for PCREs in the Vivado output to check for errors - check_log() { - grep -Pe "$1" artiq_${target}/${variant}/gateware/vivado.log && exit 1 || true - } - check_log "\d+ constraint not met\." - check_log "Timing constraints are not met\." - ''; - installPhase = - '' - TARGET_DIR=$out/${pkgs.python3Packages.python.sitePackages}/artiq/board-support/${target}-${variant} - mkdir -p $TARGET_DIR - cp artiq_${target}/${variant}/gateware/top.bit $TARGET_DIR - if [ -e artiq_${target}/${variant}/software/bootloader/bootloader.bin ] - then cp artiq_${target}/${variant}/software/bootloader/bootloader.bin $TARGET_DIR - fi - if [ -e artiq_${target}/${variant}/software/runtime ] - then cp artiq_${target}/${variant}/software/runtime/runtime.{elf,fbi} $TARGET_DIR - else cp artiq_${target}/${variant}/software/satman/satman.{elf,fbi} $TARGET_DIR - fi - ''; - # don't mangle ELF files as they are not for NixOS - dontFixup = true; - }); - in makeArtiqBoardPackage { + inherit migen misoc vivadoEnv vivado openocd-bscanspi artiq; + artiq-board-kc705-nist_clock = makeArtiqBoardPackage { target = "kc705"; variant = "nist_clock"; }; - - openocd-bscanspi = let - bscan_spi_bitstreams-pkg = pkgs.stdenv.mkDerivation { - name = "bscan_spi_bitstreams"; - src = pkgs.fetchFromGitHub { - owner = "quartiq"; - repo = "bscan_spi_bitstreams"; - rev = "01d8f819f15baf9a8cc5d96945a51e4d267ff564"; - sha256 = "1zqv47kzgvbn4c8cr019a6wcja7gn5h1z4kvw5bhpc72fyhagal9"; - }; - phases = ["installPhase"]; - installPhase = - '' - mkdir -p $out/share/bscan-spi-bitstreams - cp $src/*.bit $out/share/bscan-spi-bitstreams - ''; - }; - # https://docs.lambdaconcept.com/screamer/troubleshooting.html#error-contents-differ - openocd-fixed = pkgs.openocd.overrideAttrs(oa: { - patches = oa.patches or [] ++ [ - (pkgs.fetchurl { - url = "https://docs.lambdaconcept.com/screamer/_downloads/f0357c5f44c3c8c49f575cee5b6634a8/flashid.patch"; - sha256 = "015h4fzdrpwy5ssqbpk826snnfkkqijkmjzr5ws0a2v0ci97jzm9"; - }) - ]; - }); - in pkgs.buildEnv { - name = "openocd-bscanspi"; - paths = [ openocd-fixed bscan_spi_bitstreams-pkg ]; + artiq-board-kc705-nist_qc2 = makeArtiqBoardPackage { + target = "kc705"; + variant = "nist_qc2"; + }; + artiq-board-kc705-nist_clock_master = makeArtiqBoardPackage { + target = "kc705"; + variant = "nist_clock_master"; + }; + artiq-board-kc705-nist_qc2_master = makeArtiqBoardPackage { + target = "kc705"; + variant = "nist_qc2_master"; + }; + artiq-board-kc705-nist_clock_satellite = makeArtiqBoardPackage { + target = "kc705"; + variant = "nist_clock"; + }; + artiq-board-kc705-nist_qc2_satellite = makeArtiqBoardPackage { + target = "kc705"; + variant = "nist_qc2"; }; }; From 1a0c4219ecf0ff3cb0b5488e122de36c396ed9dd Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 12 Sep 2021 19:27:00 +0800 Subject: [PATCH 154/238] doc: mor1kx -> VexRiscv --- README.rst | 2 +- doc/manual/introduction.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index eda230b13..537745b9a 100644 --- a/README.rst +++ b/README.rst @@ -20,7 +20,7 @@ Like any open source software ARTIQ can equally be built and installed directly ARTIQ is supported by M-Labs and developed openly. Components, features, fixes, improvements, and extensions are often `funded `_ by and developed for the partnering research groups. -Core technologies employed include `Python `_, `Migen `_, `Migen-AXI `_, `Rust `_, `MiSoC `_/`mor1kx `_, `LLVM `_/`llvmlite `_, and `Qt5 `_. +Core technologies employed include `Python `_, `Migen `_, `Migen-AXI `_, `Rust `_, `MiSoC `_/`VexRiscv `_, `LLVM `_/`llvmlite `_, and `Qt5 `_. Website: https://m-labs.hk/artiq diff --git a/doc/manual/introduction.rst b/doc/manual/introduction.rst index 7b499ba42..7dcc2f802 100644 --- a/doc/manual/introduction.rst +++ b/doc/manual/introduction.rst @@ -21,7 +21,7 @@ Like any open source software ARTIQ can equally be built and installed directly ARTIQ is supported by M-Labs and developed openly. Components, features, fixes, improvements, and extensions are funded by and developed for the partnering research groups. -Technologies employed include `Python `_, `Migen `_, `MiSoC `_/`mor1kx `_, `LLVM `_/`llvmlite `_, and `Qt5 `_. +Core technologies employed include `Python `_, `Migen `_, `Migen-AXI `_, `Rust `_, `MiSoC `_/`VexRiscv `_, `LLVM `_/`llvmlite `_, and `Qt5 `_. Website: https://m-labs.hk/artiq From 2d79d824f9d267748fb07e46407f4a4f8248f18b Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 12 Sep 2021 20:03:37 +0800 Subject: [PATCH 155/238] firmware: remove minor or1k leftovers --- artiq/firmware/ksupport/eh_artiq.rs | 3 --- artiq/firmware/libeh/eh_rust.rs | 3 --- 2 files changed, 6 deletions(-) diff --git a/artiq/firmware/ksupport/eh_artiq.rs b/artiq/firmware/ksupport/eh_artiq.rs index f7923807a..86473e2ba 100644 --- a/artiq/firmware/ksupport/eh_artiq.rs +++ b/artiq/firmware/ksupport/eh_artiq.rs @@ -58,9 +58,6 @@ struct ExceptionInfo { #[cfg(target_arch = "x86_64")] const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX -#[cfg(any(target_arch = "or1k"))] -const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 - #[cfg(any(target_arch = "riscv32"))] const UNWIND_DATA_REG: (i32, i32) = (10, 11); // X10, X11 diff --git a/artiq/firmware/libeh/eh_rust.rs b/artiq/firmware/libeh/eh_rust.rs index 399ccdf6b..166aae843 100644 --- a/artiq/firmware/libeh/eh_rust.rs +++ b/artiq/firmware/libeh/eh_rust.rs @@ -31,9 +31,6 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX #[cfg(target_arch = "x86_64")] const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX -#[cfg(any(target_arch = "or1k"))] -const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 - #[cfg(any(target_arch = "riscv32"))] const UNWIND_DATA_REG: (i32, i32) = (10, 11); // X10, X11 From ffb1e3ec2d4277ecaaf09e98e80cfa758b810ea5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 13 Sep 2021 07:02:35 +0800 Subject: [PATCH 156/238] wavesynth: np.int is deprecated --- artiq/wavesynth/coefficients.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/wavesynth/coefficients.py b/artiq/wavesynth/coefficients.py index 3c41990ed..e70a4080e 100644 --- a/artiq/wavesynth/coefficients.py +++ b/artiq/wavesynth/coefficients.py @@ -111,7 +111,7 @@ class CoefficientSource: """ t = np.rint(x/scale) x_sample = t*scale - durations = np.diff(t).astype(np.int) + durations = np.diff(t).astype(int) return x_sample, durations def __call__(self, x, **kwargs): @@ -201,7 +201,7 @@ class SplineSource(CoefficientSource): inc = np.diff(t) >= 0 inc = np.r_[inc, inc[-1]] t = np.where(inc, np.ceil(t), np.floor(t)) - dt = np.diff(t.astype(np.int)) + dt = np.diff(t.astype(int)) valid = np.absolute(dt) >= min_duration if not np.any(valid): From 7209e6f2798c70333e115d86c631a34f19b20be5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 13 Sep 2021 07:20:36 +0800 Subject: [PATCH 157/238] flake: add cargo-xbuild to dev environment --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 69e07baa7..2dd3ba9e2 100644 --- a/flake.nix +++ b/flake.nix @@ -327,6 +327,7 @@ (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ps.paramiko ])) rustPlatform.rust.rustc rustPlatform.rust.cargo + cargo-xbuild pkgs.llvmPackages_11.clang-unwrapped pkgs.llvm_11 pkgs.lld_11 From 4834966798eddec9f3138aebc1ee0380534cc075 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 13 Sep 2021 07:39:15 +0800 Subject: [PATCH 158/238] flake: add jsonschema to dev environment --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 2dd3ba9e2..e04d85da5 100644 --- a/flake.nix +++ b/flake.nix @@ -324,7 +324,7 @@ devShell.x86_64-linux = pkgs.mkShell { name = "artiq-dev-shell"; buildInputs = [ - (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ps.paramiko ])) + (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ps.paramiko ps.jsonschema ])) rustPlatform.rust.rustc rustPlatform.rust.cargo cargo-xbuild From e8a7a8f41e386426c00d27873690e29c2dd3b382 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 13 Sep 2021 10:40:54 +0800 Subject: [PATCH 159/238] compiler: work around idiotic windoze behavior that causes conda ld.lld not to be found --- artiq/compiler/targets.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index 0c6ee3ee4..38e15b6cc 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -28,8 +28,10 @@ class RunTool: for argument in self._pattern: cmdline.append(argument.format(**self._tempnames)) + # https://bugs.python.org/issue17023 + windows = os.name == "nt" process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=True) + universal_newlines=True, shell=windows) stdout, stderr = process.communicate() if process.returncode != 0: raise Exception("{} invocation failed: {}". From 3ed10221d8760c0b27ee64800036f6ffa5920dd0 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 13 Sep 2021 13:40:24 +0800 Subject: [PATCH 160/238] compiler: remove big-endian support. Closes #1590 --- artiq/compiler/targets.py | 8 ------- .../compiler/transforms/llvm_ir_generator.py | 24 +++++++++---------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index 38e15b6cc..e908ce38a 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -77,9 +77,6 @@ class Target: :var print_function: (string) Name of a formatted print functions (with the signature of ``printf``) provided by the target, e.g. ``"printf"``. - :var little_endian: (boolean) - Whether the code will be executed on a little-endian machine. This cannot be always - determined from data_layout due to JIT. :var now_pinning: (boolean) Whether the target implements the now-pinning RTIO optimization. """ @@ -87,7 +84,6 @@ class Target: data_layout = "" features = [] print_function = "printf" - little_endian = False now_pinning = True tool_ld = "ld.lld" @@ -255,15 +251,12 @@ class NativeTarget(Target): super().__init__() self.triple = llvm.get_default_triple() host_data_layout = str(llvm.targets.Target.from_default_triple().create_target_machine().target_data) - assert host_data_layout[0] in "eE" - self.little_endian = host_data_layout[0] == "e" class RISCVTarget(Target): triple = "riscv32-unknown-linux" data_layout = "e-m:e-p:32:32-i64:64-n32-S128" features = ["m", "a"] print_function = "core_log" - little_endian = True now_pinning = True tool_ld = "ld.lld" @@ -276,7 +269,6 @@ class CortexA9Target(Target): data_layout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" features = ["dsp", "fp16", "neon", "vfp3"] print_function = "core_log" - little_endian = True now_pinning = False tool_ld = "ld.lld" diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 970ade340..61f66599c 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1095,15 +1095,12 @@ class LLVMIRGenerator: return self.map(insn.operands[0]) elif insn.op == "now_mu": if self.target.now_pinning: - # Word swap now.old for little endian target + # Word swap now.old as CPU is little endian # Most significant word is stored in lower address (see generated csr.rs) - if self.target.little_endian: - llnow_raw = self.llbuilder.load(self.llbuiltin("now"), name=insn.name) - llnow_lo = self.llbuilder.shl(llnow_raw, ll.Constant(lli64, 32)) - llnow_hi = self.llbuilder.lshr(llnow_raw, ll.Constant(lli64, 32)) - return self.llbuilder.or_(llnow_lo, llnow_hi) - else: - return self.llbuilder.load(self.llbuiltin("now"), name=insn.name) + llnow_raw = self.llbuilder.load(self.llbuiltin("now"), name=insn.name) + llnow_lo = self.llbuilder.shl(llnow_raw, ll.Constant(lli64, 32)) + llnow_hi = self.llbuilder.lshr(llnow_raw, ll.Constant(lli64, 32)) + return self.llbuilder.or_(llnow_lo, llnow_hi) else: return self.llbuilder.call(self.llbuiltin("now_mu"), []) elif insn.op == "at_mu": @@ -1125,12 +1122,13 @@ class LLVMIRGenerator: if self.target.now_pinning: llnowptr = self.llbuiltin("now") llnow = self.llbuilder.load(llnowptr, name="now.old") - # Word swap now.old for little endian target + + # Word swap now.old as CPU is little endian # Most significant word is stored in lower address (see generated csr.rs) - if self.target.little_endian: - llnow_lo = self.llbuilder.shl(llnow, ll.Constant(lli64, 32)) - llnow_hi = self.llbuilder.lshr(llnow, ll.Constant(lli64, 32)) - llnow = self.llbuilder.or_(llnow_lo, llnow_hi) + llnow_lo = self.llbuilder.shl(llnow, ll.Constant(lli64, 32)) + llnow_hi = self.llbuilder.lshr(llnow, ll.Constant(lli64, 32)) + llnow = self.llbuilder.or_(llnow_lo, llnow_hi) + lladjusted = self.llbuilder.add(llnow, llinterval, name="now.new") lladjusted_hi = self.llbuilder.trunc(self.llbuilder.lshr(lladjusted, ll.Constant(lli64, 32)), lli32) lladjusted_lo = self.llbuilder.trunc(lladjusted, lli32) From 7a7e17f7e3d1a53bdec4a6ff514a68b6ead80bdf Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 27 Sep 2021 09:31:49 +0800 Subject: [PATCH 161/238] openocd: update and apply 4-byte address support patch See the relevant commit made in nix-scripts repo. https://git.m-labs.hk/M-Labs/nix-scripts/commit/575ef05cd554c239e4cc8cb97ae4611db458a80d --- flake.nix | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index e04d85da5..e4343766d 100644 --- a/flake.nix +++ b/flake.nix @@ -279,12 +279,21 @@ }; # https://docs.lambdaconcept.com/screamer/troubleshooting.html#error-contents-differ openocd-fixed = pkgs.openocd.overrideAttrs(oa: { + version = "unstable-2021-09-15"; + src = pkgs.fetchFromGitHub { + owner = "openocd-org"; + repo = "openocd"; + rev = "a0bd3c9924870c3b8f428648410181040dabc33c"; + sha256 = "sha256-YgUsl4/FohfsOncM4uiz/3c6g2ZN4oZ0y5vV/2Skwqg="; + fetchSubmodules = true; + }; patches = oa.patches or [] ++ [ (pkgs.fetchurl { - url = "https://docs.lambdaconcept.com/screamer/_downloads/f0357c5f44c3c8c49f575cee5b6634a8/flashid.patch"; - sha256 = "015h4fzdrpwy5ssqbpk826snnfkkqijkmjzr5ws0a2v0ci97jzm9"; + url = "https://git.m-labs.hk/M-Labs/nix-scripts/raw/commit/575ef05cd554c239e4cc8cb97ae4611db458a80d/artiq-fast/pkgs/openocd-jtagspi.diff"; + sha256 = "0g3crk8gby42gm661yxdcgapdi8sp050l5pb2d0yjfic7ns9cw81"; }) ]; + nativeBuildInputs = oa.nativeBuildInputs or [] ++ [ pkgs.autoreconfHook269 ]; }); in pkgs.buildEnv { name = "openocd-bscanspi"; From a8333053c956fac19dbd813c1da5548db67698e2 Mon Sep 17 00:00:00 2001 From: Etienne Wodey Date: Mon, 27 Sep 2021 11:22:25 +0200 Subject: [PATCH 162/238] sinara_tester: add device_db and test selection CLI options Signed-off-by: Etienne Wodey --- artiq/frontend/artiq_sinara_tester.py | 77 ++++++++++++++++++--------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/artiq/frontend/artiq_sinara_tester.py b/artiq/frontend/artiq_sinara_tester.py index 078d7db5e..22ba53740 100755 --- a/artiq/frontend/artiq_sinara_tester.py +++ b/artiq/frontend/artiq_sinara_tester.py @@ -1,8 +1,10 @@ #!/usr/bin/env python3 -import sys +import argparse +import inspect import os import select +import sys from artiq.experiment import * from artiq.coredevice.ad9910 import AD9910, SyncDataEeprom @@ -651,40 +653,63 @@ class SinaraTester(EnvExperiment): print("Press ENTER when done.") input() - def run(self): + def run(self, tests): print("****** Sinara system tester ******") print("") self.core.reset() - if self.leds: - self.test_leds() - if self.ttl_outs: - self.test_ttl_outs() - if self.ttl_ins: - self.test_ttl_ins() - if self.urukuls: - self.test_urukuls() - if self.mirnies: - self.test_mirnies() - if self.samplers: - self.test_samplers() - if self.zotinos: - self.test_zotinos() - if self.fastinos: - self.test_fastinos() - if self.phasers: - self.test_phasers() - if self.grabbers: - self.test_grabbers() - if self.suservos: - self.test_suservos() + + for name in tests: + if getattr(self, name): + getattr(self, f"test_{name}")() + + @classmethod + def available_tests(cls): + # listed in definition order + return [ + name.split("_", maxsplit=1)[1] + for name, obj in vars(cls).items() + if is_hw_test(obj) + ] + + +def is_hw_test(obj): + return ( + inspect.isfunction(obj) and + obj.__name__.startswith("test_") and + len(inspect.signature(obj).parameters) == 1 + ) + + +def get_argparser(available_tests): + parser = argparse.ArgumentParser(description="Sinara crate testing tool") + + parser.add_argument("--device-db", default="device_db.py", + help="device database file (default: '%(default)s')") + group = parser.add_mutually_exclusive_group() + group.add_argument("-x", "--exclude", nargs="*", choices=available_tests, + help="do not run the listed tests") + group.add_argument("-o", "--only", nargs="*", choices=available_tests, + help="run only the listed tests") + return parser def main(): - device_mgr = DeviceManager(DeviceDB("device_db.py")) + available_tests = SinaraTester.available_tests() + args = get_argparser(available_tests).parse_args() + + if args.exclude is not None: + # don't use set in order to keep the order + tests = [test for test in available_tests if test not in args.exclude] + elif args.only is not None: + tests = args.only + else: + tests = available_tests + + device_mgr = DeviceManager(DeviceDB(args.device_db)) try: experiment = SinaraTester((device_mgr, None, None, None)) experiment.prepare() - experiment.run() + experiment.run(tests) experiment.analyze() finally: device_mgr.close_devices() From 4bfd010f0306819ec1624f1af6f14e59bfc26196 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 27 Sep 2021 17:46:25 +0800 Subject: [PATCH 163/238] setup: Python 3.7+ --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index ed3ef26d2..d888e9402 100755 --- a/setup.py +++ b/setup.py @@ -6,8 +6,8 @@ import sys import versioneer -if sys.version_info[:3] < (3, 5, 3): - raise Exception("You need Python 3.5.3+") +if sys.version_info[:2] < (3, 7): + raise Exception("You need Python 3.7+") # Depends on PyQt5, but setuptools cannot check for it. @@ -58,7 +58,7 @@ Intended Audience :: Science/Research License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) Operating System :: Microsoft :: Windows Operating System :: POSIX :: Linux -Programming Language :: Python :: 3.5 +Programming Language :: Python :: 3.7 Topic :: Scientific/Engineering :: Physics Topic :: System :: Hardware """.splitlines(), From 1894f0f626a72870ebe7db459e1d8e8d374f2673 Mon Sep 17 00:00:00 2001 From: Spaqin Date: Thu, 7 Oct 2021 02:19:38 +0200 Subject: [PATCH 164/238] gateware: share RTIOClockMultiplier and fix_serdes_timing_path (#1760) --- artiq/gateware/rtio/xilinx_clocking.py | 45 ++++++++++++++++++++++++ artiq/gateware/targets/kasli.py | 47 ++------------------------ artiq/gateware/targets/kc705.py | 47 ++------------------------ artiq/gateware/targets/sayma_rtm.py | 45 ++---------------------- 4 files changed, 53 insertions(+), 131 deletions(-) create mode 100644 artiq/gateware/rtio/xilinx_clocking.py diff --git a/artiq/gateware/rtio/xilinx_clocking.py b/artiq/gateware/rtio/xilinx_clocking.py new file mode 100644 index 000000000..57e6683c4 --- /dev/null +++ b/artiq/gateware/rtio/xilinx_clocking.py @@ -0,0 +1,45 @@ +from migen import * +from migen.genlib.cdc import MultiReg +from misoc.interconnect.csr import * + + +class RTIOClockMultiplier(Module, AutoCSR): + def __init__(self, rtio_clk_freq): + self.pll_reset = CSRStorage(reset=1) + self.pll_locked = CSRStatus() + self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True) + + # See "Global Clock Network Deskew Using Two BUFGs" in ug472. + clkfbout = Signal() + clkfbin = Signal() + rtiox4_clk = Signal() + pll_locked = Signal() + self.specials += [ + Instance("MMCME2_BASE", + p_CLKIN1_PERIOD=1e9/rtio_clk_freq, + i_CLKIN1=ClockSignal("rtio"), + i_RST=self.pll_reset.storage, + o_LOCKED=pll_locked, + + p_CLKFBOUT_MULT_F=8.0, p_DIVCLK_DIVIDE=1, + + o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbin, + + p_CLKOUT0_DIVIDE_F=2.0, o_CLKOUT0=rtiox4_clk, + ), + Instance("BUFG", i_I=clkfbout, o_O=clkfbin), + Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk), + + MultiReg(pll_locked, self.pll_locked.status) + ] + + +def fix_serdes_timing_path(platform): + # ignore timing of path from OSERDESE2 through the pad to ISERDESE2 + platform.add_platform_command( + "set_false_path -quiet " + "-through [get_pins -filter {{REF_PIN_NAME == OQ || REF_PIN_NAME == TQ}} " + "-of [get_cells -filter {{REF_NAME == OSERDESE2}}]] " + "-to [get_pins -filter {{REF_PIN_NAME == D}} " + "-of [get_cells -filter {{REF_NAME == ISERDESE2}}]]" + ) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 131d75a79..d47b583b1 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -17,6 +17,7 @@ from misoc.integration.builder import builder_args, builder_argdict from artiq.gateware.amp import AMPSoC from artiq.gateware import rtio from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, edge_counter +from artiq.gateware.rtio.xilinx_clocking import RTIOClockMultiplier, fix_serdes_timing_path from artiq.gateware import eem from artiq.gateware.drtio.transceiver import gtp_7series from artiq.gateware.drtio.siphaser import SiPhaser7Series @@ -94,17 +95,6 @@ class SMAClkinForward(Module): ] -def fix_serdes_timing_path(platform): - # ignore timing of path from OSERDESE2 through the pad to ISERDESE2 - platform.add_platform_command( - "set_false_path -quiet " - "-through [get_pins -filter {{REF_PIN_NAME == OQ || REF_PIN_NAME == TQ}} " - "-of [get_cells -filter {{REF_NAME == OSERDESE2}}]] " - "-to [get_pins -filter {{REF_PIN_NAME == D}} " - "-of [get_cells -filter {{REF_NAME == ISERDESE2}}]]" - ) - - class StandaloneBase(MiniSoC, AMPSoC): mem_map = { "cri_con": 0x10000000, @@ -255,37 +245,6 @@ class SUServo(StandaloneBase): pads.clkout, self.crg.cd_sys.clk) -class _RTIOClockMultiplier(Module, AutoCSR): - def __init__(self, rtio_clk_freq): - self.pll_reset = CSRStorage(reset=1) - self.pll_locked = CSRStatus() - self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True) - - # See "Global Clock Network Deskew Using Two BUFGs" in ug472. - clkfbout = Signal() - clkfbin = Signal() - rtiox4_clk = Signal() - pll_locked = Signal() - self.specials += [ - Instance("MMCME2_BASE", - p_CLKIN1_PERIOD=1e9/rtio_clk_freq, - i_CLKIN1=ClockSignal("rtio"), - i_RST=self.pll_reset.storage, - o_LOCKED=pll_locked, - - p_CLKFBOUT_MULT_F=8.0, p_DIVCLK_DIVIDE=1, - - o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbin, - - p_CLKOUT0_DIVIDE_F=2.0, o_CLKOUT0=rtiox4_clk, - ), - Instance("BUFG", i_I=clkfbout, o_O=clkfbin), - Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk), - - MultiReg(pll_locked, self.pll_locked.status) - ] - - class MasterBase(MiniSoC, AMPSoC): mem_map = { "cri_con": 0x10000000, @@ -400,7 +359,7 @@ class MasterBase(MiniSoC, AMPSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtp.rxoutclk) - self.submodules.rtio_crg = _RTIOClockMultiplier(rtio_clk_freq) + self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq) self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) @@ -627,7 +586,7 @@ class SatelliteBase(BaseSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtp.rxoutclk) - self.submodules.rtio_crg = _RTIOClockMultiplier(rtio_clk_freq) + self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq) self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 0b69c18b1..2a6e31d6f 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -17,6 +17,7 @@ from misoc.integration.builder import builder_args, builder_argdict from artiq.gateware.amp import AMPSoC from artiq.gateware import rtio, nist_clock, nist_qc2 from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2 +from artiq.gateware.rtio.xilinx_clocking import RTIOClockMultiplier, fix_serdes_timing_path from artiq.gateware.drtio.transceiver import gtx_7series from artiq.gateware.drtio.siphaser import SiPhaser7Series from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer @@ -82,48 +83,6 @@ class _RTIOCRG(Module, AutoCSR): ] -class _RTIOClockMultiplier(Module, AutoCSR): - def __init__(self, rtio_clk_freq): - self.pll_reset = CSRStorage(reset=1) - self.pll_locked = CSRStatus() - self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True) - - # See "Global Clock Network Deskew Using Two BUFGs" in ug472. - clkfbout = Signal() - clkfbin = Signal() - rtiox4_clk = Signal() - pll_locked = Signal() - self.specials += [ - Instance("MMCME2_BASE", - p_CLKIN1_PERIOD=1e9/rtio_clk_freq, - i_CLKIN1=ClockSignal("rtio"), - i_RST=self.pll_reset.storage, - o_LOCKED=pll_locked, - - p_CLKFBOUT_MULT_F=8.0, p_DIVCLK_DIVIDE=1, - - o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbin, - - p_CLKOUT0_DIVIDE_F=2.0, o_CLKOUT0=rtiox4_clk, - ), - Instance("BUFG", i_I=clkfbout, o_O=clkfbin), - Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk), - - MultiReg(pll_locked, self.pll_locked.status) - ] - - -def fix_serdes_timing_path(platform): - # ignore timing of path from OSERDESE2 through the pad to ISERDESE2 - platform.add_platform_command( - "set_false_path -quiet " - "-through [get_pins -filter {{REF_PIN_NAME == OQ || REF_PIN_NAME == TQ}} " - "-of [get_cells -filter {{REF_NAME == OSERDESE2}}]] " - "-to [get_pins -filter {{REF_PIN_NAME == D}} " - "-of [get_cells -filter {{REF_NAME == ISERDESE2}}]]" - ) - - # The default voltage for these signals on KC705 is 2.5V, and the Migen platform # follows this default. But since the SMAs are on the same bank as the DDS, # which is set to 3.3V by reprogramming the KC705 power ICs, we need to @@ -349,7 +308,7 @@ class _MasterBase(MiniSoC, AMPSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtx0.txoutclk, gtx.rxoutclk) - self.submodules.rtio_crg = _RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq) + self.submodules.rtio_crg = RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq) self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) @@ -498,7 +457,7 @@ class _SatelliteBase(BaseSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, gtx.rxoutclk) - self.submodules.rtio_crg = _RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq) + self.submodules.rtio_crg = RTIOClockMultiplier(self.drtio_transceiver.rtio_clk_freq) self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) diff --git a/artiq/gateware/targets/sayma_rtm.py b/artiq/gateware/targets/sayma_rtm.py index a302a795f..b4401e9e0 100755 --- a/artiq/gateware/targets/sayma_rtm.py +++ b/artiq/gateware/targets/sayma_rtm.py @@ -18,6 +18,7 @@ from misoc.integration.builder import Builder, builder_args, builder_argdict from artiq.gateware import rtio from artiq.gateware import jesd204_tools from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series +from artiq.gateware.rtio.xilinx_clocking import RTIOClockMultiplier, fix_serdes_timing_path from artiq.gateware.drtio.transceiver import gtp_7series from artiq.gateware.drtio.siphaser import SiPhaser7Series from artiq.gateware.drtio.wrpll import WRPLL, DDMTDSamplerGTP @@ -27,48 +28,6 @@ from artiq.build_soc import add_identifier from artiq import __artiq_dir__ as artiq_dir -def fix_serdes_timing_path(platform): - # ignore timing of path from OSERDESE2 through the pad to ISERDESE2 - platform.add_platform_command( - "set_false_path -quiet " - "-through [get_pins -filter {{REF_PIN_NAME == OQ || REF_PIN_NAME == TQ}} " - "-of [get_cells -filter {{REF_NAME == OSERDESE2}}]] " - "-to [get_pins -filter {{REF_PIN_NAME == D}} " - "-of [get_cells -filter {{REF_NAME == ISERDESE2}}]]" - ) - - -class _RTIOClockMultiplier(Module, AutoCSR): - def __init__(self, rtio_clk_freq): - self.pll_reset = CSRStorage(reset=1) - self.pll_locked = CSRStatus() - self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True) - - # See "Global Clock Network Deskew Using Two BUFGs" in ug472. - clkfbout = Signal() - clkfbin = Signal() - rtiox4_clk = Signal() - pll_locked = Signal() - self.specials += [ - Instance("MMCME2_BASE", - p_CLKIN1_PERIOD=1e9/rtio_clk_freq, - i_CLKIN1=ClockSignal("rtio"), - i_RST=self.pll_reset.storage, - o_LOCKED=pll_locked, - - p_CLKFBOUT_MULT_F=8.0, p_DIVCLK_DIVIDE=1, - - o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbin, - - p_CLKOUT0_DIVIDE_F=2.0, o_CLKOUT0=rtiox4_clk, - ), - Instance("BUFG", i_I=clkfbout, o_O=clkfbin), - Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk), - - MultiReg(pll_locked, self.pll_locked.status) - ] - - class _SatelliteBase(BaseSoC): mem_map = { "drtioaux": 0x50000000, @@ -178,7 +137,7 @@ class _SatelliteBase(BaseSoC): self.crg.cd_sys.clk, gtp.txoutclk, gtp.rxoutclk) - self.submodules.rtio_crg = _RTIOClockMultiplier(rtio_clk_freq) + self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq) self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) From 59065c466360bf76502ed6b9c91433323069dfeb Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 7 Oct 2021 11:17:02 +0800 Subject: [PATCH 165/238] alloc_list: support alloc w/ large align Signed-off-by: Oi Chee Cheung --- artiq/firmware/liballoc_list/lib.rs | 59 +++++++++++++++++++---------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/artiq/firmware/liballoc_list/lib.rs b/artiq/firmware/liballoc_list/lib.rs index f4d93310a..345f5e15f 100644 --- a/artiq/firmware/liballoc_list/lib.rs +++ b/artiq/firmware/liballoc_list/lib.rs @@ -3,9 +3,6 @@ use core::{ptr, mem, fmt}; use core::alloc::{GlobalAlloc, Layout}; -// The minimum alignment guaranteed by the architecture. -const MIN_ALIGN: usize = 16; - const MAGIC_FREE: usize = 0xDEADDEAD; const MAGIC_BUSY: usize = 0xFEEDFEED; @@ -13,7 +10,6 @@ const MAGIC_BUSY: usize = 0xFEEDFEED; struct Header { magic: usize, size: usize, - _pad: usize, next: *mut Header } @@ -42,10 +38,6 @@ impl ListAlloc { unsafe impl GlobalAlloc for ListAlloc { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - if layout.align() > MIN_ALIGN { - panic!("cannot allocate with alignment {}", layout.align()) - } - let header_size = mem::size_of::
(); let size; if layout.size() % header_size != 0 { @@ -53,6 +45,7 @@ unsafe impl GlobalAlloc for ListAlloc { } else { size = layout.size() } + let align = layout.align(); let mut curr = self.root; while !curr.is_null() { @@ -68,20 +61,48 @@ unsafe impl GlobalAlloc for ListAlloc { next = (*curr).next; } - if (*curr).size > size + header_size * 2 { - // Split - let offset = header_size + size; - let next = (curr as *mut u8).offset(offset as isize) as *mut Header; + unsafe fn split(header: *mut Header, split_size: usize) { + let offset = mem::size_of::
() + split_size; + let next = (header as *mut u8).offset(offset as isize) as *mut Header; (*next).magic = MAGIC_FREE; - (*next).size = (*curr).size - offset; - (*next).next = (*curr).next; - (*curr).next = next; - (*curr).size = size; + (*next).size = (*header).size - offset; + (*next).next = (*header).next; + (*header).next = next; + (*header).size = split_size; } - if (*curr).size >= size { - (*curr).magic = MAGIC_BUSY; - return curr.offset(1) as *mut u8 + // Case 1: Memory can be allocated straight from the current chunk + if (curr.offset(1) as usize) % align == 0 { + // Check available space + if (*curr).size > size + header_size * 2 { + split(curr, size); + } + + if (*curr).size >= size { + (*curr).magic = MAGIC_BUSY; + return curr.offset(1) as *mut u8 + } + } + + // Case 2: Padding is needed to satisfy the alignment + else { + let alloc_addr = curr.offset(2) as usize; + let padding_size = align - (alloc_addr % align); + + if (*curr).size >= size + padding_size + header_size { + // Create a padding region + split(curr, padding_size); + + curr = (*curr).next; + + // Check if a padding is needed at the rear + if (*curr).size > size + header_size * 2 { + split(curr, size); + } + + (*curr).magic = MAGIC_BUSY; + return curr.offset(1) as *mut u8 + } } }, _ => panic!("heap corruption detected at {:p}", curr) From ea9bc0440753ac22e5d42754b4b54d15ca3a4e20 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Thu, 7 Oct 2021 17:20:44 +0800 Subject: [PATCH 166/238] flake: add jesd204b --- flake.nix | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index e4343766d..0aa09d2b0 100644 --- a/flake.nix +++ b/flake.nix @@ -181,6 +181,18 @@ propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ]; }; + jesd204b = pkgs.python3Packages.buildPythonPackage rec { + pname = "jesd204b"; + version = "unstable-2021-05-05"; + src = pkgs.fetchFromGitHub { + owner = "m-labs"; + repo = "jesd204b"; + rev = "bf1cd9014c8b7a9db67609f653634daaf3bcd39b"; + sha256 = "sha256-wyYOCRIPANReeCl+KaIpiAStsn2mzfMlK+cSrUzVrAw="; + }; + propagatedBuildInputs = with pkgs.python3Packages; [ migen misoc ]; + }; + cargo-xbuild = rustPlatform.buildRustPackage rec { pname = "cargo-xbuild"; version = "0.6.5"; @@ -333,7 +345,7 @@ devShell.x86_64-linux = pkgs.mkShell { name = "artiq-dev-shell"; buildInputs = [ - (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ps.paramiko ps.jsonschema ])) + (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc jesd204b artiq ps.paramiko ps.jsonschema ])) rustPlatform.rust.rustc rustPlatform.rust.cargo cargo-xbuild From 501eb1fa23faa173a7f4f5c9f87993b840b1aeee Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Fri, 8 Oct 2021 12:13:58 +0800 Subject: [PATCH 167/238] flake: add microscope --- flake.nix | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 0aa09d2b0..4cb3aea77 100644 --- a/flake.nix +++ b/flake.nix @@ -193,6 +193,18 @@ propagatedBuildInputs = with pkgs.python3Packages; [ migen misoc ]; }; + microscope = pkgs.python3Packages.buildPythonPackage rec { + pname = "microscope"; + version = "unstable-2020-12-28"; + src = pkgs.fetchFromGitHub { + owner = "m-labs"; + repo = "microscope"; + rev = "c21afe7a53258f05bde57e5ebf2e2761f3d495e4"; + sha256 = "sha256-jzyiLRuEf7p8LdhmZvOQj/dyQx8eUE8p6uRlwoiT8vg="; + }; + propagatedBuildInputs = with pkgs.python3Packages; [ pyserial prettytable msgpack migen ]; + }; + cargo-xbuild = rustPlatform.buildRustPackage rec { pname = "cargo-xbuild"; version = "0.6.5"; @@ -345,7 +357,7 @@ devShell.x86_64-linux = pkgs.mkShell { name = "artiq-dev-shell"; buildInputs = [ - (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc jesd204b artiq ps.paramiko ps.jsonschema ])) + (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc jesd204b artiq ps.paramiko ps.jsonschema microscope ])) rustPlatform.rust.rustc rustPlatform.rust.cargo cargo-xbuild From 3f6bf332987c763767952a10630a755927a52978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Thu, 7 Oct 2021 13:47:08 +0000 Subject: [PATCH 168/238] fastino: add interpolator support --- artiq/coredevice/fastino.py | 67 +++++++++++++++++++++++++++++- artiq/gateware/rtio/phy/fastino.py | 43 ++++++++++++++----- 2 files changed, 99 insertions(+), 11 deletions(-) diff --git a/artiq/coredevice/fastino.py b/artiq/coredevice/fastino.py index 73fcfdf38..c60d5d1b1 100644 --- a/artiq/coredevice/fastino.py +++ b/artiq/coredevice/fastino.py @@ -2,7 +2,7 @@ streaming DAC. """ -from artiq.language.core import kernel, portable, delay +from artiq.language.core import kernel, portable, delay, delay_mu from artiq.coredevice.rtio import (rtio_output, rtio_output_wide, rtio_input_data) from artiq.language.units import us @@ -190,3 +190,68 @@ class Fastino: green LED. """ self.write(0x23, leds) + + @kernel + def set_continuous(self, channel_mask): + """Enable continuous DAC updates on channels regardless of new data + being submitted. + """ + self.write(0x25, channel_mask) + + @kernel + def stage_cic_mu(self, rate_mantissa, rate_exponent, gain_exponent): + """Stage machine unit interpolator configuration. + """ + if rate_mantissa < 0 or rate_mantissa >= 1 << 6: + raise ValueError("rate_mantissa out of bounds") + if rate_exponent < 0 or rate_exponent >= 1 << 4: + raise ValueError("rate_exponent out of bounds") + if gain_exponent < 0 or gain_exponent >= 1 << 6: + raise ValueError("gain_exponent out of bounds") + config = rate_mantissa | (rate_exponent << 6) | (gain_exponent << 10) + self.write(0x26, config) + + @kernel + def stage_cic(self, rate) -> TInt32: + """Compute and stage interpolator configuration. + + Approximates rate using 6+4 bit floating point representation, + approximates optimal interpolation gain compensation exponent to avoid + clipping. Gains for rates that are powers of two are accurately + compensated. Other rates lead to overall less than unity gain. + + Returns the actual interpolation rate. + The actual overall interpolation gain including gain compensation is + `actual_rate**order/2**ceil(log2(actual_rate**order))` + where `order = 3`. + """ + if rate <= 0 or rate > 1 << 16: + raise ValueError("rate out of bounds") + rate_mantissa = rate + rate_exponent = 0 + while rate_mantissa > 1 << 6: + rate_exponent += 1 + rate_mantissa >>= 1 + order = 3 + gain = 1 + for i in range(order): + gain *= rate_mantissa + gain_exponent = 0 + while gain > 1 << gain_exponent: + gain_exponent += 1 + gain_exponent += order*rate_exponent + assert gain_exponent <= order*16 + self.stage_cic_mu(rate_mantissa - 1, rate_exponent, gain_exponent) + return rate_mantissa << rate_exponent + + @kernel + def apply_cic(self, channel_mask): + """Apply the staged interpolator configuration on the specified channels. + + Channels using non-unity interpolation rate and variable data should have + continous DAC updates enabled (see :meth:`set_continuous`). + + This resets and settles the interpolators. There will be no output + updates for the next `order = 3` input samples. + """ + self.write(0x27, channel_mask) diff --git a/artiq/gateware/rtio/phy/fastino.py b/artiq/gateware/rtio/phy/fastino.py index ba8a7b5c9..474bab0f3 100644 --- a/artiq/gateware/rtio/phy/fastino.py +++ b/artiq/gateware/rtio/phy/fastino.py @@ -27,16 +27,16 @@ class Fastino(Module): # dac data words dacs = [Signal(16) for i in range(32)] + header = Record([ ("cfg", 4), ("leds", 8), - ("reserved", 8), + ("typ", 1), + ("reserved", 7), ("addr", 4), ("enable", len(dacs)), ]) - body = Cat(header.raw_bits(), dacs) - assert len(body) == len(self.serializer.payload) - self.comb += self.serializer.payload.eq(body) + assert len(Cat(header.raw_bits(), dacs)) == len(self.serializer.payload) # # # @@ -62,38 +62,61 @@ class Fastino(Module): # address space is sparse. hold = Signal.like(header.enable) + continuous = Signal.like(header.enable) + cic_config = Signal(16) read_regs = Array([Signal.like(self.serializer.readback) for _ in range(1 << len(header.addr))]) cases = { # update - 0x20: header.enable.eq(header.enable | self.rtlink.o.data), + 0x20: [ + header.enable.eq(self.rtlink.o.data), + header.typ.eq(0), + ], # hold 0x21: hold.eq(self.rtlink.o.data), # cfg 0x22: header.cfg.eq(self.rtlink.o.data), # leds 0x23: header.leds.eq(self.rtlink.o.data), - # reserved + # reserved bits 0x24: header.reserved.eq(self.rtlink.o.data), + # force continuous DAC updates + 0x25: continuous.eq(self.rtlink.o.data), + # interpolator configuration stage + 0x26: cic_config.eq(self.rtlink.o.data), + # interpolator update flags + 0x27: [ + header.enable.eq(self.rtlink.o.data), + header.typ.eq(1), + ], } for i in range(0, len(dacs), width): cases[i] = [ Cat(dacs[i:i + width]).eq(self.rtlink.o.data), - [If(~hold[i + j], + [If(~hold[i + j] & (header.typ == 0), header.enable[i + j].eq(1), ) for j in range(width)] ] + self.comb += [ + If(header.typ == 0, + self.serializer.payload.eq(Cat(header.raw_bits(), dacs)), + ).Else( + self.serializer.payload.eq(Cat(header.raw_bits(), Replicate(cic_config, len(dacs)))), + ), + ] + self.sync.rio_phy += [ If(self.serializer.stb, - header.enable.eq(0), + header.typ.eq(0), + header.enable.eq(continuous), read_regs[header.addr].eq(self.serializer.readback), header.addr.eq(header.addr + 1), ), - If(self.rtlink.o.stb & ~self.rtlink.o.address[-1], - Case(self.rtlink.o.address[:-1], cases), + If(self.rtlink.o.stb, + Case(self.rtlink.o.address, cases), ), ] From 3c1cbf47d231cf81a2b7526294dbd432c851c689 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 10 Oct 2021 16:18:55 +0800 Subject: [PATCH 169/238] phaser: add more slack during init. Closes #1757 --- artiq/coredevice/phaser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index daaed659d..5f7cd7108 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -203,6 +203,7 @@ class Phaser: self.measure_frame_timestamp() if self.frame_tstamp < 0: raise ValueError("frame timestamp measurement timed out") + delay(.1*ms) # reset self.set_cfg(dac_resetb=0, dac_sleep=1, dac_txena=0, From f5100702f608cf34a24349510d29e7708c74a8d5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 10 Oct 2021 20:40:17 +0800 Subject: [PATCH 170/238] runtime: expose rint from libm --- artiq/firmware/ksupport/api.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index 7b219562c..99add22fa 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -101,6 +101,7 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(log10), api!(nextafter), api!(pow), + api!(rint), api!(round), api!(sin), api!(sinh), From 35d21c98d384620f4cc92bb02cf111cb72d60df7 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 11 Oct 2021 08:12:04 +0800 Subject: [PATCH 171/238] Revert "runtime: expose rint from libm" Consistency with NAR3/Zynq where rint is not available. This reverts commit f5100702f608cf34a24349510d29e7708c74a8d5. --- artiq/firmware/ksupport/api.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index 99add22fa..7b219562c 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -101,7 +101,6 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(log10), api!(nextafter), api!(pow), - api!(rint), api!(round), api!(sin), api!(sinh), From 178a86bcdafd16eb40281e527ca396087a58488b Mon Sep 17 00:00:00 2001 From: fanmingyu212 Date: Wed, 13 Oct 2021 22:17:52 -0700 Subject: [PATCH 172/238] master: add an argument to set an experiment subdirectory Signed-off-by: Mingyu Fan --- RELEASE_NOTES.rst | 2 ++ artiq/frontend/artiq_master.py | 7 ++++++- artiq/master/experiments.py | 10 ++++++---- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 390665643..d9b325382 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -24,6 +24,8 @@ Highlights: - HVAMP_8CH 8 channel HV amplifier for Fastino / Zotino * ``artiq_ddb_template`` generates edge-counter keys that start with the key of the corresponding TTL device (e.g. ``"ttl_0_counter"`` for the edge counter on TTL device``"ttl_0"``) +* ``artiq_master`` now has an ``--experiment-subdir`` option to scan only a subdirectory of the + repository when building the list of experiments. Breaking changes: diff --git a/artiq/frontend/artiq_master.py b/artiq/frontend/artiq_master.py index 1a5073692..ef46fb9bb 100755 --- a/artiq/frontend/artiq_master.py +++ b/artiq/frontend/artiq_master.py @@ -50,6 +50,10 @@ def get_argparser(): group.add_argument( "-r", "--repository", default="repository", help="path to the repository (default: '%(default)s')") + group.add_argument( + "--experiment-subdir", default="", + help=("path to the experiment folder from the repository root " + "(default: '%(default)s')")) log_args(parser) @@ -104,7 +108,8 @@ def main(): repo_backend = GitBackend(args.repository) else: repo_backend = FilesystemBackend(args.repository) - experiment_db = ExperimentDB(repo_backend, worker_handlers) + experiment_db = ExperimentDB( + repo_backend, worker_handlers, args.experiment_subdir) atexit.register(experiment_db.close) scheduler = Scheduler(RIDCounter(), worker_handlers, experiment_db) diff --git a/artiq/master/experiments.py b/artiq/master/experiments.py index b9a46d7ba..918c92dc8 100644 --- a/artiq/master/experiments.py +++ b/artiq/master/experiments.py @@ -74,19 +74,20 @@ class _RepoScanner: entry_dict.update(entries) return entry_dict - async def scan(self, root): + async def scan(self, root, subdir=""): self.worker = Worker(self.worker_handlers) try: - r = await self._scan(root) + r = await self._scan(root, subdir) finally: await self.worker.close() return r class ExperimentDB: - def __init__(self, repo_backend, worker_handlers): + def __init__(self, repo_backend, worker_handlers, experiment_subdir=""): self.repo_backend = repo_backend self.worker_handlers = worker_handlers + self.experiment_subdir = experiment_subdir self.cur_rev = self.repo_backend.get_head_rev() self.repo_backend.request_rev(self.cur_rev) @@ -115,7 +116,8 @@ class ExperimentDB: self.cur_rev = new_cur_rev self.status["cur_rev"] = new_cur_rev t1 = time.monotonic() - new_explist = await _RepoScanner(self.worker_handlers).scan(wd) + new_explist = await _RepoScanner(self.worker_handlers).scan( + wd, self.experiment_subdir) logger.info("repository scan took %d seconds", time.monotonic()-t1) update_from_dict(self.explist, new_explist) finally: From 790a20edf691842d77e9e13dd2291d3f170282e7 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:28:38 +0800 Subject: [PATCH 173/238] linker: generate stack guard + symbol --- artiq/compiler/kernel.ld | 3 +++ artiq/firmware/runtime/runtime.ld | 5 ++++- artiq/firmware/satman/satman.ld | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/artiq/compiler/kernel.ld b/artiq/compiler/kernel.ld index 6523d631a..fafbea2af 100644 --- a/artiq/compiler/kernel.ld +++ b/artiq/compiler/kernel.ld @@ -50,4 +50,7 @@ SECTIONS . = ALIGN(4); _end = .; } + + . = ALIGN(0x1000); + _sstack_guard = .; } diff --git a/artiq/firmware/runtime/runtime.ld b/artiq/firmware/runtime/runtime.ld index 81138fea3..9f60bf3ac 100644 --- a/artiq/firmware/runtime/runtime.ld +++ b/artiq/firmware/runtime/runtime.ld @@ -69,8 +69,11 @@ SECTIONS _ebss = .; } > runtime - .stack (NOLOAD) : ALIGN(16) + .stack (NOLOAD) : ALIGN(0x1000) { + _sstack_guard = .; + . += 0x1000; + _estack = .; . += 0x10000; _fstack = . - 16; } > runtime diff --git a/artiq/firmware/satman/satman.ld b/artiq/firmware/satman/satman.ld index bf7ef51d0..37de797c2 100644 --- a/artiq/firmware/satman/satman.ld +++ b/artiq/firmware/satman/satman.ld @@ -58,8 +58,10 @@ SECTIONS _ebss = .; } > main_ram - .stack (NOLOAD) : ALIGN(16) + .stack (NOLOAD) : ALIGN(0x1000) { + _sstack_guard = .; + . += 0x1000; _estack = .; . += 0x10000; _fstack = . - 16; From a0bf11b465dd62a417c6a80f7890776f538d5f80 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:33:55 +0800 Subject: [PATCH 174/238] riscv: impl pmp --- .../libboard_misoc/riscv32ima/boot.rs | 14 ++++- .../firmware/libboard_misoc/riscv32ima/mod.rs | 1 + .../firmware/libboard_misoc/riscv32ima/pmp.rs | 55 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 artiq/firmware/libboard_misoc/riscv32ima/pmp.rs diff --git a/artiq/firmware/libboard_misoc/riscv32ima/boot.rs b/artiq/firmware/libboard_misoc/riscv32ima/boot.rs index 32e9cfbc3..0d2254da1 100644 --- a/artiq/firmware/libboard_misoc/riscv32ima/boot.rs +++ b/artiq/firmware/libboard_misoc/riscv32ima/boot.rs @@ -1,4 +1,5 @@ -use super::cache; +use super::{cache, pmp}; +use riscv::register::*; pub unsafe fn reset() -> ! { llvm_asm!(r#" @@ -16,3 +17,14 @@ pub unsafe fn jump(addr: usize) -> ! { "# : : "r"(addr) : : "volatile"); loop {} } + +pub unsafe fn start_user(addr: usize) -> ! { + pmp::enable_user_memory(); + mstatus::set_mpp(mstatus::MPP::User); + mepc::write(addr); + llvm_asm!( + "mret" + : : : : "volatile" + ); + unreachable!() +} diff --git a/artiq/firmware/libboard_misoc/riscv32ima/mod.rs b/artiq/firmware/libboard_misoc/riscv32ima/mod.rs index 217ef713f..a8f498adc 100644 --- a/artiq/firmware/libboard_misoc/riscv32ima/mod.rs +++ b/artiq/firmware/libboard_misoc/riscv32ima/mod.rs @@ -1,2 +1,3 @@ pub mod cache; pub mod boot; +pub mod pmp; diff --git a/artiq/firmware/libboard_misoc/riscv32ima/pmp.rs b/artiq/firmware/libboard_misoc/riscv32ima/pmp.rs new file mode 100644 index 000000000..9ac80b9e3 --- /dev/null +++ b/artiq/firmware/libboard_misoc/riscv32ima/pmp.rs @@ -0,0 +1,55 @@ +use riscv::register::{pmpaddr0, pmpaddr1, pmpaddr2, pmpaddr3, pmpcfg0}; + +static mut THREAD_DEPTH: u8 = 0; + +const PMP_L : usize = 0b10000000; +const PMP_NAPOT: usize = 0b00011000; +const PMP_X : usize = 0b00000100; +const PMP_W : usize = 0b00000010; +const PMP_R : usize = 0b00000001; +const PMP_OFF : usize = 0b00000000; + +#[inline(always)] +pub unsafe fn init_stack_guard(guard_base: usize) { + pmpaddr2::write((guard_base >> 2) | ((0x1000 - 1) >> 3)); + pmpcfg0::write((PMP_L | PMP_NAPOT) << 16); +} + +#[inline(always)] +pub fn enable_user_memory() { + pmpaddr3::write((0x80000000 - 1) >> 3); + pmpcfg0::write((PMP_L | PMP_NAPOT | PMP_X | PMP_W | PMP_R) << 24); +} + +#[inline(always)] +pub unsafe fn push_pmp_region(addr: usize) { + let pmp_addr = (addr >> 2) | ((0x1000 - 1) >> 3); + match THREAD_DEPTH { + // Activate PMP0 when switching from main stack to thread + 0 => { + pmpaddr0::write(pmp_addr); + pmpcfg0::write(PMP_NAPOT); + } + + // Temporarily activate PMP1 when spawning a thread from a thread + // The thread should swap back to the main stack very soon after init + 1 => { + pmpaddr1::write(pmp_addr); + pmpcfg0::write(PMP_NAPOT << 8 | PMP_NAPOT); + } + + // Thread *running* another thread should not be possible + _ => unreachable!() + } + THREAD_DEPTH += 1; +} + +#[inline(always)] +pub unsafe fn pop_pmp_region() { + THREAD_DEPTH -= 1; + match THREAD_DEPTH { + 0 => pmpcfg0::write(PMP_OFF), + 1 => pmpcfg0::write(PMP_NAPOT), + _ => unreachable!() + } +} From 27a7a966265293427ca4df73e51816615cf9fccf Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:34:56 +0800 Subject: [PATCH 175/238] runtime: setup pmp + transfer to user --- artiq/firmware/runtime/main.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index c04ec3a05..45e73d78c 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -29,7 +29,7 @@ use core::cell::RefCell; use core::convert::TryFrom; use smoltcp::wire::IpCidr; -use board_misoc::{csr, ident, clock, spiflash, config, net_settings}; +use board_misoc::{csr, ident, clock, spiflash, config, net_settings, pmp, boot}; #[cfg(has_ethmac)] use board_misoc::ethmac; #[cfg(has_drtio)] @@ -247,10 +247,15 @@ pub extern fn main() -> i32 { extern { static mut _fheap: u8; static mut _eheap: u8; + static mut _sstack_guard: u8; } ALLOC.add_range(&mut _fheap, &mut _eheap); - logger_artiq::BufferLogger::new(&mut LOG_BUFFER[..]).register(startup); + pmp::init_stack_guard(&_sstack_guard as *const u8 as usize); + + logger_artiq::BufferLogger::new(&mut LOG_BUFFER[..]).register(|| + boot::start_user(startup as usize) + ); 0 } From 0a59c889de60918d93433b96e5127bf1049613be Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:36:24 +0800 Subject: [PATCH 176/238] satman/kern: init locked PMP on startup --- artiq/firmware/ksupport/lib.rs | 4 +++- artiq/firmware/satman/main.rs | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index aaedbd018..f4a0ec2c7 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -23,7 +23,7 @@ use proto_artiq::{kernel_proto, rpc_proto}; use kernel_proto::*; #[cfg(has_rtio_dma)] use board_misoc::csr; -use riscv::register::{mcause, mepc}; +use riscv::register::{mcause, mepc, mtval}; fn send(request: &Message) { unsafe { mailbox::send(request as *const _ as usize) } @@ -493,11 +493,13 @@ pub unsafe fn main() { let _end = library.lookup(b"_end").unwrap(); let __modinit__ = library.lookup(b"__modinit__").unwrap(); let typeinfo = library.lookup(b"typeinfo"); + let _sstack_guard = library.lookup(b"_sstack_guard").unwrap(); LIBRARY = Some(library); ptr::write_bytes(__bss_start as *mut u8, 0, (_end - __bss_start) as usize); + board_misoc::pmp::init_stack_guard(_sstack_guard as usize); board_misoc::cache::flush_cpu_dcache(); board_misoc::cache::flush_cpu_icache(); diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index f9e3d9e7c..ef639b7f1 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -9,7 +9,7 @@ extern crate board_artiq; extern crate riscv; use core::convert::TryFrom; -use board_misoc::{csr, ident, clock, uart_logger, i2c}; +use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp}; #[cfg(has_si5324)] use board_artiq::si5324; #[cfg(has_wrpll)] @@ -449,6 +449,14 @@ const SI5324_SETTINGS: si5324::FrequencySettings #[no_mangle] pub extern fn main() -> i32 { + extern { + static mut _sstack_guard: u8; + } + + unsafe { + pmp::init_stack_guard(&_sstack_guard as *const u8 as usize); + } + clock::init(); uart_logger::ConsoleLogger::register(); From 46326716fd77e58678885773602fb583acfcf489 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:38:30 +0800 Subject: [PATCH 177/238] runtime: bump libfringe, impl ecall abi See libfringe PR: https://git.m-labs.hk/M-Labs/libfringe/pulls/1 --- artiq/firmware/Cargo.lock | 4 ++-- artiq/firmware/runtime/Cargo.toml | 2 +- artiq/firmware/runtime/main.rs | 12 ++++++++++++ artiq/firmware/runtime/sched.rs | 3 ++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 194952672..dd890c625 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "fringe" version = "1.2.1" -source = "git+https://git.m-labs.hk/M-Labs/libfringe.git?rev=9748bb#9748bb8af86c131d45be1238ea4d5f965a974630" +source = "git+https://git.m-labs.hk/M-Labs/libfringe.git?rev=3ecbe5#3ecbe53f7644b18ee46ebd5b2ca12c9cbceec43a" dependencies = [ - "libc 0.2.101", + "libc 0.2.103", ] [[package]] diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index a29acbb86..ee987ad2d 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -32,6 +32,6 @@ riscv = { version = "0.6.0", features = ["inline-asm"] } [dependencies.fringe] git = "https://git.m-labs.hk/M-Labs/libfringe.git" -rev = "9748bb" +rev = "3ecbe5" default-features = false features = ["alloc"] diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 45e73d78c..04af01be0 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -290,6 +290,18 @@ pub extern fn exception(regs: *const TrapFrame) { mcause::Trap::Interrupt(source) => { info!("Called interrupt with {:?}", source); }, + + mcause::Trap::Exception(mcause::Exception::UserEnvCall) => { + unsafe { + if (*regs).a7 == 0 { + pmp::pop_pmp_region() + } else { + pmp::push_pmp_region((*regs).a7) + } + } + mepc::write(pc + 4); + }, + mcause::Trap::Exception(e) => { println!("Trap frame: {:x?}", unsafe { *regs }); diff --git a/artiq/firmware/runtime/sched.rs b/artiq/firmware/runtime/sched.rs index 7b182a3e4..d6a347269 100644 --- a/artiq/firmware/runtime/sched.rs +++ b/artiq/firmware/runtime/sched.rs @@ -61,7 +61,8 @@ impl Thread { let spawned = io.spawned.clone(); let sockets = io.sockets.clone(); - let stack = OwnedStack::new(stack_size); + // Add a 4k stack guard to the stack of any new threads + let stack = OwnedStack::new(stack_size + 4096); ThreadHandle::new(Thread { generator: Generator::unsafe_new(stack, |yielder, _| { f(Io { From 6d3164a9128d6896777f8e60a250229483b9b2df Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:41:01 +0800 Subject: [PATCH 178/238] riscv: print mtval on panic --- artiq/firmware/bootloader/main.rs | 5 +++-- artiq/firmware/ksupport/lib.rs | 3 ++- artiq/firmware/runtime/main.rs | 5 +++-- artiq/firmware/satman/main.rs | 5 +++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/artiq/firmware/bootloader/main.rs b/artiq/firmware/bootloader/main.rs index 1ef7426a1..9a41bdb4b 100644 --- a/artiq/firmware/bootloader/main.rs +++ b/artiq/firmware/bootloader/main.rs @@ -17,7 +17,7 @@ use board_misoc::slave_fpga; #[cfg(has_ethmac)] use board_misoc::{clock, ethmac, net_settings}; use board_misoc::uart_console::Console; -use riscv::register::{mcause, mepc}; +use riscv::register::{mcause, mepc, mtval}; fn check_integrity() -> bool { extern { @@ -522,7 +522,8 @@ pub extern fn main() -> i32 { pub extern fn exception(_regs: *const u32) { let pc = mepc::read(); let cause = mcause::read().cause(); - panic!("{:?} at PC {:#08x}", cause, u32::try_from(pc).unwrap()) + let mtval = mtval::read(); + panic!("{:?} at PC {:#08x}, trap value {:#08x}", cause, u32::try_from(pc).unwrap(), mtval); } #[no_mangle] diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index f4a0ec2c7..d915d7e81 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -532,7 +532,8 @@ pub unsafe fn main() { pub extern fn exception(_regs: *const u32) { let pc = mepc::read(); let cause = mcause::read().cause(); - panic!("{:?} at PC {:#08x}", cause, u32::try_from(pc).unwrap()) + let mtval = mtval::read(); + panic!("{:?} at PC {:#08x}, trap value {:#08x}", cause, u32::try_from(pc).unwrap(), mtval); } #[no_mangle] diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 04af01be0..45fb76f91 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -40,7 +40,7 @@ use proto_artiq::{mgmt_proto, moninj_proto, rpc_proto, session_proto, kernel_pro #[cfg(has_rtio_analyzer)] use proto_artiq::analyzer_proto; -use riscv::register::{mcause, mepc}; +use riscv::register::{mcause, mepc, mtval}; mod rtio_clocking; mod rtio_mgt; @@ -319,7 +319,8 @@ pub extern fn exception(regs: *const TrapFrame) { } hexdump(u32::try_from(pc).unwrap()); - panic!("exception {:?} at PC 0x{:x}", e, u32::try_from(pc).unwrap()) + let mtval = mtval::read(); + panic!("exception {:?} at PC 0x{:x}, trap value 0x{:x}", e, u32::try_from(pc).unwrap(), mtval) } } } diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index ef639b7f1..e0ec83612 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -18,7 +18,7 @@ use board_artiq::{spi, drtioaux}; use board_artiq::drtio_routing; #[cfg(has_hmc830_7043)] use board_artiq::hmc830_7043; -use riscv::register::{mcause, mepc}; +use riscv::register::{mcause, mepc, mtval}; mod repeater; #[cfg(has_jdcg)] @@ -670,7 +670,8 @@ pub extern fn exception(_regs: *const u32) { } hexdump(u32::try_from(pc).unwrap()); - panic!("exception {:?} at PC 0x{:x}", cause, u32::try_from(pc).unwrap()) + let mtval = mtval::read(); + panic!("exception {:?} at PC 0x{:x}, trap value 0x{:x}", cause, u32::try_from(pc).unwrap(), mtval) } #[no_mangle] From d5fa3d131ac957c3d1fb0eed19bf5773b9bf664c Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:52:23 +0800 Subject: [PATCH 179/238] cargo.lock: update libc version for libfringe --- artiq/firmware/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index dd890c625..77d262538 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -165,7 +165,7 @@ name = "fringe" version = "1.2.1" source = "git+https://git.m-labs.hk/M-Labs/libfringe.git?rev=3ecbe5#3ecbe53f7644b18ee46ebd5b2ca12c9cbceec43a" dependencies = [ - "libc 0.2.103", + "libc 0.2.101", ] [[package]] From bf180c168c9276937210eb6326785035335e9a92 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 16:41:58 +0800 Subject: [PATCH 180/238] flake.lock: update dependencies --- flake.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/flake.lock b/flake.lock index e97a38179..e0cc41607 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1631098960, - "narHash": "sha256-6j6G/omHEFAnI2x7UvdrviGDNqiq1Fjd1A58Q6uc4sQ=", + "lastModified": 1633625029, + "narHash": "sha256-Ia3kwnN9DhcskAIElLSKb4u/OK7nZU/P0TkaikAX790=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "12eb1d16ae3b6cbf0ea83e9228bca8ffd7cfe347", + "rev": "781b1f8e3a2194e1e233cd62b4f2193e129a07f7", "type": "github" }, "original": { @@ -45,11 +45,11 @@ "src-migen": { "flake": false, "locked": { - "lastModified": 1628592379, - "narHash": "sha256-TQV6p0+Ri9HVge4qUKOCXe96cmcimNZ3R4sVwNY67DA=", + "lastModified": 1633615575, + "narHash": "sha256-frh+WVOkEKMpVEMhdE/GZKSj82XnSC8OF8SWNluk/Yg=", "owner": "m-labs", "repo": "migen", - "rev": "27dbf03edd75c32dc1706e2a1316950c3a8d452a", + "rev": "6e3f8e565704b4293174aedfb15b3470d233f528", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1631240866, - "narHash": "sha256-dal999XLFvS8Ol1hZnQjx7q/UfAXkzSMhAWcZKCDPx4=", + "lastModified": 1633679103, + "narHash": "sha256-1BPWfwetUZZCCZ+ldNKJvNm7Gls1AkmGYSZapNuM65s=", "ref": "master", - "rev": "c9572e777febf7abcfbebf624e0323d82600f267", - "revCount": 2371, + "rev": "7c1f614ed3ad9ce0fd3291feccb1e5e4ff65adb3", + "revCount": 2372, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" @@ -95,11 +95,11 @@ "src-sipyco": { "flake": false, "locked": { - "lastModified": 1623807309, - "narHash": "sha256-FTRAS4RjqDOygu6+cP8mKbZHu/YZ7YKpEe2gSzJc9rk=", + "lastModified": 1632832039, + "narHash": "sha256-GYXXCCOxNZyy6j7qScB3/QWUUCEVX+4tM4bXXVGXty0=", "owner": "m-labs", "repo": "sipyco", - "rev": "20c946aad78872fe60b78d9b57a624d69f3eea47", + "rev": "b83d8e5d82b25dba9393f0c12bdc5253f8138545", "type": "github" }, "original": { From 92cdfac35a969d851fda610802b96a576b8f9e76 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 16 Oct 2021 18:20:25 +0800 Subject: [PATCH 181/238] flake: fix cargoDeps sha256 --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 4cb3aea77..e44d4af74 100644 --- a/flake.nix +++ b/flake.nix @@ -238,7 +238,7 @@ cargoDeps = rustPlatform.fetchCargoTarball { name = "artiq-firmware-cargo-deps"; src = "${self}/artiq/firmware"; - sha256 = "0hh9x34gs81a8g15abka6a0z1wlankra13rbap5j7ba2r8cz4962"; + sha256 = "sha256-Lf6M4M/jdRiO5MsWSoqtOSNfRIhbze+qvg4kaiiBWW4="; }; nativeBuildInputs = [ (pkgs.python3.withPackages(ps: [ migen misoc artiq ])) From b0cbad530b4d8f28a8496f4aae258c4a30edef77 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 16 Oct 2021 19:10:28 +0800 Subject: [PATCH 182/238] flake: update dependencies --- flake.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index e0cc41607..a8bdf14b9 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1633625029, - "narHash": "sha256-Ia3kwnN9DhcskAIElLSKb4u/OK7nZU/P0TkaikAX790=", + "lastModified": 1634327140, + "narHash": "sha256-d5L7oMjUVC6VU0cQMsF0tceAPkmzuAQ51DWBFNChbEQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "781b1f8e3a2194e1e233cd62b4f2193e129a07f7", + "rev": "83667ff60a88e22b76ef4b0bdf5334670b39c2b6", "type": "github" }, "original": { @@ -45,11 +45,11 @@ "src-migen": { "flake": false, "locked": { - "lastModified": 1633615575, - "narHash": "sha256-frh+WVOkEKMpVEMhdE/GZKSj82XnSC8OF8SWNluk/Yg=", + "lastModified": 1634182166, + "narHash": "sha256-Iw2d8fCgwuuIevkugSqd8Iplj6N+2nR1pn+or5E38Fk=", "owner": "m-labs", "repo": "migen", - "rev": "6e3f8e565704b4293174aedfb15b3470d233f528", + "rev": "7507a2bb16dd2cac63535175ce67fb30dfdae1c0", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1633679103, - "narHash": "sha256-1BPWfwetUZZCCZ+ldNKJvNm7Gls1AkmGYSZapNuM65s=", + "lastModified": 1634382477, + "narHash": "sha256-onIK8GhU6ZbFXsPXEs8IbAnCMZ6q8G9vJawNCWoF6JM=", "ref": "master", - "rev": "7c1f614ed3ad9ce0fd3291feccb1e5e4ff65adb3", - "revCount": 2372, + "rev": "794d29b6c0f10b3764372f89507dd363bb76b5b1", + "revCount": 2373, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From bb61f2dae6ce66edf72393eb49715c896119eaad Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 18 Oct 2021 10:38:28 +0800 Subject: [PATCH 183/238] flake: update dependencies --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index a8bdf14b9..eacc3db64 100644 --- a/flake.lock +++ b/flake.lock @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1634382477, - "narHash": "sha256-onIK8GhU6ZbFXsPXEs8IbAnCMZ6q8G9vJawNCWoF6JM=", + "lastModified": 1634524544, + "narHash": "sha256-/x9CPW0mnUR6hgHWzOSJY//P9k9w+gObNn2uwrxL8dw=", "ref": "master", - "rev": "794d29b6c0f10b3764372f89507dd363bb76b5b1", - "revCount": 2373, + "rev": "2acffae0ee51e569dc217a9f3cea06b33103d623", + "revCount": 2374, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From df6aeb99f6da58dc76deb30f92a32a2bcf1d6589 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 18 Oct 2021 11:09:10 +0800 Subject: [PATCH 184/238] flake: check gateware timing --- flake.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index e44d4af74..5d106f666 100644 --- a/flake.nix +++ b/flake.nix @@ -260,7 +260,9 @@ export TARGET_AR=llvm-ar ${buildCommand} ''; - checkPhase = '' + doCheck = true; + checkPhase = + '' # Search for PCREs in the Vivado output to check for errors check_log() { grep -Pe "$1" artiq_${target}/${variant}/gateware/vivado.log && exit 1 || true From cc15a4f5729f28b6a2d3d9bbd1c58a3032e5be21 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 21 Oct 2021 11:24:55 +0800 Subject: [PATCH 185/238] flake: update Vivado --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 5d106f666..1f5e2afef 100644 --- a/flake.nix +++ b/flake.nix @@ -227,7 +227,7 @@ vivado = pkgs.buildFHSUserEnv { name = "vivado"; targetPkgs = vivadoDeps; - profile = "source /opt/Xilinx/Vivado/2020.1/settings64.sh"; + profile = "source /opt/Xilinx/Vivado/2021.1/settings64.sh"; runScript = "vivado"; }; From 43eab14f566d7205ea1261151c3078a17df0970a Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 21 Oct 2021 15:06:38 +0800 Subject: [PATCH 186/238] flake: update dependencies --- flake.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index eacc3db64..e9c80a1ad 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1634327140, - "narHash": "sha256-d5L7oMjUVC6VU0cQMsF0tceAPkmzuAQ51DWBFNChbEQ=", + "lastModified": 1634758644, + "narHash": "sha256-H3UW/msC6wadg28lcgZv2Ge/P7dWxesL6i37a0GOeyM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "83667ff60a88e22b76ef4b0bdf5334670b39c2b6", + "rev": "70904d4a9927a4d6e05c72c4aaac4370e05107f3", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1634524544, - "narHash": "sha256-/x9CPW0mnUR6hgHWzOSJY//P9k9w+gObNn2uwrxL8dw=", + "lastModified": 1634799783, + "narHash": "sha256-CbeXsLTwwYBWb5cfrVVYkcQYV207gi9+CQhzfeZbXGc=", "ref": "master", - "rev": "2acffae0ee51e569dc217a9f3cea06b33103d623", - "revCount": 2374, + "rev": "855914deace34880c69589022c52a8921f431063", + "revCount": 2375, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From 0aa8a739aa076c821eb712bb2fb97967dbdb5c9a Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Mon, 25 Oct 2021 09:53:40 +0800 Subject: [PATCH 187/238] sayma_rtm: fix RTM firmware not in little-endian for RISC-V --- artiq/gateware/targets/sayma_rtm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/gateware/targets/sayma_rtm.py b/artiq/gateware/targets/sayma_rtm.py index b4401e9e0..7fa740381 100755 --- a/artiq/gateware/targets/sayma_rtm.py +++ b/artiq/gateware/targets/sayma_rtm.py @@ -240,7 +240,7 @@ class SatmanSoCBuilder(Builder): "satman.bin") with open(satman, "rb") as boot_file: boot_data = [] - unpack_endian = ">I" + unpack_endian = " Date: Thu, 21 Oct 2021 15:00:48 +0800 Subject: [PATCH 188/238] artiq_flash: fix gateware header not in little-endian for RISC-V --- artiq/frontend/artiq_flash.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index d7a5bdb78..1641e31fd 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -418,8 +418,8 @@ def main(): magic = 0x5352544d # "SRTM", see sayma_rtm target length = bin_file.tell() - 8 bin_file.seek(0) - bin_file.write(magic.to_bytes(4, byteorder="big")) - bin_file.write(length.to_bytes(4, byteorder="big")) + bin_file.write(magic.to_bytes(4, byteorder="little")) + bin_file.write(length.to_bytes(4, byteorder="little")) atexit.register(lambda: os.unlink(bin_filename)) return bin_filename From 10c37b87ecfc8b893bb8e5f8b4acc7e3b674ac54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Wed, 27 Oct 2021 20:24:58 +0000 Subject: [PATCH 189/238] fastino: make driver filter order configurable --- artiq/coredevice/fastino.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/artiq/coredevice/fastino.py b/artiq/coredevice/fastino.py index c60d5d1b1..588a3d436 100644 --- a/artiq/coredevice/fastino.py +++ b/artiq/coredevice/fastino.py @@ -39,13 +39,15 @@ class Fastino: :param core_device: Core device name (default: "core") :param log2_width: Width of DAC channel group (logarithm base 2). Value must match the corresponding value in the RTIO PHY (gateware). + :param order: CIC filter interpolation order. """ - kernel_invariants = {"core", "channel", "width"} + kernel_invariants = {"core", "channel", "width", "order"} - def __init__(self, dmgr, channel, core_device="core", log2_width=0): + def __init__(self, dmgr, channel, core_device="core", log2_width=0, order=3): self.channel = channel << 8 self.core = dmgr.get(core_device) self.width = 1 << log2_width + self.order = order @kernel def init(self): @@ -222,8 +224,7 @@ class Fastino: Returns the actual interpolation rate. The actual overall interpolation gain including gain compensation is - `actual_rate**order/2**ceil(log2(actual_rate**order))` - where `order = 3`. + `actual_rate**order/2**ceil(log2(actual_rate**order))`. """ if rate <= 0 or rate > 1 << 16: raise ValueError("rate out of bounds") @@ -232,15 +233,14 @@ class Fastino: while rate_mantissa > 1 << 6: rate_exponent += 1 rate_mantissa >>= 1 - order = 3 gain = 1 - for i in range(order): + for i in range(self.order): gain *= rate_mantissa gain_exponent = 0 while gain > 1 << gain_exponent: gain_exponent += 1 - gain_exponent += order*rate_exponent - assert gain_exponent <= order*16 + gain_exponent += self.order*rate_exponent + assert gain_exponent <= self.order*16 self.stage_cic_mu(rate_mantissa - 1, rate_exponent, gain_exponent) return rate_mantissa << rate_exponent @@ -252,6 +252,6 @@ class Fastino: continous DAC updates enabled (see :meth:`set_continuous`). This resets and settles the interpolators. There will be no output - updates for the next `order = 3` input samples. + updates for the next `order` input samples. """ self.write(0x27, channel_mask) From 1ff474893df1a07399208c8dddbe3dec09879aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Thu, 28 Oct 2021 06:29:56 +0000 Subject: [PATCH 190/238] Revert "fastino: make driver filter order configurable" This reverts commit 10c37b87ecfc8b893bb8e5f8b4acc7e3b674ac54. --- artiq/coredevice/fastino.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/artiq/coredevice/fastino.py b/artiq/coredevice/fastino.py index 588a3d436..c60d5d1b1 100644 --- a/artiq/coredevice/fastino.py +++ b/artiq/coredevice/fastino.py @@ -39,15 +39,13 @@ class Fastino: :param core_device: Core device name (default: "core") :param log2_width: Width of DAC channel group (logarithm base 2). Value must match the corresponding value in the RTIO PHY (gateware). - :param order: CIC filter interpolation order. """ - kernel_invariants = {"core", "channel", "width", "order"} + kernel_invariants = {"core", "channel", "width"} - def __init__(self, dmgr, channel, core_device="core", log2_width=0, order=3): + def __init__(self, dmgr, channel, core_device="core", log2_width=0): self.channel = channel << 8 self.core = dmgr.get(core_device) self.width = 1 << log2_width - self.order = order @kernel def init(self): @@ -224,7 +222,8 @@ class Fastino: Returns the actual interpolation rate. The actual overall interpolation gain including gain compensation is - `actual_rate**order/2**ceil(log2(actual_rate**order))`. + `actual_rate**order/2**ceil(log2(actual_rate**order))` + where `order = 3`. """ if rate <= 0 or rate > 1 << 16: raise ValueError("rate out of bounds") @@ -233,14 +232,15 @@ class Fastino: while rate_mantissa > 1 << 6: rate_exponent += 1 rate_mantissa >>= 1 + order = 3 gain = 1 - for i in range(self.order): + for i in range(order): gain *= rate_mantissa gain_exponent = 0 while gain > 1 << gain_exponent: gain_exponent += 1 - gain_exponent += self.order*rate_exponent - assert gain_exponent <= self.order*16 + gain_exponent += order*rate_exponent + assert gain_exponent <= order*16 self.stage_cic_mu(rate_mantissa - 1, rate_exponent, gain_exponent) return rate_mantissa << rate_exponent @@ -252,6 +252,6 @@ class Fastino: continous DAC updates enabled (see :meth:`set_continuous`). This resets and settles the interpolators. There will be no output - updates for the next `order` input samples. + updates for the next `order = 3` input samples. """ self.write(0x27, channel_mask) From 21b07dc6673454b74ac9116cad59df65e6d9a467 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Wed, 27 Oct 2021 17:01:03 +0800 Subject: [PATCH 191/238] flake: fix missing freetype & fontconfig libs for Vivado GUI mode --- flake.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index 1f5e2afef..a43321d0e 100644 --- a/flake.nix +++ b/flake.nix @@ -42,6 +42,8 @@ xorg.libXext xorg.libXtst xorg.libXi + freetype + fontconfig ]; sipyco = pkgs.python3Packages.buildPythonPackage { From 9b1d7e297d6afb98a8aa36fc18a4d30e97dbfba1 Mon Sep 17 00:00:00 2001 From: Spaqin Date: Thu, 28 Oct 2021 16:21:51 +0800 Subject: [PATCH 192/238] runtime: clock input specification improvements closes #1735 --- RELEASE_NOTES.rst | 2 + artiq/firmware/runtime/rtio_clocking.rs | 252 ++++++++++++++---------- doc/manual/core_device.rst | 17 +- doc/manual/installing.rst | 16 +- 4 files changed, 183 insertions(+), 104 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index d9b325382..c743f2005 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -26,6 +26,8 @@ Highlights: TTL device (e.g. ``"ttl_0_counter"`` for the edge counter on TTL device``"ttl_0"``) * ``artiq_master`` now has an ``--experiment-subdir`` option to scan only a subdirectory of the repository when building the list of experiments. +* The configuration entry ``rtio_clock`` supports multiple clocking settings, deprecating the usage + of compile-time options. Breaking changes: diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index b6cf5f395..8f2560ead 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -4,29 +4,66 @@ use board_artiq::si5324; #[cfg(has_drtio)] use board_misoc::{csr, clock}; -#[derive(Debug)] +#[derive(Debug, PartialEq)] +#[allow(non_camel_case_types)] pub enum RtioClock { - Internal = 0, - External = 1 + Default, + Int_125, + Int_100, + Int_150, + Ext0_Bypass, + Ext0_Synth0_10to125, + Ext0_Synth0_100to125, + Ext0_Synth0_125to125, } +#[allow(unreachable_code)] fn get_rtio_clock_cfg() -> RtioClock { - config::read("rtio_clock", |result| { - match result { - Ok(b"i") => { - info!("using internal RTIO clock"); - RtioClock::Internal + config::read_str("rtio_clock", |result| { + let res = match result { + Ok("int_125") => RtioClock::Int_125, + Ok("int_100") => RtioClock::Int_100, + Ok("int_150") => RtioClock::Int_150, + Ok("ext0_bypass") => RtioClock::Ext0_Bypass, + Ok("ext0_bypass_125") => RtioClock::Ext0_Bypass, + Ok("ext0_bypass_100") => RtioClock::Ext0_Bypass, + Ok("ext0_synth0_10to125") => RtioClock::Ext0_Synth0_10to125, + Ok("ext0_synth0_100to125") => RtioClock::Ext0_Synth0_100to125, + Ok("ext0_synth0_125to125") => RtioClock::Ext0_Synth0_125to125, + Ok("i") => { + warn!("Using legacy rtio_clock setting ('i'). Falling back to default. This will be deprecated."); + RtioClock::Default }, - Ok(b"e") => { - info!("using external RTIO clock"); - RtioClock::External + Ok("e") => { + warn!("Using legacy rtio_clock setting ('e'). This will be deprecated."); + RtioClock::Ext0_Bypass }, _ => { - info!("using internal RTIO clock (by default)"); - RtioClock::Internal - }, + warn!("rtio_clock setting not recognised. Falling back to default."); + RtioClock::Default + } + }; + if res == RtioClock::Default { + #[cfg(any(si5324_ext_ref, ext_ref_frequency))] + warn!("si5324_ext_ref and ext_ref_frequency compile-time options are deprecated. Please use the rtio_clock coreconfig settings instead."); + #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "10.0"))] + return RtioClock::Ext0_Synth0_10to125; + #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "100.0"))] + return RtioClock::Ext0_Synth0_100to125; + #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "125.0"))] + return RtioClock::Ext0_Synth0_125to125; + #[cfg(all(rtio_frequency = "125.0", not(si5324_ext_ref)))] + return RtioClock::Int_125; + #[cfg(all(rtio_frequency = "150.0", not(si5324_ext_ref)))] + return RtioClock::Int_150; + #[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref)))] + return RtioClock::Int_100; + //in case nothing is set + return RtioClock::Int_125; } - }) + res + }) + } #[cfg(has_rtio_crg)] @@ -41,9 +78,19 @@ pub mod crg { #[cfg(has_rtio_clock_switch)] pub fn init(clk: RtioClock) -> bool { + let clk_sel: u8 = match clk { + RtioClock::Ext0_Bypass => { + info!("Using external clock"); + 1 + }, + _ => { + info!("Using internal RTIO clock"); + 0 + } + }; unsafe { csr::rtio_crg::pll_reset_write(1); - csr::rtio_crg::clock_sel_write(clk as u8); + csr::rtio_crg::clock_sel_write(clk_sel); csr::rtio_crg::pll_reset_write(0); } clock::spin_us(150); @@ -52,6 +99,7 @@ pub mod crg { #[cfg(not(has_rtio_clock_switch))] pub fn init() -> bool { + info!("Using internal RTIO clock"); unsafe { csr::rtio_crg::pll_reset_write(0); } @@ -66,84 +114,86 @@ pub mod crg { } #[cfg(si5324_as_synthesizer)] -fn setup_si5324_as_synthesizer() { - // 125 MHz output from 10 MHz CLKINx reference, 504 Hz BW - #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "10.0"))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 10, - nc1_ls : 4, - n2_hs : 10, - n2_ls : 300, - n31 : 6, - n32 : 6, - bwsel : 4, - crystal_ref: false - }; - // 125MHz output, from 100MHz CLKINx reference, 586 Hz loop bandwidth - #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "100.0"))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 10, - nc1_ls : 4, - n2_hs : 10, - n2_ls : 260, - n31 : 52, - n32 : 52, - bwsel : 4, - crystal_ref: false - }; - // 125MHz output, from 125MHz CLKINx reference, 606 Hz loop bandwidth - #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "125.0"))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 5, - nc1_ls : 8, - n2_hs : 7, - n2_ls : 360, - n31 : 63, - n32 : 63, - bwsel : 4, - crystal_ref: false - }; - // 125MHz output, from crystal, 7 Hz - #[cfg(all(rtio_frequency = "125.0", not(si5324_ext_ref)))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 10, - nc1_ls : 4, - n2_hs : 10, - n2_ls : 19972, - n31 : 4565, - n32 : 4565, - bwsel : 4, - crystal_ref: true - }; - // 150MHz output, from crystal - #[cfg(all(rtio_frequency = "150.0", not(si5324_ext_ref)))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 9, - nc1_ls : 4, - n2_hs : 10, - n2_ls : 33732, - n31 : 7139, - n32 : 7139, - bwsel : 3, - crystal_ref: true - }; - // 100MHz output, from crystal. Also used as reference for Sayma HMC830. - #[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref)))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 9, - nc1_ls : 6, - n2_hs : 10, - n2_ls : 33732, - n31 : 7139, - n32 : 7139, - bwsel : 3, - crystal_ref: true +fn setup_si5324_as_synthesizer(cfg: RtioClock) { + let si5324_settings = match cfg { + RtioClock::Ext0_Synth0_10to125 => { // 125 MHz output from 10 MHz CLKINx reference, 504 Hz BW + info!("using 10MHz reference to make 125MHz RTIO clock with PLL"); + si5324::FrequencySettings { + n1_hs : 10, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 300, + n31 : 6, + n32 : 6, + bwsel : 4, + crystal_ref: false + } + }, + RtioClock::Ext0_Synth0_100to125 => { // 125MHz output, from 100MHz CLKINx reference, 586 Hz loop bandwidth + info!("using 10MHz reference to make 125MHz RTIO clock with PLL"); + si5324::FrequencySettings { + n1_hs : 10, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 260, + n31 : 52, + n32 : 52, + bwsel : 4, + crystal_ref: false + } + }, + RtioClock::Ext0_Synth0_125to125 => { // 125MHz output, from 125MHz CLKINx reference, 606 Hz loop bandwidth + info!("using 10MHz reference to make 125MHz RTIO clock with PLL"); + si5324::FrequencySettings { + n1_hs : 5, + nc1_ls : 8, + n2_hs : 7, + n2_ls : 360, + n31 : 63, + n32 : 63, + bwsel : 4, + crystal_ref: false + } + }, + RtioClock::Int_150 => { // 150MHz output, from crystal + info!("using internal 150MHz RTIO clock"); + si5324::FrequencySettings { + n1_hs : 9, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 33732, + n31 : 7139, + n32 : 7139, + bwsel : 3, + crystal_ref: true + } + }, + RtioClock::Int_100 => { // 100MHz output, from crystal. Also used as reference for Sayma HMC830. + info!("using internal 100MHz RTIO clock"); + si5324::FrequencySettings { + n1_hs : 9, + nc1_ls : 6, + n2_hs : 10, + n2_ls : 33732, + n31 : 7139, + n32 : 7139, + bwsel : 3, + crystal_ref: true + } + }, + _ => { // 125MHz output, from crystal, 7 Hz, default (if chosen option is not supported) + info!("using internal 125MHz RTIO clock"); // covers also RtioClock::Int_125 + si5324::FrequencySettings { + n1_hs : 10, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 19972, + n31 : 4565, + n32 : 4565, + bwsel : 4, + crystal_ref: true + } + } }; #[cfg(all(soc_platform = "kasli", hw_rev = "v2.0", not(si5324_ext_ref)))] let si5324_ref_input = si5324::Input::Ckin2; @@ -155,10 +205,11 @@ fn setup_si5324_as_synthesizer() { let si5324_ref_input = si5324::Input::Ckin2; #[cfg(soc_platform = "kc705")] let si5324_ref_input = si5324::Input::Ckin2; - si5324::setup(&SI5324_SETTINGS, si5324_ref_input).expect("cannot initialize Si5324"); + si5324::setup(&si5324_settings, si5324_ref_input).expect("cannot initialize Si5324"); } pub fn init() { + let clock_cfg = get_rtio_clock_cfg(); #[cfg(si5324_as_synthesizer)] { #[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))] @@ -169,9 +220,12 @@ pub fn init() { let si5324_ext_input = si5324::Input::Ckin2; #[cfg(soc_platform = "kc705")] let si5324_ext_input = si5324::Input::Ckin2; - match get_rtio_clock_cfg() { - RtioClock::Internal => setup_si5324_as_synthesizer(), - RtioClock::External => si5324::bypass(si5324_ext_input).expect("cannot bypass Si5324") + match clock_cfg { + RtioClock::Ext0_Bypass => { + info!("using external RTIO clock with PLL bypass"); + si5324::bypass(si5324_ext_input).expect("cannot bypass Si5324") + }, + _ => setup_si5324_as_synthesizer(clock_cfg), } } @@ -189,7 +243,7 @@ pub fn init() { #[cfg(has_rtio_crg)] { #[cfg(has_rtio_clock_switch)] - let result = crg::init(get_rtio_clock_cfg()); + let result = crg::init(clock_cfg); #[cfg(not(has_rtio_clock_switch))] let result = crg::init(); if !result { diff --git a/doc/manual/core_device.rst b/doc/manual/core_device.rst index bb38c2b9e..fa3466d32 100644 --- a/doc/manual/core_device.rst +++ b/doc/manual/core_device.rst @@ -164,6 +164,19 @@ See :mod:`artiq.coredevice.i2c` for more details. Clocking ++++++++ -The KC705 supports an internal 125 MHz RTIO clock (based on its crystal oscillator) and an external clock, that can be selected using the ``rtio_clock`` configuration entry. Valid values are ``i`` and ``e``, and the default is ``i``. The selected option can be observed in the core device boot logs. +The KC705 in standalone variants supports an internal 125 MHz RTIO clock (based on its crystal oscillator, or external reference for PLL for DRTIO variants) and an external clock, that can be selected using the ``rtio_clock`` configuration entry. Valid values are: + * ``int_125`` - internal crystal oscillator, 125 MHz output (default), + * ``ext0_bypass`` - external clock. -On Kasli, ``rtio_clock=i`` is the default and generates the RTIO clock using a PLL locked either to an internal crystal or to an external frequency reference (variant-dependent). ``rtio_clock=e`` bypasses that PLL and the user must supply the RTIO clock (typically 125 MHz) at the Kasli front panel SMA input. Bypassing the PLL ensures the skews between input clock, Kasli downstream clock outputs, and RTIO clock are deterministic accross reboots of the system. This is useful when phase determinism is required in situtations where the reference clock fans out to other devices before reaching Kasli. +KC705 in DRTIO variants and Kasli generates the RTIO clock using a PLL locked either to an internal crystal or to an external frequency reference. Valid values are: + * ``int_125`` - internal crystal oscillator using PLL, 125 MHz output (default), + * ``int_100`` - internal crystal oscillator using PLL, 100 MHz output, + * ``int_150`` - internal crystal oscillator using PLL, 150 MHz output, + * ``ext0_synth0_10to125`` - external 10 MHz reference using PLL, 125 MHz output, + * ``ext0_synth0_100to125`` - external 100 MHz reference using PLL, 125 MHz output, + * ``ext0_synth0_125to125`` - external 125 MHz reference using PLL, 125 MHz output, + * ``ext0_bypass``, ``ext0_bypass_125``, ``ext0_bypass_100`` - external clock - with explicit aliases available. + +The selected option can be observed in the core device boot logs. + +Options ``rtio_clock=int_XXX`` and ``rtio_clock=ext0_synth0_XXXXX`` generate the RTIO clock using a PLL locked either to an internal crystal or to an external frequency reference (depending on exact option). ``rtio_clock=ext0_bypass`` bypasses that PLL and the user must supply the RTIO clock (typically 125 MHz) at the Kasli front panel SMA input. Bypassing the PLL ensures the skews between input clock, Kasli downstream clock outputs, and RTIO clock are deterministic accross reboots of the system. This is useful when phase determinism is required in situtations where the reference clock fans out to other devices before reaching Kasli. diff --git a/doc/manual/installing.rst b/doc/manual/installing.rst index 41b1ebc82..0b9ac8c18 100644 --- a/doc/manual/installing.rst +++ b/doc/manual/installing.rst @@ -288,7 +288,17 @@ If you are using DRTIO and the default routing table (for a star topology) is no * Select the RTIO clock source (KC705 and Kasli) -The KC705 may use either an external clock signal or its internal clock. The clock is selected at power-up. For Kasli, setting the RTIO clock source to "external" would bypass the Si5324 synthesiser, requiring that an input clock be present. To select the source, use one of these commands: :: +The KC705 may use either an external clock signal, or its internal clock with external frequency or internal crystal reference. The clock is selected at power-up. Setting the RTIO clock source to "ext0_bypass" would bypass the Si5324 synthesiser, requiring that an input clock be present. To select the source, use one of these commands: :: - $ artiq_coremgmt config write -s rtio_clock i # internal clock (default) - $ artiq_coremgmt config write -s rtio_clock e # external clock + $ artiq_coremgmt config write -s rtio_clock int_125 # internal 125MHz clock (default) + $ artiq_coremgmt config write -s rtio_clock ext0_bypass # external clock (bypass) + +Other options include: + - ``ext0_synth0_10to125`` - external 10MHz reference clock used by Si5324 to synthesize a 125MHz RTIO clock, + - ``ext0_synth0_100to125`` - exteral 100MHz reference clock used by Si5324 to synthesize a 125MHz RTIO clock, + - ``ext0_synth0_125to125`` - exteral 125MHz reference clock used by Si5324 to synthesize a 125MHz RTIO clock, + - ``int_100`` - internal crystal reference is used by Si5324 to synthesize a 100MHz RTIO clock, + - ``int_150`` - internal crystal reference is used by Si5324 to synthesize a 150MHz RTIO clock. + - ``ext0_bypass_125`` and ``ext0_bypass_100`` - explicit aliases for ``ext0_bypass``. + +Availability of these options depends on the board and their configuration - specific setting may or may not be supported. \ No newline at end of file From 69cddc6b862a85823d28e6339d3a94415e21eee9 Mon Sep 17 00:00:00 2001 From: Spaqin Date: Thu, 28 Oct 2021 16:34:22 +0800 Subject: [PATCH 193/238] rtio_clocking: add warnings for unsupported rtio_clock settings (#1773) --- artiq/firmware/runtime/rtio_clocking.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index 8f2560ead..f0330b4d9 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -83,9 +83,13 @@ pub mod crg { info!("Using external clock"); 1 }, - _ => { + RtioClock::Int_125 => { info!("Using internal RTIO clock"); 0 + }, + _ => { + warn!("rtio_clock setting '{:?}' is not supported. Using default internal RTIO clock instead", clk); + 0 } }; unsafe { @@ -181,8 +185,21 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { crystal_ref: true } }, - _ => { // 125MHz output, from crystal, 7 Hz, default (if chosen option is not supported) - info!("using internal 125MHz RTIO clock"); // covers also RtioClock::Int_125 + RtioClock::Int_125 => { // 125MHz output, from crystal, 7 Hz + info!("using internal 125MHz RTIO clock"); + si5324::FrequencySettings { + n1_hs : 10, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 19972, + n31 : 4565, + n32 : 4565, + bwsel : 4, + crystal_ref: true + } + } + _ => { // 125MHz output like above, default (if chosen option is not supported) + warn!("rtio_clock setting '{:?}' is not supported. Falling back to default internal 125MHz RTIO clock.", cfg); si5324::FrequencySettings { n1_hs : 10, nc1_ls : 4, From 5a5b0cc7c0175bf945c04b44f1aacc504e2f26d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Thu, 28 Oct 2021 15:19:48 +0000 Subject: [PATCH 194/238] fastino: expand docs --- artiq/coredevice/fastino.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/artiq/coredevice/fastino.py b/artiq/coredevice/fastino.py index c60d5d1b1..193a9d9ba 100644 --- a/artiq/coredevice/fastino.py +++ b/artiq/coredevice/fastino.py @@ -200,7 +200,7 @@ class Fastino: @kernel def stage_cic_mu(self, rate_mantissa, rate_exponent, gain_exponent): - """Stage machine unit interpolator configuration. + """Stage machine unit CIC interpolator configuration. """ if rate_mantissa < 0 or rate_mantissa >= 1 << 6: raise ValueError("rate_mantissa out of bounds") @@ -215,15 +215,18 @@ class Fastino: def stage_cic(self, rate) -> TInt32: """Compute and stage interpolator configuration. - Approximates rate using 6+4 bit floating point representation, - approximates optimal interpolation gain compensation exponent to avoid - clipping. Gains for rates that are powers of two are accurately - compensated. Other rates lead to overall less than unity gain. + This method approximates the desired interpolation rate using a 10 bit + floating point representation (6 bit mantissa, 4 bit exponent) and + then determines an optimal interpolation gain compensation exponent + to avoid clipping. Gains for rates that are powers of two are accurately + compensated. Other rates lead to overall less than unity gain (but more + than 0.5 gain). - Returns the actual interpolation rate. - The actual overall interpolation gain including gain compensation is + The overall gain including gain compensation is `actual_rate**order/2**ceil(log2(actual_rate**order))` where `order = 3`. + + Returns the actual interpolation rate. """ if rate <= 0 or rate > 1 << 16: raise ValueError("rate out of bounds") @@ -248,10 +251,21 @@ class Fastino: def apply_cic(self, channel_mask): """Apply the staged interpolator configuration on the specified channels. - Channels using non-unity interpolation rate and variable data should have - continous DAC updates enabled (see :meth:`set_continuous`). + Each Fastino channel includes a fourth order (cubic) CIC interpolator with + variable rate change and variable output gain compensation (see + :meth:`stage_cic`). - This resets and settles the interpolators. There will be no output - updates for the next `order = 3` input samples. + Channels using non-unity interpolation rate should have + continous DAC updates enabled (see :meth:`set_continuous`) unless + their output is supposed to be constant. + + This method resets and settles the affected interpolators. There will be + no output updates for the next `order = 3` input samples. + Affected channels will only accept one input sample per input sample + period. This method synchronizes the input sample period to the current + frame on the affected channels. + + If application of new interpolator settings results in a change of the + overall gain, there will be a corresponding output step. """ self.write(0x27, channel_mask) From 8da924ec0fb5a1358831510b967753adc344936a Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:28:26 +0800 Subject: [PATCH 195/238] dma: set conversion granularity using bus width --- artiq/gateware/rtio/analyzer.py | 23 +++++------------------ artiq/gateware/rtio/dma.py | 32 ++++++++++++-------------------- 2 files changed, 17 insertions(+), 38 deletions(-) diff --git a/artiq/gateware/rtio/analyzer.py b/artiq/gateware/rtio/analyzer.py index 1818d3c43..ef154affa 100644 --- a/artiq/gateware/rtio/analyzer.py +++ b/artiq/gateware/rtio/analyzer.py @@ -3,6 +3,7 @@ from migen.genlib.record import Record, layout_len from misoc.interconnect.csr import * from misoc.interconnect import stream +from artiq.gateware.rtio import dma from artiq.gateware.rtio.cri import commands as cri_commands from artiq.coredevice.comm_analyzer import MessageType, ExceptionType @@ -42,20 +43,6 @@ assert layout_len(exception_layout) == message_len assert layout_len(stopped_layout) == message_len -def convert_signal(signal): - assert len(signal) % 8 == 0 - nbytes = len(signal)//8 - assert nbytes % 4 == 0 - nwords = nbytes//4 - signal_words = [] - for i in range(nwords): - signal_bytes = [] - for j in range(4): - signal_bytes.append(signal[8*(j+i*4):8*((j+i*4)+1)]) - signal_words.extend(reversed(signal_bytes)) - return Cat(*signal_words) - - class MessageEncoder(Module, AutoCSR): def __init__(self, tsc, cri, enable): self.source = stream.Endpoint([("data", message_len)]) @@ -150,7 +137,7 @@ class MessageEncoder(Module, AutoCSR): class DMAWriter(Module, AutoCSR): - def __init__(self, membus): + def __init__(self, membus, cpu_dw): aw = len(membus.adr) dw = len(membus.dat_w) messages_per_dw = dw//message_len @@ -175,7 +162,7 @@ class DMAWriter(Module, AutoCSR): membus.stb.eq(self.sink.stb), self.sink.ack.eq(membus.ack), membus.we.eq(1), - membus.dat_w.eq(convert_signal(self.sink.data)) + membus.dat_w.eq(dma.convert_signal(self.sink.data, cpu_dw//8)) ] if messages_per_dw > 1: for i in range(dw//8): @@ -207,7 +194,7 @@ class DMAWriter(Module, AutoCSR): class Analyzer(Module, AutoCSR): - def __init__(self, tsc, cri, membus, fifo_depth=128): + def __init__(self, tsc, cri, membus, fifo_depth=128, cpu_dw=32): # shutdown procedure: set enable to 0, wait until busy=0 self.enable = CSRStorage() self.busy = CSRStatus() @@ -219,7 +206,7 @@ class Analyzer(Module, AutoCSR): self.submodules.converter = stream.Converter( message_len, len(membus.dat_w), reverse=True, report_valid_token_count=True) - self.submodules.dma = DMAWriter(membus) + self.submodules.dma = DMAWriter(membus, cpu_dw) enable_r = Signal() self.sync += [ diff --git a/artiq/gateware/rtio/dma.py b/artiq/gateware/rtio/dma.py index 84f79dfa8..f81559dde 100644 --- a/artiq/gateware/rtio/dma.py +++ b/artiq/gateware/rtio/dma.py @@ -11,28 +11,20 @@ def _reverse_bytes(s, g): return Cat(reversed(list(s[i*g:(i+1)*g] for i in range(len(s)//g)))) -def reverse_bytes(s): - n = (len(s) + 7)//8 - return Cat(*[s[i*8:min((i + 1)*8, len(s))] - for i in reversed(range(n))]) - - -def convert_signal(signal): +def convert_signal(signal, granularity): assert len(signal) % 8 == 0 nbytes = len(signal)//8 - assert nbytes % 4 == 0 - nwords = nbytes//4 + assert nbytes % granularity == 0 + nwords = nbytes//granularity signal_words = [] for i in range(nwords): - signal_bytes = [] - for j in range(4): - signal_bytes.append(signal[8*(j+i*4):8*((j+i*4)+1)]) - signal_words.extend(reversed(signal_bytes)) - return Cat(*signal_words) + signal_words.append(_reverse_bytes( + signal[i*granularity*8:(i+1)*granularity*8], 8)) + return Cat(signal_words) class WishboneReader(Module): - def __init__(self, bus): + def __init__(self, bus, cpu_dw): self.bus = bus aw = len(bus.adr) @@ -57,18 +49,18 @@ class WishboneReader(Module): If(self.source.ack, data_reg_loaded.eq(0)), If(bus.ack, data_reg_loaded.eq(1), - self.source.data.eq(convert_signal(bus.dat_r)), + self.source.data.eq(convert_signal(bus.dat_r, cpu_dw//8)), self.source.eop.eq(self.sink.eop) ) ] class DMAReader(Module, AutoCSR): - def __init__(self, membus, enable): + def __init__(self, membus, enable, cpu_dw): aw = len(membus.adr) data_alignment = log2_int(len(membus.dat_w)//8) - self.submodules.wb_reader = WishboneReader(membus) + self.submodules.wb_reader = WishboneReader(membus, cpu_dw) self.source = self.wb_reader.source # All numbers in bytes @@ -344,11 +336,11 @@ class CRIMaster(Module, AutoCSR): class DMA(Module): - def __init__(self, membus): + def __init__(self, membus, cpu_dw): self.enable = CSR() flow_enable = Signal() - self.submodules.dma = DMAReader(membus, flow_enable) + self.submodules.dma = DMAReader(membus, flow_enable, cpu_dw) self.submodules.slicer = RecordSlicer(len(membus.dat_w)) self.submodules.time_offset = TimeOffset() self.submodules.cri_master = CRIMaster() From c6e0e264406d647d4fa5210056394bb6b0d713a1 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:29:15 +0800 Subject: [PATCH 196/238] drtio: accept 32b/64b bus --- artiq/gateware/drtio/aux_controller.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/artiq/gateware/drtio/aux_controller.py b/artiq/gateware/drtio/aux_controller.py index 8effda67d..051a03a20 100644 --- a/artiq/gateware/drtio/aux_controller.py +++ b/artiq/gateware/drtio/aux_controller.py @@ -212,14 +212,15 @@ class Receiver(Module, AutoCSR): # TODO: FullMemoryWE should be applied by migen.build @FullMemoryWE() class DRTIOAuxController(Module): - def __init__(self, link_layer): - self.bus = wishbone.Interface() + def __init__(self, link_layer, dw=32): + wsb = log2_int(dw//8) + + self.bus = wishbone.Interface(data_width=dw, adr_width=32-wsb) self.submodules.transmitter = Transmitter(link_layer, len(self.bus.dat_w)) self.submodules.receiver = Receiver(link_layer, len(self.bus.dat_w)) - tx_sdram_if = wishbone.SRAM(self.transmitter.mem, read_only=False) - rx_sdram_if = wishbone.SRAM(self.receiver.mem, read_only=True) - wsb = log2_int(len(self.bus.dat_w)//8) + tx_sdram_if = wishbone.SRAM(self.transmitter.mem, read_only=False, data_width=dw) + rx_sdram_if = wishbone.SRAM(self.receiver.mem, read_only=True, data_width=dw) decoder = wishbone.Decoder(self.bus, [(lambda a: a[log2_int(max_packet)-wsb] == 0, tx_sdram_if.bus), (lambda a: a[log2_int(max_packet)-wsb] == 1, rx_sdram_if.bus)], From dd68b4ab82a9ec1c5badd5db9913d0fecd1e067b Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:30:09 +0800 Subject: [PATCH 197/238] mailbox: parametrize address width --- artiq/gateware/amp/mailbox.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/artiq/gateware/amp/mailbox.py b/artiq/gateware/amp/mailbox.py index 7c60056d1..6c498b821 100644 --- a/artiq/gateware/amp/mailbox.py +++ b/artiq/gateware/amp/mailbox.py @@ -3,9 +3,9 @@ from misoc.interconnect import wishbone class Mailbox(Module): - def __init__(self, size=1): - self.i1 = wishbone.Interface() - self.i2 = wishbone.Interface() + def __init__(self, size=1, adr_width=30): + self.i1 = wishbone.Interface(data_width=32, adr_width=adr_width) + self.i2 = wishbone.Interface(data_width=32, adr_width=adr_width) # # # From d84ad0095b0688f7164cb6a79f4fc3c918de28be Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:36:36 +0800 Subject: [PATCH 198/238] comm_cpu: select 64b bus if not kasli v1.x --- artiq/gateware/targets/kasli.py | 24 +++++++++++++++++++++--- artiq/gateware/targets/kc705.py | 3 +++ artiq/gateware/targets/metlino.py | 1 + artiq/gateware/targets/sayma_amc.py | 1 + artiq/gateware/targets/sayma_rtm.py | 1 + 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index d47b583b1..5cba517a7 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -104,9 +104,15 @@ class StandaloneBase(MiniSoC, AMPSoC): } mem_map.update(MiniSoC.mem_map) - def __init__(self, gateware_identifier_str=None, **kwargs): + def __init__(self, gateware_identifier_str=None, hw_rev="v2.0", **kwargs): + if hw_rev in ("v1.0", "v1.1"): + cpu_bus_width = 32 + else: + cpu_bus_width = 64 MiniSoC.__init__(self, cpu_type="vexriscv", + hw_rev=hw_rev, + cpu_bus_width=cpu_bus_width, sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, @@ -255,9 +261,15 @@ class MasterBase(MiniSoC, AMPSoC): } mem_map.update(MiniSoC.mem_map) - def __init__(self, rtio_clk_freq=125e6, enable_sata=False, gateware_identifier_str=None, **kwargs): + def __init__(self, rtio_clk_freq=125e6, enable_sata=False, gateware_identifier_str=None, hw_rev="v2.0", **kwargs): + if hw_rev in ("v1.0", "v1.1"): + cpu_bus_width = 32 + else: + cpu_bus_width = 64 MiniSoC.__init__(self, cpu_type="vexriscv", + hw_rev=hw_rev, + cpu_bus_width=cpu_bus_width, sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, @@ -431,9 +443,15 @@ class SatelliteBase(BaseSoC): } mem_map.update(BaseSoC.mem_map) - def __init__(self, rtio_clk_freq=125e6, enable_sata=False, *, with_wrpll=False, gateware_identifier_str=None, **kwargs): + def __init__(self, rtio_clk_freq=125e6, enable_sata=False, *, with_wrpll=False, gateware_identifier_str=None, hw_rev="v2.0", **kwargs): + if hw_rev in ("v1.0", "v1.1"): + cpu_bus_width = 32 + else: + cpu_bus_width = 64 BaseSoC.__init__(self, cpu_type="vexriscv", + hw_rev=hw_rev, + cpu_bus_width=cpu_bus_width, sdram_controller_type="minicon", l2_size=128*1024, **kwargs) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 2a6e31d6f..6e1fdd1d4 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -132,6 +132,7 @@ class _StandaloneBase(MiniSoC, AMPSoC): def __init__(self, gateware_identifier_str=None, **kwargs): MiniSoC.__init__(self, cpu_type="vexriscv", + cpu_bus_width=64, sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, @@ -209,6 +210,7 @@ class _MasterBase(MiniSoC, AMPSoC): def __init__(self, gateware_identifier_str=None, **kwargs): MiniSoC.__init__(self, cpu_type="vexriscv", + cpu_bus_width=64, sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, @@ -342,6 +344,7 @@ class _SatelliteBase(BaseSoC): def __init__(self, gateware_identifier_str=None, sma_as_sat=False, **kwargs): BaseSoC.__init__(self, cpu_type="vexriscv", + cpu_bus_width=64, sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, diff --git a/artiq/gateware/targets/metlino.py b/artiq/gateware/targets/metlino.py index 74c2e35f0..107dbc78d 100755 --- a/artiq/gateware/targets/metlino.py +++ b/artiq/gateware/targets/metlino.py @@ -43,6 +43,7 @@ class Master(MiniSoC, AMPSoC): def __init__(self, gateware_identifier_str=None, **kwargs): MiniSoC.__init__(self, cpu_type="vexriscv", + cpu_bus_width=64, sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, diff --git a/artiq/gateware/targets/sayma_amc.py b/artiq/gateware/targets/sayma_amc.py index 6155eb31f..32ebc8521 100755 --- a/artiq/gateware/targets/sayma_amc.py +++ b/artiq/gateware/targets/sayma_amc.py @@ -57,6 +57,7 @@ class SatelliteBase(MiniSoC): def __init__(self, rtio_clk_freq=125e6, identifier_suffix="", gateware_identifier_str=None, with_sfp=False, *, with_wrpll, **kwargs): MiniSoC.__init__(self, cpu_type="vexriscv", + cpu_bus_width=64, sdram_controller_type="minicon", l2_size=128*1024, integrated_sram_size=8192, diff --git a/artiq/gateware/targets/sayma_rtm.py b/artiq/gateware/targets/sayma_rtm.py index 7fa740381..a132601d6 100755 --- a/artiq/gateware/targets/sayma_rtm.py +++ b/artiq/gateware/targets/sayma_rtm.py @@ -37,6 +37,7 @@ class _SatelliteBase(BaseSoC): def __init__(self, rtio_clk_freq, *, with_wrpll, gateware_identifier_str, **kwargs): BaseSoC.__init__(self, cpu_type="vexriscv", + cpu_bus_width=64, **kwargs) add_identifier(self, gateware_identifier_str=gateware_identifier_str) self.rtio_clk_freq = rtio_clk_freq From 90f944481c5cb8efebcc235e27e334e15299c220 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:37:36 +0800 Subject: [PATCH 199/238] kernel_cpu: add fpu if not kasli v1.x --- artiq/gateware/amp/kernel_cpu.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/artiq/gateware/amp/kernel_cpu.py b/artiq/gateware/amp/kernel_cpu.py index a770b4326..bea786be9 100644 --- a/artiq/gateware/amp/kernel_cpu.py +++ b/artiq/gateware/amp/kernel_cpu.py @@ -22,10 +22,10 @@ class KernelCPU(Module): self.cd_sys_kernel.clk.eq(ClockSignal()), self.cd_sys_kernel.rst.eq(self._reset.storage) ] + kasli_v1 = isinstance(platform, kasli.Platform) and platform.hw_rev in ("v1.0", "v1.1") self.submodules.cpu = ClockDomainsRenamer("sys_kernel")( - vexriscv.VexRiscv( - platform, - exec_address)) + vexriscv.VexRiscv(platform, exec_address, + variant="VexRiscv_IMA" if kasli_v1 else "VexRiscv_G")) # DRAM access self.wb_sdram = wishbone.Interface() From cb247f235f552053323ec62d8256c84d3cd49bb9 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:42:05 +0800 Subject: [PATCH 200/238] gateware: pass adr_w/data_w to submodules --- artiq/gateware/amp/kernel_cpu.py | 10 ++++++---- artiq/gateware/amp/soc.py | 16 ++++++++++------ artiq/gateware/targets/kasli.py | 12 ++++++------ artiq/gateware/targets/kc705.py | 10 +++++----- artiq/gateware/targets/metlino.py | 4 ++-- artiq/gateware/targets/sayma_amc.py | 2 +- artiq/gateware/targets/sayma_rtm.py | 2 +- 7 files changed, 31 insertions(+), 25 deletions(-) diff --git a/artiq/gateware/amp/kernel_cpu.py b/artiq/gateware/amp/kernel_cpu.py index bea786be9..6979b7b4f 100644 --- a/artiq/gateware/amp/kernel_cpu.py +++ b/artiq/gateware/amp/kernel_cpu.py @@ -1,4 +1,5 @@ from migen import * +from migen.build.platforms.sinara import kasli from misoc.interconnect.csr import * from misoc.interconnect import wishbone from misoc.cores import vexriscv @@ -14,8 +15,6 @@ class KernelCPU(Module): # # # - self._wb_slaves = WishboneSlaveManager(0x80000000) - # CPU core self.clock_domains.cd_sys_kernel = ClockDomain() self.comb += [ @@ -26,9 +25,12 @@ class KernelCPU(Module): self.submodules.cpu = ClockDomainsRenamer("sys_kernel")( vexriscv.VexRiscv(platform, exec_address, variant="VexRiscv_IMA" if kasli_v1 else "VexRiscv_G")) + + self.cpu_dw = len(self.cpu.dbus.dat_w) + self._wb_slaves = WishboneSlaveManager(0x80000000, dw=self.cpu_dw) # DRAM access - self.wb_sdram = wishbone.Interface() + self.wb_sdram = wishbone.Interface(data_width=self.cpu_dw, adr_width=32-log2_int(self.cpu_dw//8)) self.add_wb_slave(main_mem_origin, 0x10000000, self.wb_sdram) def get_csrs(self): @@ -37,7 +39,7 @@ class KernelCPU(Module): def do_finalize(self): self.submodules.wishbonecon = wishbone.InterconnectShared( [self.cpu.ibus, self.cpu.dbus], - self._wb_slaves.get_interconnect_slaves(), register=True) + self._wb_slaves.get_interconnect_slaves(), register=True, dw=self.cpu_dw) def add_wb_slave(self, origin, length, interface): if self.finalized: diff --git a/artiq/gateware/amp/soc.py b/artiq/gateware/amp/soc.py index 76d79807c..91b75ca3a 100644 --- a/artiq/gateware/amp/soc.py +++ b/artiq/gateware/amp/soc.py @@ -1,3 +1,4 @@ +from migen import * from misoc.cores import timer from misoc.interconnect import wishbone @@ -19,21 +20,24 @@ class AMPSoC: self.csr_devices.append("kernel_cpu") mailbox_size = 3 - self.submodules.mailbox = Mailbox(mailbox_size) - self.add_wb_slave(self.mem_map["mailbox"], 4*mailbox_size, + self.csr_separation = self.kernel_cpu.cpu_dw//8 + + self.submodules.mailbox = Mailbox(mailbox_size, adr_width=32-log2_int(self.csr_separation)) + self.add_wb_slave(self.mem_map["mailbox"], self.csr_separation*mailbox_size, self.mailbox.i1) - self.kernel_cpu.add_wb_slave(self.mem_map["mailbox"], 4*mailbox_size, + self.kernel_cpu.add_wb_slave(self.mem_map["mailbox"], self.csr_separation*mailbox_size, self.mailbox.i2) self.add_memory_region("mailbox", self.mem_map["mailbox"] | 0x80000000, - 4*mailbox_size) + self.csr_separation*mailbox_size) def register_kernel_cpu_csrdevice(self, name, csrs=None): if csrs is None: csrs = getattr(self, name).get_csrs() - bank = wishbone.CSRBank(csrs) + csr_bus = wishbone.Interface(data_width=32, adr_width=32-log2_int(self.csr_separation)) + bank = wishbone.CSRBank(csrs, bus=csr_bus) self.submodules += bank - self.kernel_cpu.add_wb_slave(self.mem_map[name], 4*2**bank.decode_bits, bank.bus) + self.kernel_cpu.add_wb_slave(self.mem_map[name], self.csr_separation*2**bank.decode_bits, bank.bus) self.add_csr_region(name, self.mem_map[name] | 0x80000000, 32, csrs) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 5cba517a7..311028fcb 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -144,7 +144,7 @@ class StandaloneBase(MiniSoC, AMPSoC): self.csr_devices.append("rtio_core") self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( - rtio.DMA(self.get_native_sdram_if())) + rtio.DMA(self.get_native_sdram_if(), self.cpu_dw)) self.register_kernel_cpu_csrdevice("rtio") self.register_kernel_cpu_csrdevice("rtio_dma") self.submodules.cri_con = rtio.CRIInterconnectShared( @@ -162,7 +162,7 @@ class StandaloneBase(MiniSoC, AMPSoC): self.rtio_crg.cd_rtio.clk) self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri, - self.get_native_sdram_if()) + self.get_native_sdram_if(), cpu_dw=self.cpu_dw) self.csr_devices.append("rtio_analyzer") @@ -345,7 +345,7 @@ class MasterBase(MiniSoC, AMPSoC): self.drtio_cri.append(core.cri) self.csr_devices.append(core_name) - coreaux = cdr(DRTIOAuxController(core.link_layer)) + coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) setattr(self.submodules, coreaux_name, coreaux) self.csr_devices.append(coreaux_name) @@ -386,7 +386,7 @@ class MasterBase(MiniSoC, AMPSoC): self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( - rtio.DMA(self.get_native_sdram_if())) + rtio.DMA(self.get_native_sdram_if(), self.cpu_dw)) self.register_kernel_cpu_csrdevice("rtio") self.register_kernel_cpu_csrdevice("rtio_dma") self.submodules.cri_con = rtio.CRIInterconnectShared( @@ -398,7 +398,7 @@ class MasterBase(MiniSoC, AMPSoC): self.csr_devices.append("routing_table") self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.cri_con.switch.slave, - self.get_native_sdram_if()) + self.get_native_sdram_if(), cpu_dw=self.cpu_dw) self.csr_devices.append("rtio_analyzer") # Never running out of stupid features, GTs on A7 make you pack @@ -539,7 +539,7 @@ class SatelliteBase(BaseSoC): self.drtio_cri.append(core.cri) self.csr_devices.append(corerep_name) - coreaux = cdr(DRTIOAuxController(core.link_layer)) + coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) setattr(self.submodules, coreaux_name, coreaux) self.csr_devices.append(coreaux_name) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 6e1fdd1d4..4cec96e87 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -177,7 +177,7 @@ class _StandaloneBase(MiniSoC, AMPSoC): self.csr_devices.append("rtio_core") self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( - rtio.DMA(self.get_native_sdram_if())) + rtio.DMA(self.get_native_sdram_if(), self.cpu_dw)) self.register_kernel_cpu_csrdevice("rtio") self.register_kernel_cpu_csrdevice("rtio_dma") self.submodules.cri_con = rtio.CRIInterconnectShared( @@ -193,7 +193,7 @@ class _StandaloneBase(MiniSoC, AMPSoC): self.rtio_crg.cd_rtio.clk) self.submodules.rtio_analyzer = rtio.Analyzer(self.rtio_tsc, self.rtio_core.cri, - self.get_native_sdram_if()) + self.get_native_sdram_if(), cpu_dw=self.cpu_dw) self.csr_devices.append("rtio_analyzer") @@ -265,7 +265,7 @@ class _MasterBase(MiniSoC, AMPSoC): self.drtio_cri.append(core.cri) self.csr_devices.append(core_name) - coreaux = cdr(DRTIOAuxController(core.link_layer)) + coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) setattr(self.submodules, coreaux_name, coreaux) self.csr_devices.append(coreaux_name) @@ -323,7 +323,7 @@ class _MasterBase(MiniSoC, AMPSoC): self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( - rtio.DMA(self.get_native_sdram_if())) + rtio.DMA(self.get_native_sdram_if(), self.cpu_dw)) self.register_kernel_cpu_csrdevice("rtio") self.register_kernel_cpu_csrdevice("rtio_dma") self.submodules.cri_con = rtio.CRIInterconnectShared( @@ -407,7 +407,7 @@ class _SatelliteBase(BaseSoC): self.drtio_cri.append(core.cri) self.csr_devices.append(corerep_name) - coreaux = cdr(DRTIOAuxController(core.link_layer)) + coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) setattr(self.submodules, coreaux_name, coreaux) self.csr_devices.append(coreaux_name) diff --git a/artiq/gateware/targets/metlino.py b/artiq/gateware/targets/metlino.py index 107dbc78d..ffb2b38b9 100755 --- a/artiq/gateware/targets/metlino.py +++ b/artiq/gateware/targets/metlino.py @@ -97,7 +97,7 @@ class Master(MiniSoC, AMPSoC): drtio_cri.append(core.cri) self.csr_devices.append(core_name) - coreaux = cdr(DRTIOAuxController(core.link_layer)) + coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) setattr(self.submodules, coreaux_name, coreaux) self.csr_devices.append(coreaux_name) @@ -150,7 +150,7 @@ class Master(MiniSoC, AMPSoC): self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( - rtio.DMA(self.get_native_sdram_if())) + rtio.DMA(self.get_native_sdram_if(), self.cpu_dw)) self.register_kernel_cpu_csrdevice("rtio") self.register_kernel_cpu_csrdevice("rtio_dma") self.submodules.cri_con = rtio.CRIInterconnectShared( diff --git a/artiq/gateware/targets/sayma_amc.py b/artiq/gateware/targets/sayma_amc.py index 32ebc8521..527d37b5c 100755 --- a/artiq/gateware/targets/sayma_amc.py +++ b/artiq/gateware/targets/sayma_amc.py @@ -118,7 +118,7 @@ class SatelliteBase(MiniSoC): self.drtio_cri.append(core.cri) self.csr_devices.append(corerep_name) - coreaux = cdr(DRTIOAuxController(core.link_layer)) + coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) setattr(self.submodules, coreaux_name, coreaux) self.csr_devices.append(coreaux_name) diff --git a/artiq/gateware/targets/sayma_rtm.py b/artiq/gateware/targets/sayma_rtm.py index a132601d6..9d8a818b4 100755 --- a/artiq/gateware/targets/sayma_rtm.py +++ b/artiq/gateware/targets/sayma_rtm.py @@ -80,7 +80,7 @@ class _SatelliteBase(BaseSoC): self.submodules.drtiosat = core self.csr_devices.append("drtiosat") - coreaux = cdr(DRTIOAuxController(core.link_layer)) + coreaux = cdr(DRTIOAuxController(core.link_layer, self.cpu_dw)) self.submodules.drtioaux0 = coreaux self.csr_devices.append("drtioaux0") From 0898e101e25f451a1dff8a714c2b7df37a8ae30c Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:51:50 +0800 Subject: [PATCH 201/238] board_misoc: reuse riscv dir for comm & kernel --- artiq/firmware/libboard_misoc/build.rs | 9 +++------ artiq/firmware/libboard_misoc/lib.rs | 2 +- .../libboard_misoc/{riscv32ima => riscv32}/boot.rs | 0 .../libboard_misoc/{riscv32ima => riscv32}/cache.rs | 0 .../libboard_misoc/{riscv32ima => riscv32}/mod.rs | 0 .../libboard_misoc/{riscv32ima => riscv32}/pmp.rs | 0 .../libboard_misoc/{riscv32ima => riscv32}/vectors.S | 0 7 files changed, 4 insertions(+), 7 deletions(-) rename artiq/firmware/libboard_misoc/{riscv32ima => riscv32}/boot.rs (100%) rename artiq/firmware/libboard_misoc/{riscv32ima => riscv32}/cache.rs (100%) rename artiq/firmware/libboard_misoc/{riscv32ima => riscv32}/mod.rs (100%) rename artiq/firmware/libboard_misoc/{riscv32ima => riscv32}/pmp.rs (100%) rename artiq/firmware/libboard_misoc/{riscv32ima => riscv32}/vectors.S (100%) diff --git a/artiq/firmware/libboard_misoc/build.rs b/artiq/firmware/libboard_misoc/build.rs index 8160db88a..11d5aac2f 100644 --- a/artiq/firmware/libboard_misoc/build.rs +++ b/artiq/firmware/libboard_misoc/build.rs @@ -1,19 +1,16 @@ extern crate build_misoc; extern crate cc; -use std::env; use std::path::Path; fn main() { build_misoc::cfg(); - let triple = env::var("TARGET").unwrap(); - let arch = triple.split("-").next().unwrap(); - let vectors_path = Path::new(arch).join("vectors.S"); + let vectors_path = "riscv32/vectors.S"; - println!("cargo:rerun-if-changed={}", vectors_path.to_str().unwrap()); + println!("cargo:rerun-if-changed={}", vectors_path); cc::Build::new() .flag("--target=riscv32-unknown-elf") - .file(vectors_path) + .file(Path::new(vectors_path)) .compile("vectors"); } diff --git a/artiq/firmware/libboard_misoc/lib.rs b/artiq/firmware/libboard_misoc/lib.rs index 729f4d63b..3189ccfcd 100644 --- a/artiq/firmware/libboard_misoc/lib.rs +++ b/artiq/firmware/libboard_misoc/lib.rs @@ -8,7 +8,7 @@ extern crate log; extern crate smoltcp; #[cfg(target_arch = "riscv32")] -#[path = "riscv32ima/mod.rs"] +#[path = "riscv32/mod.rs"] mod arch; #[cfg(target_arch = "riscv32")] diff --git a/artiq/firmware/libboard_misoc/riscv32ima/boot.rs b/artiq/firmware/libboard_misoc/riscv32/boot.rs similarity index 100% rename from artiq/firmware/libboard_misoc/riscv32ima/boot.rs rename to artiq/firmware/libboard_misoc/riscv32/boot.rs diff --git a/artiq/firmware/libboard_misoc/riscv32ima/cache.rs b/artiq/firmware/libboard_misoc/riscv32/cache.rs similarity index 100% rename from artiq/firmware/libboard_misoc/riscv32ima/cache.rs rename to artiq/firmware/libboard_misoc/riscv32/cache.rs diff --git a/artiq/firmware/libboard_misoc/riscv32ima/mod.rs b/artiq/firmware/libboard_misoc/riscv32/mod.rs similarity index 100% rename from artiq/firmware/libboard_misoc/riscv32ima/mod.rs rename to artiq/firmware/libboard_misoc/riscv32/mod.rs diff --git a/artiq/firmware/libboard_misoc/riscv32ima/pmp.rs b/artiq/firmware/libboard_misoc/riscv32/pmp.rs similarity index 100% rename from artiq/firmware/libboard_misoc/riscv32ima/pmp.rs rename to artiq/firmware/libboard_misoc/riscv32/pmp.rs diff --git a/artiq/firmware/libboard_misoc/riscv32ima/vectors.S b/artiq/firmware/libboard_misoc/riscv32/vectors.S similarity index 100% rename from artiq/firmware/libboard_misoc/riscv32ima/vectors.S rename to artiq/firmware/libboard_misoc/riscv32/vectors.S From b3e315e24af56b609e9a41c882287ed152d1d1f0 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:57:13 +0800 Subject: [PATCH 202/238] rust: find json file using CARGO_TRIPLE --- artiq/firmware/bootloader/Makefile | 2 +- artiq/firmware/ksupport/Makefile | 2 +- artiq/firmware/riscv32g-unknown-none-elf.json | 40 ++++++++++++ .../firmware/riscv32ima-unknown-none-elf.json | 61 +++++++++---------- artiq/firmware/runtime/Makefile | 2 +- artiq/firmware/satman/Makefile | 2 +- 6 files changed, 74 insertions(+), 35 deletions(-) create mode 100644 artiq/firmware/riscv32g-unknown-none-elf.json diff --git a/artiq/firmware/bootloader/Makefile b/artiq/firmware/bootloader/Makefile index 4dbd7b608..82baef3eb 100644 --- a/artiq/firmware/bootloader/Makefile +++ b/artiq/firmware/bootloader/Makefile @@ -11,7 +11,7 @@ all:: bootloader.bin $(RUSTOUT)/libbootloader.a: $(cargo) --target-dir ./cargo \ --manifest-path $(BOOTLOADER_DIRECTORY)/Cargo.toml \ - --target $(BOOTLOADER_DIRECTORY)/../riscv32ima-unknown-none-elf.json + --target $(BOOTLOADER_DIRECTORY)/../$(CARGO_TRIPLE).json bootloader.elf: $(RUSTOUT)/libbootloader.a $(link) -T $(BOOTLOADER_DIRECTORY)/bootloader.ld diff --git a/artiq/firmware/ksupport/Makefile b/artiq/firmware/ksupport/Makefile index f1fbfc19a..b73faea50 100644 --- a/artiq/firmware/ksupport/Makefile +++ b/artiq/firmware/ksupport/Makefile @@ -22,7 +22,7 @@ all:: ksupport.elf $(RUSTOUT)/libksupport.a: $(cargo) --target-dir ./cargo \ --manifest-path $(KSUPPORT_DIRECTORY)/Cargo.toml \ - --target $(KSUPPORT_DIRECTORY)/../riscv32ima-unknown-none-elf.json + --target $(KSUPPORT_DIRECTORY)/../$(CARGO_TRIPLE).json ksupport.elf: $(RUSTOUT)/libksupport.a glue.o $(link) -T $(KSUPPORT_DIRECTORY)/ksupport.ld \ diff --git a/artiq/firmware/riscv32g-unknown-none-elf.json b/artiq/firmware/riscv32g-unknown-none-elf.json new file mode 100644 index 000000000..2a3fb8bfb --- /dev/null +++ b/artiq/firmware/riscv32g-unknown-none-elf.json @@ -0,0 +1,40 @@ +{ + "arch": "riscv32", + "code-model": "medium", + "cpu": "generic-rv32", + "crt-static-respected": true, + "data-layout": "e-m:e-p:32:32-i64:64-n32-S128", + "dynamic-linking": true, + "executables": true, + "features": "+m,+a,+f,+d", + "has-elf-tls": true, + "has-rpath": true, + "llvm-abiname": "ilp32d", + "llvm-target": "riscv32-unknown-linux", + "max-atomic-width": 32, + "position-independent-executables": true, + "pre-link-args": { + "gcc": [ + "-Wl,--as-needed", + "-Wl,-z,noexecstack" + ] + }, + "relro-level": "full", + "target-family": "unix", + "target-pointer-width": "32", + "unsupported-abis": [ + "cdecl", + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "aapcs", + "win64", + "sysv64", + "ptx-kernel", + "msp430-interrupt", + "x86-interrupt", + "amdgpu-kernel" + ] +} + \ No newline at end of file diff --git a/artiq/firmware/riscv32ima-unknown-none-elf.json b/artiq/firmware/riscv32ima-unknown-none-elf.json index ddacc0247..e41408842 100644 --- a/artiq/firmware/riscv32ima-unknown-none-elf.json +++ b/artiq/firmware/riscv32ima-unknown-none-elf.json @@ -1,32 +1,31 @@ { - "arch": "riscv32", - "cpu": "generic-rv32", - "data-layout": "e-m:e-p:32:32-i64:64-n32-S128", - "eh-frame-header": false, - "emit-debug-gdb-scripts": false, - "executables": true, - "features": "+m,+a,-c", - "is-builtin": false, - "linker": "rust-lld", - "linker-flavor": "ld.lld", - "llvm-target": "riscv32", - "max-atomic-width": 32, - "panic-strategy": "unwind", - "relocation-model": "static", - "target-pointer-width": "32", - "unsupported-abis": [ - "cdecl", - "stdcall", - "fastcall", - "vectorcall", - "thiscall", - "aapcs", - "win64", - "sysv64", - "ptx-kernel", - "msp430-interrupt", - "x86-interrupt", - "amdgpu-kernel" - ] - } - \ No newline at end of file + "arch": "riscv32", + "cpu": "generic-rv32", + "data-layout": "e-m:e-p:32:32-i64:64-n32-S128", + "eh-frame-header": false, + "emit-debug-gdb-scripts": false, + "executables": true, + "features": "+m,+a,-c", + "is-builtin": false, + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "llvm-target": "riscv32", + "max-atomic-width": 32, + "panic-strategy": "unwind", + "relocation-model": "static", + "target-pointer-width": "32", + "unsupported-abis": [ + "cdecl", + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "aapcs", + "win64", + "sysv64", + "ptx-kernel", + "msp430-interrupt", + "x86-interrupt", + "amdgpu-kernel" + ] +} diff --git a/artiq/firmware/runtime/Makefile b/artiq/firmware/runtime/Makefile index 00506b2f3..3e4b91ba3 100644 --- a/artiq/firmware/runtime/Makefile +++ b/artiq/firmware/runtime/Makefile @@ -18,7 +18,7 @@ all:: runtime.bin runtime.fbi $(RUSTOUT)/libruntime.a: $(cargo) --target-dir ./cargo \ --manifest-path $(RUNTIME_DIRECTORY)/Cargo.toml \ - --target $(RUNTIME_DIRECTORY)/../riscv32ima-unknown-none-elf.json + --target $(RUNTIME_DIRECTORY)/../$(CARGO_TRIPLE).json runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o $(link) -T $(RUNTIME_DIRECTORY)/runtime.ld \ diff --git a/artiq/firmware/satman/Makefile b/artiq/firmware/satman/Makefile index 7c3885c87..82e65d730 100644 --- a/artiq/firmware/satman/Makefile +++ b/artiq/firmware/satman/Makefile @@ -13,7 +13,7 @@ all:: satman.bin satman.fbi $(RUSTOUT)/libsatman.a: $(cargo) --target-dir ./cargo \ --manifest-path $(SATMAN_DIRECTORY)/Cargo.toml \ - --target $(SATMAN_DIRECTORY)/../riscv32ima-unknown-none-elf.json + --target $(SATMAN_DIRECTORY)/../$(CARGO_TRIPLE).json satman.elf: $(RUSTOUT)/libsatman.a $(link) -T $(SATMAN_DIRECTORY)/satman.ld From 03b803e7642fd295259f3c4a5312e0b496057599 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:57:30 +0800 Subject: [PATCH 203/238] firmware: adjust csr separation --- artiq/firmware/ksupport/rtio.rs | 6 ++++-- artiq/firmware/libboard_artiq/rpc_queue.rs | 6 +++--- artiq/firmware/libboard_misoc/sdram.rs | 15 +++++++++------ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/artiq/firmware/ksupport/rtio.rs b/artiq/firmware/ksupport/rtio.rs index 8736e33f5..d9f568f75 100644 --- a/artiq/firmware/ksupport/rtio.rs +++ b/artiq/firmware/ksupport/rtio.rs @@ -23,6 +23,8 @@ mod imp { pub const RTIO_I_STATUS_WAIT_STATUS: u8 = 4; pub const RTIO_I_STATUS_DESTINATION_UNREACHABLE: u8 = 8; + const OFFSET_MULTIPLE: isize = (csr::CONFIG_DATA_WIDTH_BYTES / 4) as isize; + pub extern fn init() { send(&RtioInitRequest); } @@ -47,14 +49,14 @@ mod imp { #[inline(always)] pub unsafe fn rtio_o_data_write(offset: usize, data: u32) { write_volatile( - csr::rtio::O_DATA_ADDR.offset((csr::rtio::O_DATA_SIZE - 1 - offset) as isize), + csr::rtio::O_DATA_ADDR.offset(OFFSET_MULTIPLE*(csr::rtio::O_DATA_SIZE - 1 - offset) as isize), data); } #[inline(always)] pub unsafe fn rtio_i_data_read(offset: usize) -> u32 { read_volatile( - csr::rtio::I_DATA_ADDR.offset((csr::rtio::I_DATA_SIZE - 1 - offset) as isize)) + csr::rtio::I_DATA_ADDR.offset(OFFSET_MULTIPLE*(csr::rtio::I_DATA_SIZE - 1 - offset) as isize)) } #[inline(never)] diff --git a/artiq/firmware/libboard_artiq/rpc_queue.rs b/artiq/firmware/libboard_artiq/rpc_queue.rs index 0e2049c81..877ed8c89 100644 --- a/artiq/firmware/libboard_artiq/rpc_queue.rs +++ b/artiq/firmware/libboard_artiq/rpc_queue.rs @@ -1,9 +1,9 @@ use core::ptr::{read_volatile, write_volatile}; use core::slice; -use board_misoc::{mem, cache}; +use board_misoc::{mem, cache, csr::CONFIG_DATA_WIDTH_BYTES}; -const SEND_MAILBOX: *mut usize = (mem::MAILBOX_BASE + 4) as *mut usize; -const RECV_MAILBOX: *mut usize = (mem::MAILBOX_BASE + 8) as *mut usize; +const SEND_MAILBOX: *mut usize = (mem::MAILBOX_BASE + CONFIG_DATA_WIDTH_BYTES as usize) as *mut usize; +const RECV_MAILBOX: *mut usize = (mem::MAILBOX_BASE + (CONFIG_DATA_WIDTH_BYTES * 2) as usize) as *mut usize; const QUEUE_BEGIN: usize = 0x44000000; const QUEUE_END: usize = 0x44ffff80; diff --git a/artiq/firmware/libboard_misoc/sdram.rs b/artiq/firmware/libboard_misoc/sdram.rs index 61951e725..b3e112eb0 100644 --- a/artiq/firmware/libboard_misoc/sdram.rs +++ b/artiq/firmware/libboard_misoc/sdram.rs @@ -2,6 +2,7 @@ mod ddr { use core::{ptr, fmt}; use csr::{dfii, ddrphy}; + use csr::CONFIG_DATA_WIDTH_BYTES; use sdram_phy::{self, spin_cycles}; use sdram_phy::{DFII_COMMAND_CS, DFII_COMMAND_WE, DFII_COMMAND_CAS, DFII_COMMAND_RAS, DFII_COMMAND_WRDATA, DFII_COMMAND_RDDATA}; @@ -14,6 +15,8 @@ mod ddr { const DQS_SIGNAL_COUNT: usize = DFII_PIX_DATA_SIZE / 2; + const CSR_SEPARATION: isize = CONFIG_DATA_WIDTH_BYTES as isize / 4; + macro_rules! log { ($logger:expr, $( $arg:expr ),+) => ( if let &mut Some(ref mut f) = $logger { @@ -46,7 +49,7 @@ mod ddr { for n in 0..DQS_SIGNAL_COUNT { let dq_addr = dfii::PI0_RDDATA_ADDR - .offset((DQS_SIGNAL_COUNT - 1 - n) as isize); + .offset(CSR_SEPARATION * (DQS_SIGNAL_COUNT - 1 - n) as isize); log!(logger, "Module {}:\n", DQS_SIGNAL_COUNT - 1 - n); @@ -100,7 +103,7 @@ mod ddr { let mut failed = false; for n in 0..DQS_SIGNAL_COUNT { let dq_addr = dfii::PI0_RDDATA_ADDR - .offset((DQS_SIGNAL_COUNT - 1 - n) as isize); + .offset(CSR_SEPARATION * (DQS_SIGNAL_COUNT - 1 - n) as isize); delay[n] = 0; high_skew[n] = false; @@ -223,7 +226,7 @@ mod ddr { // Write test pattern for p in 0..DFII_NPHASES { for offset in 0..DFII_PIX_DATA_SIZE { - let addr = DFII_PIX_WRDATA_ADDR[p].offset(offset as isize); + let addr = DFII_PIX_WRDATA_ADDR[p].offset(CSR_SEPARATION * offset as isize); let data = prs[DFII_PIX_DATA_SIZE * p + offset]; ptr::write_volatile(addr, data as u32); } @@ -258,7 +261,7 @@ mod ddr { for p in 0..DFII_NPHASES { for &offset in [n, n + DQS_SIGNAL_COUNT].iter() { - let addr = DFII_PIX_RDDATA_ADDR[p].offset(offset as isize); + let addr = DFII_PIX_RDDATA_ADDR[p].offset(CSR_SEPARATION * offset as isize); let data = prs[DFII_PIX_DATA_SIZE * p + offset]; if ptr::read_volatile(addr) as u8 != data { working = false; @@ -306,7 +309,7 @@ mod ddr { // Write test pattern for p in 0..DFII_NPHASES { for offset in 0..DFII_PIX_DATA_SIZE { - let addr = DFII_PIX_WRDATA_ADDR[p].offset(offset as isize); + let addr = DFII_PIX_WRDATA_ADDR[p].offset(CSR_SEPARATION * offset as isize); let data = prs[DFII_PIX_DATA_SIZE * p + offset]; ptr::write_volatile(addr, data as u32); } @@ -349,7 +352,7 @@ mod ddr { for p in 0..DFII_NPHASES { for &offset in [n, n + DQS_SIGNAL_COUNT].iter() { - let addr = DFII_PIX_RDDATA_ADDR[p].offset(offset as isize); + let addr = DFII_PIX_RDDATA_ADDR[p].offset(CSR_SEPARATION * offset as isize); let data = prs[DFII_PIX_DATA_SIZE * p + offset]; if ptr::read_volatile(addr) as u8 != data { valid = false; From 0d708cd61a83e74ea4c73d95267b999bf26138a3 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 12:59:09 +0800 Subject: [PATCH 204/238] compiler/target: split RISCV target into float/non-float --- artiq/compiler/targets.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index e908ce38a..dc5b68be8 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -98,7 +98,8 @@ class Target: lltarget = llvm.Target.from_triple(self.triple) llmachine = lltarget.create_target_machine( features=",".join(["+{}".format(f) for f in self.features]), - reloc="pic", codemodel="default") + reloc="pic", codemodel="default", + abiname="ilp32d" if isinstance(self, RV32GTarget) else "") llmachine.set_asm_verbosity(True) return llmachine @@ -252,7 +253,7 @@ class NativeTarget(Target): self.triple = llvm.get_default_triple() host_data_layout = str(llvm.targets.Target.from_default_triple().create_target_machine().target_data) -class RISCVTarget(Target): +class RV32IMATarget(Target): triple = "riscv32-unknown-linux" data_layout = "e-m:e-p:32:32-i64:64-n32-S128" features = ["m", "a"] @@ -264,6 +265,18 @@ class RISCVTarget(Target): tool_addr2line = "llvm-addr2line" tool_cxxfilt = "llvm-cxxfilt" +class RV32GTarget(Target): + triple = "riscv32-unknown-linux" + data_layout = "e-m:e-p:32:32-i64:64-n32-S128" + features = ["m", "a", "f", "d"] + print_function = "core_log" + now_pinning = True + + tool_ld = "ld.lld" + tool_strip = "llvm-strip" + tool_addr2line = "llvm-addr2line" + tool_cxxfilt = "llvm-cxxfilt" + class CortexA9Target(Target): triple = "armv7-unknown-linux-gnueabihf" data_layout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" From 0755757601657785d9ea166eef0d8c8693713fa5 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 13:00:26 +0800 Subject: [PATCH 205/238] compiler/tb: use FPU --- artiq/compiler/testbench/perf.py | 4 ++-- artiq/compiler/testbench/perf_embedding.py | 4 ++-- artiq/compiler/testbench/shlib.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/artiq/compiler/testbench/perf.py b/artiq/compiler/testbench/perf.py index 363c88840..2d70bcf84 100644 --- a/artiq/compiler/testbench/perf.py +++ b/artiq/compiler/testbench/perf.py @@ -1,7 +1,7 @@ import sys, os from pythonparser import diagnostic from ..module import Module, Source -from ..targets import RISCVTarget +from ..targets import RV32GTarget from . import benchmark def main(): @@ -30,7 +30,7 @@ def main(): benchmark(lambda: Module(source), "ARTIQ transforms and validators") - benchmark(lambda: RISCVTarget().compile_and_link([module]), + benchmark(lambda: RV32GTarget().compile_and_link([module]), "LLVM optimization and linking") if __name__ == "__main__": diff --git a/artiq/compiler/testbench/perf_embedding.py b/artiq/compiler/testbench/perf_embedding.py index d626d5534..75267cb5b 100644 --- a/artiq/compiler/testbench/perf_embedding.py +++ b/artiq/compiler/testbench/perf_embedding.py @@ -5,7 +5,7 @@ from ...master.databases import DeviceDB, DatasetDB from ...master.worker_db import DeviceManager, DatasetManager from ..module import Module from ..embedding import Stitcher -from ..targets import RISCVTarget +from ..targets import RV32GTarget from . import benchmark @@ -45,7 +45,7 @@ def main(): stitcher = embed() module = Module(stitcher) - target = RISCVTarget() + target = RV32GTarget() llvm_ir = target.compile(module) elf_obj = target.assemble(llvm_ir) elf_shlib = target.link([elf_obj]) diff --git a/artiq/compiler/testbench/shlib.py b/artiq/compiler/testbench/shlib.py index 0aa6386d3..0e2317a5c 100644 --- a/artiq/compiler/testbench/shlib.py +++ b/artiq/compiler/testbench/shlib.py @@ -1,7 +1,7 @@ import sys, os from pythonparser import diagnostic from ..module import Module, Source -from ..targets import RISCVTarget +from ..targets import RV32GTarget def main(): if not len(sys.argv) > 1: @@ -20,7 +20,7 @@ def main(): for filename in sys.argv[1:]: modules.append(Module(Source.from_filename(filename, engine=engine))) - llobj = RISCVTarget().compile_and_link(modules) + llobj = RV32GTarget().compile_and_link(modules) basename, ext = os.path.splitext(sys.argv[-1]) with open(basename + ".so", "wb") as f: From 0f660735bfb85d032277d1a1394d9465cb376250 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 13:02:15 +0800 Subject: [PATCH 206/238] ll_gen: adjust csr address by detecting target class --- .../compiler/transforms/llvm_ir_generator.py | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 61f66599c..084e5ae09 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -10,6 +10,7 @@ from llvmlite import ir as ll, binding as llvm from ...language import core as language_core from .. import types, builtins, ir from ..embedding import SpecializedFunction +from artiq.compiler.targets import RV32GTarget llvoid = ll.VoidType() @@ -1097,20 +1098,28 @@ class LLVMIRGenerator: if self.target.now_pinning: # Word swap now.old as CPU is little endian # Most significant word is stored in lower address (see generated csr.rs) - llnow_raw = self.llbuilder.load(self.llbuiltin("now"), name=insn.name) - llnow_lo = self.llbuilder.shl(llnow_raw, ll.Constant(lli64, 32)) - llnow_hi = self.llbuilder.lshr(llnow_raw, ll.Constant(lli64, 32)) - return self.llbuilder.or_(llnow_lo, llnow_hi) + csr_offset = 2 if isinstance(self.target, RV32GTarget) else 1 + + llnow_hiptr = self.llbuilder.bitcast(self.llbuiltin("now"), lli32.as_pointer()) + llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(csr_offset)]) + llnow_hi = self.llbuilder.load(llnow_hiptr, name="now.hi") + llnow_lo = self.llbuilder.load(llnow_loptr, name="now.lo") + llzext_hi = self.llbuilder.zext(llnow_hi, lli64) + llshifted_hi = self.llbuilder.shl(llzext_hi, ll.Constant(lli64, 32)) + llzext_lo = self.llbuilder.zext(llnow_lo, lli64) + return self.llbuilder.or_(llshifted_hi, llzext_lo) else: return self.llbuilder.call(self.llbuiltin("now_mu"), []) elif insn.op == "at_mu": time, = insn.operands lltime = self.map(time) if self.target.now_pinning: + csr_offset = 2 if isinstance(self.target, RV32GTarget) else 1 + lltime_hi = self.llbuilder.trunc(self.llbuilder.lshr(lltime, ll.Constant(lli64, 32)), lli32) lltime_lo = self.llbuilder.trunc(lltime, lli32) llnow_hiptr = self.llbuilder.bitcast(self.llbuiltin("now"), lli32.as_pointer()) - llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(1)]) + llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(csr_offset)]) llstore_hi = self.llbuilder.store_atomic(lltime_hi, llnow_hiptr, ordering="seq_cst", align=4) llstore_lo = self.llbuilder.store_atomic(lltime_lo, llnow_loptr, ordering="seq_cst", align=4) return llstore_lo @@ -1120,20 +1129,22 @@ class LLVMIRGenerator: interval, = insn.operands llinterval = self.map(interval) if self.target.now_pinning: - llnowptr = self.llbuiltin("now") - llnow = self.llbuilder.load(llnowptr, name="now.old") - # Word swap now.old as CPU is little endian # Most significant word is stored in lower address (see generated csr.rs) - llnow_lo = self.llbuilder.shl(llnow, ll.Constant(lli64, 32)) - llnow_hi = self.llbuilder.lshr(llnow, ll.Constant(lli64, 32)) - llnow = self.llbuilder.or_(llnow_lo, llnow_hi) + csr_offset = 2 if isinstance(self.target, RV32GTarget) else 1 + + llnow_hiptr = self.llbuilder.bitcast(self.llbuiltin("now"), lli32.as_pointer()) + llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(csr_offset)]) + llnow_hi = self.llbuilder.load(llnow_hiptr, name="now.hi") + llnow_lo = self.llbuilder.load(llnow_loptr, name="now.lo") + llzext_hi = self.llbuilder.zext(llnow_hi, lli64) + llshifted_hi = self.llbuilder.shl(llzext_hi, ll.Constant(lli64, 32)) + llzext_lo = self.llbuilder.zext(llnow_lo, lli64) + llnow = self.llbuilder.or_(llshifted_hi, llzext_lo) lladjusted = self.llbuilder.add(llnow, llinterval, name="now.new") lladjusted_hi = self.llbuilder.trunc(self.llbuilder.lshr(lladjusted, ll.Constant(lli64, 32)), lli32) lladjusted_lo = self.llbuilder.trunc(lladjusted, lli32) - llnow_hiptr = self.llbuilder.bitcast(llnowptr, lli32.as_pointer()) - llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(1)]) llstore_hi = self.llbuilder.store_atomic(lladjusted_hi, llnow_hiptr, ordering="seq_cst", align=4) llstore_lo = self.llbuilder.store_atomic(lladjusted_lo, llnow_loptr, ordering="seq_cst", align=4) return llstore_lo From 531670d6c5804cad90673b0e7daecf603fd8e275 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 13:03:17 +0800 Subject: [PATCH 207/238] dyld: check ABI --- artiq/firmware/libdyld/elf.rs | 6 ++++++ artiq/firmware/libdyld/lib.rs | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/artiq/firmware/libdyld/elf.rs b/artiq/firmware/libdyld/elf.rs index d8712b9fd..a10d9b4c3 100644 --- a/artiq/firmware/libdyld/elf.rs +++ b/artiq/firmware/libdyld/elf.rs @@ -2230,6 +2230,12 @@ pub const R_OR1K_TLS_TPOFF: u8 = 32; pub const R_OR1K_TLS_DTPOFF: u8 = 33; pub const R_OR1K_TLS_DTPMOD: u8 = 34; pub const R_OR1K_NUM: u8 = 35; +pub const EF_RISCV_RVC: u32 = 1; +pub const EF_RISCV_FLOAT_ABI: u32 = 6; +pub const EF_RISCV_FLOAT_ABI_SOFT: u32 = 0; +pub const EF_RISCV_FLOAT_ABI_SINGLE: u32 = 2; +pub const EF_RISCV_FLOAT_ABI_DOUBLE: u32 = 4; +pub const EF_RISCV_FLOAT_ABI_QUAD: u32 = 6; pub const R_RISCV_NONE: u8 = 0; pub const R_RISCV_32: u8 = 1; pub const R_RISCV_64: u8 = 2; diff --git a/artiq/firmware/libdyld/lib.rs b/artiq/firmware/libdyld/lib.rs index 1fec38959..1d89edaee 100644 --- a/artiq/firmware/libdyld/lib.rs +++ b/artiq/firmware/libdyld/lib.rs @@ -219,7 +219,13 @@ impl<'a> Library<'a> { #[cfg(not(target_arch = "riscv32"))] const ARCH: u16 = EM_NONE; - if ehdr.e_ident != IDENT || ehdr.e_type != ET_DYN || ehdr.e_machine != ARCH { + #[cfg(all(target_feature = "f", target_feature = "d"))] + const FLAGS: u32 = EF_RISCV_FLOAT_ABI_DOUBLE; + + #[cfg(not(all(target_feature = "f", target_feature = "d")))] + const FLAGS: u32 = EF_RISCV_FLOAT_ABI_SOFT; + + if ehdr.e_ident != IDENT || ehdr.e_type != ET_DYN || ehdr.e_machine != ARCH || ehdr.e_flags != FLAGS { return Err("not a shared library for current architecture")? } From 750b0ce46d6b74f890c0b750049aafa65e3deb77 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 13:04:48 +0800 Subject: [PATCH 208/238] ddb_temp: select appropriate compiler target --- artiq/coredevice/core.py | 10 ++++++---- artiq/frontend/artiq_ddb_template.py | 14 ++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/artiq/coredevice/core.py b/artiq/coredevice/core.py index dc8207266..529c42f98 100644 --- a/artiq/coredevice/core.py +++ b/artiq/coredevice/core.py @@ -11,7 +11,7 @@ from artiq.language.units import * from artiq.compiler.module import Module from artiq.compiler.embedding import Stitcher -from artiq.compiler.targets import RISCVTarget, CortexA9Target +from artiq.compiler.targets import RV32IMATarget, RV32GTarget, CortexA9Target from artiq.coredevice.comm_kernel import CommKernel, CommKernelDummy # Import for side effects (creating the exception classes). @@ -71,11 +71,13 @@ class Core: "core", "ref_period", "coarse_ref_period", "ref_multiplier", } - def __init__(self, dmgr, host, ref_period, ref_multiplier=8, target="riscv"): + def __init__(self, dmgr, host, ref_period, ref_multiplier=8, target="rv32g"): self.ref_period = ref_period self.ref_multiplier = ref_multiplier - if target == "riscv": - self.target_cls = RISCVTarget + if target == "rv32g": + self.target_cls = RV32GTarget + elif target == "rv32ima": + self.target_cls = RV32IMATarget elif target == "cortexa9": self.target_cls = CortexA9Target else: diff --git a/artiq/frontend/artiq_ddb_template.py b/artiq/frontend/artiq_ddb_template.py index 4dfba4f93..52408a0d4 100755 --- a/artiq/frontend/artiq_ddb_template.py +++ b/artiq/frontend/artiq_ddb_template.py @@ -11,14 +11,16 @@ from artiq.coredevice import jsondesc def process_header(output, description): - if description["target"] not in ("kasli", "kasli_soc"): + if description["target"] == "kasli": + if description["hw_rev"] in ("v1.0", "v1.1"): + cpu_target = "rv32ima" + else: + cpu_target = "rv32g" + elif description["target"] == "kasli_soc": + cpu_target = "cortexa9" + else: raise NotImplementedError - cpu_target = { - "kasli": "riscv", - "kasli_soc": "cortexa9" - }[description["target"]] - print(textwrap.dedent(""" # Autogenerated for the {variant} variant core_addr = "{core_addr}" From 02119282b8f069c8b1434708999a31f5018aa20f Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 13:05:30 +0800 Subject: [PATCH 209/238] build_soc: build VexRiscv_G if not kasli v1.x --- artiq/build_soc.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/artiq/build_soc.py b/artiq/build_soc.py index e3a1f3360..bdf652948 100644 --- a/artiq/build_soc.py +++ b/artiq/build_soc.py @@ -2,6 +2,7 @@ import os import subprocess from migen import * +from migen.build.platforms.sinara import kasli from misoc.interconnect.csr import * from misoc.integration.builder import * @@ -57,11 +58,17 @@ def build_artiq_soc(soc, argdict): builder = Builder(soc, **argdict) builder.software_packages = [] builder.add_software_package("bootloader", os.path.join(firmware_dir, "bootloader")) + is_kasli_v1 = isinstance(soc.platform, kasli.Platform) and soc.platform.hw_rev in ("v1.0", "v1.1") if isinstance(soc, AMPSoC): - builder.add_software_package("libm") - builder.add_software_package("libprintf") - builder.add_software_package("libunwind") - builder.add_software_package("ksupport", os.path.join(firmware_dir, "ksupport")) + kernel_cpu_type = "vexriscv" if is_kasli_v1 else "vexriscv-g" + builder.add_software_package("libm", cpu_type=kernel_cpu_type) + builder.add_software_package("libprintf", cpu_type=kernel_cpu_type) + builder.add_software_package("libunwind", cpu_type=kernel_cpu_type) + builder.add_software_package("ksupport", os.path.join(firmware_dir, "ksupport"), cpu_type=kernel_cpu_type) + # Generate unwinder for soft float target (ARTIQ runtime) + # If the kernel lacks FPU, then the runtime unwinder is already generated + if not is_kasli_v1: + builder.add_software_package("libunwind") builder.add_software_package("runtime", os.path.join(firmware_dir, "runtime")) else: # Assume DRTIO satellite. From 09945ecc4d8b06c9761e46985e7d0ee0a0492cde Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 13:05:55 +0800 Subject: [PATCH 210/238] gateware: fix drtio/dma tests --- .../test/drtio/test_aux_controller.py | 58 +++++++------ artiq/gateware/test/rtio/test_dma.py | 87 ++++++++++++------- 2 files changed, 85 insertions(+), 60 deletions(-) diff --git a/artiq/gateware/test/drtio/test_aux_controller.py b/artiq/gateware/test/drtio/test_aux_controller.py index 64e2e15d7..68c9f3bbd 100644 --- a/artiq/gateware/test/drtio/test_aux_controller.py +++ b/artiq/gateware/test/drtio/test_aux_controller.py @@ -33,63 +33,67 @@ class Loopback(Module): class TB(Module): - def __init__(self, nwords): + def __init__(self, nwords, dw): self.submodules.link_layer = Loopback(nwords) self.submodules.aux_controller = ClockDomainsRenamer( - {"rtio": "sys", "rtio_rx": "sys"})(DRTIOAuxController(self.link_layer)) + {"rtio": "sys", "rtio_rx": "sys"})(DRTIOAuxController(self.link_layer, dw)) class TestAuxController(unittest.TestCase): def test_aux_controller(self): - dut = TB(4) + dut = { + 32: TB(4, 32), + 64: TB(4, 64) + } - def link_init(): + def link_init(dw): for i in range(8): yield - yield dut.link_layer.ready.eq(1) + yield dut[dw].link_layer.ready.eq(1) - def send_packet(packet): + def send_packet(packet, dw): for i, d in enumerate(packet): - yield from dut.aux_controller.bus.write(i, d) - yield from dut.aux_controller.transmitter.aux_tx_length.write(len(packet)*4) - yield from dut.aux_controller.transmitter.aux_tx.write(1) + yield from dut[dw].aux_controller.bus.write(i, d) + yield from dut[dw].aux_controller.transmitter.aux_tx_length.write(len(packet)*dw//8) + yield from dut[dw].aux_controller.transmitter.aux_tx.write(1) yield - while (yield from dut.aux_controller.transmitter.aux_tx.read()): + while (yield from dut[dw].aux_controller.transmitter.aux_tx.read()): yield - def receive_packet(): - while not (yield from dut.aux_controller.receiver.aux_rx_present.read()): + def receive_packet(dw): + while not (yield from dut[dw].aux_controller.receiver.aux_rx_present.read()): yield - length = yield from dut.aux_controller.receiver.aux_rx_length.read() + length = yield from dut[dw].aux_controller.receiver.aux_rx_length.read() r = [] - for i in range(length//4): - r.append((yield from dut.aux_controller.bus.read(256+i))) - yield from dut.aux_controller.receiver.aux_rx_present.write(1) + for i in range(length//(dw//8)): + r.append((yield from dut[dw].aux_controller.bus.read(256+i))) + yield from dut[dw].aux_controller.receiver.aux_rx_present.write(1) return r prng = random.Random(0) - def send_and_check_packet(): - data = [prng.randrange(2**32-1) for _ in range(prng.randrange(1, 16))] - yield from send_packet(data) - received = yield from receive_packet() + def send_and_check_packet(dw): + data = [prng.randrange(2**dw-1) for _ in range(prng.randrange(1, 16))] + yield from send_packet(data, dw) + received = yield from receive_packet(dw) self.assertEqual(data, received) - def sim(): - yield from link_init() + def sim(dw): + yield from link_init(dw) for i in range(8): - yield from send_and_check_packet() + yield from send_and_check_packet(dw) @passive - def rt_traffic(): + def rt_traffic(dw): while True: while prng.randrange(4): yield - yield dut.link_layer.tx_rt_frame.eq(1) + yield dut[dw].link_layer.tx_rt_frame.eq(1) yield while prng.randrange(4): yield - yield dut.link_layer.tx_rt_frame.eq(0) + yield dut[dw].link_layer.tx_rt_frame.eq(0) yield - run_simulation(dut, [sim(), rt_traffic()]) + run_simulation(dut[32], [sim(32), rt_traffic(32)]) + run_simulation(dut[64], [sim(64), rt_traffic(64)]) diff --git a/artiq/gateware/test/rtio/test_dma.py b/artiq/gateware/test/rtio/test_dma.py index 84bc4a3ff..c5d220a9f 100644 --- a/artiq/gateware/test/rtio/test_dma.py +++ b/artiq/gateware/test/rtio/test_dma.py @@ -31,24 +31,25 @@ def encode_record(channel, timestamp, address, data): return encode_n(len(r)+1, 1, 1) + r -def pack(x, size): +def pack(x, size, dw): r = [] for i in range((len(x)+size-1)//size): n = 0 - for j in range(i*size, (i+1)*size): - n <<= 8 + for j in range(i*size//(dw//8), (i+1)*size//(dw//8)): + n <<= dw try: - n |= x[j] + encoded = int.from_bytes(x[j*(dw//8): (j+1)*(dw//8)], "little") + n |= encoded except IndexError: pass r.append(n) return r -def encode_sequence(writes, ws): +def encode_sequence(writes, ws, dw): sequence = [b for write in writes for b in encode_record(*write)] sequence.append(0) - return pack(sequence, ws) + return pack(sequence, ws, dw) def do_dma(dut, address): @@ -84,9 +85,9 @@ prng = random.Random(0) class TB(Module): - def __init__(self, ws): - sequence1 = encode_sequence(test_writes1, ws) - sequence2 = encode_sequence(test_writes2, ws) + def __init__(self, ws, dw): + sequence1 = encode_sequence(test_writes1, ws, dw) + sequence2 = encode_sequence(test_writes2, ws, dw) offset = 512//ws assert len(sequence1) < offset sequence = ( @@ -97,7 +98,7 @@ class TB(Module): bus = wishbone.Interface(ws*8) self.submodules.memory = wishbone.SRAM( 1024, init=sequence, bus=bus) - self.submodules.dut = dma.DMA(bus) + self.submodules.dut = dma.DMA(bus, dw) test_writes_full_stack = [ @@ -109,7 +110,7 @@ test_writes_full_stack = [ class FullStackTB(Module): - def __init__(self, ws): + def __init__(self, ws, dw): self.ttl0 = Signal() self.ttl1 = Signal() @@ -121,12 +122,12 @@ class FullStackTB(Module): rtio.Channel.from_phy(self.phy1) ] - sequence = encode_sequence(test_writes_full_stack, ws) + sequence = encode_sequence(test_writes_full_stack, ws, dw) - bus = wishbone.Interface(ws*8) + bus = wishbone.Interface(ws*8, 32-log2_int(dw//8)) self.submodules.memory = wishbone.SRAM( 256, init=sequence, bus=bus) - self.submodules.dut = dma.DMA(bus) + self.submodules.dut = dma.DMA(bus, dw) self.submodules.tsc = rtio.TSC("async") self.submodules.rtio = rtio.Core(self.tsc, rtio_channels) self.comb += self.dut.cri.connect(self.rtio.cri) @@ -134,16 +135,22 @@ class FullStackTB(Module): class TestDMA(unittest.TestCase): def test_dma_noerror(self): - tb = TB(64) + tb = { + 32: TB(64, 32), + 64: TB(64, 64) + } - def do_writes(): - yield from do_dma(tb.dut, 0) - yield from do_dma(tb.dut, 512) + def do_writes(dw): + yield from do_dma(tb[dw].dut, 0) + yield from do_dma(tb[dw].dut, 512) - received = [] + received = { + 32: [], + 64: [] + } @passive - def rtio_sim(): - dut_cri = tb.dut.cri + def rtio_sim(dw): + dut_cri = tb[dw].dut.cri while True: cmd = yield dut_cri.cmd if cmd == cri.commands["nop"]: @@ -153,7 +160,7 @@ class TestDMA(unittest.TestCase): timestamp = yield dut_cri.o_timestamp address = yield dut_cri.o_address data = yield dut_cri.o_data - received.append((channel, timestamp, address, data)) + received[dw].append((channel, timestamp, address, data)) yield dut_cri.o_status.eq(1) for i in range(prng.randrange(10)): @@ -163,32 +170,46 @@ class TestDMA(unittest.TestCase): self.fail("unexpected RTIO command") yield - run_simulation(tb, [do_writes(), rtio_sim()]) - self.assertEqual(received, test_writes1 + test_writes2) + run_simulation(tb[32], [do_writes(32), rtio_sim(32)]) + self.assertEqual(received[32], test_writes1 + test_writes2) + + run_simulation(tb[64], [do_writes(64), rtio_sim(64)]) + self.assertEqual(received[64], test_writes1 + test_writes2) def test_full_stack(self): - tb = FullStackTB(64) + tb = { + 32: FullStackTB(64, 32), + 64: FullStackTB(64, 64) + } - ttl_changes = [] + ttl_changes = { + 32: [], + 64: [] + } @passive - def monitor(): + def monitor(dw): old_ttl_states = [0, 0] for time in itertools.count(): ttl_states = [ - (yield tb.ttl0), - (yield tb.ttl1) + (yield tb[dw].ttl0), + (yield tb[dw].ttl1) ] for i, (old, new) in enumerate(zip(old_ttl_states, ttl_states)): if new != old: - ttl_changes.append((time, i)) + ttl_changes[dw].append((time, i)) old_ttl_states = ttl_states yield - run_simulation(tb, {"sys": [ - do_dma(tb.dut, 0), monitor(), + run_simulation(tb[32], {"sys": [ + do_dma(tb[32].dut, 0), monitor(32), + (None for _ in range(70)), + ]}, {"sys": 8, "rsys": 8, "rtio": 8, "rio": 8, "rio_phy": 8}) + run_simulation(tb[64], {"sys": [ + do_dma(tb[64].dut, 0), monitor(64), (None for _ in range(70)), ]}, {"sys": 8, "rsys": 8, "rtio": 8, "rio": 8, "rio_phy": 8}) correct_changes = [(timestamp + 11, channel) for channel, timestamp, _, _ in test_writes_full_stack] - self.assertEqual(ttl_changes, correct_changes) + self.assertEqual(ttl_changes[32], correct_changes) + self.assertEqual(ttl_changes[64], correct_changes) From db3e5e83e6c45b3037a3f414b2434993f355b1fe Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 13:14:00 +0800 Subject: [PATCH 211/238] bump misoc --- artiq/firmware/ksupport/Makefile | 2 +- flake.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/artiq/firmware/ksupport/Makefile b/artiq/firmware/ksupport/Makefile index b73faea50..e1e3e48fd 100644 --- a/artiq/firmware/ksupport/Makefile +++ b/artiq/firmware/ksupport/Makefile @@ -26,7 +26,7 @@ $(RUSTOUT)/libksupport.a: ksupport.elf: $(RUSTOUT)/libksupport.a glue.o $(link) -T $(KSUPPORT_DIRECTORY)/ksupport.ld \ - -lunwind-elf -lprintf-float -lm + -lunwind-$(CPU)-elf -lprintf-float -lm %.o: $(KSUPPORT_DIRECTORY)/%.c $(compile) diff --git a/flake.lock b/flake.lock index e9c80a1ad..d2e349045 100644 --- a/flake.lock +++ b/flake.lock @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1634799783, - "narHash": "sha256-CbeXsLTwwYBWb5cfrVVYkcQYV207gi9+CQhzfeZbXGc=", + "lastModified": 1636345885, + "narHash": "sha256-+6tqAX+ek+jUU8m59vhhp4QS9UK+D2a6pLD1aFDIWX8=", "ref": "master", - "rev": "855914deace34880c69589022c52a8921f431063", - "revCount": 2375, + "rev": "87f77a739b587a6602b87ee1a94da509d36ba269", + "revCount": 2414, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From ac2f55b3ffca761e6d326e689739ecd8397d4c02 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 8 Nov 2021 16:55:29 +0800 Subject: [PATCH 212/238] flake: patch llvmlite --- flake.nix | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index a43321d0e..fe46d4cd7 100644 --- a/flake.nix +++ b/flake.nix @@ -102,11 +102,18 @@ llvmlite-new = pkgs.python3Packages.buildPythonPackage rec { pname = "llvmlite"; - version = "0.37.0rc2"; + version = "0.37.0-artiq"; src = pkgs.python3Packages.fetchPypi { - inherit pname version; - sha256 = "sha256-F1quz+76JOt1jaQPVzdKe7RfN6gWG2lyE82qTvgyY/c="; + inherit pname; + version = "0.37.0"; + sha256 = "sha256-Y5K4cM0BjsDGRda7uRjWqg7sqMYmdLqu4whi1raGWxU="; }; + patches = [ + (pkgs.fetchurl { + url = "https://git.m-labs.hk/M-Labs/nix-scripts/raw/branch/master/artiq-fast/pkgs/llvmlite-abiname.diff"; + sha256 = "1zlss9vlhjgch6gf5gc0647kkjdwjk0833ld88xwd9vmwvkdmp3v"; + }) + ]; nativeBuildInputs = [ pkgs.llvm_11 ]; # Disable static linking # https://github.com/numba/llvmlite/issues/93 From 80115fcc022400e2f0e914481a1f13dd6d33e70b Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 8 Nov 2021 17:34:30 +0800 Subject: [PATCH 213/238] flake: apply llvmlite callsite patch --- flake.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flake.nix b/flake.nix index fe46d4cd7..4630d3ec8 100644 --- a/flake.nix +++ b/flake.nix @@ -113,6 +113,10 @@ url = "https://git.m-labs.hk/M-Labs/nix-scripts/raw/branch/master/artiq-fast/pkgs/llvmlite-abiname.diff"; sha256 = "1zlss9vlhjgch6gf5gc0647kkjdwjk0833ld88xwd9vmwvkdmp3v"; }) + (pkgs.fetchurl { + url = "https://git.m-labs.hk/M-Labs/nix-scripts/raw/branch/master/artiq-fast/pkgs/llvmlite-callsite.diff"; + sha256 = "sha256-JrIXPnI7E7Y5NIFxswVBmRfQvv61lqKDDnNJrr+nDCg="; + }) ]; nativeBuildInputs = [ pkgs.llvm_11 ]; # Disable static linking From c029977a27fc05b9c49b8865949704184d314622 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 10 Nov 2021 09:54:34 +0800 Subject: [PATCH 214/238] flake: update dependencies --- flake.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index d2e349045..0c5b07076 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "mozilla-overlay": { "flake": false, "locked": { - "lastModified": 1629225446, - "narHash": "sha256-HJX4Pc5ZUAg4apxB/XHuJ+6ukzvRQqeZMjscOBst2bA=", + "lastModified": 1636047415, + "narHash": "sha256-iDFogua24bhFJZSxG/jhZbbNxDXuKP9S/pyRIYzrRPM=", "owner": "mozilla", "repo": "nixpkgs-mozilla", - "rev": "0510159186dd2ef46e5464484fbdf119393afa58", + "rev": "cf58c4c67b15b402e77a2665b9e7bad3e9293cb2", "type": "github" }, "original": { @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1634758644, - "narHash": "sha256-H3UW/msC6wadg28lcgZv2Ge/P7dWxesL6i37a0GOeyM=", + "lastModified": 1636333654, + "narHash": "sha256-3wh9PtCzcaJQuZrgZ+ygKfhltkDNNqT6zOzGsRbjZEo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "70904d4a9927a4d6e05c72c4aaac4370e05107f3", + "rev": "e74894146a42ba552ebafa19ab2d1df7ccbc1738", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1636345885, - "narHash": "sha256-+6tqAX+ek+jUU8m59vhhp4QS9UK+D2a6pLD1aFDIWX8=", + "lastModified": 1636508796, + "narHash": "sha256-5dRDFxwKye4X6QQkdNma3SJknPXZDUUyF9GUwgS1Otc=", "ref": "master", - "rev": "87f77a739b587a6602b87ee1a94da509d36ba269", - "revCount": 2414, + "rev": "51ea207bfbc03a552071df0bbf770913ba904217", + "revCount": 2416, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From 46604300a20430c66c58e3c4722e56fc2808c740 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 10 Nov 2021 14:59:02 +0800 Subject: [PATCH 215/238] flake: update dependencies --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 0c5b07076..cfa0d3a4d 100644 --- a/flake.lock +++ b/flake.lock @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1636508796, - "narHash": "sha256-5dRDFxwKye4X6QQkdNma3SJknPXZDUUyF9GUwgS1Otc=", + "lastModified": 1636527305, + "narHash": "sha256-/2XTejqj0Bo81HaTrlTSWwInnWwsuqnq+CURXbpIrkA=", "ref": "master", - "rev": "51ea207bfbc03a552071df0bbf770913ba904217", - "revCount": 2416, + "rev": "f5203e406520874e15ab5d070058ef642fc57fd9", + "revCount": 2417, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From f0c50c80e67ee1bca336c8bf6689b554922fde04 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 12 Nov 2021 19:28:51 +0800 Subject: [PATCH 216/238] flake: update dependencies --- flake.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/flake.lock b/flake.lock index cfa0d3a4d..b01ba2a41 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "mozilla-overlay": { "flake": false, "locked": { - "lastModified": 1636047415, + "lastModified": 1636569584, "narHash": "sha256-iDFogua24bhFJZSxG/jhZbbNxDXuKP9S/pyRIYzrRPM=", "owner": "mozilla", "repo": "nixpkgs-mozilla", - "rev": "cf58c4c67b15b402e77a2665b9e7bad3e9293cb2", + "rev": "9f70f86d73fa97e043bebeb58e5676d157069cfb", "type": "github" }, "original": { @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1636333654, - "narHash": "sha256-3wh9PtCzcaJQuZrgZ+ygKfhltkDNNqT6zOzGsRbjZEo=", + "lastModified": 1636552551, + "narHash": "sha256-k7Hq/bvUnRlAfFjPGuw3FsSqqspQdRHsCHpgadw6UkQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e74894146a42ba552ebafa19ab2d1df7ccbc1738", + "rev": "9e86f5f7a19db6da2445f07bafa6694b556f9c6d", "type": "github" }, "original": { @@ -45,11 +45,11 @@ "src-migen": { "flake": false, "locked": { - "lastModified": 1634182166, - "narHash": "sha256-Iw2d8fCgwuuIevkugSqd8Iplj6N+2nR1pn+or5E38Fk=", + "lastModified": 1636715924, + "narHash": "sha256-V3ThFSo2d7OC4SHE0lCkKGQKeFXmvxtwZRWe5NMU3nM=", "owner": "m-labs", "repo": "migen", - "rev": "7507a2bb16dd2cac63535175ce67fb30dfdae1c0", + "rev": "9a0be7a4210ff96043412539eb5388659b81831d", "type": "github" }, "original": { From 20e079a381b777550ce7872151b17fb4a11cd7ae Mon Sep 17 00:00:00 2001 From: Peter Drmota <49479443+pmldrmota@users.noreply.github.com> Date: Mon, 15 Nov 2021 05:09:16 +0100 Subject: [PATCH 217/238] AD9910 driver feature extension and SUServo IIR readability (#1500) * coredevice.ad9910: Add set_cfr2 function and extend arguments of set_cfr1 and set_sync * SUServo: Wrap CPLD and DDS devices in a list * SUServo: Refactor [nfc] Co-authored-by: drmota Co-authored-by: David Nadlinger --- RELEASE_NOTES.rst | 3 + artiq/coredevice/ad9910.py | 72 +++++-- artiq/coredevice/suservo.py | 56 ++--- artiq/examples/kasli_suservo/device_db.py | 6 +- artiq/frontend/artiq_ddb_template.py | 15 +- artiq/gateware/suservo/__init__.py | 10 + artiq/gateware/suservo/iir.py | 246 +++++++++++++--------- artiq/gateware/suservo/servo.py | 66 +++++- artiq/gateware/targets/kasli.py | 6 +- 9 files changed, 301 insertions(+), 179 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index c743f2005..467e4e9c4 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -104,6 +104,9 @@ Breaking changes: * ``quamash`` has been replaced with ``qasync``. * Protocols are updated to use device endian. * Analyzer dump format includes a byte for device endianness. +* To support variable numbers of Urukul cards in the future, the + ``artiq.coredevice.suservo.SUServo`` constructor now accepts two device name lists, + ``cpld_devices`` and ``dds_devices``, rather than four individual arguments. * Experiment classes with underscore-prefixed names are now ignored when ``artiq_client`` determines which experiment to submit (consistent with ``artiq_run``). diff --git a/artiq/coredevice/ad9910.py b/artiq/coredevice/ad9910.py index 95ad66896..49bfe9a90 100644 --- a/artiq/coredevice/ad9910.py +++ b/artiq/coredevice/ad9910.py @@ -374,18 +374,25 @@ class AD9910: data[(n - preload) + i] = self.bus.read() @kernel - def set_cfr1(self, power_down: TInt32 = 0b0000, + def set_cfr1(self, + power_down: TInt32 = 0b0000, phase_autoclear: TInt32 = 0, - drg_load_lrr: TInt32 = 0, drg_autoclear: TInt32 = 0, - internal_profile: TInt32 = 0, ram_destination: TInt32 = 0, - ram_enable: TInt32 = 0, manual_osk_external: TInt32 = 0, - osk_enable: TInt32 = 0, select_auto_osk: TInt32 = 0): + drg_load_lrr: TInt32 = 0, + drg_autoclear: TInt32 = 0, + phase_clear: TInt32 = 0, + internal_profile: TInt32 = 0, + ram_destination: TInt32 = 0, + ram_enable: TInt32 = 0, + manual_osk_external: TInt32 = 0, + osk_enable: TInt32 = 0, + select_auto_osk: TInt32 = 0): """Set CFR1. See the AD9910 datasheet for parameter meanings. This method does not pulse IO_UPDATE. :param power_down: Power down bits. :param phase_autoclear: Autoclear phase accumulator. + :param phase_clear: Asynchronous, static reset of the phase accumulator. :param drg_load_lrr: Load digital ramp generator LRR. :param drg_autoclear: Autoclear digital ramp generator. :param internal_profile: Internal profile control. @@ -405,11 +412,41 @@ class AD9910: (drg_load_lrr << 15) | (drg_autoclear << 14) | (phase_autoclear << 13) | + (phase_clear << 11) | (osk_enable << 9) | (select_auto_osk << 8) | (power_down << 4) | 2) # SDIO input only, MSB first + @kernel + def set_cfr2(self, + asf_profile_enable: TInt32 = 1, + drg_enable: TInt32 = 0, + effective_ftw: TInt32 = 1, + sync_validation_disable: TInt32 = 0, + matched_latency_enable: TInt32 = 0): + """Set CFR2. See the AD9910 datasheet for parameter meanings. + + This method does not pulse IO_UPDATE. + + :param asf_profile_enable: Enable amplitude scale from single tone profiles. + :param drg_enable: Digital ramp enable. + :param effective_ftw: Read effective FTW. + :param sync_validation_disable: Disable the SYNC_SMP_ERR pin indicating + (active high) detection of a synchronization pulse sampling error. + :param matched_latency_enable: Simultaneous application of amplitude, + phase, and frequency changes to the DDS arrive at the output + + * matched_latency_enable = 0: in the order listed + * matched_latency_enable = 1: simultaneously. + """ + self.write32(_AD9910_REG_CFR2, + (asf_profile_enable << 24) | + (drg_enable << 19) | + (effective_ftw << 16) | + (matched_latency_enable << 7) | + (sync_validation_disable << 5)) + @kernel def init(self, blind: TBool = False): """Initialize and configure the DDS. @@ -442,7 +479,7 @@ class AD9910: # enable amplitude scale from profiles # read effective FTW # sync timing validation disable (enabled later) - self.write32(_AD9910_REG_CFR2, 0x01010020) + self.set_cfr2(sync_validation_disable=1) self.cpld.io_update.pulse(1 * us) cfr3 = (0x0807c000 | (self.pll_vco << 24) | (self.pll_cp << 19) | (self.pll_en << 8) | @@ -465,7 +502,7 @@ class AD9910: if i >= 100 - 1: raise ValueError("PLL lock timeout") delay(10 * us) # slack - if self.sync_data.sync_delay_seed >= 0: + if self.sync_data.sync_delay_seed >= 0 and not blind: self.tune_sync_delay(self.sync_data.sync_delay_seed) delay(1 * ms) @@ -875,20 +912,26 @@ class AD9910: self.cpld.cfg_sw(self.chip_select - 4, state) @kernel - def set_sync(self, in_delay: TInt32, window: TInt32): + def set_sync(self, + in_delay: TInt32, + window: TInt32, + en_sync_gen: TInt32 = 0): """Set the relevant parameters in the multi device synchronization register. See the AD9910 datasheet for details. The SYNC clock generator preset value is set to zero, and the SYNC_OUT generator is - disabled. + disabled by default. :param in_delay: SYNC_IN delay tap (0-31) in steps of ~75ps :param window: Symmetric SYNC_IN validation window (0-15) in steps of ~75ps for both hold and setup margin. + :param en_sync_gen: Whether to enable the DDS-internal sync generator + (SYNC_OUT, cf. sync_sel == 1). Should be left off for the normal + use case, where the SYNC clock is supplied by the core device. """ self.write32(_AD9910_REG_SYNC, (window << 28) | # SYNC S/H validation delay (1 << 27) | # SYNC receiver enable - (0 << 26) | # SYNC generator disable + (en_sync_gen << 26) | # SYNC generator enable (0 << 25) | # SYNC generator SYS rising edge (0 << 18) | # SYNC preset (0 << 11) | # SYNC output delay @@ -904,9 +947,10 @@ class AD9910: Also modifies CFR2. """ - self.write32(_AD9910_REG_CFR2, 0x01010020) # clear SMP_ERR + self.set_cfr2(sync_validation_disable=1) # clear SMP_ERR self.cpld.io_update.pulse(1 * us) - self.write32(_AD9910_REG_CFR2, 0x01010000) # enable SMP_ERR + delay(10 * us) # slack + self.set_cfr2(sync_validation_disable=0) # enable SMP_ERR self.cpld.io_update.pulse(1 * us) @kernel @@ -984,7 +1028,7 @@ class AD9910: # set up DRG self.set_cfr1(drg_load_lrr=1, drg_autoclear=1) # DRG -> FTW, DRG enable - self.write32(_AD9910_REG_CFR2, 0x01090000) + self.set_cfr2(drg_enable=1) # no limits self.write64(_AD9910_REG_RAMP_LIMIT, -1, 0) # DRCTL=0, dt=1 t_SYNC_CLK @@ -1005,7 +1049,7 @@ class AD9910: ftw = self.read32(_AD9910_REG_FTW) # read out effective FTW delay(100 * us) # slack # disable DRG - self.write32(_AD9910_REG_CFR2, 0x01010000) + self.set_cfr2(drg_enable=0) self.cpld.io_update.pulse_mu(8) return ftw & 1 diff --git a/artiq/coredevice/suservo.py b/artiq/coredevice/suservo.py index 932adf35b..1d0a72dad 100644 --- a/artiq/coredevice/suservo.py +++ b/artiq/coredevice/suservo.py @@ -57,32 +57,26 @@ class SUServo: :param channel: RTIO channel number :param pgia_device: Name of the Sampler PGIA gain setting SPI bus - :param cpld0_device: Name of the first Urukul CPLD SPI bus - :param cpld1_device: Name of the second Urukul CPLD SPI bus - :param dds0_device: Name of the AD9910 device for the DDS on the first - Urukul - :param dds1_device: Name of the AD9910 device for the DDS on the second - Urukul + :param cpld_devices: Names of the Urukul CPLD SPI buses + :param dds_devices: Names of the AD9910 devices :param gains: Initial value for PGIA gains shift register (default: 0x0000). Knowledge of this state is not transferred between experiments. :param core_device: Core device name """ - kernel_invariants = {"channel", "core", "pgia", "cpld0", "cpld1", - "dds0", "dds1", "ref_period_mu"} + kernel_invariants = {"channel", "core", "pgia", "cplds", "ddses", + "ref_period_mu"} def __init__(self, dmgr, channel, pgia_device, - cpld0_device, cpld1_device, - dds0_device, dds1_device, + cpld_devices, dds_devices, gains=0x0000, core_device="core"): self.core = dmgr.get(core_device) self.pgia = dmgr.get(pgia_device) self.pgia.update_xfer_duration_mu(div=4, length=16) - self.dds0 = dmgr.get(dds0_device) - self.dds1 = dmgr.get(dds1_device) - self.cpld0 = dmgr.get(cpld0_device) - self.cpld1 = dmgr.get(cpld1_device) + assert len(dds_devices) == len(cpld_devices) + self.ddses = [dmgr.get(dds) for dds in dds_devices] + self.cplds = [dmgr.get(cpld) for cpld in cpld_devices] self.channel = channel self.gains = gains self.ref_period_mu = self.core.seconds_to_mu( @@ -109,17 +103,15 @@ class SUServo: sampler.SPI_CONFIG | spi.SPI_END, 16, 4, sampler.SPI_CS_PGIA) - self.cpld0.init(blind=True) - cfg0 = self.cpld0.cfg_reg - self.cpld0.cfg_write(cfg0 | (0xf << urukul.CFG_MASK_NU)) - self.dds0.init(blind=True) - self.cpld0.cfg_write(cfg0) + for i in range(len(self.cplds)): + cpld = self.cplds[i] + dds = self.ddses[i] - self.cpld1.init(blind=True) - cfg1 = self.cpld1.cfg_reg - self.cpld1.cfg_write(cfg1 | (0xf << urukul.CFG_MASK_NU)) - self.dds1.init(blind=True) - self.cpld1.cfg_write(cfg1) + cpld.init(blind=True) + prev_cpld_cfg = cpld.cfg_reg + cpld.cfg_write(prev_cpld_cfg | (0xf << urukul.CFG_MASK_NU)) + dds.init(blind=True) + cpld.cfg_write(prev_cpld_cfg) @kernel def write(self, addr, value): @@ -257,9 +249,11 @@ class Channel: self.servo = dmgr.get(servo_device) self.core = self.servo.core self.channel = channel - # FIXME: this assumes the mem channel is right after the control - # channels - self.servo_channel = self.channel + 8 - self.servo.channel + # This assumes the mem channel is right after the control channels + # Make sure this is always the case in eem.py + self.servo_channel = (self.channel + 4 * len(self.servo.cplds) - + self.servo.channel) + self.dds = self.servo.ddses[self.servo_channel // 4] @kernel def set(self, en_out, en_iir=0, profile=0): @@ -311,12 +305,8 @@ class Channel: see :meth:`dds_offset_to_mu` :param phase: DDS phase in turns """ - if self.servo_channel < 4: - dds = self.servo.dds0 - else: - dds = self.servo.dds1 - ftw = dds.frequency_to_ftw(frequency) - pow_ = dds.turns_to_pow(phase) + ftw = self.dds.frequency_to_ftw(frequency) + pow_ = self.dds.turns_to_pow(phase) offs = self.dds_offset_to_mu(offset) self.set_dds_mu(profile, ftw, offs, pow_) diff --git a/artiq/examples/kasli_suservo/device_db.py b/artiq/examples/kasli_suservo/device_db.py index d33bfb280..fdb85dc47 100644 --- a/artiq/examples/kasli_suservo/device_db.py +++ b/artiq/examples/kasli_suservo/device_db.py @@ -191,10 +191,8 @@ device_db = { "arguments": { "channel": 24, "pgia_device": "spi_sampler0_pgia", - "cpld0_device": "urukul0_cpld", - "cpld1_device": "urukul1_cpld", - "dds0_device": "urukul0_dds", - "dds1_device": "urukul1_dds" + "cpld_devices": ["urukul0_cpld", "urukul1_cpld"], + "dds_devices": ["urukul0_dds", "urukul1_dds"], } }, diff --git a/artiq/frontend/artiq_ddb_template.py b/artiq/frontend/artiq_ddb_template.py index 52408a0d4..0a14a06be 100755 --- a/artiq/frontend/artiq_ddb_template.py +++ b/artiq/frontend/artiq_ddb_template.py @@ -364,8 +364,7 @@ class PeripheralManager: def process_suservo(self, rtio_offset, peripheral): suservo_name = self.get_name("suservo") sampler_name = self.get_name("sampler") - urukul0_name = self.get_name("urukul") - urukul1_name = self.get_name("urukul") + urukul_names = [self.get_name("urukul") for _ in range(2)] channel = count(0) for i in range(8): self.gen(""" @@ -386,16 +385,14 @@ class PeripheralManager: "arguments": {{ "channel": 0x{suservo_channel:06x}, "pgia_device": "spi_{sampler_name}_pgia", - "cpld0_device": "{urukul0_name}_cpld", - "cpld1_device": "{urukul1_name}_cpld", - "dds0_device": "{urukul0_name}_dds", - "dds1_device": "{urukul1_name}_dds" + "cpld_devices": {cpld_names_list}, + "dds_devices": {dds_names_list} }} }}""", suservo_name=suservo_name, sampler_name=sampler_name, - urukul0_name=urukul0_name, - urukul1_name=urukul1_name, + cpld_names_list=[urukul_name + "_cpld" for urukul_name in urukul_names], + dds_names_list=[urukul_name + "_dds" for urukul_name in urukul_names], suservo_channel=rtio_offset+next(channel)) self.gen(""" device_db["spi_{sampler_name}_pgia"] = {{ @@ -407,7 +404,7 @@ class PeripheralManager: sampler_name=sampler_name, sampler_channel=rtio_offset+next(channel)) pll_vco = peripheral.get("pll_vco") - for urukul_name in (urukul0_name, urukul1_name): + for urukul_name in urukul_names: self.gen(""" device_db["spi_{urukul_name}"] = {{ "type": "local", diff --git a/artiq/gateware/suservo/__init__.py b/artiq/gateware/suservo/__init__.py index e69de29bb..7a1df77ac 100644 --- a/artiq/gateware/suservo/__init__.py +++ b/artiq/gateware/suservo/__init__.py @@ -0,0 +1,10 @@ +"""Gateware implementation of the Sampler-Urukul (AD9910) DDS amplitude servo. + +General conventions: + + - ``t_...`` signals and constants refer to time spans measured in the gateware + module's default clock (typically a 125 MHz RTIO clock). + - ``start`` signals cause modules to proceed with the next servo iteration iff + they are currently idle (i.e. their value is irrelevant while the module is + busy, so they are not necessarily one-clock-period strobes). +""" diff --git a/artiq/gateware/suservo/iir.py b/artiq/gateware/suservo/iir.py index 0ebab3f13..0ec9bfa09 100644 --- a/artiq/gateware/suservo/iir.py +++ b/artiq/gateware/suservo/iir.py @@ -1,9 +1,7 @@ from collections import namedtuple import logging - from migen import * - logger = logging.getLogger(__name__) @@ -222,31 +220,30 @@ class IIR(Module): assert w.word <= w.coeff # same memory assert w.state + w.coeff + 3 <= w.accu - # m_coeff of active profiles should only be accessed during + # m_coeff of active profiles should only be accessed externally during # ~processing self.specials.m_coeff = Memory( width=2*w.coeff, # Cat(pow/ftw/offset, cfg/a/b) depth=4 << w.profile + w.channel) - # m_state[x] should only be read during ~(shifting | - # loading) - # m_state[y] of active profiles should only be read during + # m_state[x] should only be read externally during ~(shifting | loading) + # m_state[y] of active profiles should only be read externally during # ~processing self.specials.m_state = Memory( width=w.state, # y1,x0,x1 depth=(1 << w.profile + w.channel) + (2 << w.channel)) # ctrl should only be updated synchronously self.ctrl = [Record([ - ("profile", w.profile), - ("en_out", 1), - ("en_iir", 1), - ("clip", 1), - ("stb", 1)]) - for i in range(1 << w.channel)] + ("profile", w.profile), + ("en_out", 1), + ("en_iir", 1), + ("clip", 1), + ("stb", 1)]) + for i in range(1 << w.channel)] # only update during ~loading self.adc = [Signal((w.adc, True), reset_less=True) for i in range(1 << w.channel)] # Cat(ftw0, ftw1, pow, asf) - # only read during ~processing + # only read externally during ~processing self.dds = [Signal(4*w.word, reset_less=True) for i in range(1 << w.channel)] # perform one IIR iteration, start with loading, @@ -270,100 +267,116 @@ class IIR(Module): en_iirs = Array([ch.en_iir for ch in self.ctrl]) clips = Array([ch.clip for ch in self.ctrl]) - # state counter - state = Signal(w.channel + 2) - # pipeline group activity flags (SR) - stage = Signal(3) + # Main state machine sequencing the steps of each servo iteration. The + # module IDLEs until self.start is asserted, and then runs through LOAD, + # PROCESS and SHIFT in order (see description of corresponding flags + # above). The steps share the same memory ports, and are executed + # strictly sequentially. + # + # LOAD/SHIFT just read/write one address per cycle; the duration needed + # to iterate over all channels is determined by counting cycles. + # + # The PROCESSing step is split across a three-stage pipeline, where each + # stage has up to four clock cycles latency. We feed the first stage + # using the (MSBs of) t_current_step, and, after all channels have been + # covered, proceed once the pipeline has completely drained. self.submodules.fsm = fsm = FSM("IDLE") - state_clr = Signal() - stage_en = Signal() + t_current_step = Signal(w.channel + 2) + t_current_step_clr = Signal() + + # pipeline group activity flags (SR) + # 0: load from memory + # 1: compute + # 2: write to output registers (DDS profiles, clip flags) + stages_active = Signal(3) fsm.act("IDLE", self.done.eq(1), - state_clr.eq(1), + t_current_step_clr.eq(1), If(self.start, NextState("LOAD") ) ) fsm.act("LOAD", self.loading.eq(1), - If(state == (1 << w.channel) - 1, - state_clr.eq(1), - stage_en.eq(1), + If(t_current_step == (1 << w.channel) - 1, + t_current_step_clr.eq(1), + NextValue(stages_active[0], 1), NextState("PROCESS") ) ) fsm.act("PROCESS", self.processing.eq(1), # this is technically wasting three cycles - # (one for setting stage, and phase=2,3 with stage[2]) - If(stage == 0, - state_clr.eq(1), - NextState("SHIFT") + # (one for setting stages_active, and phase=2,3 with stages_active[2]) + If(stages_active == 0, + t_current_step_clr.eq(1), + NextState("SHIFT"), ) ) fsm.act("SHIFT", self.shifting.eq(1), - If(state == (2 << w.channel) - 1, + If(t_current_step == (2 << w.channel) - 1, NextState("IDLE") ) ) self.sync += [ - state.eq(state + 1), - If(state_clr, - state.eq(0), - ), - If(stage_en, - stage[0].eq(1) + If(t_current_step_clr, + t_current_step.eq(0) + ).Else( + t_current_step.eq(t_current_step + 1) ) ] - # pipeline group channel pointer + # global pipeline phase (lower two bits of t_current_step) + pipeline_phase = Signal(2, reset_less=True) + # pipeline group channel pointer (SR) # for each pipeline stage, this is the channel currently being # processed channel = [Signal(w.channel, reset_less=True) for i in range(3)] + self.comb += Cat(pipeline_phase, channel[0]).eq(t_current_step) + self.sync += [ + If(pipeline_phase == 3, + Cat(channel[1:]).eq(Cat(channel[:-1])), + stages_active[1:].eq(stages_active[:-1]), + If(channel[0] == (1 << w.channel) - 1, + stages_active[0].eq(0) + ) + ) + ] + # pipeline group profile pointer (SR) # for each pipeline stage, this is the profile currently being # processed profile = [Signal(w.profile, reset_less=True) for i in range(2)] - # pipeline phase (lower two bits of state) - phase = Signal(2, reset_less=True) - - self.comb += Cat(phase, channel[0]).eq(state) self.sync += [ - Case(phase, { - 0: [ - profile[0].eq(profiles[channel[0]]), - profile[1].eq(profile[0]) - ], - 3: [ - Cat(channel[1:]).eq(Cat(channel[:-1])), - stage[1:].eq(stage[:-1]), - If(channel[0] == (1 << w.channel) - 1, - stage[0].eq(0) - ) - ] - }) + If(pipeline_phase == 0, + profile[0].eq(profiles[channel[0]]), + profile[1].eq(profile[0]), + ) ] m_coeff = self.m_coeff.get_port() m_state = self.m_state.get_port(write_capable=True) # mode=READ_FIRST self.specials += m_state, m_coeff + # + # Hook up main IIR filter. + # + dsp = DSP(w) self.submodules += dsp offset_clr = Signal() - self.comb += [ - m_coeff.adr.eq(Cat(phase, profile[0], - Mux(phase==0, channel[1], channel[0]))), + m_coeff.adr.eq(Cat(pipeline_phase, profile[0], + Mux(pipeline_phase == 0, channel[1], channel[0]))), dsp.offset[-w.coeff - 1:].eq(Mux(offset_clr, 0, Cat(m_coeff.dat_r[:w.coeff], m_coeff.dat_r[w.coeff - 1]) )), dsp.coeff.eq(m_coeff.dat_r[w.coeff:]), dsp.state.eq(m_state.dat_r), - Case(phase, { + Case(pipeline_phase, { 0: dsp.accu_clr.eq(1), 2: [ offset_clr.eq(1), @@ -373,6 +386,11 @@ class IIR(Module): }) ] + + # + # Arbitrate state memory access between steps. + # + # selected adc and profile delay (combinatorial from dat_r) # both share the same coeff word (sel in the lower 8 bits) sel_profile = Signal(w.channel) @@ -389,13 +407,13 @@ class IIR(Module): sel_profile.eq(m_coeff.dat_r[w.coeff:]), dly_profile.eq(m_coeff.dat_r[w.coeff + 8:]), If(self.shifting, - m_state.adr.eq(state | (1 << w.profile + w.channel)), + m_state.adr.eq(t_current_step | (1 << w.profile + w.channel)), m_state.dat_w.eq(m_state.dat_r), - m_state.we.eq(state[0]) + m_state.we.eq(t_current_step[0]) ), If(self.loading, - m_state.adr.eq((state << 1) | (1 << w.profile + w.channel)), - m_state.dat_w[-w.adc - 1:-1].eq(Array(self.adc)[state]), + m_state.adr.eq((t_current_step << 1) | (1 << w.profile + w.channel)), + m_state.dat_w[-w.adc - 1:-1].eq(Array(self.adc)[t_current_step]), m_state.dat_w[-1].eq(m_state.dat_w[-2]), m_state.we.eq(1) ), @@ -405,16 +423,20 @@ class IIR(Module): Cat(profile[1], channel[2]), # read old y Cat(profile[0], channel[0]), - # x0 (recent) + # read x0 (recent) 0 | (sel_profile << 1) | (1 << w.profile + w.channel), - # x1 (old) + # read x1 (old) 1 | (sel << 1) | (1 << w.profile + w.channel), - ])[phase]), + ])[pipeline_phase]), m_state.dat_w.eq(dsp.output), - m_state.we.eq((phase == 0) & stage[2] & en[1]), + m_state.we.eq((pipeline_phase == 0) & stages_active[2] & en[1]), ) ] + # + # Compute auxiliary signals (delayed servo enable, clip indicators, etc.). + # + # internal channel delay counters dlys = Array([Signal(w.dly) for i in range(1 << w.channel)]) @@ -434,51 +456,65 @@ class IIR(Module): en_out = Signal(reset_less=True) # latched channel en_iir en_iir = Signal(reset_less=True) + + self.sync += [ + Case(pipeline_phase, { + 0: [ + dly.eq(dlys[channel[0]]), + en_out.eq(en_outs[channel[0]]), + en_iir.eq(en_iirs[channel[0]]), + If(stages_active[2] & en[1] & dsp.clip, + clips[channel[2]].eq(1) + ) + ], + 2: [ + en[0].eq(0), + en[1].eq(en[0]), + sel.eq(sel_profile), + If(stages_active[0] & en_out, + If(dly != dly_profile, + dlys[channel[0]].eq(dly + 1) + ).Elif(en_iir, + en[0].eq(1) + ) + ) + ], + }), + ] + + # + # Update DDS profile with FTW/POW/ASF + # Stage 0 loads the POW, stage 1 the FTW, and stage 2 writes + # the ASF computed by the IIR filter. + # + # muxing ddss = Array(self.dds) self.sync += [ - Case(phase, { - 0: [ - dly.eq(dlys[channel[0]]), - en_out.eq(en_outs[channel[0]]), - en_iir.eq(en_iirs[channel[0]]), - If(stage[1], - ddss[channel[1]][:w.word].eq(m_coeff.dat_r) - ), - If(stage[2] & en[1] & dsp.clip, - clips[channel[2]].eq(1) - ) - ], - 1: [ - If(stage[1], - ddss[channel[1]][w.word:2*w.word].eq( - m_coeff.dat_r), - ), - If(stage[2], - ddss[channel[2]][3*w.word:].eq( - m_state.dat_r[w.state - w.asf - 1:w.state - 1]) - ) - ], - 2: [ - en[0].eq(0), - en[1].eq(en[0]), - sel.eq(sel_profile), - If(stage[0], - ddss[channel[0]][2*w.word:3*w.word].eq( - m_coeff.dat_r), - If(en_out, - If(dly != dly_profile, - dlys[channel[0]].eq(dly + 1) - ).Elif(en_iir, - en[0].eq(1) - ) - ) - ) - ], - 3: [ - ], - }), + Case(pipeline_phase, { + 0: [ + If(stages_active[1], + ddss[channel[1]][:w.word].eq(m_coeff.dat_r), # ftw0 + ), + ], + 1: [ + If(stages_active[1], + ddss[channel[1]][w.word:2 * w.word].eq(m_coeff.dat_r), # ftw1 + ), + If(stages_active[2], + ddss[channel[2]][3*w.word:].eq( # asf + m_state.dat_r[w.state - w.asf - 1:w.state - 1]) + ) + ], + 2: [ + If(stages_active[0], + ddss[channel[0]][2*w.word:3*w.word].eq(m_coeff.dat_r), # pow + ), + ], + 3: [ + ], + }), ] def _coeff(self, channel, profile, coeff): diff --git a/artiq/gateware/suservo/servo.py b/artiq/gateware/suservo/servo.py index 08b31a3bc..1aec95f02 100644 --- a/artiq/gateware/suservo/servo.py +++ b/artiq/gateware/suservo/servo.py @@ -5,32 +5,76 @@ from .iir import IIR, IIRWidths from .dds_ser import DDS, DDSParams +def predict_timing(adc_p, iir_p, dds_p): + """ + The following is a sketch of the timing for 1 Sampler (8 ADCs) and N Urukuls + Shown here, the cycle duration is limited by the IIR loading+processing time. + + ADC|CONVH|CONV|READ|RTT|IDLE|CONVH|CONV|READ|RTT|IDLE|CONVH|CONV|READ|RTT|... + |4 |57 |16 |8 | .. |4 |57 |16 |8 | .. |4 |57 |16 |8 |... + ---+-------------------+------------------------+------------------------+--- + IIR| |LOAD|PROC |SHIFT|LOAD|PROC |SHIFT|... + | |8 |16*N+9 |16 |8 |16*N+9 |16 |... + ---+--------------------------------------+------------------------+--------- + DDS| |CMD|PROF|WAIT|IO_UP|IDLE|CMD|PR... + | |16 |128 |1 |1 | .. |16 | ... + + IIR loading starts once the ADC presents its data, the DDSes are updated + once the IIR processing is over. These are the only blocking processes. + IIR shifting happens in parallel to writing to the DDSes and ADC conversions + take place while the IIR filter is processing or the DDSes are being + written to, depending on the cycle duration (given by whichever module + takes the longest). + """ + t_adc = (adc_p.t_cnvh + adc_p.t_conv + adc_p.t_rtt + + adc_p.channels*adc_p.width//adc_p.lanes) + 1 + # load adc_p.channels values, process dds_p.channels + # (4 processing phases and 2 additional stages à 4 phases + # to complete the processing of the last channel) + t_iir = adc_p.channels + 4*dds_p.channels + 8 + 1 + t_dds = (dds_p.width*2 + 1)*dds_p.clk + 1 + t_cycle = max(t_adc, t_iir, t_dds) + return t_adc, t_iir, t_dds, t_cycle + class Servo(Module): def __init__(self, adc_pads, dds_pads, adc_p, iir_p, dds_p): + t_adc, t_iir, t_dds, t_cycle = predict_timing(adc_p, iir_p, dds_p) + assert t_iir + 2*adc_p.channels < t_cycle, "need shifting time" + self.submodules.adc = ADC(adc_pads, adc_p) self.submodules.iir = IIR(iir_p) self.submodules.dds = DDS(dds_pads, dds_p) # adc channels are reversed on Sampler - for i, j, k, l in zip(reversed(self.adc.data), self.iir.adc, - self.iir.dds, self.dds.profile): - self.comb += j.eq(i), l.eq(k) - - t_adc = (adc_p.t_cnvh + adc_p.t_conv + adc_p.t_rtt + - adc_p.channels*adc_p.width//adc_p.lanes) + 1 - t_iir = ((1 + 4 + 1) << iir_p.channel) + 1 - t_dds = (dds_p.width*2 + 1)*dds_p.clk + 1 - - t_cycle = max(t_adc, t_iir, t_dds) - assert t_iir + (2 << iir_p.channel) < t_cycle, "need shifting time" + for iir, adc in zip(self.iir.adc, reversed(self.adc.data)): + self.comb += iir.eq(adc) + for dds, iir in zip(self.dds.profile, self.iir.dds): + self.comb += dds.eq(iir) + # If high, a new cycle is started if the current cycle (if any) is + # finished. Consequently, if low, servo iterations cease after the + # current cycle is finished. Don't care while the first step (ADC) + # is active. self.start = Signal() + + # Counter for delay between end of ADC cycle and start of next one, + # depending on the duration of the other steps. t_restart = t_cycle - t_adc + 1 assert t_restart > 1 cnt = Signal(max=t_restart) cnt_done = Signal() active = Signal(3) + + # Indicates whether different steps (0: ADC, 1: IIR, 2: DDS) are + # currently active (exposed for simulation only), with each bit being + # reset once the successor step is launched. Depending on the + # timing details of the different steps, any number can be concurrently + # active (e.g. ADC read from iteration n, IIR computation from iteration + # n - 1, and DDS write from iteration n - 2). + + # Asserted once per cycle when the DDS write has been completed. self.done = Signal() + self.sync += [ If(self.dds.done, active[2].eq(0) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 311028fcb..cf8b5760f 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -228,9 +228,9 @@ class SUServo(StandaloneBase): ttl_serdes_7series.Output_8X, ttl_serdes_7series.Output_8X) # EEM3/2: Sampler, EEM5/4: Urukul, EEM7/6: Urukul - eem.SUServo.add_std( - self, eems_sampler=(3, 2), - eems_urukul0=(5, 4), eems_urukul1=(7, 6)) + eem.SUServo.add_std(self, + eems_sampler=(3, 2), + eems_urukul=[[5, 4], [7, 6]]) for i in (1, 2): sfp_ctl = self.platform.request("sfp_ctl", i) From b49f813b17de89933d075bde433939d61480b05f Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Thu, 18 Nov 2021 16:42:51 +0800 Subject: [PATCH 218/238] artiq_flash: ignore checking non-RTM artifacts if unused --- artiq/frontend/artiq_flash.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index 1641e31fd..62b8dc39c 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -362,7 +362,10 @@ def main(): variants.remove("rtm") except ValueError: pass - if len(variants) == 0: + if all(action in ["rtm_gateware", "storage", "rtm_load", "erase", "start"] + for action in args.action) and args.action: + pass + elif len(variants) == 0: raise FileNotFoundError("no variants found, did you install a board binary package?") elif len(variants) == 1: variant = variants[0] From 7307b30213d6b9b7ff3979024b1f7de77137f9f9 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 23 Nov 2021 12:15:17 +0800 Subject: [PATCH 219/238] flake: update to nixpkgs 21.11 --- flake.lock | 14 +++++++------- flake.nix | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/flake.lock b/flake.lock index b01ba2a41..4f321cd7b 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "mozilla-overlay": { "flake": false, "locked": { - "lastModified": 1636569584, - "narHash": "sha256-iDFogua24bhFJZSxG/jhZbbNxDXuKP9S/pyRIYzrRPM=", + "lastModified": 1637337116, + "narHash": "sha256-LKqAcdL+woWeYajs02bDQ7q8rsqgXuzhC354NoRaV80=", "owner": "mozilla", "repo": "nixpkgs-mozilla", - "rev": "9f70f86d73fa97e043bebeb58e5676d157069cfb", + "rev": "cbc7435f5b0b3d17b16fb1d20cf7b616eec5e093", "type": "github" }, "original": { @@ -18,16 +18,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1636552551, - "narHash": "sha256-k7Hq/bvUnRlAfFjPGuw3FsSqqspQdRHsCHpgadw6UkQ=", + "lastModified": 1637636156, + "narHash": "sha256-E2ym4Vcpqu9JYoQDXJZR48gVD+LPPbaCoYveIk7Xu3Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9e86f5f7a19db6da2445f07bafa6694b556f9c6d", + "rev": "b026e1cf87a108dd06fe521f224fdc72fd0b013d", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-21.05", + "ref": "release-21.11", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index 4630d3ec8..867166534 100644 --- a/flake.nix +++ b/flake.nix @@ -1,7 +1,7 @@ { description = "A leading-edge control system for quantum information experiments"; - inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-21.05; + inputs.nixpkgs.url = github:NixOS/nixpkgs/release-21.11; inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; }; inputs.src-sipyco = { url = github:m-labs/sipyco; flake = false; }; inputs.src-pythonparser = { url = github:m-labs/pythonparser; flake = false; }; From 9423428bb006fbd104c52a494eb31df79cd3e8d6 Mon Sep 17 00:00:00 2001 From: occheung Date: Mon, 22 Nov 2021 16:53:57 +0800 Subject: [PATCH 220/238] drtio: fix crc32 offset address --- artiq/firmware/libboard_artiq/drtioaux.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/artiq/firmware/libboard_artiq/drtioaux.rs b/artiq/firmware/libboard_artiq/drtioaux.rs index f72072702..818775d7b 100644 --- a/artiq/firmware/libboard_artiq/drtioaux.rs +++ b/artiq/firmware/libboard_artiq/drtioaux.rs @@ -137,11 +137,10 @@ pub fn send(linkno: u8, packet: &Packet) -> Result<(), Error> { packet.write_to(&mut writer)?; - let padding = 4 - (writer.position() % 4); - if padding != 4 { - for _ in 0..padding { - writer.write_u8(0)?; - } + // Pad till offset 4, insert checksum there + let padding = (12 - (writer.position() % 8)) % 8; + for _ in 0..padding { + writer.write_u8(0)?; } let checksum = crc::crc32::checksum_ieee(&writer.get_ref()[0..writer.position()]); From 5ed9e49b94630bdafebb261907d66dff0533ec4c Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 24 Nov 2021 11:52:59 +0800 Subject: [PATCH 221/238] changelog: update drtio protocol --- RELEASE_NOTES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 467e4e9c4..54cb3a284 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -38,6 +38,7 @@ Breaking changes: * Phaser: fixed coarse mixer frequency configuration * Mirny: Added extra delays in ``ADF5356.sync()``. This avoids the need of an extra delay before calling `ADF5356.init()`. +* DRTIO: Changed message alignment from 32-bits to 64-bits. ARTIQ-6 From 6a433b2fcefc30dc9882b0421b6bb7d62f335b22 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 24 Nov 2021 18:57:16 +0800 Subject: [PATCH 222/238] artiq_sinara_tester: test Urukul attenuator digital control --- artiq/frontend/artiq_sinara_tester.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/artiq/frontend/artiq_sinara_tester.py b/artiq/frontend/artiq_sinara_tester.py index 22ba53740..2a0392eec 100755 --- a/artiq/frontend/artiq_sinara_tester.py +++ b/artiq/frontend/artiq_sinara_tester.py @@ -229,6 +229,17 @@ class SinaraTester(EnvExperiment): self.core.break_realtime() cpld.init() + @kernel + def test_urukul_att(self, cpld): + self.core.break_realtime() + for i in range(32): + test_word = 1 << i + cpld.set_all_att_mu(test_word) + readback_word = cpld.get_att_mu() + if readback_word != test_word: + print(readback_word, test_word) + raise ValueError + @kernel def calibrate_urukul(self, channel): self.core.break_realtime() @@ -268,11 +279,12 @@ class SinaraTester(EnvExperiment): def test_urukuls(self): print("*** Testing Urukul DDSes.") - print("Initializing CPLDs...") for name, cpld in sorted(self.urukul_cplds.items(), key=lambda x: x[0]): - print(name + "...") + print(name + ": initializing CPLD...") self.init_urukul(cpld) - print("...done") + print(name + ": testing attenuator digital control...") + self.test_urukul_att(cpld) + print(name + ": done") print("Calibrating inter-device synchronization...") for channel_name, channel_dev in self.urukuls: From 9b01db3d112622a5a7ebbcb0b353d89b91807fc2 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 6 Nov 2021 22:34:32 +0000 Subject: [PATCH 223/238] compiler: Emit sret call site argument attributes LLVM 6 seemed not to mind the mismatch, but more recent versions produce miscompilations without this. Needs llvmlite support (GitHub: numba/llvmlite#702). --- artiq/compiler/transforms/llvm_ir_generator.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 084e5ae09..9e3482c18 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1355,7 +1355,7 @@ class LLVMIRGenerator: llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), []) llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee) - llcall = self.llbuilder.call(llfun, [llresultslot] + llargs) + self.llbuilder.call(llfun, [llresultslot] + llargs, arg_attrs={0: "sret"}) llresult = self.llbuilder.load(llresultslot) self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llstackptr]) @@ -1388,7 +1388,8 @@ class LLVMIRGenerator: llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee) llcall = self.llbuilder.invoke(llfun, [llresultslot] + llargs, - llnormalblock, llunwindblock, name=insn.name) + llnormalblock, llunwindblock, name=insn.name, + arg_attrs={0: "sret"}) self.llbuilder.position_at_start(llnormalblock) llresult = self.llbuilder.load(llresultslot) From 63b5727a0c69069d0096d6146b26c51b404640ce Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 6 Nov 2021 22:56:52 +0000 Subject: [PATCH 224/238] compiler: Also emit byval argument attributes at call sites See previous commit. GitHub: Fixes #1599. --- .../compiler/transforms/llvm_ir_generator.py | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 9e3482c18..5f61db822 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1174,26 +1174,32 @@ class LLVMIRGenerator: else: llfun = self.map(insn.static_target_function) llenv = self.llbuilder.extract_value(llclosure, 0, name="env.fun") - return llfun, [llenv] + list(llargs) + return llfun, [llenv] + list(llargs), {} def _prepare_ffi_call(self, insn): llargs = [] - byvals = [] + llarg_attrs = {} for i, arg in enumerate(insn.arguments()): llarg = self.map(arg) if isinstance(llarg.type, (ll.LiteralStructType, ll.IdentifiedStructType)): llslot = self.llbuilder.alloca(llarg.type) self.llbuilder.store(llarg, llslot) llargs.append(llslot) - byvals.append(i) + llarg_attrs[i] = "byval" else: llargs.append(llarg) + llretty = self.llty_of_type(insn.type, for_return=True) + is_sret = self.needs_sret(llretty) + if is_sret: + llarg_attrs = {i + 1: a for (i, a) in llarg_attrs.items()} + llarg_attrs[0] = "sret" + llfunname = insn.target_function().type.name llfun = self.llmodule.globals.get(llfunname) if llfun is None: - llretty = self.llty_of_type(insn.type, for_return=True) - if self.needs_sret(llretty): + # Function has not been declared in the current LLVM module, do it now. + if is_sret: llfunty = ll.FunctionType(llvoid, [llretty.as_pointer()] + [llarg.type for llarg in llargs]) else: @@ -1201,17 +1207,14 @@ class LLVMIRGenerator: llfun = ll.Function(self.llmodule, llfunty, insn.target_function().type.name) - if self.needs_sret(llretty): - llfun.args[0].add_attribute('sret') - byvals = [i + 1 for i in byvals] - for i in byvals: - llfun.args[i].add_attribute('byval') + for idx, attr in llarg_attrs.items(): + llfun.args[idx].add_attribute(attr) if 'nounwind' in insn.target_function().type.flags: llfun.attributes.add('nounwind') if 'nowrite' in insn.target_function().type.flags: llfun.attributes.add('inaccessiblememonly') - return llfun, list(llargs) + return llfun, list(llargs), llarg_attrs def _build_rpc(self, fun_loc, fun_type, args, llnormalblock, llunwindblock): llservice = ll.Constant(lli32, fun_type.service) @@ -1347,20 +1350,21 @@ class LLVMIRGenerator: insn.arguments(), llnormalblock=None, llunwindblock=None) elif types.is_external_function(functiontyp): - llfun, llargs = self._prepare_ffi_call(insn) + llfun, llargs, llarg_attrs = self._prepare_ffi_call(insn) else: - llfun, llargs = self._prepare_closure_call(insn) + llfun, llargs, llarg_attrs = self._prepare_closure_call(insn) if self.has_sret(functiontyp): llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), []) llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee) - self.llbuilder.call(llfun, [llresultslot] + llargs, arg_attrs={0: "sret"}) + self.llbuilder.call(llfun, [llresultslot] + llargs, arg_attrs=llarg_attrs) llresult = self.llbuilder.load(llresultslot) self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llstackptr]) else: - llcall = llresult = self.llbuilder.call(llfun, llargs, name=insn.name) + llresult = self.llbuilder.call(llfun, llargs, name=insn.name, + arg_attrs=llarg_attrs) if isinstance(llresult.type, ll.VoidType): # We have NoneType-returning functions return void, but None is @@ -1379,9 +1383,9 @@ class LLVMIRGenerator: insn.arguments(), llnormalblock, llunwindblock) elif types.is_external_function(functiontyp): - llfun, llargs = self._prepare_ffi_call(insn) + llfun, llargs, llarg_attrs = self._prepare_ffi_call(insn) else: - llfun, llargs = self._prepare_closure_call(insn) + llfun, llargs, llarg_attrs = self._prepare_closure_call(insn) if self.has_sret(functiontyp): llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), []) @@ -1389,7 +1393,7 @@ class LLVMIRGenerator: llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee) llcall = self.llbuilder.invoke(llfun, [llresultslot] + llargs, llnormalblock, llunwindblock, name=insn.name, - arg_attrs={0: "sret"}) + arg_attrs=llarg_attrs) self.llbuilder.position_at_start(llnormalblock) llresult = self.llbuilder.load(llresultslot) @@ -1397,7 +1401,7 @@ class LLVMIRGenerator: self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llstackptr]) else: llcall = self.llbuilder.invoke(llfun, llargs, llnormalblock, llunwindblock, - name=insn.name) + name=insn.name, arg_attrs=llarg_attrs) llresult = llcall # The !tbaa metadata is not legal to use with the invoke instruction, From c6039479e47e56743657355184c5f249e5137743 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 27 Nov 2021 04:43:52 +0000 Subject: [PATCH 225/238] compiler: Add lit test for call site attributes [nfc] --- artiq/test/lit/embedding/syscall_arg_attrs.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 artiq/test/lit/embedding/syscall_arg_attrs.py diff --git a/artiq/test/lit/embedding/syscall_arg_attrs.py b/artiq/test/lit/embedding/syscall_arg_attrs.py new file mode 100644 index 000000000..67207dc32 --- /dev/null +++ b/artiq/test/lit/embedding/syscall_arg_attrs.py @@ -0,0 +1,30 @@ +# RUN: env ARTIQ_DUMP_LLVM=%t %python -m artiq.compiler.testbench.embedding +compile %s +# RUN: OutputCheck %s --file-to-check=%t.ll + +from artiq.language.core import * +from artiq.language.types import * + +# Make sure `byval` and `sret` are specified both at the call site and the +# declaration. This isn't caught by the LLVM IR validator, but mismatches +# lead to miscompilations (at least in LLVM 11). + + +@kernel +def entrypoint(): + # CHECK: call void @accept_str\({ i8\*, i32 }\* nonnull byval + accept_str("foo") + + # CHECK: call void @return_str\({ i8\*, i32 }\* nonnull sret + return_str() + + +# CHECK: declare void @accept_str\({ i8\*, i32 }\* byval\) +@syscall +def accept_str(name: TStr) -> TNone: + pass + + +# CHECK: declare void @return_str\({ i8\*, i32 }\* sret\) +@syscall +def return_str() -> TStr: + pass From 5a923a095674a8192186847426a08c6f8743d800 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 1 Dec 2021 22:39:24 +0800 Subject: [PATCH 226/238] flake: switch to nixos- branch --- flake.lock | 8 ++++---- flake.nix | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index 4f321cd7b..bf378e2eb 100644 --- a/flake.lock +++ b/flake.lock @@ -18,16 +18,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1637636156, - "narHash": "sha256-E2ym4Vcpqu9JYoQDXJZR48gVD+LPPbaCoYveIk7Xu3Y=", + "lastModified": 1638279546, + "narHash": "sha256-1KCwN7twjp1dBdp0jPgVdYFztDkCR8+roo0B34J9oBY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b026e1cf87a108dd06fe521f224fdc72fd0b013d", + "rev": "96b4157790fc96e70d6e6c115e3f34bba7be490f", "type": "github" }, "original": { "owner": "NixOS", - "ref": "release-21.11", + "ref": "nixos-21.11", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index 867166534..834a8eab9 100644 --- a/flake.nix +++ b/flake.nix @@ -1,7 +1,7 @@ { description = "A leading-edge control system for quantum information experiments"; - inputs.nixpkgs.url = github:NixOS/nixpkgs/release-21.11; + inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-21.11; inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; }; inputs.src-sipyco = { url = github:m-labs/sipyco; flake = false; }; inputs.src-pythonparser = { url = github:m-labs/pythonparser; flake = false; }; From b8e7add785526ff599db5e892d83d482bf85951c Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 1 Dec 2021 22:41:34 +0800 Subject: [PATCH 227/238] language: remove deprecated set_dataset(..., save=...) --- RELEASE_NOTES.rst | 1 + artiq/language/environment.py | 8 +------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 54cb3a284..048e9876c 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -39,6 +39,7 @@ Breaking changes: * Mirny: Added extra delays in ``ADF5356.sync()``. This avoids the need of an extra delay before calling `ADF5356.init()`. * DRTIO: Changed message alignment from 32-bits to 64-bits. +* The deprecated ``set_dataset(..., save=...)`` is no longer supported. ARTIQ-6 diff --git a/artiq/language/environment.py b/artiq/language/environment.py index 7992fe3af..a1de09e5b 100644 --- a/artiq/language/environment.py +++ b/artiq/language/environment.py @@ -1,4 +1,3 @@ -import warnings from collections import OrderedDict from inspect import isclass @@ -331,7 +330,7 @@ class HasEnvironment: @rpc(flags={"async"}) def set_dataset(self, key, value, - broadcast=False, persist=False, archive=True, save=None): + broadcast=False, persist=False, archive=True): """Sets the contents and handling modes of a dataset. Datasets must be scalars (``bool``, ``int``, ``float`` or NumPy scalar) @@ -343,12 +342,7 @@ class HasEnvironment: broadcast. :param archive: the data is saved into the local storage of the current run (archived as a HDF5 file). - :param save: deprecated. """ - if save is not None: - warnings.warn("set_dataset save parameter is deprecated, " - "use archive instead", FutureWarning) - archive = save self.__dataset_mgr.set(key, value, broadcast, persist, archive) @rpc(flags={"async"}) From 9f830b86c059fe356da2962d8755d258f5b86233 Mon Sep 17 00:00:00 2001 From: Etienne Wodey <44871469+airwoodix@users.noreply.github.com> Date: Fri, 3 Dec 2021 10:05:35 +0100 Subject: [PATCH 228/238] kasli: add SED lanes count option to HW description JSON file (#1745) Signed-off-by: Etienne Wodey --- RELEASE_NOTES.rst | 2 ++ artiq/coredevice/coredevice_generic.schema.json | 7 +++++++ artiq/gateware/targets/kasli.py | 12 ++++++------ artiq/gateware/targets/kasli_generic.py | 7 ++++--- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 048e9876c..6dc247b04 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -20,6 +20,8 @@ Highlights: - Exposes upconverter calibration and enabling/disabling of upconverter LO & RF outputs. - Add helpers to align Phaser updates to the RTIO timeline (``get_next_frame_mu()``) * ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912 +* On Kasli, the number of FIFO lanes in the scalable events dispatcher (SED) can now be configured in + the JSON hardware description file. * New hardware support: - HVAMP_8CH 8 channel HV amplifier for Fastino / Zotino * ``artiq_ddb_template`` generates edge-counter keys that start with the key of the corresponding diff --git a/artiq/coredevice/coredevice_generic.schema.json b/artiq/coredevice/coredevice_generic.schema.json index 64e4a9251..274d7e2aa 100644 --- a/artiq/coredevice/coredevice_generic.schema.json +++ b/artiq/coredevice/coredevice_generic.schema.json @@ -64,6 +64,13 @@ "type": "boolean", "default": false }, + "sed_lanes": { + "type": "number", + "minimum": 1, + "maximum": 32, + "default": 8, + "description": "Number of FIFOs in the SED, must be a power of 2" + }, "peripherals": { "type": "array", "items": { diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index cf8b5760f..71ee933a5 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -135,12 +135,12 @@ class StandaloneBase(MiniSoC, AMPSoC): self.config["HAS_SI5324"] = None self.config["SI5324_SOFT_RESET"] = None - def add_rtio(self, rtio_channels): + def add_rtio(self, rtio_channels, sed_lanes=8): self.submodules.rtio_crg = _RTIOCRG(self.platform) self.csr_devices.append("rtio_crg") fix_serdes_timing_path(self.platform) self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) - self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) + self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels, lane_count=sed_lanes) self.csr_devices.append("rtio_core") self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) self.submodules.rtio_dma = ClockDomainsRenamer("sys_kernel")( @@ -375,13 +375,13 @@ class MasterBase(MiniSoC, AMPSoC): self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) - def add_rtio(self, rtio_channels): + def add_rtio(self, rtio_channels, sed_lanes=8): # Only add MonInj core if there is anything to monitor if any([len(c.probes) for c in rtio_channels]): self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) self.csr_devices.append("rtio_moninj") - self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels) + self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels, lane_count=sed_lanes) self.csr_devices.append("rtio_core") self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) @@ -608,13 +608,13 @@ class SatelliteBase(BaseSoC): self.csr_devices.append("rtio_crg") fix_serdes_timing_path(platform) - def add_rtio(self, rtio_channels): + def add_rtio(self, rtio_channels, sed_lanes=8): # Only add MonInj core if there is anything to monitor if any([len(c.probes) for c in rtio_channels]): self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) self.csr_devices.append("rtio_moninj") - self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels) + self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels, lane_count=sed_lanes) self.comb += self.drtiosat.async_errors.eq(self.local_io.async_errors) self.submodules.cri_con = rtio.CRIInterconnectShared( [self.drtiosat.cri], diff --git a/artiq/gateware/targets/kasli_generic.py b/artiq/gateware/targets/kasli_generic.py index 122c3e0cf..bb822f41e 100755 --- a/artiq/gateware/targets/kasli_generic.py +++ b/artiq/gateware/targets/kasli_generic.py @@ -57,7 +57,8 @@ class GenericStandalone(StandaloneBase): self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels) self.rtio_channels.append(rtio.LogChannel()) - self.add_rtio(self.rtio_channels) + self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"]) + if has_grabber: self.config["HAS_GRABBER"] = None self.add_csr_group("grabber", self.grabber_csr_group) @@ -94,7 +95,7 @@ class GenericMaster(MasterBase): self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels) self.rtio_channels.append(rtio.LogChannel()) - self.add_rtio(self.rtio_channels) + self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"]) if has_grabber: self.config["HAS_GRABBER"] = None self.add_csr_group("grabber", self.grabber_csr_group) @@ -127,7 +128,7 @@ class GenericSatellite(SatelliteBase): self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels) self.rtio_channels.append(rtio.LogChannel()) - self.add_rtio(self.rtio_channels) + self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"]) if has_grabber: self.config["HAS_GRABBER"] = None self.add_csr_group("grabber", self.grabber_csr_group) From 163f5d91281c1fe01f47f2c8aad9160242c2acd9 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 3 Dec 2021 17:16:54 +0800 Subject: [PATCH 229/238] flake: debug hitl auth failures --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 834a8eab9..75ef864af 100644 --- a/flake.nix +++ b/flake.nix @@ -405,6 +405,7 @@ phases = [ "buildPhase" ]; buildPhase = '' + whoami export HOME=`mktemp -d` mkdir $HOME/.ssh cp /opt/hydra_id_rsa $HOME/.ssh/id_rsa From eec3ea6589fe8aafeadab2f07dc826b522b5d4e8 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 26 Nov 2021 13:17:40 +0800 Subject: [PATCH 230/238] siphaser: add support for 100mhz rtio --- artiq/gateware/drtio/siphaser.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/artiq/gateware/drtio/siphaser.py b/artiq/gateware/drtio/siphaser.py index 81dacaed0..9dbee2d11 100644 --- a/artiq/gateware/drtio/siphaser.py +++ b/artiq/gateware/drtio/siphaser.py @@ -4,7 +4,7 @@ from migen.genlib.cdc import MultiReg, PulseSynchronizer from misoc.interconnect.csr import * -# This code assumes 125/62.5MHz reference clock and 125MHz or 150MHz RTIO +# This code assumes 125/62.5MHz reference clock and 100MHz, 125MHz or 150MHz RTIO # frequency. class SiPhaser7Series(Module, AutoCSR): @@ -15,9 +15,9 @@ class SiPhaser7Series(Module, AutoCSR): self.phase_shift_done = CSRStatus(reset=1) self.error = CSR() - assert rtio_clk_freq in (125e6, 150e6) + assert rtio_clk_freq in (100e6, 125e6, 150e6) - # 125MHz/62.5MHz reference clock to 125MHz/150MHz. VCO @ 750MHz. + # 125MHz/62.5MHz reference clock to 100MHz/125MHz/150MHz. VCO @ 750MHz. # Used to provide a startup clock to the transceiver through the Si, # we do not use the crystal reference so that the PFD (f3) frequency # can be high. @@ -43,7 +43,7 @@ class SiPhaser7Series(Module, AutoCSR): else: mmcm_freerun_output = mmcm_freerun_output_raw - # 125MHz/150MHz to 125MHz/150MHz with controllable phase shift, + # 100MHz/125MHz/150MHz to 100MHz/125MHz/150MHz with controllable phase shift, # VCO @ 1000MHz/1200MHz. # Inserted between CDR and output to Si, used to correct # non-determinstic skew of Si5324. From f281112779606f279a3f8dde05a25b71080082fb Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 3 Dec 2021 11:22:15 +0800 Subject: [PATCH 231/238] satman: add 100mhz si5324 settings siphaser: add calculated vco for 100mhz comment --- artiq/firmware/satman/main.rs | 13 +++++++++++++ artiq/gateware/drtio/siphaser.py | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index e0ec83612..c6685f895 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -447,6 +447,19 @@ const SI5324_SETTINGS: si5324::FrequencySettings crystal_ref: true }; +#[cfg(all(has_si5324, rtio_frequency = "100.0"))] +const SI5324_SETTINGS: si5324::FrequencySettings + = si5324::FrequencySettings { + n1_hs : 5, + nc1_ls : 10, + n2_hs : 10, + n2_ls : 250, + n31 : 50, + n32 : 50, + bwsel : 4, + crystal_ref: true +}; + #[no_mangle] pub extern fn main() -> i32 { extern { diff --git a/artiq/gateware/drtio/siphaser.py b/artiq/gateware/drtio/siphaser.py index 9dbee2d11..5237b7453 100644 --- a/artiq/gateware/drtio/siphaser.py +++ b/artiq/gateware/drtio/siphaser.py @@ -44,7 +44,7 @@ class SiPhaser7Series(Module, AutoCSR): mmcm_freerun_output = mmcm_freerun_output_raw # 100MHz/125MHz/150MHz to 100MHz/125MHz/150MHz with controllable phase shift, - # VCO @ 1000MHz/1200MHz. + # VCO @ 800MHz/1000MHz/1200MHz. # Inserted between CDR and output to Si, used to correct # non-determinstic skew of Si5324. mmcm_ps_fb = Signal() From 7953f3d7054404a7c4a7729ef04af65f20eabf92 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 3 Dec 2021 11:53:48 +0800 Subject: [PATCH 232/238] kc705: add drtio 100mhz clk switch --- artiq/gateware/targets/kc705.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 4cec96e87..e04088a92 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -129,7 +129,7 @@ class _StandaloneBase(MiniSoC, AMPSoC): } mem_map.update(MiniSoC.mem_map) - def __init__(self, gateware_identifier_str=None, **kwargs): + def __init__(self, gateware_identifier_str=None, drtio_100mhz=False, **kwargs): MiniSoC.__init__(self, cpu_type="vexriscv", cpu_bus_width=64, @@ -207,7 +207,7 @@ class _MasterBase(MiniSoC, AMPSoC): } mem_map.update(MiniSoC.mem_map) - def __init__(self, gateware_identifier_str=None, **kwargs): + def __init__(self, gateware_identifier_str=None, drtio_100mhz=False, **kwargs): MiniSoC.__init__(self, cpu_type="vexriscv", cpu_bus_width=64, @@ -236,11 +236,14 @@ class _MasterBase(MiniSoC, AMPSoC): platform.request("sfp"), platform.request("user_sma_mgt") ] - # 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock + rtio_clk_freq = 100e6 if drtio_100mhz else 125e6 + + # 1000BASE_BX10 Ethernet compatible, 100/125MHz RTIO clock self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("si5324_clkout"), pads=data_pads, - sys_clk_freq=self.clk_freq) + sys_clk_freq=self.clk_freq, + rtio_clk_freq=rtio_clk_freq) self.csr_devices.append("drtio_transceiver") self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3) @@ -341,7 +344,7 @@ class _SatelliteBase(BaseSoC): } mem_map.update(BaseSoC.mem_map) - def __init__(self, gateware_identifier_str=None, sma_as_sat=False, **kwargs): + def __init__(self, gateware_identifier_str=None, sma_as_sat=False, drtio_100mhz=False, **kwargs): BaseSoC.__init__(self, cpu_type="vexriscv", cpu_bus_width=64, @@ -369,11 +372,14 @@ class _SatelliteBase(BaseSoC): if sma_as_sat: data_pads = data_pads[::-1] - # 1000BASE_BX10 Ethernet compatible, 125MHz RTIO clock + rtio_clk_freq = 100e6 if drtio_100mhz else 125e6 + + # 1000BASE_BX10 Ethernet compatible, 100/125MHz RTIO clock self.submodules.drtio_transceiver = gtx_7series.GTX( clock_pads=platform.request("si5324_clkout"), pads=data_pads, - sys_clk_freq=self.clk_freq) + sys_clk_freq=self.clk_freq, + rtio_clk_freq=rtio_clk_freq) self.csr_devices.append("drtio_transceiver") self.submodules.rtio_tsc = rtio.TSC("sync", glbl_fine_ts_width=3) @@ -673,6 +679,8 @@ def main(): "(default: %(default)s)") parser.add_argument("--gateware-identifier-str", default=None, help="Override ROM identifier") + parser.add_argument("--drtio100mhz", action="store_true", default=False, + help="DRTIO systems only - use 100MHz RTIO clock") args = parser.parse_args() variant = args.variant.lower() @@ -681,7 +689,7 @@ def main(): except KeyError: raise SystemExit("Invalid variant (-V/--variant)") - soc = cls(gateware_identifier_str=args.gateware_identifier_str, **soc_kc705_argdict(args)) + soc = cls(gateware_identifier_str=args.gateware_identifier_str, drtio_100mhz=args.drtio100mhz, **soc_kc705_argdict(args)) build_artiq_soc(soc, builder_argdict(args)) From f8a649deda89460f3d56a43b798e2190b9039597 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 3 Dec 2021 11:55:23 +0800 Subject: [PATCH 233/238] release notes: mention 100mhz support --- RELEASE_NOTES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 6dc247b04..a1c807008 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -30,6 +30,7 @@ Highlights: repository when building the list of experiments. * The configuration entry ``rtio_clock`` supports multiple clocking settings, deprecating the usage of compile-time options. +* DRTIO: added support for 100MHz clock. Breaking changes: From 9bbf7eb48539082ee57e3f9b6faef7b0246a042b Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 3 Dec 2021 18:34:49 +0800 Subject: [PATCH 234/238] flake: use ed25519 key for hitl --- flake.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 75ef864af..5fa94518d 100644 --- a/flake.nix +++ b/flake.nix @@ -408,15 +408,15 @@ whoami export HOME=`mktemp -d` mkdir $HOME/.ssh - cp /opt/hydra_id_rsa $HOME/.ssh/id_rsa - cp /opt/hydra_id_rsa.pub $HOME/.ssh/id_rsa.pub + cp /opt/hydra_id_ed25519 $HOME/.ssh/id_ed25519 + cp /opt/hydra_id_ed25519.pub $HOME/.ssh/id_ed25519.pub echo "rpi-1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPOBQVcsvk6WgRj18v4m0zkFeKrcN9gA+r6sxQxNwFpv" > $HOME/.ssh/known_hosts - chmod 600 $HOME/.ssh/id_rsa + chmod 600 $HOME/.ssh/id_ed25519 LOCKCTL=$(mktemp -d) mkfifo $LOCKCTL/lockctl cat $LOCKCTL/lockctl | ${pkgs.openssh}/bin/ssh \ - -i $HOME/.ssh/id_rsa \ + -i $HOME/.ssh/id_ed25519 \ -o UserKnownHostsFile=$HOME/.ssh/known_hosts \ rpi-1 \ 'mkdir -p /tmp/board_lock && flock /tmp/board_lock/kc705-1 -c "echo Ok; cat"' \ From 4a6bea479af03bca5a3583977bbdebf4c7f6b14e Mon Sep 17 00:00:00 2001 From: Steve Fan <19037626d@connect.polyu.hk> Date: Sat, 4 Dec 2021 13:33:24 +0800 Subject: [PATCH 235/238] Host report for async error upon kernel termination (#1791) Closes #1644 --- RELEASE_NOTES.rst | 4 +++- artiq/coredevice/comm_kernel.py | 12 ++++++++++++ artiq/firmware/libproto_artiq/session_proto.rs | 14 ++++++++++---- artiq/firmware/runtime/rtio_mgt.rs | 9 +++++++++ artiq/firmware/runtime/session.rs | 8 ++++++-- 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index a1c807008..46cd999ab 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -31,6 +31,9 @@ Highlights: * The configuration entry ``rtio_clock`` supports multiple clocking settings, deprecating the usage of compile-time options. * DRTIO: added support for 100MHz clock. +* Previously detected RTIO async errors are reported to the host after each kernel terminates and a + warning is logged. The warning is additional to the one already printed in the core device log upon + detection of the error. Breaking changes: @@ -44,7 +47,6 @@ Breaking changes: * DRTIO: Changed message alignment from 32-bits to 64-bits. * The deprecated ``set_dataset(..., save=...)`` is no longer supported. - ARTIQ-6 ------- diff --git a/artiq/coredevice/comm_kernel.py b/artiq/coredevice/comm_kernel.py index cdb54a118..1b0111c49 100644 --- a/artiq/coredevice/comm_kernel.py +++ b/artiq/coredevice/comm_kernel.py @@ -621,6 +621,7 @@ class CommKernel: function = self._read_string() backtrace = [self._read_int32() for _ in range(self._read_int32())] + self._process_async_error() traceback = list(reversed(symbolizer(backtrace))) + \ [(filename, line, column, *demangler([function]), None)] @@ -635,6 +636,16 @@ class CommKernel: python_exn.artiq_core_exception = core_exn raise python_exn + def _process_async_error(self): + errors = self._read_int8() + if errors > 0: + map_name = lambda y, z: [f"{y}(s)"] if z else [] + errors = map_name("collision", errors & 2 ** 0) + \ + map_name("busy error", errors & 2 ** 1) + \ + map_name("sequence error", errors & 2 ** 2) + logger.warning(f"{(', '.join(errors[:-1]) + ' and ') if len(errors) > 1 else ''}{errors[-1]} " + f"reported during kernel execution") + def serve(self, embedding_map, symbolizer, demangler): while True: self._read_header() @@ -646,4 +657,5 @@ class CommKernel: raise exceptions.ClockFailure else: self._read_expect(Reply.KernelFinished) + self._process_async_error() return diff --git a/artiq/firmware/libproto_artiq/session_proto.rs b/artiq/firmware/libproto_artiq/session_proto.rs index 99412de10..0475a4489 100644 --- a/artiq/firmware/libproto_artiq/session_proto.rs +++ b/artiq/firmware/libproto_artiq/session_proto.rs @@ -90,7 +90,9 @@ pub enum Reply<'a> { LoadCompleted, LoadFailed(&'a str), - KernelFinished, + KernelFinished { + async_errors: u8 + }, KernelStartupFailed, KernelException { name: &'a str, @@ -100,7 +102,8 @@ pub enum Reply<'a> { line: u32, column: u32, function: &'a str, - backtrace: &'a [usize] + backtrace: &'a [usize], + async_errors: u8 }, RpcRequest { async: bool }, @@ -160,14 +163,16 @@ impl<'a> Reply<'a> { writer.write_string(reason)?; }, - Reply::KernelFinished => { + Reply::KernelFinished { async_errors } => { writer.write_u8(7)?; + writer.write_u8(async_errors)?; }, Reply::KernelStartupFailed => { writer.write_u8(8)?; }, Reply::KernelException { - name, message, param, file, line, column, function, backtrace + name, message, param, file, line, column, function, backtrace, + async_errors } => { writer.write_u8(9)?; writer.write_string(name)?; @@ -183,6 +188,7 @@ impl<'a> Reply<'a> { for &addr in backtrace { writer.write_u32(addr as u32)? } + writer.write_u8(async_errors)?; }, Reply::RpcRequest { async } => { diff --git a/artiq/firmware/runtime/rtio_mgt.rs b/artiq/firmware/runtime/rtio_mgt.rs index 825900b78..1a1d1660b 100644 --- a/artiq/firmware/runtime/rtio_mgt.rs +++ b/artiq/firmware/runtime/rtio_mgt.rs @@ -326,6 +326,14 @@ pub mod drtio { pub fn reset(_io: &Io, _aux_mutex: &Mutex) {} } +static mut SEEN_ASYNC_ERRORS: u8 = 0; + +pub unsafe fn get_async_errors() -> u8 { + let mut errors = SEEN_ASYNC_ERRORS; + SEEN_ASYNC_ERRORS = 0; + errors +} + fn async_error_thread(io: Io) { loop { unsafe { @@ -343,6 +351,7 @@ fn async_error_thread(io: Io) { error!("RTIO sequence error involving channel {}", csr::rtio_core::sequence_error_channel_read()); } + SEEN_ASYNC_ERRORS = errors; csr::rtio_core::async_error_write(errors); } } diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index 7d0935667..260a1b385 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -9,6 +9,7 @@ use urc::Urc; use sched::{ThreadHandle, Io, Mutex, TcpListener, TcpStream, Error as SchedError}; use rtio_clocking; use rtio_dma::Manager as DmaManager; +use rtio_mgt::get_async_errors; use cache::Cache; use kern_hwreq; use board_artiq::drtio_routing; @@ -431,7 +432,9 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex, match stream { None => return Ok(true), Some(ref mut stream) => - host_write(stream, host::Reply::KernelFinished).map_err(|e| e.into()) + host_write(stream, host::Reply::KernelFinished { + async_errors: unsafe { get_async_errors() } + }).map_err(|e| e.into()) } } &kern::RunException { @@ -458,7 +461,8 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex, line: line, column: column, function: function, - backtrace: backtrace + backtrace: backtrace, + async_errors: unsafe { get_async_errors() } }).map_err(|e| e.into()) } } From 12512bfb2ff0b0c83a965cb8fe14a4e39b488f44 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 5 Dec 2021 14:31:49 +0800 Subject: [PATCH 236/238] flake: get rid of TARGET_AR --- flake.lock | 8 ++++---- flake.nix | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index bf378e2eb..35c1fb29a 100644 --- a/flake.lock +++ b/flake.lock @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1636527305, - "narHash": "sha256-/2XTejqj0Bo81HaTrlTSWwInnWwsuqnq+CURXbpIrkA=", + "lastModified": 1638683371, + "narHash": "sha256-sm2SxHmEGfE56+V+joDHMjpOaxg8+t3EJEk1d11C1E0=", "ref": "master", - "rev": "f5203e406520874e15ab5d070058ef642fc57fd9", - "revCount": 2417, + "rev": "71b74f87b41c56a6c6d767cdfde0356c15a379a7", + "revCount": 2418, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" diff --git a/flake.nix b/flake.nix index 5fa94518d..f5a29ff4a 100644 --- a/flake.nix +++ b/flake.nix @@ -270,7 +270,6 @@ ln -s $ARTIQ_PATH/firmware/Cargo.lock . cargoSetupPostUnpackHook cargoSetupPostPatchHook - export TARGET_AR=llvm-ar ${buildCommand} ''; doCheck = true; @@ -384,7 +383,6 @@ packages.x86_64-linux.vivado packages.x86_64-linux.openocd-bscanspi ]; - TARGET_AR="llvm-ar"; }; hydraJobs = { From 9e3ea4e8ef8881d4913458533aa2505a8ce1539f Mon Sep 17 00:00:00 2001 From: Leon Riesebos Date: Fri, 18 Jun 2021 17:49:20 +0200 Subject: [PATCH 237/238] coredevice: fixed type annotations for AD9910 --- artiq/coredevice/ad9910.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/coredevice/ad9910.py b/artiq/coredevice/ad9910.py index 49bfe9a90..e93d3202b 100644 --- a/artiq/coredevice/ad9910.py +++ b/artiq/coredevice/ad9910.py @@ -518,7 +518,7 @@ class AD9910: @kernel def set_mu(self, ftw: TInt32, pow_: TInt32 = 0, asf: TInt32 = 0x3fff, phase_mode: TInt32 = _PHASE_MODE_DEFAULT, - ref_time_mu: TInt64 = int64(-1), profile: TInt32 = 0): + ref_time_mu: TInt64 = int64(-1), profile: TInt32 = 0) -> TInt32: """Set profile 0 data in machine units. This uses machine units (FTW, POW, ASF). The frequency tuning word @@ -823,7 +823,7 @@ class AD9910: @kernel def set(self, frequency: TFloat, phase: TFloat = 0.0, amplitude: TFloat = 1.0, phase_mode: TInt32 = _PHASE_MODE_DEFAULT, - ref_time_mu: TInt64 = int64(-1), profile: TInt32 = 0): + ref_time_mu: TInt64 = int64(-1), profile: TInt32 = 0) -> TFloat: """Set profile 0 data in SI units. .. seealso:: :meth:`set_mu` From 7ffe4dc2e3ff9a83cf861be7c4b0ec78e4d4c772 Mon Sep 17 00:00:00 2001 From: Leon Riesebos Date: Thu, 24 Jun 2021 19:40:30 -0400 Subject: [PATCH 238/238] coredevice: set default pow for ad9912 set_mu() --- artiq/coredevice/ad9912.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/coredevice/ad9912.py b/artiq/coredevice/ad9912.py index b214b9496..cb018c103 100644 --- a/artiq/coredevice/ad9912.py +++ b/artiq/coredevice/ad9912.py @@ -156,7 +156,7 @@ class AD9912: return self.cpld.get_channel_att(self.chip_select - 4) @kernel - def set_mu(self, ftw: TInt64, pow_: TInt32): + def set_mu(self, ftw: TInt64, pow_: TInt32 = 0): """Set profile 0 data in machine units. After the SPI transfer, the shared IO update pin is pulsed to