Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile error when using struct fields in nested if #116

Closed
MartinC45 opened this issue May 8, 2024 · 7 comments
Closed

Compile error when using struct fields in nested if #116

MartinC45 opened this issue May 8, 2024 · 7 comments

Comments

@MartinC45
Copy link

Description

Trying to use a field of a struct in a level other than the outermost one of a nested if yields an error. It works fine otherwise and also works when assigning the field to a variable and using that variable in an inner level.

Example

//> using scala 3.4.0
//> using lib io.github.dfianthdl::dfhdl::0.4.3
//> using plugin io.github.dfianthdl:::dfhdl-plugin:0.4.3
//> using option -deprecation -language:implicitConversions

import dfhdl.* //import all the DFHDL goodness

case class Test (
  a : Bit <> VAL,
  b : Bit <> VAL
) extends Struct


class GlobCounter (val width: Int <> CONST) extends RTDesign:
  val req = Bit <> IN
  val req2 = Bit <> IN
  val t = Test <> IN
  val t_b = Bit <> VAR
  t_b := t.b
  val t_int = Test <> VAR 
  t_int := t
  
  val cnt = UInt(width) <> OUT.REG init 0
   
  // doesn't work
  if (t.a) {
    if (t.b) { 
        cnt.din := cnt + 1
    }
  }
  
  // doesn't work
//   if (req) {
//     if (t.b) { 
//         cnt.din := cnt + 1
//     }
//   }

  // no if nesting, works
//   if (t.a && t.b) {
//     cnt.din := cnt + 1
//   }
  
  // works
//   if (t.a) {
//     if (t_b) { 
//         cnt.din := cnt + 1
//     }
//   }

  // doesn't work
//   if (t_int.a) {
//     if (t_int.b) { 
//         cnt.din := cnt + 1
//     }
//   }
  
  // works
//   if (req) {
//     if (req2) {
//       cnt.din := cnt + 1
//     }
//   }

////////////////////////////////////////////////////////////////////////////////////////////////
// DFHDL Compiler Options:                                                                    //
////////////////////////////////////////////////////////////////////////////////////////////////
// Enables printing the generated chosen backend code:
given options.CompilerOptions.PrintGenFiles = true
// Uncomment to select vhdl compilation (default is verilog):
// given options.CompilerOptions.Backend = backends.vhdl
// Uncomment to enable printing design code before compilation (after elaboration):
// given options.CompilerOptions.PrintDesignCodeBefore = true
// Uncomment to enable printing design code after compilation:
// given options.CompilerOptions.PrintDesignCodeAfter = true
// Uncomment to set different clock and reset configurations:
// given options.CompilerOptions.DefaultClkCfg = ClkCfg(ClkCfg.Edge.Rising)
// given options.CompilerOptions.DefaultRstCfg = RstCfg(RstCfg.Mode.Async, RstCfg.Active.Low)
////////////////////////////////////////////////////////////////////////////////////////////////

//The entry point to your compilation program starts here
@main def main = GlobCounter(64).compile

Output

When run with scala-cli this is the output

[warn] ./GlobCounter.scala:2:11
[warn] Using 'lib' is deprecated, use 'dep' instead
[warn] //> using lib io.github.dfianthdl::dfhdl::0.4.3
[warn]           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Compiling project (Scala 3.4.0, JVM (17))
Compiled project (Scala 3.4.0, JVM (17))
Exception in thread "main" java.util.NoSuchElementException: head of empty list
        at scala.collection.immutable.Nil$.head(List.scala:662)
        at scala.collection.immutable.Nil$.head(List.scala:661)
        at dfhdl.compiler.ir.DB.OMLGen(DB.scala:137)
        at dfhdl.compiler.ir.DB.ownerMemberList$lzyINIT1(DB.scala:165)
        at dfhdl.compiler.ir.DB.ownerMemberList(DB.scala:165)
        at dfhdl.compiler.ir.DB.ownerMemberTable$lzyINIT1(DB.scala:190)
        at dfhdl.compiler.ir.DB.ownerMemberTable(DB.scala:190)
        at dfhdl.compiler.ir.DB.getMembersOf(DB.scala:181)
        at dfhdl.compiler.analysis.DFOwnerAnalysis$package$.members(DFOwnerAnalysis.scala:8)
        at dfhdl.compiler.stages.VHDLProcToVerilog$.$anonfun$1(VHDLProcToVerilog.scala:33)
        at scala.collection.immutable.List.flatMap(List.scala:293)
        at dfhdl.compiler.stages.VHDLProcToVerilog$.transform(VHDLProcToVerilog.scala:82)
        at dfhdl.compiler.stages.StageRunner.runSingleStage(StageRunner.scala:22)
        at dfhdl.compiler.stages.StageRunner.dfhdl$compiler$stages$StageRunner$$run(StageRunner.scala:43)
        at dfhdl.compiler.stages.StageRunner$.run(StageRunner.scala:55)
        at dfhdl.backends$verilog.printer(backends.scala:15)
        at dfhdl.compiler.stages.BackendCompiler.compile(BackendCompiler.scala:19)
        at dfhdl.compiler.stages.BackendCompiler.compile$(BackendCompiler.scala:8)
        at dfhdl.backends$verilog.compile(backends.scala:11)
        at dfhdl.compiler.stages.StagedDesign$.compile(StagedDesign.scala:13)
        at dfhdl.ops$package$.compile(ops.scala:10)
        at GlobCounter$package$.main(GlobCounter.scala:82)
        at main.main(GlobCounter.scala:82)
@soronpo
Copy link
Collaborator

soronpo commented May 8, 2024

@MartinC45 Hi. Thank you very much for trying out DFHDL and reporting this!
Would fix this very soon.

@soronpo
Copy link
Collaborator

soronpo commented May 8, 2024

BTW, I have a question, if you don't mind answering. Currently our documentation shows nothing about the struct feature (one of the reasons is to first flush out most of the bugs ourselves). How did you go about learning this feature?

@MartinC45
Copy link
Author

Hi, no problem and sure. I found it in some slides you shared on Reddit some time ago. Should I wait until the release of the full documentation before opening further issues?

@soronpo
Copy link
Collaborator

soronpo commented May 8, 2024

Feel free to open issues. Your time is valuable and I don't want to waste it, and I want your experience to be fun. But if you like being on the cutting bleeding edge, hack away :)

@soronpo
Copy link
Collaborator

soronpo commented May 9, 2024

This is a more general problem in the RT to ED compilation stage, and fails in this example:

class GlobCounter(val width: Int <> CONST) extends RTDesign:
  val t = Bit <> IN

  val cnt = UInt(width) <> OUT.REG init 0

  // doesn't work
  if (t || t)
    if (t || t)
      cnt.din := cnt + 1
end GlobCounter

Should be resolved tomorrow.

@soronpo soronpo closed this as completed in 384ef80 May 9, 2024
soronpo added a commit that referenced this issue May 9, 2024
@soronpo
Copy link
Collaborator

soronpo commented May 9, 2024

@MartinC45 v0.4.4 fixes this issue.

@MartinC45
Copy link
Author

Yes, it works nicely now. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants