diff --git a/sim/L1_rtps_writer_test1_tbkdp.do b/sim/L1_rtps_writer_test1_tbkdp.do new file mode 100644 index 0000000..b346c88 --- /dev/null +++ b/sim/L1_rtps_writer_test1_tbkdp.do @@ -0,0 +1,98 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -divider SYSTEM +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/clk +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/reset +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_tbkdp/uut/time +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_tbkdp/uut/check_time +add wave -noupdate -divider INPUT +add wave -noupdate -group META /l1_rtps_writer_test1_tbkdp/uut/empty_meta +add wave -noupdate -group META /l1_rtps_writer_test1_tbkdp/uut/rd_meta +add wave -noupdate -group META /l1_rtps_writer_test1_tbkdp/uut/last_word_in_meta +add wave -noupdate -group META -radix hexadecimal /l1_rtps_writer_test1_tbkdp/uut/data_in_meta +add wave -noupdate -group USER /l1_rtps_writer_test1_tbkdp/uut/empty_user +add wave -noupdate -group USER /l1_rtps_writer_test1_tbkdp/uut/rd_user +add wave -noupdate -group USER -radix hexadecimal /l1_rtps_writer_test1_tbkdp/uut/data_in_user +add wave -noupdate -group USER /l1_rtps_writer_test1_tbkdp/uut/last_word_in_user +add wave -noupdate -divider HC +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/data_available +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/start_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/opcode_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/ack_hc +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_tbkdp/uut/seq_nr_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/done_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/ret_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/get_data_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_tbkdp/uut/data_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/valid_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/ready_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/last_word_in_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_tbkdp/uut/cc_instance_handle +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_tbkdp/uut/cc_kind +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_tbkdp/uut/cc_source_timestamp +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_tbkdp/uut/cc_seq_nr +add wave -noupdate -divider OUTPUT +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/full_rtps +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/wr_rtps +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_tbkdp/uut/data_out_rtps +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/last_word_out_rtps +add wave -noupdate /l1_rtps_writer_test1_tbkdp/rtps_out_inst/wr +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_tbkdp/rtps_out_inst/data_out +add wave -noupdate -divider {MAIN FSM} +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/stage +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/stage_next +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/cnt +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_tbkdp/uut/last_seq_nr +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_tbkdp/uut/global_ack_seq_nr_base +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_tbkdp/uut/next_seq_nr +add wave -noupdate -divider {MEMORY FSM} +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/mem_op_done +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/mem_op_start +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/mem_opcode +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/mem_stage +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/mem_stage_next +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/mem_cnt +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/mem_pos +add wave -noupdate -radix unsigned -childformat {{/l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(6) -radix unsigned} {/l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(5) -radix unsigned} {/l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(4) -radix unsigned} {/l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(3) -radix unsigned} {/l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(2) -radix unsigned} {/l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(1) -radix unsigned} {/l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(0) -radix unsigned}} -subitemconfig {/l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(6) {-height 15 -radix unsigned} /l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(5) {-height 15 -radix unsigned} /l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(4) {-height 15 -radix unsigned} /l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(3) {-height 15 -radix unsigned} /l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(2) {-height 15 -radix unsigned} /l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(1) {-height 15 -radix unsigned} /l1_rtps_writer_test1_tbkdp/uut/mem_addr_base(0) {-height 15 -radix unsigned}} /l1_rtps_writer_test1_tbkdp/uut/mem_addr_base +add wave -noupdate -childformat {{/l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.guid -radix hexadecimal} {/l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.addr -radix hexadecimal} {/l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.portn -radix hexadecimal} {/l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.lease_deadline -radix hexadecimal} {/l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.res_time -radix unsigned} {/l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.ack_seq_nr_base -radix unsigned} {/l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.req_seq_nr_base -radix unsigned}} -expand -subitemconfig {/l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.guid {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.addr {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.portn {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.lease_deadline {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.res_time {-height 15 -radix unsigned} /l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.ack_seq_nr_base {-height 15 -radix unsigned} /l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data.req_seq_nr_base {-height 15 -radix unsigned}} /l1_rtps_writer_test1_tbkdp/uut/mem_endpoint_data +add wave -noupdate -group MEM_CTRL -radix unsigned /l1_rtps_writer_test1_tbkdp/uut/mem_addr +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_tbkdp/uut/mem_valid_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_tbkdp/uut/mem_ready_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_tbkdp/uut/mem_read +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_tbkdp/uut/mem_write_data +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_tbkdp/uut/abort_read +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_tbkdp/uut/mem_valid_out +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_tbkdp/uut/mem_ready_out +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_tbkdp/uut/mem_read_data +add wave -noupdate -divider TESTBENCH +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_tbkdp/start_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_tbkdp/packet_sent_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_tbkdp/start_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_tbkdp/packet_sent_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_tbkdp/stage_hc +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_tbkdp/out_check_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_tbkdp/stim_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_tbkdp/test_done +add wave -noupdate -divider MISC +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/req_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/req_seq_nr_bitmap +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/nack_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_tbkdp/uut/bitmap_latch +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {Begin {49575000 ps} 1} {Error {7325000 ps} 1} {Cursor {62689107 ps} 0} +quietly wave cursor active 3 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 135 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {61771800 ps} {62773704 ps} diff --git a/sim/L1_rtps_writer_test1_trkdp.do b/sim/L1_rtps_writer_test1_trkdp.do new file mode 100644 index 0000000..0a8f2bd --- /dev/null +++ b/sim/L1_rtps_writer_test1_trkdp.do @@ -0,0 +1,98 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -divider SYSTEM +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/clk +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/reset +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_trkdp/uut/time +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_trkdp/uut/check_time +add wave -noupdate -divider INPUT +add wave -noupdate -group META /l1_rtps_writer_test1_trkdp/uut/empty_meta +add wave -noupdate -group META /l1_rtps_writer_test1_trkdp/uut/rd_meta +add wave -noupdate -group META /l1_rtps_writer_test1_trkdp/uut/last_word_in_meta +add wave -noupdate -group META -radix hexadecimal /l1_rtps_writer_test1_trkdp/uut/data_in_meta +add wave -noupdate -group USER /l1_rtps_writer_test1_trkdp/uut/empty_user +add wave -noupdate -group USER /l1_rtps_writer_test1_trkdp/uut/rd_user +add wave -noupdate -group USER -radix hexadecimal /l1_rtps_writer_test1_trkdp/uut/data_in_user +add wave -noupdate -group USER /l1_rtps_writer_test1_trkdp/uut/last_word_in_user +add wave -noupdate -divider HC +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/data_available +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/start_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/opcode_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/ack_hc +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_trkdp/uut/seq_nr_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/done_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/ret_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/get_data_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_trkdp/uut/data_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/valid_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/ready_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/last_word_in_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_trkdp/uut/cc_instance_handle +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_trkdp/uut/cc_kind +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_trkdp/uut/cc_source_timestamp +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_trkdp/uut/cc_seq_nr +add wave -noupdate -divider OUTPUT +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/full_rtps +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/wr_rtps +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_trkdp/uut/data_out_rtps +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/last_word_out_rtps +add wave -noupdate /l1_rtps_writer_test1_trkdp/rtps_out_inst/wr +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_trkdp/rtps_out_inst/data_out +add wave -noupdate -divider {MAIN FSM} +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/stage +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/stage_next +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/cnt +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_trkdp/uut/last_seq_nr +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_trkdp/uut/global_ack_seq_nr_base +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_trkdp/uut/next_seq_nr +add wave -noupdate -divider {MEMORY FSM} +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/mem_op_done +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/mem_op_start +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/mem_opcode +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/mem_stage +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/mem_stage_next +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/mem_cnt +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/mem_pos +add wave -noupdate -radix unsigned -childformat {{/l1_rtps_writer_test1_trkdp/uut/mem_addr_base(6) -radix unsigned} {/l1_rtps_writer_test1_trkdp/uut/mem_addr_base(5) -radix unsigned} {/l1_rtps_writer_test1_trkdp/uut/mem_addr_base(4) -radix unsigned} {/l1_rtps_writer_test1_trkdp/uut/mem_addr_base(3) -radix unsigned} {/l1_rtps_writer_test1_trkdp/uut/mem_addr_base(2) -radix unsigned} {/l1_rtps_writer_test1_trkdp/uut/mem_addr_base(1) -radix unsigned} {/l1_rtps_writer_test1_trkdp/uut/mem_addr_base(0) -radix unsigned}} -subitemconfig {/l1_rtps_writer_test1_trkdp/uut/mem_addr_base(6) {-height 15 -radix unsigned} /l1_rtps_writer_test1_trkdp/uut/mem_addr_base(5) {-height 15 -radix unsigned} /l1_rtps_writer_test1_trkdp/uut/mem_addr_base(4) {-height 15 -radix unsigned} /l1_rtps_writer_test1_trkdp/uut/mem_addr_base(3) {-height 15 -radix unsigned} /l1_rtps_writer_test1_trkdp/uut/mem_addr_base(2) {-height 15 -radix unsigned} /l1_rtps_writer_test1_trkdp/uut/mem_addr_base(1) {-height 15 -radix unsigned} /l1_rtps_writer_test1_trkdp/uut/mem_addr_base(0) {-height 15 -radix unsigned}} /l1_rtps_writer_test1_trkdp/uut/mem_addr_base +add wave -noupdate -childformat {{/l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.guid -radix hexadecimal} {/l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.addr -radix hexadecimal} {/l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.portn -radix hexadecimal} {/l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.lease_deadline -radix hexadecimal} {/l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.res_time -radix unsigned} {/l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.ack_seq_nr_base -radix unsigned} {/l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.req_seq_nr_base -radix unsigned}} -expand -subitemconfig {/l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.guid {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.addr {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.portn {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.lease_deadline {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.res_time {-height 15 -radix unsigned} /l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.ack_seq_nr_base {-height 15 -radix unsigned} /l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data.req_seq_nr_base {-height 15 -radix unsigned}} /l1_rtps_writer_test1_trkdp/uut/mem_endpoint_data +add wave -noupdate -group MEM_CTRL -radix unsigned /l1_rtps_writer_test1_trkdp/uut/mem_addr +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_trkdp/uut/mem_valid_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_trkdp/uut/mem_ready_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_trkdp/uut/mem_read +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_trkdp/uut/mem_write_data +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_trkdp/uut/abort_read +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_trkdp/uut/mem_valid_out +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_trkdp/uut/mem_ready_out +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_trkdp/uut/mem_read_data +add wave -noupdate -divider TESTBENCH +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_trkdp/start_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_trkdp/packet_sent_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_trkdp/start_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_trkdp/packet_sent_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_trkdp/stage_hc +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_trkdp/out_check_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_trkdp/stim_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_trkdp/test_done +add wave -noupdate -divider MISC +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/req_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/req_seq_nr_bitmap +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/nack_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_trkdp/uut/bitmap_latch +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {Begin {49575000 ps} 1} {Error {7325000 ps} 1} {Cursor {62689107 ps} 0} +quietly wave cursor active 3 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 135 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {61771800 ps} {62773704 ps} diff --git a/sim/L1_rtps_writer_test1_vbkdp.do b/sim/L1_rtps_writer_test1_vbkdp.do new file mode 100644 index 0000000..a1f937e --- /dev/null +++ b/sim/L1_rtps_writer_test1_vbkdp.do @@ -0,0 +1,98 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -divider SYSTEM +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/clk +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/reset +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vbkdp/uut/time +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vbkdp/uut/check_time +add wave -noupdate -divider INPUT +add wave -noupdate -group META /l1_rtps_writer_test1_vbkdp/uut/empty_meta +add wave -noupdate -group META /l1_rtps_writer_test1_vbkdp/uut/rd_meta +add wave -noupdate -group META /l1_rtps_writer_test1_vbkdp/uut/last_word_in_meta +add wave -noupdate -group META -radix hexadecimal /l1_rtps_writer_test1_vbkdp/uut/data_in_meta +add wave -noupdate -group USER /l1_rtps_writer_test1_vbkdp/uut/empty_user +add wave -noupdate -group USER /l1_rtps_writer_test1_vbkdp/uut/rd_user +add wave -noupdate -group USER -radix hexadecimal /l1_rtps_writer_test1_vbkdp/uut/data_in_user +add wave -noupdate -group USER /l1_rtps_writer_test1_vbkdp/uut/last_word_in_user +add wave -noupdate -divider HC +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/data_available +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/start_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/opcode_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/ack_hc +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vbkdp/uut/seq_nr_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/done_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/ret_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/get_data_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_vbkdp/uut/data_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/valid_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/ready_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/last_word_in_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_vbkdp/uut/cc_instance_handle +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vbkdp/uut/cc_kind +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vbkdp/uut/cc_source_timestamp +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vbkdp/uut/cc_seq_nr +add wave -noupdate -divider OUTPUT +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/full_rtps +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/wr_rtps +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_vbkdp/uut/data_out_rtps +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/last_word_out_rtps +add wave -noupdate /l1_rtps_writer_test1_vbkdp/rtps_out_inst/wr +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_vbkdp/rtps_out_inst/data_out +add wave -noupdate -divider {MAIN FSM} +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/stage +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/stage_next +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/cnt +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vbkdp/uut/last_seq_nr +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vbkdp/uut/global_ack_seq_nr_base +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vbkdp/uut/next_seq_nr +add wave -noupdate -divider {MEMORY FSM} +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/mem_op_done +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/mem_op_start +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/mem_opcode +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/mem_stage +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/mem_stage_next +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/mem_cnt +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/mem_pos +add wave -noupdate -radix unsigned -childformat {{/l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(6) -radix unsigned} {/l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(5) -radix unsigned} {/l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(4) -radix unsigned} {/l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(3) -radix unsigned} {/l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(2) -radix unsigned} {/l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(1) -radix unsigned} {/l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(0) -radix unsigned}} -subitemconfig {/l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(6) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(5) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(4) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(3) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(2) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(1) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vbkdp/uut/mem_addr_base(0) {-height 15 -radix unsigned}} /l1_rtps_writer_test1_vbkdp/uut/mem_addr_base +add wave -noupdate -childformat {{/l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.guid -radix hexadecimal} {/l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.addr -radix hexadecimal} {/l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.portn -radix hexadecimal} {/l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.lease_deadline -radix hexadecimal} {/l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.res_time -radix unsigned} {/l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.ack_seq_nr_base -radix unsigned} {/l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.req_seq_nr_base -radix unsigned}} -expand -subitemconfig {/l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.guid {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.addr {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.portn {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.lease_deadline {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.res_time {-height 15 -radix unsigned} /l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.ack_seq_nr_base {-height 15 -radix unsigned} /l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data.req_seq_nr_base {-height 15 -radix unsigned}} /l1_rtps_writer_test1_vbkdp/uut/mem_endpoint_data +add wave -noupdate -group MEM_CTRL -radix unsigned /l1_rtps_writer_test1_vbkdp/uut/mem_addr +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vbkdp/uut/mem_valid_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vbkdp/uut/mem_ready_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vbkdp/uut/mem_read +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_vbkdp/uut/mem_write_data +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vbkdp/uut/abort_read +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vbkdp/uut/mem_valid_out +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vbkdp/uut/mem_ready_out +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_vbkdp/uut/mem_read_data +add wave -noupdate -divider TESTBENCH +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vbkdp/start_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vbkdp/packet_sent_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vbkdp/start_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vbkdp/packet_sent_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vbkdp/stage_hc +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vbkdp/out_check_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vbkdp/stim_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vbkdp/test_done +add wave -noupdate -divider MISC +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/req_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/req_seq_nr_bitmap +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/nack_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_vbkdp/uut/bitmap_latch +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {Begin {49575000 ps} 1} {Error {7325000 ps} 1} {Cursor {62689107 ps} 0} +quietly wave cursor active 3 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 135 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {61771800 ps} {62773704 ps} diff --git a/sim/L1_rtps_writer_test1_vrkdn.do b/sim/L1_rtps_writer_test1_vrkdn.do new file mode 100644 index 0000000..389e6dd --- /dev/null +++ b/sim/L1_rtps_writer_test1_vrkdn.do @@ -0,0 +1,98 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -divider SYSTEM +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/clk +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/reset +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdn/uut/time +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdn/uut/check_time +add wave -noupdate -divider INPUT +add wave -noupdate -group META /l1_rtps_writer_test1_vrkdn/uut/empty_meta +add wave -noupdate -group META /l1_rtps_writer_test1_vrkdn/uut/rd_meta +add wave -noupdate -group META /l1_rtps_writer_test1_vrkdn/uut/last_word_in_meta +add wave -noupdate -group META -radix hexadecimal /l1_rtps_writer_test1_vrkdn/uut/data_in_meta +add wave -noupdate -group USER /l1_rtps_writer_test1_vrkdn/uut/empty_user +add wave -noupdate -group USER /l1_rtps_writer_test1_vrkdn/uut/rd_user +add wave -noupdate -group USER -radix hexadecimal /l1_rtps_writer_test1_vrkdn/uut/data_in_user +add wave -noupdate -group USER /l1_rtps_writer_test1_vrkdn/uut/last_word_in_user +add wave -noupdate -divider HC +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/data_available +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/start_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/opcode_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/ack_hc +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vrkdn/uut/seq_nr_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/done_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/ret_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/get_data_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_vrkdn/uut/data_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/valid_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/ready_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/last_word_in_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_vrkdn/uut/cc_instance_handle +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdn/uut/cc_kind +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vrkdn/uut/cc_source_timestamp +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vrkdn/uut/cc_seq_nr +add wave -noupdate -divider OUTPUT +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/full_rtps +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/wr_rtps +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_vrkdn/uut/data_out_rtps +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/last_word_out_rtps +add wave -noupdate /l1_rtps_writer_test1_vrkdn/rtps_out_inst/wr +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_vrkdn/rtps_out_inst/data_out +add wave -noupdate -divider {MAIN FSM} +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/stage +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/stage_next +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/cnt +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdn/uut/last_seq_nr +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdn/uut/global_ack_seq_nr_base +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdn/uut/next_seq_nr +add wave -noupdate -divider {MEMORY FSM} +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/mem_op_done +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/mem_op_start +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/mem_opcode +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/mem_stage +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/mem_stage_next +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/mem_cnt +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/mem_pos +add wave -noupdate -radix unsigned -childformat {{/l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(6) -radix unsigned} {/l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(5) -radix unsigned} {/l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(4) -radix unsigned} {/l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(3) -radix unsigned} {/l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(2) -radix unsigned} {/l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(1) -radix unsigned} {/l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(0) -radix unsigned}} -subitemconfig {/l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(6) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(5) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(4) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(3) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(2) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(1) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdn/uut/mem_addr_base(0) {-height 15 -radix unsigned}} /l1_rtps_writer_test1_vrkdn/uut/mem_addr_base +add wave -noupdate -childformat {{/l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.guid -radix hexadecimal} {/l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.addr -radix hexadecimal} {/l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.portn -radix hexadecimal} {/l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.lease_deadline -radix hexadecimal} {/l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.res_time -radix unsigned} {/l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.ack_seq_nr_base -radix unsigned} {/l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.req_seq_nr_base -radix unsigned}} -expand -subitemconfig {/l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.guid {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.addr {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.portn {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.lease_deadline {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.res_time {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.ack_seq_nr_base {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data.req_seq_nr_base {-height 15 -radix unsigned}} /l1_rtps_writer_test1_vrkdn/uut/mem_endpoint_data +add wave -noupdate -group MEM_CTRL -radix unsigned /l1_rtps_writer_test1_vrkdn/uut/mem_addr +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdn/uut/mem_valid_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdn/uut/mem_ready_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdn/uut/mem_read +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_vrkdn/uut/mem_write_data +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdn/uut/abort_read +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdn/uut/mem_valid_out +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdn/uut/mem_ready_out +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_vrkdn/uut/mem_read_data +add wave -noupdate -divider TESTBENCH +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdn/start_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdn/packet_sent_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdn/start_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdn/packet_sent_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdn/stage_hc +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdn/out_check_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdn/stim_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdn/test_done +add wave -noupdate -divider MISC +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/req_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/req_seq_nr_bitmap +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/nack_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_vrkdn/uut/bitmap_latch +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {Begin {49575000 ps} 1} {Error {7325000 ps} 1} {Cursor {62689107 ps} 0} +quietly wave cursor active 3 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 135 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {61771800 ps} {62773704 ps} diff --git a/sim/L1_rtps_writer_test1_vrkdp.do b/sim/L1_rtps_writer_test1_vrkdp.do new file mode 100644 index 0000000..555b601 --- /dev/null +++ b/sim/L1_rtps_writer_test1_vrkdp.do @@ -0,0 +1,98 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -divider SYSTEM +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/clk +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/reset +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdp/uut/time +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdp/uut/check_time +add wave -noupdate -divider INPUT +add wave -noupdate -group META /l1_rtps_writer_test1_vrkdp/uut/empty_meta +add wave -noupdate -group META /l1_rtps_writer_test1_vrkdp/uut/rd_meta +add wave -noupdate -group META /l1_rtps_writer_test1_vrkdp/uut/last_word_in_meta +add wave -noupdate -group META -radix hexadecimal /l1_rtps_writer_test1_vrkdp/uut/data_in_meta +add wave -noupdate -group USER /l1_rtps_writer_test1_vrkdp/uut/empty_user +add wave -noupdate -group USER /l1_rtps_writer_test1_vrkdp/uut/rd_user +add wave -noupdate -group USER -radix hexadecimal /l1_rtps_writer_test1_vrkdp/uut/data_in_user +add wave -noupdate -group USER /l1_rtps_writer_test1_vrkdp/uut/last_word_in_user +add wave -noupdate -divider HC +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/data_available +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/start_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/opcode_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/ack_hc +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vrkdp/uut/seq_nr_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/done_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/ret_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/get_data_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_vrkdp/uut/data_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/valid_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/ready_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/last_word_in_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_vrkdp/uut/cc_instance_handle +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrkdp/uut/cc_kind +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vrkdp/uut/cc_source_timestamp +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vrkdp/uut/cc_seq_nr +add wave -noupdate -divider OUTPUT +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/full_rtps +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/wr_rtps +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_vrkdp/uut/data_out_rtps +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/last_word_out_rtps +add wave -noupdate /l1_rtps_writer_test1_vrkdp/rtps_out_inst/wr +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_vrkdp/rtps_out_inst/data_out +add wave -noupdate -divider {MAIN FSM} +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/stage +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/stage_next +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/cnt +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdp/uut/last_seq_nr +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdp/uut/global_ack_seq_nr_base +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrkdp/uut/next_seq_nr +add wave -noupdate -divider {MEMORY FSM} +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/mem_op_done +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/mem_op_start +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/mem_opcode +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/mem_stage +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/mem_stage_next +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/mem_cnt +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/mem_pos +add wave -noupdate -radix unsigned -childformat {{/l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(6) -radix unsigned} {/l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(5) -radix unsigned} {/l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(4) -radix unsigned} {/l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(3) -radix unsigned} {/l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(2) -radix unsigned} {/l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(1) -radix unsigned} {/l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(0) -radix unsigned}} -subitemconfig {/l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(6) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(5) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(4) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(3) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(2) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(1) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdp/uut/mem_addr_base(0) {-height 15 -radix unsigned}} /l1_rtps_writer_test1_vrkdp/uut/mem_addr_base +add wave -noupdate -childformat {{/l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.guid -radix hexadecimal} {/l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.addr -radix hexadecimal} {/l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.portn -radix hexadecimal} {/l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.lease_deadline -radix hexadecimal} {/l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.res_time -radix unsigned} {/l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.ack_seq_nr_base -radix unsigned} {/l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.req_seq_nr_base -radix unsigned}} -expand -subitemconfig {/l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.guid {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.addr {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.portn {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.lease_deadline {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.res_time {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.ack_seq_nr_base {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data.req_seq_nr_base {-height 15 -radix unsigned}} /l1_rtps_writer_test1_vrkdp/uut/mem_endpoint_data +add wave -noupdate -group MEM_CTRL -radix unsigned /l1_rtps_writer_test1_vrkdp/uut/mem_addr +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdp/uut/mem_valid_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdp/uut/mem_ready_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdp/uut/mem_read +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_vrkdp/uut/mem_write_data +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdp/uut/abort_read +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdp/uut/mem_valid_out +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrkdp/uut/mem_ready_out +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_vrkdp/uut/mem_read_data +add wave -noupdate -divider TESTBENCH +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdp/start_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdp/packet_sent_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdp/start_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdp/packet_sent_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdp/stage_hc +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdp/out_check_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdp/stim_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrkdp/test_done +add wave -noupdate -divider MISC +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/req_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/req_seq_nr_bitmap +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/nack_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_vrkdp/uut/bitmap_latch +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {Begin {49575000 ps} 1} {Error {7325000 ps} 1} {Cursor {62689107 ps} 0} +quietly wave cursor active 3 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 135 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {61771800 ps} {62773704 ps} diff --git a/sim/L1_rtps_writer_test1_vrndp.do b/sim/L1_rtps_writer_test1_vrndp.do new file mode 100644 index 0000000..be2b3cb --- /dev/null +++ b/sim/L1_rtps_writer_test1_vrndp.do @@ -0,0 +1,98 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -divider SYSTEM +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/clk +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/reset +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrndp/uut/time +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrndp/uut/check_time +add wave -noupdate -divider INPUT +add wave -noupdate -group META /l1_rtps_writer_test1_vrndp/uut/empty_meta +add wave -noupdate -group META /l1_rtps_writer_test1_vrndp/uut/rd_meta +add wave -noupdate -group META /l1_rtps_writer_test1_vrndp/uut/last_word_in_meta +add wave -noupdate -group META -radix hexadecimal /l1_rtps_writer_test1_vrndp/uut/data_in_meta +add wave -noupdate -group USER /l1_rtps_writer_test1_vrndp/uut/empty_user +add wave -noupdate -group USER /l1_rtps_writer_test1_vrndp/uut/rd_user +add wave -noupdate -group USER -radix hexadecimal /l1_rtps_writer_test1_vrndp/uut/data_in_user +add wave -noupdate -group USER /l1_rtps_writer_test1_vrndp/uut/last_word_in_user +add wave -noupdate -divider HC +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/data_available +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/start_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/opcode_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/ack_hc +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vrndp/uut/seq_nr_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/done_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/ret_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/get_data_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_vrndp/uut/data_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/valid_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/ready_in_hc +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/last_word_in_hc +add wave -noupdate -expand -group HC -radix hexadecimal /l1_rtps_writer_test1_vrndp/uut/cc_instance_handle +add wave -noupdate -expand -group HC /l1_rtps_writer_test1_vrndp/uut/cc_kind +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vrndp/uut/cc_source_timestamp +add wave -noupdate -expand -group HC -radix unsigned /l1_rtps_writer_test1_vrndp/uut/cc_seq_nr +add wave -noupdate -divider OUTPUT +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/full_rtps +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/wr_rtps +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_vrndp/uut/data_out_rtps +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/last_word_out_rtps +add wave -noupdate /l1_rtps_writer_test1_vrndp/rtps_out_inst/wr +add wave -noupdate -radix hexadecimal /l1_rtps_writer_test1_vrndp/rtps_out_inst/data_out +add wave -noupdate -divider {MAIN FSM} +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/stage +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/stage_next +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/cnt +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrndp/uut/last_seq_nr +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrndp/uut/global_ack_seq_nr_base +add wave -noupdate -radix unsigned /l1_rtps_writer_test1_vrndp/uut/next_seq_nr +add wave -noupdate -divider {MEMORY FSM} +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/mem_op_done +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/mem_op_start +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/mem_opcode +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/mem_stage +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/mem_stage_next +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/mem_cnt +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/mem_pos +add wave -noupdate -radix unsigned -childformat {{/l1_rtps_writer_test1_vrndp/uut/mem_addr_base(6) -radix unsigned} {/l1_rtps_writer_test1_vrndp/uut/mem_addr_base(5) -radix unsigned} {/l1_rtps_writer_test1_vrndp/uut/mem_addr_base(4) -radix unsigned} {/l1_rtps_writer_test1_vrndp/uut/mem_addr_base(3) -radix unsigned} {/l1_rtps_writer_test1_vrndp/uut/mem_addr_base(2) -radix unsigned} {/l1_rtps_writer_test1_vrndp/uut/mem_addr_base(1) -radix unsigned} {/l1_rtps_writer_test1_vrndp/uut/mem_addr_base(0) -radix unsigned}} -subitemconfig {/l1_rtps_writer_test1_vrndp/uut/mem_addr_base(6) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrndp/uut/mem_addr_base(5) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrndp/uut/mem_addr_base(4) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrndp/uut/mem_addr_base(3) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrndp/uut/mem_addr_base(2) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrndp/uut/mem_addr_base(1) {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrndp/uut/mem_addr_base(0) {-height 15 -radix unsigned}} /l1_rtps_writer_test1_vrndp/uut/mem_addr_base +add wave -noupdate -childformat {{/l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.guid -radix hexadecimal} {/l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.addr -radix hexadecimal} {/l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.portn -radix hexadecimal} {/l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.lease_deadline -radix hexadecimal} {/l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.res_time -radix unsigned} {/l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.ack_seq_nr_base -radix unsigned} {/l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.req_seq_nr_base -radix unsigned}} -expand -subitemconfig {/l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.guid {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.addr {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.portn {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.lease_deadline {-height 15 -radix hexadecimal} /l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.res_time {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.ack_seq_nr_base {-height 15 -radix unsigned} /l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data.req_seq_nr_base {-height 15 -radix unsigned}} /l1_rtps_writer_test1_vrndp/uut/mem_endpoint_data +add wave -noupdate -group MEM_CTRL -radix unsigned /l1_rtps_writer_test1_vrndp/uut/mem_addr +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrndp/uut/mem_valid_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrndp/uut/mem_ready_in +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrndp/uut/mem_read +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_vrndp/uut/mem_write_data +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrndp/uut/abort_read +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrndp/uut/mem_valid_out +add wave -noupdate -group MEM_CTRL /l1_rtps_writer_test1_vrndp/uut/mem_ready_out +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l1_rtps_writer_test1_vrndp/uut/mem_read_data +add wave -noupdate -divider TESTBENCH +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrndp/start_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrndp/packet_sent_meta +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrndp/start_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrndp/packet_sent_user +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrndp/stage_hc +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrndp/out_check_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrndp/stim_done +add wave -noupdate -group TESTBENCH /l1_rtps_writer_test1_vrndp/test_done +add wave -noupdate -divider MISC +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/req_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/req_seq_nr_bitmap +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/nack_bitmap_pos +add wave -noupdate /l1_rtps_writer_test1_vrndp/uut/bitmap_latch +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {Begin {49575000 ps} 1} {Error {7325000 ps} 1} {Cursor {62689107 ps} 0} +quietly wave cursor active 3 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 135 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {61771800 ps} {62773704 ps} diff --git a/src/REF.txt b/src/REF.txt index 09a58b3..3fe993f 100644 --- a/src/REF.txt +++ b/src/REF.txt @@ -58,7 +58,7 @@ Optional features may not be supported by all RTPS implementations. -------------------------------------------- -ENTITYID_UKNOWN also for Built-In? +ENTITYID_UNKNOWN also for Built-In? Ignore Participant/Topic/Publication/Subscription (handle argument of Sampleinfo) ENDIANNESS diff --git a/src/TODO.txt b/src/TODO.txt index d92eaa3..9cf3b11 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -258,9 +258,15 @@ DESIGN DECISIONS sense to implement dual port RAMs for the History Cache. * Since the RTPS Writer only gets ACKNACK Messages from the matched Readers, and these Messages are - dropped by the rtps_handler if samller than expected, we do not need a "READ GUARD" in the RTPS + dropped by the rtps_handler if smaller than expected, we do not need a "READ GUARD" in the RTPS Writer. +* Because "Once Acknowledged, Always Acknowledged" the Base of an ACKNACK can only be bigger or + equal to the SN of the last ACKNACK. It is also reasonable, that the Reader will always request + ALL missing segments each time it sends an ACKNACK (i.e. does not assume once requested, always + requested until reception). This means that during the ACKNACK response delay, we can just parse + the new request bitmap and overwrite the last old one. + PROTOCOL UNCOMPLIANCE ===================== * Partition QoS diff --git a/src/Tests/Level_0/L0_rtps_writer_test1_vbkdp.vhd b/src/Tests/Level_0/L0_rtps_writer_test1_vbkdp.vhd index 125d4b0..f933a54 100644 --- a/src/Tests/Level_0/L0_rtps_writer_test1_vbkdp.vhd +++ b/src/Tests/Level_0/L0_rtps_writer_test1_vbkdp.vhd @@ -116,7 +116,8 @@ begin last_word_in_hc => '0', cc_instance_handle => HANDLE_NIL, cc_kind => ALIVE, - cc_source_timestamp => TIME_INVALID + cc_source_timestamp => TIME_INVALID, + cc_seq_nr => SEQUENCENUMBER_UNKNOWN ); stimulus_prc : process @@ -170,7 +171,7 @@ begin e1.participant := p0; e1.entityid := RV.RandSlv(ENTITYID_WIDTH); e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); - e1.expectsInlineQoS(0) := '1'; + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; -- Endpoint 3 e2 := DEFAULT_ENDPOINT_DATA; e2.participant := p1; @@ -184,7 +185,7 @@ begin e3.participant := p1; e3.entityid := RV.RandSlv(ENTITYID_WIDTH); e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); - e3.reliability := BEST_EFFORT_RELIABILITY_QOS; + e3.expectsInlineQoS(0) := '1'; Log("Initiating Test", INFO); stim_done <= '0'; diff --git a/src/Tests/Level_0/L0_rtps_writer_test1_vrkdp.vhd b/src/Tests/Level_0/L0_rtps_writer_test1_vrkdp.vhd index 8eb61c7..dd686ae 100644 --- a/src/Tests/Level_0/L0_rtps_writer_test1_vrkdp.vhd +++ b/src/Tests/Level_0/L0_rtps_writer_test1_vrkdp.vhd @@ -116,7 +116,8 @@ begin last_word_in_hc => '0', cc_instance_handle => HANDLE_NIL, cc_kind => ALIVE, - cc_source_timestamp => TIME_INVALID + cc_source_timestamp => TIME_INVALID, + cc_seq_nr => SEQUENCENUMBER_UNKNOWN ); stimulus_prc : process @@ -170,7 +171,7 @@ begin e1.participant := p0; e1.entityid := RV.RandSlv(ENTITYID_WIDTH); e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); - e1.expectsInlineQoS(0) := '1'; + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; -- Endpoint 3 e2 := DEFAULT_ENDPOINT_DATA; e2.participant := p1; @@ -184,7 +185,7 @@ begin e3.participant := p1; e3.entityid := RV.RandSlv(ENTITYID_WIDTH); e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); - e3.reliability := BEST_EFFORT_RELIABILITY_QOS; + e3.expectsInlineQoS(0) := '1'; Log("Initiating Test", INFO); stim_done <= '0'; diff --git a/src/Tests/Level_1/L1_rtps_writer_test1_tbkdp.vhd b/src/Tests/Level_1/L1_rtps_writer_test1_tbkdp.vhd new file mode 100644 index 0000000..653bfd1 --- /dev/null +++ b/src/Tests/Level_1/L1_rtps_writer_test1_tbkdp.vhd @@ -0,0 +1,964 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; -- Utility Library +context osvvm.OsvvmContext; + +use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; +use work.rtps_test_package.all; + +-- This testbench tests the RTPS Message generation of the RTPS Writer (DATA and GAP Generation). +-- This testbench covers following: +-- * (Best Effort/Transient Local/Expecting Inline Qos) Remote Readers +-- * New Data Push +-- * ACK Handling +-- * NACK/Request Handling + +entity L1_rtps_writer_test1_tbkdp is +end entity; + +architecture testbench of L1_rtps_writer_test1_tbkdp is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_ENDPOINTS : natural := 5; + constant MAX_CC : natural := 10; + + -- *TYPE DECLARATION* + type SEND_STAGE_TYPE is (IDLE, BUSY); + type TEST_CC_ARRAY_TYPE is array (0 to MAX_CC-1) of CACHE_CHANGE_TYPE; + type HC_STAGE_TYPE is (IDLE, PUSH, DONE, INVALID); + + -- *SIGNAL DECLARATION* + signal clk, empty_user, empty_meta, rd_user, rd_meta, last_word_in_user, last_word_in_meta, last_word_in_hc, last_word_out_rtps : std_logic := '0'; + signal reset : std_logic := '1'; + signal data_in_user, data_in_meta, data_out, data_in_hc : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal wr_sig, full, data_available : std_logic := '0'; + signal ready_in_hc, valid_in_hc, ack_hc, done_hc, get_data_hc, start_hc : std_logic := '0'; + signal seq_nr_hc : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + signal stim_stage_user, stim_stage_meta : SEND_STAGE_TYPE := IDLE; + signal opcode_hc : HISTORY_CACHE_OPCODE_TYPE := NOP; + signal ret_hc : HISTORY_CACHE_RESPONSE_TYPE := ERROR; + signal cc_instance_handle : INSTANCE_HANDLE_TYPE := HANDLE_NIL; + signal cc_kind : CACHE_CHANGE_KIND_TYPE := ALIVE; + signal cc_source_timestamp : TIME_TYPE := TIME_INVALID; + signal cc_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + shared variable stimulus_user, stimulus_meta, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent_user, packet_sent_meta : std_logic := '0'; + signal cnt_stim_meta, cnt_stim_user, count : natural := 0; + signal start_meta, start_user : std_logic := '0'; + shared variable SB_out, SB_hc : osvvm.ScoreBoardPkg_slv.ScoreBoardPType; + signal stim_done, out_check_done, hc_check_done, test_done : std_logic := '0'; + signal test_time : TIME_TYPE := TIME_ZERO; + signal fifo_in, fifo_out : std_logic_vector(WORD_WIDTH downto 0) := (others => '0'); + signal fifo_wr, fifo_empty, fifo_full : std_logic := '0'; + signal rtps_out_data : RTPS_OUT_DATA_TYPE := (others => (others => '0')); + signal rtps_out_rd, rtps_out_last_word_in, rtps_out_empty : std_logic_vector(0 to NUM_ENDPOINTS) := (others => '0'); + signal test_cc : TEST_CC_ARRAY_TYPE := (others => DEFAULT_CACHE_CHANGE); + -- Signal containing the current fill level of the test_cc array + signal test_cc_fill : natural := 0; + signal stage_hc : HC_STAGE_TYPE := IDLE; + signal new_cc : std_logic := '0'; + signal cnt : natural := 0; + + -- *FUNCTION DECLARATION* + function gen_sn(input : natural) return SEQUENCENUMBER_TYPE is + variable ret : SEQUENCENUMBER_TYPE; + begin + ret(0) := (others => '0'); + ret(1) := unsigned(int(input, WORD_WIDTH)); + return ret; + end function; + +begin + + -- Unit Under Test + uut : entity work.rtps_writer(arch) + generic map ( + RELIABILTY_QOS => BEST_EFFORT_RELIABILITY_QOS, + LIVELINESS_QOS => AUTOMATIC_LIVELINESS_QOS, + DURABILITY_QOS => TRANSIENT_LOCAL_DURABILITY_QOS, + DESTINATION_ORDER_QOS => BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS, + ACKNACK_RESPONSE_DELAY => gen_duration(1,0), + ACKNACK_SUPPRESSION_DELAY => DURATION_ZERO, + LEASE_DURATION => DURATION_INFINITE, + HEARTBEAT_PERIOD => DURATION_INFINITE, + ENTITYID => DEFAULT_WRITER_ENTITYID, + WITH_KEY => TRUE, + PUSH_MODE => TRUE, + INLINE_QOS => gen_inline_qos(NUM_READERS+7), + MAX_REMOTE_ENDPOINTS => MAX_REMOTE_ENDPOINTS + ) + port map ( + clk => clk, + reset => reset, + time => test_time, + empty_user => empty_user or packet_sent_user, + rd_user => rd_user, + data_in_user => data_in_user, + last_word_in_user => last_word_in_user, + empty_meta => empty_meta or packet_sent_meta, + rd_meta => rd_meta, + data_in_meta => data_in_meta, + last_word_in_meta => last_word_in_meta, + alive_sig => open, + wr_rtps => fifo_wr, + full_rtps => fifo_full, + last_word_out_rtps => fifo_in(WORD_WIDTH), + data_out_rtps => fifo_in(WORD_WIDTH-1 downto 0), + assert_liveliness => '0', + data_available => data_available, + start_hc => start_hc, + opcode_hc => opcode_hc, + ack_hc => ack_hc, + seq_nr_hc => seq_nr_hc, + done_hc => done_hc, + ret_hc => ret_hc, + get_data_hc => get_data_hc, + data_in_hc => data_in_hc, + valid_in_hc => valid_in_hc, + ready_in_hc => ready_in_hc, + last_word_in_hc => last_word_in_hc, + cc_instance_handle => cc_instance_handle, + cc_kind => cc_kind, + cc_source_timestamp => cc_source_timestamp, + cc_seq_nr => cc_seq_nr + ); + + fifo_inst : entity work.FWFT_FIFO(arch) + generic map ( + FIFO_DEPTH => 2, + DATA_WIDTH => WORD_WIDTH+1 + ) + port map + ( + reset => reset, + clk => clk, + data_in => fifo_in, + write => fifo_wr, + read => rtps_out_rd(0), + data_out => fifo_out, + empty => fifo_empty, + full => fifo_full, + free => open + ); + + rtps_out_data <= (0 => fifo_out(WORD_WIDTH-1 downto 0), others => (others => '0')); + rtps_out_last_word_in <= (0 => fifo_out(WORD_WIDTH), others => '0'); + rtps_out_empty <= (0 => fifo_empty, others => '1'); + + rtps_out_inst : entity work.rtps_out(arch) + port map ( + clk => clk, + reset => reset, + data_in => rtps_out_data, + last_word_in=> rtps_out_last_word_in, + rd => rtps_out_rd, + empty => rtps_out_empty, + data_out => data_out, + wr => wr_sig, + full => full + ); + + + stimulus_prc : process + variable RV : RandomPType; + variable e0, e1, e2, e3, e4, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + variable sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable cc : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + variable OUT_HEADER : OUTPUT_HEADER_TYPE := DEFAULT_OUTPUT_HEADER; + variable rtps_header : RTPS_HEADER_TYPE := DEFAULT_RTPS_HEADER; + + alias idle_sig is <>; + + -- Wrapper to use procedure as function + impure function gen_rand_loc_2 return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + gen_rand_loc(RV, ret); + return ret; + end function; + + impure function gen_rand_entityid_2(reader : boolean) return std_logic_vector is + variable ret : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); + begin + gen_rand_entityid(RV, reader, ret); + return ret; + end function; + + impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is + variable ret : GUIDPREFIX_TYPE; + begin + ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH)); + return ret; + end function; + + impure function gen_key_hash return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := (others => (others => '0')); + begin + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := RV.RandSlv(WORD_WIDTH); + end loop; + return ret; + end function; + + impure function gen_payload return TEST_PACKET_TYPE is + variable ret : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + begin + for i in 0 to RV.RandInt(1,10) loop + ret.data(ret.length) := RV.RandSlv(WORD_WIDTH); + ret.length := ret.length + 1; + end loop; + ret.last(ret.length-1) := '1'; + return ret; + end function; + + procedure start_meta_test is + begin + start_meta <= '1'; + wait until rising_edge(clk); + start_meta <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure start_user_test is + begin + start_user <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure wait_on_meta_sent is + begin + wait until rising_edge(packet_sent_meta); + end procedure; + + procedure wait_on_user_sent is + begin + wait until rising_edge(packet_sent_user); + end procedure; + + procedure wait_on_out_check is + begin + if (out_check_done /= '1') then + wait until out_check_done = '1'; + end if; + end procedure; + + procedure wait_on_hc_check is + begin + if (hc_check_done /= '1') then + wait until hc_check_done = '1'; + end if; + end procedure; + + procedure wait_on_completion is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + + procedure wait_on_idle is + begin + if (idle_sig /= '1') then + wait until idle_sig = '1'; + end if; + end procedure; + + procedure push_hc(opcode : in HISTORY_CACHE_OPCODE_TYPE; sn : in SEQUENCENUMBER_TYPE) is + begin + SB_hc.push(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode),WORD_WIDTH))); + SB_hc.push(std_logic_vector(sn(0))); + SB_hc.push(std_logic_vector(sn(1))); + end procedure; + + procedure gen_header(endpoint : in ENDPOINT_DATA_TYPE) is + begin + reference := EMPTY_TEST_PACKET; + -- OUTPUT HEADER + OUT_HEADER := DEFAULT_OUTPUT_HEADER; + OUT_HEADER := (dest => get_loc(endpoint), src => DEST_LOC.user.locator(1)); + gen_output_header(OUT_HEADER, reference); + -- RTPS HEADER + rtps_header := DEFAULT_RTPS_HEADER; + rtps_header.guidPrefix := GUIDPREFIX; + gen_rtps_header(rtps_header, reference); + end procedure; + + procedure gen_data(endpoint : in ENDPOINT_DATA_TYPE; ref : in CACHE_CHANGE_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.submessageLength := (others => '0'); + sub.writerSN := ref.seq_nr; + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1' when (ref.kind = ALIVE) else '0'; + sub.flags(SUBMESSAGE_KEY_FLAG_POS) := '1' when (ref.kind /= ALIVE) else '0'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + gen_inline_qos(ref, gen_endpoint(NUM_READERS+7), (endpoint.expectsInlineQoS(0) = '1'), '0', sub.inlineQos); + gen_sentinel(sub.inlineQos); + assert (ref.payload /= EMPTY_TEST_PACKET) severity FAILURE; + sub.data := ref.payload; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_ts(ts : TIME_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_INFO_TS; + sub.timestamp := ts; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_gap(first : SEQUENCENUMBER_TYPE; last : SEQUENCENUMBER_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.gapStart := first; + sub.gapList := (base => last, numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_submessage(sub, reference); + end procedure; + + procedure push_reference is + begin + fix_output_packet(reference); + for i in 0 to reference.length-1 loop + SB_out.Push(reference.data(i)); + end loop; + end procedure; + + begin + + SetAlertLogName("rtps_writer (Transient Local, Best Effort, Keyed, By Reception Timestamp, Push Mode) - Level 1 - RTPS Output (DATA & GAP)"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- Endpoint 0 + e0 := DEFAULT_ENDPOINT_DATA; + e0.nr := 0; + e0.match := MATCH; + e0.entityid := RV.RandSlv(ENTITYID_WIDTH); + e0.participant.guidPrefix := gen_rand_guid_prefix; + e0.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 1 + e1 := DEFAULT_ENDPOINT_DATA; + e1.nr := 1; + e1.match := MATCH; + e1.entityid := RV.RandSlv(ENTITYID_WIDTH); + e1.participant.guidPrefix := gen_rand_guid_prefix; + e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; + -- Endpoint 2 + e2 := DEFAULT_ENDPOINT_DATA; + e2.nr := 2; + e2.match := MATCH; + e2.entityid := RV.RandSlv(ENTITYID_WIDTH); + e2.participant.guidPrefix := gen_rand_guid_prefix; + e2.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e2.expectsInlineQoS(0) := '1'; + -- Endpoint 3 + e3 := DEFAULT_ENDPOINT_DATA; + e3.nr := 3; + e3.match := MATCH; + e3.entityid := RV.RandSlv(ENTITYID_WIDTH); + e3.participant.guidPrefix := gen_rand_guid_prefix; + e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e3.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + -- Endpoint 4 + e4 := DEFAULT_ENDPOINT_DATA; + e4.nr := 4; + e4.match := MATCH; + e4.entityid := RV.RandSlv(ENTITYID_WIDTH); + e4.participant.guidPrefix := gen_rand_guid_prefix; + e4.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e4.expectsInlineQoS(0) := '1'; + e4.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + e4.reliability := BEST_EFFORT_RELIABILITY_QOS; + + Log("Initiating Test", INFO); + Log("Current Time: 0s", INFO); + count <= 1; + test_time <= TIME_ZERO; + new_cc <= '0'; + stim_done <= '0'; + start_meta <= '0'; + start_user <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + + Log("Insert Endpoint 0,1", INFO); + gen_endpoint_match_frame(e0, stimulus_meta); + gen_endpoint_match_frame(e1, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 1] (Send DATA to Endpoint 0,1)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(1); + test_cc(0).src_timestamp <= gen_duration(1,0); + test_cc(0).payload <= gen_payload; + test_cc_fill <= 1; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + push_hc(ACK_CACHE_CHANGE, gen_sn(1)); + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Add Cache Change [SN 2,3] (Send DATA to Endpoint 0,1)", INFO); + test_cc(1).kind <= ALIVE; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(2); + test_cc(1).src_timestamp <= gen_duration(2,0); + test_cc(1).payload <= gen_payload; + test_cc(2).kind <= ALIVE; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(3); + test_cc(2).src_timestamp <= gen_duration(3,0); + test_cc(2).payload <= gen_payload; + test_cc_fill <= 3; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + push_hc(ACK_CACHE_CHANGE, gen_sn(2)); + push_hc(ACK_CACHE_CHANGE, gen_sn(3)); + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 2,3 (Send Historical DATA to Endpoint 3)", INFO); + gen_endpoint_match_frame(e2, stimulus_meta); + gen_endpoint_match_frame(e3, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + + gen_header(e3); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Add Cache Change [SN 4] (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(3).kind <= ALIVE_FILTERED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(4); + test_cc(3).src_timestamp <= gen_duration(4,0); + test_cc(3).payload <= gen_payload; + test_cc_fill <= 4; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + push_hc(ACK_CACHE_CHANGE, gen_sn(4)); + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Add Cache Change [SN 10,11,15,46,50], Remove Cache Change [SN 1,2] (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(0) <= test_cc(2); + test_cc(1) <= test_cc(3); + test_cc(2).kind <= ALIVE; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(10); + test_cc(2).src_timestamp <= gen_duration(5,0); + test_cc(2).payload <= gen_payload; + test_cc(3).kind <= NOT_ALIVE_DISPOSED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(11); + test_cc(3).src_timestamp <= gen_duration(6,0); + test_cc(3).payload <= gen_payload; + test_cc(4).kind <= NOT_ALIVE_UNREGISTERED; + test_cc(4).instance <= gen_key_hash; + test_cc(4).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(4).seq_nr <= gen_sn(15); + test_cc(4).src_timestamp <= gen_duration(7,0); + test_cc(4).payload <= gen_payload; + test_cc(5).kind <= NOT_ALIVE_DISPOSED; + test_cc(5).instance <= gen_key_hash; + test_cc(5).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(5).seq_nr <= gen_sn(37); + test_cc(5).src_timestamp <= gen_duration(8,0); + test_cc(5).payload <= gen_payload; + test_cc(6).kind <= ALIVE; + test_cc(6).instance <= gen_key_hash; + test_cc(6).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(6).seq_nr <= gen_sn(50); + test_cc(6).src_timestamp <= gen_duration(9,0); + test_cc(6).payload <= gen_payload; + test_cc_fill <= 7; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + push_hc(ACK_CACHE_CHANGE, gen_sn(10)); + push_hc(ACK_CACHE_CHANGE, gen_sn(11)); + push_hc(ACK_CACHE_CHANGE, gen_sn(15)); + push_hc(ACK_CACHE_CHANGE, gen_sn(37)); + push_hc(ACK_CACHE_CHANGE, gen_sn(50)); + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(6)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(6)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(6)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(6)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [Request SN 10,15,37]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(35, CDR_LONG_WIDTH), bitmap => (5 => '1', 10 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1s", INFO); + test_time <= gen_duration(1,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + wait_on_idle; + + Log("Insert Endpoint 4 (Send Historical DATA to Endpoint 4)", INFO); + gen_endpoint_match_frame(e4, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + + gen_header(e4); + gen_data(e4, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_data(e4, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(5), gen_sn(10)); + gen_data(e4, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_data(e4, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(12), gen_sn(15)); + gen_data(e4, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(16), gen_sn(37)); + gen_data(e4, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(38), gen_sn(50)); + gen_data(e4, test_cc(6)); + push_reference; + wait_on_out_check; + wait_on_idle; + + stim_done <= '1'; + wait_on_completion; + TranscriptOpen(RESULTS_FILE, APPEND_MODE); + SetTranscriptMirror; + ReportAlerts; + TranscriptClose; + std.env.stop; + wait; + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + empty_meta_prc : process + begin + empty_meta <= '0'; + wait until rd_meta = '1'; + wait until rising_edge(clk); + empty_meta <= '1'; + wait until rising_edge(clk); + end process; + + empty_user_prc : process + begin + empty_user <= '0'; + wait until rd_user = '1'; + wait until rising_edge(clk); + empty_user <= '1'; + wait until rising_edge(clk); + end process; + + rtps_full_prc : process + begin + full <= '0'; + wait until wr_sig = '1'; + wait until rising_edge(clk); + full <= '1'; + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(empty_meta = '1' and rd_meta = '1', "Input FIFO read signal high while empty signal high (meta)", ERROR); + alertif(empty_user = '1' and rd_user = '1', "Input FIFO read signal high while empty signal high (user)", ERROR); + alertif(full = '1' and wr_sig = '1', "Output FIFO write signal high while full signal high", ERROR); + end if; + end process; + + input_meta_prc : process(all) + begin + data_in_meta <= stimulus_meta.data(cnt_stim_meta); + last_word_in_meta <= stimulus_meta.last(cnt_stim_meta); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_meta <= 0; + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + else + case (stim_stage_meta) is + when IDLE => + if (start_meta = '1' and stimulus_meta.length /= 0) then + stim_stage_meta <= BUSY; + packet_sent_meta <= '0'; + end if; + when BUSY => + if (rd_meta = '1') then + if (cnt_stim_meta = stimulus_meta.length-1) then + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + cnt_stim_meta <= 0; + else + cnt_stim_meta <= cnt_stim_meta + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + input_user_prc : process(all) + begin + data_in_user <= stimulus_user.data(cnt_stim_user); + last_word_in_user <= stimulus_user.last(cnt_stim_user); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_user <= 0; + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + else + case (stim_stage_user) is + when IDLE => + if (start_user = '1' and stimulus_user.length /= 0) then + stim_stage_user <= BUSY; + packet_sent_user <= '0'; + end if; + when BUSY => + if (rd_user = '1') then + if (cnt_stim_user = stimulus_user.length-1) then + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + cnt_stim_user <= 0; + else + cnt_stim_user <= cnt_stim_user + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_out.empty and SB_hc.empty) then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + hc_prc : process (all) + variable stimulus : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + variable bool : boolean := FALSE; + begin + if (new_cc = '1') then + data_available <= '1'; + end if; + if rising_edge(clk) then + hc_check_done <= '0'; + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + case (opcode_hc) is + when GET_CACHE_CHANGE => + bool := FALSE; + for i in 0 to test_cc_fill-1 loop + if (test_cc(i).seq_nr = seq_nr_hc) then + cc_instance_handle <= test_cc(i).instance; + cc_source_timestamp <= test_cc(i).src_timestamp; + cc_kind <= test_cc(i).kind; + stimulus := test_cc(i).payload; + stage_hc <= DONE; + bool := TRUE; + end if; + end loop; + if (not bool) then + stage_hc <= INVALID; + end if; + when GET_MIN_SN => + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(0).seq_nr; + stage_hc <= DONE; + when GET_MAX_SN => + data_available <= '0'; + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(test_cc_fill-1).seq_nr when (test_cc_fill /= 0) else SEQUENCENUMBER_UNKNOWN; + stage_hc <= DONE; + when others => + SB_hc.Check(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode_hc), WORD_WIDTH))); + SB_hc.Check(std_logic_vector(seq_nr_hc(0))); + SB_hc.Check(std_logic_vector(seq_nr_hc(1))); + hc_check_done <= '1'; + stage_hc <= DONE; + end case; + end if; + when DONE => + if (get_data_hc = '1') then + alertif(stimulus = EMPTY_TEST_PACKET, "Requested empty Payload", FAILURE); + stage_hc <= PUSH; + cnt <= 0; + else + stage_hc <= IDLE; + end if; + when PUSH => + if (ready_in_hc = '1') then + cnt <= cnt + 1; + if (cnt = stimulus.length-1) then + stage_hc <= IDLE; + end if; + end if; + when INVALID => + stage_hc <= IDLE; + when others => + null; + end case; + end if; + + -- DEFAULT + ack_hc <= '0'; + valid_in_hc <= '0'; + data_in_hc <= (others => '0'); + last_word_in_hc <= '0'; + done_hc <= '0'; + ret_hc <= ERROR; + + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + end if; + when DONE => + done_hc <= '1'; + ret_hc <= OK; + when PUSH => + valid_in_hc <= '1'; + data_in_hc <= stimulus.data(cnt); + last_word_in_hc <= stimulus.last(cnt); + when INVALID => + done_hc <= '1'; + ret_hc <= INVALID; + when others => + null; + end case; + end process; + + output_check_prc : process(all) + begin + if (SB_out.empty) then + out_check_done <= '1'; + else + out_check_done <= '0'; + end if; + if rising_edge(clk) then + if (wr_sig = '1') then + SB_out.Check(data_out); + end if; + end if; + end process; + + watchdog : process + begin + wait for 1 ms; + Alert("Test timeout", FAILURE); + std.env.stop; + end process; + +end architecture; \ No newline at end of file diff --git a/src/Tests/Level_1/L1_rtps_writer_test1_trkdn.vhd b/src/Tests/Level_1/L1_rtps_writer_test1_trkdn.vhd new file mode 100644 index 0000000..2bf3b37 --- /dev/null +++ b/src/Tests/Level_1/L1_rtps_writer_test1_trkdn.vhd @@ -0,0 +1,1279 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; -- Utility Library +context osvvm.OsvvmContext; + +use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; +use work.rtps_test_package.all; + +-- This testbench tests the RTPS Message generation of the RTPS Writer (DATA and GAP Generation). +-- This testbench covers following: +-- * (Best Effort/Transient Local/Expecting Inline Qos) Remote Readers +-- * New Data Push +-- * ACK Handling +-- * NACK/Request Handling + +entity L1_rtps_writer_test1_trkdn is +end entity; + +architecture testbench of L1_rtps_writer_test1_trkdn is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_ENDPOINTS : natural := 5; + constant MAX_CC : natural := 10; + + -- *TYPE DECLARATION* + type SEND_STAGE_TYPE is (IDLE, BUSY); + type TEST_CC_ARRAY_TYPE is array (0 to MAX_CC-1) of CACHE_CHANGE_TYPE; + type HC_STAGE_TYPE is (IDLE, PUSH, DONE, INVALID); + + -- *SIGNAL DECLARATION* + signal clk, empty_user, empty_meta, rd_user, rd_meta, last_word_in_user, last_word_in_meta, last_word_in_hc, last_word_out_rtps : std_logic := '0'; + signal reset : std_logic := '1'; + signal data_in_user, data_in_meta, data_out, data_in_hc : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal wr_sig, full, data_available : std_logic := '0'; + signal ready_in_hc, valid_in_hc, ack_hc, done_hc, get_data_hc, start_hc : std_logic := '0'; + signal seq_nr_hc : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + signal stim_stage_user, stim_stage_meta : SEND_STAGE_TYPE := IDLE; + signal opcode_hc : HISTORY_CACHE_OPCODE_TYPE := NOP; + signal ret_hc : HISTORY_CACHE_RESPONSE_TYPE := ERROR; + signal cc_instance_handle : INSTANCE_HANDLE_TYPE := HANDLE_NIL; + signal cc_kind : CACHE_CHANGE_KIND_TYPE := ALIVE; + signal cc_source_timestamp : TIME_TYPE := TIME_INVALID; + signal cc_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + shared variable stimulus_user, stimulus_meta, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent_user, packet_sent_meta : std_logic := '0'; + signal cnt_stim_meta, cnt_stim_user, count : natural := 0; + signal start_meta, start_user : std_logic := '0'; + shared variable SB_out, SB_hc : osvvm.ScoreBoardPkg_slv.ScoreBoardPType; + signal stim_done, out_check_done, hc_check_done, test_done : std_logic := '0'; + signal test_time : TIME_TYPE := TIME_ZERO; + signal fifo_in, fifo_out : std_logic_vector(WORD_WIDTH downto 0) := (others => '0'); + signal fifo_wr, fifo_empty, fifo_full : std_logic := '0'; + signal rtps_out_data : RTPS_OUT_DATA_TYPE := (others => (others => '0')); + signal rtps_out_rd, rtps_out_last_word_in, rtps_out_empty : std_logic_vector(0 to NUM_ENDPOINTS) := (others => '0'); + signal test_cc : TEST_CC_ARRAY_TYPE := (others => DEFAULT_CACHE_CHANGE); + -- Signal containing the current fill level of the test_cc array + signal test_cc_fill : natural := 0; + signal stage_hc : HC_STAGE_TYPE := IDLE; + signal new_cc : std_logic := '0'; + signal cnt : natural := 0; + + -- *FUNCTION DECLARATION* + function gen_sn(input : natural) return SEQUENCENUMBER_TYPE is + variable ret : SEQUENCENUMBER_TYPE; + begin + ret(0) := (others => '0'); + ret(1) := unsigned(int(input, WORD_WIDTH)); + return ret; + end function; + +begin + + -- Unit Under Test + uut : entity work.rtps_writer(arch) + generic map ( + RELIABILTY_QOS => RELIABLE_RELIABILITY_QOS, + LIVELINESS_QOS => AUTOMATIC_LIVELINESS_QOS, + DURABILITY_QOS => TRANSIENT_LOCAL_DURABILITY_QOS, + DESTINATION_ORDER_QOS => BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS, + ACKNACK_RESPONSE_DELAY => gen_duration(1,0), + ACKNACK_SUPPRESSION_DELAY => DURATION_ZERO, + LEASE_DURATION => DURATION_INFINITE, + HEARTBEAT_PERIOD => DURATION_INFINITE, + ENTITYID => DEFAULT_WRITER_ENTITYID, + WITH_KEY => TRUE, + PUSH_MODE => FALSE, + INLINE_QOS => gen_inline_qos(NUM_READERS+7), + MAX_REMOTE_ENDPOINTS => MAX_REMOTE_ENDPOINTS + ) + port map ( + clk => clk, + reset => reset, + time => test_time, + empty_user => empty_user or packet_sent_user, + rd_user => rd_user, + data_in_user => data_in_user, + last_word_in_user => last_word_in_user, + empty_meta => empty_meta or packet_sent_meta, + rd_meta => rd_meta, + data_in_meta => data_in_meta, + last_word_in_meta => last_word_in_meta, + alive_sig => open, + wr_rtps => fifo_wr, + full_rtps => fifo_full, + last_word_out_rtps => fifo_in(WORD_WIDTH), + data_out_rtps => fifo_in(WORD_WIDTH-1 downto 0), + assert_liveliness => '0', + data_available => data_available, + start_hc => start_hc, + opcode_hc => opcode_hc, + ack_hc => ack_hc, + seq_nr_hc => seq_nr_hc, + done_hc => done_hc, + ret_hc => ret_hc, + get_data_hc => get_data_hc, + data_in_hc => data_in_hc, + valid_in_hc => valid_in_hc, + ready_in_hc => ready_in_hc, + last_word_in_hc => last_word_in_hc, + cc_instance_handle => cc_instance_handle, + cc_kind => cc_kind, + cc_source_timestamp => cc_source_timestamp, + cc_seq_nr => cc_seq_nr + ); + + fifo_inst : entity work.FWFT_FIFO(arch) + generic map ( + FIFO_DEPTH => 2, + DATA_WIDTH => WORD_WIDTH+1 + ) + port map + ( + reset => reset, + clk => clk, + data_in => fifo_in, + write => fifo_wr, + read => rtps_out_rd(0), + data_out => fifo_out, + empty => fifo_empty, + full => fifo_full, + free => open + ); + + rtps_out_data <= (0 => fifo_out(WORD_WIDTH-1 downto 0), others => (others => '0')); + rtps_out_last_word_in <= (0 => fifo_out(WORD_WIDTH), others => '0'); + rtps_out_empty <= (0 => fifo_empty, others => '1'); + + rtps_out_inst : entity work.rtps_out(arch) + port map ( + clk => clk, + reset => reset, + data_in => rtps_out_data, + last_word_in=> rtps_out_last_word_in, + rd => rtps_out_rd, + empty => rtps_out_empty, + data_out => data_out, + wr => wr_sig, + full => full + ); + + + stimulus_prc : process + variable RV : RandomPType; + variable e0, e1, e2, e3, e4, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + variable sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable cc : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + variable OUT_HEADER : OUTPUT_HEADER_TYPE := DEFAULT_OUTPUT_HEADER; + variable rtps_header : RTPS_HEADER_TYPE := DEFAULT_RTPS_HEADER; + + alias idle_sig is <>; + + -- Wrapper to use procedure as function + impure function gen_rand_loc_2 return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + gen_rand_loc(RV, ret); + return ret; + end function; + + impure function gen_rand_entityid_2(reader : boolean) return std_logic_vector is + variable ret : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); + begin + gen_rand_entityid(RV, reader, ret); + return ret; + end function; + + impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is + variable ret : GUIDPREFIX_TYPE; + begin + ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH)); + return ret; + end function; + + impure function gen_key_hash return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := (others => (others => '0')); + begin + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := RV.RandSlv(WORD_WIDTH); + end loop; + return ret; + end function; + + impure function gen_payload return TEST_PACKET_TYPE is + variable ret : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + begin + for i in 0 to RV.RandInt(1,10) loop + ret.data(ret.length) := RV.RandSlv(WORD_WIDTH); + ret.length := ret.length + 1; + end loop; + ret.last(ret.length-1) := '1'; + return ret; + end function; + + procedure start_meta_test is + begin + start_meta <= '1'; + wait until rising_edge(clk); + start_meta <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure start_user_test is + begin + start_user <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure wait_on_meta_sent is + begin + wait until rising_edge(packet_sent_meta); + end procedure; + + procedure wait_on_user_sent is + begin + wait until rising_edge(packet_sent_user); + end procedure; + + procedure wait_on_out_check is + begin + if (out_check_done /= '1') then + wait until out_check_done = '1'; + end if; + end procedure; + + procedure wait_on_hc_check is + begin + if (hc_check_done /= '1') then + wait until hc_check_done = '1'; + end if; + end procedure; + + procedure wait_on_completion is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + + procedure wait_on_idle is + begin + if (idle_sig /= '1') then + wait until idle_sig = '1'; + end if; + end procedure; + + procedure push_hc(opcode : in HISTORY_CACHE_OPCODE_TYPE; sn : in SEQUENCENUMBER_TYPE) is + begin + SB_hc.push(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode),WORD_WIDTH))); + SB_hc.push(std_logic_vector(sn(0))); + SB_hc.push(std_logic_vector(sn(1))); + end procedure; + + procedure gen_header(endpoint : in ENDPOINT_DATA_TYPE) is + begin + reference := EMPTY_TEST_PACKET; + -- OUTPUT HEADER + OUT_HEADER := DEFAULT_OUTPUT_HEADER; + OUT_HEADER := (dest => get_loc(endpoint), src => DEST_LOC.user.locator(1)); + gen_output_header(OUT_HEADER, reference); + -- RTPS HEADER + rtps_header := DEFAULT_RTPS_HEADER; + rtps_header.guidPrefix := GUIDPREFIX; + gen_rtps_header(rtps_header, reference); + end procedure; + + procedure gen_data(endpoint : in ENDPOINT_DATA_TYPE; ref : in CACHE_CHANGE_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.submessageLength := (others => '0'); + sub.writerSN := ref.seq_nr; + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1' when (ref.kind = ALIVE) else '0'; + sub.flags(SUBMESSAGE_KEY_FLAG_POS) := '1' when (ref.kind /= ALIVE) else '0'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + gen_inline_qos(ref, gen_endpoint(NUM_READERS+7), (endpoint.expectsInlineQoS(0) = '1'), '0', sub.inlineQos); + gen_sentinel(sub.inlineQos); + assert (ref.payload /= EMPTY_TEST_PACKET) severity FAILURE; + sub.data := ref.payload; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_ts(ts : TIME_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_INFO_TS; + sub.timestamp := ts; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_gap(first : SEQUENCENUMBER_TYPE; last : SEQUENCENUMBER_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.gapStart := first; + sub.gapList := (base => last, numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_submessage(sub, reference); + end procedure; + + procedure push_reference is + begin + fix_output_packet(reference); + for i in 0 to reference.length-1 loop + SB_out.Push(reference.data(i)); + end loop; + end procedure; + + begin + + SetAlertLogName("rtps_writer (Transient Local, Reliable, Keyed, By Reception Timestamp, Pull Mode) - Level 1 - RTPS Output (DATA & GAP)"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- Endpoint 0 + e0 := DEFAULT_ENDPOINT_DATA; + e0.nr := 0; + e0.match := MATCH; + e0.entityid := RV.RandSlv(ENTITYID_WIDTH); + e0.participant.guidPrefix := gen_rand_guid_prefix; + e0.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 1 + e1 := DEFAULT_ENDPOINT_DATA; + e1.nr := 1; + e1.match := MATCH; + e1.entityid := RV.RandSlv(ENTITYID_WIDTH); + e1.participant.guidPrefix := gen_rand_guid_prefix; + e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; + -- Endpoint 2 + e2 := DEFAULT_ENDPOINT_DATA; + e2.nr := 2; + e2.match := MATCH; + e2.entityid := RV.RandSlv(ENTITYID_WIDTH); + e2.participant.guidPrefix := gen_rand_guid_prefix; + e2.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e2.expectsInlineQoS(0) := '1'; + -- Endpoint 3 + e3 := DEFAULT_ENDPOINT_DATA; + e3.nr := 3; + e3.match := MATCH; + e3.entityid := RV.RandSlv(ENTITYID_WIDTH); + e3.participant.guidPrefix := gen_rand_guid_prefix; + e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e3.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + -- Endpoint 4 + e4 := DEFAULT_ENDPOINT_DATA; + e4.nr := 4; + e4.match := MATCH; + e4.entityid := RV.RandSlv(ENTITYID_WIDTH); + e4.participant.guidPrefix := gen_rand_guid_prefix; + e4.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e4.expectsInlineQoS(0) := '1'; + e4.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + e4.reliability := BEST_EFFORT_RELIABILITY_QOS; + + Log("Initiating Test", INFO); + Log("Current Time: 0s", INFO); + count <= 1; + test_time <= TIME_ZERO; + new_cc <= '0'; + stim_done <= '0'; + start_meta <= '0'; + start_user <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + + Log("Insert Endpoint 0,1", INFO); + gen_endpoint_match_frame(e0, stimulus_meta); + gen_endpoint_match_frame(e1, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 1]", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(1); + test_cc(0).src_timestamp <= gen_duration(1,0); + test_cc(0).payload <= gen_payload; + test_cc_fill <= 1; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + Log("Endpoint 0 sent ACKNACK [Request SN 1]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 1 sent ACKNACK [Request SN 1]", INFO); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1s", INFO); + Log("Send SN 1 to Endpoints 0,1", INFO); + test_time <= gen_duration(1,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <2] (Global ACK SN 1)", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(1)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 2,3]", INFO); + test_cc(1).kind <= ALIVE; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(2); + test_cc(1).src_timestamp <= gen_duration(2,0); + test_cc(1).payload <= gen_payload; + test_cc(2).kind <= ALIVE; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(3); + test_cc(2).src_timestamp <= gen_duration(3,0); + test_cc(2).payload <= gen_payload; + test_cc_fill <= 3; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + Log("Endpoint 0 sent ACKNACK [ACK <2, Request SN 2,3]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(2, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 1 sent ACKNACK [ACK <2, Request SN 2,3]", INFO); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(2, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 2s", INFO); + Log("Send SN 2,3 to Endpoints 0,1", INFO); + test_time <= gen_duration(2,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 2,3 (Send Historical DATA to Endpoint 3, Reset Global ACK SN 1,2,3)", INFO); + gen_endpoint_match_frame(e2, stimulus_meta); + gen_endpoint_match_frame(e3, stimulus_meta); + push_hc(NACK_CACHE_CHANGE, gen_sn(1)); + push_hc(NACK_CACHE_CHANGE, gen_sn(2)); + push_hc(NACK_CACHE_CHANGE, gen_sn(3)); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + + gen_header(e3); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <4]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <2] (Global ACK SN 1)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(1)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 4] (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(3).kind <= ALIVE_FILTERED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(4); + test_cc(3).src_timestamp <= gen_duration(4,0); + test_cc(3).payload <= gen_payload; + test_cc_fill <= 4; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + Log("Endpoint 0 sent ACKNACK [ACK SN <4, Request SN 4]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 1 sent ACKNACK [ACK SN <4, Request SN 4]", INFO); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <4, Request SN 4]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <4, Request SN 4] (Global ACK SN 2,3)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(2)); + push_hc(ACK_CACHE_CHANGE, gen_sn(3)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 3s", INFO); + Log("Send SN 4 to Endpoints 0,1,2,3", INFO); + test_time <= gen_duration(3,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <5]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <5]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <5] (Global ACK SN 4)", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(4)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 10,11,15,46,50], Remove Cache Change [SN 1,2]", INFO); + test_cc(0) <= test_cc(2); + test_cc(1) <= test_cc(3); + test_cc(2).kind <= ALIVE; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(10); + test_cc(2).src_timestamp <= gen_duration(5,0); + test_cc(2).payload <= gen_payload; + test_cc(3).kind <= NOT_ALIVE_DISPOSED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(11); + test_cc(3).src_timestamp <= gen_duration(6,0); + test_cc(3).payload <= gen_payload; + test_cc(4).kind <= NOT_ALIVE_UNREGISTERED; + test_cc(4).instance <= gen_key_hash; + test_cc(4).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(4).seq_nr <= gen_sn(15); + test_cc(4).src_timestamp <= gen_duration(7,0); + test_cc(4).payload <= gen_payload; + test_cc(5).kind <= NOT_ALIVE_DISPOSED; + test_cc(5).instance <= gen_key_hash; + test_cc(5).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(5).seq_nr <= gen_sn(37); + test_cc(5).src_timestamp <= gen_duration(8,0); + test_cc(5).payload <= gen_payload; + test_cc(6).kind <= ALIVE; + test_cc(6).instance <= gen_key_hash; + test_cc(6).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(6).seq_nr <= gen_sn(50); + test_cc(6).src_timestamp <= gen_duration(9,0); + test_cc(6).payload <= gen_payload; + test_cc_fill <= 7; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + Log("Endpoint 0 sent ACKNACK [Request SN 10,15,37]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(35, CDR_LONG_WIDTH), bitmap => (5 => '1', 10 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 4s", INFO); + Log("Send SN 10,15,37 to Endpoint 0", INFO); + test_time <= gen_duration(4,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(5)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <15]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <10, Request SN 10]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(10), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 4.5s", INFO); + test_time <= gen_duration(4,500); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <15, Request SN 15,16,47]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(33, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 5s", INFO); + Log("Send SN 15 to Endpoint 0 (GAP for SN 16, and ignore Request for SN 47)", INFO); + test_time <= gen_duration(5,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e2); + gen_data(e2, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_gap(gen_sn(16), gen_sn(17)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [Request SN 1-32]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(32, CDR_LONG_WIDTH), bitmap => (0 to 31 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 6s", INFO); + Log("Send SN 3,4,10,11,15 to Endpoint 3 (GAPs for Rest)", INFO); + test_time <= gen_duration(6,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e3); + gen_gap(gen_sn(1), gen_sn(3)); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(5), gen_sn(10)); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(12), gen_sn(15)); + gen_data(e3, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(16), gen_sn(32)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 4 (Send Historical DATA to Endpoint 4)", INFO); + gen_endpoint_match_frame(e4, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + + gen_header(e4); + gen_data(e4, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_data(e4, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(5), gen_sn(10)); + gen_data(e4, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_data(e4, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(12), gen_sn(15)); + gen_data(e4, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(16), gen_sn(37)); + gen_data(e4, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(38), gen_sn(50)); + gen_data(e4, test_cc(6)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <15] (Global ACK SN 5,6,7,8,9,10,11,12,13,14)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(5)); + push_hc(ACK_CACHE_CHANGE, gen_sn(6)); + push_hc(ACK_CACHE_CHANGE, gen_sn(7)); + push_hc(ACK_CACHE_CHANGE, gen_sn(8)); + push_hc(ACK_CACHE_CHANGE, gen_sn(9)); + push_hc(ACK_CACHE_CHANGE, gen_sn(10)); + push_hc(ACK_CACHE_CHANGE, gen_sn(11)); + push_hc(ACK_CACHE_CHANGE, gen_sn(12)); + push_hc(ACK_CACHE_CHANGE, gen_sn(13)); + push_hc(ACK_CACHE_CHANGE, gen_sn(14)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + stim_done <= '1'; + wait_on_completion; + TranscriptOpen(RESULTS_FILE, APPEND_MODE); + SetTranscriptMirror; + ReportAlerts; + TranscriptClose; + std.env.stop; + wait; + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + empty_meta_prc : process + begin + empty_meta <= '0'; + wait until rd_meta = '1'; + wait until rising_edge(clk); + empty_meta <= '1'; + wait until rising_edge(clk); + end process; + + empty_user_prc : process + begin + empty_user <= '0'; + wait until rd_user = '1'; + wait until rising_edge(clk); + empty_user <= '1'; + wait until rising_edge(clk); + end process; + + rtps_full_prc : process + begin + full <= '0'; + wait until wr_sig = '1'; + wait until rising_edge(clk); + full <= '1'; + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(empty_meta = '1' and rd_meta = '1', "Input FIFO read signal high while empty signal high (meta)", ERROR); + alertif(empty_user = '1' and rd_user = '1', "Input FIFO read signal high while empty signal high (user)", ERROR); + alertif(full = '1' and wr_sig = '1', "Output FIFO write signal high while full signal high", ERROR); + end if; + end process; + + input_meta_prc : process(all) + begin + data_in_meta <= stimulus_meta.data(cnt_stim_meta); + last_word_in_meta <= stimulus_meta.last(cnt_stim_meta); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_meta <= 0; + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + else + case (stim_stage_meta) is + when IDLE => + if (start_meta = '1' and stimulus_meta.length /= 0) then + stim_stage_meta <= BUSY; + packet_sent_meta <= '0'; + end if; + when BUSY => + if (rd_meta = '1') then + if (cnt_stim_meta = stimulus_meta.length-1) then + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + cnt_stim_meta <= 0; + else + cnt_stim_meta <= cnt_stim_meta + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + input_user_prc : process(all) + begin + data_in_user <= stimulus_user.data(cnt_stim_user); + last_word_in_user <= stimulus_user.last(cnt_stim_user); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_user <= 0; + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + else + case (stim_stage_user) is + when IDLE => + if (start_user = '1' and stimulus_user.length /= 0) then + stim_stage_user <= BUSY; + packet_sent_user <= '0'; + end if; + when BUSY => + if (rd_user = '1') then + if (cnt_stim_user = stimulus_user.length-1) then + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + cnt_stim_user <= 0; + else + cnt_stim_user <= cnt_stim_user + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_out.empty and SB_hc.empty) then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + hc_prc : process (all) + variable stimulus : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + variable bool : boolean := FALSE; + begin + if (new_cc = '1') then + data_available <= '1'; + end if; + if rising_edge(clk) then + hc_check_done <= '0'; + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + case (opcode_hc) is + when GET_CACHE_CHANGE => + bool := FALSE; + for i in 0 to test_cc_fill-1 loop + if (test_cc(i).seq_nr = seq_nr_hc) then + cc_instance_handle <= test_cc(i).instance; + cc_source_timestamp <= test_cc(i).src_timestamp; + cc_kind <= test_cc(i).kind; + stimulus := test_cc(i).payload; + stage_hc <= DONE; + bool := TRUE; + end if; + end loop; + if (not bool) then + stage_hc <= INVALID; + end if; + when GET_MIN_SN => + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(0).seq_nr; + stage_hc <= DONE; + when GET_MAX_SN => + data_available <= '0'; + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(test_cc_fill-1).seq_nr when (test_cc_fill /= 0) else SEQUENCENUMBER_UNKNOWN; + stage_hc <= DONE; + when others => + SB_hc.Check(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode_hc), WORD_WIDTH))); + SB_hc.Check(std_logic_vector(seq_nr_hc(0))); + SB_hc.Check(std_logic_vector(seq_nr_hc(1))); + hc_check_done <= '1'; + stage_hc <= DONE; + end case; + end if; + when DONE => + if (get_data_hc = '1') then + alertif(stimulus = EMPTY_TEST_PACKET, "Requested empty Payload", FAILURE); + stage_hc <= PUSH; + cnt <= 0; + else + stage_hc <= IDLE; + end if; + when PUSH => + if (ready_in_hc = '1') then + cnt <= cnt + 1; + if (cnt = stimulus.length-1) then + stage_hc <= IDLE; + end if; + end if; + when INVALID => + stage_hc <= IDLE; + when others => + null; + end case; + end if; + + -- DEFAULT + ack_hc <= '0'; + valid_in_hc <= '0'; + data_in_hc <= (others => '0'); + last_word_in_hc <= '0'; + done_hc <= '0'; + ret_hc <= ERROR; + + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + end if; + when DONE => + done_hc <= '1'; + ret_hc <= OK; + when PUSH => + valid_in_hc <= '1'; + data_in_hc <= stimulus.data(cnt); + last_word_in_hc <= stimulus.last(cnt); + when INVALID => + done_hc <= '1'; + ret_hc <= INVALID; + when others => + null; + end case; + end process; + + output_check_prc : process(all) + begin + if (SB_out.empty) then + out_check_done <= '1'; + else + out_check_done <= '0'; + end if; + if rising_edge(clk) then + if (wr_sig = '1') then + SB_out.Check(data_out); + end if; + end if; + end process; + + watchdog : process + begin + wait for 1 ms; + Alert("Test timeout", FAILURE); + std.env.stop; + end process; + +end architecture; \ No newline at end of file diff --git a/src/Tests/Level_1/L1_rtps_writer_test1_trkdp.vhd b/src/Tests/Level_1/L1_rtps_writer_test1_trkdp.vhd new file mode 100644 index 0000000..414883f --- /dev/null +++ b/src/Tests/Level_1/L1_rtps_writer_test1_trkdp.vhd @@ -0,0 +1,1218 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; -- Utility Library +context osvvm.OsvvmContext; + +use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; +use work.rtps_test_package.all; + +-- This testbench tests the RTPS Message generation of the RTPS Writer (DATA and GAP Generation). +-- This testbench covers following: +-- * (Best Effort/Transient Local/Expecting Inline Qos) Remote Readers +-- * New Data Push +-- * ACK Handling +-- * NACK/Request Handling + +entity L1_rtps_writer_test1_trkdp is +end entity; + +architecture testbench of L1_rtps_writer_test1_trkdp is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_ENDPOINTS : natural := 5; + constant MAX_CC : natural := 10; + + -- *TYPE DECLARATION* + type SEND_STAGE_TYPE is (IDLE, BUSY); + type TEST_CC_ARRAY_TYPE is array (0 to MAX_CC-1) of CACHE_CHANGE_TYPE; + type HC_STAGE_TYPE is (IDLE, PUSH, DONE, INVALID); + + -- *SIGNAL DECLARATION* + signal clk, empty_user, empty_meta, rd_user, rd_meta, last_word_in_user, last_word_in_meta, last_word_in_hc, last_word_out_rtps : std_logic := '0'; + signal reset : std_logic := '1'; + signal data_in_user, data_in_meta, data_out, data_in_hc : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal wr_sig, full, data_available : std_logic := '0'; + signal ready_in_hc, valid_in_hc, ack_hc, done_hc, get_data_hc, start_hc : std_logic := '0'; + signal seq_nr_hc : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + signal stim_stage_user, stim_stage_meta : SEND_STAGE_TYPE := IDLE; + signal opcode_hc : HISTORY_CACHE_OPCODE_TYPE := NOP; + signal ret_hc : HISTORY_CACHE_RESPONSE_TYPE := ERROR; + signal cc_instance_handle : INSTANCE_HANDLE_TYPE := HANDLE_NIL; + signal cc_kind : CACHE_CHANGE_KIND_TYPE := ALIVE; + signal cc_source_timestamp : TIME_TYPE := TIME_INVALID; + signal cc_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + shared variable stimulus_user, stimulus_meta, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent_user, packet_sent_meta : std_logic := '0'; + signal cnt_stim_meta, cnt_stim_user, count : natural := 0; + signal start_meta, start_user : std_logic := '0'; + shared variable SB_out, SB_hc : osvvm.ScoreBoardPkg_slv.ScoreBoardPType; + signal stim_done, out_check_done, hc_check_done, test_done : std_logic := '0'; + signal test_time : TIME_TYPE := TIME_ZERO; + signal fifo_in, fifo_out : std_logic_vector(WORD_WIDTH downto 0) := (others => '0'); + signal fifo_wr, fifo_empty, fifo_full : std_logic := '0'; + signal rtps_out_data : RTPS_OUT_DATA_TYPE := (others => (others => '0')); + signal rtps_out_rd, rtps_out_last_word_in, rtps_out_empty : std_logic_vector(0 to NUM_ENDPOINTS) := (others => '0'); + signal test_cc : TEST_CC_ARRAY_TYPE := (others => DEFAULT_CACHE_CHANGE); + -- Signal containing the current fill level of the test_cc array + signal test_cc_fill : natural := 0; + signal stage_hc : HC_STAGE_TYPE := IDLE; + signal new_cc : std_logic := '0'; + signal cnt : natural := 0; + + -- *FUNCTION DECLARATION* + function gen_sn(input : natural) return SEQUENCENUMBER_TYPE is + variable ret : SEQUENCENUMBER_TYPE; + begin + ret(0) := (others => '0'); + ret(1) := unsigned(int(input, WORD_WIDTH)); + return ret; + end function; + +begin + + -- Unit Under Test + uut : entity work.rtps_writer(arch) + generic map ( + RELIABILTY_QOS => RELIABLE_RELIABILITY_QOS, + LIVELINESS_QOS => AUTOMATIC_LIVELINESS_QOS, + DURABILITY_QOS => TRANSIENT_LOCAL_DURABILITY_QOS, + DESTINATION_ORDER_QOS => BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS, + ACKNACK_RESPONSE_DELAY => gen_duration(1,0), + ACKNACK_SUPPRESSION_DELAY => DURATION_ZERO, + LEASE_DURATION => DURATION_INFINITE, + HEARTBEAT_PERIOD => DURATION_INFINITE, + ENTITYID => DEFAULT_WRITER_ENTITYID, + WITH_KEY => TRUE, + PUSH_MODE => TRUE, + INLINE_QOS => gen_inline_qos(NUM_READERS+7), + MAX_REMOTE_ENDPOINTS => MAX_REMOTE_ENDPOINTS + ) + port map ( + clk => clk, + reset => reset, + time => test_time, + empty_user => empty_user or packet_sent_user, + rd_user => rd_user, + data_in_user => data_in_user, + last_word_in_user => last_word_in_user, + empty_meta => empty_meta or packet_sent_meta, + rd_meta => rd_meta, + data_in_meta => data_in_meta, + last_word_in_meta => last_word_in_meta, + alive_sig => open, + wr_rtps => fifo_wr, + full_rtps => fifo_full, + last_word_out_rtps => fifo_in(WORD_WIDTH), + data_out_rtps => fifo_in(WORD_WIDTH-1 downto 0), + assert_liveliness => '0', + data_available => data_available, + start_hc => start_hc, + opcode_hc => opcode_hc, + ack_hc => ack_hc, + seq_nr_hc => seq_nr_hc, + done_hc => done_hc, + ret_hc => ret_hc, + get_data_hc => get_data_hc, + data_in_hc => data_in_hc, + valid_in_hc => valid_in_hc, + ready_in_hc => ready_in_hc, + last_word_in_hc => last_word_in_hc, + cc_instance_handle => cc_instance_handle, + cc_kind => cc_kind, + cc_source_timestamp => cc_source_timestamp, + cc_seq_nr => cc_seq_nr + ); + + fifo_inst : entity work.FWFT_FIFO(arch) + generic map ( + FIFO_DEPTH => 2, + DATA_WIDTH => WORD_WIDTH+1 + ) + port map + ( + reset => reset, + clk => clk, + data_in => fifo_in, + write => fifo_wr, + read => rtps_out_rd(0), + data_out => fifo_out, + empty => fifo_empty, + full => fifo_full, + free => open + ); + + rtps_out_data <= (0 => fifo_out(WORD_WIDTH-1 downto 0), others => (others => '0')); + rtps_out_last_word_in <= (0 => fifo_out(WORD_WIDTH), others => '0'); + rtps_out_empty <= (0 => fifo_empty, others => '1'); + + rtps_out_inst : entity work.rtps_out(arch) + port map ( + clk => clk, + reset => reset, + data_in => rtps_out_data, + last_word_in=> rtps_out_last_word_in, + rd => rtps_out_rd, + empty => rtps_out_empty, + data_out => data_out, + wr => wr_sig, + full => full + ); + + + stimulus_prc : process + variable RV : RandomPType; + variable e0, e1, e2, e3, e4, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + variable sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable cc : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + variable OUT_HEADER : OUTPUT_HEADER_TYPE := DEFAULT_OUTPUT_HEADER; + variable rtps_header : RTPS_HEADER_TYPE := DEFAULT_RTPS_HEADER; + + alias idle_sig is <>; + + -- Wrapper to use procedure as function + impure function gen_rand_loc_2 return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + gen_rand_loc(RV, ret); + return ret; + end function; + + impure function gen_rand_entityid_2(reader : boolean) return std_logic_vector is + variable ret : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); + begin + gen_rand_entityid(RV, reader, ret); + return ret; + end function; + + impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is + variable ret : GUIDPREFIX_TYPE; + begin + ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH)); + return ret; + end function; + + impure function gen_key_hash return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := (others => (others => '0')); + begin + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := RV.RandSlv(WORD_WIDTH); + end loop; + return ret; + end function; + + impure function gen_payload return TEST_PACKET_TYPE is + variable ret : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + begin + for i in 0 to RV.RandInt(1,10) loop + ret.data(ret.length) := RV.RandSlv(WORD_WIDTH); + ret.length := ret.length + 1; + end loop; + ret.last(ret.length-1) := '1'; + return ret; + end function; + + procedure start_meta_test is + begin + start_meta <= '1'; + wait until rising_edge(clk); + start_meta <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure start_user_test is + begin + start_user <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure wait_on_meta_sent is + begin + wait until rising_edge(packet_sent_meta); + end procedure; + + procedure wait_on_user_sent is + begin + wait until rising_edge(packet_sent_user); + end procedure; + + procedure wait_on_out_check is + begin + if (out_check_done /= '1') then + wait until out_check_done = '1'; + end if; + end procedure; + + procedure wait_on_hc_check is + begin + if (hc_check_done /= '1') then + wait until hc_check_done = '1'; + end if; + end procedure; + + procedure wait_on_completion is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + + procedure wait_on_idle is + begin + if (idle_sig /= '1') then + wait until idle_sig = '1'; + end if; + end procedure; + + procedure push_hc(opcode : in HISTORY_CACHE_OPCODE_TYPE; sn : in SEQUENCENUMBER_TYPE) is + begin + SB_hc.push(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode),WORD_WIDTH))); + SB_hc.push(std_logic_vector(sn(0))); + SB_hc.push(std_logic_vector(sn(1))); + end procedure; + + procedure gen_header(endpoint : in ENDPOINT_DATA_TYPE) is + begin + reference := EMPTY_TEST_PACKET; + -- OUTPUT HEADER + OUT_HEADER := DEFAULT_OUTPUT_HEADER; + OUT_HEADER := (dest => get_loc(endpoint), src => DEST_LOC.user.locator(1)); + gen_output_header(OUT_HEADER, reference); + -- RTPS HEADER + rtps_header := DEFAULT_RTPS_HEADER; + rtps_header.guidPrefix := GUIDPREFIX; + gen_rtps_header(rtps_header, reference); + end procedure; + + procedure gen_data(endpoint : in ENDPOINT_DATA_TYPE; ref : in CACHE_CHANGE_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.submessageLength := (others => '0'); + sub.writerSN := ref.seq_nr; + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1' when (ref.kind = ALIVE) else '0'; + sub.flags(SUBMESSAGE_KEY_FLAG_POS) := '1' when (ref.kind /= ALIVE) else '0'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + gen_inline_qos(ref, gen_endpoint(NUM_READERS+7), (endpoint.expectsInlineQoS(0) = '1'), '0', sub.inlineQos); + gen_sentinel(sub.inlineQos); + assert (ref.payload /= EMPTY_TEST_PACKET) severity FAILURE; + sub.data := ref.payload; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_ts(ts : TIME_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_INFO_TS; + sub.timestamp := ts; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_gap(first : SEQUENCENUMBER_TYPE; last : SEQUENCENUMBER_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.gapStart := first; + sub.gapList := (base => last, numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_submessage(sub, reference); + end procedure; + + procedure push_reference is + begin + fix_output_packet(reference); + for i in 0 to reference.length-1 loop + SB_out.Push(reference.data(i)); + end loop; + end procedure; + + begin + + SetAlertLogName("rtps_writer (Transient Local, Reliable, Keyed, By Reception Timestamp, Push Mode) - Level 1 - RTPS Output (DATA & GAP)"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- Endpoint 0 + e0 := DEFAULT_ENDPOINT_DATA; + e0.nr := 0; + e0.match := MATCH; + e0.entityid := RV.RandSlv(ENTITYID_WIDTH); + e0.participant.guidPrefix := gen_rand_guid_prefix; + e0.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 1 + e1 := DEFAULT_ENDPOINT_DATA; + e1.nr := 1; + e1.match := MATCH; + e1.entityid := RV.RandSlv(ENTITYID_WIDTH); + e1.participant.guidPrefix := gen_rand_guid_prefix; + e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; + -- Endpoint 2 + e2 := DEFAULT_ENDPOINT_DATA; + e2.nr := 2; + e2.match := MATCH; + e2.entityid := RV.RandSlv(ENTITYID_WIDTH); + e2.participant.guidPrefix := gen_rand_guid_prefix; + e2.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e2.expectsInlineQoS(0) := '1'; + -- Endpoint 3 + e3 := DEFAULT_ENDPOINT_DATA; + e3.nr := 3; + e3.match := MATCH; + e3.entityid := RV.RandSlv(ENTITYID_WIDTH); + e3.participant.guidPrefix := gen_rand_guid_prefix; + e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e3.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + -- Endpoint 4 + e4 := DEFAULT_ENDPOINT_DATA; + e4.nr := 4; + e4.match := MATCH; + e4.entityid := RV.RandSlv(ENTITYID_WIDTH); + e4.participant.guidPrefix := gen_rand_guid_prefix; + e4.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e4.expectsInlineQoS(0) := '1'; + e4.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + e4.reliability := BEST_EFFORT_RELIABILITY_QOS; + + Log("Initiating Test", INFO); + Log("Current Time: 0s", INFO); + count <= 1; + test_time <= TIME_ZERO; + new_cc <= '0'; + stim_done <= '0'; + start_meta <= '0'; + start_user <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + + Log("Insert Endpoint 0,1", INFO); + gen_endpoint_match_frame(e0, stimulus_meta); + gen_endpoint_match_frame(e1, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 1] (Send DATA to Endpoint 0,1)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(1); + test_cc(0).src_timestamp <= gen_duration(1,0); + test_cc(0).payload <= gen_payload; + test_cc_fill <= 1; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <2] (Global ACK SN 1)", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(1)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 2,3] (Send DATA to Endpoint 0,1)", INFO); + test_cc(1).kind <= ALIVE; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(2); + test_cc(1).src_timestamp <= gen_duration(2,0); + test_cc(1).payload <= gen_payload; + test_cc(2).kind <= ALIVE; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(3); + test_cc(2).src_timestamp <= gen_duration(3,0); + test_cc(2).payload <= gen_payload; + test_cc_fill <= 3; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 2,3 (Send Historical DATA to Endpoint 3, Reset Global ACK SN 1,2,3)", INFO); + gen_endpoint_match_frame(e2, stimulus_meta); + gen_endpoint_match_frame(e3, stimulus_meta); + push_hc(NACK_CACHE_CHANGE, gen_sn(1)); + push_hc(NACK_CACHE_CHANGE, gen_sn(2)); + push_hc(NACK_CACHE_CHANGE, gen_sn(3)); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + + gen_header(e3); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <4]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <2] (Global ACK SN 1)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(1)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 4] (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(3).kind <= ALIVE_FILTERED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(4); + test_cc(3).src_timestamp <= gen_duration(4,0); + test_cc(3).payload <= gen_payload; + test_cc_fill <= 4; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <5] (Global ACK SN 2,3)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(2)); + push_hc(ACK_CACHE_CHANGE, gen_sn(3)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <5]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <5] (Global ACK SN 4)", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(4)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 10,11,15,46,50], Remove Cache Change [SN 1,2] (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(0) <= test_cc(2); + test_cc(1) <= test_cc(3); + test_cc(2).kind <= ALIVE; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(10); + test_cc(2).src_timestamp <= gen_duration(5,0); + test_cc(2).payload <= gen_payload; + test_cc(3).kind <= NOT_ALIVE_DISPOSED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(11); + test_cc(3).src_timestamp <= gen_duration(6,0); + test_cc(3).payload <= gen_payload; + test_cc(4).kind <= NOT_ALIVE_UNREGISTERED; + test_cc(4).instance <= gen_key_hash; + test_cc(4).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(4).seq_nr <= gen_sn(15); + test_cc(4).src_timestamp <= gen_duration(7,0); + test_cc(4).payload <= gen_payload; + test_cc(5).kind <= NOT_ALIVE_DISPOSED; + test_cc(5).instance <= gen_key_hash; + test_cc(5).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(5).seq_nr <= gen_sn(37); + test_cc(5).src_timestamp <= gen_duration(8,0); + test_cc(5).payload <= gen_payload; + test_cc(6).kind <= ALIVE; + test_cc(6).instance <= gen_key_hash; + test_cc(6).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(6).seq_nr <= gen_sn(50); + test_cc(6).src_timestamp <= gen_duration(9,0); + test_cc(6).payload <= gen_payload; + test_cc_fill <= 7; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(6)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(6)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(6)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(6)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [Request SN 10,15,37]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(35, CDR_LONG_WIDTH), bitmap => (5 => '1', 10 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1s", INFO); + Log("Send SN 10,15,37 to Endpoint 0", INFO); + test_time <= gen_duration(1,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(5)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <15]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <10, Request SN 10]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(10), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1.5s", INFO); + test_time <= gen_duration(1,500); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <15, Request SN 15,16,47]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(33, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 2s", INFO); + Log("Send SN 15 to Endpoint 0 (GAP for SN 16, and ignore Request for SN 47)", INFO); + test_time <= gen_duration(2,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e2); + gen_data(e2, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_gap(gen_sn(16), gen_sn(17)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [Request SN 1-32]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(32, CDR_LONG_WIDTH), bitmap => (0 to 31 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 3s", INFO); + Log("Send SN 3,4,10,11,15 to Endpoint 3 (GAPs for Rest)", INFO); + test_time <= gen_duration(3,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e3); + gen_gap(gen_sn(1), gen_sn(3)); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(5), gen_sn(10)); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(12), gen_sn(15)); + gen_data(e3, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(16), gen_sn(32)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 4 (Send Historical DATA to Endpoint 4)", INFO); + gen_endpoint_match_frame(e4, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + + gen_header(e4); + gen_data(e4, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_data(e4, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(5), gen_sn(10)); + gen_data(e4, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_data(e4, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(12), gen_sn(15)); + gen_data(e4, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(16), gen_sn(37)); + gen_data(e4, test_cc(5)); + push_reference; + wait_on_out_check; + gen_header(e4); + gen_gap(gen_sn(38), gen_sn(50)); + gen_data(e4, test_cc(6)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <15] (Global ACK SN 5,6,7,8,9,10,11,12,13,14)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(ACK_CACHE_CHANGE, gen_sn(5)); + push_hc(ACK_CACHE_CHANGE, gen_sn(6)); + push_hc(ACK_CACHE_CHANGE, gen_sn(7)); + push_hc(ACK_CACHE_CHANGE, gen_sn(8)); + push_hc(ACK_CACHE_CHANGE, gen_sn(9)); + push_hc(ACK_CACHE_CHANGE, gen_sn(10)); + push_hc(ACK_CACHE_CHANGE, gen_sn(11)); + push_hc(ACK_CACHE_CHANGE, gen_sn(12)); + push_hc(ACK_CACHE_CHANGE, gen_sn(13)); + push_hc(ACK_CACHE_CHANGE, gen_sn(14)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + stim_done <= '1'; + wait_on_completion; + TranscriptOpen(RESULTS_FILE, APPEND_MODE); + SetTranscriptMirror; + ReportAlerts; + TranscriptClose; + std.env.stop; + wait; + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + empty_meta_prc : process + begin + empty_meta <= '0'; + wait until rd_meta = '1'; + wait until rising_edge(clk); + empty_meta <= '1'; + wait until rising_edge(clk); + end process; + + empty_user_prc : process + begin + empty_user <= '0'; + wait until rd_user = '1'; + wait until rising_edge(clk); + empty_user <= '1'; + wait until rising_edge(clk); + end process; + + rtps_full_prc : process + begin + full <= '0'; + wait until wr_sig = '1'; + wait until rising_edge(clk); + full <= '1'; + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(empty_meta = '1' and rd_meta = '1', "Input FIFO read signal high while empty signal high (meta)", ERROR); + alertif(empty_user = '1' and rd_user = '1', "Input FIFO read signal high while empty signal high (user)", ERROR); + alertif(full = '1' and wr_sig = '1', "Output FIFO write signal high while full signal high", ERROR); + end if; + end process; + + input_meta_prc : process(all) + begin + data_in_meta <= stimulus_meta.data(cnt_stim_meta); + last_word_in_meta <= stimulus_meta.last(cnt_stim_meta); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_meta <= 0; + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + else + case (stim_stage_meta) is + when IDLE => + if (start_meta = '1' and stimulus_meta.length /= 0) then + stim_stage_meta <= BUSY; + packet_sent_meta <= '0'; + end if; + when BUSY => + if (rd_meta = '1') then + if (cnt_stim_meta = stimulus_meta.length-1) then + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + cnt_stim_meta <= 0; + else + cnt_stim_meta <= cnt_stim_meta + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + input_user_prc : process(all) + begin + data_in_user <= stimulus_user.data(cnt_stim_user); + last_word_in_user <= stimulus_user.last(cnt_stim_user); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_user <= 0; + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + else + case (stim_stage_user) is + when IDLE => + if (start_user = '1' and stimulus_user.length /= 0) then + stim_stage_user <= BUSY; + packet_sent_user <= '0'; + end if; + when BUSY => + if (rd_user = '1') then + if (cnt_stim_user = stimulus_user.length-1) then + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + cnt_stim_user <= 0; + else + cnt_stim_user <= cnt_stim_user + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_out.empty and SB_hc.empty) then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + hc_prc : process (all) + variable stimulus : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + variable bool : boolean := FALSE; + begin + if (new_cc = '1') then + data_available <= '1'; + end if; + if rising_edge(clk) then + hc_check_done <= '0'; + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + case (opcode_hc) is + when GET_CACHE_CHANGE => + bool := FALSE; + for i in 0 to test_cc_fill-1 loop + if (test_cc(i).seq_nr = seq_nr_hc) then + cc_instance_handle <= test_cc(i).instance; + cc_source_timestamp <= test_cc(i).src_timestamp; + cc_kind <= test_cc(i).kind; + stimulus := test_cc(i).payload; + stage_hc <= DONE; + bool := TRUE; + end if; + end loop; + if (not bool) then + stage_hc <= INVALID; + end if; + when GET_MIN_SN => + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(0).seq_nr; + stage_hc <= DONE; + when GET_MAX_SN => + data_available <= '0'; + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(test_cc_fill-1).seq_nr when (test_cc_fill /= 0) else SEQUENCENUMBER_UNKNOWN; + stage_hc <= DONE; + when others => + SB_hc.Check(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode_hc), WORD_WIDTH))); + SB_hc.Check(std_logic_vector(seq_nr_hc(0))); + SB_hc.Check(std_logic_vector(seq_nr_hc(1))); + hc_check_done <= '1'; + stage_hc <= DONE; + end case; + end if; + when DONE => + if (get_data_hc = '1') then + alertif(stimulus = EMPTY_TEST_PACKET, "Requested empty Payload", FAILURE); + stage_hc <= PUSH; + cnt <= 0; + else + stage_hc <= IDLE; + end if; + when PUSH => + if (ready_in_hc = '1') then + cnt <= cnt + 1; + if (cnt = stimulus.length-1) then + stage_hc <= IDLE; + end if; + end if; + when INVALID => + stage_hc <= IDLE; + when others => + null; + end case; + end if; + + -- DEFAULT + ack_hc <= '0'; + valid_in_hc <= '0'; + data_in_hc <= (others => '0'); + last_word_in_hc <= '0'; + done_hc <= '0'; + ret_hc <= ERROR; + + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + end if; + when DONE => + done_hc <= '1'; + ret_hc <= OK; + when PUSH => + valid_in_hc <= '1'; + data_in_hc <= stimulus.data(cnt); + last_word_in_hc <= stimulus.last(cnt); + when INVALID => + done_hc <= '1'; + ret_hc <= INVALID; + when others => + null; + end case; + end process; + + output_check_prc : process(all) + begin + if (SB_out.empty) then + out_check_done <= '1'; + else + out_check_done <= '0'; + end if; + if rising_edge(clk) then + if (wr_sig = '1') then + SB_out.Check(data_out); + end if; + end if; + end process; + + watchdog : process + begin + wait for 1 ms; + Alert("Test timeout", FAILURE); + std.env.stop; + end process; + +end architecture; \ No newline at end of file diff --git a/src/Tests/Level_1/L1_rtps_writer_test1_vbkdp.vhd b/src/Tests/Level_1/L1_rtps_writer_test1_vbkdp.vhd new file mode 100644 index 0000000..2eb570a --- /dev/null +++ b/src/Tests/Level_1/L1_rtps_writer_test1_vbkdp.vhd @@ -0,0 +1,922 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; -- Utility Library +context osvvm.OsvvmContext; + +use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; +use work.rtps_test_package.all; + +-- This testbench tests the RTPS Message generation of the RTPS Writer (DATA and GAP Generation). +-- This testbench covers following: +-- * (Best Effort/Transient Local/Expecting Inline Qos) Remote Readers +-- * New Data Push +-- * ACK Handling +-- * NACK/Request Handling + +entity L1_rtps_writer_test1_vbkdp is +end entity; + +architecture testbench of L1_rtps_writer_test1_vbkdp is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_ENDPOINTS : natural := 5; + constant MAX_CC : natural := 10; + + -- *TYPE DECLARATION* + type SEND_STAGE_TYPE is (IDLE, BUSY); + type TEST_CC_ARRAY_TYPE is array (0 to MAX_CC-1) of CACHE_CHANGE_TYPE; + type HC_STAGE_TYPE is (IDLE, PUSH, DONE, INVALID); + + -- *SIGNAL DECLARATION* + signal clk, empty_user, empty_meta, rd_user, rd_meta, last_word_in_user, last_word_in_meta, last_word_in_hc, last_word_out_rtps : std_logic := '0'; + signal reset : std_logic := '1'; + signal data_in_user, data_in_meta, data_out, data_in_hc : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal wr_sig, full, data_available : std_logic := '0'; + signal ready_in_hc, valid_in_hc, ack_hc, done_hc, get_data_hc, start_hc : std_logic := '0'; + signal seq_nr_hc : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + signal stim_stage_user, stim_stage_meta : SEND_STAGE_TYPE := IDLE; + signal opcode_hc : HISTORY_CACHE_OPCODE_TYPE := NOP; + signal ret_hc : HISTORY_CACHE_RESPONSE_TYPE := ERROR; + signal cc_instance_handle : INSTANCE_HANDLE_TYPE := HANDLE_NIL; + signal cc_kind : CACHE_CHANGE_KIND_TYPE := ALIVE; + signal cc_source_timestamp : TIME_TYPE := TIME_INVALID; + signal cc_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + shared variable stimulus_user, stimulus_meta, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent_user, packet_sent_meta : std_logic := '0'; + signal cnt_stim_meta, cnt_stim_user, count : natural := 0; + signal start_meta, start_user : std_logic := '0'; + shared variable SB_out, SB_hc : osvvm.ScoreBoardPkg_slv.ScoreBoardPType; + signal stim_done, out_check_done, hc_check_done, test_done : std_logic := '0'; + signal test_time : TIME_TYPE := TIME_ZERO; + signal fifo_in, fifo_out : std_logic_vector(WORD_WIDTH downto 0) := (others => '0'); + signal fifo_wr, fifo_empty, fifo_full : std_logic := '0'; + signal rtps_out_data : RTPS_OUT_DATA_TYPE := (others => (others => '0')); + signal rtps_out_rd, rtps_out_last_word_in, rtps_out_empty : std_logic_vector(0 to NUM_ENDPOINTS) := (others => '0'); + signal test_cc : TEST_CC_ARRAY_TYPE := (others => DEFAULT_CACHE_CHANGE); + -- Signal containing the current fill level of the test_cc array + signal test_cc_fill : natural := 0; + signal stage_hc : HC_STAGE_TYPE := IDLE; + signal new_cc : std_logic := '0'; + signal cnt : natural := 0; + + -- *FUNCTION DECLARATION* + function gen_sn(input : natural) return SEQUENCENUMBER_TYPE is + variable ret : SEQUENCENUMBER_TYPE; + begin + ret(0) := (others => '0'); + ret(1) := unsigned(int(input, WORD_WIDTH)); + return ret; + end function; + +begin + + -- Unit Under Test + uut : entity work.rtps_writer(arch) + generic map ( + RELIABILTY_QOS => BEST_EFFORT_RELIABILITY_QOS, + LIVELINESS_QOS => AUTOMATIC_LIVELINESS_QOS, + DURABILITY_QOS => VOLATILE_DURABILITY_QOS, + DESTINATION_ORDER_QOS => BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS, + ACKNACK_RESPONSE_DELAY => gen_duration(1,0), + ACKNACK_SUPPRESSION_DELAY => DURATION_ZERO, + LEASE_DURATION => DURATION_INFINITE, + HEARTBEAT_PERIOD => DURATION_INFINITE, + ENTITYID => DEFAULT_WRITER_ENTITYID, + WITH_KEY => TRUE, + PUSH_MODE => TRUE, + INLINE_QOS => gen_inline_qos(NUM_READERS+7), + MAX_REMOTE_ENDPOINTS => MAX_REMOTE_ENDPOINTS + ) + port map ( + clk => clk, + reset => reset, + time => test_time, + empty_user => empty_user or packet_sent_user, + rd_user => rd_user, + data_in_user => data_in_user, + last_word_in_user => last_word_in_user, + empty_meta => empty_meta or packet_sent_meta, + rd_meta => rd_meta, + data_in_meta => data_in_meta, + last_word_in_meta => last_word_in_meta, + alive_sig => open, + wr_rtps => fifo_wr, + full_rtps => fifo_full, + last_word_out_rtps => fifo_in(WORD_WIDTH), + data_out_rtps => fifo_in(WORD_WIDTH-1 downto 0), + assert_liveliness => '0', + data_available => data_available, + start_hc => start_hc, + opcode_hc => opcode_hc, + ack_hc => ack_hc, + seq_nr_hc => seq_nr_hc, + done_hc => done_hc, + ret_hc => ret_hc, + get_data_hc => get_data_hc, + data_in_hc => data_in_hc, + valid_in_hc => valid_in_hc, + ready_in_hc => ready_in_hc, + last_word_in_hc => last_word_in_hc, + cc_instance_handle => cc_instance_handle, + cc_kind => cc_kind, + cc_source_timestamp => cc_source_timestamp, + cc_seq_nr => cc_seq_nr + ); + + fifo_inst : entity work.FWFT_FIFO(arch) + generic map ( + FIFO_DEPTH => 2, + DATA_WIDTH => WORD_WIDTH+1 + ) + port map + ( + reset => reset, + clk => clk, + data_in => fifo_in, + write => fifo_wr, + read => rtps_out_rd(0), + data_out => fifo_out, + empty => fifo_empty, + full => fifo_full, + free => open + ); + + rtps_out_data <= (0 => fifo_out(WORD_WIDTH-1 downto 0), others => (others => '0')); + rtps_out_last_word_in <= (0 => fifo_out(WORD_WIDTH), others => '0'); + rtps_out_empty <= (0 => fifo_empty, others => '1'); + + rtps_out_inst : entity work.rtps_out(arch) + port map ( + clk => clk, + reset => reset, + data_in => rtps_out_data, + last_word_in=> rtps_out_last_word_in, + rd => rtps_out_rd, + empty => rtps_out_empty, + data_out => data_out, + wr => wr_sig, + full => full + ); + + + stimulus_prc : process + variable RV : RandomPType; + variable e0, e1, e2, e3, e4, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + variable sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable cc : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + variable OUT_HEADER : OUTPUT_HEADER_TYPE := DEFAULT_OUTPUT_HEADER; + variable rtps_header : RTPS_HEADER_TYPE := DEFAULT_RTPS_HEADER; + + alias idle_sig is <>; + + -- Wrapper to use procedure as function + impure function gen_rand_loc_2 return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + gen_rand_loc(RV, ret); + return ret; + end function; + + impure function gen_rand_entityid_2(reader : boolean) return std_logic_vector is + variable ret : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); + begin + gen_rand_entityid(RV, reader, ret); + return ret; + end function; + + impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is + variable ret : GUIDPREFIX_TYPE; + begin + ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH)); + return ret; + end function; + + impure function gen_key_hash return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := (others => (others => '0')); + begin + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := RV.RandSlv(WORD_WIDTH); + end loop; + return ret; + end function; + + impure function gen_payload return TEST_PACKET_TYPE is + variable ret : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + begin + for i in 0 to RV.RandInt(1,10) loop + ret.data(ret.length) := RV.RandSlv(WORD_WIDTH); + ret.length := ret.length + 1; + end loop; + ret.last(ret.length-1) := '1'; + return ret; + end function; + + procedure start_meta_test is + begin + start_meta <= '1'; + wait until rising_edge(clk); + start_meta <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure start_user_test is + begin + start_user <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure wait_on_meta_sent is + begin + wait until rising_edge(packet_sent_meta); + end procedure; + + procedure wait_on_user_sent is + begin + wait until rising_edge(packet_sent_user); + end procedure; + + procedure wait_on_out_check is + begin + if (out_check_done /= '1') then + wait until out_check_done = '1'; + end if; + end procedure; + + procedure wait_on_hc_check is + begin + if (hc_check_done /= '1') then + wait until hc_check_done = '1'; + end if; + end procedure; + + procedure wait_on_completion is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + + procedure wait_on_idle is + begin + if (idle_sig /= '1') then + wait until idle_sig = '1'; + end if; + end procedure; + + procedure push_hc(opcode : in HISTORY_CACHE_OPCODE_TYPE; sn : in SEQUENCENUMBER_TYPE) is + begin + SB_hc.push(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode),WORD_WIDTH))); + SB_hc.push(std_logic_vector(sn(0))); + SB_hc.push(std_logic_vector(sn(1))); + end procedure; + + procedure gen_header(endpoint : in ENDPOINT_DATA_TYPE) is + begin + reference := EMPTY_TEST_PACKET; + -- OUTPUT HEADER + OUT_HEADER := DEFAULT_OUTPUT_HEADER; + OUT_HEADER := (dest => get_loc(endpoint), src => DEST_LOC.user.locator(1)); + gen_output_header(OUT_HEADER, reference); + -- RTPS HEADER + rtps_header := DEFAULT_RTPS_HEADER; + rtps_header.guidPrefix := GUIDPREFIX; + gen_rtps_header(rtps_header, reference); + end procedure; + + procedure gen_data(endpoint : in ENDPOINT_DATA_TYPE; ref : in CACHE_CHANGE_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.submessageLength := (others => '0'); + sub.writerSN := ref.seq_nr; + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1' when (ref.kind = ALIVE) else '0'; + sub.flags(SUBMESSAGE_KEY_FLAG_POS) := '1' when (ref.kind /= ALIVE) else '0'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + gen_inline_qos(ref, gen_endpoint(NUM_READERS+7), (endpoint.expectsInlineQoS(0) = '1'), '0', sub.inlineQos); + gen_sentinel(sub.inlineQos); + assert (ref.payload /= EMPTY_TEST_PACKET) severity FAILURE; + sub.data := ref.payload; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_ts(ts : TIME_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_INFO_TS; + sub.timestamp := ts; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_gap(first : SEQUENCENUMBER_TYPE; last : SEQUENCENUMBER_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.gapStart := first; + sub.gapList := (base => last, numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_submessage(sub, reference); + end procedure; + + procedure push_reference is + begin + fix_output_packet(reference); + for i in 0 to reference.length-1 loop + SB_out.Push(reference.data(i)); + end loop; + end procedure; + + begin + + SetAlertLogName("rtps_writer (Volatile, Best Effort, Keyed, By Reception Timestamp, Push Mode) - Level 1 - RTPS Output (DATA & GAP)"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- Endpoint 0 + e0 := DEFAULT_ENDPOINT_DATA; + e0.nr := 0; + e0.match := MATCH; + e0.entityid := RV.RandSlv(ENTITYID_WIDTH); + e0.participant.guidPrefix := gen_rand_guid_prefix; + e0.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 1 + e1 := DEFAULT_ENDPOINT_DATA; + e1.nr := 1; + e1.match := MATCH; + e1.entityid := RV.RandSlv(ENTITYID_WIDTH); + e1.participant.guidPrefix := gen_rand_guid_prefix; + e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; + -- Endpoint 2 + e2 := DEFAULT_ENDPOINT_DATA; + e2.nr := 2; + e2.match := MATCH; + e2.entityid := RV.RandSlv(ENTITYID_WIDTH); + e2.participant.guidPrefix := gen_rand_guid_prefix; + e2.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e2.expectsInlineQoS(0) := '1'; + -- Endpoint 3 + e3 := DEFAULT_ENDPOINT_DATA; + e3.nr := 3; + e3.match := MATCH; + e3.entityid := RV.RandSlv(ENTITYID_WIDTH); + e3.participant.guidPrefix := gen_rand_guid_prefix; + e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e3.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + -- Endpoint 4 + e4 := DEFAULT_ENDPOINT_DATA; + e4.nr := 4; + e4.match := MATCH; + e4.entityid := RV.RandSlv(ENTITYID_WIDTH); + e4.participant.guidPrefix := gen_rand_guid_prefix; + e4.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e4.expectsInlineQoS(0) := '1'; + e4.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + e4.reliability := BEST_EFFORT_RELIABILITY_QOS; + + Log("Initiating Test", INFO); + Log("Current Time: 0s", INFO); + count <= 1; + test_time <= TIME_ZERO; + new_cc <= '0'; + stim_done <= '0'; + start_meta <= '0'; + start_user <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + + Log("Insert Endpoint 0,1", INFO); + gen_endpoint_match_frame(e0, stimulus_meta); + gen_endpoint_match_frame(e1, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 1] (Send DATA to Endpoint 0,1 and Remove)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(1); + test_cc(0).src_timestamp <= gen_duration(1,0); + test_cc(0).payload <= gen_payload; + test_cc_fill <= 1; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + push_hc(REMOVE_CACHE_CHANGE, gen_sn(1)); + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 2,3] (Send DATA to Endpoint 0,1 and Remove)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(2); + test_cc(0).src_timestamp <= gen_duration(2,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= ALIVE; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(3); + test_cc(1).src_timestamp <= gen_duration(3,0); + test_cc(1).payload <= gen_payload; + test_cc_fill <= 2; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + + push_hc(REMOVE_CACHE_CHANGE, gen_sn(2)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(3)); + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + wait_on_idle; + test_cc_fill <= 0; + + Log("Insert Endpoint 2,3", INFO); + gen_endpoint_match_frame(e2, stimulus_meta); + gen_endpoint_match_frame(e3, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 4] (Send DATA to Endpoint 0,1,2,3 and Remove)", INFO); + test_cc(0).kind <= ALIVE_FILTERED; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(4); + test_cc(0).src_timestamp <= gen_duration(4,0); + test_cc(0).payload <= gen_payload; + test_cc_fill <= 1; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + push_hc(REMOVE_CACHE_CHANGE, gen_sn(4)); + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 10,11,15,46,50], (Send DATA to Endpoint 0,1,2,3 and Remove)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(10); + test_cc(0).src_timestamp <= gen_duration(5,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= NOT_ALIVE_DISPOSED; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(11); + test_cc(1).src_timestamp <= gen_duration(6,0); + test_cc(1).payload <= gen_payload; + test_cc(2).kind <= NOT_ALIVE_UNREGISTERED; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(15); + test_cc(2).src_timestamp <= gen_duration(7,0); + test_cc(2).payload <= gen_payload; + test_cc(3).kind <= NOT_ALIVE_DISPOSED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(37); + test_cc(3).src_timestamp <= gen_duration(8,0); + test_cc(3).payload <= gen_payload; + test_cc(4).kind <= ALIVE; + test_cc(4).instance <= gen_key_hash; + test_cc(4).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(4).seq_nr <= gen_sn(50); + test_cc(4).src_timestamp <= gen_duration(9,0); + test_cc(4).payload <= gen_payload; + test_cc_fill <= 5; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + push_hc(REMOVE_CACHE_CHANGE, gen_sn(10)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(11)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(15)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(37)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(50)); + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(4)); + push_reference; + wait_on_out_check; + wait_on_idle; + test_cc_fill <= 0; + + Log("Endpoint 0 sent ACKNACK [Request SN 10,15,37]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(35, CDR_LONG_WIDTH), bitmap => (5 => '1', 10 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1s", INFO); + Log("Send SN 10,15,37 to Endpoint 0", INFO); + test_time <= gen_duration(1,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + wait_on_idle; + + Log("Insert Endpoint 4", INFO); + gen_endpoint_match_frame(e4, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + stim_done <= '1'; + wait_on_completion; + TranscriptOpen(RESULTS_FILE, APPEND_MODE); + SetTranscriptMirror; + ReportAlerts; + TranscriptClose; + std.env.stop; + wait; + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + empty_meta_prc : process + begin + empty_meta <= '0'; + wait until rd_meta = '1'; + wait until rising_edge(clk); + empty_meta <= '1'; + wait until rising_edge(clk); + end process; + + empty_user_prc : process + begin + empty_user <= '0'; + wait until rd_user = '1'; + wait until rising_edge(clk); + empty_user <= '1'; + wait until rising_edge(clk); + end process; + + rtps_full_prc : process + begin + full <= '0'; + wait until wr_sig = '1'; + wait until rising_edge(clk); + full <= '1'; + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(empty_meta = '1' and rd_meta = '1', "Input FIFO read signal high while empty signal high (meta)", ERROR); + alertif(empty_user = '1' and rd_user = '1', "Input FIFO read signal high while empty signal high (user)", ERROR); + alertif(full = '1' and wr_sig = '1', "Output FIFO write signal high while full signal high", ERROR); + end if; + end process; + + input_meta_prc : process(all) + begin + data_in_meta <= stimulus_meta.data(cnt_stim_meta); + last_word_in_meta <= stimulus_meta.last(cnt_stim_meta); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_meta <= 0; + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + else + case (stim_stage_meta) is + when IDLE => + if (start_meta = '1' and stimulus_meta.length /= 0) then + stim_stage_meta <= BUSY; + packet_sent_meta <= '0'; + end if; + when BUSY => + if (rd_meta = '1') then + if (cnt_stim_meta = stimulus_meta.length-1) then + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + cnt_stim_meta <= 0; + else + cnt_stim_meta <= cnt_stim_meta + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + input_user_prc : process(all) + begin + data_in_user <= stimulus_user.data(cnt_stim_user); + last_word_in_user <= stimulus_user.last(cnt_stim_user); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_user <= 0; + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + else + case (stim_stage_user) is + when IDLE => + if (start_user = '1' and stimulus_user.length /= 0) then + stim_stage_user <= BUSY; + packet_sent_user <= '0'; + end if; + when BUSY => + if (rd_user = '1') then + if (cnt_stim_user = stimulus_user.length-1) then + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + cnt_stim_user <= 0; + else + cnt_stim_user <= cnt_stim_user + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_out.empty and SB_hc.empty) then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + hc_prc : process (all) + variable stimulus : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + variable bool : boolean := FALSE; + begin + -- Data Setter + if (new_cc = '1') then + data_available <= '1'; + end if; + + if rising_edge(clk) then + hc_check_done <= '0'; + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + case (opcode_hc) is + when GET_CACHE_CHANGE => + bool := FALSE; + for i in 0 to test_cc_fill-1 loop + if (test_cc(i).seq_nr = seq_nr_hc) then + cc_instance_handle <= test_cc(i).instance; + cc_source_timestamp <= test_cc(i).src_timestamp; + cc_kind <= test_cc(i).kind; + stimulus := test_cc(i).payload; + stage_hc <= DONE; + bool := TRUE; + end if; + end loop; + if (not bool) then + stage_hc <= INVALID; + end if; + when GET_MIN_SN => + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(0).seq_nr; + stage_hc <= DONE; + when GET_MAX_SN => + data_available <= '0'; + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(test_cc_fill-1).seq_nr when (test_cc_fill /= 0) else SEQUENCENUMBER_UNKNOWN; + stage_hc <= DONE; + when others => + SB_hc.Check(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode_hc), WORD_WIDTH))); + SB_hc.Check(std_logic_vector(seq_nr_hc(0))); + SB_hc.Check(std_logic_vector(seq_nr_hc(1))); + hc_check_done <= '1'; + stage_hc <= DONE; + end case; + end if; + when DONE => + if (get_data_hc = '1') then + alertif(stimulus = EMPTY_TEST_PACKET, "Requested empty Payload", FAILURE); + stage_hc <= PUSH; + cnt <= 0; + else + stage_hc <= IDLE; + end if; + when PUSH => + if (ready_in_hc = '1') then + cnt <= cnt + 1; + if (cnt = stimulus.length-1) then + stage_hc <= IDLE; + end if; + end if; + when INVALID => + stage_hc <= IDLE; + when others => + null; + end case; + end if; + + -- DEFAULT + ack_hc <= '0'; + valid_in_hc <= '0'; + data_in_hc <= (others => '0'); + last_word_in_hc <= '0'; + done_hc <= '0'; + ret_hc <= ERROR; + + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + end if; + when DONE => + done_hc <= '1'; + ret_hc <= OK; + when PUSH => + valid_in_hc <= '1'; + data_in_hc <= stimulus.data(cnt); + last_word_in_hc <= stimulus.last(cnt); + when INVALID => + done_hc <= '1'; + ret_hc <= INVALID; + when others => + null; + end case; + end process; + + output_check_prc : process(all) + begin + if (SB_out.empty) then + out_check_done <= '1'; + else + out_check_done <= '0'; + end if; + if rising_edge(clk) then + if (wr_sig = '1') then + SB_out.Check(data_out); + end if; + end if; + end process; + + watchdog : process + begin + wait for 1 ms; + Alert("Test timeout", FAILURE); + std.env.stop; + end process; + +end architecture; \ No newline at end of file diff --git a/src/Tests/Level_1/L1_rtps_writer_test1_vrkdn.vhd b/src/Tests/Level_1/L1_rtps_writer_test1_vrkdn.vhd new file mode 100644 index 0000000..6a742c6 --- /dev/null +++ b/src/Tests/Level_1/L1_rtps_writer_test1_vrkdn.vhd @@ -0,0 +1,1222 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; -- Utility Library +context osvvm.OsvvmContext; + +use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; +use work.rtps_test_package.all; + +-- This testbench tests the RTPS Message generation of the RTPS Writer (DATA and GAP Generation). +-- This testbench covers following: +-- * (Best Effort/Transient Local/Expecting Inline Qos) Remote Readers +-- * New Data Push +-- * ACK Handling +-- * NACK/Request Handling + +entity L1_rtps_writer_test1_vrkdn is +end entity; + +architecture testbench of L1_rtps_writer_test1_vrkdn is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_ENDPOINTS : natural := 5; + constant MAX_CC : natural := 10; + + -- *TYPE DECLARATION* + type SEND_STAGE_TYPE is (IDLE, BUSY); + type TEST_CC_ARRAY_TYPE is array (0 to MAX_CC-1) of CACHE_CHANGE_TYPE; + type HC_STAGE_TYPE is (IDLE, PUSH, DONE, INVALID); + + -- *SIGNAL DECLARATION* + signal clk, empty_user, empty_meta, rd_user, rd_meta, last_word_in_user, last_word_in_meta, last_word_in_hc, last_word_out_rtps : std_logic := '0'; + signal reset : std_logic := '1'; + signal data_in_user, data_in_meta, data_out, data_in_hc : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal wr_sig, full, data_available : std_logic := '0'; + signal ready_in_hc, valid_in_hc, ack_hc, done_hc, get_data_hc, start_hc : std_logic := '0'; + signal seq_nr_hc : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + signal stim_stage_user, stim_stage_meta : SEND_STAGE_TYPE := IDLE; + signal opcode_hc : HISTORY_CACHE_OPCODE_TYPE := NOP; + signal ret_hc : HISTORY_CACHE_RESPONSE_TYPE := ERROR; + signal cc_instance_handle : INSTANCE_HANDLE_TYPE := HANDLE_NIL; + signal cc_kind : CACHE_CHANGE_KIND_TYPE := ALIVE; + signal cc_source_timestamp : TIME_TYPE := TIME_INVALID; + signal cc_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + shared variable stimulus_user, stimulus_meta, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent_user, packet_sent_meta : std_logic := '0'; + signal cnt_stim_meta, cnt_stim_user, count : natural := 0; + signal start_meta, start_user : std_logic := '0'; + shared variable SB_out, SB_hc : osvvm.ScoreBoardPkg_slv.ScoreBoardPType; + signal stim_done, out_check_done, hc_check_done, test_done : std_logic := '0'; + signal test_time : TIME_TYPE := TIME_ZERO; + signal fifo_in, fifo_out : std_logic_vector(WORD_WIDTH downto 0) := (others => '0'); + signal fifo_wr, fifo_empty, fifo_full : std_logic := '0'; + signal rtps_out_data : RTPS_OUT_DATA_TYPE := (others => (others => '0')); + signal rtps_out_rd, rtps_out_last_word_in, rtps_out_empty : std_logic_vector(0 to NUM_ENDPOINTS) := (others => '0'); + signal test_cc : TEST_CC_ARRAY_TYPE := (others => DEFAULT_CACHE_CHANGE); + -- Signal containing the current fill level of the test_cc array + signal test_cc_fill : natural := 0; + signal stage_hc : HC_STAGE_TYPE := IDLE; + signal new_cc : std_logic := '0'; + signal cnt : natural := 0; + + -- *FUNCTION DECLARATION* + function gen_sn(input : natural) return SEQUENCENUMBER_TYPE is + variable ret : SEQUENCENUMBER_TYPE; + begin + ret(0) := (others => '0'); + ret(1) := unsigned(int(input, WORD_WIDTH)); + return ret; + end function; + +begin + + -- Unit Under Test + uut : entity work.rtps_writer(arch) + generic map ( + RELIABILTY_QOS => RELIABLE_RELIABILITY_QOS, + LIVELINESS_QOS => AUTOMATIC_LIVELINESS_QOS, + DURABILITY_QOS => VOLATILE_DURABILITY_QOS, + DESTINATION_ORDER_QOS => BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS, + ACKNACK_RESPONSE_DELAY => gen_duration(1,0), + ACKNACK_SUPPRESSION_DELAY => DURATION_ZERO, + LEASE_DURATION => DURATION_INFINITE, + HEARTBEAT_PERIOD => DURATION_INFINITE, + ENTITYID => DEFAULT_WRITER_ENTITYID, + WITH_KEY => TRUE, + PUSH_MODE => FALSE, + INLINE_QOS => gen_inline_qos(NUM_READERS+7), + MAX_REMOTE_ENDPOINTS => MAX_REMOTE_ENDPOINTS + ) + port map ( + clk => clk, + reset => reset, + time => test_time, + empty_user => empty_user or packet_sent_user, + rd_user => rd_user, + data_in_user => data_in_user, + last_word_in_user => last_word_in_user, + empty_meta => empty_meta or packet_sent_meta, + rd_meta => rd_meta, + data_in_meta => data_in_meta, + last_word_in_meta => last_word_in_meta, + alive_sig => open, + wr_rtps => fifo_wr, + full_rtps => fifo_full, + last_word_out_rtps => fifo_in(WORD_WIDTH), + data_out_rtps => fifo_in(WORD_WIDTH-1 downto 0), + assert_liveliness => '0', + data_available => data_available, + start_hc => start_hc, + opcode_hc => opcode_hc, + ack_hc => ack_hc, + seq_nr_hc => seq_nr_hc, + done_hc => done_hc, + ret_hc => ret_hc, + get_data_hc => get_data_hc, + data_in_hc => data_in_hc, + valid_in_hc => valid_in_hc, + ready_in_hc => ready_in_hc, + last_word_in_hc => last_word_in_hc, + cc_instance_handle => cc_instance_handle, + cc_kind => cc_kind, + cc_source_timestamp => cc_source_timestamp, + cc_seq_nr => cc_seq_nr + ); + + fifo_inst : entity work.FWFT_FIFO(arch) + generic map ( + FIFO_DEPTH => 2, + DATA_WIDTH => WORD_WIDTH+1 + ) + port map + ( + reset => reset, + clk => clk, + data_in => fifo_in, + write => fifo_wr, + read => rtps_out_rd(0), + data_out => fifo_out, + empty => fifo_empty, + full => fifo_full, + free => open + ); + + rtps_out_data <= (0 => fifo_out(WORD_WIDTH-1 downto 0), others => (others => '0')); + rtps_out_last_word_in <= (0 => fifo_out(WORD_WIDTH), others => '0'); + rtps_out_empty <= (0 => fifo_empty, others => '1'); + + rtps_out_inst : entity work.rtps_out(arch) + port map ( + clk => clk, + reset => reset, + data_in => rtps_out_data, + last_word_in=> rtps_out_last_word_in, + rd => rtps_out_rd, + empty => rtps_out_empty, + data_out => data_out, + wr => wr_sig, + full => full + ); + + + stimulus_prc : process + variable RV : RandomPType; + variable e0, e1, e2, e3, e4, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + variable sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable cc : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + variable OUT_HEADER : OUTPUT_HEADER_TYPE := DEFAULT_OUTPUT_HEADER; + variable rtps_header : RTPS_HEADER_TYPE := DEFAULT_RTPS_HEADER; + + alias idle_sig is <>; + + -- Wrapper to use procedure as function + impure function gen_rand_loc_2 return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + gen_rand_loc(RV, ret); + return ret; + end function; + + impure function gen_rand_entityid_2(reader : boolean) return std_logic_vector is + variable ret : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); + begin + gen_rand_entityid(RV, reader, ret); + return ret; + end function; + + impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is + variable ret : GUIDPREFIX_TYPE; + begin + ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH)); + return ret; + end function; + + impure function gen_key_hash return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := (others => (others => '0')); + begin + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := RV.RandSlv(WORD_WIDTH); + end loop; + return ret; + end function; + + impure function gen_payload return TEST_PACKET_TYPE is + variable ret : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + begin + for i in 0 to RV.RandInt(1,10) loop + ret.data(ret.length) := RV.RandSlv(WORD_WIDTH); + ret.length := ret.length + 1; + end loop; + ret.last(ret.length-1) := '1'; + return ret; + end function; + + procedure start_meta_test is + begin + start_meta <= '1'; + wait until rising_edge(clk); + start_meta <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure start_user_test is + begin + start_user <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure wait_on_meta_sent is + begin + wait until rising_edge(packet_sent_meta); + end procedure; + + procedure wait_on_user_sent is + begin + wait until rising_edge(packet_sent_user); + end procedure; + + procedure wait_on_out_check is + begin + if (out_check_done /= '1') then + wait until out_check_done = '1'; + end if; + end procedure; + + procedure wait_on_hc_check is + begin + if (hc_check_done /= '1') then + wait until hc_check_done = '1'; + end if; + end procedure; + + procedure wait_on_completion is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + + procedure wait_on_idle is + begin + if (idle_sig /= '1') then + wait until idle_sig = '1'; + end if; + end procedure; + + procedure push_hc(opcode : in HISTORY_CACHE_OPCODE_TYPE; sn : in SEQUENCENUMBER_TYPE) is + begin + SB_hc.push(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode),WORD_WIDTH))); + SB_hc.push(std_logic_vector(sn(0))); + SB_hc.push(std_logic_vector(sn(1))); + end procedure; + + procedure gen_header(endpoint : in ENDPOINT_DATA_TYPE) is + begin + reference := EMPTY_TEST_PACKET; + -- OUTPUT HEADER + OUT_HEADER := DEFAULT_OUTPUT_HEADER; + OUT_HEADER := (dest => get_loc(endpoint), src => DEST_LOC.user.locator(1)); + gen_output_header(OUT_HEADER, reference); + -- RTPS HEADER + rtps_header := DEFAULT_RTPS_HEADER; + rtps_header.guidPrefix := GUIDPREFIX; + gen_rtps_header(rtps_header, reference); + end procedure; + + procedure gen_data(endpoint : in ENDPOINT_DATA_TYPE; ref : in CACHE_CHANGE_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.submessageLength := (others => '0'); + sub.writerSN := ref.seq_nr; + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1' when (ref.kind = ALIVE) else '0'; + sub.flags(SUBMESSAGE_KEY_FLAG_POS) := '1' when (ref.kind /= ALIVE) else '0'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + gen_inline_qos(ref, gen_endpoint(NUM_READERS+7), (endpoint.expectsInlineQoS(0) = '1'), '0', sub.inlineQos); + gen_sentinel(sub.inlineQos); + assert (ref.payload /= EMPTY_TEST_PACKET) severity FAILURE; + sub.data := ref.payload; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_ts(ts : TIME_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_INFO_TS; + sub.timestamp := ts; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_gap(first : SEQUENCENUMBER_TYPE; last : SEQUENCENUMBER_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.gapStart := first; + sub.gapList := (base => last, numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_submessage(sub, reference); + end procedure; + + procedure push_reference is + begin + fix_output_packet(reference); + for i in 0 to reference.length-1 loop + SB_out.Push(reference.data(i)); + end loop; + end procedure; + + begin + + SetAlertLogName("rtps_writer (Volatile, Reliable, Keyed, By Reception Timestamp, Pull Mode) - Level 1 - RTPS Output (DATA & GAP)"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- Endpoint 0 + e0 := DEFAULT_ENDPOINT_DATA; + e0.nr := 0; + e0.match := MATCH; + e0.entityid := RV.RandSlv(ENTITYID_WIDTH); + e0.participant.guidPrefix := gen_rand_guid_prefix; + e0.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 1 + e1 := DEFAULT_ENDPOINT_DATA; + e1.nr := 1; + e1.match := MATCH; + e1.entityid := RV.RandSlv(ENTITYID_WIDTH); + e1.participant.guidPrefix := gen_rand_guid_prefix; + e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; + -- Endpoint 2 + e2 := DEFAULT_ENDPOINT_DATA; + e2.nr := 2; + e2.match := MATCH; + e2.entityid := RV.RandSlv(ENTITYID_WIDTH); + e2.participant.guidPrefix := gen_rand_guid_prefix; + e2.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e2.expectsInlineQoS(0) := '1'; + -- Endpoint 3 + e3 := DEFAULT_ENDPOINT_DATA; + e3.nr := 3; + e3.match := MATCH; + e3.entityid := RV.RandSlv(ENTITYID_WIDTH); + e3.participant.guidPrefix := gen_rand_guid_prefix; + e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e3.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + -- Endpoint 4 + e4 := DEFAULT_ENDPOINT_DATA; + e4.nr := 4; + e4.match := MATCH; + e4.entityid := RV.RandSlv(ENTITYID_WIDTH); + e4.participant.guidPrefix := gen_rand_guid_prefix; + e4.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e4.expectsInlineQoS(0) := '1'; + e4.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + e4.reliability := BEST_EFFORT_RELIABILITY_QOS; + + Log("Initiating Test", INFO); + Log("Current Time: 0s", INFO); + count <= 1; + test_time <= TIME_ZERO; + new_cc <= '0'; + stim_done <= '0'; + start_meta <= '0'; + start_user <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + + Log("Insert Endpoint 0,1", INFO); + gen_endpoint_match_frame(e0, stimulus_meta); + gen_endpoint_match_frame(e1, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 1]", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(1); + test_cc(0).src_timestamp <= gen_duration(1,0); + test_cc(0).payload <= gen_payload; + test_cc_fill <= 1; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + Log("Endpoint 0 sent ACKNACK [Request SN 1]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 1 sent ACKNACK [Request SN 1]", INFO); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1s", INFO); + Log("Send SN 1 to Endpoints 0,1", INFO); + test_time <= gen_duration(1,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <2] (Remove SN 1)", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(1)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 2,3]", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(2); + test_cc(0).src_timestamp <= gen_duration(2,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= ALIVE; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(3); + test_cc(1).src_timestamp <= gen_duration(3,0); + test_cc(1).payload <= gen_payload; + test_cc_fill <= 2; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + Log("Endpoint 0 sent ACKNACK [ACK SN <2, Request SN 2,3]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(2, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 1 sent ACKNACK [ACK SN <2, Request SN 2,3]", INFO); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(2, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 2s", INFO); + Log("Send SN 2,3 to Endpoints 0,1", INFO); + test_time <= gen_duration(2,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 2,3", INFO); + gen_endpoint_match_frame(e2, stimulus_meta); + gen_endpoint_match_frame(e3, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <4]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <2]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 4]", INFO); + test_cc(2).kind <= ALIVE_FILTERED; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(4); + test_cc(2).src_timestamp <= gen_duration(4,0); + test_cc(2).payload <= gen_payload; + test_cc_fill <= 3; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + Log("Endpoint 0 sent ACKNACK [ACK SN <4, Request SN 4]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 1 sent ACKNACK [ACK SN <4, Request SN 4]", INFO); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <4, Request SN 4]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <4, Request SN 4]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(2)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(3)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 3s", INFO); + Log("Send SN 4 to Endpoints 0,1,2,3", INFO); + test_time <= gen_duration(3,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <5]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc(0) <= test_cc(2); + test_cc_fill <= 1; + + Log("Endpoint 0 sent ACKNACK [ACK SN <5]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <5] (Remove SN 4)", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(4)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 10,11,15,46,50]", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(10); + test_cc(0).src_timestamp <= gen_duration(5,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= NOT_ALIVE_DISPOSED; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(11); + test_cc(1).src_timestamp <= gen_duration(6,0); + test_cc(1).payload <= gen_payload; + test_cc(2).kind <= NOT_ALIVE_UNREGISTERED; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(15); + test_cc(2).src_timestamp <= gen_duration(7,0); + test_cc(2).payload <= gen_payload; + test_cc(3).kind <= NOT_ALIVE_DISPOSED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(37); + test_cc(3).src_timestamp <= gen_duration(8,0); + test_cc(3).payload <= gen_payload; + test_cc(4).kind <= ALIVE; + test_cc(4).instance <= gen_key_hash; + test_cc(4).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(4).seq_nr <= gen_sn(50); + test_cc(4).src_timestamp <= gen_duration(9,0); + test_cc(4).payload <= gen_payload; + test_cc_fill <= 5; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + Log("Endpoint 0 sent ACKNACK [Request SN 10,15,37]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(35, CDR_LONG_WIDTH), bitmap => (5 => '1', 10 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 4s", INFO); + Log("Send SN 10,15,37 to Endpoint 0", INFO); + test_time <= gen_duration(4,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <15]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <10, Request SN 10]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(10), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 4.5s", INFO); + test_time <= gen_duration(4,500); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <15, Request SN 15,16,47]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(33, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 5s", INFO); + Log("Send SN 15 to Endpoint 0 (GAP for SN 16, and ignore Request for SN 47)", INFO); + test_time <= gen_duration(5,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_gap(gen_sn(16), gen_sn(17)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [Request SN 1-32]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(32, CDR_LONG_WIDTH), bitmap => (0 to 31 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 6s", INFO); + Log("Send SN 10,11,15 to Endpoint 3 (GAPs for Rest)", INFO); + test_time <= gen_duration(6,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e3); + gen_gap(gen_sn(1), gen_sn(10)); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(12), gen_sn(15)); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(16), gen_sn(32)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 4", INFO); + gen_endpoint_match_frame(e4, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <15] (Remove SN 5,6,7,8,9,10,11,12,13,14)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(5)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(6)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(7)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(8)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(9)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(10)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(11)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(12)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(13)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(14)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + stim_done <= '1'; + wait_on_completion; + TranscriptOpen(RESULTS_FILE, APPEND_MODE); + SetTranscriptMirror; + ReportAlerts; + TranscriptClose; + std.env.stop; + wait; + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + empty_meta_prc : process + begin + empty_meta <= '0'; + wait until rd_meta = '1'; + wait until rising_edge(clk); + empty_meta <= '1'; + wait until rising_edge(clk); + end process; + + empty_user_prc : process + begin + empty_user <= '0'; + wait until rd_user = '1'; + wait until rising_edge(clk); + empty_user <= '1'; + wait until rising_edge(clk); + end process; + + rtps_full_prc : process + begin + full <= '0'; + wait until wr_sig = '1'; + wait until rising_edge(clk); + full <= '1'; + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(empty_meta = '1' and rd_meta = '1', "Input FIFO read signal high while empty signal high (meta)", ERROR); + alertif(empty_user = '1' and rd_user = '1', "Input FIFO read signal high while empty signal high (user)", ERROR); + alertif(full = '1' and wr_sig = '1', "Output FIFO write signal high while full signal high", ERROR); + end if; + end process; + + input_meta_prc : process(all) + begin + data_in_meta <= stimulus_meta.data(cnt_stim_meta); + last_word_in_meta <= stimulus_meta.last(cnt_stim_meta); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_meta <= 0; + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + else + case (stim_stage_meta) is + when IDLE => + if (start_meta = '1' and stimulus_meta.length /= 0) then + stim_stage_meta <= BUSY; + packet_sent_meta <= '0'; + end if; + when BUSY => + if (rd_meta = '1') then + if (cnt_stim_meta = stimulus_meta.length-1) then + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + cnt_stim_meta <= 0; + else + cnt_stim_meta <= cnt_stim_meta + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + input_user_prc : process(all) + begin + data_in_user <= stimulus_user.data(cnt_stim_user); + last_word_in_user <= stimulus_user.last(cnt_stim_user); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_user <= 0; + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + else + case (stim_stage_user) is + when IDLE => + if (start_user = '1' and stimulus_user.length /= 0) then + stim_stage_user <= BUSY; + packet_sent_user <= '0'; + end if; + when BUSY => + if (rd_user = '1') then + if (cnt_stim_user = stimulus_user.length-1) then + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + cnt_stim_user <= 0; + else + cnt_stim_user <= cnt_stim_user + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_out.empty and SB_hc.empty) then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + hc_prc : process (all) + variable stimulus : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + variable bool : boolean := FALSE; + begin + if (new_cc = '1') then + data_available <= '1'; + end if; + + if rising_edge(clk) then + hc_check_done <= '0'; + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + case (opcode_hc) is + when GET_CACHE_CHANGE => + bool := FALSE; + for i in 0 to test_cc_fill-1 loop + if (test_cc(i).seq_nr = seq_nr_hc) then + cc_instance_handle <= test_cc(i).instance; + cc_source_timestamp <= test_cc(i).src_timestamp; + cc_kind <= test_cc(i).kind; + stimulus := test_cc(i).payload; + stage_hc <= DONE; + bool := TRUE; + end if; + end loop; + if (not bool) then + stage_hc <= INVALID; + end if; + when GET_MIN_SN => + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(0).seq_nr; + stage_hc <= DONE; + when GET_MAX_SN => + data_available <= '0'; + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(test_cc_fill-1).seq_nr when (test_cc_fill /= 0) else SEQUENCENUMBER_UNKNOWN; + stage_hc <= DONE; + when others => + SB_hc.Check(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode_hc), WORD_WIDTH))); + SB_hc.Check(std_logic_vector(seq_nr_hc(0))); + SB_hc.Check(std_logic_vector(seq_nr_hc(1))); + hc_check_done <= '1'; + stage_hc <= DONE; + end case; + end if; + when DONE => + if (get_data_hc = '1') then + alertif(stimulus = EMPTY_TEST_PACKET, "Requested empty Payload", FAILURE); + stage_hc <= PUSH; + cnt <= 0; + else + stage_hc <= IDLE; + end if; + when PUSH => + if (ready_in_hc = '1') then + cnt <= cnt + 1; + if (cnt = stimulus.length-1) then + stage_hc <= IDLE; + end if; + end if; + when INVALID => + stage_hc <= IDLE; + when others => + null; + end case; + end if; + + -- DEFAULT + ack_hc <= '0'; + valid_in_hc <= '0'; + data_in_hc <= (others => '0'); + last_word_in_hc <= '0'; + done_hc <= '0'; + ret_hc <= ERROR; + + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + end if; + when DONE => + done_hc <= '1'; + ret_hc <= OK; + when PUSH => + valid_in_hc <= '1'; + data_in_hc <= stimulus.data(cnt); + last_word_in_hc <= stimulus.last(cnt); + when INVALID => + done_hc <= '1'; + ret_hc <= INVALID; + when others => + null; + end case; + end process; + + output_check_prc : process(all) + begin + if (SB_out.empty) then + out_check_done <= '1'; + else + out_check_done <= '0'; + end if; + if rising_edge(clk) then + if (wr_sig = '1') then + SB_out.Check(data_out); + end if; + end if; + end process; + + watchdog : process + begin + wait for 1 ms; + Alert("Test timeout", FAILURE); + std.env.stop; + end process; + +end architecture; \ No newline at end of file diff --git a/src/Tests/Level_1/L1_rtps_writer_test1_vrkdp.vhd b/src/Tests/Level_1/L1_rtps_writer_test1_vrkdp.vhd new file mode 100644 index 0000000..26d546d --- /dev/null +++ b/src/Tests/Level_1/L1_rtps_writer_test1_vrkdp.vhd @@ -0,0 +1,1162 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; -- Utility Library +context osvvm.OsvvmContext; + +use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; +use work.rtps_test_package.all; + +-- This testbench tests the RTPS Message generation of the RTPS Writer (DATA and GAP Generation). +-- This testbench covers following: +-- * (Best Effort/Transient Local/Expecting Inline Qos) Remote Readers +-- * New Data Push +-- * ACK Handling +-- * NACK/Request Handling + +entity L1_rtps_writer_test1_vrkdp is +end entity; + +architecture testbench of L1_rtps_writer_test1_vrkdp is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_ENDPOINTS : natural := 5; + constant MAX_CC : natural := 10; + + -- *TYPE DECLARATION* + type SEND_STAGE_TYPE is (IDLE, BUSY); + type TEST_CC_ARRAY_TYPE is array (0 to MAX_CC-1) of CACHE_CHANGE_TYPE; + type HC_STAGE_TYPE is (IDLE, PUSH, DONE, INVALID); + + -- *SIGNAL DECLARATION* + signal clk, empty_user, empty_meta, rd_user, rd_meta, last_word_in_user, last_word_in_meta, last_word_in_hc, last_word_out_rtps : std_logic := '0'; + signal reset : std_logic := '1'; + signal data_in_user, data_in_meta, data_out, data_in_hc : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal wr_sig, full, data_available : std_logic := '0'; + signal ready_in_hc, valid_in_hc, ack_hc, done_hc, get_data_hc, start_hc : std_logic := '0'; + signal seq_nr_hc : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + signal stim_stage_user, stim_stage_meta : SEND_STAGE_TYPE := IDLE; + signal opcode_hc : HISTORY_CACHE_OPCODE_TYPE := NOP; + signal ret_hc : HISTORY_CACHE_RESPONSE_TYPE := ERROR; + signal cc_instance_handle : INSTANCE_HANDLE_TYPE := HANDLE_NIL; + signal cc_kind : CACHE_CHANGE_KIND_TYPE := ALIVE; + signal cc_source_timestamp : TIME_TYPE := TIME_INVALID; + signal cc_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + shared variable stimulus_user, stimulus_meta, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent_user, packet_sent_meta : std_logic := '0'; + signal cnt_stim_meta, cnt_stim_user, count : natural := 0; + signal start_meta, start_user : std_logic := '0'; + shared variable SB_out, SB_hc : osvvm.ScoreBoardPkg_slv.ScoreBoardPType; + signal stim_done, out_check_done, hc_check_done, test_done : std_logic := '0'; + signal test_time : TIME_TYPE := TIME_ZERO; + signal fifo_in, fifo_out : std_logic_vector(WORD_WIDTH downto 0) := (others => '0'); + signal fifo_wr, fifo_empty, fifo_full : std_logic := '0'; + signal rtps_out_data : RTPS_OUT_DATA_TYPE := (others => (others => '0')); + signal rtps_out_rd, rtps_out_last_word_in, rtps_out_empty : std_logic_vector(0 to NUM_ENDPOINTS) := (others => '0'); + signal test_cc : TEST_CC_ARRAY_TYPE := (others => DEFAULT_CACHE_CHANGE); + -- Signal containing the current fill level of the test_cc array + signal test_cc_fill : natural := 0; + signal stage_hc : HC_STAGE_TYPE := IDLE; + signal new_cc : std_logic := '0'; + signal cnt : natural := 0; + + -- *FUNCTION DECLARATION* + function gen_sn(input : natural) return SEQUENCENUMBER_TYPE is + variable ret : SEQUENCENUMBER_TYPE; + begin + ret(0) := (others => '0'); + ret(1) := unsigned(int(input, WORD_WIDTH)); + return ret; + end function; + +begin + + -- Unit Under Test + uut : entity work.rtps_writer(arch) + generic map ( + RELIABILTY_QOS => RELIABLE_RELIABILITY_QOS, + LIVELINESS_QOS => AUTOMATIC_LIVELINESS_QOS, + DURABILITY_QOS => VOLATILE_DURABILITY_QOS, + DESTINATION_ORDER_QOS => BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS, + ACKNACK_RESPONSE_DELAY => gen_duration(1,0), + ACKNACK_SUPPRESSION_DELAY => DURATION_ZERO, + LEASE_DURATION => DURATION_INFINITE, + HEARTBEAT_PERIOD => DURATION_INFINITE, + ENTITYID => DEFAULT_WRITER_ENTITYID, + WITH_KEY => TRUE, + PUSH_MODE => TRUE, + INLINE_QOS => gen_inline_qos(NUM_READERS+7), + MAX_REMOTE_ENDPOINTS => MAX_REMOTE_ENDPOINTS + ) + port map ( + clk => clk, + reset => reset, + time => test_time, + empty_user => empty_user or packet_sent_user, + rd_user => rd_user, + data_in_user => data_in_user, + last_word_in_user => last_word_in_user, + empty_meta => empty_meta or packet_sent_meta, + rd_meta => rd_meta, + data_in_meta => data_in_meta, + last_word_in_meta => last_word_in_meta, + alive_sig => open, + wr_rtps => fifo_wr, + full_rtps => fifo_full, + last_word_out_rtps => fifo_in(WORD_WIDTH), + data_out_rtps => fifo_in(WORD_WIDTH-1 downto 0), + assert_liveliness => '0', + data_available => data_available, + start_hc => start_hc, + opcode_hc => opcode_hc, + ack_hc => ack_hc, + seq_nr_hc => seq_nr_hc, + done_hc => done_hc, + ret_hc => ret_hc, + get_data_hc => get_data_hc, + data_in_hc => data_in_hc, + valid_in_hc => valid_in_hc, + ready_in_hc => ready_in_hc, + last_word_in_hc => last_word_in_hc, + cc_instance_handle => cc_instance_handle, + cc_kind => cc_kind, + cc_source_timestamp => cc_source_timestamp, + cc_seq_nr => cc_seq_nr + ); + + fifo_inst : entity work.FWFT_FIFO(arch) + generic map ( + FIFO_DEPTH => 2, + DATA_WIDTH => WORD_WIDTH+1 + ) + port map + ( + reset => reset, + clk => clk, + data_in => fifo_in, + write => fifo_wr, + read => rtps_out_rd(0), + data_out => fifo_out, + empty => fifo_empty, + full => fifo_full, + free => open + ); + + rtps_out_data <= (0 => fifo_out(WORD_WIDTH-1 downto 0), others => (others => '0')); + rtps_out_last_word_in <= (0 => fifo_out(WORD_WIDTH), others => '0'); + rtps_out_empty <= (0 => fifo_empty, others => '1'); + + rtps_out_inst : entity work.rtps_out(arch) + port map ( + clk => clk, + reset => reset, + data_in => rtps_out_data, + last_word_in=> rtps_out_last_word_in, + rd => rtps_out_rd, + empty => rtps_out_empty, + data_out => data_out, + wr => wr_sig, + full => full + ); + + + stimulus_prc : process + variable RV : RandomPType; + variable e0, e1, e2, e3, e4, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + variable sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable cc : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + variable OUT_HEADER : OUTPUT_HEADER_TYPE := DEFAULT_OUTPUT_HEADER; + variable rtps_header : RTPS_HEADER_TYPE := DEFAULT_RTPS_HEADER; + + alias idle_sig is <>; + + -- Wrapper to use procedure as function + impure function gen_rand_loc_2 return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + gen_rand_loc(RV, ret); + return ret; + end function; + + impure function gen_rand_entityid_2(reader : boolean) return std_logic_vector is + variable ret : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); + begin + gen_rand_entityid(RV, reader, ret); + return ret; + end function; + + impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is + variable ret : GUIDPREFIX_TYPE; + begin + ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH)); + return ret; + end function; + + impure function gen_key_hash return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := (others => (others => '0')); + begin + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := RV.RandSlv(WORD_WIDTH); + end loop; + return ret; + end function; + + impure function gen_payload return TEST_PACKET_TYPE is + variable ret : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + begin + for i in 0 to RV.RandInt(1,10) loop + ret.data(ret.length) := RV.RandSlv(WORD_WIDTH); + ret.length := ret.length + 1; + end loop; + ret.last(ret.length-1) := '1'; + return ret; + end function; + + procedure start_meta_test is + begin + start_meta <= '1'; + wait until rising_edge(clk); + start_meta <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure start_user_test is + begin + start_user <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure wait_on_meta_sent is + begin + wait until rising_edge(packet_sent_meta); + end procedure; + + procedure wait_on_user_sent is + begin + wait until rising_edge(packet_sent_user); + end procedure; + + procedure wait_on_out_check is + begin + if (out_check_done /= '1') then + wait until out_check_done = '1'; + end if; + end procedure; + + procedure wait_on_hc_check is + begin + if (hc_check_done /= '1') then + wait until hc_check_done = '1'; + end if; + end procedure; + + procedure wait_on_completion is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + + procedure wait_on_idle is + begin + if (idle_sig /= '1') then + wait until idle_sig = '1'; + end if; + end procedure; + + procedure push_hc(opcode : in HISTORY_CACHE_OPCODE_TYPE; sn : in SEQUENCENUMBER_TYPE) is + begin + SB_hc.push(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode),WORD_WIDTH))); + SB_hc.push(std_logic_vector(sn(0))); + SB_hc.push(std_logic_vector(sn(1))); + end procedure; + + procedure gen_header(endpoint : in ENDPOINT_DATA_TYPE) is + begin + reference := EMPTY_TEST_PACKET; + -- OUTPUT HEADER + OUT_HEADER := DEFAULT_OUTPUT_HEADER; + OUT_HEADER := (dest => get_loc(endpoint), src => DEST_LOC.user.locator(1)); + gen_output_header(OUT_HEADER, reference); + -- RTPS HEADER + rtps_header := DEFAULT_RTPS_HEADER; + rtps_header.guidPrefix := GUIDPREFIX; + gen_rtps_header(rtps_header, reference); + end procedure; + + procedure gen_data(endpoint : in ENDPOINT_DATA_TYPE; ref : in CACHE_CHANGE_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.submessageLength := (others => '0'); + sub.writerSN := ref.seq_nr; + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1' when (ref.kind = ALIVE) else '0'; + sub.flags(SUBMESSAGE_KEY_FLAG_POS) := '1' when (ref.kind /= ALIVE) else '0'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + gen_inline_qos(ref, gen_endpoint(NUM_READERS+7), (endpoint.expectsInlineQoS(0) = '1'), '0', sub.inlineQos); + gen_sentinel(sub.inlineQos); + assert (ref.payload /= EMPTY_TEST_PACKET) severity FAILURE; + sub.data := ref.payload; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_ts(ts : TIME_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_INFO_TS; + sub.timestamp := ts; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_gap(first : SEQUENCENUMBER_TYPE; last : SEQUENCENUMBER_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.gapStart := first; + sub.gapList := (base => last, numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_submessage(sub, reference); + end procedure; + + procedure push_reference is + begin + fix_output_packet(reference); + for i in 0 to reference.length-1 loop + SB_out.Push(reference.data(i)); + end loop; + end procedure; + + begin + + SetAlertLogName("rtps_writer (Volatile, Reliable, Keyed, By Reception Timestamp, Push Mode) - Level 1 - RTPS Output (DATA & GAP)"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- Endpoint 0 + e0 := DEFAULT_ENDPOINT_DATA; + e0.nr := 0; + e0.match := MATCH; + e0.entityid := RV.RandSlv(ENTITYID_WIDTH); + e0.participant.guidPrefix := gen_rand_guid_prefix; + e0.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 1 + e1 := DEFAULT_ENDPOINT_DATA; + e1.nr := 1; + e1.match := MATCH; + e1.entityid := RV.RandSlv(ENTITYID_WIDTH); + e1.participant.guidPrefix := gen_rand_guid_prefix; + e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; + -- Endpoint 2 + e2 := DEFAULT_ENDPOINT_DATA; + e2.nr := 2; + e2.match := MATCH; + e2.entityid := RV.RandSlv(ENTITYID_WIDTH); + e2.participant.guidPrefix := gen_rand_guid_prefix; + e2.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e2.expectsInlineQoS(0) := '1'; + -- Endpoint 3 + e3 := DEFAULT_ENDPOINT_DATA; + e3.nr := 3; + e3.match := MATCH; + e3.entityid := RV.RandSlv(ENTITYID_WIDTH); + e3.participant.guidPrefix := gen_rand_guid_prefix; + e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e3.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + -- Endpoint 4 + e4 := DEFAULT_ENDPOINT_DATA; + e4.nr := 4; + e4.match := MATCH; + e4.entityid := RV.RandSlv(ENTITYID_WIDTH); + e4.participant.guidPrefix := gen_rand_guid_prefix; + e4.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e4.expectsInlineQoS(0) := '1'; + e4.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + e4.reliability := BEST_EFFORT_RELIABILITY_QOS; + + Log("Initiating Test", INFO); + Log("Current Time: 0s", INFO); + count <= 1; + test_time <= TIME_ZERO; + new_cc <= '0'; + stim_done <= '0'; + start_meta <= '0'; + start_user <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + + Log("Insert Endpoint 0,1", INFO); + gen_endpoint_match_frame(e0, stimulus_meta); + gen_endpoint_match_frame(e1, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 1] (Send DATA to Endpoint 0,1)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(1); + test_cc(0).src_timestamp <= gen_duration(1,0); + test_cc(0).payload <= gen_payload; + test_cc_fill <= 1; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <2] (Remove SN 1)", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(1)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 2,3] (Send DATA to Endpoint 0,1)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(2); + test_cc(0).src_timestamp <= gen_duration(2,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= ALIVE; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(3); + test_cc(1).src_timestamp <= gen_duration(3,0); + test_cc(1).payload <= gen_payload; + test_cc_fill <= 2; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 2,3", INFO); + gen_endpoint_match_frame(e2, stimulus_meta); + gen_endpoint_match_frame(e3, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <4]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <2]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 4] (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(2).kind <= ALIVE_FILTERED; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(4); + test_cc(2).src_timestamp <= gen_duration(4,0); + test_cc(2).payload <= gen_payload; + test_cc_fill <= 3; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <5] (Remove SN 2,3)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(2)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(3)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc(0) <= test_cc(2); + test_cc_fill <= 1; + + Log("Endpoint 0 sent ACKNACK [ACK SN <5]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <5] (Remove SN 4)", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(4)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 10,11,15,46,50], (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(10); + test_cc(0).src_timestamp <= gen_duration(5,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= NOT_ALIVE_DISPOSED; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(11); + test_cc(1).src_timestamp <= gen_duration(6,0); + test_cc(1).payload <= gen_payload; + test_cc(2).kind <= NOT_ALIVE_UNREGISTERED; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(15); + test_cc(2).src_timestamp <= gen_duration(7,0); + test_cc(2).payload <= gen_payload; + test_cc(3).kind <= NOT_ALIVE_DISPOSED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(37); + test_cc(3).src_timestamp <= gen_duration(8,0); + test_cc(3).payload <= gen_payload; + test_cc(4).kind <= ALIVE; + test_cc(4).instance <= gen_key_hash; + test_cc(4).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(4).seq_nr <= gen_sn(50); + test_cc(4).src_timestamp <= gen_duration(9,0); + test_cc(4).payload <= gen_payload; + test_cc_fill <= 5; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(4)); + push_reference; + wait_on_out_check; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [Request SN 10,15,37]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(35, CDR_LONG_WIDTH), bitmap => (5 => '1', 10 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1s", INFO); + Log("Send SN 10,15,37 to Endpoint 0", INFO); + test_time <= gen_duration(1,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <15]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <10, Request SN 10]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(10), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1.5s", INFO); + test_time <= gen_duration(1,500); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <15, Request SN 15,16,47]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(33, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 2s", INFO); + Log("Send SN 15 to Endpoint 0 (GAP for SN 16, and ignore Request for SN 47)", INFO); + test_time <= gen_duration(2,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_gap(gen_sn(16), gen_sn(17)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [Request SN 1-32]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(32, CDR_LONG_WIDTH), bitmap => (0 to 31 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 3s", INFO); + Log("Send SN 10,11,15 to Endpoint 3 (GAPs for Rest)", INFO); + test_time <= gen_duration(3,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e3); + gen_gap(gen_sn(1), gen_sn(10)); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(12), gen_sn(15)); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(16), gen_sn(32)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 4", INFO); + gen_endpoint_match_frame(e4, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <15] (Remove SN 5,6,7,8,9,10,11,12,13,14)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(5)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(6)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(7)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(8)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(9)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(10)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(11)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(12)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(13)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(14)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + stim_done <= '1'; + wait_on_completion; + TranscriptOpen(RESULTS_FILE, APPEND_MODE); + SetTranscriptMirror; + ReportAlerts; + TranscriptClose; + std.env.stop; + wait; + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + empty_meta_prc : process + begin + empty_meta <= '0'; + wait until rd_meta = '1'; + wait until rising_edge(clk); + empty_meta <= '1'; + wait until rising_edge(clk); + end process; + + empty_user_prc : process + begin + empty_user <= '0'; + wait until rd_user = '1'; + wait until rising_edge(clk); + empty_user <= '1'; + wait until rising_edge(clk); + end process; + + rtps_full_prc : process + begin + full <= '0'; + wait until wr_sig = '1'; + wait until rising_edge(clk); + full <= '1'; + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(empty_meta = '1' and rd_meta = '1', "Input FIFO read signal high while empty signal high (meta)", ERROR); + alertif(empty_user = '1' and rd_user = '1', "Input FIFO read signal high while empty signal high (user)", ERROR); + alertif(full = '1' and wr_sig = '1', "Output FIFO write signal high while full signal high", ERROR); + end if; + end process; + + input_meta_prc : process(all) + begin + data_in_meta <= stimulus_meta.data(cnt_stim_meta); + last_word_in_meta <= stimulus_meta.last(cnt_stim_meta); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_meta <= 0; + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + else + case (stim_stage_meta) is + when IDLE => + if (start_meta = '1' and stimulus_meta.length /= 0) then + stim_stage_meta <= BUSY; + packet_sent_meta <= '0'; + end if; + when BUSY => + if (rd_meta = '1') then + if (cnt_stim_meta = stimulus_meta.length-1) then + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + cnt_stim_meta <= 0; + else + cnt_stim_meta <= cnt_stim_meta + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + input_user_prc : process(all) + begin + data_in_user <= stimulus_user.data(cnt_stim_user); + last_word_in_user <= stimulus_user.last(cnt_stim_user); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_user <= 0; + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + else + case (stim_stage_user) is + when IDLE => + if (start_user = '1' and stimulus_user.length /= 0) then + stim_stage_user <= BUSY; + packet_sent_user <= '0'; + end if; + when BUSY => + if (rd_user = '1') then + if (cnt_stim_user = stimulus_user.length-1) then + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + cnt_stim_user <= 0; + else + cnt_stim_user <= cnt_stim_user + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_out.empty and SB_hc.empty) then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + hc_prc : process (all) + variable stimulus : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + variable bool : boolean := FALSE; + begin + if (new_cc = '1') then + data_available <= '1'; + end if; + + if rising_edge(clk) then + hc_check_done <= '0'; + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + case (opcode_hc) is + when GET_CACHE_CHANGE => + bool := FALSE; + for i in 0 to test_cc_fill-1 loop + if (test_cc(i).seq_nr = seq_nr_hc) then + cc_instance_handle <= test_cc(i).instance; + cc_source_timestamp <= test_cc(i).src_timestamp; + cc_kind <= test_cc(i).kind; + stimulus := test_cc(i).payload; + stage_hc <= DONE; + bool := TRUE; + end if; + end loop; + if (not bool) then + stage_hc <= INVALID; + end if; + when GET_MIN_SN => + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(0).seq_nr; + stage_hc <= DONE; + when GET_MAX_SN => + data_available <= '0'; + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(test_cc_fill-1).seq_nr when (test_cc_fill /= 0) else SEQUENCENUMBER_UNKNOWN; + stage_hc <= DONE; + when others => + SB_hc.Check(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode_hc), WORD_WIDTH))); + SB_hc.Check(std_logic_vector(seq_nr_hc(0))); + SB_hc.Check(std_logic_vector(seq_nr_hc(1))); + hc_check_done <= '1'; + stage_hc <= DONE; + end case; + end if; + when DONE => + if (get_data_hc = '1') then + alertif(stimulus = EMPTY_TEST_PACKET, "Requested empty Payload", FAILURE); + stage_hc <= PUSH; + cnt <= 0; + else + stage_hc <= IDLE; + end if; + when PUSH => + if (ready_in_hc = '1') then + cnt <= cnt + 1; + if (cnt = stimulus.length-1) then + stage_hc <= IDLE; + end if; + end if; + when INVALID => + stage_hc <= IDLE; + when others => + null; + end case; + end if; + + -- DEFAULT + ack_hc <= '0'; + valid_in_hc <= '0'; + data_in_hc <= (others => '0'); + last_word_in_hc <= '0'; + done_hc <= '0'; + ret_hc <= ERROR; + + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + end if; + when DONE => + done_hc <= '1'; + ret_hc <= OK; + when PUSH => + valid_in_hc <= '1'; + data_in_hc <= stimulus.data(cnt); + last_word_in_hc <= stimulus.last(cnt); + when INVALID => + done_hc <= '1'; + ret_hc <= INVALID; + when others => + null; + end case; + end process; + + output_check_prc : process(all) + begin + if (SB_out.empty) then + out_check_done <= '1'; + else + out_check_done <= '0'; + end if; + if rising_edge(clk) then + if (wr_sig = '1') then + SB_out.Check(data_out); + end if; + end if; + end process; + + watchdog : process + begin + wait for 1 ms; + Alert("Test timeout", FAILURE); + std.env.stop; + end process; + +end architecture; \ No newline at end of file diff --git a/src/Tests/Level_1/L1_rtps_writer_test1_vrksp.vhd b/src/Tests/Level_1/L1_rtps_writer_test1_vrksp.vhd new file mode 100644 index 0000000..2617892 --- /dev/null +++ b/src/Tests/Level_1/L1_rtps_writer_test1_vrksp.vhd @@ -0,0 +1,1163 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; -- Utility Library +context osvvm.OsvvmContext; + +use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; +use work.rtps_test_package.all; + +-- This testbench tests the RTPS Message generation of the RTPS Writer (DATA and GAP Generation). +-- This testbench covers following: +-- * (Best Effort/Transient Local/Expecting Inline Qos) Remote Readers +-- * New Data Push +-- * ACK Handling +-- * NACK/Request Handling + +entity L1_rtps_writer_test1_vrksp is +end entity; + +architecture testbench of L1_rtps_writer_test1_vrksp is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_ENDPOINTS : natural := 5; + constant MAX_CC : natural := 10; + + -- *TYPE DECLARATION* + type SEND_STAGE_TYPE is (IDLE, BUSY); + type TEST_CC_ARRAY_TYPE is array (0 to MAX_CC-1) of CACHE_CHANGE_TYPE; + type HC_STAGE_TYPE is (IDLE, PUSH, DONE, INVALID); + + -- *SIGNAL DECLARATION* + signal clk, empty_user, empty_meta, rd_user, rd_meta, last_word_in_user, last_word_in_meta, last_word_in_hc, last_word_out_rtps : std_logic := '0'; + signal reset : std_logic := '1'; + signal data_in_user, data_in_meta, data_out, data_in_hc : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal wr_sig, full, data_available : std_logic := '0'; + signal ready_in_hc, valid_in_hc, ack_hc, done_hc, get_data_hc, start_hc : std_logic := '0'; + signal seq_nr_hc : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + signal stim_stage_user, stim_stage_meta : SEND_STAGE_TYPE := IDLE; + signal opcode_hc : HISTORY_CACHE_OPCODE_TYPE := NOP; + signal ret_hc : HISTORY_CACHE_RESPONSE_TYPE := ERROR; + signal cc_instance_handle : INSTANCE_HANDLE_TYPE := HANDLE_NIL; + signal cc_kind : CACHE_CHANGE_KIND_TYPE := ALIVE; + signal cc_source_timestamp : TIME_TYPE := TIME_INVALID; + signal cc_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + shared variable stimulus_user, stimulus_meta, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent_user, packet_sent_meta : std_logic := '0'; + signal cnt_stim_meta, cnt_stim_user, count : natural := 0; + signal start_meta, start_user : std_logic := '0'; + shared variable SB_out, SB_hc : osvvm.ScoreBoardPkg_slv.ScoreBoardPType; + signal stim_done, out_check_done, hc_check_done, test_done : std_logic := '0'; + signal test_time : TIME_TYPE := TIME_ZERO; + signal fifo_in, fifo_out : std_logic_vector(WORD_WIDTH downto 0) := (others => '0'); + signal fifo_wr, fifo_empty, fifo_full : std_logic := '0'; + signal rtps_out_data : RTPS_OUT_DATA_TYPE := (others => (others => '0')); + signal rtps_out_rd, rtps_out_last_word_in, rtps_out_empty : std_logic_vector(0 to NUM_ENDPOINTS) := (others => '0'); + signal test_cc : TEST_CC_ARRAY_TYPE := (others => DEFAULT_CACHE_CHANGE); + -- Signal containing the current fill level of the test_cc array + signal test_cc_fill : natural := 0; + signal stage_hc : HC_STAGE_TYPE := IDLE; + signal new_cc : std_logic := '0'; + signal cnt : natural := 0; + + -- *FUNCTION DECLARATION* + function gen_sn(input : natural) return SEQUENCENUMBER_TYPE is + variable ret : SEQUENCENUMBER_TYPE; + begin + ret(0) := (others => '0'); + ret(1) := unsigned(int(input, WORD_WIDTH)); + return ret; + end function; + +begin + + -- Unit Under Test + uut : entity work.rtps_writer(arch) + generic map ( + RELIABILTY_QOS => RELIABLE_RELIABILITY_QOS, + LIVELINESS_QOS => AUTOMATIC_LIVELINESS_QOS, + DURABILITY_QOS => VOLATILE_DURABILITY_QOS, + DESTINATION_ORDER_QOS => BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS, + ACKNACK_RESPONSE_DELAY => gen_duration(1,0), + ACKNACK_SUPPRESSION_DELAY => DURATION_ZERO, + LEASE_DURATION => DURATION_INFINITE, + HEARTBEAT_PERIOD => DURATION_INFINITE, + ENTITYID => DEFAULT_WRITER_ENTITYID, + WITH_KEY => TRUE, + PUSH_MODE => TRUE, + INLINE_QOS => gen_inline_qos(NUM_READERS+7), + MAX_REMOTE_ENDPOINTS => MAX_REMOTE_ENDPOINTS + ) + port map ( + clk => clk, + reset => reset, + time => test_time, + empty_user => empty_user or packet_sent_user, + rd_user => rd_user, + data_in_user => data_in_user, + last_word_in_user => last_word_in_user, + empty_meta => empty_meta or packet_sent_meta, + rd_meta => rd_meta, + data_in_meta => data_in_meta, + last_word_in_meta => last_word_in_meta, + alive_sig => open, + wr_rtps => fifo_wr, + full_rtps => fifo_full, + last_word_out_rtps => fifo_in(WORD_WIDTH), + data_out_rtps => fifo_in(WORD_WIDTH-1 downto 0), + assert_liveliness => '0', + data_available => data_available, + start_hc => start_hc, + opcode_hc => opcode_hc, + ack_hc => ack_hc, + seq_nr_hc => seq_nr_hc, + done_hc => done_hc, + ret_hc => ret_hc, + get_data_hc => get_data_hc, + data_in_hc => data_in_hc, + valid_in_hc => valid_in_hc, + ready_in_hc => ready_in_hc, + last_word_in_hc => last_word_in_hc, + cc_instance_handle => cc_instance_handle, + cc_kind => cc_kind, + cc_source_timestamp => cc_source_timestamp, + cc_seq_nr => cc_seq_nr + ); + + fifo_inst : entity work.FWFT_FIFO(arch) + generic map ( + FIFO_DEPTH => 2, + DATA_WIDTH => WORD_WIDTH+1 + ) + port map + ( + reset => reset, + clk => clk, + data_in => fifo_in, + write => fifo_wr, + read => rtps_out_rd(0), + data_out => fifo_out, + empty => fifo_empty, + full => fifo_full, + free => open + ); + + rtps_out_data <= (0 => fifo_out(WORD_WIDTH-1 downto 0), others => (others => '0')); + rtps_out_last_word_in <= (0 => fifo_out(WORD_WIDTH), others => '0'); + rtps_out_empty <= (0 => fifo_empty, others => '1'); + + rtps_out_inst : entity work.rtps_out(arch) + port map ( + clk => clk, + reset => reset, + data_in => rtps_out_data, + last_word_in=> rtps_out_last_word_in, + rd => rtps_out_rd, + empty => rtps_out_empty, + data_out => data_out, + wr => wr_sig, + full => full + ); + + + stimulus_prc : process + variable RV : RandomPType; + variable e0, e1, e2, e3, e4, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + variable sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable cc : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + variable OUT_HEADER : OUTPUT_HEADER_TYPE := DEFAULT_OUTPUT_HEADER; + variable rtps_header : RTPS_HEADER_TYPE := DEFAULT_RTPS_HEADER; + + alias idle_sig is <>; + + -- Wrapper to use procedure as function + impure function gen_rand_loc_2 return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + gen_rand_loc(RV, ret); + return ret; + end function; + + impure function gen_rand_entityid_2(reader : boolean) return std_logic_vector is + variable ret : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); + begin + gen_rand_entityid(RV, reader, ret); + return ret; + end function; + + impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is + variable ret : GUIDPREFIX_TYPE; + begin + ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH)); + return ret; + end function; + + impure function gen_key_hash return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := (others => (others => '0')); + begin + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := RV.RandSlv(WORD_WIDTH); + end loop; + return ret; + end function; + + impure function gen_payload return TEST_PACKET_TYPE is + variable ret : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + begin + for i in 0 to RV.RandInt(1,10) loop + ret.data(ret.length) := RV.RandSlv(WORD_WIDTH); + ret.length := ret.length + 1; + end loop; + ret.last(ret.length-1) := '1'; + return ret; + end function; + + procedure start_meta_test is + begin + start_meta <= '1'; + wait until rising_edge(clk); + start_meta <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure start_user_test is + begin + start_user <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure wait_on_meta_sent is + begin + wait until rising_edge(packet_sent_meta); + end procedure; + + procedure wait_on_user_sent is + begin + wait until rising_edge(packet_sent_user); + end procedure; + + procedure wait_on_out_check is + begin + if (out_check_done /= '1') then + wait until out_check_done = '1'; + end if; + end procedure; + + procedure wait_on_hc_check is + begin + if (hc_check_done /= '1') then + wait until hc_check_done = '1'; + end if; + end procedure; + + procedure wait_on_completion is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + + procedure wait_on_idle is + begin + if (idle_sig /= '1') then + wait until idle_sig = '1'; + end if; + end procedure; + + procedure push_hc(opcode : in HISTORY_CACHE_OPCODE_TYPE; sn : in SEQUENCENUMBER_TYPE) is + begin + SB_hc.push(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode),WORD_WIDTH))); + SB_hc.push(std_logic_vector(sn(0))); + SB_hc.push(std_logic_vector(sn(1))); + end procedure; + + procedure gen_header(endpoint : in ENDPOINT_DATA_TYPE) is + begin + reference := EMPTY_TEST_PACKET; + -- OUTPUT HEADER + OUT_HEADER := DEFAULT_OUTPUT_HEADER; + OUT_HEADER := (dest => get_loc(endpoint), src => DEST_LOC.user.locator(1)); + gen_output_header(OUT_HEADER, reference); + -- RTPS HEADER + rtps_header := DEFAULT_RTPS_HEADER; + rtps_header.guidPrefix := GUIDPREFIX; + gen_rtps_header(rtps_header, reference); + end procedure; + + procedure gen_ts(ts : TIME_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_INFO_TS; + sub.timestamp := ts; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_data(endpoint : in ENDPOINT_DATA_TYPE; ref : in CACHE_CHANGE_TYPE) is + begin + gen_ts(ref.src_timestamp); + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.submessageLength := (others => '0'); + sub.writerSN := ref.seq_nr; + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1' when (ref.kind = ALIVE) else '0'; + sub.flags(SUBMESSAGE_KEY_FLAG_POS) := '1' when (ref.kind /= ALIVE) else '0'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + gen_inline_qos(ref, gen_endpoint(NUM_READERS+7), (endpoint.expectsInlineQoS(0) = '1'), '0', sub.inlineQos); + gen_sentinel(sub.inlineQos); + assert (ref.payload /= EMPTY_TEST_PACKET) severity FAILURE; + sub.data := ref.payload; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_gap(first : SEQUENCENUMBER_TYPE; last : SEQUENCENUMBER_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.gapStart := first; + sub.gapList := (base => last, numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_submessage(sub, reference); + end procedure; + + procedure push_reference is + begin + fix_output_packet(reference); + for i in 0 to reference.length-1 loop + SB_out.Push(reference.data(i)); + end loop; + end procedure; + + begin + + SetAlertLogName("rtps_writer (Volatile, Reliable, Keyed, By Source Timestamp, Push Mode) - Level 1 - RTPS Output (DATA & GAP)"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- Endpoint 0 + e0 := DEFAULT_ENDPOINT_DATA; + e0.nr := 0; + e0.match := MATCH; + e0.entityid := RV.RandSlv(ENTITYID_WIDTH); + e0.participant.guidPrefix := gen_rand_guid_prefix; + e0.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 1 + e1 := DEFAULT_ENDPOINT_DATA; + e1.nr := 1; + e1.match := MATCH; + e1.entityid := RV.RandSlv(ENTITYID_WIDTH); + e1.participant.guidPrefix := gen_rand_guid_prefix; + e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; + -- Endpoint 2 + e2 := DEFAULT_ENDPOINT_DATA; + e2.nr := 2; + e2.match := MATCH; + e2.entityid := RV.RandSlv(ENTITYID_WIDTH); + e2.participant.guidPrefix := gen_rand_guid_prefix; + e2.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e2.expectsInlineQoS(0) := '1'; + -- Endpoint 3 + e3 := DEFAULT_ENDPOINT_DATA; + e3.nr := 3; + e3.match := MATCH; + e3.entityid := RV.RandSlv(ENTITYID_WIDTH); + e3.participant.guidPrefix := gen_rand_guid_prefix; + e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e3.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + -- Endpoint 4 + e4 := DEFAULT_ENDPOINT_DATA; + e4.nr := 4; + e4.match := MATCH; + e4.entityid := RV.RandSlv(ENTITYID_WIDTH); + e4.participant.guidPrefix := gen_rand_guid_prefix; + e4.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e4.expectsInlineQoS(0) := '1'; + e4.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + e4.reliability := BEST_EFFORT_RELIABILITY_QOS; + + Log("Initiating Test", INFO); + Log("Current Time: 0s", INFO); + count <= 1; + test_time <= TIME_ZERO; + new_cc <= '0'; + stim_done <= '0'; + start_meta <= '0'; + start_user <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + + Log("Insert Endpoint 0,1", INFO); + gen_endpoint_match_frame(e0, stimulus_meta); + gen_endpoint_match_frame(e1, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 1] (Send DATA to Endpoint 0,1)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(1); + test_cc(0).src_timestamp <= gen_duration(1,0); + test_cc(0).payload <= gen_payload; + test_cc_fill <= 1; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <2] (Remove SN 1)", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(1)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 2,3] (Send DATA to Endpoint 0,1)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(2); + test_cc(0).src_timestamp <= gen_duration(2,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= ALIVE; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(3); + test_cc(1).src_timestamp <= gen_duration(3,0); + test_cc(1).payload <= gen_payload; + test_cc_fill <= 2; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 2,3", INFO); + gen_endpoint_match_frame(e2, stimulus_meta); + gen_endpoint_match_frame(e3, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <4]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <2]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 4] (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(2).kind <= ALIVE_FILTERED; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(4); + test_cc(2).src_timestamp <= gen_duration(4,0); + test_cc(2).payload <= gen_payload; + test_cc_fill <= 3; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <5] (Remove SN 2,3)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(2)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(3)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc(0) <= test_cc(2); + test_cc_fill <= 1; + + Log("Endpoint 0 sent ACKNACK [ACK SN <5]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <5] (Remove SN 4)", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(4)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 10,11,15,46,50], (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).instance <= gen_key_hash; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(10); + test_cc(0).src_timestamp <= gen_duration(5,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= NOT_ALIVE_DISPOSED; + test_cc(1).instance <= gen_key_hash; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(11); + test_cc(1).src_timestamp <= gen_duration(6,0); + test_cc(1).payload <= gen_payload; + test_cc(2).kind <= NOT_ALIVE_UNREGISTERED; + test_cc(2).instance <= gen_key_hash; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(15); + test_cc(2).src_timestamp <= gen_duration(7,0); + test_cc(2).payload <= gen_payload; + test_cc(3).kind <= NOT_ALIVE_DISPOSED; + test_cc(3).instance <= gen_key_hash; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(37); + test_cc(3).src_timestamp <= gen_duration(8,0); + test_cc(3).payload <= gen_payload; + test_cc(4).kind <= ALIVE; + test_cc(4).instance <= gen_key_hash; + test_cc(4).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(4).seq_nr <= gen_sn(50); + test_cc(4).src_timestamp <= gen_duration(9,0); + test_cc(4).payload <= gen_payload; + test_cc_fill <= 5; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(4)); + push_reference; + wait_on_out_check; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [Request SN 10,15,37]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(35, CDR_LONG_WIDTH), bitmap => (5 => '1', 10 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1s", INFO); + Log("Send SN 10,15,37 to Endpoint 0", INFO); + test_time <= gen_duration(1,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <15]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <10, Request SN 10]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(10), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1.5s", INFO); + test_time <= gen_duration(1,500); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <15, Request SN 15,16,47]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(33, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 2s", INFO); + Log("Send SN 15 to Endpoint 0 (GAP for SN 16, and ignore Request for SN 47)", INFO); + test_time <= gen_duration(2,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_gap(gen_sn(16), gen_sn(17)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [Request SN 1-32]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(32, CDR_LONG_WIDTH), bitmap => (0 to 31 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 3s", INFO); + Log("Send SN 10,11,15 to Endpoint 3 (GAPs for Rest)", INFO); + test_time <= gen_duration(3,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e3); + gen_gap(gen_sn(1), gen_sn(10)); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(12), gen_sn(15)); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(16), gen_sn(32)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 4", INFO); + gen_endpoint_match_frame(e4, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <15] (Remove SN 5,6,7,8,9,10,11,12,13,14)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(5)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(6)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(7)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(8)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(9)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(10)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(11)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(12)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(13)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(14)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + stim_done <= '1'; + wait_on_completion; + TranscriptOpen(RESULTS_FILE, APPEND_MODE); + SetTranscriptMirror; + ReportAlerts; + TranscriptClose; + std.env.stop; + wait; + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + empty_meta_prc : process + begin + empty_meta <= '0'; + wait until rd_meta = '1'; + wait until rising_edge(clk); + empty_meta <= '1'; + wait until rising_edge(clk); + end process; + + empty_user_prc : process + begin + empty_user <= '0'; + wait until rd_user = '1'; + wait until rising_edge(clk); + empty_user <= '1'; + wait until rising_edge(clk); + end process; + + rtps_full_prc : process + begin + full <= '0'; + wait until wr_sig = '1'; + wait until rising_edge(clk); + full <= '1'; + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(empty_meta = '1' and rd_meta = '1', "Input FIFO read signal high while empty signal high (meta)", ERROR); + alertif(empty_user = '1' and rd_user = '1', "Input FIFO read signal high while empty signal high (user)", ERROR); + alertif(full = '1' and wr_sig = '1', "Output FIFO write signal high while full signal high", ERROR); + end if; + end process; + + input_meta_prc : process(all) + begin + data_in_meta <= stimulus_meta.data(cnt_stim_meta); + last_word_in_meta <= stimulus_meta.last(cnt_stim_meta); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_meta <= 0; + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + else + case (stim_stage_meta) is + when IDLE => + if (start_meta = '1' and stimulus_meta.length /= 0) then + stim_stage_meta <= BUSY; + packet_sent_meta <= '0'; + end if; + when BUSY => + if (rd_meta = '1') then + if (cnt_stim_meta = stimulus_meta.length-1) then + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + cnt_stim_meta <= 0; + else + cnt_stim_meta <= cnt_stim_meta + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + input_user_prc : process(all) + begin + data_in_user <= stimulus_user.data(cnt_stim_user); + last_word_in_user <= stimulus_user.last(cnt_stim_user); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_user <= 0; + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + else + case (stim_stage_user) is + when IDLE => + if (start_user = '1' and stimulus_user.length /= 0) then + stim_stage_user <= BUSY; + packet_sent_user <= '0'; + end if; + when BUSY => + if (rd_user = '1') then + if (cnt_stim_user = stimulus_user.length-1) then + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + cnt_stim_user <= 0; + else + cnt_stim_user <= cnt_stim_user + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_out.empty and SB_hc.empty) then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + hc_prc : process (all) + variable stimulus : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + variable bool : boolean := FALSE; + begin + if (new_cc = '1') then + data_available <= '1'; + end if; + + if rising_edge(clk) then + hc_check_done <= '0'; + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + case (opcode_hc) is + when GET_CACHE_CHANGE => + bool := FALSE; + for i in 0 to test_cc_fill-1 loop + if (test_cc(i).seq_nr = seq_nr_hc) then + cc_instance_handle <= test_cc(i).instance; + cc_source_timestamp <= test_cc(i).src_timestamp; + cc_kind <= test_cc(i).kind; + stimulus := test_cc(i).payload; + stage_hc <= DONE; + bool := TRUE; + end if; + end loop; + if (not bool) then + stage_hc <= INVALID; + end if; + when GET_MIN_SN => + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(0).seq_nr; + stage_hc <= DONE; + when GET_MAX_SN => + data_available <= '0'; + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(test_cc_fill-1).seq_nr when (test_cc_fill /= 0) else SEQUENCENUMBER_UNKNOWN; + stage_hc <= DONE; + when others => + SB_hc.Check(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode_hc), WORD_WIDTH))); + SB_hc.Check(std_logic_vector(seq_nr_hc(0))); + SB_hc.Check(std_logic_vector(seq_nr_hc(1))); + hc_check_done <= '1'; + stage_hc <= DONE; + end case; + end if; + when DONE => + if (get_data_hc = '1') then + alertif(stimulus = EMPTY_TEST_PACKET, "Requested empty Payload", FAILURE); + stage_hc <= PUSH; + cnt <= 0; + else + stage_hc <= IDLE; + end if; + when PUSH => + if (ready_in_hc = '1') then + cnt <= cnt + 1; + if (cnt = stimulus.length-1) then + stage_hc <= IDLE; + end if; + end if; + when INVALID => + stage_hc <= IDLE; + when others => + null; + end case; + end if; + + -- DEFAULT + ack_hc <= '0'; + valid_in_hc <= '0'; + data_in_hc <= (others => '0'); + last_word_in_hc <= '0'; + done_hc <= '0'; + ret_hc <= ERROR; + + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + end if; + when DONE => + done_hc <= '1'; + ret_hc <= OK; + when PUSH => + valid_in_hc <= '1'; + data_in_hc <= stimulus.data(cnt); + last_word_in_hc <= stimulus.last(cnt); + when INVALID => + done_hc <= '1'; + ret_hc <= INVALID; + when others => + null; + end case; + end process; + + output_check_prc : process(all) + begin + if (SB_out.empty) then + out_check_done <= '1'; + else + out_check_done <= '0'; + end if; + if rising_edge(clk) then + if (wr_sig = '1') then + SB_out.Check(data_out); + end if; + end if; + end process; + + watchdog : process + begin + wait for 1 ms; + Alert("Test timeout", FAILURE); + std.env.stop; + end process; + +end architecture; \ No newline at end of file diff --git a/src/Tests/Level_1/L1_rtps_writer_test1_vrndp.vhd b/src/Tests/Level_1/L1_rtps_writer_test1_vrndp.vhd new file mode 100644 index 0000000..15b6e34 --- /dev/null +++ b/src/Tests/Level_1/L1_rtps_writer_test1_vrndp.vhd @@ -0,0 +1,1156 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; -- Utility Library +context osvvm.OsvvmContext; + +use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; +use work.rtps_test_package.all; + +-- This testbench tests the RTPS Message generation of the RTPS Writer (DATA and GAP Generation). +-- This testbench covers following: +-- * (Best Effort/Transient Local/Expecting Inline Qos) Remote Readers +-- * New Data Push +-- * ACK Handling +-- * NACK/Request Handling + +entity L1_rtps_writer_test1_vrndp is +end entity; + +architecture testbench of L1_rtps_writer_test1_vrndp is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_ENDPOINTS : natural := 5; + constant MAX_CC : natural := 10; + + -- *TYPE DECLARATION* + type SEND_STAGE_TYPE is (IDLE, BUSY); + type TEST_CC_ARRAY_TYPE is array (0 to MAX_CC-1) of CACHE_CHANGE_TYPE; + type HC_STAGE_TYPE is (IDLE, PUSH, DONE, INVALID); + + -- *SIGNAL DECLARATION* + signal clk, empty_user, empty_meta, rd_user, rd_meta, last_word_in_user, last_word_in_meta, last_word_in_hc, last_word_out_rtps : std_logic := '0'; + signal reset : std_logic := '1'; + signal data_in_user, data_in_meta, data_out, data_in_hc : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal wr_sig, full, data_available : std_logic := '0'; + signal ready_in_hc, valid_in_hc, ack_hc, done_hc, get_data_hc, start_hc : std_logic := '0'; + signal seq_nr_hc : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + signal stim_stage_user, stim_stage_meta : SEND_STAGE_TYPE := IDLE; + signal opcode_hc : HISTORY_CACHE_OPCODE_TYPE := NOP; + signal ret_hc : HISTORY_CACHE_RESPONSE_TYPE := ERROR; + signal cc_instance_handle : INSTANCE_HANDLE_TYPE := HANDLE_NIL; + signal cc_kind : CACHE_CHANGE_KIND_TYPE := ALIVE; + signal cc_source_timestamp : TIME_TYPE := TIME_INVALID; + signal cc_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + shared variable stimulus_user, stimulus_meta, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent_user, packet_sent_meta : std_logic := '0'; + signal cnt_stim_meta, cnt_stim_user, count : natural := 0; + signal start_meta, start_user : std_logic := '0'; + shared variable SB_out, SB_hc : osvvm.ScoreBoardPkg_slv.ScoreBoardPType; + signal stim_done, out_check_done, hc_check_done, test_done : std_logic := '0'; + signal test_time : TIME_TYPE := TIME_ZERO; + signal fifo_in, fifo_out : std_logic_vector(WORD_WIDTH downto 0) := (others => '0'); + signal fifo_wr, fifo_empty, fifo_full : std_logic := '0'; + signal rtps_out_data : RTPS_OUT_DATA_TYPE := (others => (others => '0')); + signal rtps_out_rd, rtps_out_last_word_in, rtps_out_empty : std_logic_vector(0 to NUM_ENDPOINTS) := (others => '0'); + signal test_cc : TEST_CC_ARRAY_TYPE := (others => DEFAULT_CACHE_CHANGE); + -- Signal containing the current fill level of the test_cc array + signal test_cc_fill : natural := 0; + signal stage_hc : HC_STAGE_TYPE := IDLE; + signal new_cc : std_logic := '0'; + signal cnt : natural := 0; + + -- *FUNCTION DECLARATION* + function gen_sn(input : natural) return SEQUENCENUMBER_TYPE is + variable ret : SEQUENCENUMBER_TYPE; + begin + ret(0) := (others => '0'); + ret(1) := unsigned(int(input, WORD_WIDTH)); + return ret; + end function; + +begin + + -- Unit Under Test + uut : entity work.rtps_writer(arch) + generic map ( + RELIABILTY_QOS => RELIABLE_RELIABILITY_QOS, + LIVELINESS_QOS => AUTOMATIC_LIVELINESS_QOS, + DURABILITY_QOS => VOLATILE_DURABILITY_QOS, + DESTINATION_ORDER_QOS => BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS, + ACKNACK_RESPONSE_DELAY => gen_duration(1,0), + ACKNACK_SUPPRESSION_DELAY => DURATION_ZERO, + LEASE_DURATION => DURATION_INFINITE, + HEARTBEAT_PERIOD => DURATION_INFINITE, + ENTITYID => DEFAULT_WRITER_ENTITYID, + WITH_KEY => FALSE, + PUSH_MODE => TRUE, + INLINE_QOS => gen_inline_qos(NUM_READERS+7), + MAX_REMOTE_ENDPOINTS => MAX_REMOTE_ENDPOINTS + ) + port map ( + clk => clk, + reset => reset, + time => test_time, + empty_user => empty_user or packet_sent_user, + rd_user => rd_user, + data_in_user => data_in_user, + last_word_in_user => last_word_in_user, + empty_meta => empty_meta or packet_sent_meta, + rd_meta => rd_meta, + data_in_meta => data_in_meta, + last_word_in_meta => last_word_in_meta, + alive_sig => open, + wr_rtps => fifo_wr, + full_rtps => fifo_full, + last_word_out_rtps => fifo_in(WORD_WIDTH), + data_out_rtps => fifo_in(WORD_WIDTH-1 downto 0), + assert_liveliness => '0', + data_available => data_available, + start_hc => start_hc, + opcode_hc => opcode_hc, + ack_hc => ack_hc, + seq_nr_hc => seq_nr_hc, + done_hc => done_hc, + ret_hc => ret_hc, + get_data_hc => get_data_hc, + data_in_hc => data_in_hc, + valid_in_hc => valid_in_hc, + ready_in_hc => ready_in_hc, + last_word_in_hc => last_word_in_hc, + cc_instance_handle => cc_instance_handle, + cc_kind => cc_kind, + cc_source_timestamp => cc_source_timestamp, + cc_seq_nr => cc_seq_nr + ); + + fifo_inst : entity work.FWFT_FIFO(arch) + generic map ( + FIFO_DEPTH => 2, + DATA_WIDTH => WORD_WIDTH+1 + ) + port map + ( + reset => reset, + clk => clk, + data_in => fifo_in, + write => fifo_wr, + read => rtps_out_rd(0), + data_out => fifo_out, + empty => fifo_empty, + full => fifo_full, + free => open + ); + + rtps_out_data <= (0 => fifo_out(WORD_WIDTH-1 downto 0), others => (others => '0')); + rtps_out_last_word_in <= (0 => fifo_out(WORD_WIDTH), others => '0'); + rtps_out_empty <= (0 => fifo_empty, others => '1'); + + rtps_out_inst : entity work.rtps_out(arch) + port map ( + clk => clk, + reset => reset, + data_in => rtps_out_data, + last_word_in=> rtps_out_last_word_in, + rd => rtps_out_rd, + empty => rtps_out_empty, + data_out => data_out, + wr => wr_sig, + full => full + ); + + + stimulus_prc : process + variable RV : RandomPType; + variable e0, e1, e2, e3, e4, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + variable sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable cc : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + variable OUT_HEADER : OUTPUT_HEADER_TYPE := DEFAULT_OUTPUT_HEADER; + variable rtps_header : RTPS_HEADER_TYPE := DEFAULT_RTPS_HEADER; + + alias idle_sig is <>; + + -- Wrapper to use procedure as function + impure function gen_rand_loc_2 return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + gen_rand_loc(RV, ret); + return ret; + end function; + + impure function gen_rand_entityid_2(reader : boolean) return std_logic_vector is + variable ret : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); + begin + gen_rand_entityid(RV, reader, ret); + return ret; + end function; + + impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is + variable ret : GUIDPREFIX_TYPE; + begin + ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH)); + return ret; + end function; + + impure function gen_key_hash return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := (others => (others => '0')); + begin + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := RV.RandSlv(WORD_WIDTH); + end loop; + return ret; + end function; + + impure function gen_payload return TEST_PACKET_TYPE is + variable ret : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + begin + for i in 0 to RV.RandInt(1,10) loop + ret.data(ret.length) := RV.RandSlv(WORD_WIDTH); + ret.length := ret.length + 1; + end loop; + ret.last(ret.length-1) := '1'; + return ret; + end function; + + procedure start_meta_test is + begin + start_meta <= '1'; + wait until rising_edge(clk); + start_meta <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure start_user_test is + begin + start_user <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure wait_on_meta_sent is + begin + wait until rising_edge(packet_sent_meta); + end procedure; + + procedure wait_on_user_sent is + begin + wait until rising_edge(packet_sent_user); + end procedure; + + procedure wait_on_out_check is + begin + if (out_check_done /= '1') then + wait until out_check_done = '1'; + end if; + end procedure; + + procedure wait_on_hc_check is + begin + if (hc_check_done /= '1') then + wait until hc_check_done = '1'; + end if; + end procedure; + + procedure wait_on_completion is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + + procedure wait_on_idle is + begin + if (idle_sig /= '1') then + wait until idle_sig = '1'; + end if; + end procedure; + + procedure push_hc(opcode : in HISTORY_CACHE_OPCODE_TYPE; sn : in SEQUENCENUMBER_TYPE) is + begin + SB_hc.push(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode),WORD_WIDTH))); + SB_hc.push(std_logic_vector(sn(0))); + SB_hc.push(std_logic_vector(sn(1))); + end procedure; + + procedure gen_header(endpoint : in ENDPOINT_DATA_TYPE) is + begin + reference := EMPTY_TEST_PACKET; + -- OUTPUT HEADER + OUT_HEADER := DEFAULT_OUTPUT_HEADER; + OUT_HEADER := (dest => get_loc(endpoint), src => DEST_LOC.user.locator(1)); + gen_output_header(OUT_HEADER, reference); + -- RTPS HEADER + rtps_header := DEFAULT_RTPS_HEADER; + rtps_header.guidPrefix := GUIDPREFIX; + gen_rtps_header(rtps_header, reference); + end procedure; + + procedure gen_data(endpoint : in ENDPOINT_DATA_TYPE; ref : in CACHE_CHANGE_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.submessageLength := (others => '0'); + sub.writerSN := ref.seq_nr; + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1' when (ref.kind = ALIVE) else '0'; + gen_inline_qos(ref, gen_endpoint(NUM_READERS+7), (endpoint.expectsInlineQoS(0) = '1'), '0', sub.inlineQos); + if (sub.inlineQos.length /= 0) then + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + gen_sentinel(sub.inlineQos); + end if; + if (ref.kind = ALIVE) then + assert (ref.payload /= EMPTY_TEST_PACKET) severity FAILURE; + sub.data := ref.payload; + end if; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_ts(ts : TIME_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_INFO_TS; + sub.timestamp := ts; + gen_rtps_submessage(sub, reference); + end procedure; + + procedure gen_gap(first : SEQUENCENUMBER_TYPE; last : SEQUENCENUMBER_TYPE) is + begin + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := ENTITYID_UNKNOWN; + sub.gapStart := first; + sub.gapList := (base => last, numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_submessage(sub, reference); + end procedure; + + procedure push_reference is + begin + fix_output_packet(reference); + for i in 0 to reference.length-1 loop + SB_out.Push(reference.data(i)); + end loop; + end procedure; + + begin + + SetAlertLogName("rtps_writer (Volatile, Reliable, Non Keyed, By Reception Timestamp, Push Mode) - Level 1 - RTPS Output (DATA & GAP)"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- Endpoint 0 + e0 := DEFAULT_ENDPOINT_DATA; + e0.nr := 0; + e0.match := MATCH; + e0.entityid := RV.RandSlv(ENTITYID_WIDTH); + e0.participant.guidPrefix := gen_rand_guid_prefix; + e0.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 1 + e1 := DEFAULT_ENDPOINT_DATA; + e1.nr := 1; + e1.match := MATCH; + e1.entityid := RV.RandSlv(ENTITYID_WIDTH); + e1.participant.guidPrefix := gen_rand_guid_prefix; + e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e1.reliability := BEST_EFFORT_RELIABILITY_QOS; + -- Endpoint 2 + e2 := DEFAULT_ENDPOINT_DATA; + e2.nr := 2; + e2.match := MATCH; + e2.entityid := RV.RandSlv(ENTITYID_WIDTH); + e2.participant.guidPrefix := gen_rand_guid_prefix; + e2.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e2.expectsInlineQoS(0) := '1'; + -- Endpoint 3 + e3 := DEFAULT_ENDPOINT_DATA; + e3.nr := 3; + e3.match := MATCH; + e3.entityid := RV.RandSlv(ENTITYID_WIDTH); + e3.participant.guidPrefix := gen_rand_guid_prefix; + e3.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e3.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + -- Endpoint 4 + e4 := DEFAULT_ENDPOINT_DATA; + e4.nr := 4; + e4.match := MATCH; + e4.entityid := RV.RandSlv(ENTITYID_WIDTH); + e4.participant.guidPrefix := gen_rand_guid_prefix; + e4.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + e4.expectsInlineQoS(0) := '1'; + e4.durability := TRANSIENT_LOCAL_DURABILITY_QOS; + e4.reliability := BEST_EFFORT_RELIABILITY_QOS; + + Log("Initiating Test", INFO); + Log("Current Time: 0s", INFO); + count <= 1; + test_time <= TIME_ZERO; + new_cc <= '0'; + stim_done <= '0'; + start_meta <= '0'; + start_user <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + + Log("Insert Endpoint 0,1", INFO); + gen_endpoint_match_frame(e0, stimulus_meta); + gen_endpoint_match_frame(e1, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 1] (Send DATA to Endpoint 0,1)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(1); + test_cc(0).src_timestamp <= gen_duration(1,0); + test_cc(0).payload <= gen_payload; + test_cc_fill <= 1; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <2] (Remove SN 1)", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(1)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 2,3] (Send DATA to Endpoint 0,1)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(2); + test_cc(0).src_timestamp <= gen_duration(2,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= ALIVE; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(3); + test_cc(1).src_timestamp <= gen_duration(3,0); + test_cc(1).payload <= gen_payload; + test_cc_fill <= 2; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 2,3", INFO); + gen_endpoint_match_frame(e2, stimulus_meta); + gen_endpoint_match_frame(e3, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <4]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(4), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <2]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(2), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Add Cache Change [SN 4] (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(2).kind <= ALIVE_FILTERED; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(4); + test_cc(2).src_timestamp <= gen_duration(4,0); + test_cc(2).payload <= gen_payload; + test_cc_fill <= 3; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <5] (Remove SN 2,3)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(2)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(3)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc(0) <= test_cc(2); + test_cc_fill <= 1; + + Log("Endpoint 0 sent ACKNACK [ACK SN <5]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <5] (Remove SN 4)", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(4)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + test_cc_fill <= 0; + + Log("Add Cache Change [SN 10,11,15,46,50], (Send DATA to Endpoint 0,1,2,3)", INFO); + test_cc(0).kind <= ALIVE; + test_cc(0).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(0).seq_nr <= gen_sn(10); + test_cc(0).src_timestamp <= gen_duration(5,0); + test_cc(0).payload <= gen_payload; + test_cc(1).kind <= NOT_ALIVE_DISPOSED; + test_cc(1).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(1).seq_nr <= gen_sn(11); + test_cc(1).src_timestamp <= gen_duration(6,0); + test_cc(1).payload <= gen_payload; + test_cc(2).kind <= NOT_ALIVE_UNREGISTERED; + test_cc(2).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(2).seq_nr <= gen_sn(15); + test_cc(2).src_timestamp <= gen_duration(7,0); + test_cc(2).payload <= gen_payload; + test_cc(3).kind <= NOT_ALIVE_DISPOSED; + test_cc(3).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(3).seq_nr <= gen_sn(37); + test_cc(3).src_timestamp <= gen_duration(8,0); + test_cc(3).payload <= gen_payload; + test_cc(4).kind <= ALIVE; + test_cc(4).writer_guid <= to_guid(GUIDPREFIX, DEFAULT_WRITER_ENTITYID); + test_cc(4).seq_nr <= gen_sn(50); + test_cc(4).src_timestamp <= gen_duration(9,0); + test_cc(4).payload <= gen_payload; + test_cc_fill <= 5; + new_cc <= '1'; + wait until rising_edge(clk); + new_cc <= '0'; + wait until rising_edge(clk); + + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(3)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e1); + gen_data(e1, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_data(e2, test_cc(4)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(4)); + push_reference; + wait_on_out_check; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [Request SN 10,15,37]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(5), numBits => int(35, CDR_LONG_WIDTH), bitmap => (5 => '1', 10 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1s", INFO); + Log("Send SN 10,15,37 to Endpoint 0", INFO); + test_time <= gen_duration(1,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e0); + gen_data(e0, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e0); + gen_data(e0, test_cc(3)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 0 sent ACKNACK [ACK SN <15]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <10, Request SN 10]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(10), numBits => int(1, CDR_LONG_WIDTH), bitmap => (0 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 1.5s", INFO); + test_time <= gen_duration(1,500); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + wait_on_idle; + + Log("Endpoint 2 sent ACKNACK [ACK SN <15, Request SN 15,16,47]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(33, CDR_LONG_WIDTH), bitmap => (0 => '1', 1 => '1', 32 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 2s", INFO); + Log("Send SN 15 to Endpoint 0 (GAP for SN 16, and ignore Request for SN 47)", INFO); + test_time <= gen_duration(2,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e2); + gen_data(e2, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e2); + gen_gap(gen_sn(16), gen_sn(17)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [Request SN 1-32]", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(1), numBits => int(32, CDR_LONG_WIDTH), bitmap => (0 to 31 => '1', others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Current Time: 3s", INFO); + Log("Send SN 10,11,15 to Endpoint 3 (GAPs for Rest)", INFO); + test_time <= gen_duration(3,0); + wait until rising_edge(clk); + wait until rising_edge(clk); -- Allow idle_sig to go low + gen_header(e3); + gen_gap(gen_sn(1), gen_sn(10)); + gen_data(e3, test_cc(0)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_data(e3, test_cc(1)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(12), gen_sn(15)); + gen_data(e3, test_cc(2)); + push_reference; + wait_on_out_check; + gen_header(e3); + gen_gap(gen_sn(16), gen_sn(32)); + push_reference; + wait_on_out_check; + wait_on_idle; + + Log("Insert Endpoint 4", INFO); + gen_endpoint_match_frame(e4, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + Log("Endpoint 3 sent ACKNACK [ACK SN <15] (Remove SN 5,6,7,8,9,10,11,12,13,14)", INFO); + endpoint := e3; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_ACKNACK; + sub.writerId := DEFAULT_WRITER_ENTITYID; + sub.readerId := endpoint.entityid; + sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); + sub.readerSNState := (base => gen_sn(15), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus_user); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(5)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(6)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(7)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(8)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(9)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(10)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(11)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(12)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(13)); + push_hc(REMOVE_CACHE_CHANGE, gen_sn(14)); + start_user_test; + wait_on_user_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + wait_on_idle; + + stim_done <= '1'; + wait_on_completion; + TranscriptOpen(RESULTS_FILE, APPEND_MODE); + SetTranscriptMirror; + ReportAlerts; + TranscriptClose; + std.env.stop; + wait; + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + empty_meta_prc : process + begin + empty_meta <= '0'; + wait until rd_meta = '1'; + wait until rising_edge(clk); + empty_meta <= '1'; + wait until rising_edge(clk); + end process; + + empty_user_prc : process + begin + empty_user <= '0'; + wait until rd_user = '1'; + wait until rising_edge(clk); + empty_user <= '1'; + wait until rising_edge(clk); + end process; + + rtps_full_prc : process + begin + full <= '0'; + wait until wr_sig = '1'; + wait until rising_edge(clk); + full <= '1'; + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(empty_meta = '1' and rd_meta = '1', "Input FIFO read signal high while empty signal high (meta)", ERROR); + alertif(empty_user = '1' and rd_user = '1', "Input FIFO read signal high while empty signal high (user)", ERROR); + alertif(full = '1' and wr_sig = '1', "Output FIFO write signal high while full signal high", ERROR); + end if; + end process; + + input_meta_prc : process(all) + begin + data_in_meta <= stimulus_meta.data(cnt_stim_meta); + last_word_in_meta <= stimulus_meta.last(cnt_stim_meta); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_meta <= 0; + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + else + case (stim_stage_meta) is + when IDLE => + if (start_meta = '1' and stimulus_meta.length /= 0) then + stim_stage_meta <= BUSY; + packet_sent_meta <= '0'; + end if; + when BUSY => + if (rd_meta = '1') then + if (cnt_stim_meta = stimulus_meta.length-1) then + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + cnt_stim_meta <= 0; + else + cnt_stim_meta <= cnt_stim_meta + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + input_user_prc : process(all) + begin + data_in_user <= stimulus_user.data(cnt_stim_user); + last_word_in_user <= stimulus_user.last(cnt_stim_user); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_user <= 0; + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + else + case (stim_stage_user) is + when IDLE => + if (start_user = '1' and stimulus_user.length /= 0) then + stim_stage_user <= BUSY; + packet_sent_user <= '0'; + end if; + when BUSY => + if (rd_user = '1') then + if (cnt_stim_user = stimulus_user.length-1) then + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + cnt_stim_user <= 0; + else + cnt_stim_user <= cnt_stim_user + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_out.empty and SB_hc.empty) then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + hc_prc : process (all) + variable stimulus : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + variable bool : boolean := FALSE; + begin + if (new_cc = '1') then + data_available <= '1'; + end if; + + if rising_edge(clk) then + hc_check_done <= '0'; + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + case (opcode_hc) is + when GET_CACHE_CHANGE => + bool := FALSE; + for i in 0 to test_cc_fill-1 loop + if (test_cc(i).seq_nr = seq_nr_hc) then + cc_instance_handle <= test_cc(i).instance; + cc_source_timestamp <= test_cc(i).src_timestamp; + cc_kind <= test_cc(i).kind; + stimulus := test_cc(i).payload; + stage_hc <= DONE; + bool := TRUE; + end if; + end loop; + if (not bool) then + stage_hc <= INVALID; + end if; + when GET_MIN_SN => + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(0).seq_nr; + stage_hc <= DONE; + when GET_MAX_SN => + data_available <= '0'; + stimulus := EMPTY_TEST_PACKET; + cc_seq_nr <= test_cc(test_cc_fill-1).seq_nr when (test_cc_fill /= 0) else SEQUENCENUMBER_UNKNOWN; + stage_hc <= DONE; + when others => + SB_hc.Check(std_logic_vector(to_unsigned(HISTORY_CACHE_OPCODE_TYPE'pos(opcode_hc), WORD_WIDTH))); + SB_hc.Check(std_logic_vector(seq_nr_hc(0))); + SB_hc.Check(std_logic_vector(seq_nr_hc(1))); + hc_check_done <= '1'; + stage_hc <= DONE; + end case; + end if; + when DONE => + if (get_data_hc = '1') then + alertif(stimulus = EMPTY_TEST_PACKET, "Requested empty Payload", FAILURE); + stage_hc <= PUSH; + cnt <= 0; + else + stage_hc <= IDLE; + end if; + when PUSH => + if (ready_in_hc = '1') then + cnt <= cnt + 1; + if (cnt = stimulus.length-1) then + stage_hc <= IDLE; + end if; + end if; + when INVALID => + stage_hc <= IDLE; + when others => + null; + end case; + end if; + + -- DEFAULT + ack_hc <= '0'; + valid_in_hc <= '0'; + data_in_hc <= (others => '0'); + last_word_in_hc <= '0'; + done_hc <= '0'; + ret_hc <= ERROR; + + case (stage_hc) is + when IDLE => + if (start_hc = '1') then + ack_hc <= '1'; + end if; + when DONE => + done_hc <= '1'; + ret_hc <= OK; + when PUSH => + valid_in_hc <= '1'; + data_in_hc <= stimulus.data(cnt); + last_word_in_hc <= stimulus.last(cnt); + when INVALID => + done_hc <= '1'; + ret_hc <= INVALID; + when others => + null; + end case; + end process; + + output_check_prc : process(all) + begin + if (SB_out.empty) then + out_check_done <= '1'; + else + out_check_done <= '0'; + end if; + if rising_edge(clk) then + if (wr_sig = '1') then + SB_out.Check(data_out); + end if; + end if; + end process; + + watchdog : process + begin + wait for 1 ms; + Alert("Test timeout", FAILURE); + std.env.stop; + end process; + +end architecture; \ No newline at end of file diff --git a/src/Tests/testbench.pro b/src/Tests/testbench.pro index 7f5d14f..a8ebccb 100644 --- a/src/Tests/testbench.pro +++ b/src/Tests/testbench.pro @@ -43,6 +43,14 @@ analyze Level_1/L1_rtps_reader_test1_vrk.vhd analyze Level_1/L1_rtps_reader_test1_trk.vhd analyze Level_0/L0_rtps_writer_test1_vrkdp.vhd analyze Level_0/L0_rtps_writer_test1_vbkdp.vhd +analyze Level_1/L1_rtps_writer_test1_vrkdp.vhd +analyze Level_1/L1_rtps_writer_test1_trkdp.vhd +analyze Level_1/L1_rtps_writer_test1_tbkdp.vhd +analyze Level_1/L1_rtps_writer_test1_vbkdp.vhd +analyze Level_1/L1_rtps_writer_test1_vrndp.vhd +analyze Level_1/L1_rtps_writer_test1_vrksp.vhd +analyze Level_1/L1_rtps_writer_test1_vrkdn.vhd +analyze Level_1/L1_rtps_writer_test1_trkdn.vhd #simulate L0_rtps_handler_test1 #simulate L0_rtps_handler_test2 @@ -68,4 +76,12 @@ analyze Level_0/L0_rtps_writer_test1_vbkdp.vhd #simulate L1_rtps_reader_test1_vrk #simulate L1_rtps_reader_test1_trk #simulate L0_rtps_writer_test1_vrkdp -simulate L0_rtps_writer_test1_vbkdp \ No newline at end of file +#simulate L0_rtps_writer_test1_vbkdp +simulate L1_rtps_writer_test1_vrkdp +#simulate L1_rtps_writer_test1_trkdp +#simulate L1_rtps_writer_test1_tbkdp +#simulate L1_rtps_writer_test1_vbkdp +#simulate L1_rtps_writer_test1_vrndp +#simulate L1_rtps_writer_test1_vrksp +#simulate L1_rtps_writer_test1_vrkdn +#simulate L1_rtps_writer_test1_trkdn \ No newline at end of file diff --git a/src/rtps_writer.vhd b/src/rtps_writer.vhd index b149d3f..f65873f 100644 --- a/src/rtps_writer.vhd +++ b/src/rtps_writer.vhd @@ -63,7 +63,8 @@ entity rtps_writer is last_word_in_hc : in std_logic; cc_instance_handle : in INSTANCE_HANDLE_TYPE; cc_kind : in CACHE_CHANGE_KIND_TYPE; - cc_source_timestamp : in TIME_TYPE + cc_source_timestamp : in TIME_TYPE; + cc_seq_nr : in SEQUENCENUMBER_TYPE ); end entity; @@ -147,7 +148,7 @@ architecture arch of rtps_writer is res_time : TIME_TYPE; ack_seq_nr_base : SEQUENCENUMBER_TYPE; req_seq_nr_base : SEQUENCENUMBER_TYPE; - req_seq_nr_bitmap : std_logic_vector(WORD_WIDTH-1 downto 0); + req_seq_nr_bitmap : std_logic_vector(0 to WORD_WIDTH-1); end record; -- Zero initialized Endpoint Data constant ZERO_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := ( @@ -171,7 +172,7 @@ architecture arch of rtps_writer is res_time : TIME_TYPE; ack_seq_nr_base : SEQUENCENUMBER_TYPE; req_seq_nr_base : SEQUENCENUMBER_TYPE; - req_seq_nr_bitmap : std_logic_vector(WORD_WIDTH-1 downto 0); + req_seq_nr_bitmap : std_logic_vector(0 to WORD_WIDTH-1); field_flag : std_logic_vector(0 to EMF_FLAG_WIDTH-1); end record; -- Zero initialized Endpoint Data Latch @@ -196,7 +197,9 @@ architecture arch of rtps_writer is -- FSM state latch. Used to transition dynamically to different states from the same state. signal return_stage, return_stage_next : STAGE_TYPE := IDLE; -- General Purpose Counter - signal cnt, cnt_next : natural range 0 to 11 := 0; + signal cnt, cnt_next : natural range 0 to 13 := 0; + -- Counter Latch. Used to transition dynamically to different sub-states from the same state. + signal return_cnt, return_cnt_next : natural range 0 to 13 := 0; -- Packet Opcode Latch (RTPS Message ID) signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := (others => '0'); -- Metatraffic Opcode Latch @@ -237,6 +240,8 @@ architecture arch of rtps_writer is signal historical_push, historical_push_next : std_logic := '0'; -- Signifies that the first half of a GAP Message has been written, and needs to be "closed" signal gap_in_progress, gap_in_progress_next : std_logic := '0'; + -- Signifies that the GAP is the Last Submessage + signal gap_is_last, gap_is_last_next : std_logic := '0'; -- Signal containing the RTPS Heartbeat Count Field signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0) := (others => '0'); -- Signal containing the lowest common Sequence Number ACKed by ALL remote Readers @@ -268,7 +273,7 @@ architecture arch of rtps_writer is -- Signal used to pass Sequence Numbers from main to memory process signal seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; -- Signal used to pass the Request Sequence Number Bitmap from main to memory process - signal req_seq_nr_bitmap, req_seq_nr_bitmap_next : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal req_seq_nr_bitmap, req_seq_nr_bitmap_next : std_logic_vector(0 to WORD_WIDTH-1) := (others => '0'); -- Signal used to iterate through Request Bitmaps signal req_bitmap_pos, req_bitmap_pos_next : natural range 0 to req_seq_nr_bitmap'length-1 := 0; -- Test signal used for testbench synchronisation @@ -378,10 +383,10 @@ begin -- METATRAFFIC_OPERATION State handling the Metatraffic Operations -- LATCH_SRC_ADDR Store source IPv4 Address -- LATCH_ACKNACK Store ACKNACK Heartbeat Sequence Numbers + -- PARSE_NACK_BITMAP Parse the bitmap containing the requested Sequence Numbers + -- PROCESS_NACK Process Requested (Negatively Acknowledged) Sequence Numbers -- PROCESS_ACK Process Acknowledged Sequence Numbers. Assert Liveliness of remore Reader. -- UPDATE_GLOBAL_ACK Iterate over all remote Readers and update the global_ack_seq_nr_base to the lowest common ACKed Sequence Number - -- PROCESS_NACK Process Requested (Negatively Acknowledged) Sequence Numbers - -- PARSE_NACK_BITMAP Parse the bitmap containing the requested Sequence Numbers -- ENDPOINT_STALE_CHECK Check remote Endpoint Entries for Liveliness Lease Expiration, and Response Timeouts. -- GET_MIN_SN Get the lowest available Sequence Number from the History Cache -- GET_MAX_SN Get the highest available Sequence Number from the History Cache @@ -437,6 +442,10 @@ begin new_push_next <= new_push; historical_push_next <= historical_push; assert_liveliness_latch_next<= assert_liveliness_latch; + bitmap_cnt_next <= bitmap_cnt; + bitmap_latch_next <= bitmap_latch; + gap_is_last_next <= gap_is_last; + return_cnt_next <= return_cnt; -- DEFAULT Unregistered mem_opcode <= NOP; opcode_hc <= NOP; @@ -477,36 +486,51 @@ begin -- New Cache Change in HC if (data_available = '1') then - -- Propagate Liveliness - alive_sig <= '1'; + start_hc <= '1'; + opcode_hc <= GET_MAX_SN; - new_push_next <= '1'; - - stage_next <= GET_MAX_SN; - cnt_next <= 0; + if (ack_hc = '1') then + -- Propagate Liveliness + alive_sig <= '1'; + + new_push_next <= '1'; + + stage_next <= GET_MAX_SN; + cnt_next <= 0; + end if; -- Manual Liveliness Assertion elsif (LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS and assert_liveliness_latch = '1') then - -- Propagate Liveliness - alive_sig <= '1'; + start_hc <= '1'; + opcode_hc <= GET_MIN_SN; - -- Reset - heartbeat_time_next <= time + HEARTBEAT_PERIOD; - - -- Increment Heartbeat Count - count_next <= count + 1; - - stage_next <= GET_MIN_SN; - cnt_next <= 0; + if (ack_hc = '1') then + -- Propagate Liveliness + alive_sig <= '1'; + + -- Reset + heartbeat_time_next <= time + HEARTBEAT_PERIOD; + + -- Increment Heartbeat Count + count_next <= count + 1; + + stage_next <= GET_MIN_SN; + cnt_next <= 0; + end if; -- Heartbeat Timeout elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and time >= heartbeat_time) then - -- Reset - heartbeat_time_next <= time + HEARTBEAT_PERIOD; + start_hc <= '1'; + opcode_hc <= GET_MIN_SN; - -- Increment Heartbeat Count - count_next <= count + 1; - - stage_next <= GET_MIN_SN; - cnt_next <= 0; + if (ack_hc = '1') then + -- Reset + heartbeat_time_next <= time + HEARTBEAT_PERIOD; + + -- Increment Heartbeat Count + count_next <= count + 1; + + stage_next <= GET_MIN_SN; + cnt_next <= 0; + end if; -- Stale Check Timeout elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and time >= check_time) then -- Memory Operation Guard @@ -662,7 +686,7 @@ begin cnt_next <= 0; mem_op_start <= '1'; mem_opcode <= SEARCH_ENDPOINT; - mem_field_flags <= EMF_ACK_SEQ_NR_BASE_FLAG or EMF_RES_TIME_FLAG or EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG; + mem_field_flags <= EMF_ACK_SEQ_NR_BASE_FLAG or EMF_RES_TIME_FLAG; when others => stage_next <= SKIP_PACKET; end case; @@ -722,15 +746,26 @@ begin lease_deadline <= TIME_INVALID; end if; -- Initialize ACK Sequence Number - seq_nr <= SEQUENCENUMBER_UNKNOWN when (reader_flags(READER_IS_BEST_EFFORT_FLAG) = '1') else (others => (others => '0')); + if (reader_flags(READER_IS_BEST_EFFORT_FLAG) = '1') then + seq_nr <= SEQUENCENUMBER_UNKNOWN; + elsif (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and reader_flags(READER_EXPECTS_HISTORICAL_DATA_FLAG) = '1') then + seq_nr <= (others => (others => '0')); + else + seq_nr <= global_ack_seq_nr_base; + end if; -- Reader needs Historical Data if (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and reader_flags(READER_EXPECTS_HISTORICAL_DATA_FLAG) = '1') then - -- Send Historical Data - historical_push_next <= '1'; + start_hc <= '1'; + opcode_hc <= GET_MIN_SN; - stage_next <= GET_MIN_SN; - cnt_next <= 0; + if (ack_hc = '1') then + -- Send Historical Data + historical_push_next <= '1'; + + stage_next <= GET_MIN_SN; + cnt_next <= 0; + end if; else -- DONE stage_next <= IDLE; @@ -763,7 +798,7 @@ begin if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then -- Global ACK SN possibly changed if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and global_ack_seq_nr_base /= SEQUENCENUMBER_UNKNOWN) then - -- NOTE: We are triggering an Global ACK SN Update on each Participant Removal. This should not happen as often, and is therefore acceptable. + -- NOTE: We are triggering a Global ACK SN Update on each Participant Removal. This should not happen as often, and is therefore acceptable. -- Otherwise we need to check the ack_seq_nr_base in the other substate and mark when equal to current Global ACK SN. -- Update Global ACK stage_next <= UPDATE_GLOBAL_ACK; @@ -813,45 +848,130 @@ begin if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then -- Input FIFO Guard if (empty_user = '0') then - rd_user <= '1'; - cnt_next <= cnt + 1; - case (cnt) is -- ReaderSNState.Base 1/2 - when 1 => + when 0 => nack_base_next(0) <= unsigned(data_in_user); + rd_user <= '1'; + cnt_next <= cnt + 1; -- ReaderSNState.Base 2/2 - when 2 => + when 1 => nack_base_next(1) <= unsigned(data_in_user); + rd_user <= '1'; + cnt_next <= cnt + 1; -- ReaderSNState.NumBits - when 3 => + when 2 => ack_base_next <= nack_base - 1; long_latch_next <= data_in_user; bitmap_cnt_next <= unsigned(round_slv(data_in_user(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length)); + rd_user <= '1'; + cnt_next <= cnt + 1; cnt2_next <= 0; -- ReaderSNState.Bitmap - when 4 => + when 3 => -- Read Bitmap if (cnt2 < bitmap_cnt) then cnt2_next <= cnt2 + 1; bitmap_latch_next(cnt2) <= data_in_user; + rd_user <= '1'; - -- Keep Sub-State - cnt_next <= cnt; else - stage_next <= PROCESS_ACK; + -- NACK Bitmap is not Empty + if (long_latch /= (long_latch'range => '0')) then + nack_bitmap_pos_next <= 0; + stage_next <= PARSE_NACK_BITMAP; + cnt_next <= 0; + else + stage_next <= PROCESS_ACK; + end if; end if; when others => null; end case; end if; end if; + when PARSE_NACK_BITMAP => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + tmp_bitmap := to_slv_bitmap(bitmap_latch); + + -- NOTE: nack_bitmap_pos is used for the NACK Bitmap, and cnt is used for the Request Bitmap. + + case (cnt) is + -- Find Beginning + when 0 => + -- First Requested Sequence Number + if (tmp_bitmap(nack_bitmap_pos) = '1') then + req_seq_nr_bitmap_next <= (others => '0'); + req_bitmap_pos_next <= 0; + cnt_next <= cnt + 1; + else + nack_bitmap_pos_next <= nack_bitmap_pos + 1; + nack_base_next <= nack_base + 1; + end if; + -- Parse Rest + when 1 => + nack_bitmap_pos_next <= nack_bitmap_pos + 1; + req_bitmap_pos_next <= req_bitmap_pos + 1; + -- Next Requested Sequence Number + if (tmp_bitmap(nack_bitmap_pos) = '1') then + req_seq_nr_bitmap_next(req_bitmap_pos) <= '1'; + end if; + + -- End of Bitmap + if (nack_bitmap_pos = unsigned(long_latch) or req_bitmap_pos = req_seq_nr_bitmap'length-1) then + stage_next <= PROCESS_NACK; + end if; + -- Find Requested + when others => + null; + end case; + end if; + when PROCESS_NACK => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Memory Operation Guard + if (mem_op_done = '1') then + -- No Pending Response + if (mem_endpoint_data.res_time = TIME_INVALID) then + mem_op_start <= '1'; + mem_opcode <= UPDATE_ENDPOINT; + mem_field_flags <= EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG or EMF_RES_TIME_FLAG; + seq_nr <= nack_base; + if (ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then + res_time <= time + ACKNACK_RESPONSE_DELAY; + -- NOTE: Last Bit denotes if this is Response or Suppression Delay + res_time(1)(0) <= '0'; + + -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock) + -- Update Check Time + if ((time + ACKNACK_RESPONSE_DELAY) < check_time) then + check_time_next <= time + ACKNACK_RESPONSE_DELAY; + end if; + else + res_time <= TIME_INVALID; + end if; + -- Currently in Acknack Response Delay + elsif (mem_endpoint_data.res_time(1)(0) = '0') then + mem_op_start <= '1'; + mem_opcode <= UPDATE_ENDPOINT; + mem_field_flags <= EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG; + seq_nr <= nack_base; + end if; + + -- DONE + stage_next <= PROCESS_ACK; + end if; + end if; when PROCESS_ACK => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then -- Wait for Endpoint Search if (mem_op_done = '1') then + -- DEFAULT + stage_next <= SKIP_PACKET; + -- Known Remote Endpoint if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then @@ -877,27 +997,15 @@ begin mem_field_flags <= EMF_LEASE_DEADLINE_FLAG or EMF_ACK_SEQ_NR_BASE_FLAG; seq_nr <= ack_base; -- NOTE: The global_ack_seq_nr_base contains the lowest SN of all remote Endpoints. - -- It only needs to be updated, if the remote Endpoint with the lowest ACKed Sn is updated. - -- This does not necesserily mean, that the Global ACK SN will be updated, as there can + -- It only needs to be updated, if the remote Endpoint with the lowest ACKed SN is updated. + -- This does not necesserily mean, that the Global ACK SN will change, as there can -- be multiple remote Endpoints with the same lowest ACK SN. -- Global ACK SN needs updating if (mem_endpoint_data.ack_seq_nr_base = global_ack_seq_nr_base) then stage_next <= UPDATE_GLOBAL_ACK; cnt_next <= 0; end if; - else - -- NACK Bitmap is not Empty - if (long_latch /= (long_latch'range => '0')) then - stage_next <= PROCESS_NACK; - cnt_next <= 0; - else - -- DONE - stage_next <= SKIP_PACKET; - end if; end if; - else - -- Skip - stage_next <= SKIP_PACKET; end if; end if; end if; @@ -922,16 +1030,10 @@ begin if (new_global_ack /= global_ack_seq_nr_base) then -- Mark common ACKed SNs global_ack_seq_nr_base_next <= global_ack_seq_nr_base + 1; - cnt_next <= 2; + cnt_next <= cnt + 1; else - -- NACK Bitmap is not Empty - if (long_latch /= (long_latch'range => '0')) then - stage_next <= PROCESS_NACK; - cnt_next <= 0; - else - -- DONE - stage_next <= SKIP_PACKET; - end if; + -- DONE + stage_next <= SKIP_PACKET when (is_meta = '0') else IDLE; end if; else -- NOTE: Remote Endpoints with RELIABILITY BEST_EFFORT have a ack_seq_nr_base = SEQUENCENUMBER_UNKNOWN, since @@ -960,17 +1062,10 @@ begin -- Wait for Operation Acknowledgement if (ack_hc = '1') then - start_hc <= '1'; -- Exit Condition if (global_ack_seq_nr_base = new_global_ack) then - -- NACK Bitmap is not Empty - if (long_latch /= (long_latch'range => '0')) then - stage_next <= PROCESS_NACK; - cnt_next <= 0; - else - -- DONE - stage_next <= SKIP_PACKET; - end if; + -- DONE + stage_next <= SKIP_PACKET when (is_meta = '0') else IDLE; else global_ack_seq_nr_base_next <= global_ack_seq_nr_base + 1; end if; @@ -979,142 +1074,6 @@ begin end case; end if; end if; - when PROCESS_NACK => - -- Synthesis Guard - if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then - -- Memory Operation Guard - if (mem_op_done = '1') then - - case (cnt) is - -- Initiate Bitmap Parsing - when 0 => - -- No scheduled Acknack Response - if (mem_endpoint_data.res_time = TIME_INVALID) then - req_seq_nr_bitmap_next <= (others => '0'); - - stage_next <= PARSE_NACK_BITMAP; - cnt_next <= 0; - -- Currently in Acknack Response Delay - elsif (mem_endpoint_data.res_time(1)(0) = '0') then - req_seq_nr_bitmap_next <= mem_endpoint_data.req_seq_nr_bitmap; - - -- NOTE: If we already received a ACKNACK with requests, then we only add the requested SN that fit in the existing - -- "Request SN window" (i.e. the req_seq_nr_bitmap). We need to "align" the Bitmaps for that purpose. - if (nack_base > mem_endpoint_data.req_seq_nr_base) then - stage_next <= PARSE_NACK_BITMAP; - cnt_next <= 2; - elsif (nack_base = mem_endpoint_data.req_seq_nr_base) then - stage_next <= PARSE_NACK_BITMAP; - cnt_next <= 3; - else - stage_next <= PARSE_NACK_BITMAP; - cnt_next <= 1; - end if; - end if; - -- Check Requested Sequence Numbers - when 1 => - if (mem_endpoint_data.res_time = TIME_INVALID) then - mem_op_start <= '1'; - mem_opcode <= UPDATE_ENDPOINT; - mem_field_flags <= EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG or EMF_RES_TIME_FLAG; - seq_nr <= nack_base; - if (ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then - res_time <= time + ACKNACK_RESPONSE_DELAY; - -- NOTE: Last Bit denotes if this is Response or Suppression Delay - res_time(1)(0) <= '0'; - - -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock) - -- Update Check Time - if ((time + ACKNACK_RESPONSE_DELAY) < check_time) then - check_time_next <= time + ACKNACK_RESPONSE_DELAY; - end if; - else - res_time <= TIME_INVALID; - end if; - -- Currently in Acknack Response Delay - elsif (mem_endpoint_data.res_time(1)(0) = '0') then - -- New Sequence Numbers Requested - if ((req_seq_nr_bitmap or mem_endpoint_data.req_seq_nr_bitmap) /= mem_endpoint_data.req_seq_nr_bitmap) then - mem_op_start <= '1'; - mem_opcode <= UPDATE_ENDPOINT; - mem_field_flags <= EMF_REQ_SEQ_NR_BITMAP_FLAG; - end if; - end if; - - -- DONE - stage_next <= SKIP_PACKET; - when others => - null; - end case; - end if; - end if; - when PARSE_NACK_BITMAP => - -- Synthesis Guard - if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then - tmp_bitmap := to_slv_bitmap(bitmap_latch); - - -- NOTE: nack_bitmap_pos is used for the NACK Bitmap, and cnt is used for the Request Bitmap. - - case (cnt) is - -- Find Beginning - when 0 => - -- First Requested Sequence Number - if (tmp_bitmap(nack_bitmap_pos) = '1') then - cnt_next <= 3; - else - nack_bitmap_pos_next <= nack_bitmap_pos + 1; - nack_base_next <= nack_base + 1; - end if; - -- Adjust NACK Bitmap (REQ Base > NACK Base) - when 1 => - -- Bitmaps Adjusted - if (nack_base = mem_endpoint_data.req_seq_nr_base) then - cnt_next <= 3; - else - -- Reached End of Bitmap (NACK Bitmap out of window) - if (nack_bitmap_pos = unsigned(long_latch)) then - -- DONE (Nothing to update) - stage_next <= SKIP_PACKET; - else - nack_bitmap_pos_next <= nack_bitmap_pos + 1; - nack_base_next <= nack_base + 1; - end if; - end if; - -- Abjust REQ Bitmap (REQ Base < NACK Base) - when 2 => - -- Bitmaps Adjusted - if (nack_base = mem_endpoint_data.req_seq_nr_base) then - cnt_next <= 3; - else - -- Reached End of Bitmap (NACK Bitmap out of window) - if (req_bitmap_pos = req_seq_nr_bitmap'length-1) then - -- DONE (Nothing to update) - stage_next <= SKIP_PACKET; - else - -- NOTE: Instead of incrementing the req_seq_nr_base, we decrement the nack_base - req_bitmap_pos_next <= req_bitmap_pos + 1; - nack_base_next <= nack_base - 1; - end if; - end if; - -- Parse Rest - when 3 => - nack_bitmap_pos_next <= nack_bitmap_pos + 1; - -- Next Requested Sequence Number - if (tmp_bitmap(nack_bitmap_pos) = '1') then - req_bitmap_pos_next <= req_bitmap_pos + 1; - req_seq_nr_bitmap_next(req_bitmap_pos) <= '1'; - end if; - - -- End of Bitmap - if (nack_bitmap_pos = unsigned(long_latch) or req_bitmap_pos = req_seq_nr_bitmap'length-1) then - stage_next <= PROCESS_NACK; - cnt_next <= 1; - end if; - -- Find Requested - when others => - null; - end case; - end if; when ENDPOINT_STALE_CHECK => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -1159,13 +1118,11 @@ begin -- Get Additional Data mem_op_start <= '1'; mem_opcode <= GET_ENDPOINT; - mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG; + mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG or EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG; -- Send Requests stage_next <= HANDLE_REQUESTS; - cnt_next <= 0; - next_seq_nr_next <= mem_endpoint_data.req_seq_nr_base; - req_bitmap_pos_next <= 0; + cnt_next <= 4; end if; else -- Update Check Time @@ -1222,169 +1179,156 @@ begin end if; end if; when GET_MIN_SN => - case (cnt) is - -- GET MIN Sequence Number - when 0 => - start_hc <= '1'; - opcode_hc <= GET_MIN_SN; - - if (ack_hc = '1') then - start_hc <= '0'; - cnt_next <= cnt + 1; - end if; - -- READ MIN Sequence Number 1/2 - when 1 => - ready_in_hc <= '1'; - -- Input Guard - if (valid_in_hc = '1') then - min_sn_next(0) <= unsigned(data_in_hc); - cnt_next <= cnt + 1; - end if; - -- READ MIN Sequence Number 2/2 - when 2 => - ready_in_hc <= '1'; - -- Input Guard - if (valid_in_hc = '1') then - min_sn_next(1) <= unsigned(data_in_hc); - assert (last_word_in_hc = '1') severity FAILURE; - - if (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and historical_push = '1') then - stage_next <= HANDLE_HISTORICAL; - cnt_next <= 4; -- Pre-Check Sub-state - elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS or LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS) then - stage_next <= HANDLE_HEARTBEATS; - cnt_next <= 0; - else - assert FALSE severity FAILURE; - end if; - end if; - when others => - null; - end case; + -- Wait for HC + if (done_hc = '1') then + assert (ret_hc = OK) severity FAILURE; + + min_sn_next <= cc_seq_nr; + + if (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and historical_push = '1') then + stage_next <= HANDLE_HISTORICAL; + cnt_next <= 4; -- Pre-Check Sub-state + elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS or LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS) then + stage_next <= HANDLE_HEARTBEATS; + cnt_next <= 0; + else + assert FALSE severity FAILURE; + end if; + end if; when GET_MAX_SN => - case (cnt) is - -- GET MAX Sequence Number - when 0 => - start_hc <= '1'; - opcode_hc <= GET_MAX_SN; + -- Wait for HC + if (done_hc = '1') then + assert (ret_hc = OK) severity FAILURE; + + max_sn_next <= cc_seq_nr; + + -- EXIT + if (new_push = '1') then + -- NOTE: If PUSH_MODE = FALSE, we manually update the last_seq_nr signal, since this is + -- not done anymore. - if (ack_hc = '1') then - start_hc <= '0'; - cnt_next <= cnt + 1; - end if; - -- READ MAX Sequence Number 1/2 - when 1 => - ready_in_hc <= '1'; - -- Input Guard - if (valid_in_hc = '1') then - max_sn_next(0) <= unsigned(data_in_hc); - cnt_next <= cnt + 1; - end if; - -- READ MAX Sequence Number 2/2 - when 2 => - ready_in_hc <= '1'; - -- Input Guard - if (valid_in_hc = '1') then - max_sn_next(1) <= unsigned(data_in_hc); - assert (last_word_in_hc = '1') severity FAILURE; - - -- EXIT - if (new_push = '1') then - - -- NOTE: If PUSH_MODE = FALSE, we manually update the last_seq_nr signal, since thsi is - -- not done anymore. - - -- Synthesis Guard - if (PUSH_MODE) then - stage_next <= HANDLE_NEW; - cnt_next <= 0; - else - tmp_dw := (0 => max_sn(0), 1 => unsigned(data_in_hc)); - - -- New higher Sequence Number Available - if (tmp_dw /= SEQUENCENUMBER_UNKNOWN and tmp_dw > last_seq_nr) then - last_seq_nr_next <= tmp_dw; - end if; - -- DONE - stage_next <= IDLE; - end if; - else - assert FALSE severity FAILURE; + -- Synthesis Guard + if (PUSH_MODE) then + stage_next <= HANDLE_NEW; + cnt_next <= 0; + else + -- New higher Sequence Number Available + if (cc_seq_nr /= SEQUENCENUMBER_UNKNOWN and cc_seq_nr > last_seq_nr) then + last_seq_nr_next <= cc_seq_nr; end if; + -- DONE + stage_next <= IDLE; end if; - when others => - null; - end case; + else + assert FALSE severity FAILURE; + end if; + end if; when HANDLE_REQUESTS => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then - case (cnt) is - -- Find SN - when 0 => - -- End of Bitmap - if (req_bitmap_pos = req_seq_nr_bitmap'length) then + -- Wait for Endpoint Data + if (mem_op_done = '1') then + case (cnt) is + -- Next Bitmap Pos + when 0 => + req_bitmap_pos_next <= req_bitmap_pos + 1; + next_seq_nr_next <= next_seq_nr + 1; + cnt_next <= cnt + 1; + -- Find SN + when 1 => + -- End of Bitmap + if (req_bitmap_pos = req_seq_nr_bitmap'length-1) then if (gap_in_progress = '1') then -- NOTE: We close the GAP, than come back here, and exit through the else branch. -- Close GAP Message gap_in_progress_next <= '0'; stage_next <= SEND_GAP_B; - return_stage_next <= HANDLE_REQUESTS; cnt_next <= 0; + -- DONE + return_stage_next <= ENDPOINT_STALE_CHECK; + return_cnt_next <= 2; + gap_is_last_next <= '1'; else -- DONE stage_next <= ENDPOINT_STALE_CHECK; cnt_next <= 2; end if; - -- Next Requested SN found - elsif (mem_endpoint_data.req_seq_nr_bitmap(req_bitmap_pos) = '1') then - cnt_next <= cnt + 1; - else - req_bitmap_pos_next <= req_bitmap_pos + 1; - next_seq_nr_next <= next_seq_nr + 1; - end if; - -- Get SN - when 1 => - start_hc <= '1'; - opcode_hc <= GET_CACHE_CHANGE; - seq_nr_hc <= next_seq_nr; - - -- Wait until Operation Acknowledgement - if (ack_hc = '1') then - start_hc <= '0'; - cnt_next <= cnt + 1; - end if; - -- Handle Request - when 2 => - -- Wait until Operation Response - if (done_hc = '1') then - -- Wait for Operation Response - if (ret_hc = OK) then - get_data_hc <= '1'; - if (gap_in_progress = '1') then - -- Close GAP and send DATA - gap_in_progress_next <= '0'; - stage_next <= SEND_GAP_B; - return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; - cnt_next <= 0; - else - -- Send DATA - stage_next <= SEND_HEADER; - return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; - cnt_next <= 0; - end if; - elsif (ret_hc = INVALID) then - if (gap_in_progress = '0') then - -- Open new GAP - gap_in_progress_next <= '1'; - stage_next <= SEND_HEADER; - return_stage_next <= SEND_GAP_A; - cnt_next <= 0; + -- Next Requested SN found + elsif (mem_endpoint_data.req_seq_nr_bitmap(req_bitmap_pos) = '1') then + cnt_next <= cnt + 1; + elsif (gap_in_progress = '1') then + -- Close GAP Message + gap_in_progress_next <= '0'; + stage_next <= SEND_GAP_B; + cnt_next <= 0; + -- Continue + return_stage_next <= HANDLE_REQUESTS; + return_cnt_next <= 0; + gap_is_last_next <= '1'; + else + req_bitmap_pos_next <= req_bitmap_pos + 1; + next_seq_nr_next <= next_seq_nr + 1; + end if; + -- Get SN + when 2 => + start_hc <= '1'; + opcode_hc <= GET_CACHE_CHANGE; + seq_nr_hc <= next_seq_nr; + + -- Wait until Operation Acknowledgement + if (ack_hc = '1') then + cnt_next <= cnt + 1; + end if; + -- Handle Request + when 3 => + -- Wait until Operation Response + if (done_hc = '1') then + -- Wait for Operation Response + if (ret_hc = OK) then + -- Only request Payload if necessary (Contains DATA or Serialized Key) + if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then + get_data_hc <= '1'; + end if; + + if (gap_in_progress = '1') then + -- Close GAP and send DATA + gap_in_progress_next <= '0'; + stage_next <= SEND_GAP_B; + cnt_next <= 0; + return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; + return_cnt_next <= 0; + else + -- Send DATA + stage_next <= SEND_HEADER; + cnt_next <= 0; + return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; + return_cnt_next <= 0; + end if; + elsif (ret_hc = INVALID) then + if (gap_in_progress = '0') then + -- Open new GAP + gap_in_progress_next <= '1'; + stage_next <= SEND_HEADER; + cnt_next <= 0; + return_stage_next <= SEND_GAP_A; + return_cnt_next <= 0; + else + -- Continue + req_bitmap_pos_next <= req_bitmap_pos + 1; + next_seq_nr_next <= next_seq_nr + 1; + cnt_next <= 1; + end if; end if; end if; - end if; - when others => - null; - end case; + -- Initialize + when 4 => + next_seq_nr_next <= mem_endpoint_data.req_seq_nr_base; + req_bitmap_pos_next <= 0; + cnt_next <= 1; + when others => + null; + end case; + end if; end if; when HANDLE_HEARTBEATS => -- Synthesis Guard @@ -1421,8 +1365,9 @@ begin stage_next <= IDLE; else stage_next <= SEND_HEADER; - return_stage_next <= SEND_HEARTBEAT; cnt_next <= 0; + return_stage_next <= SEND_HEARTBEAT; + return_cnt_next <= 0; end if; when others => null; @@ -1442,6 +1387,7 @@ begin stage_next <= IDLE; else last_seq_nr_next <= last_seq_nr + 1; + next_seq_nr_next <= last_seq_nr + 1; cnt_next <= cnt + 1; end if; -- Get First Reader @@ -1463,14 +1409,13 @@ begin -- ACK newly sent Cache Changes if Writer is BEST_EFFORT, or if all remore Readers are BEST_EFFORT if (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS or global_ack_seq_nr_base = SEQUENCENUMBER_UNKNOWN) then start_hc <= '1'; - opcode_hc <= ACK_CACHE_CHANGE; + opcode_hc <= REMOVE_CACHE_CHANGE when (DURABILITY_QOS = VOLATILE_DURABILITY_QOS) else ACK_CACHE_CHANGE; seq_nr_hc <= last_seq_nr; -- NOTE: Ignore return Code -- Wait until Operation Acknowledgement if (ack_hc = '1') then - start_hc <= '0'; -- EXIT cnt_next <= 0; end if; @@ -1485,7 +1430,6 @@ begin -- Wait until Operation Acknowledgement if (ack_hc = '1') then - start_hc <= '0'; cnt_next <= cnt + 1; end if; end if; @@ -1502,8 +1446,9 @@ begin end if; stage_next <= SEND_HEADER; - return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; cnt_next <= 0; + return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; + return_cnt_next <= 0; -- Cache Change Unavailable else report "New Cache Change unavailable" severity WARNING; @@ -1537,8 +1482,14 @@ begin -- Close GAP Message gap_in_progress_next <= '0'; stage_next <= SEND_GAP_B; - return_stage_next <= HANDLE_HISTORICAL; cnt_next <= 0; + gap_is_last_next <= '1'; + -- DONE + return_stage_next <= IDLE; + return_cnt_next <= 0; + + -- Reset + historical_push_next <= '0'; else -- Reset historical_push_next <= '0'; @@ -1558,12 +1509,15 @@ begin start_hc <= '1'; opcode_hc <= NACK_CACHE_CHANGE; seq_nr_hc <= next_seq_nr; - -- NOTE: Ignore Return Code + -- Update Global ACK + if (next_seq_nr <= global_ack_seq_nr_base) then + global_ack_seq_nr_base_next <= next_seq_nr - 1; + end if; + -- Wait until Operation Acknowledgement if (ack_hc = '1') then - start_hc <= '0'; cnt_next <= cnt + 1; end if; end if; @@ -1575,7 +1529,6 @@ begin -- Wait until Operation Acknowledgement if (ack_hc = '1') then - start_hc <= '0'; cnt_next <= cnt + 1; end if; -- Handle Request @@ -1593,21 +1546,27 @@ begin -- Close GAP and send DATA gap_in_progress_next <= '0'; stage_next <= SEND_GAP_B; - return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; cnt_next <= 0; + return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; + return_cnt_next <= 0; else -- Send DATA stage_next <= SEND_HEADER; - return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; cnt_next <= 0; + return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; + return_cnt_next <= 0; end if; elsif (ret_hc = INVALID) then if (gap_in_progress = '0') then -- Open new GAP gap_in_progress_next <= '1'; stage_next <= SEND_HEADER; - return_stage_next <= SEND_GAP_A; cnt_next <= 0; + return_stage_next <= SEND_GAP_A; + return_cnt_next <= 0; + else + -- Continue + cnt_next <= 0; end if; end if; end if; @@ -1660,7 +1619,7 @@ begin data_out_rtps <= GUIDPREFIX(2); -- Continue with respective RTPS Submessage stage_next <= return_stage; - cnt_next <= 0; + cnt_next <= return_cnt; when others => null; end case; @@ -1700,7 +1659,8 @@ begin data_flag <= '1' when (cc_kind = ALIVE) else '0'; key_flag <= '1' when (WITH_KEY and cc_kind /= ALIVE) else '0'; qos_flag <= '1' when (cc_kind /= ALIVE or WITH_KEY or mem_endpoint_data.flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') else '0'; - cnt_next <= cnt + 1; + wr_rtps <= '1'; + cnt_next <= cnt + 1; -- extraFlags, octetsToInlineQoS when 1 => data_out_rtps <= x"0000" & std_logic_vector(to_unsigned(16, 16)); @@ -1731,7 +1691,7 @@ begin cnt_next <= cnt + 1; -- Need to send Status Info elsif (cc_kind /= ALIVE) then - cnt_next <= cnt + 5; + cnt_next <= cnt + 6; -- Reader expect in-line QoS elsif(mem_endpoint_data.flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') then stage_next <= SEND_INLINE_QOS; @@ -1741,12 +1701,11 @@ begin stage_next <= SEND_DATA_B; cnt_next <= 0; else + last_word_out_rtps <= '1'; -- Continue if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then - stage_next <= HANDLE_REQUESTS; - cnt_next <= 0; - req_bitmap_pos_next <= req_bitmap_pos + 1; - next_seq_nr_next <= next_seq_nr + 1; + stage_next <= HANDLE_REQUESTS; + cnt_next <= 0; elsif (PUSH_MODE and new_push = '1') then stage_next <= HANDLE_NEW; cnt_next <= 4; @@ -1757,36 +1716,44 @@ begin assert FALSE severity FAILURE; end if; end if; - -- Key Hash 1/4 + -- Key Hash PID when 6 => -- Synthesis Guard if (WITH_KEY) then - data_out_rtps <= std_logic_vector(cc_instance_handle(0)); - wr_rtps <= '1'; + data_out_rtps <= PID_KEY_HASH & std_logic_vector(to_unsigned(16, SUBMESSAGE_LENGTH_WIDTH)); + wr_rtps <= '1'; cnt_next <= cnt + 1; end if; - -- Key Hash 2/4 + -- Key Hash 1/4 when 7 => -- Synthesis Guard if (WITH_KEY) then - data_out_rtps <= std_logic_vector(cc_instance_handle(1)); - wr_rtps <= '1'; + data_out_rtps <= std_logic_vector(cc_instance_handle(0)); + wr_rtps <= '1'; cnt_next <= cnt + 1; end if; - -- Key Hash 3/4 + -- Key Hash 2/4 when 8 => -- Synthesis Guard if (WITH_KEY) then - data_out_rtps <= std_logic_vector(cc_instance_handle(2)); - wr_rtps <= '1'; + data_out_rtps <= std_logic_vector(cc_instance_handle(1)); + wr_rtps <= '1'; cnt_next <= cnt + 1; end if; - -- Key Hash 4/4 + -- Key Hash 3/4 when 9 => + -- Synthesis Guard + if (WITH_KEY) then + data_out_rtps <= std_logic_vector(cc_instance_handle(2)); + wr_rtps <= '1'; + cnt_next <= cnt + 1; + end if; + -- Key Hash 4/4 + when 10 => -- Synthesis Guard if (WITH_KEY) then data_out_rtps <= std_logic_vector(cc_instance_handle(3)); - wr_rtps <= '1'; + wr_rtps <= '1'; -- Need to send Status Info if (cc_kind /= ALIVE) then @@ -1796,11 +1763,16 @@ begin stage_next <= SEND_INLINE_QOS; cnt3_next <= 0; else - cnt_next <= cnt + 2; + cnt_next <= cnt + 3; end if; end if; + -- Status Info PID + when 11 => + data_out_rtps <= PID_STATUS_INFO & std_logic_vector(to_unsigned(4, SUBMESSAGE_LENGTH_WIDTH)); + wr_rtps <= '1'; + cnt_next <= cnt + 1; -- Status Info - when 10 => + when 12 => data_out_rtps <= (others => '0'); wr_rtps <= '1'; case (cc_kind) is @@ -1822,7 +1794,7 @@ begin cnt_next <= cnt + 1; end if; -- Sentinel - when 11 => + when 13 => data_out_rtps <= PID_SENTINEL & std_logic_vector(to_unsigned(0, PARAMETER_LENGTH_WIDTH)); wr_rtps <= '1'; @@ -1830,12 +1802,11 @@ begin if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then stage_next <= SEND_DATA_B; else + last_word_out_rtps <= '1'; -- Continue if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then stage_next <= HANDLE_REQUESTS; cnt_next <= 0; - req_bitmap_pos_next <= req_bitmap_pos + 1; - next_seq_nr_next <= next_seq_nr + 1; elsif (PUSH_MODE and new_push = '1') then stage_next <= HANDLE_NEW; cnt_next <= 4; @@ -1863,12 +1834,11 @@ begin if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then stage_next <= SEND_DATA_B; else + last_word_out_rtps <= '1'; -- Continue if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then - stage_next <= HANDLE_REQUESTS; - cnt_next <= 0; - req_bitmap_pos_next <= req_bitmap_pos + 1; - next_seq_nr_next <= next_seq_nr + 1; + stage_next <= HANDLE_REQUESTS; + cnt_next <= 0; elsif (PUSH_MODE and new_push = '1') then stage_next <= HANDLE_NEW; cnt_next <= 4; @@ -1897,8 +1867,6 @@ begin if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then stage_next <= HANDLE_REQUESTS; cnt_next <= 0; - req_bitmap_pos_next <= req_bitmap_pos + 1; - next_seq_nr_next <= next_seq_nr + 1; elsif (PUSH_MODE and new_push = '1') then stage_next <= HANDLE_NEW; cnt_next <= 4; @@ -1939,8 +1907,6 @@ begin if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then stage_next <= HANDLE_REQUESTS; cnt_next <= 0; - req_bitmap_pos_next <= req_bitmap_pos + 1; - next_seq_nr_next <= next_seq_nr + 1; elsif (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and historical_push = '1') then stage_next <= HANDLE_HISTORICAL; cnt_next <= 0; @@ -1966,9 +1932,15 @@ begin when 2 => data_out_rtps <= (others => '0'); + if (gap_is_last = '1') then + last_word_out_rtps <= '1'; + -- Reset + gap_is_last_next <= '0'; + end if; + -- Continue stage_next <= return_stage; - cnt_next <= 0; + cnt_next <= return_cnt; when others => null; end case; @@ -2111,6 +2083,17 @@ begin mem_pos_next <= 0; mem_stage_next <= FIND_EMPTY_SLOT; mem_cnt_next <= 0; + -- Set Endpoint Data + mem_endpoint_data_next <= ZERO_ENDPOINT_DATA; + mem_endpoint_data_next.guid <= guid_next; + mem_endpoint_data_next.addr <= addr_next; + mem_endpoint_data_next.portn <= portn_next; + mem_endpoint_data_next.flags <= reader_flags_next; + mem_endpoint_data_next.lease_deadline <= lease_deadline; + mem_endpoint_data_next.res_time <= TIME_INVALID; + mem_endpoint_data_next.ack_seq_nr_base <= seq_nr; + mem_endpoint_data_next.req_seq_nr_base <= SEQUENCENUMBER_UNKNOWN; + mem_endpoint_data_next.req_seq_nr_bitmap <= (others => '0'); when UPDATE_ENDPOINT => mem_stage_next <= UPDATE_ENDPOINT; if check_mask(mem_field_flags,EMF_IPV4_ADDR_FLAG) then @@ -3048,7 +3031,7 @@ begin if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET; - mem_write_data <= std_logic_vector(seq_nr(0)); + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(0)); if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; @@ -3059,7 +3042,7 @@ begin if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET + 1; - mem_write_data <= std_logic_vector(seq_nr(1)); + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(1)); if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; @@ -3530,8 +3513,6 @@ begin sn_latch_1 <= SEQUENCENUMBER_UNKNOWN; sn_latch_2 <= SEQUENCENUMBER_UNKNOWN; sn_latch_3 <= SEQUENCENUMBER_UNKNOWN; - global_ack_seq_nr_base <= SEQUENCENUMBER_UNKNOWN; - last_seq_nr <= SEQUENCENUMBER_UNKNOWN; check_time <= TIME_INVALID; heartbeat_time <= TIME_INVALID; guid <= GUID_UNKNOWN; @@ -3546,6 +3527,8 @@ begin req_bitmap_pos <= 0; mem_cnt <= 0; mem_pos <= 0; + return_cnt <= 0; + gap_is_last <= '0'; is_meta <= '0'; last_word_in_latch <= '0'; stale_check <= '0'; @@ -3553,6 +3536,7 @@ begin new_push <= '0'; historical_push <= '0'; assert_liveliness_latch <= '0'; + bitmap_cnt <= (others => '0'); meta_opcode <= (others => '0'); opcode <= (others => '0'); rtps_flags <= (others => '0'); @@ -3564,15 +3548,16 @@ begin last_addr <= (others => '0'); mem_addr_latch <= (others => '0'); max_endpoint_addr <= (others => '0'); + global_ack_seq_nr_base <= (others => (others => '0')); + last_seq_nr <= (others => (others => '0')); + bitmap_latch <= (others => (others => '0')); else stage <= stage_next; - return_stage <= return_stage; + return_stage <= return_stage_next; mem_stage <= mem_stage_next; sn_latch_1 <= sn_latch_1_next; sn_latch_2 <= sn_latch_2_next; sn_latch_3 <= sn_latch_3_next; - global_ack_seq_nr_base <= global_ack_seq_nr_base_next; - last_seq_nr <= last_seq_nr_next; check_time <= check_time_next; heartbeat_time <= heartbeat_time_next; guid <= guid_next; @@ -3587,12 +3572,15 @@ begin req_bitmap_pos <= req_bitmap_pos_next; mem_cnt <= mem_cnt_next; mem_pos <= mem_pos_next; + return_cnt <= return_cnt_next; + gap_is_last <= gap_is_last_next; is_meta <= is_meta_next; last_word_in_latch <= last_word_in_latch_next; stale_check <= stale_check_next; gap_in_progress <= gap_in_progress_next; new_push <= new_push_next; historical_push <= historical_push_next; + bitmap_cnt <= bitmap_cnt_next; assert_liveliness_latch <= assert_liveliness_latch_next; meta_opcode <= meta_opcode_next; opcode <= opcode_next; @@ -3605,6 +3593,9 @@ begin last_addr <= last_addr_next; mem_addr_latch <= mem_addr_latch_next; max_endpoint_addr <= max_endpoint_addr_next; + global_ack_seq_nr_base <= global_ack_seq_nr_base_next; + last_seq_nr <= last_seq_nr_next; + bitmap_latch <= bitmap_latch_next; end if; end if; end process;