chipsalliance / chisel

Chisel: A Modern Hardware Design Language
https://www.chisel-lang.org/
Apache License 2.0
3.91k stars 588 forks source link

recursive value needs type #467

Closed sols1 closed 7 years ago

sols1 commented 7 years ago

It would be handy to do this:

 val slaveWait = Reg(init = Bool(false), next = (io.port.scl.oe && !dSCLOen && !sSCL) || (slaveWait && !sSCL))

Unfortunately, it doesn't work:

recursive value slaveWait needs type
mwachs5 commented 7 years ago

Can you do

val slaveWait: Bool = ...?

On Mon, Jan 30, 2017 at 2:18 PM, sols1 notifications@github.com wrote:

It would be handy to do this:

val slaveWait = Reg(init = Bool(false), next = (io.port.scl.oe && !dSCLOen && !sSCL) || (slaveWait && !sSCL))

Unfortunately, it doesn't work:

recursive value slaveWait needs type

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ucb-bar/chisel3/issues/467, or mute the thread https://github.com/notifications/unsubscribe-auth/ARCAJCIs2c_Wkg5GRjqCr8XSDNxMue_Nks5rXmG6gaJpZM4Lx_a5 .

-- Megan A. Wachs Engineer | SiFive, Inc 300 Brannan St, Suite 403 San Francisco, CA 94107 megan@sifive.com

sols1 commented 7 years ago

Tried your suggestion:

  val slaveWait: Bool = Reg(init = Bool(false), init = (io.port.scl.oe && !dSCLOen && !sSCL) || (slaveWait && !sSCL))

Error:

[error] ...: overloaded method value apply with alternatives:
[error]   [T <: chisel3.core.Data](outType: T)(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, implicit compileOptions: chisel3.core.CompileOptions)T <and>
[error]   [T <: chisel3.core.Data](t: T, next: T, init: T)(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, implicit compileOptions: chisel3.core.CompileOptions)T
[error]  cannot be applied to (init: Chisel.Bool, init: chisel3.core.Bool)
[error]   val slaveWait: Bool = Reg(init = Bool(false), init = (io.port.scl.oe && !dSCLOen && !sSCL) || (slaveWait && !sSCL))
[error]                         ^
[error] one error found
ducky64 commented 7 years ago

The optional-argument Reg API is going to be deprecated, because of a bunch of issues (such as use of nulls and not handling type parameters well) The suggested replacement is to use RegEnable / RegNext.

mwachs5 commented 7 years ago

@sols1 in your second example I think you used init in one place where you meant next

sols1 commented 7 years ago

@mwachs5 you are right - second example should be:

  val slaveWait: Bool = Reg(init = Bool(false), next = (io.port.scl.oe && !dSCLOen && !sSCL) || (slaveWait && !sSCL))

However, when I tried it, I got an exception:

