Giter Site home page Giter Site logo

chipsalliance / chisel Goto Github PK

View Code? Open in Web Editor NEW
3.7K 149.0 571.0 96.04 MB

Chisel: A Modern Hardware Design Language

Home Page: https://www.chisel-lang.org/

License: Apache License 2.0

Scala 97.52% Makefile 0.13% C++ 1.02% Verilog 0.09% Python 0.55% Dockerfile 0.11% SystemVerilog 0.03% C 0.01% Nix 0.06% JavaScript 0.36% CSS 0.14%
chisel chisel3 scala firrtl rtl chip-generator verilog

chisel's Introduction

The Constructing Hardware in a Scala Embedded Language (Chisel) is an open-source hardware description language (HDL) used to describe digital electronics and circuits at the register-transfer level that facilitates advanced circuit generation and design reuse for both ASIC and FPGA digital logic designs.

Chisel adds hardware construction primitives to the Scala programming language, providing designers with the power of a modern programming language to write complex, parameterizable circuit generators that produce synthesizable Verilog. This generator methodology enables the creation of re-usable components and libraries, such as the FIFO queue and arbiters in the Chisel Standard Library, raising the level of abstraction in design while retaining fine-grained control.

For more information on the benefits of Chisel see: "What benefits does Chisel offer over classic Hardware Description Languages?"

Chisel is powered by FIRRTL (Flexible Intermediate Representation for RTL), a hardware compiler framework implemented by LLVM CIRCT.

Chisel is permissively licensed (Apache 2.0) under the guidance of CHIPS Alliance.


Join the chat at https://gitter.im/freechipsproject/chisel3 Scaladoc CI GitHub tag (latest SemVer) Scala version support Scala version support (chisel3) Sonatype Snapshots

What does Chisel code look like?

LED blink

import chisel3._
import chisel3.util.Counter
import circt.stage.ChiselStage

class Blinky(freq: Int, startOn: Boolean = false) extends Module {
  val io = IO(new Bundle {
    val led0 = Output(Bool())
  })
  // Blink LED every second using Chisel built-in util.Counter
  val led = RegInit(startOn.B)
  val (_, counterWrap) = Counter(true.B, freq / 2)
  when(counterWrap) {
    led := ~led
  }
  io.led0 := led
}

object Main extends App {
  // These lines generate the Verilog output
  println(
    ChiselStage.emitSystemVerilog(
      new Blinky(1000),
      firtoolOpts = Array("-disable-all-randomization", "-strip-debug-info")
    )
  )
}

Should output the following Verilog:

Click to expand!

// Generated by CIRCT firtool-1.37.0
module Blinky(
  input  clock,
         reset,
  output io_led0
);

  reg       led;
  reg [8:0] counterWrap_c_value;
  always @(posedge clock) begin
    if (reset) begin
      led <= 1'h0;
      counterWrap_c_value <= 9'h0;
    end
    else begin
      automatic logic counterWrap = counterWrap_c_value == 9'h1F3;
      led <= counterWrap ^ led;
      if (counterWrap)
        counterWrap_c_value <= 9'h0;
      else
        counterWrap_c_value <= counterWrap_c_value + 9'h1;
    end
  end // always @(posedge)
  assign io_led0 = led;
endmodule

FIR Filter

Consider an FIR filter that implements a convolution operation, as depicted in this block diagram:

While Chisel provides similar base primitives as synthesizable Verilog, and could be used as such:

// 3-point moving sum implemented in the style of a FIR filter
class MovingSum3(bitWidth: Int) extends Module {
  val io = IO(new Bundle {
    val in = Input(UInt(bitWidth.W))
    val out = Output(UInt(bitWidth.W))
  })

  val z1 = RegNext(io.in)
  val z2 = RegNext(z1)

  io.out := (io.in * 1.U) + (z1 * 1.U) + (z2 * 1.U)
}

the power of Chisel comes from the ability to create generators, such as an FIR filter that is defined by the list of coefficients:

// Generalized FIR filter parameterized by the convolution coefficients
class FirFilter(bitWidth: Int, coeffs: Seq[UInt]) extends Module {
  val io = IO(new Bundle {
    val in = Input(UInt(bitWidth.W))
    val out = Output(UInt(bitWidth.W))
  })
  // Create the serial-in, parallel-out shift register
  val zs = Reg(Vec(coeffs.length, UInt(bitWidth.W)))
  zs(0) := io.in
  for (i <- 1 until coeffs.length) {
    zs(i) := zs(i-1)
  }

  // Do the multiplies
  val products = VecInit.tabulate(coeffs.length)(i => zs(i) * coeffs(i))

  // Sum up the products
  io.out := products.reduce(_ + _)
}

and use and re-use them across designs:

val movingSum3Filter = Module(new FirFilter(8, Seq(1.U, 1.U, 1.U)))  // same 3-point moving sum filter as before
val delayFilter = Module(new FirFilter(8, Seq(0.U, 1.U)))  // 1-cycle delay as a FIR filter
val triangleFilter = Module(new FirFilter(8, Seq(1.U, 2.U, 3.U, 2.U, 1.U)))  // 5-point FIR filter with a triangle impulse response

The above can be converted to Verilog using ChiselStage:

import chisel3.stage.ChiselGeneratorAnnotation
import circt.stage.{ChiselStage, FirtoolOption}

(new ChiselStage).execute(
  Array("--target", "systemverilog"),
  Seq(ChiselGeneratorAnnotation(() => new FirFilter(8, Seq(1.U, 1.U, 1.U))),
    FirtoolOption("--disable-all-randomization"))
)

Alternatively, you may generate some Verilog directly for inspection:

val verilogString = chisel3.getVerilogString(new FirFilter(8, Seq(0.U, 1.U)))
println(verilogString)

Getting Started

Bootcamp Interactive Tutorial

The online Chisel Bootcamp is the recommended way to get started with and learn Chisel. No setup is required (it runs in the browser), nor does it assume any prior knowledge of Scala.

The classic Chisel tutorial contains small exercises and runs on your computer.

A Textbook on Chisel

If you like a textbook to learn Chisel and also a bit of digital design in general, you may be interested in reading Digital Design with Chisel. It is available in English, Chinese, Japanese, and Vietnamese.

Build Your Own Chisel Projects

Please see the Installation page of the Chisel website for information about how to use Chisel locally.

When you're ready to build your own circuits in Chisel, we recommend starting from the Chisel Template repository, which provides a pre-configured project, example design, and testbench. Follow the chisel-template README to get started.

If you insist on setting up your own project from scratch, your project needs to depend on both the chisel-plugin (Scalac plugin) and the chisel library. For example, in SBT this could be expressed as:

// build.sbt
scalaVersion := "2.13.12"
val chiselVersion = "6.0.0"
addCompilerPlugin("org.chipsalliance" % "chisel-plugin" % chiselVersion cross CrossVersion.full)
libraryDependencies += "org.chipsalliance" %% "chisel" % chiselVersion

For Chisel prior to v5.0.0, Chisel was published using a different artifact name:

// build.sbt
scalaVersion := "2.13.10"
addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % "3.6.0" cross CrossVersion.full)
libraryDependencies += "edu.berkeley.cs" %% "chisel3" % "3.6.0"
// We also recommend using chiseltest for writing unit tests
libraryDependencies += "edu.berkeley.cs" %% "chiseltest" % "0.6.0" % "test"

Guide For New Contributors

If you are trying to make a contribution to this project, please read CONTRIBUTING.md.

Design Verification

These simulation-based verification tools are available for Chisel:

  • svsim is the lightweight testing library for Chisel, included in this repository.
  • chiseltest (Chisel 5.0 and before) is the batteries-included testing and formal verification library for Chisel-based RTL designs and a replacement for the former PeekPokeTester, providing the same base constructs but with a streamlined interface and concurrency support with fork and join with internal and Verilator integration for simulations.

Documentation

Useful Resources

If you are migrating from Chisel2, see the migration guide.

Chisel Dev Meeting

Chisel/FIRRTL development meetings happen every Monday from 9:00-10:00 am PT.

Call-in info and meeting notes are available here.

Data Types Overview

These are the base data types for defining circuit components:

Image

Contributor Documentation

This section describes how to get started contributing to Chisel itself, including how to test your version locally against other projects that pull in Chisel using sbt's managed dependencies.

Useful Resources for Contributors

The Useful Resources for users are also helpful for contributors.

Compiling and Testing Chisel

You must first install required dependencies to build Chisel locally, please see the installation instructions.

Clone and build the Chisel library:

git clone https://github.com/chipsalliance/chisel.git
cd chisel
sbt compile

In order to run the following unit tests, you will need several tools on your PATH, namely verilator, yosys, and espresso. Check that each is installed on your PATH by running which verilator and so on.

If the compilation succeeded and the dependencies noted above are installed, you can then run the included unit tests by invoking:

sbt test

Running Projects Against Local Chisel

To use the development version of Chisel (main branch), you will need to build from source and publish locally. The repository version can be found by running sbt version. As of the time of writing it was: 6.0.0+1-8d92842c-SNAPSHOT.

