S. Takano
S. Takano

Reputation: 313

"for-loop" to reduce coding on Chisel3.2

I want to code with for-loop for redundant part.

Coding.

//Priority Encoder
class P_Encoder(NumInputs: UInt) extends Module {
    val io = new Bundle {
        val Req[NumInputs]          = Bool(INPUT)                   //Requests
        val Rls[NumInputs]          = Bool(INPUT)                   //Releases
        val Grant[NumInputs]        = UInt(OUTPUT(log(NumInputs)))  //Grants
    }

    val cnt = 0
    for (i<-0 to NumInputs-1) {
        when (io.Req[i] & !io.Rls[i]) {
            cnt         := cnt + 1.W
            io.Grant[i] = cnt
        }
        else {
            io.Grant[i] = 0.W
        }
    }
}

I want to code using "for-loop" to code redundant part.

Upvotes: 2

Views: 1144

Answers (2)

Chick Markley
Chick Markley

Reputation: 4051

I agree with everything @jkoenig says. In an another example assuming Jack's IO structure, there are times I like using foldLeft combined with when/elsewhen

io.rel.zip(io.req).zipWithIndex.foldLeft(when(false.B){}) { case (lastWhen,((req, rel), index)) =>
    lastWhen.elsewhen(req && !rel) {
      io.grant := index.U
    }
  } otherwise {
    io.grant := 0.U
  }

when and elsewhen both return a WhenClause which can be used with foldLeft to keep adding clauses.

Upvotes: 2

Jack Koenig
Jack Koenig

Reputation: 6064

There are a few minor issues with this code:

  • Generally we name variables starting with a lower-case letter in Scala, this is primarily style, but it does have semantic meaning it certain circumstances (like pattern matching)
  • Square brackets are only used for type parameters (like Java generics), indexing uses normal parentheses in Scala
  • An input Vec of Bools is normally defined as: val req = Input(Vec(numInputs, Bool())) (assuming import chisel3._, but this should also work in Chisel._ for Chisel 3.2)
  • if and else are used for static parameterization (ie. at hardware elaboration time) while when and .otherwise are used for dynamic logic (eg. actual muxes)
  • UInt is for hardware types, if you have a static parameter (like numInputs), use a Scala Int

Other than the minor syntactical stuff, the trickiest part of getting this code right is understanding the difference between Scala constructs that are only run at elaboration time (ie. when the Scala program generates the hardware), vs. what actually shows up in the hardware. I would suggest reading this thread from the chisel-users mailing list for some more context about some of this stuff: https://groups.google.com/d/msg/chisel-users/gRoNnH-Y5hE/ynDCtmNPCAAJ

I'm a little confused as to what value io.grant is supposed to get, but I'm assuming it should be the index of the highest priority io.req. Here's an untested version of your code that I think should work and do what you want:

//Priority Encoder
class P_Encoder(numInputs: Int) extends Module {
    // We wrap ports in IO
    val io = IO(new Bundle {
        val req        = Input(Vec(numInputs, Bool()))
        val rls        = Input(Vec(numInputs, Bool()))
        val grant      = Output(UInt(log2Up(numInputs).W))
    })
    io.grant := 0.U // default grant value
    // Due to Chisel last connect semantics, the last connection wins
    // Thus the highest index will have priority
    for (i <- 0 to numInputs - 1) {
        when (io.req(i) && !io.rls(i)) {
            io.grant := i.U
        }
    }
}

This code is tricky because it's mixing an elaboration time for loop with hardware whens and connections, I'm going to manually unroll this loop to illustrate what it's doing:

    io.grant := 0.U
    when (io.req(0) && !io.rls(0)) {
        io.grant := 0.U
    }
    when (io.req(1) && !io.rls(1)) {
        io.grant := 1.U
    }
    when (io.req(2) && !io.rls(2)) {
        io.grant := 2.U
    }
    ...

Alternatively, we can just reuse the built-in PriorityEncoder utility if we want

import chisel3.util.PriorityEncoder
val enables = io.req.zip(io.rls).map { case (x, y) => x && !y }
// PriorityEncoder gives priority to *lowest* order bit
io.grant := PriorityEncoder(enables)

Upvotes: 2

Related Questions