What is the proper way to specify a default value for a Bundle?

817 views
Skip to first unread message

Christopher Celio

unread,
Apr 17, 2014, 6:36:00 PM4/17/14
to chisel...@googlegroups.com
// Here are some use cases I would like to handle... how can I make this work?

class MyBundle extends Bundle
{
   val x = Bool()
   val y = UInt(width=2)
   val z = Bool()
}


// Use Case #1
val reg_a = Reg(init = MyInitBundle) // what does MyInitBundle look like?

// Use Case #2
val reg_b = Reg(outType = MyBundle)

when (something)
{
   reg_b := MyInitBundle
}


What does MyInitBundle look like, to make the above use cases work seamlessly?

This has been the best I can do so far, but it doesn't work inside of when() statements:

def MyInitBundle(): MyBundle =
{
   val b = new MyBundle
   b.x := Bool(false)
   b.y := UInt(0)
   b
}

Again, that barfs on Use Case #2. The best I can do is:

val nullval = MyInitBundle
when (something)
{
  reg_b := nullval
}

Which is hugely non-intuitive.

Finally, as an additional constraint, I may NOT want to specify initial values for ALL of the fields in the bundle.  My bundles are very large and I can't waste the hardware resetting every inconsequential value.


-Chris



Wolfgang Puffitsch

unread,
Apr 17, 2014, 6:54:18 PM4/17/14
to chisel...@googlegroups.com
Hi Chris,