To publish your version of Chisel to the local Ivy (sbt's dependency manager) repository, run:

sbt "unipublish / publishLocal"

The compiled version gets placed in ~/.ivy2/local/org.chipsalliance/. If you need to un-publish your local copy of Chisel, remove the directory generated in ~/.ivy2/local/org.chipsalliance/.

In order to have your projects use this version of Chisel, you should update the libraryDependencies setting in your project's build.sbt file to use the current version, for example:

val chiselVersion = "6.0.0+1-8d92842c-SNAPSHOT"
addCompilerPlugin("org.chipsalliance" % "chisel-plugin" % chiselVersion cross CrossVersion.full)
libraryDependencies += "org.chipsalliance" %% "chisel" % chiselVersion

Chisel Architecture Overview

The Chisel compiler consists of these main parts:

  • The frontend, chisel3.*, which is the publicly visible "API" of Chisel and what is used in Chisel RTL. These just add data to the...
  • The Builder, chisel3.internal.Builder, which maintains global state (like the currently open Module) and contains commands, generating...
  • The intermediate data structures, chisel3.firrtl.*, which are syntactically very similar to Firrtl. Once the entire circuit has been elaborated, the top-level object (a Circuit) is then passed to...
  • The Firrtl emitter, chisel3.firrtl.Emitter, which turns the intermediate data structures into a string that can be written out into a Firrtl file for further processing.

Also included is:

  • The standard library of circuit generators, chisel3.util.*. These contain commonly used interfaces and constructors (like Decoupled, which wraps a signal with a ready-valid pair) as well as fully parameterizable circuit generators (like arbiters and multiplexors).
  • Chisel Stage, chisel3.stage.*, which contains compilation and test functions that are invoked in the standard Verilog generation and simulation testing infrastructure. These can also be used as part of custom flows.

Chisel Sub-Projects

Chisel consists of several Scala projects; each is its own separate compilation unit:

  • core is the bulk of the source code of Chisel, depends on firrtl, svsim, and macros
  • firrtl is the vestigial remains of the old Scala FIRRTL compiler, much if it will likely be absorbed into core
  • macros is most of the macros used in Chisel, no internal dependencies
  • plugin is the compiler plugin, no internal dependencies
  • src/main is the "main" that brings it all together and includes a util library, which depends on core
  • svsim is a low-level library for compiling and controlling SystemVerilog simulations, currently targeting Verilator and VCS as backends

Code that touches lots of APIs that are private to the chisel3 package should belong in core, while code that is pure Chisel should belong in src/main.

Which version should I use?

We encourage Chisel users (as opposed to Chisel developers), to use the latest release version of Chisel. This chisel-template repository is kept up-to-date, depending on the most recent version of Chisel. The recommended version is also captured near the top of this README, and in the Github releases section of this repo. If you encounter an issue with a released version of Chisel, please file an issue on GitHub mentioning the Chisel version and provide a simple test case (if possible). Try to reproduce the issue with the associated latest minor release (to verify that the issue hasn't been addressed).

For more information on our versioning policy and what versions of the various Chisel ecosystem projects work together, see Chisel Project Versioning.

If you're developing a Chisel library (or chisel3 itself), you'll probably want to work closer to the tip of the development trunk. By default, the main branch of the chisel repository is configured to build and publish its version of the code as <version>+<n>-<commit hash>-SNAPSHOT. Updated SNAPSHOTs are publised on every push to main. You are encouraged to do your development against the latest SNAPSHOT, but note that neither API nor ABI compatibility is guaranteed so your code may break at any time.

Roadmap

See Roadmap.

chisel's People

Contributors

adkian-sifive avatar albert-magyar avatar albertchen-sifive avatar aswaterman avatar azidar avatar chick avatar chiselbot avatar colin4124 avatar davidbiancolin avatar debs-sifive avatar dependabot[bot] avatar donggyukim avatar dtzsifive avatar ducky64 avatar edwardcwang avatar ekiwi avatar ekiwi-sifive avatar grebe avatar hcook avatar jackbackrack avatar jackkoenig avatar jared-barocsi avatar mikeurbach avatar mwachs5 avatar palmer-dabbelt avatar scala-steward avatar seldridge avatar sequencer avatar shunshou avatar ucbjrl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chisel's Issues

Module ports beyond io

It is my understanding that firrtl doesn't care what input and output ports of a module are named. The current chisel3 frontend has a private variable called ports that is only clk, reset, and io.

I propose that we make this variable protected instead of private.

This will allow people to have input/output ports outside of the IO bundle, making chisel3 match firrtl more closely.

Forcing width of data

Porting from Chisel2 I was able to force the width of a Node with something like

UInt(data, width)

This apply method has since disappeared and I ended up using something like

val data_wire = Wire(UInt(width=width))
data_wire := data

Is there a canonical way to do this? A function I should be using?

Call it SyncMem

Rename the new memory from sequential to synchronous memory (e.g., SyncMem). That's the term that is used for memory chips. E.g., SSRAM is a synchronous static RAM, in SDRAM the S is for synchronous.

Basically there are two types of memories (or better memory interfaces) available: asynchronous and synchronous. The term sequential is not use for memories. And if your really want to, I would say both asynchronous and synchronous are 'sequential'.

firrtl parsing error on string literal with escaped double quotes

Pushed a branch to chisel3 named assert_message_causes_firrtl_quote_parsing_error (nice name)

Add new AssertQuoteProblem test that shows how adding a message param to Chisel.assert.apply causes a firrtl parsing error apparently because the string has escaped double quotes in it.
Error is

 [0.053] Done elaborating.
line 27:164 token recognition error at: '\'
line 27:165 extraneous input '")\n"' expecting {'circuit', 'module', 'extmodule', 'input', 'output', 'UInt', 'SInt', 'Clock', '[', 'wire', 'reg', 'with', 'reset', ')', 'mem', 'data-type', 'depth', 'read-latency', 'write-latency', 'read-under-write', 'reader', 'writer', 'readwriter', 'inst', 'node', 'is', 'invalid', 'when', 'else', 'skip', 'infer', 'read', 'write', 'rdwr', 'old', 'new', 'undefined', 'UBits', 'SBits', '.', 'mux(', 'validif(', 'stop', 'printf', 'mux', 'validif', 'add(', 'sub(', 'mul(', 'div(', 'rem(', 'lt(', 'leq(', 'gt(', 'geq(', 'eq(', 'neq(', 'pad(', 'asUInt(', 'asSInt(', 'asClock(', 'shl(', 'shr(', 'dshl(', 'dshr(', 'cvt(', 'neg(', 'not(', 'and(', 'or(', 'xor(', 'andr(', 'orr(', 'xorr(', 'cat(', 'bits(', 'head(', 'tail(', Id}
Exception in thread "main" firrtl.ParserException: 1 syntax error(s) detected
    at firrtl.Parser$.parse(Parser.scala:64)
    at firrtl.Driver$.compile(Driver.scala:52)
    at firrtl.Driver$.main(Driver.scala:95)
    at firrtl.Driver.main(Driver.scala)

Attached is the *.fir file with problematic string literal at line 27
*fir.txt

Not really a show stopper, but caused some problems in new testers

.asInput not respected in Vec creation

...
      val wpred = Vec(2, new BankPredEntry().asInput)
      val wdata = new BankDataPredEntry().asInput
...

produces the firrtl

... wpred : { pred : UInt<8>}[2], flip wdata : { data : UInt<128>, pred : UInt<8>} ...

Where I would expect wpred to also have flip

Using elsewhen produces invalid firrtl file

Added ByteSelector.scala to chiselTests
Running causes firrtl error, each elsewhen clause becomes another else in firrtl. Should be nested

    when T_9 :
      node T_10 = bits(io.in, 7, 0)
      io.out := T_10
      skip
    else :
      node T_12 = eq(io.offset, UInt<1>("h01"))
      when T_12 :
        node T_13 = bits(io.in, 15, 8)
        io.out := T_13
        skip
      skip
    else :
      node T_15 = eq(io.offset, UInt<2>("h02"))
      when T_15 :
        node T_16 = bits(io.in, 23, 16)
        io.out := T_16
        skip
      skip
    else :
      node T_17 = bits(io.in, 31, 24)
      io.out := T_17
      skip

Support zero width wires

Hwacha makes use of zero width wires and I would prefer not to add lots of workarounds for a feature that will be eventually added.

Is there an ETA for this support?

can't find top.cpp when using chisel testing tools in another project

When using Chisel testing tools in another project like chisel-tutorial, the verilator build fails with

make: *** No rule to make target `/Users/chick/Aspire/IdeaProjects/chisel-tutorial/src/main/resources/top.cpp', needed by `top.o'.  Stop.

because TesterDriver.scala:22 is looking for top.cpp in the user directory suffixed with the relative path to the file in chisel3.

printf statements are not visible when running from set

Only way I can see statements now is by going to temp directory and running binary directly.
Looks like when it is being run from scala, there is filtering on the process to only pick up assertions. while it might be nice to filter the printf somehow i think the default should be to show them
I'd be happy to have some prefix attached to lines that come from chisel#printf if it makes it easier to dodge a lot of other output

Problems with methods defined in Bundles

The code below:

class Foo(val bar: Int) extends Bundle {
  val num = SInt(bar)

  def sign: Bool = num < SInt(0)
}

class FooTester extends BasicTester {
  val a = new Foo(5)
  val b = new Foo(-3)
  val c = new Foo(2)

  stop()
}

Gives the following FIRRTL:

circuit FooTester : 
  module FooTester : 
    input clk : Clock
    input reset : UInt<1>
    output io : {}

    io is invalid
    node T_10 = eq(reset, UInt<1>("h00"))
    when T_10 :
      stop(clk, UInt<1>(1), 0)
      skip
    node sign = lt(asSInt(UInt<4>("h05")), asSInt(UInt<1>("h00")))
    node sign = lt(asSInt(UInt<3>("h05")), asSInt(UInt<1>("h00")))
    node sign = lt(asSInt(UInt<3>("h02")), asSInt(UInt<1>("h00")))

It seems there might be some kind of reflection issue. I'm also wondering if this might be an anti-pattern? Is it okay to define methods on classes that extend Bundle? It seems like it should be supported.

Chisel emits firrtl files with undeclared wires

Creating a circuit with an IO of the following form

class Packet extends Bundle {
  val header = UInt(width = 1)
}
class VectorPacketIO(n: Int) extends Bundle {
  val ins  = Vec(n, new DeqIO(new Packet()))
  val outs = Vec(n, new EnqIO(new Packet()))
}

coupled with the fact that DeqIO and EnqIO contain initialization code emits a .fir file that firrtl blows up with the following messages

[DEBUG] Starting High Form Check
Exception in thread "main" firrtl.passes.PassExceptions: 
firrtl.passes.CheckHighForm$UndeclaredReferenceException: [email protected]: [module BrokenVectorPacketModule] Reference T_7 is not declared.
firrtl.passes.CheckHighForm$UndeclaredReferenceException: [email protected]: [module BrokenVectorPacketModule] Reference T_15 is not declared.

There is a spec file chiselTests/VectorPacketIO.scala that demonstrates this error in the chisel3 branch DeqIO_contains_init_code.

when statement is incorrectly synthesized

Failing input: http://www.eecs.berkeley.edu/~waterman/whenBug.fir

The following code snippet

reg out_slow_bits : UInt<17>, clock, reset
out_slow_bits := tohost_q.deq.bits
when fromhost_q.deq.valid :
  out_slow_bits := fromhost_q.deq.bits

generates the following incorrect Verilog:

always @(posedge clock) begin
  out_slow_bits <= fromhost_q$deq$bits;
end

Of course, the correct code is

always @(posedge clock) begin
  out_slow_bits <= fromhost_q$deq$valid ? fromhost_q$deq$bits : tohost_q$deq$bits;
end

Bulk connects override bundle components even without valid assignment (different than Chisel2)

This code behaves differently in Chisel2 and 3

io.rocc.resp.ready := !(wb_reg_valid && wb_ctrl.wxd)
...
csr.io.rocc <> io.rocc

In Chisel2 because the csr module does not write to rocc.resp.ready the initial assignment is preserved and last connect semantics are ignored.

In Chisel3 last connect semantics are honored and the second bulk connect overrides the previous assignment. This leads to a random value since csr.io.rocc.resp.ready was never written to.

This anomalous behavior in Chisel2 can cause issues in porting from chisel2 to chisel3 as it silently generates a different circuit.

addPin from chisel2

chisel2.Module had an addPin method that allowed the user to add a pin to the Module outside of its io (Actually, it would add it to the io Bundle; however, I am proposing that it adds the pin in the same hierarchy as clk, reset, and io. Into chisel3.Module.ports).

This was useful (essentially requisite) for writing libraries that needed to thread signals across Module boundaries. As an analogy (to justify the behehavior of bypassing io), if io is similar to a function's signature, addPin is part of the architecture for throwing exceptions from inner Modules.

Ideally, the chisel3 addPin would actually check to make sure no accidentally overwrites occur.

Chisel3 compile time much slower than Chisel2

Chisel 3 runtime is about 9-10 minutes for this configuration of Hwacha to generate FIRRTL. Chisel 2 creates verilog for this config in 3 minutes.

Chisel3 Output

[info] Running rocketchip.TestGenerator rocketchip Top ISCA2016Config --W0W --minimumCompatibility 3.0.0 --backend v --configName ISCA2016Config --compileInitializationUnoptimized --targetDir /scratch/colins/rocket-chip/vsim/generated-src --configDump --noInlineMem
[info] [0.001] Elaborating design...
Generated Address Map
        conf:devicetree 40000000 - 40007fff
        conf:csr0 40008000 - 4000ffff
        conf:scr 40010000 - 400101ff
Generated Configuration String
platform {
  vendor ucb;
  arch rocket;
};
ram {
  0 {
    addr 0;
    size 0x40000000;
  };
};
core {
  0 {
    0 {
      isa rv64;
      addr 0x40008000;
    };
  };
};

UNCORE_SCR: 40010000 -> N_CORES
UNCORE_SCR: 40010001 -> MMIO_BASE
UNCORE_SCR: 40010002 -> MEMORY_CHANNEL_MUX_SELECT
UNCORE_SCR: 4001003f -> HTIF_IO_CLOCK_DIVISOR
[info] [519.435] Done elaborating.

Chisel2 Output:

[info] Running rocketchip.TestGenerator rocketchip Top ISCA2016Config --W0W --minimumCompatibility 3.0.0 --backend v --configName ISCA2016Config --compileInitializationUnoptimized --targetDir /scratch/colins/rocket-chip/vsim/generated-src --configDump --noInlineMem
Generated Address Map
        conf:devicetree 40000000 - 40007fff
        conf:csr0 40008000 - 4000ffff
        conf:scr 40010000 - 400101ff
Generated Configuration String
platform {
  vendor ucb;
  arch rocket;
};
ram {
  0 {
    addr 0;
    size 0x40000000;
  };
};
core {
  0 {
    0 {
      isa rv64;
      addr 0x40008000;
    };
  };
};

UNCORE_SCR: 40010000 -> N_CORES
UNCORE_SCR: 40010001 -> MMIO_BASE
UNCORE_SCR: 40010002 -> MEMORY_CHANNEL_MUX_SELECT
UNCORE_SCR: 4001003f -> HTIF_IO_CLOCK_DIVISOR
[info] [126.447] // COMPILING < (class rocketchip.Top)>(14)
...
[info] [171.427] COMPILING <Top (class rocketchip.Top)> 14 CHILDREN (9,0)

Build instructions

What is the correct setting in build.sbt to use the local published version of Chisel 3? I tried to set it similar to Chisel 2:

libraryDependencies += "edu.berkeley.cs" %% "chisel" % "3.0-SNAPSHOT"

But got:
Note: Unresolved dependencies path:
[warn] edu.berkeley.cs:chisel_2.11:3.0-SNAPSHOT

macro assertion text is flaky

Here are two assertions that show up in rocket's uncore:

assert(!io.in.acquire.valid || !smallget || read_size_ok,
      "Can't perform Get wider than outer width")
assert(io.nasti.r.bits.resp === UInt(0), "NASTI read error")

They result in the following FIRRTL output:

printf(clk, UInt<1>(1), "Assertion failed: converters.scala:599 assert(!io.in.acquire.valid || !smallget || read_size_ok,: Can't perform Get wider than outer width\n")
printf(clk, UInt<1>(1), "Assertion failed: converters.scala:513 assert(io.nasti.r.bits.resp === UInt(0), \"NASTI read error\"): NASTI read error\n")

Note the first one erroneously grabs the comma after read_size_ok, and the second one redundantly grabs the assertion string. It seems that the macro is taking everything until the end of the line.

Width specification on IO ports

Currently, IO ports can be defined without widths and width inference in FIRRTL will take care of it. In process of porting over the Chisel 2 classic scala tester, we've come across the issue that we need to know the widths of the IO ports before FIRRTL is run. Regardless of this use case, it does make some sense to force the width to be defined on all the IO ports because the IO ports are the interface to a module and you don't have a fully specified interface without the width. However, there are use cases where sub module IO port widths should be inferred based on the context in which they are used. We should discuss this issue.

Tests use deprecated functions

A lot of the tests in chiselTests are using deprecated functions. It would be good (and a partial bonus to documentation) if this was fixed.

Naming a register 'reg' causes firrtl processing error

When a circuit contains a register definition like

val reg = Reg(init = UInt(0, width = 32))

It emits the following firrtl line

    reg reg : UInt<32>, clock, reset

This causes an error

   at /Users/chick/Aspire/IdeaProjects/firrtl/src/lib/stanza/compiler/[email protected]

There may be a family of such bugs. I was able to identify at least one other,
If I name a circuit inst like this

val inst = Module( new BadNameReg )

It creates a firrtl line

  inst inst of BadNameReg

Which leads to an error

[[email protected]] FIRRTL Parsing Error: Expected the 'of' keyword here.

Bits don't support BITwise operations

I am unable to logically or, and, xor, etc. two Bits together.

value | is not a member of Chisel.Bits

The definition of Bits has a comment in it

  // TODO: perhaps make this concrete?
  // Arguments for: self-checking code (can't do arithmetic on bits)
  // Arguments against: generates down to a FIRRTL UInt anyways

I would like to argue for having these operations.
Having a datatype that can only have logical ops performed gives the designer useful feedback when they inadvertently perform arithmetic on it.

The argument in the comment against doesn't seem sensible to me.
If chisel3 can help the designer make fewer mistakes why does it matter that the next stage of the compiler can't provide the same check.

Source Information via Macros, RFC

We need scala source information carried into the FIRRTL representation of the graph (see note 1 for caveat). This essentially needs to be done with the macro system.

Part 1: Basic Proposal with Implicits and Macro-based materializers
The general idea is that chisel API functions will take an implicit SourceInfo parameter. For example, addition will become:

def +(that: UInt)(implicit sinfo: SourceInfo): UInt = create_operation(...)

SourceInfo.scala has:

case class SourceInfo(filename: String, line: String, column: String)
object SourceInfo {
  implicit def materialize: SourceInfo = macro Locators.injectSourceInfo
}

Note, the compiler ultimately sees:

a + b // before macro expansion and implicit resolution
a.+(b)(_root_.chisel.SourceInfo("file.scala","1","3") // after

The use of implicits for this is partly inspired by https://github.com/lihaoyi/sourcecode (I was using implicits for a loosely related EnclosingModule concept way earlier). I want to use a separate implementation, or at least Chisel-specific SourceInfo subclass of those classes, so there is less chance of conflicts with other libraries that may use that library.
I can later walk through an implementation of using macros to extract line/file information as shown in gama: https://github.com/sdtwigg/gama/blob/master/chiselfrontend/src/main/scala/frontend/implementation/macrodefs/TransformMacro.scala#L16 (ignore the EnclosingModule part, that is a separate thing).

The general idea of using macros plus implicits rather than just macros is twofold. First, API functions that otherwise don't need macro transformations don't need to use macro transformations. They can just get SourceInfo by taking an implicit. Second, libraries can 'hide' their definitions from Chisel source locators so that Chisel instead 'sees' the caller of the user library through standard implicit chaining. e.g.

def add_uints(uints: Seq[UInt])(implicit sinfo: SourceInfo): UInt = uints.foldLeft(0.U)(_+_)

This should just work; however, the + nodes in the generated graph will have source information from where add_uints was called, not from where is was defined. (The implicit parameter on the function is shadowing the default macro-based materialization of SourceInfo.)

Part 2: Extension using macro transformations to hide implicits
Implicits do not play nice with chaining apply calls. Consider the following (somewhat silly but I don't want to define too many funcitons for this example):

myuint(5,0)(2,1)

class UInt { def apply(l: Int, r: Int)(implicit sinfo: SourceInfo): UInt = {...} }

You will get an error that 2, an Int, is not a SourceInfo. The Scala parser is interpreting the second set of parameters as an explicit override of the implicit parameters.

To resolve this case, we need to use the trick I used in gama. This is where I use macros, for example, to transform an apply or extract call into a do_extract call with extra arguments. The API similar to the following:

class UInt {
  def apply(l: Int, r: Int): UInt = macro XForm.to_do_extract
  def do_extract(l: Int, r: Int, sinfo: SourceInfo): UInt = create_operation(...)
}

myuint(5,0)(2,1) // before macro expansion
myuint.do_extract(5, 0, implicitly[SourceInfo]).do_extract(2, 1, implicitly[SourceInfo]) // after macro expansion, before implicit resolution

In summary, I like to say the macro transform into do_* is making the implicits explicit and unifying the argument lists. I know this trick works because I tested it extensively in gama. However, in gama, every operation is transformed into a do_* form.

This may be unnecessary. You only need to transform operations that you expect to be occasionally succeeded by an apply (like apply). (Edit: Actually, implicit resolution happens too late that (a+b)(0) is interpreted the same as a.+(b)(0)) Of course, for consistency, it may make sense to transform all operations (that return an applyable type. /edit)

Notice that in the Part 1 library case, you can't do add_uints(Seq(a, b))(0). To allow that, the library would have to use macros to transform into the do_* form as well.

Notes
Note 1: The proposals will, in general, only give one line of source information: the line that invoked the chisel API. If the user code involves libraries and intervening functions, this information may not be meaningful in all cases. For example, if I have a function that takes two parameters and just connects them together, then the source information will just point to that function definition. Thus, if FIRRTL reports an error, it will complain about that library code, which didn't necessarily make the mistake. Ideally, the frontend will still do sanity checks as much as possible since the frontend can dump the slightly more helpful stack traces.

Note 2: These proposals all use simple def macros and thus do not need macro paradise. This has a more comforting forward compatibility story.

Width inference crash on shr primop

The following simple circuit causes FIRRTL to crash during width inference:

circuit Test : 
  module Test : 
    input clock : Clock
    input reset : UInt<1>

    reg out_buf : UInt, clock, reset

    out_buf := shr(out_buf, 16)

sbt fail in run command after an external publish-local of a library dependency

I am running sbt in two different projects, chisel3 and chisel-tutorial, in the chisel3 project I do

publish-local

When it finishes, in chisel-tutorial I run

run GCDReal

I get the following

run RealGCD
[info] Updating {file:/Users/chick/Aspire/IdeaProjects/chisel-tutorial/solutions/}solutions...
[info] Resolving jline#jline;2.12.1 ...
[info] Done updating.
[info] Compiling 19 Scala sources to /Users/chick/Aspire/IdeaProjects/chisel-tutorial/solutions/target/scala-2.11/classes...
[info] Running TutorialSolutions.TutorialSolutions RealGCD
[info] [0.002] Elaborating design...
step
0
1
2
3
4
5
6
7
8
[info] [0.080] Done elaborating.
error java.lang.NullPointerException
java.lang.NullPointerException
at Chisel.testers.TesterDriver$$anonfun$copyResourceToFile$1.apply$mcI$sp(TesterDriver.scala:15)
at Chisel.testers.TesterDriver$$anonfun$copyResourceToFile$1.apply(TesterDriver.scala:15)
at Chisel.testers.TesterDriver$$anonfun$copyResourceToFile$1.apply(TesterDriver.scala:15)
at scala.collection.Iterator$$anon$9.next(Iterator.scala:162)
at scala.collection.Iterator$$anon$16.hasNext(Iterator.scala:536)
at scala.collection.Iterator$class.foreach(Iterator.scala:742)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1194)
at Chisel.testers.TesterDriver$.copyResourceToFile(TesterDriver.scala:15)
at Chisel.testers.TesterDriver$.execute(TesterDriver.scala:38)
at Chisel.testers.UnitTestRunners$class.execute(UnitTester.scala:10)
at TutorialSolutions.TutorialSolutions$.execute(solutions.scala:6)
at TutorialSolutions.TutorialSolutions$$anonfun$main$1.apply(solutions.scala:35)
at TutorialSolutions.TutorialSolutions$$anonfun$main$1.apply(solutions.scala:33)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
at TutorialSolutions.TutorialSolutions$.main(solutions.scala:33)
at TutorialSolutions.TutorialSolutions.main(solutions.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
[trace] Stack trace suppressed: run last compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last compile:run for the full output.
error Nonzero exit code: 1
[error] Total time: 8 s, completed Dec 15, 2015 7:36:13 PM

No default dynamicContext in Builder

This is not urgent, but as someone coming to Chisel from the scala side, I like to be able to go into the interpreter or scala worksheet and just fiddle around. The default Builder dynamic context of none prevents this. Changing line 88 of Builder.scala from

  private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None)

to

  private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](Some(new DynamicContext))

Let's me perform small experiments in interpreter, and seems to cause no harm to tests etc. Could we consider adopting this change, or are there deeper considerations behind this design decision.

Drowning in warnings in chisel3

Running GCD in chiselTests gives a bunch of errors of the following forms.

%Warning-STMTDLY: /var/folders/ls/0xl3wjy949b2b9j36yn36v3c0000gn/T/GCDTester2434714804424790707/GCDTester1526173926997725650.v:31: Unsupported: Ignoring delay on this delayed statement.
%Warning-WIDTH: /var/folders/ls/0xl3wjy949b2b9j36yn36v3c0000gn/T/GCDTester2434714804424790707/GCDTester1526173926997725650.v:27: Operator EQ expects 32 bits on the RHS, but RHS's CONST '1'h0' generates 1 bits.

For problems in the chisel-tutorials, there can be dozens or more of these lines and they dwarf the actual output.
Question:
Are these errors important, if so, can they be fixed.
Otherwise, can we suppress them, new chiselers will be unnerved and overwhelmed with this output

Assertions Fire on 1st rising clock edge

In rocket-chip we have a problem where lots of assertions fire on the first rising clock edge. While the generated FIRRTL and Verilog does have conditional statements predicated on reset not being asserted, in rocket-chip, we have pipelined resets where it takes a couple of cycles for reset to propagate from the top-level reset to each module. This leads to assertions firing because their local reset randomly initialized to zero, thus the assertion can fire even though reset has yet to be asserted.

Chisel 2 solves this issue by creating non-synthesizable 1 bit values that initialize to 0, and are set to 1 the first time the local reset is asserted.

  always @(posedge clk) begin
`ifndef SYNTHESIS
// synthesis translate_off
  if(reset) T0 <= 1'b1;
  if(!T1 && T0 && !reset) begin
    $fwrite(32'h80000002, "ASSERTION FAILED: %s\n", "VoluntaryReleaseTracker accepted Release that wasn't voluntary!");                                                                                                                                                    
    $finish;
  end
// synthesis translate_on
`endif

There are a couple of ways to solve this in Chisel 3: We could add similar unsynthesizable magic to the FIRRTL Verilog emitter. This is problematic, however, because FIRRTL does not treat resets as special so this might be either specific to Chsiel 3 generated FIRRTL or use some inference that would probably be brittle. It could be enhanced by adding a "reset" field to printf and stop in FIRRTL.

The better solution in my opinion is in Chisel 3. We could propagate the top-level reset to each register, and include this reset in the condition for allowing any assertions to fire. This adds a restriction that global reset must be asserted for long enough that it overlaps with every local module reset, but this isn't all that bad of a restriction. It has the nice property of being synthesizable too.

Chisel errors should suggest a resolution.

Example: "Parameterized Bundle class (blah) needs cloneType method. You are probably using an anonymous Bundle object that captures external state and hence is un-cloneTypeable in class (blah)"

It does a good job telling me very specifically what the error is, but doesn't suggest a resolution strategy. Should the Bundle not be a nested class? Does it just need to have a cloneType overloaded?

Bad Error Message when Wire, Reg not used

Problem

val internal_wire = UInt()
internal_wire := io.in * 2
io.out := internal_wire

You will get a FIRRTL error saying that internal_wire is not defined. The error is far worse to manage when the name wasn't detectable. This issue is particularly relevant when porting from chisel2 to chisel3; however, it could easily come up when writing new RTL.

Proposal
My advised strategy is for the Wire, Reg, Literal, etc. constructions to also tag the datatype's nodes with information of what they are in the hardware graph (wires, regs, literals, etc.). Then, operations like connects or arithmetic, throw an error when involving operands not actually on the hardware graph.

You run into an issue with ports (as all current code does val io = // raw Data instantiation here). This is where my proposal to declare IOs as part of the Module constructor arguments comes into play. (The Module constructor can then tag the granted IO with the port information).

Allow for bulk connect on Seq?

In chisel2 I was able to create a Vec of nodes and bulk connect them to another Vec of the same type as follows

  val issue = Vec(io.abox(0), io.pbox(0),
    agent.io.span(io.abox(1), io.pbox(1)), io.abox(2))
  issue <> agent.io.issue

In order to use chisel3 this is transformed to

  val issue = Seq(io.abox(0), io.pbox(0),
    agent.io.span(io.abox(1), io.pbox(1)), io.abox(2))
  issue zip agent.io.issue map {case(s,d) => s := d}

The issue Vec/Seq in this case will not be dynamically indexed itself but the agent.io.issue Vec will be, so it seemed reasonable to match the types for the previous <> usage.

Is this transformation the only way chisel3 will support this operation?

Creating a reg of vec, fails to emit a declaration, causes firrtl error

Running https://github.com/ucb-bar/chisel-tutorial/blob/chisel3prep/solutions/VecShiftRegisterParam.scala
via the Launcher.scala in the same directory
Using chisel3 and the new_unit_test branch

Causes an error
Starting High Form Check
Fatal Uncaught Exception.
[email protected]: [module VecShiftRegisterParam]  Reference T_8 is not declared.
   at /Users/chick/Aspire/IdeaProjects/firrtl/src/lib/stanza/compiler/[email protected]

head of produced firrtl, shows reference to T_8, which has not been emitted

      1 circuit VecShiftRegisterParamTests :
      2   module VecShiftRegisterParam :
      3     input clk : Clock
      4     input reset : UInt<1>
      5     output io : {flip in : UInt<4>, out : UInt<4>}
      6
      7     io is invalid
      8     reg delays : UInt<4>[8], clk with : (reset => (reset, T_8))
      9     delays[7] <= delays[6]
     10     delays[6] <= delays[5]

VecShiftRegisterParamTests5447116487126880273.fir.txt

chisel2 vs. chisel3 <>, := semantics

I can get into examples if necessary: But, basically, <> and := work very different in chisel3 than in chisel2.

In chisel2, := is a mono-directional connect operator where you knew the LHS was a sink and the RHS was a source. <> is a bi-directional connect operator where is figured whether nets were sources or sinks. (This required at least one side to be an IO so the appropriate direction hints were available.) A nice property of <> was that it was commutative.

In chisel3, the semantics are a bit more topsy turvy. In code, it seems like <> is often just an alias for :=. I keep running into oddities and bugs related to the edge cases for this. (In old code one of the structs was defines as all being inputs instead of all being outputs and this led to really crazy verilog.) Also, in some cases, it isn't clear which argument has to be on the LHS for a <> connection between two module IOs.

Given that chisel3 tries to maintain compatibility with chisel2, what are the drawbacks of restoring the chisel2 behavior in chisel3? I'm willing to go through necessary measures to fix this.

Arbiter family of apply methods use (gen: T, n: Int) signature

Possible minor consistency issue. While most things aggregate or aggregate like, in chisel3, use the signature
The following Arbiter, RRArbiter, ArbiterIO,QueueIO, use the older form.
(n:Int, gen: T), with the flipped argument version deprecated or removed.
It could be that these are not worth changing, but it would be an easy fix I could make to provide new apply methods and deprecate the older forms

Why does Top.cpp run 10 extra cycles?

This seems somewhat arbitrary. (At best, I can think of needing 1 or 2 to get waves after an assert fails.)

The main impact of this change is that it is harder to write a 'tightly timed' unit test.

Separation of Utils and Frontend

With macro-based source locators happening ( #147 ), there now needs to be a clean separation of the Chisel frontend (core data types - Bool, UInt, etc) and things which invoke the frontend (like utils - Mux, Cat, PopCount, and friends) because macros require definition and invocation to be in different compilation units.

I think it makes sense for Chisel utils be strictly dependent on Chisel frontend since it provides an example of how libraries can be written and structured (rather than invoking Chisel frontend internal functions directly, bypassing the source locator macro layer). If necessary, utils can also have transform macros for source locators, and may demonstrate multiple levels of source locators.

Anyways, the current problematic calls I've found are:

  • Data.toBits is dependent on Cat
  • Vec.count is dependent on PopCount
  • Vec.{indexWhere, lastIndexWhere} are dependent on PriorityMux
  • Vec.onlyIndexWhere is dependent on Mux1H

This issue was brought up about a year ago, during the Chisel3 code review, but that was before separate compilation needed to happen, so the consensus then was to leave it as-is. That's not necessarily a good option anymore. Thoughts for solving this?

Tests don't appear to check correctness

It seems they look for assertions (which don't seem to work) but not the simulation error return value. All tests pass, even those with a nonzero return.

Chisel 2 compatibility: assignment of UInt to Vec

I'm porting the LBNL OpenSoC code to Chisel and have come across a statement that looks like:

val a = Vec(UInt())
a := UInt(0)

Chisel 2 actually assigns UInt(0) to each element in a. Chisel 3 doesn't support this type of assignment. Should this be supported in Chisel 3? If not, we should change the chisel 2 compatibility mode checker to flag this as an error.

Personally, I don't think this type of assignment makes a whole lot of sense, but would love to hear everyone's thoughts on the issue.

Creating a DeqIO causes unchecked recursion

The following line in examples/Router.scala:21

  val reads   = new DeqIO(new ReadCmd())

causes unchecked recursion as the gen argument is flipped and flipped..

    at Chisel.DeqIO.<init>(Decoupled.scala:38)
    at Chisel.DeqIO.cloneType(Decoupled.scala:41)
    at Chisel.DeqIO.cloneType(Decoupled.scala:36)
    at Chisel.Data.cloneWithDirection(Data.scala:37)
    at Chisel.Data.flip(Data.scala:45)
    at Chisel.DeqIO.<init>(Decoupled.scala:38)
    at Chisel.DeqIO.cloneType(Decoupled.scala:41)
    at Chisel.DeqIO.cloneType(Decoupled.scala:36)
    at Chisel.Data.cloneWithDirection(Data.scala:37)
    at Chisel.Data.flip(Data.scala:45)
    at Chisel.DeqIO.<init>(Decoupled.scala:38)
    at Chisel.DeqIO.cloneType(Decoupled.scala:41)
    at Chisel.DeqIO.cloneType(Decoupled.scala:36)
    at Chisel.Data.cloneWithDirection(Data.scala:37)

scalastyle*.xml files break using chisel3 as a submodule

I have chisel3 as a submodule of another repo, the line

(scalastyleConfig in Test) := baseDirectory.value / "scalastyle-test-config.xml"

breaks everything with the error

error: not found: value scalastyleConfig
(scalastyleConfig in Test) := baseDirectory.value / "scalastyle-test-config.xml"
 ^
[error] Type error in expression

This does not manifest when running chisel3 from within its directory, but does when you try to use chisel3 as a sbt dependency.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.