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

Add Verilog blackbox TLDevice example #1827

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions generators/chipyard/src/main/resources/vsrc/ExampleVerilogTL.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module ExampleVerilogTLDevice #(
parameter CTRL_ADDR_BITS,
parameter CTRL_DATA_BITS,
parameter CTRL_SOURCE_BITS,
parameter CTRL_SINK_BITS,
parameter CTRL_SIZE_BITS,
parameter CLIENT_ADDR_BITS,
parameter CLIENT_DATA_BITS,
parameter CLIENT_SOURCE_BITS,
parameter CLIENT_SINK_BITS,
parameter CLIENT_SIZE_BITS
)(
input tl_client_a_ready,
output tl_client_a_valid,
output [2:0] tl_client_a_bits_opcode,
output [2:0] tl_client_a_bits_param,
output [CLIENT_SIZE_BITS-1:0] tl_client_a_bits_size,
output [CLIENT_SOURCE_BITS-1:0] tl_client_a_bits_source,
output [CLIENT_ADDR_BITS-1:0] tl_client_a_bits_address,
output [(CLIENT_DATA_BITS/8)-1:0] tl_client_a_bits_mask,
output [CLIENT_DATA_BITS-1:0] tl_client_a_bits_data,
output tl_client_a_bits_corrupt,
output tl_client_d_ready,
input tl_client_d_valid,
input [2:0] tl_client_d_bits_opcode,
input [1:0] tl_client_d_bits_param,
input [CLIENT_SIZE_BITS-1:0] tl_client_d_bits_size,
input [CLIENT_SOURCE_BITS-1:0] tl_client_d_bits_source,
input [CLIENT_SINK_BITS-1:0] tl_client_d_bits_sink,
input tl_client_d_bits_denied,
input [CLIENT_DATA_BITS-1:0] tl_client_d_bits_data,
input tl_client_d_bits_corrupt,
output tl_ctrl_a_ready,
input tl_ctrl_a_valid,
input [2:0] tl_ctrl_a_bits_opcode,
input [2:0] tl_ctrl_a_bits_param,
input [CTRL_SIZE_BITS-1:0] tl_ctrl_a_bits_size,
input [CTRL_SOURCE_BITS-1:0] tl_ctrl_a_bits_source,
input [CTRL_ADDR_BITS-1:0] tl_ctrl_a_bits_address,
input [(CTRL_DATA_BITS/8)-1:0] tl_ctrl_a_bits_mask,
input [CTRL_DATA_BITS-1:0] tl_ctrl_a_bits_data,
input tl_ctrl_a_bits_corrupt,
input tl_ctrl_d_ready,
output tl_ctrl_d_valid,
output [2:0] tl_ctrl_d_bits_opcode,
output [1:0] tl_ctrl_d_bits_param,
output [CTRL_SIZE_BITS-1:0] tl_ctrl_d_bits_size,
output [CTRL_SOURCE_BITS-1:0] tl_ctrl_d_bits_source,
output [CTRL_SINK_BITS-1:0] tl_ctrl_d_bits_sink,
output tl_ctrl_d_bits_denied,
output [CTRL_DATA_BITS-1:0] tl_ctrl_d_bits_data,
output tl_ctrl_d_bits_corrupt,
input clock,
input reset
);

endmodule
1 change: 1 addition & 0 deletions generators/chipyard/src/main/scala/DigitalTop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem
with sifive.blocks.devices.spi.HasPeripherySPIFlash // Enables optionally adding the sifive SPI flash controller
with sifive.blocks.devices.spi.HasPeripherySPI // Enables optionally adding the sifive SPI port
with icenet.CanHavePeripheryIceNIC // Enables optionally adding the IceNIC for FireSim
with chipyard.example.CanHavePeripheryVerilogTLDevice // enables optionally adding a verilog black-box TL device
with chipyard.example.CanHavePeripheryInitZero // Enables optionally adding the initzero example widget
with chipyard.example.CanHavePeripheryGCD // Enables optionally adding the GCD example widget
with chipyard.example.CanHavePeripheryStreamingFIR // Enables optionally adding the DSPTools FIR example widget
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,22 @@ class LargeNVDLARocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)

class VerilogTLDeviceRocketConfig extends Config(
new chipyard.example.WithVerilogTLDevice(chipyard.example.VerilogTLDeviceParams(
deviceName = "example",
moduleName = "ExampleVerilogTLDevice",
verilogResourceFiles = Seq("ExampleVerilogTL.v")
)) ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)


