Skip to content

Commit

Permalink
Merge branch 'lr121218' into 3.1.x
Browse files Browse the repository at this point in the history
  • Loading branch information
ucbjrl committed Dec 13, 2018
2 parents 80cd4b5 + 09ff8b0 commit 4a1b86f
Show file tree
Hide file tree
Showing 14 changed files with 13,141 additions and 23 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @freechipsproject/chisel-reviewers
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Chisel 3
![Chisel 3](https://raw.githubusercontent.com/freechipsproject/chisel3/master/doc/images/chisel_logo.svg?sanitize=true)

#

[![Join the chat at https://gitter.im/freechipsproject/chisel3](https://badges.gitter.im/freechipsproject/chisel3.svg)](https://gitter.im/freechipsproject/chisel3?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

Expand Down Expand Up @@ -164,11 +166,9 @@ sbt test
```
### Running Projects Against Local Chisel
Chisel3 is still undergoing rapid development and we haven't pusblished a
stable version to the Nexus repository.
You will need to build from source and `publishLocal`.
To use the development version of Chisel (`master` branch), you will need to build from source and `publishLocal`.
The repo version can be found in the build.sbt file.
At last check it was:
As of the time of writing it was:
version := "3.2-SNAPSHOT",
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ lazy val chiselSettings = Seq (
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "3.0.1" % "test",
"org.scalacheck" %% "scalacheck" % "1.13.4" % "test",
"com.github.scopt" %% "scopt" % "3.6.0"
"com.github.scopt" %% "scopt" % "3.7.0"
),

// Tests from other projects may still run concurrently.
Expand Down
2 changes: 1 addition & 1 deletion chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ sealed class Vec[T <: Data] private[core] (gen: => T, val length: Int)
def apply(idx: Int): T = self(idx)

override def cloneType: this.type = {
new Vec(gen.cloneType, length).asInstanceOf[this.type]
new Vec(gen.cloneTypeFull, length).asInstanceOf[this.type]
}

override def getElements: Seq[Data] =
Expand Down
8 changes: 7 additions & 1 deletion chiselFrontend/src/main/scala/chisel3/core/Module.scala
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,13 @@ abstract class BaseModule extends HasId {
def desiredName = this.getClass.getName.split('.').last

/** Legalized name of this module. */
final val name = Builder.globalNamespace.name(desiredName)
final lazy val name = try {
Builder.globalNamespace.name(desiredName)
} catch {
case e: NullPointerException => throwException(
s"Error: desiredName of ${this.getClass.getName} is null. Did you evaluate 'name' before all values needed by desiredName were available?", e)
case t: Throwable => throw t
}

/** Returns a FIRRTL ModuleName that references this object
* @note Should not be called until circuit elaboration is complete
Expand Down
Binary file added doc/images/chisel_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12,593 changes: 12,593 additions & 0 deletions doc/images/chisel_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions src/main/scala/chisel3/Driver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ trait ChiselExecutionResult
*
* @param circuitOption Optional circuit, has information like circuit name
* @param emitted The emitted Chirrrl text
* @param firrtlResultOption Optional Firrtl result, @see ucb-bar/firrtl for details
* @param firrtlResultOption Optional Firrtl result, @see freechipsproject/firrtl for details
*/
case class ChiselExecutionSuccess(
circuitOption: Option[Circuit],
Expand All @@ -77,9 +77,9 @@ case class ChiselExecutionSuccess(
) extends ChiselExecutionResult

/**
* Getting one of these indicates failure of some sort
*
* @param message a clue perhaps will be provided in the here
* Getting one of these indicates failure of some sort.
*
* @param message A clue might be provided here.
*/
case class ChiselExecutionFailure(message: String) extends ChiselExecutionResult

Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/chisel3/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ package object chisel3 { // scalastyle:ignore package.object.name

type BlackBox = chisel3.core.BlackBox

type InstanceId = chisel3.internal.InstanceId

val Mem = chisel3.core.Mem
type MemBase[T <: Data] = chisel3.core.MemBase[T]
type Mem[T <: Data] = chisel3.core.Mem[T]
Expand Down
15 changes: 8 additions & 7 deletions src/main/scala/chisel3/util/Decoupled.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
package chisel3.util

import chisel3._
import chisel3.experimental.{DataMirror, Direction}
import chisel3.experimental.{DataMirror, Direction, requireIsChiselType}
import chisel3.internal.naming._ // can't use chisel3_ version because of compile order

/** An I/O Bundle containing 'valid' and 'ready' signals that handshake
Expand Down Expand Up @@ -36,7 +36,7 @@ object ReadyValidIO {
implicit class AddMethodsToReadyValid[T<:Data](target: ReadyValidIO[T]) {
def fire(): Bool = target.ready && target.valid

/** push dat onto the output bits of this interface to let the consumer know it has happened.
/** Push dat onto the output bits of this interface to let the consumer know it has happened.
* @param dat the values to assign to bits.
* @return dat.
*/
Expand All @@ -47,22 +47,23 @@ object ReadyValidIO {
}

/** Indicate no enqueue occurs. Valid is set to false, and bits are
* connected to an uninitialized wire
* connected to an uninitialized wire.
*/
def noenq(): Unit = {
target.valid := false.B
target.bits := DontCare
}

/** Assert ready on this port and return the associated data bits.
* This is typically used when valid has been asserted by the producer side.
* @return the data for this device,
* @return The data bits.
*/
def deq(): T = {
target.ready := true.B
target.bits
}

/** Indicate no dequeue occurs. Ready is set to false
/** Indicate no dequeue occurs. Ready is set to false.
*/
def nodeq(): Unit = {
target.ready := false.B
Expand Down Expand Up @@ -199,7 +200,7 @@ class Queue[T <: Data](gen: T,
}

val genType = if (compileOptions.declaredTypeMustBeUnbound) {
experimental.requireIsChiselType(gen)
requireIsChiselType(gen)
gen
} else {
if (DataMirror.internal.isSynthesizable(gen)) {
Expand Down Expand Up @@ -252,7 +253,7 @@ class Queue[T <: Data](gen: T,

private val ptr_diff = enq_ptr.value - deq_ptr.value
if (isPow2(entries)) {
io.count := Cat(maybe_full && ptr_match, ptr_diff)
io.count := Mux(maybe_full && ptr_match, entries.U, 0.U) | ptr_diff
} else {
io.count := Mux(ptr_match,
Mux(maybe_full,
Expand Down
234 changes: 234 additions & 0 deletions src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
// See LICENSE for license details.

package chisel3.util.experimental

import chisel3._
import chisel3.experimental.annotate
// import chisel3.InstanceId
import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform}
import firrtl.annotations.{MemoryLoadFileType, _}
import firrtl.ir.{Module => _, _}
import firrtl.transforms.BlackBoxInlineAnno
import firrtl.Mappers._
import firrtl.{AnnotationSeq, CircuitForm, CircuitState, EmitCircuitAnnotation, LowForm, Transform, VerilogEmitter}

import scala.collection.mutable

/** This is the annotation created when using [[loadMemoryFromFile]], it records the memory, the load file
* and the format of the file.
* @param target memory to load
* @param fileName name of input file
* @param hexOrBinary use $readmemh or $readmemb, i.e. hex or binary text input, default is hex
*/
case class ChiselLoadMemoryAnnotation[T <: Data](
target: MemBase[T],
fileName: String,
hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex
)
extends ChiselAnnotation with RunFirrtlTransform {

if(fileName.isEmpty) {
throw new Exception(
s"""LoadMemory from file annotations file empty file name"""
)
}

def transformClass: Class[LoadMemoryTransform] = classOf[LoadMemoryTransform]

def toFirrtl: LoadMemoryAnnotation = {
LoadMemoryAnnotation(target.toNamed.asInstanceOf[ComponentName], fileName, hexOrBinary)
}
}


object loadMemoryFromFile {
/** Use this annotation generator to load a memory from a text file by using verilator and
* verilog's $readmemh or $readmemb.
* The treadle backend can also recognize this annotation and load memory at run-time.
*
* This annotation triggers the [[LoadMemoryTransform]] which will take add the verilog directive to
* the relevant module by using the creating separate modules that are bound to the modules containing
* the memories to be loaded.
*
* ==Example module==
*
* Consider a simple Module containing a memory
* {{{
* import chisel3._
* class UsesMem(memoryDepth: Int, memoryType: Data) extends Module {
* val io = IO(new Bundle {
* val address = Input(UInt(memoryType.getWidth.W))
* val value = Output(memoryType)
* })
* val memory = Mem(memoryDepth, memoryType)
* io.value := memory(io.address)
* }
* }}}
*
* ==Above module with annotation==
*
* To load this memory from a file /workspace/workdir/mem1.hex.txt
* Just add an import and annotate the memory
* {{{
* import chisel3._
* import chisel3.util.experimental.loadMemoryFromFile // <<-- new import here
* class UsesMem(memoryDepth: Int, memoryType: Data) extends Module {
* val io = IO(new Bundle {
* val address = Input(UInt(memoryType.getWidth.W))
* val value = Output(memoryType)
* })
* val memory = Mem(memoryDepth, memoryType)
* io.value := memory(io.address)
* loadMemoryFromFile(memory, "/workspace/workdir/mem1.hex.txt") // <<-- Note the annotation here
* }
* }}}
*
* ==Example file format==
* A memory file should consist of ascii text in either hex or binary format
* Example (a file containing the decimal values 0, 7, 14, 21):
* {{{
* 0
* 7
* d
* 15
* }}}
* Binary file is similarly constructed.
*
* ==More info==
* See the LoadMemoryFromFileSpec.scala in the test suite for more examples
* @see <a href="https://github.com/freechipsproject/chisel3/wiki/Chisel-Memories">Load Memories in the wiki</a>
*/
def apply[T <: Data](
memory: MemBase[T],
fileName: String,
hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex
): Unit = {
annotate(ChiselLoadMemoryAnnotation(memory, fileName))
}
}

/**
* This transform only is activated if verilog is being generated
* (determined by presence of the proper emit annotation)
* when activated it creates additional verilog files that contain
* modules bound to the modules that contain an initializable memory
*
* Currently the only non-verilog based simulation that can support loading
* memory from a file is treadle but it does not need this transform
* to do that.
*/
//scalastyle:off method.length
class LoadMemoryTransform extends Transform {
def inputForm: CircuitForm = LowForm
def outputForm: CircuitForm = LowForm

private var memoryCounter: Int = -1

private val bindModules: mutable.ArrayBuffer[BlackBoxInlineAnno] = new mutable.ArrayBuffer()

private val verilogEmitter: VerilogEmitter = new VerilogEmitter

/**
* run the pass
* @param circuit the circuit
* @param annotations all the annotations
* @return
*/
def run(circuit: Circuit, annotations: AnnotationSeq): Circuit = {
val groups = annotations
.collect{ case m: LoadMemoryAnnotation => m }
.groupBy(_.target.serialize)
val memoryAnnotations = groups.map { case (key, annos) =>
if (annos.size > 1) {
throw new Exception(
s"Multiple (${annos.size} found for memory $key one LoadMemoryAnnotation is allowed per memory"
)
}
key -> annos.head
}

val modulesByName = circuit.modules.collect { case module: firrtl.ir.Module => module.name -> module }.toMap

/**
* walk the module and for memories that have LoadMemory annotations
* generate the bindable modules for verilog emission
*
* @param myModule module being searched for memories
*/
def processModule(myModule: DefModule): DefModule = {

def makePath(componentName: String): String = {
circuit.main + "." + myModule.name + "." + componentName
}

def processMemory(name: String): Unit = {
val fullMemoryName = makePath(s"$name")

memoryAnnotations.get(fullMemoryName) match {
case Some(lma @ LoadMemoryAnnotation(ComponentName(componentName, moduleName), _, hexOrBinary, _)) =>
val writer = new java.io.StringWriter

modulesByName.get(moduleName.name).foreach { module =>
val renderer = verilogEmitter.getRenderer(module, modulesByName)(writer)
val loadFileName = lma.getFileName

memoryCounter += 1
val bindsToName = s"BindsTo_${memoryCounter}_${moduleName.name}"
renderer.emitVerilogBind(bindsToName,
s"""
|initial begin
| $$readmem$hexOrBinary("$loadFileName", ${myModule.name}.$componentName);
|end
""".stripMargin)
val inLineText = writer.toString + "\n" +
s"""bind ${myModule.name} $bindsToName ${bindsToName}_Inst(.*);"""

val blackBoxInline = BlackBoxInlineAnno(
moduleName,
moduleName.serialize + "." + componentName + ".v",
inLineText
)

bindModules += blackBoxInline
}

case _ =>
}
}

def processStatements(statement: Statement): Statement = {
statement match {
case m: DefMemory => processMemory(m.name)
case s => s map processStatements
}
statement
}

myModule match {
case module: firrtl.ir.Module =>
processStatements(module.body)
case _ =>
}

myModule
}

circuit map processModule
}

def execute(state: CircuitState): CircuitState = {
val isVerilog = state.annotations.exists {
case EmitCircuitAnnotation(emitter) =>
emitter == classOf[VerilogEmitter]
case _ =>
false
}
if(isVerilog) {
run(state.circuit, state.annotations)
state.copy(annotations = state.annotations ++ bindModules)
}
else {
state
}
}
}
Loading

0 comments on commit 4a1b86f

Please sign in to comment.