GitHub - abs-tudelft/Tydi-Chisel (original) (raw)

Tydi-Chisel

Tydi-Chisel allows you to transfer simple to very complex nested variable length sequences between components over a stream bus in a structured way, using familiar Chisel concepts.

What is Tydi?

Tydi-Chisel is an implementation of Tydi interfaces and concepts in Chisel.

Tydi (Typed dataflow interface) is an open specification for streaming dataflow designs in digital circuits, allowing designers to express how composite and variable-length data structures are transferred over streams using clear, data-centric types.

Chisel (Constructing Hardware in a Scala Embedded Language) is a high-level open-source hardware description language (HDL).

With Tydi as data-streaming communication flow specification and Chisel as flexible implementation, an interface-driven design method can be followed.

Why Tidy?

Developing hardware is notoriously difficult. Many solutions exist to lighten the load of developing implementations for hardware components. Yet, a gap exists between the easy use of complex nested (sequence) data structures in software and trying to work with them in hardware.

Tydi aims to solve this issue by proposing an open standard for streams of arbitrary variable length data-structures. A data-structure is created by nesting Bits, Group, Union and Stream elements. See the following table for the meaning of the used terms.

Term Type Software equivalent Chisel equivalent Meaning
Null Logical type Null Bits(0) Empty data
Bit Logical type Any primary datatype Ground hardware type Primary datatype of x bits
Group Logical type Struct/dict/map Bundle Aggregate of several logic types
Union Logical type Union Bundle with tag “pick one” of several logic types
Stream Logical type Bus to transport sequence of instance Specify how to transport logic type
Streamlet Hardware element Interface Trait with IO defs IO specification of component
Impl Hardware element Class with functionality Module Inner structure of component

By being a super-set of ready-valid communication, like Chisel's DecoupledIO, and the AXI-Stream standard, Tydi-interfaces stay close to existing streaming implementations.

See the work in publications for more details.

Example

Using Tydi data-structures and streams

The following example provides an overview of the declaration of a nested Tydi data structure and its usage in streams.

In software, the declared data structure would look like

[ { "time": 123456789, "nested": { "a": 5, "b": true }, "message": [ "Hello", "this", "is", "a", "string." ] } ]

For Tydi, this gives us the following structure

timestamped-message.svg

In Chisel, it can be expressed as follows

// Declaration of the data-structure class Character extends BitsEl(8.W)

class NestedBundle extends Group { val a: UInt = UInt(8.W) val b: Bool = Bool() }

class TimestampedMessageBundle extends Group { val time: UInt = UInt(64.W) val nested: NestedBundle = new NestedBundle // Create a 2D sub-stream of character data with 3 data-lanes val message = new PhysicalStreamDetailed(Character, n = 3, d = 2, c = 7) }

// Declaration of the module class TimestampedMessageModule extends TydiModule { // Create Tydi logical stream object val stream = PhysicalStreamDetailed(new TimestampedMessageBundle, 1, c = 7)

// Create and connect physical streams as IO // following the Tydi standard with concatenated data bitvector val tydi_port_top = stream.toPhysical val tydi_port_child = stream.el.message.toPhysical

// → Assign values to logical stream group elements directly stream.el.time := System.currentTimeMillis().U stream.el.nested.a := 5.U stream.el.nested.b := true.B stream.el.message.data(0).value := 'H'.U stream.el.message.data(1).value := 'e'.U stream.el.message.data(2).value := 'l'.U ... }

See the timestamped_message file for the full example. This file is just for showing the syntax of declaring and using Tydi-interfaces. It does not contain an implementation. For that, look at the pipeline examples in the overview below. There you will also find advanced syntax for the creation of modules and chaining of submodules through their streams:

...

class PipelineExampleModule extends SimpleProcessorBase(new NumberGroup, new Stats) { out := in.processWith(new NonNegativeFilter).processWith(new Reducer) }

Testing a TydiModule

The code below shows a snippet from the pipeline example test code. It shows how to use the TydiStreamDriver to easily enqueue and dequeue data to sink and from source streams. Currently, this is only available for ChiselTest, and not ChiselSim.

// Import stuff

class PipelineExampleTest extends AnyFlatSpec with ChiselScalatestTester { behavior of "PipelineExample"

class PipelineWrap extends TydiTestWrapper(new PipelineExampleModule, new NumberGroup, new Stats)

it should "process a sequence" in { // Test code test(new PipelineWrap) { c => // Initialize signals c.in.initSource() c.out.initSink()

  // Generate list of random numbers
  val nums = randomSeq(n = 50)
  val stats = processSeq(nums) // Software impl.

  // Test component
  parallel({
    for ((elem, i) <- nums.zipWithIndex) {
      c.in.enqueueElNow(_.time -> i.U, _.value -> elem.S)
    }
    c.in.enqueueEmptyNow(last = Some(c.in.lastLit(0 -> 1.U)))
  }, {
    c.out.waitForValid()
    // Utility for comprehensively printing stream state
    println(c.out.printState(statsRenderer))
    c.out.expectDequeue(_.min -> stats.min.U, _.max -> stats.max.U, _.sum -> stats.sum.U, _.average -> stats.average.U)
  })
}

} }

Look through the test examples for all functionality and syntax.

Examples overview

Timestamped message data structure

Simple pipeline diagram

Advanced pipeline diagram

TVLSI example system diagram

Getting started

Acquire the lib

To get started with Tydi-Chisel, you can either run it in your local development environment, or use the Tydi-tools docker container.

For usage with sbt or scala-cli, the project package must first be built. Make sure you have git, java, and sbt installed and available in your path.

git clone https://github.com/abs-tudelft/Tydi-Chisel.git sbt publishLocal

Use the lib

After this, the library can be added to your project's dependencies in your build.sbt like so.

libraryDependencies += "nl.tudelft" %% "tydi-chisel" % "0.1.0" libraryDependencies += "nl.tudelft" %% "tydi-chisel-test" % "0.1.0" % Test

When using scala-cli, use the following directive:

//> using dep "nl.tudelft::tydi-chisel::0.1.0"

Then, one can import the functionality, and start to write Tydi-Chisel code!

import nl.tudelft.tydi_chisel._

Look through the examples for inspiration for the functionality and syntax.

Features

Concretely, this project contains:

Future work

Publications

License

Tydi and this library are licensed under the Apache-2.0 license. See LICENSE.