For Patmos we had a similar problem. I ended up having a function
reset() in the bundle for use case 2, and an object with a function
resetVal() for use case 1. You find examples for this at
https://github.com/t-crest/patmos/blob/master/hardware/src/patmos/connections.scala
Suggestions to achieve the same thing with less clutter would be
appreciated though. In some cases, this pattern ends up adding quite a
bit of boiler-plate code (see for example
https://github.com/t-crest/patmos/blob/master/hardware/src/ocp/Ocp.scala)

Cheers,
Wolfgang

edm...@edmondcote.com

unread,
Mar 22, 2017, 11:32:54 AM3/22/17
to chisel-users
Has this been resolved since 2014?

edm...@edmondcote.com

unread,
Mar 23, 2017, 11:10:46 PM3/23/17
to chisel-users

I played around with an example with, imho, deserves a look.

My example may be different.  It would be nice to initialize a Reg of a Bundle with a default value (sync reset value) .  Not sure whether this is supported.

class DDR3Command extends Bundle {
  val casN
= UInt(1.W)
  val rasN
= UInt(1.W)
  val ba
= UInt(3.W)
 
def defaults() = {
    casN
:= 1.U // reset value should be non-zero
    rasN
:= 1.U
    ba
:= 0.U
 
}
}

class MemoryController extends Module {
  val io
= IO(new Bundle {
    val ddr3
= Output(new DDR3Command())
 
})

 
// attempting to model a register with synchronous reset
  val nextDDR3Cmd
= Reg(new DDR3Command())

 
when (reset) { // chisel global reset
    nextDDR3Cmd
.defaults()
 
} .elsewhen (true.B) {
    nextDDR3Cmd
.ba := 3.U
    nextDDR3Cmd
.casN := 0.U
//    nextDDR3Cmd.rasN := 0.U // never update this
 
}
  io
.ddr3 := nextDDR3Cmd // assign to output
}

The resulting RTL is funky and might not synthesize correctly.  If reset is not first stmt in always block, then violating synthesizable guidelines and linting checks.

  always @(posedge clock) begin
   
if (_T_22) begin
      nextDDR3Cmd_casN
<= 1'h0;
    end else begin
      if (reset) begin
        nextDDR3Cmd_casN <= 1'
h1;
     
end
   
end
   
if (reset) begin
      nextDDR3Cmd_rasN
<= 1'h1;
    end
    if (_T_22) begin
      nextDDR3Cmd_ba <= 3'
h3;
   
end else begin
     
if (reset) begin
        nextDDR3Cmd_ba
<= 3'h0;
      end
    end
  end


edm...@edmondcote.com

unread,
Mar 23, 2017, 11:25:31 PM3/23/17
to chisel-users
Update. This appears to work.

class MemoryController extends Module {
  val io
= IO(new Bundle {
    val ddr3
= Output(new DDR3Command())
 
})


  val resetDDR3Cmd
= Wire(new DDR3Command())
  resetDDR3Cmd
.defaults()

 
// simple register
  val nextDDR3Cmd
= Reg(new DDR3Command(), init=resetDDR3Cmd)


 
when (true.B) {
    nextDDR3Cmd
.ba := 3.U
    nextDDR3Cmd
.casN := 0.U

    nextDDR3Cmd
.rasN := 0.U
 
}

  io
.ddr3 := nextDDR3Cmd
}


  assign resetDDR3Cmd_casN = 1'h1;
  assign resetDDR3Cmd_rasN = 1'
h1;
  assign resetDDR3Cmd_ba
= 3'h0;

[..]

  always @(posedge clock) begin
    if (reset) begin
      nextDDR3Cmd_casN <= resetDDR3Cmd_casN;
    end else begin
      nextDDR3Cmd_casN <= 1'
h0;
   
end
   
if (reset) begin
      nextDDR3Cmd_rasN
<= resetDDR3Cmd_rasN;
   
end else begin
      nextDDR3Cmd_rasN
<= 1'h0;
    end
    if (reset) begin
      nextDDR3Cmd_ba <= resetDDR3Cmd_ba;
    end else begin
      nextDDR3Cmd_ba <= 3'
h3;
   
end
 
end

ch...@berkeley.edu

unread,
Mar 24, 2017, 7:28:35 PM3/24/17
to chisel-users
I have created an example that uses a companion object and initializing methods that illustrates initializing some or all fields, including
a preserving the existing values of fields that are not set.  The example is in the current master of chisel-testers examples/BundleInitSpec.scala
Please take a look.  A quick partial snippet from this is

class MyBundle extends Bundle {
  val x = UInt(8.W)
  val y = UInt(8.W)
}

object MyBundle {
  /**
    * initialize x and y
    * @return
    */
  def init1: MyBundle = {
    val wire = Wire(new MyBundle)
    wire.x := 8.U
    wire.y := 9.U
    wire
  }
  /**
    * This init takes an existing bundle to preserve unspecified values, in this case wire.y
    * @param newX new value for x
    * @param current set this to preserve existing values for fields not set
    * @return
    */
  def setX(newX: Int, current: MyBundle): MyBundle = {
    val wire = Wire(new MyBundle)
    wire := current
    wire.x := newX.U
    wire
  }
[...]
  val regB = RegInit(MyBundle.init1)
  when (something) {
    regC := MyBundle.setX(7, regC)
  }

On Thursday, April 17, 2014 at 3:36:00 PM UTC-7, Christopher Celio wrote:

edm...@edmondcote.com

unread,
Mar 25, 2017, 2:10:10 PM3/25/17
to chisel-users
Thanks Chick.

Would you kindly enlighten us (me) on your choice of using a companion object for this task?

ch...@berkeley.edu

unread,
Mar 29, 2017, 12:51:13 PM3/29/17
to chisel-users
There's no particular functional reason to put it there.  I'd say it struck me as following the pattern of putting alternative constructors, utility functions, and constants and parameters in companion objects.  


On Thursday, April 17, 2014 at 3:36:00 PM UTC-7, Christopher Celio wrote:

Jack Koenig

unread,
Mar 29, 2017, 12:56:09 PM3/29/17
to chisel...@googlegroups.com
It is standard Scala style to use companion objects as a place to put factory methods and other "static" methods for a given class. Note that companion objects also have access to private class members which makes this practice even more appealing.


--
You received this message because you are subscribed to the Google Groups "chisel-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chisel-users+unsubscribe@googlegroups.com.
To post to this group, send email to chisel...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/chisel-users/757baa53-163e-4ade-9383-06931b00cb41%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages