Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Brief Tour of Functional HDLs

mt_caret
August 25, 2019

A Brief Tour of Functional HDLs

mt_caret

August 25, 2019
Tweet

More Decks by mt_caret

Other Decks in Technology

Transcript

  1. whoami Faculty of Science and Technology, Computer Science major I

    need a thesis topic, like, yesterday mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 2 / 19
  2. motivation NRE costs for ASIC development is absurdly high chip

    costs: shuttle runs cost $30,0001 larger scale tapeouts cost several million ~ tens of millions of $s bugs cost astronomical amounts as well ex. the Intel FDIV bug costed approx. $4.75m2 effort goes into verification to ensure correctness chip verification is a well-known use case for formal methods so, chip development workflow naturally optimizes for developer efficiency and correctness. . . 1Computer Architecture, Sixth Edition: A Quantitative Approach 2Pentium FDIV flaw FAQ http://www.trnicely.net/pentbug/pentbug.html mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 3 / 19
  3. motivation actual workflow (at a small scale shop) EDA tool

    compatibility is terrible, etc etc constant lack of people results in cutting corners (especially verification) seems like this happens at big shops too3 Hardware Description Lanugages (HDL) are terrible Verilog sucks4 I hear SystemVerilog is ok, but EDA tools have varying levels of compatibility5 3CPU bugs https://danluu.com/cpu-bugs/ 4Verilog is weird https://danluu.com/why-hardware-development-is-hard/ 5why SystemVerilog is bad for You. https://www.linkedin.com/pulse/why-systemverilog-bad-you-ilia-greenblat/ mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 5 / 19
  4. functional HDLs Connection between functional programming languages and digital logic6

    ex. implement HDLs as an embedded domain specific language (EDSL) is functional languages possible gains less stress higher levels of abstraction, expressivity faster simulations easier verification etc. 6c.f. Cλash or: Just because you’re using an FPGA doesn’t mean you have to lower your standards http://yager.io/talks/CLaSH.pdf mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 6 / 19
  5. functional HDL zoo CλaSH: Synthesis from Haskell compiler IR Chisel:

    Scala EDSL hardcaml: OCaml EDSL ForSyDe, HHDL, Lava: Haskell EDSLs Bluespec: Started out as a Haskell EDSL lambda-ccc7: Conversion from Haskell via CCCs8 SpinalHDL: a Scala EDSL, similar in spirit to Chisel9 7conal/lambda-ccc: Convert lambda expressions to CCC combinators https://github.com/conal/lambda-ccc 8Compiling to categories http://conal.net/papers/compiling-to-categories/ 9Add comparison with Chisel to the documentation https://github.com/SpinalHDL/SpinalHDL/issues/202 mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 7 / 19
  6. CλaSH11 While Chisel and hardcaml are written at the same

    level as RTL, CλaSH synthesizes circuits from Core, GHC’s (Haskell’s compiler) lazily evaluated, lambda calculus intermediate language10. CλaSH produces some surprisingly readable Verilog, and it’s fairly easy to predict what kind of Verilog you get from Haskell. For example, type MaybeNum = Maybe (Unsigned 8) will synthesize to a 9-bit (8 bits + 1 bit for constructor tag) wire. 10Into the Core - Squeezing Haskell into Nine Constructors https://www.youtube.com/watch?v=uR_VzYxvbxg 11Haskell as a higher order structural hardware description language. https://essay.utwente.nl/59381/ mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 8 / 19
  7. this. . . -- Test.hs module Test where import Clash.Prelude

    type Output = Unsigned 8 counter :: HiddenClockResetEnable dom => Signal dom Output counter = register 0 (counter + 1) topEntity :: Clock System -> Reset System -> Enable System -> Signal System Output topEntity = exposeClockResetEnable counter {-# NOINLINE topEntity #-} mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 9 / 19
  8. . . . becomes this module Test_topEntity ( // Inputs

    input clk // clock , input rst // reset , input en // Outputs , output wire [7:0] result ); wire [7:0] c$result_rec; // register begin reg [7:0] c$result_rec_reg = 8 d0 ; always @(posedge clk or posedge rst) begin : c$result_rec_register if ( rst) begin c$result_rec_reg <= 8 d0; end else if (en) begin c$result_rec_reg <= (c$result_rec + 8 d1); end end assign c$result_rec = c$result_rec_reg; // register end assign result = c$result_rec; endmodule mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 10 / 19
  9. Chisel15 Chisel is a EDSL based in Scala. Used to

    tapeout the Edge TPU12, among a number of tapeouts. Large research effort13 & conferences14 probably makes this the safest bet out the three. Don’t have much to say about writing Chisel, but the imperative style of writing Chisel feel fairly intuitive, and onboarding hardware engineers might be relatively easier? 12Experiences Building Edge TPU with Chisel https://www.youtube.com/watch?v=x85342Cny8c 13Berkeley Architecture Research https://bar.eecs.berkeley.edu/index.html 14https://chisel-community-conference.org/home 15Chisel: Constructing Hardware in a Scala Embedded Language https://chisel.eecs.berkeley.edu/chisel-dac2012.pdf mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 11 / 19
  10. this. . . import chisel3._ import chisel3.Driver class Counter extends

    Module { val io = IO(new Bundle { val q = Output(UInt(8.W)) }) val cntReg = RegInit(0.U(8.W)) cntReg := cntReg + 1.U io.q := cntReg } object Counter extends App { chisel3.Driver.execute(Array[String](), () => new Counter()) } mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 12 / 19
  11. . . . gets translated to this. . . ;buildInfoPackage:

    chisel3, version: 3.1.3, scalaVersion: 2.11.12, ; sbtVersion: 1.1.1, builtAtString: 2018-09-12 19:37:29.007, ; builtAtMillis: 1536781049007 circuit Counter : module Counter : input clock : Clock input reset : UInt<1> output io : {q : UInt<8>} reg cntReg : UInt<8>, clock with : (reset => (reset, UInt<8>("h00"))) @[Counter.scala 9:23] node _T_10 = add(cntReg, UInt<1>("h01")) @[Counter.scala 11:20] node _T_11 = tail(_T_10, 1) @[Counter.scala 11:20] cntReg <= _T_11 @[Counter.scala 11:10] io.q <= cntReg @[Counter.scala 12:8] mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 13 / 19
  12. . . . then this module Counter( // @[:@3.2] input

    clock, // @[:@4.4] input reset, // @[:@5.4] output [7:0] io_q // @[:@6.4] ); reg [7:0] cntReg; // @[Counter.scala 9:23:@8.4] reg [31:0] _RAND_0; wire [8:0] _T_10; // @[Counter.scala 11:20:@9.4] wire [7:0] _T_11; // @[Counter.scala 11:20:@10.4] assign _T_10 = cntReg + 8 h1; // @[Counter.scala 11:20:@9.4] assign _T_11 = _T_10[7:0]; // @[Counter.scala 11:20:@10.4] assign io_q = cntReg; // @[Counter.scala 12:8:@12.4] ifdef RANDOMIZE_GARBAGE_ASSIGN define RANDOMIZE endif ifdef RANDOMIZE_INVALID_ASSIGN define RANDOMIZE endif ifdef RANDOMIZE_REG_INIT define RANDOMIZE endif ifdef RANDOMIZE_MEM_INIT define RANDOMIZE endif ifndef RANDOM define RANDOM $random endif ifdef RANDOMIZE integer initvar; initial begin ifdef INIT_RANDOM INIT_RANDOM endif ifndef VERILATOR ifdef RANDOMIZE_DELAY # RANDOMIZE_DELAY begin end else #0.002 begin end endif endif ifdef RANDOMIZE_REG_INIT _RAND_0 = {1{ RANDOM}}; cntReg = _RAND_0[7:0]; endif // RANDOMIZE_REG_INIT end endif // RANDOMIZE always @(posedge clock) begin if (reset) begin cntReg <= 8 h0; end else begin cntReg <= _T_11; end end endmodule mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 14 / 19
  13. hardcaml16 Functional HDL currently developed at Jane Street Capital (also

    develops Core, one of OCaml’s standard libraries). Level of abstraction feels similar to Chisel. Not much information available on the internet. 16OCaml All The Way Down https://www.youtube.com/watch?v=X1cgRXhpQLY mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 15 / 19
  14. this. . . open! Hardcaml module Counter = struct module

    I = struct type a t = { clk : a ; clr : a ; enable : a } [@@deriving sexp_of, hardcaml] end module O = struct type a t = { q : a [@bits 8] } [@@deriving sexp_of, hardcaml] end let f (i : Signal.t I.t) = let open Signal in let w = 8 in let reg_spec = Reg_spec.create () ~clock:i.clk ~clear:i.clr in let update d = mux2 i.clr (zero w) (d +:. 1) in { O.q = reg_fb reg_spec ~enable:i.enable ~w update } ;; end module C = Circuit.With_interface (Counter.I)(Counter.O) let () = C.create_exn ~name:"counter" Counter.f |> Rtl.print Verilog ;; mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 16 / 19
  15. . . . becomes this module counter ( enable, clk,

    clr, q ); input enable; input clk; input clr; output [7:0] q; /* signal declarations */ wire _2; wire [7:0] _10 = 8 b00000000; wire [7:0] _9 = 8 b00000000; wire _4; wire [7:0] _14 = 8 b00000000; wire [7:0] _12 = 8 b00000001; wire [7:0] _13; wire _6; wire [7:0] _15; wire [7:0] _7; reg [7:0] _11; /* logic */ assign _2 = enable; assign _4 = clk; assign _13 = _11 + _12; assign _6 = clr; assign _15 = _6 ? _14 : _13; assign _7 = _15; always @(posedge _4) begin if (_6) _11 <= _10; else if (_2) _11 <= _7; end /* aliases */ /* output assignments */ assign q = _11; endmodule mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 17 / 19
  16. issues with functional HDLs learning curve associated with host languages

    ~ community size difficulty something like Haskell > > > Scala > OCaml? applying formal methods are probably easier, but AFAIK not much applying is happening hardcaml has some equivalence checking with Verilog, which is amazing we need more of this everything still is beta-ish maturity feels like chisel > > > > > clash, hardcaml but all have commerical adopters, so development probably won’t disappear in the near future mt_caret (@katakata-talks.0) Brief Tour of Functional HDLs 2019-08-25 18 / 19