[doc] Completely replace docgen with hugo
This change completely replaces docgen and replaces or removes
docgen-specific markdown in documentation. It also does the following:
* Updates all local links to use hugo relative references so that a
broken link is a broken build.
* Uses upstream wavedrom, which breaks at least one page that depends
on local modifications.
* Renames most hw/ip/**/ip_name.doc and dv_plan documents for a more
aesthetic document tree layout.
* Moves some doc/ pages into their own page bundle.
* Updates util/build_docs.py to pre-generate registers, hwcfg, and
dashboard fragments and invoke hugo.
diff --git a/hw/ip/rv_plic/doc/index.md b/hw/ip/rv_plic/doc/index.md
new file mode 100644
index 0000000..4e0e6fa
--- /dev/null
+++ b/hw/ip/rv_plic/doc/index.md
@@ -0,0 +1,255 @@
+---
+title: "Interrupt Controller Technical Specification"
+---
+
+# Overview
+
+This document specifies the Interrupt Controller (RV_PLIC) functionality. This
+module conforms to the
+[Comportable guideline for peripheral functionality.]({{< relref "doc/rm/comportability_specification" >}})
+See that document for integration overview within the broader top level system.
+
+
+## Features
+
+- RISC-V Platform-Level Interrupt Controller (PLIC) compliant interrupt controller
+- Support arbitrary number of interrupt vectors (up to 256) and targets
+- Support interrupt enable, interrupt status registers
+- Memory-mapped MSIP register per HART for software interrupt control.
+
+## Description
+
+The RV_PLIC module is designed to manage various interrupt sources from the
+peripherals. It receives interrupt events as either edge or level of the
+incoming interrupt signals (``intr_src_i``) and can notify multiple targets.
+
+## Compatibility
+
+The RV_PLIC is compatible with any RISC-V core implementing the RISC-V privilege specification.
+
+# Theory of Operations
+
+## Block Diagram
+
+
+
+## Details
+
+### Identifier
+
+Each interrupt source has a unique ID assigned based upon its bit position
+within the input `intr_src_i`. ID ranges from 0 to N, the number of interrupt
+sources. ID 0 is reserved and represents no interrupt. The `intr_src_i[i]` bit
+has an ID of `i+1`. This ID is used when targets "claim" the interrupt and to
+"complete" the interrupt event.
+
+### Priority and Threshold
+
+Interrupt sources have configurable priority values. The maximum value of the
+priority is configurable through the localparam `MAX_PRIO` in the rv_plic
+top-level module. For each target there is a threshold value ({{< regref "THRESHOLD0" >}} for
+target 0). RV_PLIC notifies a target of an interrupt only if it's priority is
+strictly greater than the target's threshold. Note this means an interrupt with
+a priority is 0 is effectively prevented from causing an interrupt at any target
+and a target can suppress all interrupts by setting it's threshold to the max
+priority value.
+
+`MAX_PRIO` parameter is most area contributing option in RV_PLIC. If `MAX_PRIO`
+is big, then finding the highest priority in Process module consumes a lot of
+logic gates.
+
+### Interrupt Gateways
+
+The Gateway observes incoming interrupt sources and converts them to a common
+interrupt format used internally by RV_PLIC. It can be configured to detect
+interrupts events on an edge (when the signal changes from **0** to **1**) or
+level basis (where the signal remains at **1**).
+
+When the gateway detects an interrupt event it raises the interrupt pending bit
+({{< regref "IP" >}}) for that interrupt source. When an interrupt is claimed by a target the
+relevant bit of {{< regref "IP" >}} is cleared. A bit in {{< regref "IP" >}} will be not reasserted until the
+target signals completion of the interrupt. Any new interrupt event between a
+bit in {{< regref "IP" >}} asserting and completing that interrupt is ignored. In particular
+this means that for edge triggered interrupts if a new edge is seen after the
+source's {{< regref "IP" >}} bit is asserted and before completion that edge will be ignored
+(counting missed edges as discussed in the RISC-V PLIC specification is not
+supported).
+
+Note that there is no ability for a level triggered interrupt to be cancelled.
+If the interrupt drops after the gateway has set a bit in {{< regref "IP" >}}, the bit will
+remain set until the interrupt is completed. The SW handler should be conscious
+of this and check the interrupt still requires handling in the handler if this
+behaviour is possible.
+
+### Interrupt Enables
+
+Each target has a set of Interrupt Enable ({{< regref "IE0" >}} for target 0) registers. Each
+bit in the {{< regref "IE0" >}} registers controls the corresponding interrupt source. If an
+interrupt source is disabled for a target, then interrupt events from that
+source won't trigger an interrupt at the target. RV_PLIC doesn't have a global
+interrupt disable feature.
+
+### Interrupt Claims
+
+"Claiming" an interrupt is done by a target reading the associated
+Claim/Completion register for the target ({{< regref "CC0" >}} for target 0). The return value
+of the {{< regref "CC0" >}} read represents the ID of the pending interrupt that has the
+highest priority. If two or more pending interrupts have the same priority,
+RV_PLIC chooses the one with lowest ID. Only interrupts that that are enabled
+for the target can be claimed. The target priority threshold doesn't matter
+(this only factors into whether an interrupt is signalled to the target) so
+lower priority interrupt IDs can be returned on a read from {{< regref "CC0" >}}. If no
+interrupt is pending (or all pending interrupts are disabled for the target) a
+read of {{< regref "CC0" >}} returns an ID of 0.
+
+### Interrupt Completion
+
+After an interrupt is claimed, the relevant bit of interrupt pending ({{< regref "IP" >}}) is
+cleared, regardless of the status of the `intr_src_i` input value. Until a
+target "completes" the interrupt, it won't be re-asserted if a new event for the
+interrupt occurs. A target completes the interrupt by writing the ID of the
+interrupt to the Claim/Complete register ({{< regref "CC0" >}} for target 0). The write event
+is forwarded to the Gateway logic, which resets the interrupt status to accept a
+new interrupt event. The assumption is that the processor has cleaned up the
+originating interrupt event during the time between claim and complete such that
+`intr_src_i[ID-1]` will have de-asserted (unless a new interrupt has occurred).
+
+~~~~wavejson
+{ signal: [
+ { name: 'clk', wave: 'p...........' },
+ { name: 'intr_src_i[i]', wave: '01....0.1...', node:'.a....e.f...'},
+ { name: 'irq_o', wave: '0.1.0......1', node:'..b.d......h'},
+ { name: 'irq_id_o', wave: '=.=.=......=',
+ data: ["0","i+1","0","i+1"] },
+ { name: 'claim', wave: '0..10.......', node:'...c........'},
+ { name: 'complete', wave: '0.........10', node:'..........g.'},
+ ],
+ head:{
+ text: 'Interrupt Flow',
+ tick: 0,
+ },
+}
+~~~~
+
+In the example above an interrupt for source ID `i+1` is configured as a level
+interrupt and is raised at a, this results in the target being notified of the
+interrupt at b. The target claims the interrupt at c (reading `i+1` from it's
+Claim/Complete register) so `irq_o` deasserts though `intr_src_i[i]` remains
+raised. The SW handles the interrupt and it drops at e. However a new interrupt
+quickly occurs at f. As complete hasn't been signaled yet `irq_o` isn't
+asserted. At g the interrupt is completed (by writing `i+1` to it's
+Claim/Complete register) so at h `irq_o` is asserted due to the new interrupt.
+
+## Hardware Interfaces
+
+{{< hwcfg "hw/ip/rv_plic/data/rv_plic.hjson" >}}
+
+# Programmers Guide
+
+## Initialization
+
+After reset, RV_PLIC doesn't generate any interrupts to any targets even if
+interrupt sources are set, as all priorities and thresholds are 0 by default and
+all ``IE`` values are 0. Software should configure the above three registers and the
+interrupt source type {{< regref "LE" >}} .
+
+{{< regref "LE" >}} and {{< regref "PRIO0" >}} .. {{< regref "PRIO31" >}} registers are unique. So, only one of the targets
+shall configure them.
+
+```c
+// Pseudo-code below
+void plic_init() {
+ // Set to level-triggered for interrupt sources
+ for (int i = 0 ; i < ceil(N_SOURCE/32) ; i++) {
+ *(LE+i) = 0;
+
+ // Configure priority
+ for (int i = 0 ; i < N_SOURCE ; i++) {
+ *(PRIO+i) = value(i);
+
+}
+
+void plic_threshold(tid, threshold) {
+ *(THRESHOLD+tid) = threshold;
+}
+
+void plic_enable(tid, iid) {
+ // iid: 0-based ID
+ int offset = ceil(N_SOURCE/32) * tid + (iid>>5);
+
+ *(IE+offset) = *(IE+offset) | (1<<(iid%32));
+}
+```
+
+## Handling Interrupt Request Events
+
+If software receives an interrupt request, it is recommended to follow the steps
+shown below (assuming target 0 which uses {{< regref "CC0" >}} for claim/complete).
+
+1. Claim the interrupts right after entering to the interrupt service routine
+ by reading the {{< regref "CC0" >}} register.
+2. Determine which interrupt should be serviced based on the values read from
+ the {{< regref "CC0" >}} register.
+3. Execute ISR, clearing the originating peripheral interrupt.
+4. Write Interrupt ID to {{< regref "CC0" >}}
+5. Repeat as necessary for other pending interrupts.
+
+It is possible to have multiple interrupt events claimed. If software claims one
+interrupt request, then the process module advertises any pending interrupts
+with lower priority unless new higher priority interrupt events occur. If a
+higher interrupt event occurs after previous interrupt is claimed, the RV_PLIC
+IP advertises the higher priority interrupt. Software may utilize an event
+manager inside a loop so that interrupt claiming and completion can be
+separated.
+
+~~~~c
+void interrupt_service() {
+ // tid is predefined value.
+ uint32 iid;
+ iid = *(CC + tid);
+ if (iid == 0) {
+ // Interrupt is claimed by one of other targets
+ return ;
+
+ do {
+ // Process interrupts
+ // ...
+
+ // Complete
+ *(CC + tid) = iid;
+ iid = *(CC + tid);
+ } while (iid != 0);
+}
+~~~~
+
+## Registers
+
+The register description can be generated with `reg_rv_plic.py` script. The reason
+another script for register generation is that RV_PLIC is configurable to the
+number of input sources and output targets. To implement it, some of the
+registers (see below **IE**) should be double nested in register description
+file. As of Jan. 2019, `regtool.py` supports only one nested multiple register
+format `multireg`.
+
+The below register description doesn't match with Top Earlgrey RV_PLIC design. The
+RV_PLIC in the top_earlgrey is generated by topgen tool so that the number of
+interrupt sources is different.
+
+- LE: CEILING(N_SOURCE / DW)
+ Value 1 indicates the interrupt source's behavior is edge-triggered It is
+ used in the gateways module.
+- IE: CEILING(N_SOURCE / DW) X N_TARGET
+ Each bit enables corresponding interrupt source. Each target has IE set.
+- PRIO: N_SOURCE
+ Universal set across all targets. Lower n bits are valid. n is determined by
+ MAX_PRIO parameter
+- THRESHOLD: N_TARGET
+ Priority threshold per target. Only priority of the interrupt greater than
+ threshold can raise interrupt notification to the target.
+- IP: CEILING(N_SOURCE / DW)
+ Pending bits right after the gateways. Read-only
+- CC: N_TARGET
+ Claim by read, complete by write
+
+{{< registers "hw/ip/rv_plic/data/rv_plic.hjson" >}}
+