Skip to content

Commit b042c2c

Browse files
author
Oron Port
committed
docs updating
1 parent 16c23f8 commit b042c2c

File tree

2 files changed

+63
-35
lines changed

2 files changed

+63
-35
lines changed

docs/user-guide/design-hierarchy/index.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ Since this design is annotated with `@top`, it is a top-app design that generate
172172
The `@top` annotation captures any [implicit/given](https://docs.scala-lang.org/scala3/book/ca-context-parameters.html#given-instances-implicit-definitions-in-scala-2){target="_blank"} options within its scope and provides them as defaults when no CLI arguments are specified.
173173

174174
/// tab | Generated Verilog
175+
```verilog
176+
--8<-- "lib/src/test/resources/ref/docExamples.ugdemos.demo1.LeftShift2Spec/verilog.sv2009/hdl/LeftShift2.sv"
177+
```
175178
Looking at the generated Verilog code, we can observe several key differences from the DFHDL source:
176179

177180
1. **Module Interface**: DFHDL's Scala-style port declarations (`<> IN/OUT`) are translated to traditional Verilog port declarations (`input wire`/`output logic`)
@@ -184,12 +187,12 @@ Looking at the generated Verilog code, we can observe several key differences fr
184187

185188
5. **Assignment Syntax**: DFHDL's `:=` assignments are translated to Verilog's `assign` statements
186189

187-
```verilog
188-
--8<-- "lib/src/test/resources/ref/docExamples.ugdemos.demo1.LeftShift2Spec/verilog.sv2009/hdl/LeftShift2.sv"
189-
```
190190
///
191191

192192
/// tab | Generated VHDL
193+
```vhdl
194+
--8<-- "lib/src/test/resources/ref/docExamples.ugdemos.demo1.LeftShift2Spec/vhdl.v2008/hdl/LeftShift2.vhd"
195+
```
193196
The generated VHDL code shows similar transformations from the DFHDL source:
194197

195198
1. **Entity Interface**: DFHDL's port declarations are translated to VHDL's `in`/`out` mode declarations with explicit signal types
@@ -201,10 +204,6 @@ The generated VHDL code shows similar transformations from the DFHDL source:
201204
4. **Signal Types**: DFHDL's `Bits` type is translated to VHDL's `std_logic_vector` with appropriate widths
202205

203206
5. **Assignment Syntax**: While both DFHDL and VHDL use `:=`, the semantics differ - DFHDL represents high-level connections while VHDL represents signal assignments
204-
205-
```vhdl
206-
--8<-- "lib/src/test/resources/ref/docExamples.ugdemos.demo1.LeftShift2Spec/vhdl.v2008/hdl/LeftShift2.vhd"
207-
```
208207
///
209208

210209
/// details | Runnable example
@@ -240,7 +239,7 @@ The DFHDL design parameter block follows standard Scala syntax, accepting a comm
240239
#### `LeftShiftBasic` example {#LeftShiftBasic}
241240
/// admonition | Scala-parameterized top-app design example: a basic left shifter
242241
type: example
243-
The DFHDL code below implements a basic left shifter design named `LeftShiftBasic`. This design is similar to the earlier example of `LeftShift2` except here the design has the shift value as an input, and its input and output port widths are set according to the Scala parameter `width`.
242+
The DFHDL code below implements a basic left shifter design named `LeftShiftBasic`. This design is similar to the earlier example of [`LeftShift2`][LeftShift2], except here the design has the shift value as an input, and its input and output port widths are set according to the Scala parameter `width`.
244243

245244
<div class="grid" markdown>
246245

docs/user-guide/type-system/index.md

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -189,15 +189,12 @@ class Foo extends DFDesign:
189189

190190
/// details | Transitioning from Verilog
191191
type: verilog
192-
* Declaration Syntax: Port and variable declaration syntax is obviously very different
193-
* Types:
194-
* Scope
195-
* The non-blocking assignment operator in DFHDL is `:==` instead of `<=` in Verilog.
192+
TODO
196193
///
197194

198195
/// details | Transitioning from VHDL
199196
type: vhdl
200-
* VHDL has
197+
TODO
201198
///
202199

203200

@@ -327,10 +324,7 @@ Ports can be grouped together in dedicated [interfaces][interfaces].
327324

328325
/// details | Transitioning from Verilog
329326
type: verilog
330-
* Declaration Syntax: Port and variable declaration syntax is obviously very different
331-
* Types:
332-
* Scope
333-
* The non-blocking assignment operator in DFHDL is `:==` instead of `<=` in Verilog.
327+
TODO
334328
///
335329

336330
/// details | Transitioning from VHDL
@@ -451,37 +445,72 @@ class Foo extends DFDesign:
451445
///
452446
453447
454-
## DFHDL Value Mutation {#mutability}
448+
## Bit-Accurate Operations and Type Inference
455449
456-
DFiant supports dataflow variables mutability via the `:=` operator. Do not confuse with Scala-level mutability which is enabled by using `#!scala var` instead of `#!scala val`. Each dataflow class has two variations: an immutable class, which inherits from `DFAny.Val` and a mutable class, which inherits from `DFAny.Var` and accepts `:=`. The difference between the types enforces an immutable right-hand-side (RHS), where required, and a mutable variable creation.
450+
DFHDL provides bit-accurate operations and strong type inference for bit-level manipulations. Here are the key features:
457451
458-
Consider, for instance, the DFiant implementation of `g` in Table \ref`tbl:StateExDefImpl`: `a` is immutable because it is a RHS addition between the dataflow variable `i` and a literal value `5`. Contrarily, `c` is mutable, since it is a dataflow variable constructor (`.init` constructs a new initialized variable, while preserving the mutability trait).
452+
### Bit Selection and Slicing
453+
```scala
454+
val b8 = Bits(8) <> VAR
455+
// Most significant bits selection
456+
val ms7 = b8(7, 1) // 7 MSBs
457+
val ms1 = b8(7, 7) // MSB only
459458
460-
Fig. 1 demonstrates a dual class definition for every type (immutable and mutable). The naming convention helps to reason about the mutability. For example, `DFBits` and `DFBits.Var` are immutable and mutable classes, respectively. Constructing a new variable via `DFBits` (e.g, `#!scala val a = DFBits[5]`) returns the mutable `DFBits.Var[5]`. Usually, we either receive or return an immutable type, hence we do not require annotating a type with its mutable variation. In cases where we want to return a mutable type, we annotate it as an output port (see Section~\ref`sec:io_ports`).
459+
// Least significant bits selection
460+
val ls7 = b8(6, 0) // 7 LSBs
461+
val ls1 = b8(0, 0) // LSB only
461462
463+
// Single bit access
464+
val msbit = b8(7) // MSB
465+
val lsbit = b8(0) // LSB
466+
```
462467

463-
## Bit-Accurate Operations, Type Inference, and Data Structures
468+
### Bit Operations
469+
```scala
470+
val b8 = Bits(8) <> VAR
464471

465-
All DFiant's dataflow types are bit-accurate and structurally static, with their bit-width set upon construction (e.g., `DFBits[5]` is a 5-bit vector). Operations between dataflow variables produce a bit-accurate result with the proper type inference. For example, an addition between an unsigned 5-bit variable (`DFUInt[5]`) and a signed 10-bit variable (`DFSInt[10]`) produces an adder that can be implicitly converted to a 10-bit signed variable, if carry is not required, or an 11-bit signed variable by explicitly invoking `.wc` from the addition.
472+
// Shift operations
473+
val shifted_left = b8 << 2 // Logical left shift
474+
val shifted_right = b8 >> 2 // Logical right shift
466475

467-
DFiant also allows operations between dataflow types and their corresponding Scala numeric types, by treating the Scala numeric types as constants (e.g., addition between `DFSInt` and `Integer` variables). A constant in the dataflow graph is a node that can produce infinite tokens of the same value.
476+
// Bit reduction operations
477+
val or_reduced = b8.| // OR reduction
478+
val and_reduced = b8.& // AND reduction
479+
val xor_reduced = b8.^ // XOR reduction
468480

469-
## Bit Aliasing and Casting
481+
// Bit concatenation
482+
val concat = (b"100", b"1", b"0", b"11").toBits // Creates 8-bit value
483+
```
470484

471-
Aliasing in DFiant enables referencing a part of a dataflow variable, by invoking `.bits(hiIdx, loIdx)`, which creates a bits vector alias that references the original variable at the given index parameters. Every change of a dataflow variable affects its alias and vice versa (similar to VHDL's signal aliasing). Since this function also casts the variable as `DFBits`, this feature is used as a raw-data cast between different dataflow types. Aliasing of an alias is also possible, while maintaining relative bits indexing. Aliasing preserves the mutability trait: an alias of an immutable value is immutable, while an alias of a mutable variable is mutable.
485+
### Multiple Variable Assignment
486+
```scala
487+
val b4M, b4L = Bits(4) <> VAR // Declare multiple variables
488+
val b3M = Bits(3) <> VAR
489+
val u5L = UInt(5) <> VAR
490+
491+
// Assign to multiple variables using tuple pattern
492+
(b4M, b4L) := (h"1", 1, 0, b"11") // Values are concatenated and split
493+
494+
// Mix different types in assignment
495+
(b3M, u5L) := (h"1", 1, 0, b"11") // Values automatically cast to appropriate types
472496

473-
Fig.~\ref`fig:Aliasing` demonstrates aliasing code and its effect on the contents of a dataflow variable (`bits128`). Each line code does as follows:
497+
// Assign bit slices to multiple variables
498+
(b4M, b4L) := (u8.bits(3, 0), u8.bits(7, 4)) // Split byte into nibbles
474499

500+
// Complex multiple assignment
501+
(b4M, b3M, u5L, b4L) := (u8, b8) // Automatically extracts appropriate bits for each variable
502+
```
475503

504+
### Width Inference and Resizing
505+
```scala
506+
// Automatic width inference
507+
val b3 = Bits(3) <> VAR
508+
val b8 = Bits(8) <> VAR
476509

477-
1. Constructs a new 128-bit vector, `bits128`, and clears it.
478-
2. Creates a new alias, `alias64`, which references the most significant 64 bits of `bits128`. Since `bits128` is a `DFBits` variable, there is no need to invoke `.bits()`, and we can apply the required indexes directly.
479-
3. Creates a new alias, `alias32`, which references the least significant 32 bits of `alias64`, which reference bits 64 to 95 of `bits128`.
480-
4. Constructs a new double precision floating point dataflow variable, `dbl`, and initialize its value as `1.0` (hexadecimal value of `0x3FF00...0`).
481-
5. Modifies the least significant byte of `dbl`.
482-
6. Sets the most significant bit of `bits128`.
483-
7. Assigns `dbl` to the least significant 64 bits of `bits128` through casting. All the bits of `dbl` are selected because `.bits()` is invoked without index parameters.
484-
8. Modifies a byte of `bits128`.
510+
// Explicit resizing required when widths don't match
511+
b8 := b3.resize(8) // Zero-extend to 8 bits
512+
b3 := b8.resize(3) // Truncate to 3 bits
513+
```
485514

486515
## Bubble Values {#bubble}
487516

0 commit comments

Comments
 (0)