Skip to content

Commit 3efc0dd

Browse files
authored
Merge pull request #3 from rameloni/tywaves-add-readme
Tywaves add readme
2 parents 3462701 + ae2edcd commit 3efc0dd

21 files changed

+553
-358
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
# Scala project
1212
target/
13-
project/
1413

1514
# Chiseltest run directory
1615
test_run_dir/

Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.PHONY: all download-surfer clean
2+
3+
TYWAVES_SURFER_REPO=https://gitlab.com/rameloni/surfer-tywaves-demo.git
4+
TYWAVES_BRANCH=tywaves
5+
TYWAVES_NAME=surfer-tywaves-demo
6+
7+
all: install-surfer-tywaves clean install-tywaves-backend
8+
9+
install-surfer-tywaves:
10+
@mkdir -p tmp/
11+
@cd tmp/ && git clone -b $(TYWAVES_BRANCH) $(TYWAVES_SURFER_REPO) && cd $(TYWAVES_NAME) && git submodule update --init --recursive
12+
@cd tmp/$(TYWAVES_NAME) && cargo install --path .
13+
14+
clean:
15+
@rm -rf tmp/
16+
17+
install-tywaves-backend:
18+
@sbt publishLocal

README.md

Lines changed: 187 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,187 @@
1-
# Tywaves demo projec: Chisel backend
2-
Demo backend of the Tywaves project. This repo contains function that parse the information a Chisel circuit, debug info emitted by the firtool compiler, simulate a circuit using ChiselSim and combine all the information to the [surfer-tywaves-demo](https://gitlab.com/rameloni/surfer-tywaves-demo) frontend (an extension of the Surfer waveform viewer written in Rust to support Chisel).
1+
# Tywaves demo project: Chisel backend
2+
3+
Demo backend of the Tywaves project: a type based waveform viewer for Chisel
4+
and [Tydi-Chisel](https://github.com/abs-tudelft/Tydi-Chisel) circuits.
5+
This repo contains functions that parse the information of a Chisel circuit and the debug info emitted by the firtool
6+
compiler, simulate a circuit using ChiselSim and combine all the information to the
7+
[surfer-tywaves-demo](https://gitlab.com/rameloni/surfer-tywaves-demo) frontend (an extension of the Surfer waveform
8+
viewer written in Rust to support Chisel constructs).
9+
10+
Since it is a demo project, it has been tested and developed for a restricted set of examples (it may not work with
11+
all circuits). In the [features](#features) section, you can find the already supported features.
12+
13+
Starting from this demo project, a better implementation and integration in the Chisel/Firrtl infrastructure will be
14+
developed that aims to address the issues
15+
discovered [here](https://github.com/rameloni/Tydi-Chisel-testing-frameworks-analysis).
16+
17+
> Do not use Verilog / System Verilog reserved keywords in Chisel circuit (i.e. `wire`, `reg`).
18+
> In that case, `firtool` will change the `var_name` (which should be `wire`) field of the emitted HGLDD to get a legal
19+
> name as explained in the comments
20+
> [here](https://github.com/llvm/circt/blob/37fbe5e5f5c7a07064d02cea8bf4e8454178fc0e/lib/Target/DebugInfo/EmitHGLDD.cpp#L163C1-L175C2).
21+
> Thus, it is not possible to match Chisel/FIRRTL with the `var_name` in HGLDD.
22+
>
23+
> HGLDD is a file format emitted for other existing tools based on verilog simulations and verilog keywords.
24+
> **I am using it temporarily and in the future firtool will be able to emit a new file format more consistent with
25+
> tywaves.**
26+
27+
# Table of contents
28+
29+
- [Installation](#installation)
30+
- [Install surfer-tywaves-demo](#install-surfer-tywaves-demo)
31+
- [Publish locally this scala project](#publish-locally-this-scala-project)
32+
- [Use it on your project](#use-it-on-your-project)
33+
- [Example output](#example-output)
34+
- [Features](#features)
35+
- [How it works internally](#how-it-works-internally)
36+
- [Drawbacks](#drawbacks)
37+
38+
# Installation
39+
40+
You can run `make all` to install all the pre-requisites.
41+
42+
## Install [surfer-tywaves-demo](https://gitlab.com/rameloni/surfer-tywaves-demo/-/tree/tywaves)
43+
44+
The makefile contains a rule to clone the frontend repository, build and install it.
45+
46+
```bash
47+
make install-surfer-tywaves
48+
make clean # To remove the cloned repository
49+
```
50+
51+
The frontend will be installed as `surfer-tywaves` executable.
52+
53+
## Publish locally this scala project
54+
55+
```bash
56+
make install-tywaves-backend
57+
```
58+
59+
Once published locally, the `tywaves-demo-backend` can be used by adding the following line to the `build.sbt` file:
60+
61+
```scala
62+
libraryDependencies += "com.github.rameloni" %% "tywaves-backend" % "0.1.0-SNAPSHOT"
63+
```
64+
65+
# Use it on your project
66+
67+
The `TywavesBackend` provides a [simulator](./src/main/tywaves/simulator/BetterEphemeralSimulator.scala) with
68+
functionalities to simulate a circuit through [svsim](https://github.com/chipsalliance/chisel/tree/main/svsim), emit VCD
69+
traces and of course generate the symbol table for the waveform viewer itself automatically.
70+
71+
The following example shows how it is possible also to:
72+
73+
- Enable the trace of the simulation
74+
- Launch the waveform viewer after the simulation
75+
- Set the name of the simulation (it will be used to create a folder with a user defined name for the traces and
76+
workspace of svsim)
77+
- Use tywaves and expect API to test the circuit
78+
79+
```scala
80+
import tywaves.simulator.BetterEphemeralSimulator._
81+
import tywaves.simulator.simSettings
82+
import org.scalatest.flatspec.AnyFlatSpec
83+
84+
class BarTest extends AnyFlatSpec {
85+
behavior of "BarTest"
86+
it should "trace simple bar" in {
87+
simulate(
88+
new Bar,
89+
Seq(simSettings.EnableTraceWithUnderscore, simSettings.LaunchTywavesWaveforms),
90+
simName = "trace_simple_bar",
91+
) { c =>
92+
c.io.a.poke(true)
93+
c.io.b.poke(false)
94+
c.io.out.expect(false.B)
95+
c.clock.step()
96+
c.io.a.poke(true)
97+
c.io.b.poke(true)
98+
c.io.out.expect(true.B)
99+
c.clock.step()
100+
}
101+
}
102+
}
103+
```
104+
105+
# Example output
106+
107+
The following images show the classic and tywaves waveform visualization of the [GCD](./src/test/gcd/GCD.scala) module.
108+
It is possible to see that the left picture does not provide any information about Chisel level types and hierarchy.
109+
110+
```scala
111+
class GCD extends Module {
112+
val io = IO(new Bundle {
113+
val a = Input(UInt(32.W))
114+
val b = Input(UInt(32.W))
115+
val loadValues = Input(Bool())
116+
val result = Output(UInt(32.W))
117+
val resultIsValid = Output(Bool())
118+
})
119+
120+
val x = Reg(UInt(32.W))
121+
val y = Reg(UInt(32.W))
122+
123+
when(x > y)(x := x -% y).otherwise(y := y -% x)
124+
when(io.loadValues) {
125+
x := io.a;
126+
y := io.b
127+
}
128+
io.result := x
129+
io.resultIsValid := y === 0.U
130+
}
131+
```
132+
133+
| Only VCD loaded | Tywaves (VCD + symbol table) |
134+
|----------------------------------------------------|-------------------------------------------------------------|
135+
| ![VCD GCD waveform](./images/vcd-gcd-waveform.png) | ![Tywaves GCD waveform](./images/tywaves-gcd-waveforms.png) |
136+
137+
# Features
138+
139+
- [x] Parse and map Chisel/FIRRTL/Verilog circuits
140+
- [x] Emit VCD traces from the simulator (both with and without underscores in the signal names)
141+
- [x]
142+
- [x] Automatically generate the symbol table for the waveform viewer
143+
- [x] Dump Chisel types in the final symbol table
144+
- [x] Represent hierarchical structures of bundles
145+
- [ ] Represent vectors
146+
- [ ] Represent enums
147+
- [ ] Represent hierarchical modules
148+
- [ ] For loops code generation
149+
- [ ] Reg with init
150+
151+
# How it works internally
152+
153+
The following diagram shows the main components of the demo project and how they interact with each other.
154+
![Tywaves backend diagram](./images/tywaves-backend-diagram.png)
155+
156+
It retrieves, parses and finally maps together the Intermediate Representation (IR) of the Chisel, Firrtl and debug info
157+
emitted by the firtool (HGLDD) to output a symbol table that can be used by the frontend to display the waveform.
158+
It aims to map each high level signal (Chisel) to the low level signal (System Verilog) and vice versa. Usually, HGLDD
159+
would be enough, but it does provide only information about FIRRTL-to-SystemVerilog mapping, so it does not contain user
160+
types information.
161+
162+
In this small example if I use only HGLDD I would be able to see that they are both bundles, but it is not possible to
163+
see that they are actually `MyFloat` and `IntCoordination` respectively. Also `Bool`, `UInt`, `SInt` would not be
164+
retrieved from HGLDD/FIRRTL only. From here the reason to use Chisel IR to get the user types information.
165+
166+
```scala
167+
class MyFloat extends Bundle {
168+
val sign = Bool()
169+
val exponent = UInt(8.W)
170+
val significand = UInt(23.W)
171+
}
172+
173+
class IntCoordination extends Bundle {
174+
val x = SInt(32.W)
175+
val y = SInt(32.W)
176+
}
177+
```
178+
179+
## Drawbacks
180+
181+
Chisel IR is an **internal** IR, and it is not meant to be used by external tools. It is not stable, and it can change
182+
basing on additional future features. It will be really hard to maintain this project for future Chisel versions.
183+
Therefore, I planned to "integrate" a functionality to directly transfer Chisel information to FIRRTL. In this way,
184+
the `firtool` would be able to access all the needed information for `surfer-tywaves-demo` to render the signals.
185+
This would also allow to simplify the process that `tywaves-demo-backend` currently does to generate the symbol table,
186+
improving performances. And it may extend the support to other languages/dialects in
187+
the [CIRCT](https://circt.llvm.org/) ecosystem.

build.sbt

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@ Compile / scalaSource := baseDirectory.value / "src/main"
66

77
Test / scalaSource := baseDirectory.value / "src/test"
88

9-
Compile / doc / scalacOptions ++= Seq("-siteroot", "docs")
10-
11-
ThisBuild / version := "0.1.0-SNAPSHOT"
12-
9+
ThisBuild / organization := "com.github.rameloni"
10+
ThisBuild / version := "0.1.0-SNAPSHOT"
1311
ThisBuild / scalaVersion := "2.13.10"
1412

1513
lazy val root = (project in file("."))
1614
.settings(
17-
name := "TyWaves-demo: backend Chisel-to-Vcd mapper",
15+
name := "TyWaves-demo-backend",
1816
addCompilerPlugin(
1917
"org.chipsalliance" % "chisel-plugin" % chiselVersion cross CrossVersion.full
2018
),
@@ -24,10 +22,7 @@ lazy val root = (project in file("."))
2422
libraryDependencies += "io.circe" %% "circe-generic" % circeVersion,
2523
libraryDependencies += "io.circe" %% "circe-generic-extras" % "0.14.3",
2624
libraryDependencies += "io.circe" %% "circe-parser" % circeVersion,
27-
28-
// libraryDependencies += "nl.tudelft" %% "root" % "0.1.0",
29-
libraryDependencies += "edu.berkeley.cs" %% "chiseltest" % "6.0.0",
30-
libraryDependencies += "nl.tudelft" %% "tydi-chisel" % "0.1.6",
25+
libraryDependencies += "edu.berkeley.cs" %% "chiseltest" % "6.0.0",
3126
scalacOptions ++= Seq(
3227
"-deprecation",
3328
"-encoding",

images/tywaves-backend-diagram.png

763 KB
Loading

images/tywaves-gcd-waveforms.png

75.6 KB
Loading

images/vcd-gcd-waveform.png

75.6 KB
Loading

project/build.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version=1.9.7

project/plugins.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")

src/main/chisel3/tywaves/circuitparser/CircuitParser.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,12 @@ trait CircuitParser[T, ModuleT, PortT, AggregateT, ElementT, BodyStatementT] {
2626
}
2727
case _: firrtl.ir.AggregateType => this.getWidth(f.tpe.asInstanceOf[AggregateT])
2828
}
29+
2930
// extract the number <width> from the GroundType
3031
).sum
32+
case firrtl.ir.VectorType(firrtl.ir.GroundType(width), size) => width.serialize match {
33+
case widthPattern(width) => width.toInt * size
34+
}
3135
}
3236

3337
case chisel: chisel3.Record => chisel.getWidth

0 commit comments

Comments
 (0)