Commit b1077f0f authored by Dimitris Lampridis's avatar Dimitris Lampridis

sim: introduce WRTD driver and log message classes

parent 69f83f7c
......@@ -23,49 +23,177 @@
// and limitations under the License.
//------------------------------------------------------------------------------
`include "mock_turtle_driver.svh"
`include "wrtd_driver.svh"
`include "vhd_wishbone_master.svh"
`timescale 1ns/10fs
module simple_tdc_driver
(
input [3:0] addr,
output reg [27:0] data,
input wr,
input rd,
output reg ef1,
output reg ef2
);
typedef struct {
int channel;
time ts;
} acam_fifo_entry;
acam_fifo_entry fifo1[$], fifo2[$];
task pulse(int channel, time ts);
acam_fifo_entry ent;
ent.channel = channel % 4;
ent.ts = ts;
if (channel >= 0 && channel <= 3)
fifo1.push_back(ent);
else
fifo2.push_back(ent);
#100ns;
if(fifo1.size())
ef1 = 0;
if(fifo2.size())
ef2 = 0;
endtask // pulse
initial begin
ef1 = 1;
ef2 = 1;
data = 28'bz;
end
always@(negedge rd) begin
if (addr == 8) begin
acam_fifo_entry ent;
ent=fifo1.pop_front();
data <= ent.ts | (ent.channel << 26) | (1<<17);
end else if (addr == 9) begin
acam_fifo_entry ent;
ent=fifo2.pop_front();
data <= ent.ts | (ent.channel << 26) | (1<<17);
end else
data <= 28'bz;
#10ns;
ef1 <= (fifo1.size() ? 0 : 1);
ef2 <= (fifo2.size() ? 0 : 1);
end
endmodule // simple_tdc_driver
module simple_fdelay_mon
(
input [3:0] len,
input [9:0] val,
input [3:0] pulse
);
task display_pulse ();
string tmp;
tmp = $sformatf("[FDEL] Pulse: len=%x, val=%x, out=%x", len, val, pulse);
$display (tmp);
endtask // display_pulse
always@(posedge pulse) begin
display_pulse();
end
endmodule // simple_fdelay_mon
module main;
reg rst_n = 0;
reg clk_125m_pllref = 0;
reg clk_20m_vcxo = 0;
reg clk_ext = 0;
reg clk_acam = 0;
wire a2btxp, a2btxn, b2atxp, b2atxn;
always #50ns clk_ext <= ~clk_ext;
wire tdc_ef1, tdc_ef2, tdc_rd_n;
wire [3:0] tdc_addr;
wire [27:0] tdc_data;
wire [3:0] fdl_len, fdl_pulse;
wire [9:0] fdl_val;
always #50ns clk_ext <= ~clk_ext;
always #4ns clk_125m_pllref <= ~clk_125m_pllref;
always #20ns clk_20m_vcxo <= ~clk_20m_vcxo;
always #16ns clk_acam <= ~clk_acam;
always #20ns clk_20m_vcxo <= ~clk_20m_vcxo;
initial begin
repeat(20) @(posedge clk_20m_vcxo);
rst_n = 1;
end
const uint64_t mt_base = 'h2_0000;
//
// WRTD transmitter (TDC)
//
simple_tdc_driver
TDC
(
.addr(tdc_addr),
.data(tdc_data),
.wr(1'b0),
.rd(tdc_rd_n),
.ef1(tdc_ef1),
.ef2(tdc_ef2)
);
svec_list_top #
(
.g_simulation (1),
.g_sim_bypass_vme (1),
.g_dpram_initf("../../../dependencies/wr-cores/bin/wrpc/wrc_phy8_sim.bram")
.g_wr_dpram_initf("../../../dependencies/wr-cores/bin/wrpc/wrc_phy8_sim.bram"),
.g_mt_cpu0_initf("../../../software/firmware/tdc/wrtd-rt-tdc.bram"),
.g_mt_cpu1_initf("none")
)
DUT_A
(
.rst_n_i (rst_n),
.clk_125m_pllref_p_i (clk_125m_pllref),
.clk_125m_pllref_n_i (~clk_125m_pllref),
.clk_125m_gtp_p_i (clk_125m_pllref),
.clk_125m_gtp_n_i (~clk_125m_pllref),
.clk_20m_vcxo_i (clk_20m_vcxo),
.sim_wb_i (HostA.out),
.sim_wb_o (HostA.in),
.sfp_txp_o (a2btxp),
.sfp_txn_o (a2btxn),
.sfp_rxp_i (b2atxp),
.sfp_rxn_i (b2atxn)
.rst_n_i (rst_n),
.clk_125m_pllref_p_i (clk_125m_pllref),
.clk_125m_pllref_n_i (~clk_125m_pllref),
.clk_125m_gtp_p_i (clk_125m_pllref),
.clk_125m_gtp_n_i (~clk_125m_pllref),
.clk_20m_vcxo_i (clk_20m_vcxo),
.sim_wb_i (HostA.out),
.sim_wb_o (HostA.in),
.sfp_txp_o (a2btxp),
.sfp_txn_o (a2btxn),
.sfp_rxp_i (b2atxp),
.sfp_rxn_i (b2atxn),
.fmc0_tdc_pll_status_i (1'b1),
.fmc0_tdc_125m_clk_p_i (clk_125m_pllref),
.fmc0_tdc_125m_clk_n_i (~clk_125m_pllref),
.fmc0_tdc_acam_refclk_p_i (clk_acam),
.fmc0_tdc_acam_refclk_n_i (~clk_acam),
.fmc0_tdc_ef1_i (tdc_ef1),
.fmc0_tdc_ef2_i (tdc_ef2),
.fmc0_tdc_err_flag_i (1'b0),
.fmc0_tdc_int_flag_i (1'b0),
.fmc0_tdc_data_bus_io (tdc_data),
.fmc0_tdc_address_o (tdc_addr),
.fmc0_tdc_rd_n_o (tdc_rd_n)
);
IVHDWishboneMaster HostA
......@@ -75,26 +203,65 @@ module main;
IMockTurtleIRQ IrqMonitorA (`MT_ATTACH_IRQ(DUT_A.cmp_mock_turtle));
WrtdDriver drvA;
initial begin
@(posedge DUT_A.rst_sys_62m5_n);
@(posedge DUT_A.clk_sys_62m5);
drvA = new (HostA.get_accessor(), mt_base, IrqMonitorA, "DUT:A");
drvA.init();
forever begin
drvA.update ();
#1us;
end
end // initial begin DUTA
//
// WRTD receiver (Fine Delay)
//
/* -----\/----- EXCLUDED -----\/-----
simple_fdelay_mon
FDL
(
.len (fdl_len),
.val (fdl_val),
.pulse (fdl_pulse)
);
-----/\----- EXCLUDED -----/\----- */
svec_list_top #
(
.g_simulation (1),
.g_sim_bypass_vme (1),
.g_dpram_initf("../../../dependencies/wr-cores/bin/wrpc/wrc_phy8_sim.bram")
.g_wr_dpram_initf("../../../dependencies/wr-cores/bin/wrpc/wrc_phy8_sim.bram"),
.g_mt_cpu0_initf("none"),
.g_mt_cpu1_initf("../../../software/firmware/fd/wrtd-rt-fd.bram")
)
DUT_B
(
.rst_n_i (rst_n),
.clk_125m_pllref_p_i (clk_125m_pllref),
.clk_125m_pllref_n_i (~clk_125m_pllref),
.clk_125m_gtp_p_i (clk_125m_pllref),
.clk_125m_gtp_n_i (~clk_125m_pllref),
.clk_20m_vcxo_i (clk_20m_vcxo),
.sim_wb_i (HostB.out),
.sim_wb_o (HostB.in),
.sfp_txp_o (b2atxp),
.sfp_txn_o (b2atxn),
.sfp_rxp_i (a2btxp),
.sfp_rxn_i (a2btxn)
.rst_n_i (rst_n),
.clk_125m_pllref_p_i (clk_125m_pllref),
.clk_125m_pllref_n_i (~clk_125m_pllref),
.clk_125m_gtp_p_i (clk_125m_pllref),
.clk_125m_gtp_n_i (~clk_125m_pllref),
.clk_20m_vcxo_i (clk_20m_vcxo),
.sim_wb_i (HostB.out),
.sim_wb_o (HostB.in),
.sfp_txp_o (b2atxp),
.sfp_txn_o (b2atxn),
.sfp_rxp_i (a2btxp),
.sfp_rxn_i (a2btxn),
.fmc1_fd_clk_ref_p_i (clk_125m_pllref),
.fmc1_fd_clk_ref_n_i (~clk_125m_pllref),
.fmc1_fd_delay_len_o (fdl_len),
.fmc1_fd_delay_val_o (fdl_val),
.fmc1_fd_delay_pulse_o (fdl_pulse)
);
IVHDWishboneMaster HostB
......@@ -104,44 +271,34 @@ module main;
IMockTurtleIRQ IrqMonitorB (`MT_ATTACH_IRQ(DUT_B.cmp_mock_turtle));
string fw = "../../../tests/firmware/rmq-udp/fw-rmq-udp.bin";
const uint64_t mt_base = 'h2_0000;
MockTurtleDriver drvA, drvB;
WrtdDriver drvB;
initial begin
@(posedge DUT_A.rst_sys_62m5_n);
@(posedge DUT_A.clk_sys_62m5);
@(posedge DUT_B.rst_sys_62m5_n);
@(posedge DUT_B.clk_sys_62m5);
drvA = new (HostA.get_accessor(), mt_base, IrqMonitorA, "DUTA");
drvB = new (HostB.get_accessor(), mt_base, IrqMonitorB, "DUTB");
drvB = new (HostB.get_accessor(), mt_base, IrqMonitorB, "DUT:B");
drvA.init();
drvB.init();
drvA.enable_console_irq (0, 1);
drvB.enable_console_irq (1, 1);
drvA.load_firmware(0, fw, 1'b0);
drvB.load_firmware(1, fw, 1'b0);
drvA.reset_core(0, 0);
drvB.reset_core(1, 0);
forever begin
drvA.update ();
drvB.update ();
#1us;
end
end // initial begin
end // initial begin DUTB
/// ////////////////////////////////////////////////////////////////////////
/// Silence Xilinx unisim DSP48A1 warnings about invalid OPMODE
/// ////////////////////////////////////////////////////////////////////////
initial begin
initial begin // others
$timeformat (-6, 3, "us", 10);
// Skip WR SoftPLL lock
force DUT_A.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.U_SOFTPLL.U_Wrapped_Softpll.out_locked_o = 3'b111;
force DUT_B.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.U_SOFTPLL.U_Wrapped_Softpll.out_locked_o = 3'b111;
// Silence Xilinx unisim DSP48A1 warnings about invalid OPMODE
force DUT_A.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D1.OPMODE_dly = 0;
......@@ -160,6 +317,16 @@ module main;
force DUT_B.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D3.OPMODE_dly = 0;
end
#200us;
forever begin
#200us;
TDC.pulse(0, 0);
TDC.pulse(1, 0);
TDC.pulse(2, 0);
end
end // initial begin others
endmodule // main
......@@ -5,4 +5,4 @@ set NumericStdNoWarnings 1
radix -hexadecimal
run 300us
run 1000us
......@@ -5,7 +5,7 @@ vsim -quiet -L unisim work.main -suppress 8683,8684,8822
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
run 800us
run 1000us
exit
//
// unit name: WrtdDriver
//
// description: A SystemVerilog Class to provide an abstraction of a complete
// WRTD system.
//
//------------------------------------------------------------------------------
// Copyright CERN 2018
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0.
// Unless required by applicable law or agreed to in writing, software,
// hardware and materials distributed under this License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions
// and limitations under the License.
//------------------------------------------------------------------------------
`ifndef __WRTD_DRIVER_INCLUDED
`define __WRTD_DRIVER_INCLUDED
`include "mock_turtle_driver.svh"
`define WRTD_HMQ_LOG_SLOT 0
typedef struct {
uint32_t system;
uint32_t source_port;
uint32_t trigger;
} wrtd_trig_id;
typedef struct {
uint64_t seconds;
uint32_t ticks;
uint32_t frac;
} wr_timestamp;
typedef enum {
NOT_MISSED = -1,
DEAD_TIME = 0,
OVERFLOW = 1,
NO_WR = 2,
TIMEOUT = 3
} wrtd_log_miss_reason;
typedef enum {
RAW = (1 << 0),
SENT = (1 << 1),
PROMISC = (1 << 2),
FILTERED = (1 << 3),
EXECUTED = (1 << 4),
MISSED = (1 << 5)
} wrtd_log_type;
typedef enum {
WRTD_IN = 2,
WRTD_OUT = 6
} wrtd_log_origin;
class WrtdLogMsg;
wrtd_log_origin origin;
wrtd_log_type ltype;
uint32_t seq;
int channel;
wrtd_trig_id id;
wr_timestamp ts;
wrtd_log_miss_reason miss_reason;
function new ( MQueueMsg msg );
this.origin = wrtd_log_origin'(msg.header.msg_id);
this.ltype = wrtd_log_type'(msg.data[0]);
this.seq = msg.data[1];
this.channel = msg.data[2];
this.id.system = msg.data[3];
this.id.source_port = msg.data[4];
this.id.trigger = msg.data[5];
this.ts.seconds = (msg.data[7] << 32) | msg.data[6];
this.ts.ticks = msg.data[8];
this.ts.frac = msg.data[9];
if ( this.ltype == MISSED )
this.miss_reason = wrtd_log_miss_reason'(msg.data[10]);
else
this.miss_reason = NOT_MISSED;
endfunction // new
function string tostring ();
string str;
str = $sformatf ( {"[%8s] TYPE: %8s, SEQ: %3d, CHANNEL: %2d, ",
"TRIG_SYS: %0d, TRIG_PORT: %0d, TRIG_ID: %0d, ",
"TS_SEC: %2d, TS_TICKS: %10d" },
origin.name(), ltype.name(), seq, channel,
id.system, id.source_port, id.trigger,
ts.seconds, ts.ticks);
if ( ts.frac > 0 )
str = { str, $sformatf ( ", TS_FRAC: %0d", ts.frac ) };
if ( miss_reason != NOT_MISSED )
str = { str, $sformatf ( ", MISS_REASON: %s", miss_reason ) };
return str;
endfunction // tostring
endclass // WrtdLogMsg
class WrtdDriver;
protected string name;
protected int hmq_log_slot;
protected MockTurtleDriver mt;
function new ( CWishboneAccessor acc, uint64_t base,
vIMockTurtleIRQ irq, string name = "" );
this.name = name;
this.mt = new (acc, base, irq, name);
endfunction // new
task mdisplay ( string str );
string tmp;
if (this.name == "")
tmp = $sformatf("<%t> %s", $realtime, str);
else
tmp = $sformatf("[%s] <%t> %s", this.name, $realtime, str);
$display (tmp);
endtask // mdisplay
task init ( wb_cycle_type_t mode = PIPELINED,
string cpu0_fw = "",
string cpu1_fw = "");
mt.init ( mode );
mt.enable_console_irq ( 0, 1 );
mt.enable_console_irq ( 1, 1 );
mt.enable_hmqi_irq ( 0, 0, 1 );
mt.enable_hmqi_irq ( 1, 0, 1 );
mt.reset_core ( 0, 1 );
mt.reset_core ( 1, 1 );
if ( cpu0_fw != "" )
mt.load_firmware ( 0, cpu0_fw, 1'b0 );
if ( cpu1_fw != "" )
mt.load_firmware ( 0, cpu1_fw, 1'b0 );
mt.reset_core ( 0, 0 );
mt.reset_core ( 1, 0 );
endtask // init
task check_log_queue ( int core );
WrtdLogMsg log_msg;
MQueueMsg msg;
msg = new ( core, `WRTD_HMQ_LOG_SLOT );
while ( mt.hmq_pending_messages ( core, `WRTD_HMQ_LOG_SLOT ) )
begin
mt.hmq_receive_message ( msg );
log_msg = new ( msg );
mdisplay ( log_msg.tostring ( ) );
end
endtask // check_log_queue
task update ( );
mt.update ( );
fork
check_log_queue ( 0 );
check_log_queue ( 1 );
join
endtask // update
endclass // WrtdDriver
`endif // `ifndef __WRTD_DRIVER_INCLUDED
......@@ -2,6 +2,7 @@
*.bin
*.o
*.d
*.bram
build/
.config
.config.old
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment