Skip to content

Commit 18ddcba

Browse files
authored
[patch] Define Circuit Subcomponents (#150)
* Add section on circuit subcomponents. * Remove sections on sub-{index,access,field}.
1 parent 0c88431 commit 18ddcba

File tree

1 file changed

+112
-196
lines changed

1 file changed

+112
-196
lines changed

spec.md

Lines changed: 112 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,9 @@ Circuit components can be connected together (see [@sec:connections]).
400400
Each circuit component in a module has a type ([@sec:types]).
401401
It is used to determine the legality of connections.
402402

403-
## Nodes
403+
## Kinds
404+
405+
### Nodes
404406

405407
Nodes are named expressions in FIRRTL.
406408

@@ -412,7 +414,7 @@ node mynode = and(in, UInt<4>(1))
412414

413415
The type of a node is the type of the expression given in the definition.
414416

415-
## Wires
417+
### Wires
416418

417419
Wires represent named expressions whose value is determined by FIRRTL `connect`{.firrtl} statements (see [@sec:connections]).
418420

@@ -426,7 +428,7 @@ connect mywire, UInt<1>(0)
426428
Unlike nodes, the type of a wire must be explicitly declared.
427429
The type of a wire is given after the colon (`:`{.firrtl}).
428430

429-
## Registers
431+
### Registers
430432

431433
Registers are stateful elements of a design.
432434

@@ -466,7 +468,7 @@ Semantically, registers become flip-flops in the design.
466468
The next value is latched on the positive edge of the clock.
467469
The initial value of a register is indeterminate (see [@sec:indeterminate-values]).
468470

469-
## Output Ports and Input Ports
471+
### Output Ports and Input Ports
470472

471473
The way a module interacts with the outside world is through its output and input ports.
472474

@@ -481,7 +483,7 @@ For both variants of port, the type is given after the colon (`:`{.firrtl}).
481483

482484
The two kinds of ports differ in the rules for how they may be connected (see [@sec:connections]).
483485

484-
## Submodule Instances
486+
### Submodule Instances
485487

486488
A module in FIRRTL may contain submodules.
487489

@@ -513,7 +515,7 @@ The type of the submodule instance `passthrough`{.firrtl} above is thus:
513515
{ flip in : UInt<8>, out : UInt<8> }
514516
```
515517

516-
## Memories
518+
### Memories
517519

518520
Memories are stateful elements of a design.
519521

@@ -538,6 +540,109 @@ It indicates the type of the data being stored inside of the memory.
538540

539541
See [@sec:memories] for more details.
540542

543+
## Subcomponents
544+
545+
Each circuit component factors into subcomponents which can be accessed through references.
546+
547+
### Examples
548+
549+
To motivate the notion of subcomponents, let's look at a few examples.
550+
551+
First, let's look at a wire with a vector type:
552+
553+
``` firrtl
554+
module Foo :
555+
wire v : UInt<8>[3]
556+
connect v[0], UInt(0)
557+
connect v[1], UInt(10)
558+
connect v[2], UInt(42)
559+
```
560+
561+
Here, we have declared a wire `v`{.firrtl} with a vector type with length 3.
562+
We can index into the wire `v`{.firrtl} with the expressions `v[0]`{.firrtl}, `v[1]`{.firrtl}, and `v[2]`{.firrtl}, and target these with a `connect`{.firrtl} statement (see [@sec:connections]).
563+
Each of these is a subcomponent of `v`{.firrtl} and each acts like a wire with type `UInt<8>`{.firrtl}.
564+
565+
Next, let's look at a port with a bundle type:
566+
567+
``` firrtl
568+
module Bar :
569+
output io : { x : UInt<8>, flip y : UInt<8> }
570+
connect io.x, add(io.y, UInt(1))
571+
```
572+
573+
The bundle of port `io`{.firrtl} has type `{ x : UInt<8>, flip y : UInt<8> }`{.firrtl}.
574+
It has two fields, `x`{.firrtl} and `y`{.firrtl}, and `y`{.firrtl} is flipped.
575+
In the connect expression, we read from `io.y`{.firrtl}, add 1 to it, and then assign it to `io.x`{.firrtl}.
576+
Both `io.x`{.firrtl} and `io.y`{.firrtl} are subcomponents of `io`{.firrtl} and both have type `UInt<8>`{.firrtl}.
577+
Note that while `io.x`{.firrtl} is an output port, `io.y`{.firrtl} is an input port.
578+
579+
### Definition
580+
581+
Every circuit component declared within a module results in a tree of **subcomponents**.
582+
Circuit subcomponents have both a kind and a type.
583+
584+
We define this tree of subcomponents recursively by defining the **direct subcomponent** relation.
585+
586+
A circuit component with a ground type, an enumeration type, a probe type, or property type (see [@sec:types]) has no direct subcomponents.
587+
For example, `wire w : UInt<8>`{.firrtl} has no direct subcomponents.
588+
589+
When a circuit component has a vector type (see [@sec:vector-types]), it has as many direct subcomponents as its length.
590+
Each subcomponent has the same kind as its parent and has the element type.
591+
For example, if we declare `wire v : UInt<8>[3]`{.firrtl}, it has three direct subcomponents: `v[0]`{.firrtl}, `v[1]`{.firrtl}, and `v[2]`{.firrtl}.
592+
All three are wires and all three have type `UInt<8>`{.firrtl}.
593+
594+
When a circuit component has a bundle type (see [@sec:bundle-types]), it has one direct subcomponent for each field.
595+
The kind of the subcomponent depends on both the kind and the type of the parent:
596+
597+
- For nodes, wires, and registers, the kind of each direct subcomponent is the same.
598+
- For output and input ports, the kind of each direct subcomponent depends on whether or not the field is flipped.
599+
When the field is not flipped, the kind remains the same.
600+
When the field is flipped, it changes from output to input or vice versa.
601+
- For submodule instances and memories, the kind of each direct subcomponent depends on whether or not the field is flipped.
602+
When the field is not flipped, the kind is an input port.
603+
When the field is flipped, the kind is an output port.
604+
605+
If the bundle is not `const`{.firrtl}, the type of each subcomponent is simply the type of the corresponding field.
606+
However, if the bundle is `const`{.firrtl}, the type of each subcomponent is the `const`{.firrtl} version of the type of the corresponding field.
607+
608+
A circuit component is a **subcomponent** of another if there is a way to get from the first component to the second through the direct subcomponent relation.
609+
A circuit component is trivially considered to be a subcomponent of itself.
610+
If we need to speak of the subcomponents excluding the component itself, we call these the **proper subcomponents**.
611+
612+
A **root component** is a circuit component that is not the direct subcomponent of any other component.
613+
Equivalently, these are the circuit components which are declared inside a module.
614+
615+
A **leaf component** is a circuit component that has no direct subcomponents.
616+
Leaf components are useful for checking initialization.
617+
618+
Two components are **disjoint** if they have no common subcomponent.
619+
For example, given `wire w : { x : UInt<1>, y : UInt<8>[2] }`{.firrtl}, `w.x`{.firrtl} and `w.y`{.firrtl} are disjoint, but `w.y[0]`{.firrtl} and `w.y`{.firrtl} are not.
620+
621+
### References
622+
623+
A **reference** is a name that refers to a previously declared circuit component.
624+
These are constructed using the names of root components, and optionally, through the dot and bracket operators.
625+
626+
For instance, suppose we declare `wire w : { x : UInt<1>, v : UInt<8>[2] }`{.firrtl}.
627+
Then `w`{.firrtl}, `w.x`{.firrtl}, `w.y`{.firrtl}, `w.y[0]`{.firrtl}, and `w.y[1]`{.firrtl}, and `w.y[i]`{.firrtl} are all examples of references.
628+
629+
When a circuit component has a vector type, you can perform both static and dynamic indexing.
630+
For example, given `wire v : UInt<8>[2]`{.firrtl}, both `v[0]`{.firrtl} and `v[1]`{.firrtl} are references using static indexing.
631+
On the other hand, `v[i]`{.firrtl} is a reference using dynamic indexing, given an expression `i`{.firrtl} with an unsigned integer type.
632+
633+
The result of an out-of-bounds dynamic index is an indeterminate value (see [@sec:indeterminate-values]).
634+
635+
A **static reference** is a reference where all indexing is static.
636+
For instances, `v[0]`{.firrtl}, `v[1]`{.firrtl}, and `v[2]`{.firrtl} are static references.
637+
Static references are checked to ensure they are always in-bounds.
638+
A static reference identifies a concrete subcomponent within the module definition.
639+
Static references may be used in `probe`{.firrtl} or `rwprobe`{.firrtl} expressions (see [@sec:probes]).
640+
641+
A **dynamic reference** is one which is not a static reference.
642+
643+
References may appear as the target of `connect`{.firrtl} statements (see [@sec:connections]).
644+
A connection to a dynamic reference is equivalent to a (potentially large) conditional statement consisting of only connects to static references.
645+
541646
# Types
542647

543648
FIRRTL has four classes of types: **ground** types, **aggregate** types, **probe** types, and **property** types.
@@ -1116,7 +1221,7 @@ module MyModule :
11161221
connect myport, portx
11171222
```
11181223

1119-
See [@sec:sub-fields] for more details about sub-field expressions.
1224+
See [@sec:references] for more details about indexing.
11201225

11211226
## Invalidates
11221227

@@ -2432,195 +2537,6 @@ The data value expression may be omitted when the data type is `UInt<0>(0)`{.fir
24322537
{|some: UInt<8>, None|}(Some, x)
24332538
```
24342539

2435-
## References
2436-
2437-
A reference is simply a name that refers to a previously declared circuit component.
2438-
2439-
The following example connects a reference expression `in`{.firrtl}, referring to the previously declared port `in`{.firrtl}, to the reference expression `out`{.firrtl}, referring to the previously declared port `out`{.firrtl}.
2440-
2441-
``` firrtl
2442-
module MyModule :
2443-
input in: UInt
2444-
output out: UInt
2445-
connect out, in
2446-
```
2447-
2448-
In the rest of the document, for brevity, the names of components will be used to refer to a reference expression to that component.
2449-
Thus, the above example will be rewritten as "the port `in`{.firrtl} is connected to the port `out`{.firrtl}".
2450-
2451-
### Static Reference Expressions
2452-
2453-
Static references start with an identifier, optionally followed by sub-fields or sub-indices selecting a particular sub-element.
2454-
Sub-accesses are not allowed.
2455-
2456-
Define statements must have static references as their target, and their source must be either a static reference or a probe expression whose argument is a static reference.
2457-
2458-
## Sub-fields
2459-
2460-
The sub-field expression refers to a sub-element of an expression with a bundle type.
2461-
If the expression is of a constant bundle type, the sub-element shall be of a constant type (`const`{.firrtl} propagates from the bundle to the element on indexing).
2462-
2463-
The following example connects the `in`{.firrtl} port to the `a`{.firrtl} sub-element of the `out`{.firrtl} port.
2464-
2465-
``` firrtl
2466-
module MyModule :
2467-
input in: UInt
2468-
output out: {a: UInt, b: UInt}
2469-
connect out.a, in
2470-
```
2471-
2472-
The following example is the same as above, but with a constant output bundle.
2473-
2474-
``` firrtl
2475-
module MyModule :
2476-
input in: const UInt
2477-
output out: const {a: UInt, b: UInt}
2478-
connect out.a, in ; out.a is of type const UInt
2479-
```
2480-
2481-
The following example is the same as above, but with a bundle with a constant field.
2482-
2483-
``` firrtl
2484-
module MyModule :
2485-
input in: const UInt
2486-
output out: {a: const UInt, b: UInt}
2487-
connect out.a, in ; out.a is of type const UInt
2488-
```
2489-
2490-
A sub-field referring to a field whose name is a literal identifier is shown below:
2491-
2492-
``` firrtl
2493-
module MyModule :
2494-
input a: { `0` : { `0` : { b : UInt<1> } } }
2495-
output b: UInt<1>
2496-
connect b, a.`0`.`0`.b
2497-
```
2498-
2499-
## Sub-indices
2500-
2501-
The sub-index expression statically refers, by index, to a sub-element of an expression with a vector type.
2502-
The index must be a non-negative integer and cannot be equal to or exceed the length of the vector it indexes.
2503-
If the expression is of a constant vector type, the sub-element shall be of a constant type.
2504-
2505-
The following example connects the `in`{.firrtl} port to the fifth sub-element of the `out`{.firrtl} port.
2506-
2507-
``` firrtl
2508-
module MyModule :
2509-
input in: UInt
2510-
output out: UInt[10]
2511-
connect out[4], in
2512-
```
2513-
2514-
The following example is the same as above, but with a constant vector.
2515-
2516-
``` firrtl
2517-
module MyModule :
2518-
input in: const UInt
2519-
output out: const UInt[10]
2520-
connect out[4], in ; out[4] has a type of const UInt
2521-
```
2522-
2523-
## Sub-accesses
2524-
2525-
The sub-access expression dynamically refers to a sub-element of a vector-typed expression using a calculated index.
2526-
The index must be an expression with an unsigned integer type.
2527-
If the expression is of a constant vector type, the sub-element shall be of a constant type.
2528-
An access to an out-of-bounds element results in an indeterminate value (see [@sec:indeterminate-values]).
2529-
Each out-of-bounds element is a different indeterminate value.
2530-
Sub-access operations with constant index may be converted to sub-index operations even though it converts indeterminate-value-on-out-of-bounds behavior to a compile-time error.
2531-
2532-
The following example connects the n'th sub-element of the `in`{.firrtl} port to the `out`{.firrtl} port.
2533-
2534-
``` firrtl
2535-
module MyModule :
2536-
input in: UInt[3]
2537-
input n: UInt<2>
2538-
output out: UInt
2539-
connect out, in[n]
2540-
```
2541-
2542-
A connection from a sub-access expression can be modeled by conditionally connecting from every sub-element in the vector, where the condition holds when the dynamic index is equal to the sub-element's static index.
2543-
2544-
``` firrtl
2545-
module MyModule :
2546-
input in: UInt[3]
2547-
input n: UInt<2>
2548-
output out: UInt
2549-
when eq(n, UInt(0)) :
2550-
connect out, in[0]
2551-
else when eq(n, UInt(1)) :
2552-
connect out, in[1]
2553-
else when eq(n, UInt(2)) :
2554-
connect out, in[2]
2555-
else :
2556-
invalidate out
2557-
```
2558-
2559-
The following example connects the `in`{.firrtl} port to the n'th sub-element of the `out`{.firrtl} port.
2560-
All other sub-elements of the `out`{.firrtl} port are connected from the corresponding sub-elements of the `default`{.firrtl} port.
2561-
2562-
``` firrtl
2563-
module MyModule :
2564-
input in: UInt
2565-
input default: UInt[3]
2566-
input n: UInt<2>
2567-
output out: UInt[3]
2568-
connect out, default
2569-
connect out[n], in
2570-
```
2571-
2572-
A connection to a sub-access expression can be modeled by conditionally connecting to every sub-element in the vector, where the condition holds when the dynamic index is equal to the sub-element's static index.
2573-
2574-
``` firrtl
2575-
module MyModule :
2576-
input in: UInt
2577-
input default: UInt[3]
2578-
input n: UInt<2>
2579-
output out: UInt[3]
2580-
connect out, default
2581-
when eq(n, UInt(0)) :
2582-
connect out[0], in
2583-
else when eq(n, UInt(1)) :
2584-
connect out[1], in
2585-
else when eq(n, UInt(2)) :
2586-
connect out[2], in
2587-
```
2588-
2589-
The following example connects the `in`{.firrtl} port to the m'th `UInt`{.firrtl} sub-element of the n'th vector-typed sub-element of the `out`{.firrtl} port.
2590-
All other sub-elements of the `out`{.firrtl} port are connected from the corresponding sub-elements of the `default`{.firrtl} port.
2591-
2592-
``` firrtl
2593-
module MyModule :
2594-
input in: UInt
2595-
input default: UInt[2][2]
2596-
input n: UInt<1>
2597-
input m: UInt<1>
2598-
output out: UInt[2][2]
2599-
connect out, default
2600-
connect out[n][m], in
2601-
```
2602-
2603-
A connection to an expression containing multiple nested sub-access expressions can also be modeled by conditionally connecting to every sub-element in the expression.
2604-
However the condition holds only when all dynamic indices are equal to all of the sub-element's static indices.
2605-
2606-
``` firrtl
2607-
module MyModule :
2608-
input in: UInt
2609-
input default: UInt[2][2]
2610-
input n: UInt<1>
2611-
input m: UInt<1>
2612-
output out: UInt[2][2]
2613-
connect out, default
2614-
when and(eq(n, UInt(0)), eq(m, UInt(0))) :
2615-
connect out[0][0], in
2616-
else when and(eq(n, UInt(0)), eq(m, UInt(1))) :
2617-
connect out[0][1], in
2618-
else when and(eq(n, UInt(1)), eq(m, UInt(0))) :
2619-
connect out[1][0], in
2620-
else when and(eq(n, UInt(1)), eq(m, UInt(1))) :
2621-
connect out[1][1], in
2622-
```
2623-
26242540
## Multiplexers
26252541

26262542
A multiplexer outputs one of two input expressions depending on the value of an unsigned selection signal.

0 commit comments

Comments
 (0)