1
votes

Consider a module that does some simple arithmetic and is controlled by a few parameters. One parameter controls the top level behavior: the module either reads its inputs from its module ports, or from other parameters. Therefore, the result will either be dynamically computed, or statically known at compile (cough, synthesis) time.

The Verilog generated by Chisel has different module names for the various flavors of this module, as expected. For the case where the result is statically known, there is a module with just one output port and a set of internal wires that are assigned constants and then implement the arithmetic to drive that output.

Is it possible to ask Chisel or FIRRTL to go further and completely optimize this away, i.e. in the next level of hierarchy up, just replace the instantiated module with its constant and statically known result? (granted that these constant values should by optimized away during synthesis, but maybe there are complicated use cases where this kind of elaboration time optimization could be useful).

1

1 Answers

2
votes

For simple things that Firrtl currently knows how to constant propagate, it already actually does this. The issue is that it currently doesn't const prop arithmetic operators. I am planning to expand what operators can be constant propagated in the Chisel 3.1 release expected around New Years.

Below is an example of 3.0 behavior constant propagating a logical AND and a MUX.

import chisel3._

class OptChild extends Module {
  val io = IO(new Bundle {
    val a = Input(UInt(32.W))
    val b = Input(UInt(32.W))
    val s = Input(Bool())
    val z = Output(UInt(32.W))
  })

  when (io.s) {
    io.z := io.a & "hffff0000".U
  } .otherwise {
    io.z := io.b & "h0000ffff".U
  }
}

class Optimize extends Module {
  val io = IO(new Bundle {
    val out = Output(UInt())
  })
  val child = Module(new OptChild)
  child.io.a := "hdeadbeef".U
  child.io.b := "hbadcad00".U
  child.io.s := true.B
  io.out := child.io.z

}

object OptimizeTop extends App {
  chisel3.Driver.execute(args, () => new Optimize)
}

The emitted Verilog looks like:

module Optimize(
  input         clock,
  input         reset,
  output [31:0] io_out
);
  assign io_out = 32'hdead0000;
endmodule