Skip to content

Commit 52f4598

Browse files
committed
FPGA: expose IO with finishFPGA
This change expose FPGA IO with finishFPGA, enabling us to wrap both DUT, Difftest, and changing DiffTestBundle Interface within the same wrapper. Only the output of Batch, with width declared at DifftestMacros.v, will be exposed to FPGA.
1 parent 1953acf commit 52f4598

File tree

3 files changed

+30
-15
lines changed

3 files changed

+30
-15
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,6 @@ jobs:
334334
- name: FPGA-difftest Build
335335
run: |
336336
cd $NOOP_HOME
337-
make sim-verilog MILL_ARGS="--difftest-config SF" -j2
337+
make sim-verilog MILL_ARGS="--difftest-config ESBIDF" -j2
338338
cd ./difftest
339339
make fpga-build FPGA=1

src/main/scala/Difftest.scala

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import chisel3._
2020
import chisel3.reflect.DataMirror
2121
import chisel3.util._
2222
import difftest.common.{DifftestWiring, FileControl}
23-
import difftest.gateway.{Gateway, GatewayConfig}
23+
import difftest.gateway.{FpgaDiffIO, Gateway, GatewayConfig, GatewayResult}
2424
import difftest.util.Profile
2525

2626
import scala.annotation.tailrec
@@ -541,9 +541,8 @@ object DifftestModule {
541541

542542
def get_current_interfaces(): Seq[(DifftestBundle, Int)] = interfaces.toSeq
543543

544-
def finish(cpu: String, createTopIO: Boolean): Option[DifftestTopIO] = {
544+
def collect(cpu: String): GatewayResult = {
545545
val gateway = Gateway.collect()
546-
547546
generateCppHeader(
548547
cpu,
549548
gateway.instances,
@@ -556,7 +555,19 @@ object DifftestModule {
556555
}
557556
generateVeriogHeader(gateway.vMacros)
558557
Profile.generateJson(cpu, interfaces.toSeq)
558+
gateway
559+
}
559560

561+
def finishFPGA(cpu: String): FpgaDiffIO = {
562+
val gateway = collect(cpu)
563+
val fpgaIO = gateway.fpgaIO.get
564+
val io = IO(Output(chiselTypeOf(fpgaIO)))
565+
io := fpgaIO
566+
io
567+
}
568+
569+
def finish(cpu: String, createTopIO: Boolean): Option[DifftestTopIO] = {
570+
val gateway = collect(cpu)
560571
Option.when(createTopIO) {
561572
if (enabled) {
562573
createTopIOs(gateway.exit, gateway.step)

src/main/scala/Gateway.scala

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,18 @@ case class GatewayConfig(
103103
if (isBatch) require(!hasDutZone)
104104
// Currently Delta depends on Batch to ensure update and sync order
105105
if (isDelta) require(isBatch)
106+
// Batch provides unified IO interface for FPGA Diff
107+
if (isFPGA) require(isBatch)
106108
// TODO: support dump and load together
107109
require(!(traceDump && traceLoad))
108110
}
109111
}
110112

113+
class FpgaDiffIO(config: GatewayConfig) extends Bundle {
114+
val data = UInt(config.batchBitWidth.W)
115+
val enable = Bool()
116+
}
117+
111118
case class GatewayResult(
112119
cppMacros: Seq[String] = Seq(),
113120
vMacros: Seq[String] = Seq(),
@@ -117,6 +124,7 @@ case class GatewayResult(
117124
cppExtModule: Option[Boolean] = None,
118125
exit: Option[UInt] = None,
119126
step: Option[UInt] = None,
127+
fpgaIO: Option[FpgaDiffIO] = None,
120128
) {
121129
def +(that: GatewayResult): GatewayResult = {
122130
GatewayResult(
@@ -128,6 +136,7 @@ case class GatewayResult(
128136
cppExtModule = if (cppExtModule.isDefined) cppExtModule else that.cppExtModule,
129137
exit = if (exit.isDefined) exit else that.exit,
130138
step = if (step.isDefined) step else that.step,
139+
fpgaIO = if (fpgaIO.isDefined) fpgaIO else that.fpgaIO,
131140
)
132141
}
133142
}
@@ -199,6 +208,7 @@ object Gateway {
199208
structPacked = Some(config.isBatch),
200209
structAligned = Some(config.isDelta),
201210
step = Some(endpoint.step),
211+
fpgaIO = endpoint.fpgaIO,
202212
)
203213
} else {
204214
GatewayResult(instances = instances) + GatewaySink.collect(config)
@@ -256,11 +266,16 @@ class GatewayEndpoint(instanceWithDelay: Seq[(DifftestBundle, Int)], config: Gat
256266
val step = IO(Output(UInt(config.stepWidth.W)))
257267
val control = Wire(new GatewaySinkControl(config))
258268

269+
val fpgaIO = Option.when(config.isFPGA)(IO(Output(new FpgaDiffIO(config))))
259270
if (config.isBatch) {
260271
val batch = Batch(toSink, config)
261272
step := RegNext(batch.step, 0.U) // expose Batch step to check timeout
262273
control.enable := batch.enable
263274
GatewaySink.batch(Batch.getTemplate, control, batch.io, config)
275+
if (config.isFPGA) {
276+
fpgaIO.get.data := batch.io.asUInt
277+
fpgaIO.get.enable := batch.enable
278+
}
264279
} else {
265280
val sink_enable = VecInit(toSink.map(_.valid).toSeq).asUInt.orR
266281
step := RegNext(sink_enable, 0.U)
@@ -292,17 +307,6 @@ object GatewaySink {
292307
case "dpic" => DPIC.batch(template, control, io, config)
293308
case _ => DPIC.batch(template, control, io, config) // Default: DPI-C
294309
}
295-
val out = Option.when(config.isFPGA) {
296-
IO(new Bundle {
297-
val data = Output(UInt(config.batchBitWidth.W))
298-
val enable = Output(Bool())
299-
})
300-
}
301-
if (config.isFPGA) {
302-
out.get.data := Cat(io.data, io.info)
303-
out.get.enable := control.enable
304-
dontTouch(out.get)
305-
}
306310
}
307311

308312
def collect(config: GatewayConfig): GatewayResult = {

0 commit comments

Comments
 (0)