Commit 563d4184 authored by Dimitris Lampridis's avatar Dimitris Lampridis

hdl: align testbench with updated wrtd library

parent 7d0c067c
...@@ -34,8 +34,8 @@ class WrtdAlarm extends WrtdRepCap; ...@@ -34,8 +34,8 @@ class WrtdAlarm extends WrtdRepCap;
protected int repeat_count; protected int repeat_count;
protected uint32_t period_ns; protected uint32_t period_ns;
function new ( int core, int index, string name = "" ); function new ( string name = "" );
super.new ( core, index, name ); super.new ( name );
this.setup_time = new(); this.setup_time = new();
this.ev.ts = new(); this.ev.ts = new();
this.ev.id = new(); this.ev.id = new();
......
...@@ -36,13 +36,18 @@ ...@@ -36,13 +36,18 @@
`define WRTD_IO_MSG_WORD_SIZE 2 `define WRTD_IO_MSG_WORD_SIZE 2
`define WRTD_CFG_MSG_WORD_SIZE 5 `define WRTD_CFG_MSG_WORD_SIZE 5
`define WRTD_ROOT_WORD_SIZE 13 `define WRTD_ROOT_WORD_SIZE 12
`define WRTD_RULE_WORD_SIZE 40 `define WRTD_RULE_WORD_SIZE 40
`define WRTD_ALRM_WORD_SIZE 15 `define WRTD_ALRM_WORD_SIZE 15
`define WRTD_DEST_CPU_LOCAL 'hfe `define WRTD_DEST_CPU_LOCAL 'hfe
`define WRTD_DEST_CH_NET 'hff `define WRTD_DEST_CH_NET 'hff
`define WRTD_CAP_NET_RX 1
`define WRTD_CAP_NET_TX 2
`define WRTD_CAP_LOCAL_RX 4
`define WRTD_CAP_LOCAL_TX 8
enum { enum {
WRTD_ACTION_GET_CONFIG, WRTD_ACTION_GET_CONFIG,
WRTD_ACTION_READW, WRTD_ACTION_READW,
...@@ -211,44 +216,15 @@ typedef struct { ...@@ -211,44 +216,15 @@ typedef struct {
typedef struct { typedef struct {
uint32_t addr; uint32_t addr;
uint32_t fw_id;
uint32_t nbr_alarms; uint32_t nbr_alarms;
uint32_t alarms_addr; uint32_t alarms_addr;
uint32_t nbr_rules; uint32_t nbr_rules;
uint32_t capabilities;
uint32_t rules_addr; uint32_t rules_addr;
uint32_t nbr_devs; uint32_t nbr_devs;
uint32_t devs_addr[4]; uint32_t nbr_channels[4];
uint32_t channel_dir[4];
} wrtd_root; } wrtd_root;
typedef struct {
int core;
int index;
int ch_en;
} wrtd_dev;
typedef struct {
string name;
uint32_t dir;
uint32_t nbr_chs;
string channels[];
/* -----\/----- EXCLUDED -----\/-----
enum wrtd_status (*configure)(struct wrtd_dev *wrtd,
unsigned cpu, unsigned dev,
unsigned int mask);
-----/\----- EXCLUDED -----/\----- */
} wrtd_mt_device;
typedef struct {
uint32_t fw_id;
uint32_t nbr_devices;
wrtd_mt_device devices[`WRTD_MAX_DEVS];
} wrtd_mt_cpu_config;
typedef struct {
uint32_t mt_app_id;
uint32_t nbr_cpus;
uint32_t tx_cpu;
uint32_t rx_cpu;
wrtd_mt_cpu_config cpus[`WRTD_MAX_CPUS];
} wrtd_mt_config;
`endif // `ifndef __WRTD_DEFINE_INCLUDED `endif // `ifndef __WRTD_DEFINE_INCLUDED
...@@ -39,9 +39,7 @@ class WrtdDrv; ...@@ -39,9 +39,7 @@ class WrtdDrv;
protected uint32_t nbr_cpus; protected uint32_t nbr_cpus;
protected uint32_t free_rule_slots[]; protected uint32_t free_rule_slots[];
protected uint32_t hmq_words[]; protected uint32_t hmq_words[];
protected wrtd_mt_config cfg;
protected wrtd_root roots[]; protected wrtd_root roots[];
protected wrtd_dev devices[$];
protected WrtdRepCapCollection rules; protected WrtdRepCapCollection rules;
protected WrtdRepCapCollection alarms; protected WrtdRepCapCollection alarms;
...@@ -75,39 +73,12 @@ class WrtdDrv; ...@@ -75,39 +73,12 @@ class WrtdDrv;
WrtdAlarm new_alarm; WrtdAlarm new_alarm;
wrtd_dev new_dev;
uint32_t data[]; uint32_t data[];
this.ready = 0; this.ready = 0;
mt.init ( ); mt.init ( );
// TODO: replace with non-hardcoded values
this.cfg.mt_app_id = 'h115790d1;
this.cfg.nbr_cpus = 1;
this.cfg.tx_cpu = 0;
this.cfg.rx_cpu = 0;
this.cfg.cpus[0].fw_id = 'h35b0;
this.cfg.cpus[0].nbr_devices = 2;
this.cfg.cpus[0].devices[0].name = "FMC ADCin 5CH";
this.cfg.cpus[0].devices[0].dir = WRTD_DIR_INPUT;
this.cfg.cpus[0].devices[0].nbr_chs = 5;
this.cfg.cpus[0].devices[0].channels = new[5];
this.cfg.cpus[0].devices[0].channels[0] = "ADCI1";
this.cfg.cpus[0].devices[0].channels[1] = "ADCI2";
this.cfg.cpus[0].devices[0].channels[2] = "ADCI3";
this.cfg.cpus[0].devices[0].channels[3] = "ADCI4";
this.cfg.cpus[0].devices[0].channels[4] = "ADCI5";
this.cfg.cpus[0].devices[1].name = "FMC ADCout";
this.cfg.cpus[0].devices[1].dir = WRTD_DIR_OUTPUT;
this.cfg.cpus[0].devices[1].nbr_chs = 1;
this.cfg.cpus[0].devices[1].channels = new[1];
this.cfg.cpus[0].devices[1].channels[0] = "ADCO1";
this.nbr_cpus = mt.rom.getCoreCount ( ); this.nbr_cpus = mt.rom.getCoreCount ( );
this.free_rule_slots = new[this.nbr_cpus]; this.free_rule_slots = new[this.nbr_cpus];
...@@ -135,9 +106,12 @@ class WrtdDrv; ...@@ -135,9 +106,12 @@ class WrtdDrv;
while ( cpu_ready == 0 ) while ( cpu_ready == 0 )
begin begin
val = 0; val = 0;
mt.get_single_cpu_notification ( 0, val ); if ( mt.pending_cpu_notifications ( i ) != 0 )
if ( val == TRTL_CPU_NOTIFY_MAIN ) begin
cpu_ready = 1; mt.get_single_cpu_notification ( i, val );
if ( val == TRTL_CPU_NOTIFY_MAIN )
cpu_ready = 1;
end
# 1us; # 1us;
end end
// retrieve address of root // retrieve address of root
...@@ -145,17 +119,23 @@ class WrtdDrv; ...@@ -145,17 +119,23 @@ class WrtdDrv;
this.roots[i].addr = data[0]; this.roots[i].addr = data[0];
// retrieve root // retrieve root
msg_readw ( i, this.roots[i].addr, `WRTD_ROOT_WORD_SIZE, data ); msg_readw ( i, this.roots[i].addr, `WRTD_ROOT_WORD_SIZE, data );
this.roots[i].nbr_rules = ( data[1] & 'h00ff0000 ) >> 16; this.roots[i].fw_id = data[1];
this.roots[i].nbr_alarms = ( data[1] & 'h0000ff00 ) >> 8; this.roots[i].capabilities = ( data[2] & 'hff000000 ) >> 24;
this.roots[i].nbr_devs = ( data[1] & 'h000000ff ) >> 0; this.roots[i].nbr_rules = ( data[2] & 'h00ff0000 ) >> 16;
this.roots[i].devs_addr[0:3] = data[4:7]; this.roots[i].nbr_alarms = ( data[2] & 'h0000ff00 ) >> 8;
this.roots[i].rules_addr = data[8]; this.roots[i].nbr_devs = ( data[2] & 'h000000ff ) >> 0;
this.roots[i].alarms_addr = data[9]; for ( j = 0; j < 4; j++)
begin
this.roots[i].nbr_channels[j] = ( data[5] >> j*8 ) & 'hff;
this.roots[i].channel_dir[j] = ( data[6] >> j*8 ) & 'hff;
end
this.roots[i].rules_addr = data[7];
this.roots[i].alarms_addr = data[8];
// init free rule slots // init free rule slots
this.free_rule_slots[i] = this.roots[i].nbr_rules; this.free_rule_slots[i] = this.roots[i].nbr_rules;
// turn on all logging if enabled // turn on all logging if enabled
if ( this.enable_logging ) if ( this.enable_logging )
msg_writew ( i, this.roots[i].addr + 12, 1, { data[3] | 32'hff } ); msg_writew ( i, this.roots[i].addr + 16, 1, { data[4] | 32'hff } );
end end
// initialise rules // initialise rules
...@@ -163,7 +143,7 @@ class WrtdDrv; ...@@ -163,7 +143,7 @@ class WrtdDrv;
for ( i = 0; i < this.nbr_cpus; i++ ) for ( i = 0; i < this.nbr_cpus; i++ )
for ( j = 0; j < this.roots[i].nbr_rules; j++ ) for ( j = 0; j < this.roots[i].nbr_rules; j++ )
begin begin
new_rule = new ( i, j, this.name ); new_rule = new ( this.name );
this.rules.collection.push_back ( new_rule ); this.rules.collection.push_back ( new_rule );
end end
...@@ -172,29 +152,14 @@ class WrtdDrv; ...@@ -172,29 +152,14 @@ class WrtdDrv;
for ( i = 0; i < this.nbr_cpus; i++ ) for ( i = 0; i < this.nbr_cpus; i++ )
for ( j = 0; j < this.roots[i].nbr_alarms; j++ ) for ( j = 0; j < this.roots[i].nbr_alarms; j++ )
begin begin
new_alarm = new ( i, j, this.name ); new_alarm = new ( this.name );
this.alarms.collection.push_back ( new_alarm ); this.alarms.collection.push_back ( new_alarm );
end end
// initialise devices
this.devices.delete();
for ( i = 0; i < this.nbr_cpus; i++ )
for ( j = 0; j < this.roots[i].nbr_devs; j++ )
begin
new_dev.core = i;
new_dev.index = j;
new_dev.ch_en = 0;
this.devices.push_back ( new_dev );
end
// TODO remove hard-coded ADC init
adc_init ();
this.ready = 1;
end end
begin begin
while ( this.ready == 0 ) while ( i != this.nbr_cpus )
begin begin
mt.update ( ); mt.update ( );
# 1us; # 1us;
...@@ -202,6 +167,8 @@ class WrtdDrv; ...@@ -202,6 +167,8 @@ class WrtdDrv;
end end
join join
this.ready = 1;
endtask // init endtask // init
task msg_get_config ( int core, ref uint32_t data[] ); task msg_get_config ( int core, ref uint32_t data[] );
...@@ -293,16 +260,6 @@ class WrtdDrv; ...@@ -293,16 +260,6 @@ class WrtdDrv;
endtask // msg_writew endtask // msg_writew
task adc_init ( );
uint32_t addr;
uint32_t data[1];
addr = this.roots[0].devs_addr[0] + 'h4;
data[0] = 'h10f;
msg_writew ( 0, addr, 1, data );
endtask // adc_init
task add_rule ( string rep_cap_id ); task add_rule ( string rep_cap_id );
int idx; int idx;
idx = this.rules.add ( rep_cap_id ); idx = this.rules.add ( rep_cap_id );
...@@ -352,18 +309,50 @@ class WrtdDrv; ...@@ -352,18 +309,50 @@ class WrtdDrv;
$cast ( rule, this.rules.collection[idx] ); $cast ( rule, this.rules.collection[idx] );
hash = wrtd_gen_hash ( rule.get_src() ) % this.rules.collection.size(); hash = wrtd_gen_hash ( rule.get_src() ) % this.roots[core].nbr_rules;
core = rule.get_core ( ); core = rule.get_core ( );
addr = this.roots[core].rules_addr + hash * `WRTD_RULE_WORD_SIZE * 4; addr = this.roots[core].rules_addr + hash * `WRTD_RULE_WORD_SIZE * 4;
data = rule.data_pack ( ); data = rule.data_pack ( );
msg_writew ( core, addr, `WRTD_RULE_WORD_SIZE, data ); msg_writew ( core, addr, `WRTD_RULE_WORD_SIZE, data );
endtask // write_rule endtask // write_rule
function void map_local_channel_to_cpu ( string ch_id, int ch_dir,
ref int core, ref int ch_idx );
int i, j, k, idx_in, idx_out, dev_dir;
string dev_id;
idx_in = 1;
idx_out = 1;
core = -1;
ch_idx = -1;
for ( i = 0; i < this.nbr_cpus; i++ )
for ( j = 0; j < this.roots[i].nbr_devs; j++ )
begin
dev_dir = this.roots[i].channel_dir[j];
for ( k = 0; k < this.roots[i].nbr_channels[j]; k++ )
begin
if ( dev_dir == WRTD_DIR_INPUT )
dev_id = $sformatf ( "LC-I%0d", idx_in++ );
else
dev_id = $sformatf ( "LC-O%0d", idx_out++ );
if ( ( dev_dir == ch_dir ) && ( dev_id == ch_id ) )
begin
core = i;
ch_idx = k;
return;
end
end
end
endfunction // map_local_channel_to_cpu
task enable_rule ( string rep_cap_id ); task enable_rule ( string rep_cap_id );
int idx; int idx, src_cpu, dst_cpu, src_ch, dst_ch;
string id; string id;
uint32_t src_cpu;
WrtdRule rule; WrtdRule rule;
...@@ -374,22 +363,65 @@ class WrtdDrv; ...@@ -374,22 +363,65 @@ class WrtdDrv;
$cast ( rule, this.rules.collection[idx] ); $cast ( rule, this.rules.collection[idx] );
rule.set_enable ( ); /* Place the rule on the same CPU as the input source.
If source is network, src_cpu = -1 for now */
// TODO, replace hard-coding map_local_channel_to_cpu ( rule.get_src(), WRTD_DIR_INPUT, src_cpu, src_ch );
src_cpu = 0;
if ( this.free_rule_slots[src_cpu] == 0 ) // TODO: check if rule source is alarm
$error ( "no more available free rule slots on CPU %d", src_cpu );
this.free_rule_slots[src_cpu] -= 1; /* Set destination cpu and channel */
rule.set_dest_cpu ( `WRTD_DEST_CPU_LOCAL ); map_local_channel_to_cpu ( rule.get_dst(), WRTD_DIR_OUTPUT, dst_cpu, dst_ch );
id = rule.get_dst ( );
if ( id == "ADCO1" ) if ( dst_cpu >= 0 ) // local output device
rule.set_dest_ch ( 0 ); begin
else /* If source is network message and this cpu can receive from
rule.set_dest_ch ( `WRTD_DEST_CH_NET ); network, set cpu affinity to this cpu */
if ( ( src_cpu == -1 ) && ( this.roots[dst_cpu].capabilities & `WRTD_CAP_NET_RX ) )
src_cpu = dst_cpu;
/* Otherwise find the first cpu that is capable of net RX */
else
for ( src_cpu = 0; src_cpu < this.nbr_cpus; src_cpu++ )
if ( this.roots[src_cpu].capabilities & `WRTD_CAP_NET_RX )
break;
end
else // network destination
begin
dst_ch = `WRTD_DEST_CH_NET;
/* If source cpu can also send to
network, set dest cpu affinity to that cpu */
if ( ( src_cpu >= 0 ) && ( this.roots[src_cpu].capabilities & `WRTD_CAP_NET_TX ) )
dst_cpu = src_cpu;
/* Otherwise find the first cpu that is capable of net TX */
else
for ( dst_cpu = 0; dst_cpu < this.nbr_cpus; dst_cpu++ )
if ( this.roots[dst_cpu].capabilities & `WRTD_CAP_NET_TX )
break;
end
// TODO: handle network to network events
if ( ( src_cpu < 0 ) || ( dst_cpu < 0 ) ||
( src_cpu >= this.nbr_cpus ) || ( dst_cpu >= this.nbr_cpus ) )
$error ( "cannot determine source and/or destination cpu for rule" );
/* If the same CPU can handle both input and output, use special value so that
the firmware will know not to forward this event to another CPU (it does not
know its own index) */
if ( src_cpu == dst_cpu )
dst_cpu = `WRTD_DEST_CPU_LOCAL;
// TODO: handle free_rule_slots per cpu
rule.set_core ( src_cpu );
rule.set_dest_cpu ( dst_cpu );
rule.set_dest_ch ( dst_ch );
rule.set_enable ( 1 );
// TODO: properly recalculate and rewrite rules
write_rule ( idx ); write_rule ( idx );
endtask // enable_rule endtask // enable_rule
// TODO: properly support alarms
task add_alarm ( string rep_cap_id ); task add_alarm ( string rep_cap_id );
int idx; int idx;
idx = this.alarms.add ( rep_cap_id ); idx = this.alarms.add ( rep_cap_id );
...@@ -415,7 +447,7 @@ class WrtdDrv; ...@@ -415,7 +447,7 @@ class WrtdDrv;
$error ( "cannot write alarm with negative index" ); $error ( "cannot write alarm with negative index" );
core = this.alarms.collection[idx].get_core ( ); core = this.alarms.collection[idx].get_core ( );
index = this.alarms.collection[idx].get_index (); //index = this.alarms.collection[idx].get_index ();
addr = this.roots[core].alarms_addr + index * `WRTD_ALRM_WORD_SIZE * 4; addr = this.roots[core].alarms_addr + index * `WRTD_ALRM_WORD_SIZE * 4;
data = this.alarms.collection[idx].data_pack( ); data = this.alarms.collection[idx].data_pack( );
......
...@@ -31,12 +31,9 @@ virtual class WrtdRepCap; ...@@ -31,12 +31,9 @@ virtual class WrtdRepCap;
protected string name; protected string name;
protected WrtdId rep_cap_id; protected WrtdId rep_cap_id;
protected int core; protected int core;
protected int index;
protected int enabled; protected int enabled;
function new ( int core, int index, string name = "" ); function new ( string name = "" );
this.core = core;
this.index = index;
this.name = name; this.name = name;
this.rep_cap_id = new(); this.rep_cap_id = new();
clear(); clear();
...@@ -44,7 +41,7 @@ virtual class WrtdRepCap; ...@@ -44,7 +41,7 @@ virtual class WrtdRepCap;
function void clear ( ); function void clear ( );
this.rep_cap_id.clear(); this.rep_cap_id.clear();
this.enabled = 0; this.enabled = 0;
endfunction // clear endfunction // clear
task mdisplay ( string str ); task mdisplay ( string str );
...@@ -60,9 +57,9 @@ virtual class WrtdRepCap; ...@@ -60,9 +57,9 @@ virtual class WrtdRepCap;
return this.core; return this.core;
endfunction // get_core endfunction // get_core
function int get_index ( ); function void set_core ( int core );
return this.index; this.core = core;
endfunction // get_index endfunction // set_core
function string get_rep_cap_id ( ); function string get_rep_cap_id ( );
return this.rep_cap_id.get(); return this.rep_cap_id.get();
...@@ -84,8 +81,11 @@ virtual class WrtdRepCap; ...@@ -84,8 +81,11 @@ virtual class WrtdRepCap;
return ( this.enabled > 0 ); return ( this.enabled > 0 );
endfunction // is_enabled endfunction // is_enabled
function void set_enable ( ); function void set_enable ( int enable );
this.enabled = 1; if ( enable > 0)
this.enabled = 1;
else
this.enabled = 0;
endfunction // set_enable endfunction // set_enable
function void set_disable ( ); function void set_disable ( );
......
...@@ -53,8 +53,8 @@ class WrtdRule extends WrtdRepCap; ...@@ -53,8 +53,8 @@ class WrtdRule extends WrtdRepCap;
protected WrtdTstamp hold_off; protected WrtdTstamp hold_off;
protected uint32_t seq; protected uint32_t seq;
function new ( int core, int index, string name = "" ); function new ( string name = "" );
super.new ( core, index, name ); super.new ( name );
this.src = new(); this.src = new();
this.dst = new(); this.dst = new();
this.rx_last = new(); this.rx_last = new();
......
...@@ -69,7 +69,7 @@ module main; ...@@ -69,7 +69,7 @@ module main;
devA = new (accA, MT_BASE, MtIrqMonitorA, "DUT:A"); devA = new (accA, MT_BASE, MtIrqMonitorA, "DUT:A");
devA.init(); devA.init();
devA.add_rule ( "rule0" ); devA.add_rule ( "rule0" );
devA.set_rule ( "rule0", "ADCI5", "NET0", 0 ); devA.set_rule ( "rule0", "LC-I5", "NET0", 0 );
devA.enable_rule ( "rule0" ); devA.enable_rule ( "rule0" );
// Config DUTA to trigger on external trigger and get 64 samples // Config DUTA to trigger on external trigger and get 64 samples
...@@ -85,7 +85,8 @@ module main; ...@@ -85,7 +85,8 @@ module main;
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_SAT, 'h7fff); accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_SAT, 'h7fff);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_SAT, 'h7fff); accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_SAT, 'h7fff);
val = (1'b1 << `FMC_ADC_100MS_CSR_TRIG_EN_EXT_OFFSET); val = (1'b1 << `FMC_ADC_100MS_CSR_TRIG_EN_EXT_OFFSET);
val |= (1'b1 << `FMC_ADC_100MS_CSR_TRIG_EN_FWD_EXT_OFFSET);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_TRIG_EN, val); accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_TRIG_EN, val);
expected = 'h39; expected = 'h39;
...@@ -103,7 +104,7 @@ module main; ...@@ -103,7 +104,7 @@ module main;
devB = new (accB, MT_BASE, MtIrqMonitorB, "DUT:B"); devB = new (accB, MT_BASE, MtIrqMonitorB, "DUT:B");
devB.init(); devB.init();
devB.add_rule ( "rule0" ); devB.add_rule ( "rule0" );
devB.set_rule ( "rule0", "NET0", "ADCO1", 50000 ); devB.set_rule ( "rule0", "NET0", "LC-O1", 50000 );
devB.enable_rule ( "rule0" ); devB.enable_rule ( "rule0" );
// Config DUTB to trigger on WRTD and get 64 samples // Config DUTB to trigger on WRTD and get 64 samples
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
`timescale 1ns/1ps `timescale 1ns/1ps
`include "vhd_wishbone_master.svh" `include "vhd_wishbone_master.svh"
`include "simdrv_defs.svh"
module simple_tdc_driver module simple_tdc_driver
( (
...@@ -78,7 +77,7 @@ module simple_tdc_driver ...@@ -78,7 +77,7 @@ module simple_tdc_driver
now = $time; now = $time;
if (t.ts <= now) if (t.ts <= now)
$display("TDC: pulse in the past (%t now=%t)!", t.ts, now); $display("[DUT] <%t> TDC: pulse in the past (%t now=%t)!", $realtime, t.ts, now);
else else
begin begin
const int fifo_n = t.channel / 4; const int fifo_n = t.channel / 4;
...@@ -91,8 +90,8 @@ module simple_tdc_driver ...@@ -91,8 +90,8 @@ module simple_tdc_driver
val[17] = 1'b1; val[17] = 1'b1;
val[16:0] = (t.ts - start_time) / 81ps; val[16:0] = (t.ts - start_time) / 81ps;
$display("TDC: pulse at %t for channel %0d (start #0x%x, time_data 0x%x, start_time %t)", $display("[DUT] <%t> TDC: pulse at %t for channel %0d (start #0x%x, time_data 0x%x, start_time %t)",
t.ts, t.channel, start, val[16:0], start_time); $realtime, t.ts, t.channel, start, val[16:0], start_time);
fifos[t.channel / 4].push_back(val); fifos[t.channel / 4].push_back(val);
end end
...@@ -137,7 +136,7 @@ module simple_tdc_driver ...@@ -137,7 +136,7 @@ module simple_tdc_driver
rdata <= start01; rdata <= start01;
end end
else begin else begin
$display("invalid ACAM read 0x%x", addr); $display("[DUT] <%t> invalid ACAM read 0x%x", $realtime, addr);
end end
end end
end end
...@@ -146,8 +145,9 @@ module simple_tdc_driver ...@@ -146,8 +145,9 @@ module simple_tdc_driver
assign ef2 = fifos[1].size() == 0; assign ef2 = fifos[1].size() == 0;
always@(negedge wr) begin always@(negedge wr) begin
// Unused in simulation mode. /* Not supposed to have writes to the ACAM if
$display("invalid ACAM write 0x%x <- 0x%08x", addr, data); firmware is compiled with -DSIMULATION */
$display("[DUT] <%t> invalid ACAM write 0x%x <- 0x%08x", $realtime, addr, data);
end end
endmodule // simple_tdc_driver endmodule // simple_tdc_driver
...@@ -212,11 +212,11 @@ endmodule // simple_fdelay_mon ...@@ -212,11 +212,11 @@ endmodule // simple_fdelay_mon
module dut_env module dut_env
( (
IVHDWishboneMaster host, IVHDWishboneMaster host,
output sfp_txp_o, sfp_txn_o, output clk_sys, rst_sys_n,
sfp_txp_o, sfp_txn_o,
input sfp_rxp_i, sfp_rxn_i input sfp_rxp_i, sfp_rxn_i
); );
reg clk_125m_pll = 0; reg clk_125m_pll = 0;
reg clk_125m_gtp = 0; reg clk_125m_gtp = 0;
reg clk_20m_vcxo = 0; reg clk_20m_vcxo = 0;
...@@ -240,6 +240,9 @@ module dut_env ...@@ -240,6 +240,9 @@ module dut_env
wire sfp_scl, sfp_sda, sfp_sda_en; wire sfp_scl, sfp_sda, sfp_sda_en;
assign clk_sys = DUT.clk_sys_62m5;
assign rst_sys_n = DUT.rst_sys_62m5_n;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// The DUT // The DUT
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
...@@ -248,13 +251,12 @@ module dut_env ...@@ -248,13 +251,12 @@ module dut_env
( (
.g_SIMULATION (1), .g_SIMULATION (1),
.g_SIM_BYPASS_VME (1), .g_SIM_BYPASS_VME (1),
.g_WRPC_INITF ("../../../dependencies/wr-cores/bin/wrpc/wrc_phy8_sim.bram"), .g_WRPC_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 ("../../../software/firmware/fd/wrtd-rt-fd.bram")
) )
DUT DUT
( (
.rst_n_i (1'b1), .rst_n_i (1'b1),
.vme_sysreset_n_i (1'b1),
.clk_125m_pllref_p_i (clk_125m_pll), .clk_125m_pllref_p_i (clk_125m_pll),
.clk_125m_pllref_n_i (~clk_125m_pll), .clk_125m_pllref_n_i (~clk_125m_pll),
.clk_125m_gtp_p_i (clk_125m_gtp), .clk_125m_gtp_p_i (clk_125m_gtp),
...@@ -367,10 +369,9 @@ module dut_env ...@@ -367,10 +369,9 @@ module dut_env
push_pulse(1, start + 30us); push_pulse(1, start + 30us);
push_pulse(2, start + 50us); push_pulse(2, start + 50us);
#(start + 200us) ; #(start + 1000us) ;
// Should have been finished by the FD monitor. // Should have been finished by the FD monitor.
$fatal(1, "FAILED"); $fatal(1, "FAILED");
end end
initial begin initial begin
......
//
// unit name: ListDriver
//
// description: A SystemVerilog Class to provide an abstraction of a complete
// LIST 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 __LIST_DRIVER_INCLUDED
`define __LIST_DRIVER_INCLUDED
`include "mock_turtle_driver.svh"
`define LIST_HMQ_LOG_SLOT 0
typedef struct {
uint32_t system;
uint32_t source_port;
uint32_t trigger;
} list_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
} list_log_miss_reason;
typedef enum {
RAW = (1 << 0),
SENT = (1 << 1),
PROMISC = (1 << 2),
FILTERED = (1 << 3),
EXECUTED = (1 << 4),
MISSED = (1 << 5)
} list_log_type;
typedef enum {
LIST_IN = 2,
LIST_OUT = 6
} list_log_origin;
class ListLogMsg;
list_log_origin origin;
list_log_type ltype;
uint32_t seq;
int channel;
list_trig_id id;
wr_timestamp ts;
list_log_miss_reason miss_reason;
function new ( MQueueMsg msg );
this.origin = list_log_origin'(msg.header.msg_id);
this.ltype = list_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 = list_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: %10dns" },
origin.name(), ltype.name(), seq, channel,
id.system, id.source_port, id.trigger,
ts.seconds, ts.ticks * 8);
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 // ListLogMsg
class ListDriver;
protected string name;
protected int hmq_log_slot;
protected MockTurtleDriver mt;
function new ( CBusAccessor 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 ( string cpu0_fw = "",
string cpu1_fw = "");
mt.init ( );
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 );
ListLogMsg log_msg;
MQueueMsg msg;
msg = new ( core, `LIST_HMQ_LOG_SLOT );
while ( mt.hmq_pending_messages ( core, `LIST_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 // ListDriver
`endif // `ifndef __LIST_DRIVER_INCLUDED
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
// //
// unit name: main // unit name: main
// //
// description: Testbench for the SPEC150T-based FMC ADC WRTD reference design. // description: Testbench for the SVEC-based FMC TDC+FD WRTD reference design.
// //
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Copyright CERN 2018-2019 // Copyright CERN 2018-2019
...@@ -27,50 +27,75 @@ ...@@ -27,50 +27,75 @@
`include "wrtd_driver.svh" `include "wrtd_driver.svh"
`include "vhd_wishbone_master.svh" `include "vhd_wishbone_master.svh"
`define TDC_DIRECT_BASE 'h18000
module main; module main;
wire clk_sys, rst_sys_n;
wire sfp_txp, sfp_txn, sfp_rxp, sfp_rxn; wire sfp_txp, sfp_txn, sfp_rxp, sfp_rxn;
IVHDWishboneMaster host (DUT.DUT.clk_sys_62m5, DUT.DUT.rst_sys_62m5_n); IVHDWishboneMaster host (clk_sys, rst_sys_n);
dut_env DUT (host, sfp_txp, sfp_txn, sfp_rxp, sfp_rxn); dut_env DUT (host, clk_sys, rst_sys_n, sfp_txp, sfp_txn, sfp_rxp, sfp_rxn);
IMockTurtleIRQ MtIrqMonitor (`MT_ATTACH_IRQ(DUT.DUT.cmp_mock_turtle)); IMockTurtleIRQ MtIrqMonitor (`MT_ATTACH_IRQ(DUT.DUT.cmp_mock_turtle));
assign sfp_rxp = sfp_txp; assign sfp_rxp = sfp_txp;
assign sfp_rxn = sfp_txn; assign sfp_rxn = sfp_txn;
CBusAccessor acc;
WrtdDrv dev; WrtdDrv dev;
const uint64_t MT_BASE = 'h0002_0000; const uint64_t MT_BASE = 'h0002_0000;
CBusAccessor acc;
initial begin initial begin
$timeformat (-6, 3, "us", 10); $timeformat (-6, 3, "us", 10);
@(posedge DUT.DUT.rst_sys_62m5_n); #10us;
@(posedge DUT.DUT.clk_sys_62m5);
acc = host.get_accessor(); acc = host.get_accessor();
acc.set_default_xfer_size(4); acc.set_default_xfer_size(4);
dev = new (acc, MT_BASE, MtIrqMonitor, "DUT"); dev = new (acc, MT_BASE, MtIrqMonitor, "DUT");
dev.init(); dev.init();
dev.add_rule ( "rule0" ); dev.add_rule ( "rule0" );
dev.set_rule ( "rule0", "NET0", "FD", 100000 ); dev.set_rule ( "rule0", "NET0", "LC-O1", 150000 );
dev.enable_rule ( "rule0" ); dev.enable_rule ( "rule0" );
dev.add_rule ( "rule1" ); dev.add_rule ( "rule1" );
dev.set_rule ( "rule1", "TDC", "NET0", 0 ); dev.set_rule ( "rule1", "NET1", "LC-O2", 150000 );
dev.enable_rule ( "rule1" ); dev.enable_rule ( "rule1" );
dev.add_rule ( "rule2" );
dev.set_rule ( "rule2", "NET2", "LC-O3", 150000 );
dev.enable_rule ( "rule2" );
dev.add_rule ( "rule3" );
dev.set_rule ( "rule3", "LC-I1", "NET0", 0 );
dev.enable_rule ( "rule3" );
dev.add_rule ( "rule4" );
dev.set_rule ( "rule4", "LC-I2", "NET1", 0 );
dev.enable_rule ( "rule4" );
dev.add_rule ( "rule5" );
dev.set_rule ( "rule5", "LC-I3", "NET2", 0 );
dev.enable_rule ( "rule5" );
// Set dead-time
acc.write(`TDC_DIRECT_BASE + 'h4, 'h40);
// Enable channels
acc.write(`TDC_DIRECT_BASE + 'h0, 'h1f);
end
initial begin
forever begin forever begin
if ( ( dev != null ) && ( dev.ready ) ) if ( ( dev != null ) && ( dev.ready ) )
dev.update (); dev.update ();
#1us; #1us;
end end
end end
endmodule // main endmodule // main
vsim -quiet -t 10fs -L unisim work.main vsim -quiet -t 10fs -L unisim work.main -suppress 1270,8617,8683,8684,8822
set StdArithNoWarnings 1 set StdArithNoWarnings 1
set NumericStdNoWarnings 1 set NumericStdNoWarnings 1
......
# Modelsim run script for continuous integration # Modelsim run script for continuous integration
# execute: vsim -c -do "run_ci.do" # execute: vsim -c -do "run_ci.do"
vsim -quiet -t 10fs -L unisim work.main vsim -quiet -t 10fs -L unisim work.main -suppress 1270,8617,8683,8684,8822
set StdArithNoWarnings 1 set StdArithNoWarnings 1
set NumericStdNoWarnings 1 set NumericStdNoWarnings 1
......
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