AsciiDoc basics

AsciiDoc is fully documented, and its documentation is actively maintained. This document has information about AsciiDoc markup to get you started.

For details and additional options, see:

In addition, you can ask questions in https://asciidoctor.zulipchat.com/

Best practice is to test the PDF build often to ensure that you have not accidentally introduced something that breaks the build.

Send questions to help@riscv.org.

Paragraphs

In AsciiDoc, normal paragraphs do not require markup.

To create a new paragraph, put a space after the earlier line of text and continue.

Basics of blocks and indents

If you add an indent, your indented text becomes a block like this.
  • You can add indented, explanatory paragraphs to lists.

    Add a + directly preceding the line of text that you want to indent within the list.

  • Another point.

    Using the + to create an indented paragraph works only within the context of a numbered or bulleted list.

AsciiDoc/Asciidoctor supports code blocks with syntax highlighting for many languages. You can use either periods or dashes to indicate code blocks, and use macros to indicate that the block has code in the specified language, as in the following example:

[source,python]
....
mono-spaced code block
add a1,a2,a3; # do an ADD
....

This example renders as follows:

mono-spaced code block
add a1,a2,a3; # do an ADD

See Admonition blocks for additional information about blocks.

Headers

When you author in AsciiDoc, you cannot jump directly from a Head 1 to a Head 3 or 4. Your headers must appear in sequence from Head 1 to Head 2, and onward. If you skip over a header in the sequence, Asciidoctor throws an error.

The following example is a valid sequence of headers.

= Title head (book or report title)

[colophon]
= Colophon head (in frontmatter, used for preface)

[[chapter_title]]
== Head 1 (chapter)

=== Head 2 (section)

==== Head 3 (subsection)

===== Head 4 (sub-subsection)

[appendix]
== Appendix title

[index]
Index
Settings in the header file (modules/ROOT/pages/spec-sample.adoc in the docs-spec-template repository) trigger auto-generation of Appendix prefixes and of the Index (among other things).

Lists

Create unordered lists with the * before the list item. Ordered lists require a . Add a space between any supporting text at the beginning of a list.

Unordered list

To create an unordered list, place a * and a space before an item. Put each new list item on a new line. Add a space between any supporting text at the beginning of a list.

Example:

* Priv
* Unpriv
* Debug

Example output:

  • Priv

  • Unpriv

  • Debug

Ordered list

To create an ordered (numbered) list, place a . and a space before an item. Put each new list item on a new line. Add a space between any supporting text at the beginning of a list.

. Priv
. Unpriv
. Debug

Example output:

  1. Priv

  2. Unpriv

  3. Debug

Nested list

To create a nested unordered list, use `** ` before the nested item.

* Priv
** Intro
*** Definitions
** CSRs
* Unpriv

Example output:

  • Priv

    • Intro

      • Definitions

    • CSRs

  • Unpriv

To create a nested ordered list, use `.. ` before the nested list item.

. first item
.. nested item
.. second nested item
. back to original level.

Example output:

  1. first item

    1. nested item

    2. second nested item

  2. back to original level.

You can also create an unordered list that has a nested ordered list (or an ordered list that has a nested unordered list).

* unordered item
.. numbered item
.. second numbered item
* another bullet

Example output:

  • unordered item

    1. numbered item

    2. second numbered item

  • another bullet

Add a title to a list

Titles can help introduce your list content.

.Ordered list
. Priv
. Unpriv
. Debug

Example output:

Ordered list
  1. Priv

  2. Unpriv

  3. Debug

Asciidoctor automates some linking as follows:

  • Recognizes hyperlinks to Web pages and shortens them for readability.

  • Automatically creates an anchor for every section and discrete heading.

To create highlighted links, use the pattern in the following example:

https://asciidoctor.org[Asciidoctor]

Cross references

Use macros for cross references (links within a document) as in the following example:

<<Index markers>> describes how index markers work.

This example renders as:

[Index markers] describes how index markers work.

For more information about options, see Cross References.

Tables

By using tables, you can group information into logical units, which can make the infromation presented easier to understand.

General rules for tables

Follow these general rules when you create a table.

  • Avoid tables in the middle of lists.

  • Do not use tables to lay out a page. For example, if you have a long list of items, do not use a 2 column table to save space. The information should make sense side by side.

  • Do not create a table that has a single row or a single column, unless you are following an earlier layout. For example, if each section in a chapter includes a table of options, then use a table even if one of the sections has only a single option.

  • Always use table headers and captions to make your tables more accessible.

  • Use introductory sentences for your table. For example, "The following table has the options for the CSR." You can use either a period or a colon for your introductory sentence.

  • Do not refer to the "table above" or the "below table". Use words such as "The following table" or "The preceeding table".

Never use automated wrapping for table titles, figure captions, and example captions. Asciidoctor reads a hard return as an indicator to start a new "Normal" paragraph.

Simple table

The following example shows a simple table with 2 rows and 2 columns. To indicate a new row, put a empty line between them.

[cols="1,1"]
|===
|Cell in column 1, row 1
|Cell in column 2, row 1

|Cell in column 1, row 2
|Cell in column 2, row 2
|===

Results in the following table.

Cell in column 1, row 1

Cell in column 2, row 1

Cell in column 1, row 2

Cell in column 2, row 2

Adding table headers

Headers can add additional information to your table, making them easier to understand.

You can add a header row by adding the first row of cells directly in a line.

[cols="1,1,1"]
|===
|Col 1, header row|Col 2, header row|Col 3, header row

|Cell in col 1, row 2
|Cell in col 2, row 2
|Cell in col 3, row 2
|===

Or you can use the header option.

[%header,cols="1,1,1"]
|===
|Col 1, header row
|Col 2, header row
|Col 3, header row

|Cell in col 1, row 2
|Cell in col 2, row 2
|Cell in col 3, row 2
|===

Either table renders with table headers.

Col 1, header row Col 2, header row Col 3, header row

Cell in col 1, row 2

Cell in col 2, row 2

Cell in col 3, row 2

Table captions

The modules/ROOT/pages/spec-sample.adoc file in the docs-spec-template repository sets the full cross-reference attribute to enable captions to display from targets in the anchors. You can set captions for tables, blocks, and illustrations. If you do not offer a caption, Asciidoctor defaults to the basic cross-reference style.

To set a caption for a table or image, use the pattern as follows:

The following table, <<trapcharacteristics,Characteristics of traps>> shows the characteristics of each kind of trap.
[[trapcharacteristics,Characteristics of traps]]
.Characteristics of traps.
[cols="<,^,^,^,^",options="header",]
|===
| |Contained |Requested |Invisible |Fatal
|Execution terminates |No |Nolatexmath:[$^{1}$] |No |Yes
|Software is oblivious |No |No |Yes |Yeslatexmath:[$^{2}$]
|Handled by environment |No |Yes |Yes |Yes
|===

The following table, Table 1 shows the characteristics of each kind of trap.

Table 1. Characteristics of traps.
Contained Requested Invisible Unrecoverable

Execution terminates

No

No

No

Yes

Software is oblivious

No

No

Yes

Yes

Handled by environment

No

Yes

Yes

Yes

AsciiDoc tables from CSV data.

You can also create AsciiDoc tables directly from CSV data. Set the format block attribute to csv and insert the data inside the block delimiters directly:

[%header,format=csv]
|===
Artist,Track,Genre
Baauer,Harlem Shake,Hip Hop
The Lumineers,Ho Hey,Folk Rock
|===

The prior example renders as follows:

Artist Track Genre

Baauer

Harlem Shake

Hip Hop

The Lumineers

Ho Hey

Folk Rock

There are many formatting options available. While some of the property settings are cryptic, they can be quite useful. There are examples available at https://asciidoc.org/newtables.html. Here is an example showing spans alignment in tables from that page:

[cols="e,m,^,>s",width="25%"]
|============================
|1 >s|2 |3 |4
^|5 2.2+^.^|6 .3+<.>m|7
^|8
|9 2+>|10
|============================

Which renders as follows:

1

2

3

4

5

6

7

8

9

10

The following example is code for a numbered encoding table with link target.

We have added annotations to the code to illustrate their use.
[[proposed-16bit-encodings-1]  (1)
.proposed 16-bit encodings-1    (2)
[width="100%",options=header]
|===
|15 |14 |13 |12 |11 |10 |9 |8 |7 |6 |5 |4 |3 |2 |1 |0 |instruction
3+|100|1|0|0|0 2+|field|0 |0 2+|00 | field 2+|00|mnemonic1
3+|100|1|0|0 3+|field|bit|1 3+|field 2+|00|mnemonic2
3+|110|1|0|0 3+|field|1 |0 3+|field 2+|00|mnemonic3
17+|This row spans the whole table
3+|100|1|1|1 8+|    field        2+| 00  | mnemonic4
|===
  1. Link target.

  2. Numbered table title.

The earlier example results in the following table.

Table 2. proposed 16-bit encodings-1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 instruction

100

1

0

0

0

field

0

0

00

field

00

mnemonic1

100

1

0

0

field

bit

1

field

00

mnemonic2

110

1

0

0

field

1

0

field

00

mnemonic3

This row spans the whole table

100

1

1

1

field

00

mnemonic4

Unicode symbols

For PDFs, five-digit unicode symbols generally do not work and some other unicode symbols are buggy. This failure happens because the Ruby asciidoctor-pdf toolchain makes use of Prawn to build PDFs and it is Prawn that has the problems.

Here are a few unicode examples from https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references that might be useful:

As an example, encode ♦ as follows:

&#9830;
Table 3. Useful unicode for specifications
sym num name

^

94

caret

ˆ

136

8942

vdots

9830

name

"

0034

name

w

0077

w

8756

therefore

9839

sharp

ш

1096

shcy

ϖ

982

piv varpi

ω

969

omega

8472

weierp wp

8721

sum

8734

infin

8747

integral

8800

not equal to

8804

le

8805

ge

8776

numerical approximation

D

68

mathematical D?

8658

rightwards double arrow

X

88

Latin Capital x

χ

967

Greek x

×

215

times

9745

boxed checkmark

r

114

latin small letter r

For many other symbols, use asciidoctor-mathematical. See [Superscripts and other mathematical notations].

Table 4. Unicode identified as not working
sym num name

9084

angzarr not working

8921

ggg not working

8617

hookleftarrow not working

9083

not checkmark not working

Mathematical notations

Asciidoctor-mathematical has some limitations. For inline expressions, the graphical representations are displayed small and center vertically. In some cases where there is a single-character Asciidoctor-mathematical expression, it unintentionally is displayed as a superscript. For this reason, always use viable options such as italics or unicode (see Unicode symbols).

Superscripts and subscripts

To indicate a superscript, enclose the string for the superscript in carets as in the following example:

2^8^

Which renders as:

28

You can indicate text in a superscript as well:

1234^NOTE^

Which renders as:

1234NOTE

For subscripts, use tildes:

C~2~ H~6~

With the following result:

C2 H6

An example:

"`Well the H~2~O formula written on their whiteboard could be part
of a shopping list, but I don't think the local bodega sells
E=mc^2^,`" Lazarus replied.

Renders as:

"Well the H2O formula written on their whiteboard could be part of a shopping list, but I don’t think the local bodega sells E=mc2," Lazarus replied.

Latexmath

You can make use of LaTeX notation as in the following:

latexmath:[$C = \alpha + \beta Y^{\gamma} + \epsilon$]

Which renders as:

Latexmath rendering has some limitations with respect to sizing and placement inline. This happens because of how the images for the mathematical renders symbols within the build process. For this reason, avoid using single character latexmath expressions inline and preferentially make use of unicode or superscripts and subscripts when possible.

Stem content

The :stem: latexmath setting makes use of asciidoctor-mathematical for asciidoctor-pdf output.

Asciidoctor Mathematical is a Ruby gem that uses native extensions. It has a few system prerequisites that limit installation to Linux and macOS. See the README in the RISC-V docs-templates repo for information on the asciidoctor-mathematical install.

[stem]
++++
sqrt(4) = 2
++++

In some cases, you might want to make use of unicode characters. Remember that asciidoctor-pdf supports only decimal character references. See https://github.com/asciidoctor/asciidoctor-pdf/issues/486

For updates to asciidoctor-pdf, see https://github.com/asciidoctor/asciidoctor-pdf.

Admonition blocks

Five types of standard admonition blocks are available in AsciiDoc. RISC-V uses these five types with the default icons.

The admonition type is not displayed, only the icon.
Note

Highlight extra information that should stand out from the rest of the text. A "by the way, you should know this" statement.

example of note type
Caution

Cautions users about a condition or action that can lead to bad outcomes such as personal injury or damage equipment. A "we don’t recommend" statement.

example of caution type
Warning

Warns users about a situation that is undesirable. A "Do not do this!" or "You must do this" statement.

example of warning type
Important

Information that a user must have. For example, "After you set your password, you cannot change it."

example of important type
Tip

Used for Non-normative text such as clarification or hints for implementers or to convey design rationale and why the team discontinued other options. RISC-V tech team is working on a solution that enables users to turn off these admonitions.

example of tip type

As a general rule, follow these guidelines for admonitions:

  • Understand that admonitions are interruptions. They should be relevant to the topic, but not necessary. If the reader skips reading it, they can still succeed.

  • If the information is necessary, make it part of the topic and even add a heading. do not put it in an admonition.

  • Limit admonitions to a maximum of 3 on a page (standard PDF page - longer HTML pages can use more.)

  • Do not include results, steps, or prerequisites in admonitions.

  • Make your admonition clear and concise.

Single paragraph admonition

For a single paragraph admonition, use a double colon:

NOTE: Note content.

that renders as:

Note content.

Admonition blocks

An admonition block can contain any AsciiDoc content.

[IMPORTANT]
====
As a general rule, follow these guidelines for admonitions:

* Understand that admonitions are interruptions. They should be relevant to the topic, but not necessary. If the reader skips reading it, they can still succeed.
* If the information is necessary, make it part of the topic and even add a heading. Don't put it in an admonition.
* Limit admonitions to a maximum of 3 on a page (standard PDF page - longer HTML pages can use more.)
* Do not include results, steps, or prerequisites in admonitions.
* Make your admonition clear and concise.
====

that renders as:

As a general rule, follow these guidelines for admonitions:

  • Understand that admonitions are interruptions. They should be relevant to the topic, but not necessary. If the reader skips reading it, they can still succeed.

  • If the information is necessary, make it part of the topic and even add a heading. do not put it in an admonition.

  • Limit admonitions to a maximum of 3 on a page (standard PDF page - longer HTML pages can use more.)

  • Do not include results, steps, or prerequisites in admonitions.

  • Make your admonition clear and concise.

Admonition with a title

You can add a title to your admonition block.

[WARNING]
.Security vulnerability
====
*Be aware that RLB introduces a security vulnerability if you set iiiiiit after the boot process is over.* Use with caution, even when you use it temporarily. Editable PMP rules in M-mode gives a false sense of security since it only takes a few malicious instructions to lift any PMP restrictions this way. It doesn't make sense to have a security control in place and leave it unprotected. Rule Locking Bypass is only meant as a way to optimize the allocation of PMP rules, catch errors durring debugging, and allow the bootrom/firmware to register executable _Shared-Region_ rules. If developers / vendors have no use for such functionality, they should never set ``mseccfg.RLB`` and if possible hard-wire it to 0. In any case *RLB should be disabled and locked as soon as possible*.
====

Rendered:

Security vulnerability

Be aware that RLB introduces a security vulnerability if you set it after the boot process is over. Use with caution, even when you use it temporarily. Editable PMP rules in M-mode gives a false sense of security since it only takes a few malicious instructions to lift any PMP restrictions this way. It does not make sense to have a security control in place and leave it unprotected. Rule Locking Bypass is only meant as a way to optimize the allocation of PMP rules, catch errors durring debugging, and allow the bootrom/firmware to register executable Shared-Region rules. If developers / vendors have no use for such functionality, they should never set mseccfg.RLB and if possible hard-wire it to 0. In any case RLB should be disabled and locked as soon as possible.

RISC-V admonition icon colors

The admonition icons are set in risc-v_spec-pdf.yml. RISC-V uses custom colors, as indicated in the Table 5.

note
tip
warning
caution
important
Table 5. Customized colors for icons
Icon default customized

NOTE

19407c

6489b3

TIP

111111

5g27ag

WARNING

bf6900

9c4d4b

CAUTION

bf3400

c99a2c

IMPORTANT

bf0000

b58f5b

Code blocks

AsciiDoc enables code blocks that support syntax highlighting.

For example, preceding a block with a macro [source,json] enables json syntax highlighting:

{
    "weather": {
        "city":       "Zurich",
        "temperature":      25,
    }
}

While syntax highlighters for machine code that integrate with the Asciidoctor Ruby toolchain do leave something to be desired, the Rouge highlighter enables line numbers within the code examples.

We are numbering examples as in the following:

.A spinlock with fences
[source%linenums,asm]
....
          sd           x1, (a1)     # Arbitrary unrelated store
          ld           x2, (a2)     # Arbitrary unrelated load
          li           t0, 1        # Initialize swap value.
      again:
          amoswap.w    t0, t0, (a0) # Attempt to acquire lock.
          fence        r, rw        # Enforce "acquire" memory ordering
          bnez         t0, again    # Retry if held.
          # ...
          # Critical section.
          # ...
          fence        rw, w        # Enforce "release" memory ordering
          amoswap.w    x0, x0, (a0) # Release lock by storing 0.
          sd           x3, (a3)     # Arbitrary unrelated store
          ld           x4, (a4)     # Arbitrary unrelated load
....

With the following result:

A spinlock with fences
          sd           x1, (a1)     # Arbitrary unrelated store
          ld           x2, (a2)     # Arbitrary unrelated load
          li           t0, 1        # Initialize swap value.
      again:
          amoswap.w    t0, t0, (a0) # Attempt to acquire lock.
          fence        r, rw        # Enforce "acquire" memory ordering
          bnez         t0, again    # Retry if held.
          # ...
          # Critical section.
          # ...
          fence        rw, w        # Enforce "release" memory ordering
          amoswap.w    x0, x0, (a0) # Release lock by storing 0.
          sd           x3, (a3)     # Arbitrary unrelated store
          ld           x4, (a4)     # Arbitrary unrelated load

Change bars

Change indicators within text files are exceedingly useful and also can be equally complex to implement. Please consider the fact that much of the software programming for Git revolves around handling various kinds of change indicators.

In exploring possible implementation of change bars for RISC-V, we have looked for a solution that is as simple as possible while maximizing value with respect to the time invested in implementing, maintaining, and using the tools and procedures.

The suggested solution makes use of:

  • an AsciiDoc role.

  • modification of two files in the Ruby gem with code snippets (see procedure in the README for https://github.com/riscv/docs-templates).

  • Git features.

  • a few procedures associated, specifically, with Git updates.

Indicate changes

Indicators for the changed lines must be inserted manually:

[.Changed]#SELECT clause#

Text without the change bar

[.Changed]#Text with the change bar#

SELECT clause

Text without the change bar

Text with the change bar

For change bars associated with headings, place the change indicator after the heading indicator and before the text, like the following:

== [.Changed]#SELECT clause#

Check for changed lines before a git commit

You can double check for all changed lines before committing by using this pattern:

git blame <file> | grep -n '^0\{8\} ' | cut -f1 -d:

This lists the line numbers of changes within the specified file like the following example:

5
38
109
237

Footnotes

AsciiDoc has a limitation in that footnotes appear at the end of each chapter. Asciidoctor does not support footnotes appearing at the bottom of each page.

You can add footnotes to your presentation using the footnote macro. If you plan to reference a footnote more than once, use the footnote macro with a target that you identify in the brackets.

Initiate the hail-and-rainbow protocol at one of three levels:

- doublefootnote:[The double hail-and-rainbow level makes my toes tingle.]
- tertiary
- apocalyptic

A bold statement!footnote:disclaimer[Opinions are my own.]

Another outrageous statement.footnote:disclaimer[]

Renders as:

The hail-and-rainbow protocol can be initiated at three levels:

  • double[1]

  • tertiary

  • apocalyptic

A bold statement![2]

Another outrageous statement.[2]

Sidebars provide for a form of commentary.

****
This is content in a sidebar block.

image:example-3.svg[]

This is more content in the sidebar block.
****

This renders as follows:

This is content in a sidebar block.

example 3

This is more content in the sidebar block.

You can add a title, along with any kind of content. Best practice for many of the "commentaries" in the LaTeX source that elucidate the decision-making process is to convert to this format with the TIP icon that illustrates a conversation or discussion, as in the following example:

.Optional Title
****
Sidebars are used to visually separate auxiliary bits of content
that supplement the main text.

TIP: They can contain any type of content, including admonitions like this, and code examples like the following.

.Source code block within a sidebar
[source,js]
/----   (1)
const { expect, expectCalledWith, heredoc } = require('../test/test-utils')
/----  (2)
****

1 and 2. Escapes are necessary to preserve this as an AsciiDoc code example.

Once the escapes are removed, the above renders with both the admonition and code blocks within the sidebar:

Optional Title

Sidebars are used to visually separate auxiliary bits of content that supplement the main text.

They can contain any type of content, including admonitions like this, and code examples like the following.
Source code block in a sidebar
const { expect, expectCalledWith, heredoc } = require('../test/test-utils')

1. The double hail-and-rainbow level makes my toes tingle.
2. Opinions are my own.