object MarkDebug {
private var counter = 0
def apply(clock: Clock, signals: Seq[UInt],
widths: Seq[Int]): ILACore = {
val ila = Module(new ILACore(s"hub${counter}", widths))
ila.io.clk := clock
// ISSUE: Connect probes with corresponding signals
(signals zip ila.io.drop(1)) foreach { case (s, p) p := s }
counter += 1
ila
}
}
class ILACore(name: String, probeWidths: Seq[Int])
extends BlackBox with HasBlackBoxInline {
// ISSUE: Generate ports with matching names and widths
// using verilog inline source
// probeWidths contains the width of each signal
// (i.e., probeWidths(3) => width of probe3)
val io = IO(new Bundle{
val clk = Input(Clock())
(0 until probeWidths.length) map/foreach { i => declare probe#i }
})
setInline(s"BlackBox${name}.v",
s"""`timescale 1ns/1ps
|
|module BlackBox${name} (
| input clk,
${(probeWidths.zip(0 until probeWidths.length) map {
case (w, idx) =>
s"| input [${w-1}:0] probe${idx}"}).mkString(",\n")}
|);
|
|ila_debug_${name} debug_${name} (
| .clk(clk)
${((0 until probeWidths.length) map {
i => s"| .probe${i}(probe${i})"}).mkString(",\n")}
|);
|
|endmodule""".stripMargin)
ILAGenerator(name, probeWidths)
}
object ILAGenerator {
def apply(name: String, probeWidths: Seq[Int]) = {
var builder = s"""
create_ip -vendor xilinx.com -library ip -name ila \ -version 6.2 -module_name ila_debug_${name} \
-dir $$ipdir -force
set_property -dict [list \
CONFIG.ALL_PROBE_SAME_MU {TRUE} \
CONFIG.ALL_PROBE_SAME_MU_CNT {1} \
CONFIG.C_ADV_TRIGGER {FALSE} \
CONFIG.C_CLKFBOUT_MULT_F {10} \
CONFIG.C_CLKOUT0_DIVIDE_F {10} \
CONFIG.C_CLK_FREQ {200} \
CONFIG.C_CLK_PERIOD {5} \
CONFIG.C_DATA_DEPTH {1024} \
CONFIG.C_DDR_CLK_GEN {FALSE} \
CONFIG.C_DIVCLK_DIVIDE {3} \
CONFIG.C_ENABLE_ILA_AXI_MON {false} \
CONFIG.C_EN_DDR_ILA {FALSE} \
CONFIG.C_EN_STRG_QUAL {0} \
CONFIG.C_EN_TIME_TAG {0} \
CONFIG.C_ILA_CLK_FREQ {2000000} \
CONFIG.C_INPUT_PIPE_STAGES {0} \
CONFIG.C_MONITOR_TYPE {Native} \
CONFIG.C_NUM_MONITOR_SLOTS {1} \"""
builder += s"\nCONFIG.C_NUM_OF_PROBES
{${probeWidths.length}} \\"
for (i <- 0 until probeWidths.length) {
builder += s"\nCONFIG.C_PROBE${i}_MU_CNT {1} \\"
builder += s"\nCONFIG.C_PROBE${i}_TYPE {0} \\"
builder += s"\nCONFIG.C_PROBE${i}_WIDTH
{${probeWidths(i)}} \\"
}
builder += s"""
CONFIG.C_SLOT_0_AXIS_TDATA_WIDTH {32} \
CONFIG.C_SLOT_0_AXIS_TDEST_WIDTH {1} \
CONFIG.C_SLOT_0_AXIS_TID_WIDTH {1} \
CONFIG.C_SLOT_0_AXIS_TUSER_WIDTH {1} \
CONFIG.C_SLOT_0_AXI_ADDR_WIDTH {32} \
CONFIG.C_SLOT_0_AXI_ARUSER_WIDTH {1} \
CONFIG.C_SLOT_0_AXI_AWUSER_WIDTH {1} \
CONFIG.C_SLOT_0_AXI_BUSER_WIDTH {1} \
CONFIG.C_SLOT_0_AXI_DATA_WIDTH {32} \
CONFIG.C_SLOT_0_AXI_ID_WIDTH {1} \
CONFIG.C_SLOT_0_AXI_PROTOCOL {AXI4} \
CONFIG.C_SLOT_0_AXI_RUSER_WIDTH {1} \
CONFIG.C_SLOT_0_AXI_WUSER_WIDTH {1} \
CONFIG.C_TIME_TAG_WIDTH {32} \
CONFIG.C_TRIGIN_EN {false} \
CONFIG.C_TRIGOUT_EN {false} \
CONFIG.C_XLNX_HW_PROBE_INFO {DEFAULT} \
CONFIG.EN_BRAM_DRC {TRUE} \
CONFIG.SIGNAL_CLOCK.FREQ_HZ {100000000} \
CONFIG.SIGNAL_CLOCK.INSERT_VIP {0} \
CONFIG.SLOT_0_AXI.INSERT_VIP {0} \
CONFIG.SLOT_0_AXIS.INSERT_VIP {0} \
] [get_ips ila_debug_${name}]
"""
ElaborationArtefacts.add(s"iladebug${name}.vivado.tcl",
builder)
}
}