chipsalliance / chisel

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

loadMemoryFromFile seems not work in chisel6.2.0 #3961

Open yongruifang opened 6 months ago

yongruifang commented 6 months ago

Version: chisel6.2.0 OS: Ubuntu 22.04.3 LTS on Windows 10 x86_64 Kernel: 5.15.150.1-microsoft-standard-WSL2

Question in chisel6.2.0, my test code indicates that loadMemoryFromFile makes no sense. I'm sure my filepath is correct, it works in chisel5.1.0 .Unfortunately, it doesn't work now.

Here is the structure of my project :

example
└── src
│   └── hex
│   │   └── example.hex.txt
│   └── main/scala/circuit
│   │             └── IMemory.scala
│   └── test/scala/circuit
│                 └── IMemorySpec.scala
└--build.sbt

build.sbt

ThisBuild / scalaVersion := "2.13.12"
ThisBuild / version := "0.1.0"
ThisBuild / organization := "%ORGANIZATION%"

val chiselVersion = "6.2.0"

lazy val root = (project in file("."))
  .settings(
    name := "%NAME%",
    libraryDependencies ++= Seq(
      "org.chipsalliance" %% "chisel" % chiselVersion,
      "org.scalatest" %% "scalatest" % "3.2.16" % "test"
    ),
    scalacOptions ++= Seq(
      "-language:reflectiveCalls",
      "-deprecation",
      "-feature",
      "-Xcheckinit",
      "-Ymacro-annotations"
    ),
    addCompilerPlugin(
      "org.chipsalliance" % "chisel-plugin" % chiselVersion cross CrossVersion.full
    )
  )

example.hex.txt

003100b3
40628033
06432283
06512423
064000ef

IMemory.scala

package circuit

import chisel3._
import chisel3.util.experimental.loadMemoryFromFileInline
import circt.stage.ChiselStage

class IMemoryIO extends Bundle {
  val rdAddr = Input(UInt(5.W))
  val rdData = Output(UInt(32.W))
  val wrAddr = Input(UInt(5.W))
  val wrData = Input(UInt(32.W))
  val wrEna = Input(UInt(1.W))
}

class IMemory(memoryFile: String = "") extends Module {
  val io = IO(new IMemoryIO)
  val mem = SyncReadMem(1024, UInt(32.W))
  io.rdData := mem.read(io.rdAddr)
  io.rdData := mem(io.rdAddr)
  when(io.wrEna === 1.U) {
    mem.write(io.wrAddr, io.wrData)
  }
  if (memoryFile.trim().nonEmpty) {
    loadMemoryFromFileInline(mem, memoryFile)
  }
}

IMemorySpec.scala

package circuit
import chisel3._
import chisel3.experimental.BundleLiterals._
import chisel3.simulator.EphemeralSimulator._
import org.scalatest.freespec.AnyFreeSpec
import org.scalatest.matchers.must.Matchers
import java.io.File
class IMemorySpec extends AnyFreeSpec with Matchers {
  "write memory" in {
    simulate(new IMemory("src/hex/example.hex.txt")) { dut =>
      dut.io.wrAddr.poke(4.U)
      dut.io.wrEna.poke(1.U)
      dut.io.wrData.poke(0x003100b3.U)
      dut.clock.step()
      dut.io.rdAddr.poke(4.U)
      dut.clock.step()
      dut.io.rdData.expect(0x003100b3.U)
    }
  }
  "loadMemory from file" in {
    simulate(new IMemory("src/hex/example.hex.txt")) { dut =>
      dut.io.rdAddr.poke(0.U)
      dut.clock.step()
      dut.io.rdData.expect(0x003100b3.U)
    }
  }
}

when I run sbt "testOnly circuit.IMemorySpec, the output is :

[info] - file should exist
[info] - write memory
[info] - loadMemory from file *** FAILED ***
[info]   chisel3.simulator.PeekPokeAPI$FailedExpectationException: Failed Expectation: Observed value '0' != 3211443. Expectation failed: observed value 0 != 3211443

Observed value '0' != 3211443. Mem doesn't initialize by loadMemory method.

Other Information I first ask this question in here: stackoverflow

seldridge commented 6 months ago

Is this non-deterministic? I.e., is the memory getting a random value every time?

loadMemoryFromFile results in a bind file getting generated. My guess is that ChiselSim is not properly including this bind file in the compilation so this isn't working.

yongruifang commented 6 months ago

Is this non-deterministic? I.e., is the memory getting a random value every time?

loadMemoryFromFile results in a bind file getting generated. My guess is that ChiselSim is not properly including this bind file in the compilation so this isn't working.

No, in my project, the memory always get 0. I have tried many times, and cannot see any other value.

seldridge commented 6 months ago

That may be the same behavior. Memories may come up as zero by default. Basically, I'm saying that this may not be getting initialized because the bind is not happening.

carlosedp commented 3 months ago

I'm porting my tests to ChiselSim from chiseltest and saw a similar behavior. Have you tried loadMemoryFromFileInline to see if it's the same @yongruifang ?