Chisel Overview

Overview

졜근 Softcore 동ν–₯μ—μ„œ μ£Όλͺ©λ°›λŠ” Chisel 을 μ†Œκ°œν•©λ‹ˆλ‹€.

Constructing Hardware in a Scala Embedded Language (Chisel)

Chisel 의 νŠΉμ„±μ„ μ‚΄νŽ΄λ³΄λ©΄

RTL generator 듀은 Chisel 둜 λ§Œλ“€μ–΄μ§‘λ‹ˆλ‹€.

  • scala λ₯Ό 기반으둜 μ‚¬μš©ν•˜λŠ” HDL

Scala μ–Έμ–΄μ˜ 쒋은 νŠΉμ„±μ„ 많이 μ“Έ 수 μžˆμŠ΅λ‹ˆλ‹€.

  • object-oriented programming
  • functional programming

또 ν₯미둜운 ν”„λ‘œμ νŠΈλ“€μ΄ 많이 μžˆλŠ”λ°, ν•˜λ‚˜λ₯Ό 예둜 λ“€λ©΄

RISC-V “Rocket Chip” SoC Generator1

특히 Rocket Chip2 을 기반으둜 FPGA λ³΄λ“œμ— μ˜¬λ €μ„œ λ§Œλ“ 

lowrisc 데λͺ¨μ˜μƒμ„ 보고 감동을 λ°›μ•˜μŠ΅λ‹ˆλ‹€.

lowrisc demo



κ·Έ κ°λ™μ˜ 원인은,

κΈ°μ‘΄ FPGA & Arm (기타 λ“±λ“±..) core κ°€ SoC 에 λ“€μ–΄μžˆμ–΄ λ¦¬λˆ…μŠ€ λΆ€νŒ… κ°€λŠ₯ν•œ λ³΄λ“œκ°€ μ•„λ‹ˆλΌ

FPGA μ—μ„œ ν•©μ„±ν•΄μ„œ CPU, FPU, λ©”λͺ¨λ¦¬ 컨트둀러, λ²„μŠ€κΉŒμ§€ κ°œλ°œμžκ°€ λšλ”±!

그것도 νŽŒμ›¨μ–΄ μˆ˜μ€€μ΄ μ•„λ‹ˆλΌ, λ¦¬λˆ…μŠ€ λΆ€νŒ…κΉŒμ§€ κ°€λŠ₯ν•œ ν•˜λ“œμ›¨μ–΄ μ„€κ³„λΌλŠ” μ μž…λ‹ˆλ‹€!

ꡉμž₯히 λ²”μš©μ μœΌλ‘œ ν•˜λ“œμ›¨μ–΄ 가속화λ₯Ό μ‚¬μš©ν•  수 μžˆμ„κ±°λΌ 생각이 λ“œλ„€μš”.

lowrisc getting started 3에 보면 μœ„μ˜ 데λͺ¨λ₯Ό μœ„ν•œ λ‚΄μš©μ΄ λ‚˜μ™€μžˆμŠ΅λ‹ˆλ‹€.

Chisel example source code

adder μ½”λ“œ μ˜ˆμ‹œλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

example - adder

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Add extends Module {

    val io = IO(new Bundle {
        val a = Input(UInt(8.W))
        val b = Input(UInt(8.W))
        val y = Output(UInt(8.W))
    })

    io.y := io.a + io.b
}

μ΅œκ·Όμ— λ‚˜μ˜¨ μ–Έμ–΄λ“€μ˜ νŠΉμ§•μ΄κΈ°λ„ ν•˜κ³ ,

Scala 문법을 λ”°λΌμ„œ

λͺ¨λ“ˆλ§ˆλ‹€ λͺ…μ‹œν•΄μ£Όλ˜ λ³€μˆ˜ 선언이 κ°„νŽΈν•΄μ‘Œλ„€μš”.

example - stack

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Stack(val depth: Int) extends Module {
    
    val io = new Bundle {
        val push = Bool(INPUT)
        val pop = Bool(INPUT)
        val en = Bool(INPUT)
        val dataIn = UInt(INPUT, 32)
        val dataOut = UInt(OUTPUT, 32)
    }

    val stack_mem = Mem(UInt(width = 32), depth)
    val sp = Reg(init = UInt(0, width = log2Up(depth+1)))
    val dataOut = Reg(init = UInt(0, width = 32))

    when (io.en) {
        when(io.push && (sp < UInt(depth))) {
            stack_mem(sp) := io.dataIn
            sp := sp + UInt(1)
        } .elsewhen(io.pop && (sp > UInt(0))) {
            sp := sp - UInt(1)
        }

        when (sp > UInt(0)) {
            dataOut := stack_mem(sp - UInt(1))
        }
    }

    io.dataOut := dataOut
}

ν˜ΈμΆœν•΄μ„œ μ‚¬μš©ν•˜λŠ” 각 λͺ¨λ“ˆμ΄ μ–΄λ–€μ‹μœΌλ‘œ Overload λ˜μ–΄ μžˆλŠ”μ§€ κΆκΈˆν•΄μ§€λŠ” μ½”λ“œλ„€μš”.

example - stack unit test

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class StackTests(c: Stack) extends Tester(c) {
    var nxtDataOut = 0
    val stack = new ScalaStack[Int]()

    for (t <- 0 until 16) {
        val enable = rnd.nextInt(2)
        val push = rnd.nextInt(2)
        val pop = rnd.nextInt(2)
        val dataIn = rnd.nextInt(256)
        val dataOut = nxtDataOut

        if (enable == 1) {
            if (stack.length > 0)
                nxtDataOut = stack.top

            if (push == 1 && stack.length < c.depth) {
                stack.push(dataIn)
            } else if (pop == 1 && stack.length > 0) {
                stack.pop()
            }
        }

        poke(c.io.pop, pop)
        poke(c.io.push, push)
        poke(c.io.en, enable)
        poke(c.io.dataIn, dataIn)

        step(1)
        
        expect(c.io.dataOut, dataOut)
    }
}

unit test μ½”λ“œλŠ” κ³Όμ—° 이 μ½”λ“œκ°€ ν•˜λ“œμ›¨μ–΄λ₯Ό ν…ŒμŠ€νŠΈ ν•˜λŠ”κ²Œ λ§žμ„κΉŒ? ν•˜λŠ” 생각이 λ“œλ„€μš”.


Summary

μ˜€λŠ˜λ‚  μ†Œν”„νŠΈμ›¨μ–΄ 개발이 λΈ”λž™λ°•μŠ€λ₯Ό 가지고 νŽΈν•˜κ²Œ λΉ„μ§€λ‹ˆμŠ€ λ‘œμ§μ„ κ°œλ°œν•˜λ“―μ΄,

ν•˜λ“œμ›¨μ–΄ κ°œλ°œλ„ μ–Όλ§ˆ 만큼 νŽΈν•˜κ³  생산성 μ’‹κ²Œ κ΅¬ν˜„ν•  수 μžˆμ„μ§€ κΈ°λŒ€λ˜κ³  κΆκΈˆν•˜λ„€μš”.



  1. Chisel – Accelerating Hardware Design pdf link ↩︎

  2. Rocket Chip pdf link ↩︎

  3. lowrisc getting started link ↩︎