Skip to content

Commit a96d5ff

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 a96d5ff

File tree

5 files changed

+37
-17
lines changed

5 files changed

+37
-17
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/DPIC.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,6 @@ class DPICBatch(template: Seq[DifftestBundle], batchIO: BatchIO, config: Gateway
292292
| enum DifftestBundleType {
293293
| ${bundleEnum.mkString(",\n ")}
294294
| };
295-
| extern void simv_nstep(uint8_t step);
296295
| static int dut_index = 0;
297296
| $batchDecl
298297
| for (int i = 0; i < $infoLen; i++) {
@@ -301,7 +300,13 @@ class DPICBatch(template: Seq[DifftestBundle], batchIO: BatchIO, config: Gateway
301300
| uint32_t coreid, index, address;
302301
| if (id == BatchFinish) {
303302
|#ifdef CONFIG_DIFFTEST_INTERNAL_STEP
303+
|#ifdef CONFIG_PLATFORM_FPGA
304+
| extern void fpga_nstep(uint8_t step);
305+
| fpga_nstep(num);
306+
|#else
307+
| extern void simv_nstep(uint8_t step);
304308
| simv_nstep(num);
309+
|#endif // CONFIG_PLATFORM_FPGA
305310
|#endif // CONFIG_DIFFTEST_INTERNAL_STEP
306311
| break;
307312
| }

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.isBatch && 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 = {

src/test/csrc/fpga/fpga_main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ void fpga_finish() {
106106
simMemory = nullptr;
107107
}
108108

109-
void fpga_nstep(uint8_t step) {
109+
extern "C" void fpga_nstep(uint8_t step) {
110110
for (int i = 0; i < step; i++) {
111111
fpga_step();
112112
}

0 commit comments

Comments
 (0)