class ManyMMIOAcceleratorRocketConfig extends Config(
new chipyard.example.WithVerilogTLDevice(chipyard.example.VerilogTLDeviceParams(
deviceName = "example",
moduleName = "ExampleVerilogTLDevice",
verilogResourceFiles = Seq("ExampleVerilogTL.v")
)) ++
new chipyard.example.WithInitZero(0x88000000L, 0x1000L) ++ // add InitZero
new chipyard.harness.WithDontTouchChipTopPorts(false) ++ // TODO: hack around dontTouch not working in SFC
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
Expand Down
99 changes: 99 additions & 0 deletions generators/chipyard/src/main/scala/example/VerilogTLDevice.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package chipyard.example

import chisel3._
import chisel3.util._
import freechips.rocketchip.prci._
import freechips.rocketchip.subsystem._
import org.chipsalliance.cde.config.{Parameters, Field, Config}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper.{HasRegMap, RegField}
import freechips.rocketchip.tilelink._


// Template for a verilog TileLink device that contains both a register node, and a
// client node
case class VerilogTLDeviceParams(
deviceName: String,
moduleName: String,
verilogResourceFiles: Seq[String],
ctrlAddress: BigInt = 0x5000,
ctrlWhere: TLBusWrapperLocation = CBUS,
clientWhere: TLBusWrapperLocation = SBUS,
clientIdBits: Int = 4,
clientBeatBytes: Int = 8,
)

case object VerilogTLDeviceKey extends Field[Option[VerilogTLDeviceParams]](None)

trait CanHavePeripheryVerilogTLDevice { this: BaseSubsystem =>
p(VerilogTLDeviceKey).map { devParams =>
// WARNING: This assumes ctrlBus and clientBus are on the same clock
// This is most likely true, but beware if you start adding
// clock crossings between buses
val ctrlBus = locateTLBusWrapper(devParams.ctrlWhere)
val clientBus = locateTLBusWrapper(devParams.clientWhere)

val device = LazyModule(new VerilogTLDeviceWrapper(devParams)).suggestName(devParams.deviceName)
ctrlBus.coupleTo(devParams.deviceName) { device.ctrlNode := TLFragmenter(ctrlBus.beatBytes, ctrlBus.blockBytes) := _ }
clientBus.coupleFrom(devParams.deviceName) { _ := TLWidthWidget(devParams.clientBeatBytes) := device.clientNode }
device.clockNode := clientBus.fixedClockNode
}
}

class VerilogTLDeviceBlackBox(params: VerilogTLDeviceParams, ctrlBundle: TLBundleParameters, clientBundle: TLBundleParameters) extends BlackBox(Map(
"CTRL_ADDR_BITS" -> ctrlBundle.addressBits,
"CTRL_DATA_BITS" -> ctrlBundle.dataBits,
"CTRL_SOURCE_BITS" -> ctrlBundle.sourceBits,
"CTRL_SINK_BITS" -> ctrlBundle.sinkBits,
"CTRL_SIZE_BITS" -> ctrlBundle.sizeBits,
"CLIENT_ADDR_BITS" -> clientBundle.addressBits,
"CLIENT_DATA_BITS" -> clientBundle.dataBits,
"CLIENT_SOURCE_BITS" -> clientBundle.sourceBits,
"CLIENT_SINK_BITS" -> clientBundle.sinkBits,
"CLIENT_SIZE_BITS" -> clientBundle.sizeBits,
)) with HasBlackBoxResource {
val io = IO(new Bundle {
val clock = Input(Clock())
val reset = Input(Bool())
val tl_ctrl = Flipped(new TLBundle(ctrlBundle))
val tl_client = new TLBundle(clientBundle)
})
override val desiredName = params.moduleName

require(ctrlBundle.echoFields.isEmpty)
require(ctrlBundle.requestFields.isEmpty)
require(ctrlBundle.responseFields.isEmpty)
require(!ctrlBundle.hasBCE)
require(clientBundle.echoFields.isEmpty)
require(clientBundle.requestFields.isEmpty)
require(clientBundle.responseFields.isEmpty)
require(!clientBundle.hasBCE)

params.verilogResourceFiles.foreach(f => addResource(s"/vsrc/$f"))
}


class VerilogTLDeviceWrapper(params: VerilogTLDeviceParams)(implicit p: Parameters) extends ClockSinkDomain(ClockSinkParameters())(p) {
val device = new SimpleDevice(params.deviceName, Seq(s"ucbbar,${params.deviceName}"))
val ctrlNode = TLRegisterNode(
address = Seq(AddressSet(params.ctrlAddress, 4096-1)),
device = device,
beatBytes = 8)
val clientNode = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLClientParameters(
name = params.deviceName,
sourceId = IdRange(0, (1 << params.clientIdBits)))))))

override lazy val module = new VerilogTLDeviceImpl
class VerilogTLDeviceImpl extends Impl {
val device = Module(new VerilogTLDeviceBlackBox(params, ctrlNode.in(0)._2.bundle, clientNode.out(0)._2.bundle)).suggestName(params.deviceName)
device.io.clock := clock
device.io.reset := reset
device.io.tl_ctrl <> ctrlNode.in(0)._1
device.io.tl_client <> clientNode.out(0)._1

}
}

class WithVerilogTLDevice(params: VerilogTLDeviceParams) extends Config((site, here, up) => {
case VerilogTLDeviceKey => Some(params)
})
Loading