-
Notifications
You must be signed in to change notification settings - Fork 615
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ExtModule's lacked support built in support for providing (#1154)
* ExtModule's lacked support built in support for providing the verilog source. This changes creates traits that can be used with ExtModule to provide the support currently found in BlackBox - Add support for ExtModule helpers - HasExtModuleResource to use addResource - HasExtModuleInline to use setInline - HasExtModulePath to use addPath - Add tests of the above support. - Note: These tests use Stage instead of Driver - Added ScalaDoc for HasBlackBoxInline#setInline * Fix the danged trailing commas. * Change to use `.transform` as the correct API for `ChiselStage`
- Loading branch information
Showing
3 changed files
with
207 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// See LICENSE for license details. | ||
|
||
package chisel3.util | ||
|
||
import chisel3.experimental.{ChiselAnnotation, ExtModule, RunFirrtlTransform} | ||
import firrtl.transforms.{BlackBoxPathAnno, BlackBoxResourceAnno, BlackBoxInlineAnno, BlackBoxSourceHelper} | ||
|
||
trait HasExtModuleResource extends ExtModule { | ||
self: ExtModule => | ||
|
||
/** Copies a resource file to the target directory | ||
* | ||
* Resource files are located in project_root/src/main/resources/. | ||
* Example of adding the resource file project_root/src/main/resources/blackbox.v: | ||
* {{{ | ||
* addResource("/blackbox.v") | ||
* }}} | ||
*/ | ||
def addResource(blackBoxResource: String): Unit = { | ||
val anno = new ChiselAnnotation with RunFirrtlTransform { | ||
def toFirrtl = BlackBoxResourceAnno(self.toNamed, blackBoxResource) | ||
def transformClass = classOf[BlackBoxSourceHelper] | ||
} | ||
chisel3.experimental.annotate(anno) | ||
} | ||
} | ||
|
||
trait HasExtModuleInline extends ExtModule { | ||
self: ExtModule => | ||
|
||
/** Creates a black box verilog file, from the contents of a local string | ||
* | ||
* @param blackBoxName The black box module name, to create filename | ||
* @param blackBoxInline The black box contents | ||
*/ | ||
def setInline(blackBoxName: String, blackBoxInline: String): Unit = { | ||
val anno = new ChiselAnnotation with RunFirrtlTransform { | ||
def toFirrtl = BlackBoxInlineAnno(self.toNamed, blackBoxName, blackBoxInline) | ||
def transformClass = classOf[BlackBoxSourceHelper] | ||
} | ||
chisel3.experimental.annotate(anno) | ||
} | ||
} | ||
|
||
trait HasExtModulePath extends ExtModule { | ||
self: ExtModule => | ||
|
||
/** Copies a file to the target directory | ||
* | ||
* This works with absolute and relative paths. Relative paths are relative | ||
* to the current working directory, which is generally not the same as the | ||
* target directory. | ||
*/ | ||
def addPath(blackBoxPath: String): Unit = { | ||
val anno = new ChiselAnnotation with RunFirrtlTransform { | ||
def toFirrtl = BlackBoxPathAnno(self.toNamed, blackBoxPath) | ||
def transformClass = classOf[BlackBoxSourceHelper] | ||
} | ||
chisel3.experimental.annotate(anno) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// See LICENSE for license details. | ||
|
||
package chiselTests | ||
|
||
import java.io.File | ||
|
||
import chisel3._ | ||
import chisel3.experimental.ExtModule | ||
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} | ||
import chisel3.util.{HasExtModuleInline, HasExtModulePath, HasExtModuleResource} | ||
import firrtl.FirrtlExecutionSuccess | ||
import firrtl.options.TargetDirAnnotation | ||
import firrtl.stage.FirrtlCircuitAnnotation | ||
import org.scalacheck.Test.Failed | ||
import org.scalatest.{FreeSpec, Matchers, Succeeded} | ||
|
||
//scalastyle:off magic.number | ||
|
||
class ExtModuleAdd(n: Int) extends ExtModule with HasExtModuleInline { | ||
val io = IO(new Bundle { | ||
val in = Input(UInt(16.W)) | ||
val out = Output(UInt(16.W)) | ||
}) | ||
|
||
//scalastyle:off regex | ||
setInline("ExtModuleAdd.v", s""" | ||
|module ExtModuleAdd( | ||
| input [15:0] in, | ||
| output [15:0] out | ||
|); | ||
| assign out = in + $n; | ||
|endmodule | ||
""".stripMargin) | ||
} | ||
|
||
class UsesExtModuleAddViaInline extends Module { | ||
val io = IO(new Bundle { | ||
val in = Input(UInt(16.W)) | ||
val out = Output(UInt(16.W)) | ||
}) | ||
|
||
val blackBoxAdd = Module(new ExtModuleAdd(5)) | ||
blackBoxAdd.io.in := io.in | ||
io.out := blackBoxAdd.io.out | ||
} | ||
|
||
class ExtModuleMinus extends ExtModule with HasExtModuleResource { | ||
val io = IO(new Bundle { | ||
val in1 = Input(UInt(16.W)) | ||
val in2 = Input(UInt(16.W)) | ||
val out = Output(UInt(16.W)) | ||
}) | ||
addResource("/chisel3/BlackBoxTest.v") | ||
} | ||
|
||
class ExtModuleMinusPath extends ExtModule with HasExtModulePath { | ||
val io = IO(new Bundle { | ||
val in1 = Input(UInt(16.W)) | ||
val in2 = Input(UInt(16.W)) | ||
val out = Output(UInt(16.W)) | ||
}) | ||
addPath( | ||
new File("src/test/resources/chisel3/BlackBoxTest.v").getCanonicalPath | ||
) | ||
} | ||
|
||
class UsesExtModuleMinusViaResource extends Module { | ||
val io = IO(new Bundle { | ||
val in1 = Input(UInt(16.W)) | ||
val in2 = Input(UInt(16.W)) | ||
val out = Output(UInt(16.W)) | ||
}) | ||
|
||
val mod0 = Module(new ExtModuleMinus) | ||
|
||
mod0.io.in1 := io.in1 | ||
mod0.io.in2 := io.in2 | ||
io.out := mod0.io.out | ||
} | ||
|
||
class UsesExtModuleMinusViaPath extends Module { | ||
val io = IO(new Bundle { | ||
val in1 = Input(UInt(16.W)) | ||
val in2 = Input(UInt(16.W)) | ||
val out = Output(UInt(16.W)) | ||
}) | ||
|
||
val mod0 = Module(new ExtModuleMinusPath) | ||
|
||
mod0.io.in1 := io.in1 | ||
mod0.io.in2 := io.in2 | ||
io.out := mod0.io.out | ||
} | ||
|
||
class ExtModuleImplSpec extends FreeSpec with Matchers { | ||
"ExtModule can have verilator source implementation" - { | ||
|
||
"Implementations can be contained in-line" in { | ||
val targetDir = "test_run_dir/extmodule-inline" | ||
|
||
val annotations = Seq( | ||
TargetDirAnnotation(targetDir), | ||
ChiselGeneratorAnnotation(() => new UsesExtModuleAddViaInline) | ||
) | ||
val newAnnotations = (new ChiselStage).transform(annotations) | ||
|
||
newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be (true) | ||
val verilogOutput = new File(targetDir, "ExtModuleAdd.v") | ||
verilogOutput.exists() should be(true) | ||
verilogOutput.delete() | ||
} | ||
|
||
"Implementations can be contained in resource files" in { | ||
val targetDir = "test_run_dir/extmodule-resource" | ||
val annotations = Seq( | ||
TargetDirAnnotation(targetDir), | ||
ChiselGeneratorAnnotation(() => new UsesExtModuleMinusViaResource) | ||
) | ||
val newAnnotations = (new ChiselStage).transform(annotations) | ||
|
||
newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be (true) | ||
val verilogOutput = new File(targetDir, "BlackBoxTest.v") | ||
verilogOutput.exists() should be(true) | ||
verilogOutput.delete() | ||
} | ||
|
||
"Implementations can be contained in arbitrary files" in { | ||
val targetDir = "test_run_dir/extmodule-path" | ||
val annotations = Seq( | ||
TargetDirAnnotation(targetDir), | ||
ChiselGeneratorAnnotation(() => new UsesExtModuleMinusViaPath) | ||
) | ||
val newAnnotations = (new ChiselStage).transform(annotations) | ||
|
||
newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be (true) | ||
val verilogOutput = new File(targetDir, "BlackBoxTest.v") | ||
verilogOutput.exists() should be(true) | ||
verilogOutput.delete() | ||
} | ||
} | ||
} |