From d6ed0bb31b86320a1c5aa229b3f9755f776f77e7 Mon Sep 17 00:00:00 2001 From: Max Korbel Date: Tue, 18 Mar 2025 12:55:20 -0700 Subject: [PATCH 01/11] Add docs about trusting ROHD --- README.md | 2 +- ...m-module-behavior-inline-system-verilog.md | 2 +- doc/user_guide/_get-started/01-overview.md | 35 ++++++++++++++++++- lib/src/modules/conditionals/case.dart | 2 +- lib/src/modules/conditionals/conditional.dart | 2 +- 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 823200b36..ec642e053 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![License](https://img.shields.io/badge/License-BSD--3-blue)](https://github.com/intel/rohd/blob/main/LICENSE) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://github.com/intel/rohd/blob/main/CODE_OF_CONDUCT.md) -ROHD (pronounced like "road") is a framework for describing and verifying hardware in the Dart programming language. +ROHD (pronounced like "road") is a silicon-proven framework for describing and verifying hardware in the Dart programming language. ## Documentation diff --git a/doc/user_guide/_docs/A13-custom-module-behavior-inline-system-verilog.md b/doc/user_guide/_docs/A13-custom-module-behavior-inline-system-verilog.md index 5d4186ad1..0183b3e84 100644 --- a/doc/user_guide/_docs/A13-custom-module-behavior-inline-system-verilog.md +++ b/doc/user_guide/_docs/A13-custom-module-behavior-inline-system-verilog.md @@ -6,7 +6,7 @@ last_modified_at: 2024-6-3 toc: true --- -Many of the basic built-in gates in Dart implement custom behavior. An implementation of the `NotGate` is shown below as an example. There is different syntax for functions which can be inlined versus those which cannot (the `~` can be inlined). In this case, the `InlineSystemVerilog` mixin is used, but if it were not inlineable, you could use the `SystemVerilog` mixin instead. Note that it is mandatory to provide an initial value computation when the module is first created for non-sequential modules. +Many of the basic built-in gates in ROHD implement custom behavior. An implementation of the `NotGate` is shown below as an example. There is different syntax for functions which can be inlined versus those which cannot (the `~` can be inlined). In this case, the `InlineSystemVerilog` mixin is used, but if it were not inlineable, you could use the `SystemVerilog` mixin instead. Note that it is mandatory to provide an initial value computation when the module is first created for non-sequential modules. ```dart /// A gate [Module] that performs bit-wise inversion. diff --git a/doc/user_guide/_get-started/01-overview.md b/doc/user_guide/_get-started/01-overview.md index c1a98cdc1..9220633f1 100644 --- a/doc/user_guide/_get-started/01-overview.md +++ b/doc/user_guide/_get-started/01-overview.md @@ -8,7 +8,7 @@ toc: true ## Describing Hardware in Dart with ROHD -ROHD (pronounced like "road") is a framework for describing and verifying hardware in the Dart programming language. +ROHD (pronounced like "road") is a silicon-proven framework for describing and verifying hardware in the Dart programming language. Features of ROHD include: @@ -63,3 +63,36 @@ Try out Dart instantly from your browser here (it supports ROHD too!): For more information on Dart and tutorials, see and + +## Trusting ROHD + +A common initial concern when adopting ROHD is the matter of trust. How can one trust that there is equivalence between what was developed and simulated in ROHD and what gets generated in the output SystemVerilog? + +### Unoptimized, simple, one-to-one mapping + +ROHD generates outputs one-to-one with the objects constructed in the original Dart. There is no magic compiler under the hood that's transforming or optimizing your design. A module instantiated in a ROHD model will directly map to a piece of equivalent generated SystemVerilog. This is key to generating logically equivalent, structurally similar outputs with instance and signal names and hierarchy maintained. This means there are two somewhat independent pieces of ROHD generation: + +1. How to generate an output based on an instance in the ROHD model. +2. How to compose and connect instances together in the generated output. + +These two steps are a thin layer between the original design intent and the generated output. More complex abstractions are created by composing together lower-level building blocks. One can always trace exactly how an output was created. + +### Extensive unit testing across simulators + +Generation and composition are extensively tested in the ROHD test suite. Every feature, argument, and composition mechanism is unit-tested before it can be merged in. Most of these tests are written using test vectors which are then run on both the ROHD simulator and in a SystemVerilog simulator on the generated outputs, ensuring identical behavior between the two simulators. + +Generally speaking, the ROHD simulations are *stricter* and *more predictable* than SystemVerilog simulators can be. For example, in SystemVerilog, transitions between invalid signal states (`x` and `z`) can trigger as edges in sequential logic, whereas in ROHD they cannot, and in fact would propagate an `x` instead. In SystemVerilog, if you violate a `unique` on a `case`, you get a *warning printed in the logs*, whereas in ROHD you get an `x` out of that block. + +ROHD is also both more flexible in design intent and more restrictive in SystemVerilog generation. It is easy in SystemVerilog to describe non-synthesizable logic, but ROHD makes it very difficult to generate SystemVerilog which would imply an ambiguous design. ROHD also helps ensure lint-clean SystemVerilog generation, even if that means it would become more verbose. Since ROHD does not generate everything that SystemVerilog *could* do, it means the surface area to test is dramatically reduced for equivalence of simulator behavior. + +### Trusting EDA tools in general + +How does anyone trust any EDA tool in general? Usually a combination of + +- testing methodologies to ensure the tool works (and doesn't break with new versions), +- a history of real-world usage, and +- sanity checking the results. + +Bugs are still found regularly in "industry-standard" EDA tools, including between simulators and synthesis tools from the same developer and in formal analysis tools. Even if you run formal tools (equivalence, verification, etc.) on a design, those tools themselves were not formally proven. There's a lot of human-written software between the source code you wrote and the design you tape out. It's not a bad thing to do some sanity checking on critical designs for *any* EDA tool (e.g. reviewing outputs manually, paranoia checks, running other tools to compare results, formal analysis, etc.). + +ROHD's thin generation layer, real-world usage, and open-source, well-tested implementation should inspire a good amount of confidence. In the end, it's up to you, the user, to decide how much you trust the tools you're using and what additional steps are worth taking to mitigate risk. diff --git a/lib/src/modules/conditionals/case.dart b/lib/src/modules/conditionals/case.dart index 590437391..c6221da10 100644 --- a/lib/src/modules/conditionals/case.dart +++ b/lib/src/modules/conditionals/case.dart @@ -166,7 +166,7 @@ class Case extends Conditional { CaseItem? foundMatch; for (final item in items) { - // match on the first matchinig item + // match on the first matching item if (isMatch(driverValue(item.value), driverValue(expression))) { for (final conditional in item.then) { conditional.execute(drivenSignals, guard); diff --git a/lib/src/modules/conditionals/conditional.dart b/lib/src/modules/conditionals/conditional.dart index c26a60b3a..beb87ebf5 100644 --- a/lib/src/modules/conditionals/conditional.dart +++ b/lib/src/modules/conditionals/conditional.dart @@ -131,7 +131,7 @@ abstract class Conditional { String verilogContents(int indent, Map inputsNameMap, Map outputsNameMap, String assignOperator); - /// Calculates an amount of padding to provie at the beginning of each new + /// Calculates an amount of padding to provide at the beginning of each new /// line based on [indent]. static String calcPadding(int indent) => List.filled(indent, ' ').join(); From 4aa2e4c2802167641e98fc59d491099165825f30 Mon Sep 17 00:00:00 2001 From: Max Korbel Date: Tue, 22 Apr 2025 20:36:27 -0700 Subject: [PATCH 02/11] wip alternative docs --- .../B02-comparisons-with-alternatives.md | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/doc/user_guide/_docs/B02-comparisons-with-alternatives.md b/doc/user_guide/_docs/B02-comparisons-with-alternatives.md index 1af3d0619..b555c9b1e 100644 --- a/doc/user_guide/_docs/B02-comparisons-with-alternatives.md +++ b/doc/user_guide/_docs/B02-comparisons-with-alternatives.md @@ -2,11 +2,11 @@ title: "Comparison with Alternatives" permalink: /docs/comparison-with-alternatives/ excerpt: "Comparison with Alternatives" -last_modified_at: 2024-01-04 +last_modified_at: 2025-03-19 toc: true --- -There are a lot of options for developing hardware. This section briefly discusses popular alternatives to ROHD and some of their strengths and weaknesses. +There are a lot of options for developing hardware. This section briefly discusses some popular alternatives to ROHD and some of their strengths and weaknesses. ### SystemVerilog @@ -15,26 +15,31 @@ SystemVerilog is the most popular HDL (hardware descriptive language). It is ba - SystemVerilog is old, verbose, and limited, which makes code more bug-prone - Integration of IPs at SOC level with SystemVerilog is very difficult and time-consuming. - Validation collateral is hard to develop, debug, share, and reuse when it is written in SystemVerilog. -- Building requires building packages with proper `include ordering based on dependencies, ordering of files read by compilers in .f files, correctly specifiying order of package and library dependencies, and correct analysis and elaboration options. This is an area that drains many engineers' time debugging. -- Build and simulation are dependent on expensive EDA vendor tools or incomplete open-source alternatives. Every tool has its own intricacies, dependencies, licensing, switches, etc. and different tools may synthesize or simulate the same code in a functionally inequivalent way. +- Building requires building packages and libraries with proper `include ordering based on dependencies, ordering of files read by compilers in .f files, correctly specifiying order of package and library dependencies, and correct analysis and elaboration options. This is an area that drains many engineers' time debugging. +- Build and simulation are dependent on expensive EDA vendor tools or incomplete open-source alternatives. Every tool has its own intricacies, dependencies, licensing, switches, etc. and different tools may synthesize or simulate the same code in a functionally different way. - Designing configurable and flexible modules in pure SystemVerilog usually requires parameterization, compile-time defines, and "generate" blocks, which can be challenging to use, difficult to debug, and restrictive on approaches. - - People often rely on perl scripts to bridge the gap for iteratively generating more complex hardware or stitching together large numbers of modules. -- Testbenches are, at the end of the day, software. SystemVerilog is arguably a terrible programming language, since it is primarily focused at hardware description, which makes developing testbenches excessively challenging. Basic software quality-of-life features are missing in SystemVerilog. + - Engineers often rely on perl or python scripts to bridge the gap for iteratively generating more complex hardware or stitching together large numbers of modules. +- Testbenches are, at the end of the day, software. SystemVerilog is arguably a poor programming language, since it is primarily focused at hardware description, which makes developing testbenches excessively challenging. Basic software quality-of-life features are missing in SystemVerilog. - Mitigating the problem by connecting to other languages through DPI calls (e.g. C++ or SystemC) has it's own complexities with extra header files, difficulty modelling parallel execution and edge events, passing callbacks, etc. - - UVM throws macros and boilerplate at the problem, which doesn't resolve the underlying limitations. + - [UVM](https://en.wikipedia.org/wiki/Universal_Verification_Methodology) throws macros and boilerplate at the problem, which doesn't resolve the underlying limitations. ROHD aims to enable all the best parts of SystemVerilog, while completely eliminating each of the above issues. Build is automatic and part of Dart, packages and files can just be imported as needed, no vendor tools are required, hardware can be constructed using all available software constructs, and Dart is a fully-featured modern software language with modern features. -You can read more about SystemVerilog here: +You can read more about SystemVerilog here: . + +VHDL is another of the most popular HDLs, with many similar characteristics to Verilog . ### Chisel Chisel is a domain specific language (DSL) built on top of [Scala](https://www.scala-lang.org/), which is built on top of the Java virtual machine (JVM). The goals of Chisel are somewhat aligned with the goals of ROHD. Chisel can also convert to SystemVerilog. - The syntax of Scala (and thus Chisel) is probably less familiar-feeling to most hardware engineers, and it can be more verbose than ROHD with Dart. -- Scala and the JVM are arguably less user friendly to debug than Dart code. +- Scala and the JVM are arguably less user-friendly to debug than Dart code. - Chisel is focused mostly on the hardware *designer* rather than the *validator*. Many of the design choices for the language are centered around making it easier to parameterize and synthesize logic. ROHD was created with validators in mind. - Chisel generates logic that's closer to a netlist than what a similar implementation in SystemVerilog would look like. This can make it difficult to debug or validate generated code. ROHD generates structurally similar SystemVerilog that looks close to how you might write it. +- Chisel does not have a native hardware simulator in the same way that ROHD does. A variety of simulation approaches exist for Chisel. Some operate on the intermediate representations between the source code into the compiler stack. Most teams rely on other simulators (e.g. Verilator) to simulate the generated SystemVerilog, which leaves validation to the most of the same problems as verifying any other SystemVerilog design. +- Chisel has some amount of code reflection, meaning the structure of the generator code you write in Chisel (e.g. variable names) has an impact on the generated output. Conversely, in ROHD, the Dart code written is completely independent of the model which the code generates. This means that sometimes simpler designs can be a little more succinct in Chisel, but ROHD excels at scaling configurability. +- Parameterization and configuration of hardware in Chisel is often determined prior to module construction, similar to how SystemVerilog does it. In ROHD, you can dynamically determine port widths, module contents, etc. based on introspecting the signals connected to it (or anything else). This provides a lot more flexibility and reusability for hardware developed with ROHD. Read more about Chisel here: @@ -43,8 +48,8 @@ Read more about Chisel here: There have been a number of attempts to create a HDL on top of Python, but it appears the MyHDL is one of the most mature options. MyHDL has many similar goals to ROHD, but chose to develop in Python instead of Dart. MyHDL can also convert to SystemVerilog. - MyHDL uses "generators" and decorators to help model concurrent behavior of hardware, which is arguably less user-friendly and intuitive than async/await and event based simulation in ROHD. -- While Python is a great programming langauge for the right purposes, some language features of Dart make it better for representing hardware. Above is already mentioned Dart's isolates and async/await, which don't exist in the same way in Python. Dart is statically typed with null safety while Python is dynamically typed, which can make static analysis (including intellisense, type safety, etc.) more challenging in Python. Python can also be challenging to scale to large programs without careful architecting. -- Python is inherently slower to execute than Dart. +- While Python is a great programming langauge for the right purposes, some language features of Dart make it better for representing hardware. Above is already mentioned Dart's asynchronous programming capabilities, which don't exist in the same way in Python. Dart is statically typed with null safety while Python is dynamically typed, which can make static analysis (including IDE integration, type safety, etc.) more challenging in Python. Python can also be challenging to scale to large programs without careful architecting. +- Python is generally slower to execute than Dart. - MyHDL has support for cosimulation via VPI calls to SystemVerilog simulators. Read more about MyHDL here: @@ -74,6 +79,7 @@ Read more about TL-Verilog here: PyMTL is another attempt at creating an HDL in Python. It is developed at Cornell University and the third version (PyMTL 3) is currently in Beta. PyMTL aims to resolve a lot of the same things as ROHD, but with Python. It supports conversion to SystemVerilog and simulation. - The Python language trade-offs described in the above section on MyHDL apply to PyMTL as well. +- The general approach is similar to Chisel, described above, but with Python. Read more about PyMTL here: or @@ -84,3 +90,12 @@ cocotb is a Python-based testbench framework for testing SystemVerilog and VHDL The cosimulation capabilities of cocotb are gratefully leveraged within the [ROHD Cosim](https://github.com/intel/rohd-cosim) package for cosimulation with SystemVerilog simulators. Read more about cocotb here: or + + +### Spade + +### PipelineC + +### Sus + +### DFiant HDL \ No newline at end of file From 0f08d73d3803e4efee5564ca9e64ed0b4eac07c6 Mon Sep 17 00:00:00 2001 From: Max Korbel Date: Wed, 23 Apr 2025 14:19:39 -0700 Subject: [PATCH 03/11] add some background on compiled vs generator --- .../_docs/B02-comparisons-with-alternatives.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/user_guide/_docs/B02-comparisons-with-alternatives.md b/doc/user_guide/_docs/B02-comparisons-with-alternatives.md index b555c9b1e..b539ee752 100644 --- a/doc/user_guide/_docs/B02-comparisons-with-alternatives.md +++ b/doc/user_guide/_docs/B02-comparisons-with-alternatives.md @@ -8,6 +8,16 @@ toc: true There are a lot of options for developing hardware. This section briefly discusses some popular alternatives to ROHD and some of their strengths and weaknesses. +There is a conceptual difference between a *compiled hardware language* and an *embedded generator framework*. ROHD falls in the latter category because it is embedded into a software language (Dart) and is fundamentally a package or library for modelling hardware, simulating it, and generating outputs (e.g. SystemVerilog). By contrast, compiled hardware languages (e.g. VHDL, SystemVerilog) are independent langauges, and a compiler stack reads the code and converts it into some synthesizable/simulatable representation. There are benefits and downsides to each approach, and some solutions are a mixture between these. + +- **Language expressiveness:** A compiled hardware language can add specific syntax that can make it easier and more natural to describe hardware, whereas an embedded framework would need to remain within the bounds of the programming language. However, compiled hardware languages can become limiting in their expressiveness, requiring additional language features to expand capabilities. Meanwhile, an embedded framework has the full software language available to control hardware construction. +- **Source alignment:** In a compiled language, it is reasonable to expect that the *names of variables* would have an impact on *generated outputs*. For example, if you name a `logic abc` for a register in SystemVerilog, you might reasonably expect a compiled netlist to still have that name `abc` somewhere in it. In a generator framework (with no [reflection](https://en.wikipedia.org/wiki/Reflective_programming)), you'd need to explicitly name a signal with a `String` for the name to show up in a generated output. The trade-off here is succinctness vs. flexibility. You can potentially write less repetitive code for simple descriptions in a compiled language, but you have greater flexibility and control in the generator framework for more configurable and complex designs. +- **Optimization and predictability:** A compiler can spend time optimizing/lowering a design which could potentially give you better outcomes in synthesis, simulation, etc. However, the more optimization there is, the harder it is to map results back to the original source code or predict how a change in the source will affect the output. For at least the near future, many engineers are still concerned with inspecting the generated outputs, so readability is important. More importantly, in ASIC development just before tape-out, there may be tiny bug fixes needed to the design that are done by hand rather than with full re-synthesis. If a small change in the source code can have a large or unpredictable set of changes in the final hardware, then these small manual edits become impossible. Additionally, a lot of the optimization for simulation and synthesis in standard EDA tools, once it's in SystemVerilog, is optimized for non-bit-blasted representations. Most compiler stacks are not producing good enough optimizations to outperform what those standard EDA tools already do, so the optimizations may not be adding a lot of value. +- **Algorithm Abstraction**: Some compiled languages (e.g. High-Level Synthesis) actually compile some algorithmic intent and constraints into a performant implementation, for example with automatic pipelining. In practice, this kind of approach requires re-validating the generated outputs since that's where the actual cycle-accurate hardware exists. Generator frameworks, by contrast, achieve abstraction via composition: automating the way you compose and construct pieces of hardware provides a layer of abstraction for building more complex designs. The generator framework approach grounds the designer in a hardware mindset instead of a more detached algorithmic one. +- **Determination of synthesizability:** Compiled languages usually still have a capability of doing some "generation" or parameterization that do not represent actual hardware operations (e.g. `generate` in SystemVerilog). They also might have pure-software constructs for verification purposes that are neither synthesizable nor generation-time compatible (e.g. SystemVerilog classes). This can create a blurry barrier for developers where it's unclear which language constructs can be used to represent or control generation of hardware, and which ones are non-synthesizable. A generator framework can eliminate such blurriness: hardware objects represent hardware, and software constructs used to generate those objects do not. +- **Automation Development:** In a compiled language, developing a new EDA tool often requires either/both parsing the language and/or generating the language. This is a substantial barrier for tool development. Even more concerning is that any new language advancement can only be leveraged once all required tools are able to handle it. This is a serious problem that often forces engineers to leverage only the subset of language features which all tools support. This also instills an aversion in developers to use new language features since things may work initially in one context, but then a tool incompatibility downstream may force a rewrite later. By contrast, a generator language can *reduce* barriers to EDA development since the object model already exists and generation is already handled. +- **Ecosystem:** A development ecosystem with editors, static analysis tools, reusable packages, documentation, and community is extremely valuable. Building a thriving ecosystem is very difficult, and the relative size of the hardware development community compared to that of software development only makes this more challenging. Even industry standards like SystemVerilog and VHDL have a very limited ecosystem (compared to Python, Dart, etc.). While compiled languages are on their own, embedded frameworks instantly gain the ecosystem of the underlying language, which is a huge advantage. + ### SystemVerilog SystemVerilog is the most popular HDL (hardware descriptive language). It is based on Verilog, with additional software-like constructs added on top of it. Some major drawbacks of SystemVerilog are: From e8388c50a933b108f27d26677d476b6108e6dccd Mon Sep 17 00:00:00 2001 From: Max Korbel Date: Wed, 7 May 2025 11:24:57 -0700 Subject: [PATCH 04/11] more langs --- doc/user_guide/_docs/B02-comparisons-with-alternatives.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/user_guide/_docs/B02-comparisons-with-alternatives.md b/doc/user_guide/_docs/B02-comparisons-with-alternatives.md index b539ee752..1a83d26df 100644 --- a/doc/user_guide/_docs/B02-comparisons-with-alternatives.md +++ b/doc/user_guide/_docs/B02-comparisons-with-alternatives.md @@ -108,4 +108,10 @@ Read more about cocotb here: or Date: Wed, 7 May 2025 13:18:35 -0700 Subject: [PATCH 05/11] update a bit about why dart --- doc/user_guide/_get-started/01-overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user_guide/_get-started/01-overview.md b/doc/user_guide/_get-started/01-overview.md index 9220633f1..ad3de9e97 100644 --- a/doc/user_guide/_get-started/01-overview.md +++ b/doc/user_guide/_get-started/01-overview.md @@ -40,9 +40,9 @@ One of ROHD's goals is to help grow an open-source community around reusable har ## Why Dart? -Dart is a modern, relatively new language developed by Google. It is designed with client-side application development in mind (e.g. apps and websites), but also has great performance for general tasks. It adopts some of the most loved syntax and features from languages like C++, Java, C#, JavaScript/TypeScript, and Kotlin. Dart is extremely user-friendly, fun to use, and **easy to learn**. The excellent, fast static analysis with a modern IDE with autocomplete makes it easy to learn as you work. Dart has a lot of great modern language features, including null safety. +[Dart](https://dart.dev/) is a modern, relatively new, [extremely popular](https://survey.stackoverflow.co/2024/technology#most-popular-technologies) ([top-20](https://redmonk.com/sogrady/2024/09/12/language-rankings-6-24/)) language developed by Google. It is designed with client-side application development in mind (e.g. apps and websites), but also has great performance for general tasks. It adopts some of the most loved syntax and features from languages like C++, Java, C#, JavaScript/TypeScript, and Kotlin. Dart is extremely user-friendly, fun to use, and [**easy to learn** with **excellent documentation**](https://dart.dev/language). The excellent, fast static analysis with a modern IDE with autocomplete makes it easy to learn as you work. Dart has a lot of great modern language features, including null safety. -Because it is designed with asynchronous requests in mind (i.e. sending a request to a server and not freezing the application while it waits for a response), Dart has `async`/`await` and `Future`s built in, with [concurrent programming](https://dart.dev/language/concurrency). These constructs enable code to execute in parallel without multithreading. These chacteristics make modelling hardware very easy. +Because it is designed with asynchronous requests in mind (i.e. sending a request to a server and not freezing the application while it waits for a response), Dart has `async`/`await` and `Future`s built in, with [concurrent programming](https://dart.dev/language/concurrency). These constructs enable code to execute in parallel without multithreading. These characteristics make modelling, interacting with, and verifying hardware very easy. Dart can compile to native machine code, but also includes its own high-performance VM and a JIT compiler. During development, you can use a feature called "hot reload" to change code while the program is actively executing. From a0185e0535ee4dc2dbf86893ce77b9da7222fad3 Mon Sep 17 00:00:00 2001 From: Max Korbel Date: Tue, 27 May 2025 15:43:53 -0700 Subject: [PATCH 06/11] fix tutorial typo in iff and elseif --- .../chapter_6/00_combinational_logic.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/tutorials/chapter_6/00_combinational_logic.md b/doc/tutorials/chapter_6/00_combinational_logic.md index 2b6cbf8f5..fa40c34a8 100644 --- a/doc/tutorials/chapter_6/00_combinational_logic.md +++ b/doc/tutorials/chapter_6/00_combinational_logic.md @@ -85,39 +85,39 @@ If.block([ ### Add the condition inside the conditional Block -`Iff(condition, then: [])`: `Iff` Statement, if condition is matched, then execute the `then` condition. +`Iff(condition, [])`: `Iff` Statement, if condition is matched, then execute the `then` condition. ```dart // template If.block([ - Iff(condition, then: [ + Iff(condition, [ // You can wrap condition here ]), ]); // If.block // example If.block([ - Iff(a.eq(0), then: [ + Iff(a.eq(0), [ sum < 0 ]), ]); // If.block ``` -`ElseIf(condition, then: [])`: `ElseIf` Statement, if the condition in `Iff` is not matched, its will skip and look for next condition in `ElseIf` condition, then execute the `then`. +`ElseIf(condition, [])`: `ElseIf` Statement, if the condition in `Iff` is not matched, its will skip and look for next condition in `ElseIf` condition, then execute the `then`. ```dart // template If.block([ - Iff(condition, then: []), // If statement - ElseIf(condition, then: []) // Else If Statement + Iff(condition, []), // If statement + ElseIf(condition, []) // Else If Statement ]); // If.block // example If.block([ - Iff(a.eq(0), then: [ + Iff(a.eq(0), [ sum < 1 ]), // If statement - ElseIf(b.eq(0), then: [ + ElseIf(b.eq(0), [ sum < 0 ]) // Else If Statement ]); // If.block @@ -127,17 +127,17 @@ If.block([ ```dart If.block([ - Iff(condition, then: []), // If statement - ElseIf(condition, then: []), // Else If Statement + Iff(condition, []), // If statement + ElseIf(condition, []), // Else If Statement Else([]) // execute this ]); // If.block // example If.block([ - Iff(a.eq(0), then: [ + Iff(a.eq(0), [ sum < 0 ]), // If statement - ElseIf(b.eq(0), then: [ + ElseIf(b.eq(0), [ sum < 1 ]), // Else If Statement Else([ From b43e5a89ca4ce39f3e4de28105be6bde796a8b8e Mon Sep 17 00:00:00 2001 From: Max Korbel Date: Tue, 27 May 2025 15:44:42 -0700 Subject: [PATCH 07/11] clarify bus ranges and swizzling docs --- doc/user_guide/_docs/A07-bus-ranges-and-swizzling.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user_guide/_docs/A07-bus-ranges-and-swizzling.md b/doc/user_guide/_docs/A07-bus-ranges-and-swizzling.md index 3b89edb3f..aebc50125 100644 --- a/doc/user_guide/_docs/A07-bus-ranges-and-swizzling.md +++ b/doc/user_guide/_docs/A07-bus-ranges-and-swizzling.md @@ -16,10 +16,10 @@ var a = Logic(width:8), e = Logic(width: 9); -// assign b to the bottom 3 bits of a +// assign b to be driven by the bottom 3 bits of a b <= a.slice(2,0); -// assign d to the top bit of a +// assign d to be driven by the top bit of a d <= a[7]; // construct e by swizzling bits from b, c, and d From 63233b5ff39d4f54e47f4d989f0b45bbc3ffd9d3 Mon Sep 17 00:00:00 2001 From: Max Korbel Date: Tue, 27 May 2025 15:48:51 -0700 Subject: [PATCH 08/11] fix typo in exception message --- lib/src/exceptions/module/port_rules_violation_exception.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/exceptions/module/port_rules_violation_exception.dart b/lib/src/exceptions/module/port_rules_violation_exception.dart index 29e5f2ab7..f1db83f56 100644 --- a/lib/src/exceptions/module/port_rules_violation_exception.dart +++ b/lib/src/exceptions/module/port_rules_violation_exception.dart @@ -23,7 +23,7 @@ class PortRulesViolationException extends RohdException { ' in module $module on signal $signal.' ' Logic within a Module should only communicate outside of itself' ' by consuming inputs/inouts and' - ' driving outputs/inouts of that itself.' + ' driving outputs/inouts of itself.' ' See https://intel.github.io/rohd-website/docs/modules/' ' for more information. $additionalMessage'); From 621efaa9753b2cc696063d1dbdd11862aa0a57aa Mon Sep 17 00:00:00 2001 From: Max Korbel Date: Mon, 2 Jun 2025 11:24:43 -0700 Subject: [PATCH 09/11] remove pin for dart doc bug --- .github/workflows/general.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/general.yml b/.github/workflows/general.yml index cffbcbf1f..48215e8e1 100644 --- a/.github/workflows/general.yml +++ b/.github/workflows/general.yml @@ -34,8 +34,6 @@ jobs: - name: Setup Dart uses: dart-lang/setup-dart@v1 - with: - sdk: 3.6.2 # downgrade pending https://github.com/dart-lang/dartdoc/issues/3996 - name: Setup Node uses: actions/setup-node@v4 From 4d9f50888a8d5d055005f779b53c9982e74d0f78 Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Fri, 17 Jul 2026 10:58:32 -0700 Subject: [PATCH 10/11] updates and wrapping up these doc updates --- .../B02-comparisons-with-alternatives.md | 175 ++++++++++++------ doc/user_guide/_get-started/01-overview.md | 45 +++-- 2 files changed, 142 insertions(+), 78 deletions(-) diff --git a/doc/user_guide/_docs/B02-comparisons-with-alternatives.md b/doc/user_guide/_docs/B02-comparisons-with-alternatives.md index c882b7e8a..60874aad3 100644 --- a/doc/user_guide/_docs/B02-comparisons-with-alternatives.md +++ b/doc/user_guide/_docs/B02-comparisons-with-alternatives.md @@ -2,116 +2,171 @@ title: "Comparison with Alternatives" permalink: /docs/comparison-with-alternatives/ excerpt: "Comparison with Alternatives" -last_modified_at: 2025-03-19 +last_modified_at: 2026-07-17 toc: true --- -There are a lot of options for developing hardware. This section briefly discusses some popular alternatives to ROHD and some of their strengths and weaknesses. +There are a lot of options for developing hardware. This section briefly discusses some popular alternatives to ROHD and some of their strengths and weaknesses. It is not intended to be an exhaustive list or a ranking; each approach makes different trade-offs, and these projects continue to evolve. -There is a conceptual difference between a *compiled hardware language* and an *embedded generator framework*. ROHD falls in the latter category because it is embedded into a software language (Dart) and is fundamentally a package or library for modelling hardware, simulating it, and generating outputs (e.g. SystemVerilog). By contrast, compiled hardware languages (e.g. VHDL, SystemVerilog) are independent langauges, and a compiler stack reads the code and converts it into some synthesizable/simulatable representation. There are benefits and downsides to each approach, and some solutions are a mixture between these. +There is a conceptual difference between a *compiled hardware language* and an *embedded generator framework*. ROHD falls in the latter category: it is a Dart package for constructing and simulating a hardware model and generating outputs such as SystemVerilog. By contrast, a compiled hardware language has its own syntax and compiler. These are not rigid categories; many tools combine a host language, hardware-specific compiler passes, intermediate representations, and external simulators. -- **Language expressiveness:** A compiled hardware language can add specific syntax that can make it easier and more natural to describe hardware, whereas an embedded framework would need to remain within the bounds of the programming language. However, compiled hardware languages can become limiting in their expressiveness, requiring additional language features to expand capabilities. Meanwhile, an embedded framework has the full software language available to control hardware construction. -- **Source alignment:** In a compiled language, it is reasonable to expect that the *names of variables* would have an impact on *generated outputs*. For example, if you name a `logic abc` for a register in SystemVerilog, you might reasonably expect a compiled netlist to still have that name `abc` somewhere in it. In a generator framework (with no [reflection](https://en.wikipedia.org/wiki/Reflective_programming)), you'd need to explicitly name a signal with a `String` for the name to show up in a generated output. The trade-off here is succinctness vs. flexibility. You can potentially write less repetitive code for simple descriptions in a compiled language, but you have greater flexibility and control in the generator framework for more configurable and complex designs. -- **Optimization and predictability:** A compiler can spend time optimizing/lowering a design which could potentially give you better outcomes in synthesis, simulation, etc. However, the more optimization there is, the harder it is to map results back to the original source code or predict how a change in the source will affect the output. For at least the near future, many engineers are still concerned with inspecting the generated outputs, so readability is important. More importantly, in ASIC development just before tape-out, there may be tiny bug fixes needed to the design that are done by hand rather than with full re-synthesis. If a small change in the source code can have a large or unpredictable set of changes in the final hardware, then these small manual edits become impossible. Additionally, a lot of the optimization for simulation and synthesis in standard EDA tools, once it's in SystemVerilog, is optimized for non-bit-blasted representations. Most compiler stacks are not producing good enough optimizations to outperform what those standard EDA tools already do, so the optimizations may not be adding a lot of value. -- **Algorithm Abstraction**: Some compiled languages (e.g. High-Level Synthesis) actually compile some algorithmic intent and constraints into a performant implementation, for example with automatic pipelining. In practice, this kind of approach requires re-validating the generated outputs since that's where the actual cycle-accurate hardware exists. Generator frameworks, by contrast, achieve abstraction via composition: automating the way you compose and construct pieces of hardware provides a layer of abstraction for building more complex designs. The generator framework approach grounds the designer in a hardware mindset instead of a more detached algorithmic one. -- **Determination of synthesizability:** Compiled languages usually still have a capability of doing some "generation" or parameterization that do not represent actual hardware operations (e.g. `generate` in SystemVerilog). They also might have pure-software constructs for verification purposes that are neither synthesizable nor generation-time compatible (e.g. SystemVerilog classes). This can create a blurry barrier for developers where it's unclear which language constructs can be used to represent or control generation of hardware, and which ones are non-synthesizable. A generator framework can eliminate such blurriness: hardware objects represent hardware, and software constructs used to generate those objects do not. -- **Automation Development:** In a compiled language, developing a new EDA tool often requires either/both parsing the language and/or generating the language. This is a substantial barrier for tool development. Even more concerning is that any new language advancement can only be leveraged once all required tools are able to handle it. This is a serious problem that often forces engineers to leverage only the subset of language features which all tools support. This also instills an aversion in developers to use new language features since things may work initially in one context, but then a tool incompatibility downstream may force a rewrite later. By contrast, a generator language can *reduce* barriers to EDA development since the object model already exists and generation is already handled. -- **Ecosystem:** A development ecosystem with editors, static analysis tools, reusable packages, documentation, and community is extremely valuable. Building a thriving ecosystem is very difficult, and the relative size of the hardware development community compared to that of software development only makes this more challenging. Even industry standards like SystemVerilog and VHDL have a very limited ecosystem (compared to Python, Dart, etc.). While compiled languages are on their own, embedded frameworks instantly gain the ecosystem of the underlying language, which is a huge advantage. +- **Language expressiveness:** A purpose-built language can provide concise, hardware-specific syntax and enforce hardware-specific rules. An embedded framework stays within the syntax of its host language, but can use that language's metaprogramming, libraries, and tooling to control hardware construction. +- **Source alignment:** A compiler can preserve source names and locations in generated RTL, although optimization may transform them. An embedded framework cannot necessarily infer the names of host-language variables. ROHD therefore names hardware objects explicitly, keeping the Dart program independent from the object model it constructs. This trades some convenience in simple code for explicit control in highly configurable generators. +- **Optimization and predictability:** Lowering and optimization can improve generated RTL or enable higher-level abstractions, but can also make the output less recognizable and changes less predictable. Downstream synthesis tools already perform extensive optimization, so a front end must balance additional transformations against source mapping and readability. ROHD favors structurally recognizable output and mechanical simplifications over architectural optimization. +- **Algorithm abstraction:** HLS and some compiler-based languages derive scheduling, pipelining, resource sharing, or other microarchitectural decisions from higher-level intent and constraints. That can make design-space exploration much faster, but the resulting cycle-level implementation is partly a compiler decision. ROHD generally keeps those decisions explicit and builds abstraction through composition of hardware objects. +- **Determination of synthesizability:** Traditional HDLs can contain elaboration-time constructs, synthesizable RTL, and verification-only behavior in the same language. Tool support and synthesizable subsets can vary. ROHD separates Dart code that constructs hardware from the hardware objects themselves, making the boundary clearer, although users can still deliberately integrate custom SystemVerilog and non-synthesizable models. +- **Automation development:** Building an EDA tool around a source language often requires parsing that language, integrating with a compiler or intermediate representation, and generating an output format. Shared infrastructure such as CIRCT can reduce that burden. ROHD takes another approach: after a design is built, its modules, signals, hierarchy, and connectivity are available directly as a native Dart object model. A developer can write analyses, design checks, visualizations, or other hardware automation using normal Dart code without first parsing SystemVerilog. Since ROHD also handles SystemVerilog generation, new automation can focus on its hardware-specific purpose and still produce RTL for existing downstream flows. This substantially lowers the barrier for users to create their own EDA tooling. +- **Ecosystem:** Editors, static analysis, reusable packages, documentation, and community are extremely valuable. An embedded framework immediately gains much of its host language's ecosystem, although hardware-specific tooling still has to be built. A purpose-built language starts with less general tooling but can offer deeper hardware-aware diagnostics and editor features. -### SystemVerilog +## SystemVerilog -SystemVerilog is the most popular HDL (hardware descriptive language). It is based on Verilog, with additional software-like constructs added on top of it. Some major drawbacks of SystemVerilog are: +SystemVerilog is the dominant industry-standard language for digital hardware design and verification. The IEEE standard covers behavioral, RTL, and gate-level modeling as well as assertions, coverage, object-oriented programming, and constrained-random verification. Its broad vendor support, existing IP, and mature verification ecosystem are major strengths. Relative to ROHD, some trade-offs are: -- SystemVerilog is old, verbose, and limited, which makes code more bug-prone -- Integration of IPs at SOC level with SystemVerilog is very difficult and time-consuming. -- Validation collateral is hard to develop, debug, share, and reuse when it is written in SystemVerilog. -- Building requires building packages and libraries with proper `include ordering based on dependencies, ordering of files read by compilers in .f files, correctly specifiying order of package and library dependencies, and correct analysis and elaboration options. This is an area that drains many engineers' time debugging. -- Build and simulation are dependent on expensive EDA vendor tools or incomplete open-source alternatives. Every tool has its own intricacies, dependencies, licensing, switches, etc. and different tools may synthesize or simulate the same code in a functionally different way. -- Designing configurable and flexible modules in pure SystemVerilog usually requires parameterization, compile-time defines, and "generate" blocks, which can be challenging to use, difficult to debug, and restrictive on approaches. - - Engineers often rely on perl or python scripts to bridge the gap for iteratively generating more complex hardware or stitching together large numbers of modules. -- Testbenches are, at the end of the day, software. SystemVerilog is arguably a poor programming language, since it is primarily focused at hardware description, which makes developing testbenches excessively challenging. Basic software quality-of-life features are missing in SystemVerilog. - - Mitigating the problem by connecting to other languages through DPI calls (e.g. C++ or SystemC) has it's own complexities with extra header files, difficulty modelling parallel execution and edge events, passing callbacks, etc. - - [UVM](https://en.wikipedia.org/wiki/Universal_Verification_Methodology) throws macros and boilerplate at the problem, which doesn't resolve the underlying limitations. +- SystemVerilog is a large language with decades of accumulated features. Synthesizable subsets and support for newer constructs vary across tools. +- RTL authors must reason about details such as blocking versus non-blocking assignments, implicit widths and signedness, sensitivity and scheduling semantics, and nets versus variables. These distinctions are powerful, but mistakes can be subtle. +- Multi-file builds may require explicit package, library, include, and file ordering plus tool-specific analysis and elaboration options. +- Parameterization, `generate` constructs, macros, and interfaces support reusable RTL, but complex generation and integration often lead teams to add scripts or other tooling around the language. +- SystemVerilog has capable verification features, including assertions, constrained randomization, functional coverage, classes, and UVM. Large class-based environments can also become verbose and require substantial methodology and tooling expertise. +- Commercial tools provide the broadest language and methodology support. Open-source support continues to improve, but supported subsets and behavior still vary between tools. -ROHD aims to enable all the best parts of SystemVerilog, while completely eliminating each of the above issues. Build is automatic and part of Dart, packages and files can just be imported as needed, no vendor tools are required, hardware can be constructed using all available software constructs, and Dart is a fully-featured modern software language with modern features. +ROHD takes a different front-end approach while retaining SystemVerilog as an integration format. Hardware generation and testbench code use Dart, ROHD simulation and generation do not require a vendor tool, and generated RTL can enter the same lint, simulation, synthesis, and implementation flows as hand-written SystemVerilog. -You can read more about SystemVerilog here: . +You can read more in the [IEEE 1800-2023 SystemVerilog standard overview](https://standards.ieee.org/ieee/1800/7743/) or on Wikipedia at . VHDL is another of the most popular HDLs, with many similar characteristics to Verilog . -### Chisel +## Chisel -Chisel is a domain specific language (DSL) built on top of [Scala](https://www.scala-lang.org/), which is built on top of the Java virtual machine (JVM). The goals of Chisel are somewhat aligned with the goals of ROHD. Chisel can also convert to SystemVerilog. +Chisel (Constructing Hardware in a Scala Embedded Language) is a hardware construction language embedded in [Scala](https://www.scala-lang.org/). A Scala program elaborates a hardware graph, which is lowered through FIRRTL and CIRCT to SystemVerilog. Its goals overlap substantially with ROHD's. -- The syntax of Scala (and thus Chisel) is probably less familiar-feeling to most hardware engineers, and it can be more verbose than ROHD with Dart. -- Scala and the JVM are arguably less user-friendly to debug than Dart code. -- Chisel is focused mostly on the hardware *designer* rather than the *validator*. Many of the design choices for the language are centered around making it easier to parameterize and synthesize logic. ROHD was created with validators in mind. -- Chisel generates logic that's closer to a netlist than what a similar implementation in SystemVerilog would look like. This can make it difficult to debug or validate generated code. ROHD generates structurally similar SystemVerilog that looks close to how you might write it. -- Chisel does not have a native hardware simulator in the same way that ROHD does. A variety of simulation approaches exist for Chisel. Some operate on the intermediate representations between the source code into the compiler stack. Most teams rely on other simulators (e.g. Verilator) to simulate the generated SystemVerilog, which leaves validation to the most of the same problems as verifying any other SystemVerilog design. -- Chisel has some amount of code reflection, meaning the structure of the generator code you write in Chisel (e.g. variable names) has an impact on the generated output. Conversely, in ROHD, the Dart code written is completely independent of the model which the code generates. This means that sometimes simpler designs can be a little more succinct in Chisel, but ROHD excels at scaling configurability. -- Parameterization and configuration of hardware in Chisel is often determined prior to module construction, similar to how SystemVerilog does it. In ROHD, you can dynamically determine port widths, module contents, etc. based on introspecting the signals connected to it (or anything else). This provides a lot more flexibility and reusability for hardware developed with ROHD. +- Both projects use a general-purpose, statically typed host language for parameterization and hardware construction. The choice between Scala/JVM and Dart brings different syntax, build systems, libraries, and debugging experiences. +- Scala and its functional programming style are less familiar to many hardware engineers than C-style imperative languages. Productive Chisel can also involve Scala-specific concepts such as implicits or givens, type-level programming, higher-order functions, and extensive operator overloading. Developers must distinguish Scala constructs that execute during elaboration from Chisel constructs that the DSL and compiler interpret as hardware. ROHD never converts a Dart language semantic into hardware: Dart executes as ordinary software and constructs explicit hardware objects, and only those objects are converted to RTL. Dart control flow can determine which objects are constructed, but Dart variables, statements, and classes do not themselves acquire hardware meaning. +- A common complaint about Chisel is that the Scala/JVM toolchain can feel heavy and less approachable. Build configuration, dependency and version compatibility, compiler plugins, and startup time add friction, while debugging may cross Scala elaboration, FIRRTL/CIRCT lowering, generated SystemVerilog, and an external simulator. ROHD's Dart toolchain and more direct generation path generally provide a simpler development and debugging workflow. +- Modern Chisel uses a Scala compiler plugin to capture source-level information such as many `val` names and propagate it into generated hardware. This can make simple code more concise, but it also means that aspects of the Scala source affect the hardware model and generated output. ROHD instead keeps Dart source semantics separate from the object model and names hardware objects explicitly. +- Chisel's compiler stack performs lowering and optimization through intermediate representations. This enables powerful transformations, but generated SystemVerilog can be less structurally aligned with the source than ROHD's more direct output. CIRCT provides options to tune Chisel's emission style. +- Chisel provides first-party ChiselSim APIs for stimulus and checking, but ChiselSim requires a compatible external simulator such as Verilator or VCS. ROHD includes its event-driven simulator directly in the package. +- Both systems elaborate configuration using their host language. Chisel commonly passes Scala parameters into module construction; ROHD can also derive configuration from `Logic` objects connected during construction. Read more about Chisel here: -### MyHDL (Python) +## MyHDL (Python) -There have been a number of attempts to create a HDL on top of Python, but it appears the MyHDL is one of the most mature options. MyHDL has many similar goals to ROHD, but chose to develop in Python instead of Dart. MyHDL can also convert to SystemVerilog. +MyHDL is a long-running Python package for hardware modeling, simulation, and conversion. Hardware blocks are Python functions, and decorators create concurrent generator processes. Subject to a convertible subset, MyHDL emits Verilog or VHDL. -- MyHDL uses "generators" and decorators to help model concurrent behavior of hardware, which is arguably less user-friendly and intuitive than async/await and event based simulation in ROHD. -- While Python is a great programming language for the right purposes, some language features of Dart make it better for representing hardware. Above is already mentioned Dart's asynchronous programming capabilities, which don't exist in the same way in Python. Dart is statically typed with null safety while Python is dynamically typed, which can make static analysis (including IDE integration, type safety, etc.) more challenging in Python. Python can also be challenging to scale to large programs without careful architecting. -- Python is generally slower to execute than Dart. -- MyHDL has support for cosimulation via VPI calls to SystemVerilog simulators. +- MyHDL and ROHD both use a general-purpose host language for elaboration and include a simulator. MyHDL models hardware processes with Python generators, decorators, and `Signal.next`; ROHD constructs an object graph and uses Dart events, `Future`s, and `async`/`await` for testbench interaction. +- Modern Python also supports `async`/`await`, but MyHDL's hardware process API predates those features and remains generator-based. +- Dart's static type system and null safety provide stronger compile-time checking and IDE inference by default than dynamically typed Python. Python offers a much larger package ecosystem and broad familiarity. +- For work that executes in the host language, such as elaboration and built-in simulation, the standard CPython interpreter generally runs pure Python more slowly than Dart's JIT- or AOT-compiled runtime. That difference can become significant as generators and testbenches scale. Python flows can move performance-critical work into native extensions or external HDL simulators, so it does not imply that every Python-based hardware flow is slower end to end. +- MyHDL's conversion output is normally flattened, while ROHD generally preserves module hierarchy in generated SystemVerilog. +- MyHDL can co-simulate passive Verilog through simulator-specific PLI modules, including VPI integration for Icarus Verilog. ROHD Cosim supports integration with external SystemVerilog simulators separately from ROHD's built-in simulation. Read more about MyHDL here: -### High-Level Synthesis (HLS) +## High-Level Synthesis (HLS) -High-Level Synthesis (HLS) uses a subset of C++ and SystemC to describe algorithms and functionality, which EDA vendor tools can compile into SystemVerilog. The real strength of HLS is that it enables design exploration to optimize a higher-level functional intent for area, power, and/or performance through proper staging and knowledge of the characteristics of the targeted process. +High-Level Synthesis (HLS) derives an RTL implementation from a higher-level algorithmic model. Commercial tools commonly accept C, C++, or SystemC, while research tools also use domain-specific languages and intermediate representations. The compiler schedules operations, chooses clock-cycle boundaries, allocates or shares resources, structures memories, and emits RTL such as Verilog or VHDL. -- HLS is a step above/away from RTL-level modelling, which is a strength in some situations but might not be the right level in others. -- HLS uses C++/SystemC, which is arguably a less "friendly" language to use than Dart. +- HLS can explore many implementations of an algorithm against area, power, performance, latency, and throughput goals much faster than implementing each candidate by hand. +- The trade-off is that important microarchitectural decisions are made jointly by source code, constraints, directives, and the compiler. Understanding cycle behavior and achieving a specific structure can require familiarity with that tool's scheduling and cost model. +- C and C++ are familiar, but they are not especially user-friendly hardware modeling languages. Their low-level type and memory semantics, undefined behavior, templates, build systems, and often difficult diagnostics remain, while an HLS tool accepts only particular coding patterns plus tool-specific constraints and directives. SystemC adds hardware concepts, but also adds a class- and template-heavy library and its own simulation semantics. Dart and ROHD provide a more modern language, stronger default safety, and a hardware-focused API without pretending that ordinary software code is hardware. +- HLS is strongest for self-contained computational kernels. Integration into a real design often requires exact control of ports, individual wires, clocks and resets, protocols, memories, existing IP, and hierarchy. Many HLS flows expose those details through interface synthesis, prescribed protocols, pragmas, or tool-specific wrappers rather than a natural, general wire-level composition model. Designers commonly have to drop the generated kernel into a conventional RTL environment to assemble the complete system. +- ROHD works at the RTL construction level: designers normally choose state, resources, cycle boundaries, ports, and connectivity explicitly, while reusable generators automate composition. It can therefore express both detailed wire-level integration and higher-level reusable structure in the same object model. Read more about one example of an HLS tool (Cadence's Stratus tool) here: There are a number of other attempts to make HLS better, including [XLS](https://github.com/google/xls) and [Dahlia](https://capra.cs.cornell.edu/dahlia/) & [Calyx](https://capra.cs.cornell.edu/calyx/). There are discussions on ways to reasonably incorporate some of the strengths of HLS approaches into ROHD. -### Transaction Level Verilog (TL-Verilog) +## CIRCT -Transaction Level Verilog (TL-Verilog) is like an extension on top of SystemVerilog that makes pipelining simpler and more concise. +CIRCT (Circuit IR Compilers and Tools) is not primarily an end-user hardware language. It is an open-source compiler infrastructure project that applies LLVM and MLIR techniques to hardware design. CIRCT provides reusable intermediate-representation dialects, transformations, analyses, and Verilog/SystemVerilog emission across abstractions including RTL, finite-state machines, pipelines, dataflow, and verification. -- TL-Verilog makes RTL design easier, especially when pipelining, but doesn't really add much in terms of verification -- ROHD also supports a [pipelining abstraction](https://intel.github.io/rohd-website/docs/pipelines/). +- CIRCT is most directly useful to authors of hardware languages and EDA tools. For example, its `firtool` lowers the FIRRTL produced by Chisel into SystemVerilog. +- Its shared infrastructure can reduce the cost of building a new language or flow and provides configurable lowering for the differing capabilities and lint rules of downstream tools. +- ROHD is an end-user Dart framework with its own object model, simulator, and SystemVerilog generator. CIRCT operates lower in the tool stack, so the projects are more complementary than direct substitutes. + +Read more about CIRCT here: . + +## Transaction Level Verilog (TL-Verilog) + +Transaction-Level Verilog (TL-Verilog) introduces new syntax for pipelines, transactions, validity, hierarchy, and state on top of a Verilog workflow. In practical terms, SandPiper acts as a source-to-source compiler or sophisticated preprocessor: it expands TL-Verilog constructs, including implied pipeline registers, into ordinary Verilog or SystemVerilog for standard downstream tools. TL-Verilog files can also contain regions of raw SystemVerilog. + +- TL-Verilog makes timing changes and pipeline alignment more concise by keeping signals in a pipeline context. Makerchip integrates compilation, simulation, diagrams, and organized waveforms for design and debug. +- The trade-off is adopting another language syntax and making SandPiper part of the build flow. The generated RTL remains compatible with existing tools, but the concise source is not itself standard SystemVerilog. +- ROHD also supports a [pipelining abstraction](https://intel.github.io/rohd-website/docs/pipelines/), but uses Dart objects and composition rather than adding purpose-built syntax to Verilog. Read more about TL-Verilog here: -### PyMTL +## PyMTL -PyMTL is another attempt at creating an HDL in Python. It is developed at Cornell University and the third version (PyMTL 3) is currently in Beta. PyMTL aims to resolve a lot of the same things as ROHD, but with Python. It supports conversion to SystemVerilog and simulation. +PyMTL 3 is an open-source Python framework for hardware generation, simulation, and verification developed at Cornell. It supports multiple modeling levels, including functional, cycle-level, RTL, and imported Verilog components. Its current project README still describes version 3 as beta software under active development. -- The Python language trade-offs described in the above section on MyHDL apply to PyMTL as well. -- The general approach is similar to Chisel, described above, but with Python. +- PyMTL and ROHD both aim to keep generation, simulation, and verification in one environment rather than treating the HDL generator as an isolated front end. +- PyMTL emphasizes multi-level modeling and Python interoperability, with passes for Verilog translation and Verilator-backed integration. ROHD uses Dart, includes four-state event-driven simulation, and emits SystemVerilog. +- The static-versus-dynamic typing trade-offs discussed for MyHDL also apply, while Python offers a larger existing scientific and verification ecosystem. Read more about PyMTL here: or -### cocotb +## cocotb -cocotb is a Python-based testbench framework for testing SystemVerilog and VHDL designs. It makes no attempt to represent hardware or create a simulator, but rather connects to other hardware simulators via things like VPI calls. +cocotb is a Python coroutine-based cosimulation testbench framework for verifying VHDL and SystemVerilog RTL. It is not a hardware generator framework and does not provide the HDL simulator itself. Instead, it controls a supported simulator through interfaces such as VPI, VHPI, or FLI and lets tests drive and inspect the design from Python. The cosimulation capabilities of cocotb are gratefully leveraged within the [ROHD Cosim](https://github.com/intel/rohd-cosim) package for cosimulation with SystemVerilog simulators. Read more about cocotb here: or +## Spade + +Spade is a compiled RTL hardware description language inspired by modern software languages. It has a strong type system, first-class pipelines with compiler-checked latency, dedicated editor and build tooling, and Verilog output. + +- Spade and ROHD both work at RTL and emphasize predictable hardware with explicit control rather than using HLS to infer a microarchitecture. +- Spade does not prioritize human-readable generated Verilog. Its documented goal is instead a clear two-way mapping between source signal names and generated names for waveforms and tooling. ROHD places more emphasis on human-readable, structurally similar generated SystemVerilog that can be inspected and debugged directly. +- Spade's purpose-built compiler can enforce hardware-specific timing and type rules, and its source-aware tooling can present complex Spade types during debug. ROHD instead offers the full Dart language for generation and verification, together with a built-in event-driven simulator. + +Read more about Spade here: . + +## PipelineC + +PipelineC is a C-like HDL with compiler-managed automatic pipelining for pure functions. It primarily generates human-readable VHDL, with a path to Verilog when needed, and occupies a middle ground between explicit RTL and HLS. + +- PipelineC is a strong fit when automatic pipelining of computational functions is a primary goal. +- ROHD normally keeps cycle boundaries explicit and predictable, while offering reusable pipeline abstractions and broader support for testbench and event-driven simulation code in the same language. + +Read more about PipelineC here: . + +## SUS + +SUS is a compiled synchronous RTL language that generates SystemVerilog. Its distinguishing features include latency counting for pipelines, explicit hardware domains, compile-time metaprogramming, and hardware-aware editor feedback. + +- SUS provides a purpose-built syntax and compiler that can reason directly about latency and hardware domains. +- ROHD supports both synthesizable construction and non-synthesizable event-driven models, and uses Dart rather than introducing a new language and toolchain. + +Read more about SUS here: . + +## DFiant HDL (DFHDL) + +DFHDL is an embedded Scala hardware description framework. It supports dataflow, register-transfer, and event-driven levels of abstraction, with dataflow firing rules intended to enable timing- and device-agnostic descriptions. + +- DFHDL and ROHD both gain metaprogramming and abstraction capabilities by embedding hardware construction in a general-purpose language. +- DFHDL emphasizes multiple hardware abstraction domains and dataflow semantics. ROHD emphasizes explicit structural construction, a built-in simulator, and structurally similar SystemVerilog generation using the Dart ecosystem. + +Read more about DFHDL here: . + +## Bluespec + +Bluespec is a high-level hardware description language available as Bluespec SystemVerilog and Bluespec Haskell. Its defining abstraction is *guarded atomic actions*: designers describe rules and invariants, and the compiler determines a valid schedule. The open-source BSC toolchain emits Verilog and includes the Bluesim simulator. -### Spade +- Bluespec's rules can make complex concurrent behavior highly composable, while its compiler handles scheduling conflicts. +- That scheduling step also puts more behavior in the compiler's hands. ROHD keeps cycle-level structure more explicit and uses composition in Dart rather than a separate rule-based language. -### PipelineC +Read more about Bluespec here: . -### Sus +## Clash -### DFiant HDL +Clash is a functional hardware description language based on Haskell's syntax and semantics. It uses strong types, higher-order functions, and streams of values to describe hardware, and it generates synthesizable VHDL, Verilog, or SystemVerilog. It also provides an interactive REPL for testing components. -### BlueSpec +- Clash is especially attractive for functional, strongly typed, and highly parametric circuit descriptions. +- ROHD uses Dart's imperative and object-oriented styles, executes Dart to construct the hardware model at generation time, and includes a four-state event-driven simulator. The choice often comes down to the preferred programming model and ecosystem. -### Clash +Earlier Haskell-embedded hardware description projects such as Lava helped establish this style; Clash is the more actively maintained comparison today. -### Lava? \ No newline at end of file +Read more about Clash here: . diff --git a/doc/user_guide/_get-started/01-overview.md b/doc/user_guide/_get-started/01-overview.md index ad3de9e97..60595da54 100644 --- a/doc/user_guide/_get-started/01-overview.md +++ b/doc/user_guide/_get-started/01-overview.md @@ -2,7 +2,7 @@ title: "Overview" permalink: /get-started/overview/ excerpt: "Overview of ROHD framework." -last_modified_at: 2024-01-04 +last_modified_at: 2026-07-16 toc: true --- @@ -66,33 +66,42 @@ For more information on Dart and tutorials, see and Date: Fri, 17 Jul 2026 11:12:18 -0700 Subject: [PATCH 11/11] ignore ieee link check --- .github/configs/mlc_config.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/configs/mlc_config.json b/.github/configs/mlc_config.json index 0c4421967..5eb00f934 100644 --- a/.github/configs/mlc_config.json +++ b/.github/configs/mlc_config.json @@ -1,5 +1,8 @@ { "ignorePatterns": [ + { + "pattern": "^https://standards.ieee.org/ieee/1800/7743/$" + }, { "pattern": "^https://www.cadence.com/en_US/home/tools/digital-design-and-signoff/synthesis/stratus-high-level-synthesis.html$" },