Skip to content

Commit 948724d

Browse files
committed
doc/embedding: crack into pages
Signed-off-by: Joshua Wise <joshua@accelerated.tech>
1 parent a913631 commit 948724d

7 files changed

Lines changed: 150 additions & 144 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
Adding an applet to an Assembly
2+
-------------------------------
3+
4+
The most common straightforward of an Assembly is to add `existing Glasgow
5+
applets <../applets>`_ to it. (Indeed, internally, the "new-style" Glasgow
6+
``AppletV2`` subsystem is based on Assemblies.) Many Glasgow applets were
7+
designed to be used with :ref:`the REPL <repl-script>`, and expose a
8+
programmatic interface to be used interactively; you can also use these from
9+
your own programs. In this section, we will instantiate a pair of UARTs,
10+
with the interface as described in :ref:`the UART REPL example <repl-uart>`.
11+
12+
.. note::
13+
14+
Not all Glasgow applets have been ported to the "new-style" API yet.
15+
(Applets that haven't instead derive from ``GlasgowApplet``.) If
16+
you find one that hasn't yet been ported, the Glasgow project will
17+
gladly accept your help!
18+
19+
Most "new-style" applets include an ``Interface`` module that encapsulates
20+
their digital logic, and host-side logic to act on it. The UART is no
21+
exception; it is implemented as
22+
``glasgow.applet.interface.uart.UARTInterface``. In this example, we
23+
instantiate two ``UARTInterface``\s, and use them to talk to each other
24+
through Glasgow's external I/O pins. Most of the example is relatively
25+
self-explanatory, but it is worth considering:
26+
27+
* Instantiating the ``Interface`` -- and, indeed, any module that adds logic
28+
into the Assembly -- must be done before the Assembly is started. In our
29+
examples, as described above, the Assembly is started implicitly by the
30+
``async with`` block, so we attach the ``UARTInterface`` to the Assembly
31+
before we enter that block.
32+
* Conversely, interacting with the ``Interface`` can happen only after
33+
synthesis is complete and the gateware is running to Glasgow. Many
34+
applets will implement configuration settings (in this example, setting
35+
the baud rate on the UART peripheral) as dynamic register writes; these
36+
qualify as interactions, for our purposes! So we ``set_baud`` on each of
37+
the ``UARTInterface``\s inside of the ``async with`` block, after the
38+
Assembly has been started.
39+
* In this example, we want to run the transmit and receive tasks in parallel
40+
(the Glasgow system has enough buffer for this trivial case, even if we do
41+
not, but it is educational to demonstrate how to do it!). Many
42+
applications will want to operate in a "straight line" -- there is no
43+
inherent requirement that ``uart_b.read(...)`` must be wrapped in an
44+
``asyncio.create_task``, and indeed, you could just as well do something
45+
like ``result = await uart_b.read(...)`` to immediately block on an
46+
interaction with an ``Interface``. (This is also demonstrated in the
47+
``.set_baud`` calls.)
48+
49+
`Below, we give a program <../_static/examples/assembly-applets.py>`_ that
50+
instantiates two unidirectional UARTs, sets them each to 115200 baud, and
51+
transmits some bytes from one to the other. In order to run this program,
52+
remember to connect a flying lead from pin A0 to pin B0!
53+
54+
.. literalinclude:: ../_static/examples/assembly-applets.py
55+
:language: python
56+
57+
Glasgow should respond:
58+
59+
.. code:: console
60+
61+
DEBUG:asyncio:Using selector: EpollSelector
62+
DEBUG:glasgow.hardware.device:found revC3 device with serial C3-20240518T200308Z
63+
DEBUG:glasgow.hardware.assembly:setting port A voltage to 3.30 V
64+
DEBUG:glasgow.hardware.assembly:setting port B voltage to 3.30 V
65+
DEBUG:glasgow.hardware.assembly:assigning pin tx[0] to A0
66+
DEBUG:glasgow.hardware.assembly:assigning pin rx[0] to B0
67+
DEBUG:glasgow.hardware.assembly:pulling pin B0 high
68+
DEBUG:glasgow.hardware.toolchain:using toolchain 'builtin' (yosys 0.61.0.0.post1073, nextpnr-ice40 0.9.0.0.post686, icepack 0.9.0.0.post686)
69+
INFO:glasgow.hardware.device:device already has bitstream ID 083ca04cc3edb43de9ba63d35bec38fc
70+
INFO:glasgow.hardware.assembly:port A voltage set to 3.3 V
71+
INFO:glasgow.hardware.assembly:port B voltage set to 3.3 V
72+
INFO:root:assembly has started
73+
INFO:root:uart_a transmitted data, waiting for received data
74+
INFO:root:uart_b received data b'Hello, Glasgow!'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Putting your own logic into an Assembly
2+
---------------------------------------
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
Getting started with Assemblies
2+
-------------------------------
3+
4+
The core concept of the Glasgow embeddable API is the Assembly, accessible
5+
through the ``glasgow.hardware.assembly.HardwareAssembly`` class
6+
[#other_assemblies]_. An Assembly represents a configuration of gateware
7+
for a specific Glasgow, including all gateware necessary to interface with
8+
the host software, and including all pipes and registers that the gateware
9+
has access to.
10+
11+
Because each Assembly object is associated with a specific Glasgow, in order
12+
to begin working with an Assembly, you will need to instantiate it with
13+
reference to an attached device; you can use
14+
``HardwareAssembly.find_device()`` to locate a device, and build an Assembly
15+
based on it. An Assembly has ``.start()`` and ``.stop()`` methods to
16+
synthesize it and download it to the device, but for convenience, it also
17+
implements the async context manager protocol to connect to the device.
18+
`The following skeleton of a program
19+
<../_static/examples/assembly-skeleton.py>`_ will search for a Glasgow,
20+
create an empty Assembly targetted to it, and then download it to the
21+
attached Glasgow:
22+
23+
.. literalinclude:: ../_static/examples/assembly-skeleton.py
24+
:language: python
25+
26+
.. note::
27+
28+
Most users that have `followed the recommended installation instructions
29+
<initial-setup>`__ will have Glasgow already installed via ``pipx``.
30+
Usually, this is an important part of making Glasgow easy-to-install --
31+
but ``pipx`` is designed for standalone packages that are not meant to
32+
be imported! Installing Glasgow outside of ``pipx`` in your own
33+
environment is outside of the scope of this document, but to run these
34+
samples, you might consider running inside of the Glasgow venv that
35+
``pipx`` already set up for you. For many users, doing so will take the
36+
form:
37+
38+
.. code:: console
39+
40+
$ ~/.local/pipx/venvs/glasgow/bin/python3 assembly-skeleton.py
41+
42+
Glasgow should respond:
43+
44+
.. code:: console
45+
46+
DEBUG:asyncio:Using selector: EpollSelector
47+
DEBUG:glasgow.hardware.device:found revC3 device with serial C3-20240518T200308Z
48+
DEBUG:glasgow.hardware.toolchain:using toolchain 'builtin' (yosys 0.61.0.0.post1073, nextpnr-ice40 0.9.0.0.post686, icepack 0.9.0.0.post686)
49+
INFO:glasgow.hardware.device:generating bitstream ID ae08e17ee60fe32bc1165e0c59410d57
50+
DEBUG:glasgow.hardware.build_plan:bitstream ID ae08e17ee60fe32bc1165e0c59410d57 is not cached, executing build
51+
INFO:root:Glasgow is alive!
52+
53+
.. [#other_assemblies]
54+
55+
There are other Assemblies in Glasgow; for instance, if you
56+
wish to develop gateware without hardware on your desk at all, you might
57+
consider a ``SimulationAssembly``. All Assemblies derive from the
58+
``AbstractAssembly`` base class, which is the type that you will most
59+
commonly find passed around in Glasgow's internals. These types of
60+
Assemblies are out of scope for this document!

docs/manual/src/embedding/index.rst

Lines changed: 8 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -27,150 +27,14 @@ framework.
2727
Glasgow's embeddable APIs, they may change underneath you in future
2828
versions of Glasgow!
2929

30-
Getting started with Assemblies
31-
-------------------------------
30+
This section documents Glasgow's embeddable APIs in a tutorial fashion.
3231

33-
The core concept of the Glasgow embeddable API is the Assembly, accessible
34-
through the ``glasgow.hardware.assembly.HardwareAssembly`` class
35-
[#other_assemblies]_. An Assembly represents a configuration of gateware
36-
for a specific Glasgow, including all gateware necessary to interface with
37-
the host software, and including all pipes and registers that the gateware
38-
has access to.
32+
.. toctree::
3933

40-
Because each Assembly object is associated with a specific Glasgow, in order
41-
to begin working with an Assembly, you will need to instantiate it with
42-
reference to an attached device; you can use
43-
``HardwareAssembly.find_device()`` to locate a device, and build an Assembly
44-
based on it. An Assembly has ``.start()`` and ``.stop()`` methods to
45-
synthesize it and download it to the device, but for convenience, it also
46-
implements the async context manager protocol to connect to the device.
47-
`The following skeleton of a program
48-
<../_static/examples/assembly-skeleton.py>`_ will search for a Glasgow,
49-
create an empty Assembly targetted to it, and then download it to the
50-
attached Glasgow:
34+
getting-started-with-assemblies
35+
adding-an-applet
36+
adding-your-own-logic
37+
using-registers
38+
using-pins
39+
using-pipes
5140

52-
.. literalinclude:: ../_static/examples/assembly-skeleton.py
53-
:language: python
54-
55-
.. note::
56-
57-
Most users that have `followed the recommended installation instructions
58-
<initial-setup>`__ will have Glasgow already installed via ``pipx``.
59-
Usually, this is an important part of making Glasgow easy-to-install --
60-
but ``pipx`` is designed for standalone packages that are not meant to
61-
be imported! Installing Glasgow outside of ``pipx`` in your own
62-
environment is outside of the scope of this document, but to run these
63-
samples, you might consider running inside of the Glasgow venv that
64-
``pipx`` already set up for you. For many users, doing so will take the
65-
form:
66-
67-
.. code:: console
68-
69-
$ ~/.local/pipx/venvs/glasgow/bin/python3 assembly-skeleton.py
70-
71-
Glasgow should respond:
72-
73-
.. code:: console
74-
75-
DEBUG:asyncio:Using selector: EpollSelector
76-
DEBUG:glasgow.hardware.device:found revC3 device with serial C3-20240518T200308Z
77-
DEBUG:glasgow.hardware.toolchain:using toolchain 'builtin' (yosys 0.61.0.0.post1073, nextpnr-ice40 0.9.0.0.post686, icepack 0.9.0.0.post686)
78-
INFO:glasgow.hardware.device:generating bitstream ID ae08e17ee60fe32bc1165e0c59410d57
79-
DEBUG:glasgow.hardware.build_plan:bitstream ID ae08e17ee60fe32bc1165e0c59410d57 is not cached, executing build
80-
INFO:root:Glasgow is alive!
81-
82-
Adding an applet to an Assembly
83-
-------------------------------
84-
85-
The most common straightforward of an Assembly is to add `existing Glasgow
86-
applets <../applets>`_ to it. (Indeed, internally, the "new-style" Glasgow
87-
``AppletV2`` subsystem is based on Assemblies.) Many Glasgow applets were
88-
designed to be used with :ref:`the REPL <repl-script>`, and expose a
89-
programmatic interface to be used interactively; you can also use these from
90-
your own programs. In this section, we will instantiate a pair of UARTs,
91-
with the interface as described in :ref:`the UART REPL example <repl-uart>`.
92-
93-
.. note::
94-
95-
Not all Glasgow applets have been ported to the "new-style" API yet.
96-
(Applets that haven't instead derive from ``GlasgowApplet``.) If
97-
you find one that hasn't yet been ported, the Glasgow project will
98-
gladly accept your help!
99-
100-
Most "new-style" applets include an ``Interface`` module that encapsulates
101-
their digital logic, and host-side logic to act on it. The UART is no
102-
exception; it is implemented as
103-
``glasgow.applet.interface.uart.UARTInterface``. In this example, we
104-
instantiate two ``UARTInterface``\s, and use them to talk to each other
105-
through Glasgow's external I/O pins. Most of the example is relatively
106-
self-explanatory, but it is worth considering:
107-
108-
* Instantiating the ``Interface`` -- and, indeed, any module that adds logic
109-
into the Assembly -- must be done before the Assembly is started. In our
110-
examples, as described above, the Assembly is started implicitly by the
111-
``async with`` block, so we attach the ``UARTInterface`` to the Assembly
112-
before we enter that block.
113-
* Conversely, interacting with the ``Interface`` can happen only after
114-
synthesis is complete and the gateware is running to Glasgow. Many
115-
applets will implement configuration settings (in this example, setting
116-
the baud rate on the UART peripheral) as dynamic register writes; these
117-
qualify as interactions, for our purposes! So we ``set_baud`` on each of
118-
the ``UARTInterface``\s inside of the ``async with`` block, after the
119-
Assembly has been started.
120-
* In this example, we want to run the transmit and receive tasks in parallel
121-
(the Glasgow system has enough buffer for this trivial case, even if we do
122-
not, but it is educational to demonstrate how to do it!). Many
123-
applications will want to operate in a "straight line" -- there is no
124-
inherent requirement that ``uart_b.read(...)`` must be wrapped in an
125-
``asyncio.create_task``, and indeed, you could just as well do something
126-
like ``result = await uart_b.read(...)`` to immediately block on an
127-
interaction with an ``Interface``. (This is also demonstrated in the
128-
``.set_baud`` calls.)
129-
130-
`Below, we give a program <../_static/examples/assembly-applets.py>`_ that
131-
instantiates two unidirectional UARTs, sets them each to 115200 baud, and
132-
transmits some bytes from one to the other. In order to run this program,
133-
remember to connect a flying lead from pin A0 to pin B0!
134-
135-
.. literalinclude:: ../_static/examples/assembly-applets.py
136-
:language: python
137-
138-
Glasgow should respond:
139-
140-
.. code:: console
141-
142-
DEBUG:asyncio:Using selector: EpollSelector
143-
DEBUG:glasgow.hardware.device:found revC3 device with serial C3-20240518T200308Z
144-
DEBUG:glasgow.hardware.assembly:setting port A voltage to 3.30 V
145-
DEBUG:glasgow.hardware.assembly:setting port B voltage to 3.30 V
146-
DEBUG:glasgow.hardware.assembly:assigning pin tx[0] to A0
147-
DEBUG:glasgow.hardware.assembly:assigning pin rx[0] to B0
148-
DEBUG:glasgow.hardware.assembly:pulling pin B0 high
149-
DEBUG:glasgow.hardware.toolchain:using toolchain 'builtin' (yosys 0.61.0.0.post1073, nextpnr-ice40 0.9.0.0.post686, icepack 0.9.0.0.post686)
150-
INFO:glasgow.hardware.device:device already has bitstream ID 083ca04cc3edb43de9ba63d35bec38fc
151-
INFO:glasgow.hardware.assembly:port A voltage set to 3.3 V
152-
INFO:glasgow.hardware.assembly:port B voltage set to 3.3 V
153-
INFO:root:assembly has started
154-
INFO:root:uart_a transmitted data, waiting for received data
155-
INFO:root:uart_b received data b'Hello, Glasgow!'
156-
157-
Putting your own logic into an Assembly
158-
---------------------------------------
159-
160-
Using registers to connect to logic
161-
-----------------------------------
162-
163-
Connecting to pins
164-
------------------
165-
166-
Using pipes to transfer data
167-
----------------------------
168-
169-
.. [#other_assemblies]
170-
171-
There are other Assemblies in Glasgow; for instance, if you
172-
wish to develop gateware without hardware on your desk at all, you might
173-
consider a ``SimulationAssembly``. All Assemblies derive from the
174-
``AbstractAssembly`` base class, which is the type that you will most
175-
commonly find passed around in Glasgow's internals. These types of
176-
Assemblies are out of scope for this document!
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Connecting to pins
2+
------------------
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Using pipes to transfer data
2+
----------------------------
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Using registers to connect to logic
2+
-----------------------------------

0 commit comments

Comments
 (0)