/
VitisShim.scala
120 lines (98 loc) · 4.51 KB
/
VitisShim.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package midas
package platform
import chisel3._
import junctions._
import freechips.rocketchip.amba.axi4._
import org.chipsalliance.cde.config.Parameters
import freechips.rocketchip.diplomacy.LazyRawModuleImp
import midas.core.HostMemChannelKey
import midas.widgets.CtrlNastiKey
import midas.stage.GoldenGateOutputFileAnnotation
import midas.platform.xilinx._
object VitisConstants {
// Configurable through v++
val kernelDefaultFreqMHz = 300.0
// This is wider than the addresses used in FPGATop
val axi4MAddressBits = 64
/** The hardcoded TCL variable name used to specify the simulator's frequency */
val frequencyVariableName = "frequency"
}
class VitisShim(implicit p: Parameters) extends PlatformShim {
val ctrlAXI4BundleParams =
AXI4BundleParameters(p(CtrlNastiKey).addrBits, p(CtrlNastiKey).dataBits, p(CtrlNastiKey).idBits)
val hostMemAXI4BundleParams = p(HostMemChannelKey).axi4BundleParams
.copy(addrBits = VitisConstants.axi4MAddressBits)
lazy val module = new LazyRawModuleImp(this) {
// drive all {Lazy}Modules with a default clock/reset (defaults to an incorrect clock/reset)
override def provideImplicitClockToLazyChildren = true
val ap_rst_n = IO(Input(AsyncReset()))
val ap_clk = IO(Input(Clock()))
val s_axi_lite = IO(Flipped(new XilinxAXI4Bundle(ctrlAXI4BundleParams, isAXI4Lite = true)))
val host_mem_0 = IO((new XilinxAXI4Bundle(hostMemAXI4BundleParams)))
val ap_rst = (!ap_rst_n.asBool)
// Setup Internal Clocking
val firesimMMCM = Module(
new MMCM(
FrequencySpec.Static(VitisConstants.kernelDefaultFreqMHz),
FrequencySpec.TCLVariable(VitisConstants.frequencyVariableName),
"firesim_clocking",
)
)
firesimMMCM.io.clk_in1 := ap_clk
firesimMMCM.io.reset := ap_rst.asAsyncReset
val hostClock = firesimMMCM.io.clk_out1
val hostSyncReset = ResetSynchronizer(ap_rst || !firesimMMCM.io.locked, hostClock, initValue = true)
// overrides the implicit clock/reset given
top.module.reset := hostSyncReset
top.module.clock := hostClock
top.module.mem.foreach({ case bundle =>
bundle.ar.ready := false.B
bundle.aw.ready := false.B
bundle.w.ready := false.B
bundle.r.valid := false.B
bundle.b.valid := false.B
})
val ctrl_cdc = Module(new AXI4ClockConverter(ctrlAXI4BundleParams, "ctrl_cdc", isAXI4Lite = true))
ctrl_cdc.io.s_axi <> s_axi_lite
ctrl_cdc.io.s_axi_aclk := ap_clk
ctrl_cdc.io.s_axi_aresetn := (!ap_rst).asAsyncReset
ctrl_cdc.io.m_axi_aclk := hostClock
ctrl_cdc.io.m_axi_aresetn := (!hostSyncReset).asAsyncReset
// All this awful block of code does is convert between three different
// AXI4 bundle formats (Xilinx, RC Standard, Legacy Nasti).
val axi4ToNasti = Module(new AXI42NastiIdentityModule(ctrlAXI4BundleParams))
// Clock and reset are provided here only to enable assertion generation
ctrl_cdc.io.m_axi.driveStandardAXI4(axi4ToNasti.io.axi4, hostClock, hostSyncReset)
top.module.ctrl <> axi4ToNasti.io.nasti
if (top.module.mem.nonEmpty) {
val addrWidth = VitisConstants.axi4MAddressBits.W
val host_mem_cdc = Module(new AXI4ClockConverter(hostMemAXI4BundleParams, "host_mem_cdc"))
host_mem_cdc.io.s_axi.drivenByStandardAXI4(top.module.mem(0), hostClock, hostSyncReset)
host_mem_cdc.io.s_axi_aclk := hostClock
host_mem_cdc.io.s_axi_aresetn := (!hostSyncReset).asAsyncReset
host_mem_cdc.io.s_axi.araddr := 0x4000000000L.U(addrWidth) + top.module.mem(0).ar.bits.addr
host_mem_cdc.io.s_axi.awaddr := 0x4000000000L.U(addrWidth) + top.module.mem(0).aw.bits.addr
host_mem_cdc.io.s_axi.arcache.foreach { _ := AXI4Parameters.CACHE_MODIFIABLE }
host_mem_cdc.io.s_axi.awcache.foreach { _ := AXI4Parameters.CACHE_MODIFIABLE }
host_mem_0 <> host_mem_cdc.io.m_axi
host_mem_cdc.io.m_axi_aclk := ap_clk
host_mem_cdc.io.m_axi_aresetn := ap_rst_n
} else {
host_mem_0.tieoffAsManager
}
top.module.fpga_managed_axi4.map { axi4 =>
axi4.ar.ready := false.B
axi4.aw.ready := false.B
axi4.w.ready := false.B
axi4.r <> DontCare
axi4.b <> DontCare
axi4.r.valid := false.B
axi4.b.valid := false.B
}
GoldenGateOutputFileAnnotation.annotateFromChisel(
s"// Vitis Shim requires no dynamically generated macros \n",
fileSuffix = ".defines.vh",
)
GoldenGateOutputFileAnnotation.annotateFromChisel(s"# Currenty unused", ".env.tcl")
}
}