[info] [0.003] Elaborating design...
[error] (run-main-0) java.lang.reflect.InvocationTargetException
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at util.HasGeneratorUtilities$$anonfun$2.apply(GeneratorUtils.scala:47)
    at util.HasGeneratorUtilities$$anonfun$2.apply(GeneratorUtils.scala:44)
    at chisel3.core.Module$.do_apply(Module.scala:35)
    at chisel3.Driver$$anonfun$elaborate$1.apply(Driver.scala:193)
    at chisel3.Driver$$anonfun$elaborate$1.apply(Driver.scala:193)
    at chisel3.internal.Builder$$anonfun$build$1.apply(Builder.scala:218)
    at chisel3.internal.Builder$$anonfun$build$1.apply(Builder.scala:216)
    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
    at chisel3.internal.Builder$.build(Builder.scala:216)
    at chisel3.Driver$.elaborate(Driver.scala:193)
    at util.HasGeneratorUtilities$class.elaborate(GeneratorUtils.scala:50)
    at sifive.enterprise.generator.EnterpriseGenerator$.elaborate(Generator.scala:40)
    at util.GeneratorApp$class.circuit(GeneratorUtils.scala:82)
    at sifive.enterprise.generator.EnterpriseGenerator$.circuit$lzycompute(Generator.scala:40)
    at sifive.enterprise.generator.EnterpriseGenerator$.circuit(Generator.scala:40)
    at util.GeneratorApp$class.generateFirrtl(GeneratorUtils.scala:88)
    at sifive.enterprise.generator.EnterpriseGenerator$.generateFirrtl(Generator.scala:40)
    at sifive.enterprise.generator.EnterpriseGenerator$.delayedEndpoint$sifive$enterprise$generator$EnterpriseGenerator$1(Generator.scala:42)
    at sifive.enterprise.generator.EnterpriseGenerator$delayedInit$body.apply(Generator.scala:40)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at sifive.enterprise.generator.EnterpriseGenerator$.main(Generator.scala:40)
    at sifive.enterprise.generator.EnterpriseGenerator.main(Generator.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
Caused by: java.lang.NullPointerException
    at sifive.blocks.devices.i2c.I2CModule$class.$init$(I2C.scala:135)
    at sifive.blocks.devices.i2c.TLI2C$$anonfun$19$$anon$2.<init>(I2C.scala:225)
    at sifive.blocks.devices.i2c.TLI2C$$anonfun$19.apply(I2C.scala:225)
    at sifive.blocks.devices.i2c.TLI2C$$anonfun$19.apply(I2C.scala:225)
    at uncore.tilelink2.TLRegisterRouter.module$lzycompute(RegisterRouter.scala:118)
    at uncore.tilelink2.TLRegisterRouter.module(RegisterRouter.scala:118)
    at diplomacy.LazyModule$$anonfun$instantiate$1$$anonfun$apply$5.apply(LazyModule.scala:55)
    at diplomacy.LazyModule$$anonfun$instantiate$1$$anonfun$apply$5.apply(LazyModule.scala:55)
    at chisel3.core.Module$.do_apply(Module.scala:35)
    at diplomacy.LazyModule$$anonfun$instantiate$1.apply(LazyModule.scala:55)
    at diplomacy.LazyModule$$anonfun$instantiate$1.apply(LazyModule.scala:52)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at diplomacy.LazyModule.instantiate(LazyModule.scala:52)
    at diplomacy.LazyModuleImp.<init>(LazyModule.scala:133)
    at rocketchip.BareTopModule.<init>(BaseTop.scala:24)
    at rocketchip.BaseTopModule.<init>(BaseTop.scala:63)
    at sifive.enterprise.everywhere.guava.GuavaRocketChipTopModule.<init>(Top.scala:110)
    at sifive.enterprise.everywhere.guava.GuavaRocketChipTop.module$lzycompute(Top.scala:87)
    at sifive.enterprise.everywhere.guava.GuavaRocketChipTop.module(Top.scala:87)
    at sifive.enterprise.everywhere.guava.GuavaTop$$anonfun$2.apply(Top.scala:152)
    at sifive.enterprise.everywhere.guava.GuavaTop$$anonfun$2.apply(Top.scala:152)
    at chisel3.core.Module$.do_apply(Module.scala:35)
    at sifive.enterprise.everywhere.guava.GuavaTop.<init>(Top.scala:152)
    at sifive.enterprise.everywhere.guava.TestHarness$$anonfun$8.apply(TestHarness.scala:61)
    at sifive.enterprise.everywhere.guava.TestHarness$$anonfun$8.apply(TestHarness.scala:61)
    at chisel3.core.Module$.do_apply(Module.scala:35)
    at sifive.enterprise.everywhere.guava.TestHarness.<init>(TestHarness.scala:61)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at util.HasGeneratorUtilities$$anonfun$2.apply(GeneratorUtils.scala:47)
    at util.HasGeneratorUtilities$$anonfun$2.apply(GeneratorUtils.scala:44)
    at chisel3.core.Module$.do_apply(Module.scala:35)
    at chisel3.Driver$$anonfun$elaborate$1.apply(Driver.scala:193)
    at chisel3.Driver$$anonfun$elaborate$1.apply(Driver.scala:193)
    at chisel3.internal.Builder$$anonfun$build$1.apply(Builder.scala:218)
    at chisel3.internal.Builder$$anonfun$build$1.apply(Builder.scala:216)
    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
    at chisel3.internal.Builder$.build(Builder.scala:216)
    at chisel3.Driver$.elaborate(Driver.scala:193)
    at util.HasGeneratorUtilities$class.elaborate(GeneratorUtils.scala:50)
    at sifive.enterprise.generator.EnterpriseGenerator$.elaborate(Generator.scala:40)
    at util.GeneratorApp$class.circuit(GeneratorUtils.scala:82)
    at sifive.enterprise.generator.EnterpriseGenerator$.circuit$lzycompute(Generator.scala:40)
    at sifive.enterprise.generator.EnterpriseGenerator$.circuit(Generator.scala:40)
    at util.GeneratorApp$class.generateFirrtl(GeneratorUtils.scala:88)
    at sifive.enterprise.generator.EnterpriseGenerator$.generateFirrtl(Generator.scala:40)
    at sifive.enterprise.generator.EnterpriseGenerator$.delayedEndpoint$sifive$enterprise$generator$EnterpriseGenerator$1(Generator.scala:42)
    at sifive.enterprise.generator.EnterpriseGenerator$delayedInit$body.apply(Generator.scala:40)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at sifive.enterprise.generator.EnterpriseGenerator$.main(Generator.scala:40)
    at sifive.enterprise.generator.EnterpriseGenerator.main(Generator.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
[trace] Stack trace suppressed: run last federation/compile:runMain for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
    at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last federation/compile:runMain for the full output.
[error] (federation/compile:runMain) Nonzero exit code: 1
[error] Total time: 8 s, completed Jan 30, 2017 3:06:17 PM
mwachs5 commented 7 years ago

Again, is this a scala problem or a chisel problem? If I do

val b:Int = 5
val a:Int = a + b
println("a is %d", a)

what happens?

ducky64 commented 7 years ago

Oh I see, you have an actual recursive definition. I don't think the (Scala) value is defined until it is actually assigned. It might be null.

Consider defining a Wire first, then reassigning to the wire a Reg. Like val a = Wire(...) a := RegNext(a)

sdtwigg commented 7 years ago

For this, just forgo the next in the Reg and do:

val slaveWait = Reg(init = Bool(false))
slaveWait := (io.port.scl.oe && !dSCLOen && !sSCL) || (slaveWait && !sSCL))

Or, the perhaps slightly better:

val slaveWait = RegInit(Bool(false))
slaveWait := (io.port.scl.oe && !dSCLOen && !sSCL) || (slaveWait && !sSCL))

vals are initialized to null hence the NPE when you tried to access it 'before' it was defined (since the arguments to the defining function are evaluated before the defining assignment). Theoretically, scalac should have given a warning on this but it can be nebulous as to when it decides a case it use-before-define (and it might be allowing the recursive definition type error to stomp that warning)

sols1 commented 7 years ago

@sdtwigg I had the same code that you wrote. I was trying to reduce the number of lines of code from 2 to 1 but got an error message and it was not obvious how to fix. @mwachs5 suggested fix but that caused an exception.

ducky64 commented 7 years ago

Can you post the (new) code that is erroring with the error message?