From 0970fa3c91d3cd2d5484b7e636b13660e721da06 Mon Sep 17 00:00:00 2001 From: Will Dietz Date: Wed, 25 May 2022 13:44:37 -0500 Subject: [PATCH] [docs] touchups (#3194) Lots of small fixes to documentation. --- docs/Charter.md | 4 ++-- docs/GettingStarted.md | 17 ++++++++--------- docs/RationaleComb.md | 29 ++++++++++++++++------------- docs/RationaleESI.md | 2 +- docs/RationaleFIRRTL.md | 8 ++++---- docs/RationaleFSM.md | 4 ++-- docs/RationaleHW.md | 20 ++++++++++---------- docs/RationaleHandshake.md | 6 +++--- docs/RationaleSV.md | 2 +- docs/RationaleSeq.md | 2 +- docs/RationaleSymbols.md | 28 ++++++++++++++-------------- docs/Scheduling.md | 10 +++++----- docs/VerilogGeneration.md | 6 +++--- 13 files changed, 70 insertions(+), 68 deletions(-) diff --git a/docs/Charter.md b/docs/Charter.md index 29ea85b8c751..561c8b758745 100644 --- a/docs/Charter.md +++ b/docs/Charter.md @@ -3,7 +3,7 @@ ## Abstract Recent trends in computer architecture have resulted in two core problems. -Firstly, how do we design complex, heterogenous systems-on-chip mixing +Firstly, how do we design complex, heterogeneous systems-on-chip mixing general purpose and specialized components? Secondly, how do we program them? We believe that design tools that represent and manipulate a wide variety of abstractions are central to solving these @@ -134,7 +134,7 @@ transformation performed on RTL descriptions. ### Finite-State Machine + Datapath (FSMD) -High-Level synthesis(HLS) of RTL designs from C code has become a common +High-Level synthesis (HLS) of RTL designs from C code has become a common paradigm for accelerator design. Typically generating a high-performance implementation requires analysis and scheduling of the FSMD model in order to understand the performance diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index 9e4e54676fcb..d028af5f96d1 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -45,7 +45,7 @@ $ git submodule update *Note:* The repository is set up so that `git submodule update` performs a shallow clone, meaning it downloads just enough of the LLVM repository to check out the currently specified commit. If you wish to work with the full history of -the LLVM repository, you can manually "unshallow" the the submodule: +the LLVM repository, you can manually "unshallow" the submodule: ``` $ cd llvm @@ -116,7 +116,7 @@ the right thing. [Verilator](https://github.com/verilator/verilator) can be used to check SystemVerilog code. To run the tests, build or install a **recent** version -of Verilator (at least v4.034, ideally v1.110 or later to avoid a known bug). +of Verilator (at least v4.034, ideally v4.110 or later to avoid a known bug). (Some Linux distributions have *ancient* versions.) If Verilator is in your PATH, `build check-circt` should run the tests which require Verilator. @@ -135,9 +135,8 @@ dependencies are installed on your system. They are: 7) **Install Cap'nProto** (optional, affects ESI dialect only) -Some of the ESI dialect code requires [libcapnp](https://capnproto.org/). -(Specifically, the [cosimulation](ESI/cosim.md) component.) That code -requires a version of libcapnp which is not yet part of a release. Most of +Some of the ESI dialect code requires [libcapnp](https://capnproto.org/), 0.9.1 or newer. +(Specifically, the [cosimulation](ESI/cosim.md) component.) Most of the ESI cosim integration tests also require the python bindings: pycapnp. The `utils/get-capnp.sh` script downloads, compiles, and installs a known good version to a directory within the circt source code. It optionally @@ -151,10 +150,10 @@ Alternatively, you can use a docker image we provide via software suite for (mathematical) optimization. It provides a uniform interface to several open-source and commercial solvers, e.g. for linear programs and satisfiability problems. Here, it is optionally used in the static scheduling -instructure. Binary distributions often do not include the required CMake build -info. The `utils/get-or-tools.sh` script downloads, compiles, and installs a -known good version to a directory within the CIRCT source code, where it is then -picked up automatically by the build. +infrastructure. Binary distributions often do not include the required CMake +build info. The `utils/get-or-tools.sh` script downloads, compiles, and +installs a known good version to a directory within the CIRCT source code, +where it is then picked up automatically by the build. ## Windows: notes on setting up with Ninja diff --git a/docs/RationaleComb.md b/docs/RationaleComb.md index e02fd7d69d93..5226d44d41b5 100644 --- a/docs/RationaleComb.md +++ b/docs/RationaleComb.md @@ -30,7 +30,7 @@ substrate that may be extended with higher level dialects mixed into it. ## Type System for `comb` Dialect -TODO: Simple integer types, eventually parametricly wide integer type +TODO: Simple integer types, eventually parametrically wide integer type `hw.int`. Supports type aliases. See HW rationale for more info. ### Zero-bit integer width is not supported @@ -156,13 +156,13 @@ discussed the tradeoffs of adding support for a single-operation mux. Such a move has some advantages and disadvantages: 1) It is another operation that many transformations would need to be aware of, - e.g. verilog emission would have to handle it, and peephole optimizations - would have to be aware of array_get and comb.mux. + e.g. Verilog emission would have to handle it, and peephole optimizations + would have to be aware of `array_get` and `comb.mux`. 2) We don't have any known analyses or optimizations that are difficult to implement with the current representation. We agreed that we'd revisit in the future if there were a specific reason to -add it. Until then we represent the array_create/array_get pattern for +add it. Until then we represent the `array_create`/`array_get` pattern for frontends that want to generate this. ## Endianness: operand ordering and internal representation @@ -197,12 +197,14 @@ them in lexical order. %arr456 = ... // {0x4, 0x5, 0x6} %arr78 = ... // {0x7, 0x8} %arr = comb.array_concat %arr123, %arr456, %arr78 : !hw.array<3 x i4>, !hw.array<3 x i4>, !hw.array<2 x i4> -// %arr[0] = 0x6 -// %arr[1] = 0x5 -// %arr[2] = 0x4 -// %arr[3] = 0x3 -// %arr[4] = 0x2 -// %arr[5] = 0x1 +// %arr[0] = 0x8 +// %arr[1] = 0x7 +// %arr[2] = 0x6 +// %arr[3] = 0x5 +// %arr[4] = 0x4 +// %arr[5] = 0x3 +// %arr[6] = 0x2 +// %arr[7] = 0x1 ``` **Note**: This ordering scheme is unintuitive for anyone expecting C @@ -231,7 +233,7 @@ operand list which created the array upon which the op is running. ## Bitcasts -The bitcast operation represents a bitwise reinerpretation (cast) of a value. +The bitcast operation represents a bitwise reinterpretation (cast) of a value. This always synthesizes away in hardware, though it may or may not be syntactically represented in lowering or export language. Since bitcasting requires information on the bitwise layout of the types on which it operates, @@ -244,7 +246,7 @@ used to represent bit vectors. They are never padded or aligned. layout matches C -- the high index of array starts at the MSB. Array's 0th element's LSB located at array LSB. - **Structs**: The HW dialect defines a custom `StructType`. The in-hardware -layout matchss C -- the first listed member's MSB corresponds to the struct's +layout matches C -- the first listed member's MSB corresponds to the struct's MSB. The last member in the list shares its LSB with the struct. - **Unions**: The HW dialect's `UnionType` could contain the data of any of the member types so its layout is defined to be equivalent to the union of members @@ -347,7 +349,8 @@ because - `extract` gets "closer" to underlying `add/sub/xor/op` operations, giving way optimizations like narrowing. - the form gives a more accurate view of the values that are being depended on. -- redundant extract operations can be removed from the concat args lists, eg: +- redundant extract operations can be removed from the concat argument lists, + e.g.: `cat(extract(a), b, c, extract(d))` Both forms perform similarly on hardware, since they are simply bit-copies. diff --git a/docs/RationaleESI.md b/docs/RationaleESI.md index 28a162e7ca64..0874266f73bd 100644 --- a/docs/RationaleESI.md +++ b/docs/RationaleESI.md @@ -8,7 +8,7 @@ to standardize the signaling protocols there are many minor and major variants, both of which lead to confusion which can cause real problems when one is listening to and twiddling the wires manually. ESI solves this by providing a simple, intuitive, common, and standardized interface to developers -then figures out the signaling details and conversions between then. +and then figures out the signaling details and conversions between them. While the ABI/signaling problem is slowly being partially solved, it does not speak to the types of data on the wires – the software analogy being memory diff --git a/docs/RationaleFIRRTL.md b/docs/RationaleFIRRTL.md index 9d5481ff2435..c18b62ea9c42 100644 --- a/docs/RationaleFIRRTL.md +++ b/docs/RationaleFIRRTL.md @@ -44,8 +44,8 @@ FIRRTL specification and is actively maintained, tracking new enhancements. The FIRRTL dialect supports some undocumented features and the "CHIRRTL" flavor of FIRRTL IR that is produced from Chisel. The FIRRTL dialect has support for parsing an SFC Annotation file consisting of only local annotations and -converting this to operation or argument attributes. Non-local annotation -support is planned, but not implemented. +converting this to operation or argument attributes. Non-local annotations +are also supported. There are some exceptions to the above: @@ -379,7 +379,7 @@ result value of the `firrtl.mem` operation. Also, the `firrtl.mem` node does not allow zero port memories for simplicity. Zero port memories are dropped by the .fir file parser. -In the FIRRTL pipeline, the firrtl.mem op can be lowered into either a external +In the FIRRTL pipeline, the `firrtl.mem` op can be lowered into either a external module for macro replacement or a register of vector type. The conditions for macro replacement are as follows: @@ -570,7 +570,7 @@ firrtl.connect %out, %myport_data : !firrtl.uint<1>, !firrtl.uint<1 The CHIRRTL operations and types are contained in the CHIRRTL dialect. The is primary reason to move them into their own dialect was to keep the CHIRRTL -types out of the FIRRTL dialect type hiearchy. We tried to have the CHIRRTL +types out of the FIRRTL dialect type hierarchy. We tried to have the CHIRRTL dialect depend on the FIRRTL dialect, but the flow checking in FIRRTL had to know about CHIRRTL operations, which created a circular dependency. To simplify how this is handled, both dialects are contained in the same library. diff --git a/docs/RationaleFSM.md b/docs/RationaleFSM.md index 81f7b687fa94..d3facdba311b 100644 --- a/docs/RationaleFSM.md +++ b/docs/RationaleFSM.md @@ -54,7 +54,7 @@ don't have such a semantics -- SW IRs “run” sequentially. Here we define that each *trigger* causes the possibility of a transition from one state to another state through exactly one transition. In a SW context, `fsm.instance` generates an `InstanceType` value to represent a state machine -instance. Each `fsm.trigger` targets a machine instance and explicilty causes a +instance. Each `fsm.trigger` targets a machine instance and explicitly causes a *trigger*. Therefore, `fsm.trigger` may change the state of the machine instance thus is a side-effecting operation. The following MLIR code shows an example of instantiating and triggering the state machine defined above: @@ -74,7 +74,7 @@ func @bar() { In the contrast, to comply with the HW semantics, `fsm.hw_instance` directly consumes inputs and generates results. The operand and result types must align with the type of the referenced `fsm.machine`. In a HW context, *trigger*s are -implicilty initiated by the processors of `fsm.hw_instance`. The following +implicitly initiated by the processors of `fsm.hw_instance`. The following MLIR code shows an example of instantiating the same state machine in HW IRs: ```mlir diff --git a/docs/RationaleHW.md b/docs/RationaleHW.md index fa3eb3660498..65ca93d26ff4 100644 --- a/docs/RationaleHW.md +++ b/docs/RationaleHW.md @@ -35,7 +35,7 @@ standard language for hardware design and verification, is known by a large number of engineers who write it manually, and is an important interchange format between EDA tools. However, while it is ubiquitous, SystemVerilog is not easy to generate or transform. Furthermore, it -is non-trivial for compiler tools to generate high quality human readable +is non-trivial for compiler tools to generate high-quality human-readable SystemVerilog. The `hw`, `comb` and `sv` dialects attempt to address these problems with @@ -144,7 +144,7 @@ notable differences: for example: - The `comb` dialect in particular does not use signed integer types, its operators do not support zero-width integer types. Modules in the `hw` dialect, on the other hand, do support both of these. Zero width ports are omitted (printed as - comments) when generating verilog. + comments) when generating Verilog. ### GlobalRefOp The GlobalRefOp operation (`hw.globalRef`) can be used to identify the unique @@ -213,7 +213,7 @@ This allows for metaprogramming along the instance tree, guaranteed "instantiation time" optimizations and code generation, further enables the "IR compression" benefits of using instances in the first place, and enables the generation of parameters in generated Verilog (which can increase the -percieved readability of the generated code). +perceived readability of the generated code). Parameters are declared on modules (including generated and external ones) with angle brackets: each parameter has a name and type, and can optionally @@ -272,7 +272,7 @@ module: rules to ensure important cases are canonicalized to uniquable representations. - `#hw.param.verbatim<"some string">` may be used to provide an opaque blob of - textual verilog that is uniqued by its string contents. This is intended + textual Verilog that is uniqued by its string contents. This is intended as a general "escape hatch" that allows frontend authors to express anything Verilog cannot, even if first-class IR support doesn't exist yet. CIRCT does not provide any checking to ensure that this is correct or safe, and assumes it @@ -318,8 +318,8 @@ well. On the other hand, we expect to support a lot of weird expressions over time (at least the full complement that Verilog supports) and canonicalize arbitrary -expressions in a predictable way is untennable. As such, we support -canonicalizating a fixed set of expressions predictably: more may be added in +expressions in a predictable way is untenable. As such, we support +canonicalizing a fixed set of expressions predictably: more may be added in the future. This set includes: @@ -446,7 +446,7 @@ All that said, using attributes is the right thing for a number of reasons: 3) We need to support parameterized types like `!hw.int`: because MLIR types are immortal and uniqued, they can refer to attributes but cannot refer to [SSA values](https://en.wikipedia.org/wiki/Static_single_assignment_form) - (which may be destoyed). + (which may be destroyed). 4) Operations need to be able to compute their own type without creating other operations. For example, we need to compute that the result type of `comb.concat %a, %b : (i1, !hw.int)` is `!hw.int` without introducing @@ -545,7 +545,7 @@ Until then, we must duplicate the type in the IR. Verilog has a broad notion of what can be named outside the context of its declaration. This is compounded by the many tools which have additional source -files which refer to verilog names (e.g. tcl files). However, we do not want to +files which refer to Verilog names (e.g. tcl files). However, we do not want to require that every wire, register, instance, localparam, port, etc which can be named not be touched by passes. We want only entities marked as public facing to impede transformation. @@ -564,7 +564,7 @@ references are more general, SV and HW dialects do not define symbol tables for modules. Therefore, wires, registers, and interfaces exist in the same namespace as modules. It is encouraged that one prefaces the names to avoid conflict with modules. The symbol names on these entities has no bearing on the -output verilog, each of these entities has a defined way to assign its name (SSA +output Verilog, each of these entities has a defined way to assign its name (SSA value name for wires and regs, a non-optional string for instances). As MLIR symbol support improves, it is desired to move to per-module symbol @@ -572,7 +572,7 @@ tables and to unify names with symbol names. **Ports** -Module ports are remotely namable entities in Verilog, but are not easily named +Module ports are remotely nameable entities in Verilog, but are not easily named with symbols. A suggested workaround is to attach a wire to a port and use its symbol for remote references. Instance ports have a similar problem. diff --git a/docs/RationaleHandshake.md b/docs/RationaleHandshake.md index 73eecadc478a..99b57e8035ea 100644 --- a/docs/RationaleHandshake.md +++ b/docs/RationaleHandshake.md @@ -6,11 +6,11 @@ This document also explains in a high-level manner how different components are organized, the principles behind them and the conventions we followed. The document assume that you have basic understanding of [asynchronous digital circuits](https://en.wikipedia.org/wiki/Asynchronous_circuit) -at the behavioral level abstraction. +at the behavioral level of abstraction. ## Principle -Handshake/dataflow IR is describes independent, unsynchronized processes +Handshake/dataflow IR describes independent, unsynchronized processes communicating data through First-in First-out (FIFO) communication channels. This can be implemented in many ways, such as using synchronous logic, or with processors. @@ -40,7 +40,7 @@ can also lower the std MLIR produced by different frontends to Handshake IR. ## IR Representation -Simple Handshake IR snippet for add function look like this - +Simple Handshake IR snippet for an add function looks like this - ``` handshake.func @simple_addi(%arg0: index, %arg1: index, %arg2: none, ...) -> (index, none) { %0 = addi %arg0, %arg1 : index diff --git a/docs/RationaleSV.md b/docs/RationaleSV.md index 8b48df9a1a10..6a8440d2bfd9 100644 --- a/docs/RationaleSV.md +++ b/docs/RationaleSV.md @@ -84,7 +84,7 @@ that is lowered to the `indexed part-select` operation. The `sv.part_select` is defined on `Integer` type input and `sv.part_select_inout` is defined on `inout` type. - Part select consits of 3 arguments, the input value, + Part select consists of 3 arguments, the input value, a `width` and a `base` and an optional boolean attribute `decrement`. The `width` shall be a compile-time constant expression. The `base` can be a runtime integer expression. diff --git a/docs/RationaleSeq.md b/docs/RationaleSeq.md index b1ca223b716f..f591e5539ffc 100644 --- a/docs/RationaleSeq.md +++ b/docs/RationaleSeq.md @@ -105,7 +105,7 @@ optimization) another op could be added. do not detect and generate the SystemVerilog correctly), we can build it into the compreg op. - Reset style and clock style: how should we model posedge vs negedge clocks? -Async vs sync resets? There are some reasonble options here: attributes on +Async vs sync resets? There are some reasonable options here: attributes on this op or `clock` and `reset` types which are parameterized with that information. - Initial value: this register is uninitialized. Using an uninitialized value diff --git a/docs/RationaleSymbols.md b/docs/RationaleSymbols.md index 69d3e2ec97ca..2483ef82b85c 100644 --- a/docs/RationaleSymbols.md +++ b/docs/RationaleSymbols.md @@ -8,13 +8,13 @@ related types. This follows in the spirit of other ## Introduction Verilog and FIRRTL have, from a software compiler perspective, an unusual -number of namable entities which can be referred to non-locally. These entities +number of nameable entities which can be referred to non-locally. These entities have deep nesting in the code structures. The requirements of dealing with -these entities and references entails a more complexity than provided by MLIR's -symbols and symbol tables. Several CIRCT dialects, therefor, share a common +these entities and references entails more complexity than provided by MLIR's +symbols and symbol tables. Several CIRCT dialects, therefore, share a common supplemental mechanism called "Inner Symbols" to manage these requirements. -Inner Symbols necessarily deviates from MLIR nested symbol tables to enable -representation of the behavior of verilog and FIRRTL. +Inner Symbols necessarily deviate from MLIR nested symbol tables to enable +representation of the behavior of Verilog and FIRRTL. ## Use of MLIR symbols @@ -31,11 +31,11 @@ instantiated module. Within a `firrtl` or `hw` module, many entities may exist which can be referenced outside the module. Operations and ports (and memory ports), need to define -symbol-like data to allow forming non-ssa linkage between disparate elements. -To accomplish this, an attribute named `inner_sym` is attached a scoped -symbol-like name to the element. An operation with an `inner_sym` resides in -arbitrarily-nested regions of a region that defines an `InnerSymbolTable` and -a `Symbol` . +symbol-like data to allow forming non-SSA linkage between disparate elements. +To accomplish this, an attribute named `inner_sym` is attached providing a +scoped symbol-like name to the element. An operation with an `inner_sym` +resides in arbitrarily-nested regions of a region that defines an +`InnerSymbolTable` and a `Symbol` . Inner Symbols are different from normal symbols due to MLIR symbol table resolution rules. Specifically normal symbols are resolved by first going up @@ -54,7 +54,7 @@ something not allowed by normal symbols. ## Inner Symbol Reference Attribute -An attribute `InnerRefAttr` is provided to encapsulated references to inner +An attribute `InnerRefAttr` is provided to encapsulate references to inner symbols. This attribute stores the parent symbol and the inner symbol. This provides a uniform type for storing and manipulating references to inner symbols. @@ -63,15 +63,15 @@ symbols. Inner symbols are more costly than normal symbols, precisely from the relaxation of MLIR symbol constraints. Since nested regions are allowed, -finding all operations defining an `inner_sym` requires a recursive ir scan. +finding all operations defining an `inner_sym` requires a recursive IR scan. Verification is likewise trickier, partly due the significant increase in non-local references. ## Common Use The most common use for `InnerRefAttr`s are to build paths through the instantiation -graph to use a subset of the instances of an entity is some way. This may -be reading values via System Verilog's cross-module references (XMRs), +graph to use a subset of the instances of an entity in some way. This may +be reading values via SystemVerilog's cross-module references (XMRs), specifying SV bind constraints, specifying placement constraints, or representing non-local attributes (FIRRTL). diff --git a/docs/Scheduling.md b/docs/Scheduling.md index 5d0e012a524f..1431e97677f9 100644 --- a/docs/Scheduling.md +++ b/docs/Scheduling.md @@ -77,7 +77,7 @@ Note that we do not have to tell the instance about the *dependences* between th ### Scheduling -Before we attempt to schedule, we invoke the `check()` method, which ensures that the constructed instance is complete and valid. For example, the check would capture if we had forgot to set an operator type's latency. We dump the instance to visualize the depedence graph. +Before we attempt to schedule, we invoke the `check()` method, which ensures that the constructed instance is complete and valid. For example, the check would capture if we had forgot to set an operator type's latency. We dump the instance to visualize the dependence graph. ```c++ auto checkRes = prob.check(); @@ -96,7 +96,7 @@ assert(succeeded(schedRes)); ### Working with the solution -The solution is now stored in the instance, and we invoke the problem's `verify()` method to ensure that the computed start times adhere to the precendence constraint we stated earlier, i.e. operations start after their operands have computed their results. We can also convince ourselves of that by dumping the instance and inspecting the solution. +The solution is now stored in the instance, and we invoke the problem's `verify()` method to ensure that the computed start times adhere to the precedence constraint we stated earlier, i.e. operations start after their operands have computed their results. We can also convince ourselves of that by dumping the instance and inspecting the solution. ```c++ auto verifRes = prob.verify(); @@ -151,7 +151,7 @@ Properties can involve arbitrary data types, as long as these can be stored in m #### Constraints -Clients call the virtual `Problem::check()` method to test any input constraints, and `Problem::verify()` to test the solution constraits. Problem classes are expected to override them as needed. There are no further restrictions of how these methods are implemented, but it is recommended to introduce helper methods that test a specific aspect and can be reused in extended problems. In addition, it makes sense to check/verify the properties in an order that avoids redundant tests for the presence of a particular property as well as redundant iteration over the problem components. +Clients call the virtual `Problem::check()` method to test any input constraints, and `Problem::verify()` to test the solution constraints. Problem classes are expected to override them as needed. There are no further restrictions of how these methods are implemented, but it is recommended to introduce helper methods that test a specific aspect and can be reused in extended problems. In addition, it makes sense to check/verify the properties in an order that avoids redundant tests for the presence of a particular property as well as redundant iteration over the problem components. ## Available problem definitions @@ -174,7 +174,7 @@ NB: The classes listed above each model a *trait*-like aspect of scheduling. The ## Utilities See [`Utilities.h`](https://github.com/llvm/circt/blob/main/include/circt/Scheduling/Utilities.h): -- Topologic graph traversal +- Topological graph traversal - DFA to compute combinational path delays - DOT dump @@ -185,7 +185,7 @@ See [`Utilities.h`](https://github.com/llvm/circt/blob/main/include/circt/Schedu - Decide where to add it. Guideline: If it is trait-like and similar to the existing problem mentioned above, add it to `Problems.h`. If the model is specific to your use-case, it is best to start out in locally in your dialect/pass. - Declare the new problem class and inherit *virtually* from the relevant superclasses (at least `Problem`). - Define additional properties (private), and the corresponding public getters/setters. Getters return `Optional` values, to indicate an unset state. - - Note that dependence properties are somewhat expensive to store, making it desirable that clients and algorithms expect and handle the unset state. This should be clearly documented. Example: `distance` propertiy in `CyclicProblem`. + - Note that dependence properties are somewhat expensive to store, making it desirable that clients and algorithms expect and handle the unset state. This should be clearly documented. Example: `distance` property in `CyclicProblem`. - Redefine the `getProperties(*)` methods to get dumping support. These should consider any properties the new class adds, plus properties defined in the superclass(es). - Redefine `check()` (input constraints) and `verify()` (solution constraints). If possible, follow the [design used in the existing problem classes](#constraints). - Write a couple of "positive" testcases, as well as at least one error test for each input/solution constraint, as validated by `check()` / `verify()`. See [`TestPasses.cpp`](https://github.com/llvm/circt/blob/main/lib/Scheduling/TestPasses.cpp) for inspiration. The testing situation will hopefully improve with [#2760](https://github.com/llvm/circt/issues/2760). diff --git a/docs/VerilogGeneration.md b/docs/VerilogGeneration.md index cb2448e32d2b..61b6a15f393c 100644 --- a/docs/VerilogGeneration.md +++ b/docs/VerilogGeneration.md @@ -3,7 +3,7 @@ [Verilog](https://en.wikipedia.org/wiki/Verilog) and [SystemVerilog](https://en.wikipedia.org/wiki/SystemVerilog) are critical components of the hardware design tool -ecosystem, but generating syntatically correct Verilog that is acceptable by a +ecosystem, but generating syntactically correct Verilog that is acceptable by a wide range of tools is a challenge -- and generating "good looking" output even more so. This document describes CIRCT's approach and support for generating Verilog and @@ -146,7 +146,7 @@ of your pipeline should work well: // passes after this that aren't aware of LoweringOptions. modulePM.addPass(sv::createHWLegalizeModulesPass()); - // Optional: Tidy up the IR to improve verilog emission quality. + // Optional: Tidy up the IR to improve Verilog emission quality. modulePM.addPass(sv::createPrettifyVerilogPass()); // Actually export the module. @@ -205,7 +205,7 @@ in inverse order. ### The core `ExportVerilog` logic The core of `ExportVerilog` walks the IR and prints out syntactically correct -verilog to an `llvm::raw_ostream`. +Verilog to an `llvm::raw_ostream`. TODO: Talk about line splitting, preorder traversal, NameCollector, etc. Cross block references always go through a temporary. This doesn't support cyclic