URL
https://opencores.org/ocsvn/ht_tunnel/ht_tunnel/trunk
Subversion Repositories ht_tunnel
[/] [ht_tunnel/] [tags/] [START/] [bench/] [link_l2/] [link_frame_rx_l3_tb/] [link_frame_rx_l3_tb.cpp] - Rev 19
Compare with Previous | Blame | View Log
//link_fram_rx_l3_tb.cpp /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is HyperTransport Tunnel IP Core. * * The Initial Developer of the Original Code is * Ecole Polytechnique de Montreal. * Portions created by the Initial Developer are Copyright (C) 2005 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Ami Castonguay <acastong@grm.polymtl.ca> * * Alternatively, the contents of this file may be used under the terms * of the Polytechnique HyperTransport Tunnel IP Core Source Code License * (the "PHTICSCL License", see the file PHTICSCL.txt), in which case the * provisions of PHTICSCL License are applicable instead of those * above. If you wish to allow use of your version of this file only * under the terms of the PHTICSCL License and not to allow others to use * your version of this file under the MPL, indicate your decision by * deleting the provisions above and replace them with the notice and * other provisions required by the PHTICSCL License. If you do not delete * the provisions above, a recipient may use your version of this file * under either the MPL or the PHTICSCL License." * * ***** END LICENSE BLOCK ***** */ #include "link_frame_rx_l3_tb.h" #include "../../core/require.h" #include "link_rx_transmitter.h" #include <sstream> #include <string> using namespace std; link_frame_rx_l3_tb::link_frame_rx_l3_tb(sc_module_name name): sc_module(name){ SC_THREAD(stimulate_inputs); sensitive_pos << clk; SC_THREAD(validate_outputs); sensitive_pos << clk; ///Create and link transmitter submodule transmitter = new link_rx_transmitter("link_rx_transmitter"); transmitter->clk(clk); transmitter->phy_ctl_lk(phy_ctl_lk); for(int n = 0; n < CAD_IN_WIDTH; n++){ transmitter->phy_cad_lk[n](phy_cad_lk[n]); } transmitter->phy_available_lk(phy_available_lk); transmitter->lk_deser_stall_phy(lk_deser_stall_phy); transmitter->lk_deser_stall_cycles_phy(lk_deser_stall_cycles_phy); } link_frame_rx_l3_tb::~link_frame_rx_l3_tb(){ delete transmitter;} void link_frame_rx_l3_tb::init(){ /** Not much to understand here, just init misc variables to an initial state to start new. You'll notice that reset is asserted and pwrok is de-asserted, meaning that this is a cold reset and re-initializes the RX part of the link. */ phy_ctl_lk = sc_uint<CAD_IN_DEPTH>(0); for(int n = 0; n < CAD_IN_WIDTH; n++){ phy_cad_lk[n] = sc_uint<CAD_IN_DEPTH>(0); } phy_available_lk = true; resetx = false; pwrok = false; ldtstopx = false; /** Link widths 000 8 bits 100 2 bits 101 4 bits 111 Link physically not connected @{ */ csr_rx_link_width_lk = "000"; csr_end_of_chain = false; csr_sync = false; csr_extended_ctl_timeout_lk = false; #ifdef RETRY_MODE_ENABLED ///If we are in retry mode csr_retry = false; ///Command decoder commands a retry disconnect cd_initiate_retry_disconnect = false; #endif expect_connected = 0; expect_disable_receivers_phy = 0; expect_link_width_update = 0; expected_link_width = "000"; expect_link_failure = 0; check_dword_reception = true; } void link_frame_rx_l3_tb::stimulate_inputs(){ ///////////////////////////////////////////// // Test link failure ///////////////////////////////////////////// phy_ctl_lk = sc_uint<CAD_IN_DEPTH>(0); for(int n = 0; n < CAD_IN_WIDTH; n++){ phy_cad_lk[n] = sc_uint<CAD_IN_DEPTH>(0); } phy_available_lk = true; resetx = false; pwrok = false; expect_connected = -4; for(int n = 0; n < 5; n++) wait(); resetx = true; pwrok = true; expect_link_failure = 5; expect_link_width_update = 0; for(int n = 0; n < 5; n++) wait(); /////////////////////////////////////// // Do a normal valid cold reset /////////////////////////////////////// cout << "Entered stimulate_inputs" << endl; init(); expect_link_failure = 0; cout << "Init done" << endl; cout << "Cold reset" << endl; //Keep the cold reset for(int n = 0; n < 2; n++){ wait(); } //Clock from other node starts running phy_available_lk = true; //Keep the cold reset for(int n = 0; n < 4; n++){ wait(); } //Power is stable pwrok = true; //Not in ldtstop sequence ldtstopx = true; transmitter->send_initial_value(4); ///////////////////////////////////////////// // Test normal 8 bit behavious, offset 1/3 ///////////////////////////////////////////// //End cold reset expect_link_width_update = 4; expected_link_width = "000"; resetx = true; cout << "Init sequence" << endl; transmitter->send_init_sequence(1,3); expect_connected = 16; cout << "Data transmission" << endl; LinkTransmission transmit; transmit.dword = "0xA417F05B"; transmit.lctl = true; transmit.hctl = true; expected_transmission.push(transmit); transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); transmit.dword = "0x11112222"; transmit.lctl = true; transmit.hctl = false; expected_transmission.push(transmit); transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); transmit.dword = "0xFFBB3388"; transmit.lctl = false; transmit.hctl = true; expected_transmission.push(transmit); transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); transmit.dword = "0x00000000"; transmit.lctl = false; transmit.hctl = false; transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); for(int n = 0; n < 5; n++){ wait(); } resetx = false; expect_connected = -4; for(int n = 0; n < 5; n++){ wait(); } ///////////////////////////////////////////// // Test normal 8 bit behavious, offset 0/0 ///////////////////////////////////////////// resetx = true; transmitter->send_init_sequence(0,0); expect_connected = 16; cout << "Data transmission" << endl; transmit.dword = "0xABCDEF01"; transmit.lctl = true; transmit.hctl = true; expected_transmission.push(transmit); transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); transmit.dword = "0x55336644"; transmit.lctl = true; transmit.hctl = false; expected_transmission.push(transmit); transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); for(int n = 0; n < 5; n++) wait(); //////////////////////////////////////////////////////////////// // Testing LDTSTOP //////////////////////////////////////////////////////////////// cout << "Testing LDTSTOP" << endl; check_dword_reception = false; expect_connected = -4; expect_disable_receivers_phy = 6; ldtstopx = false; ldtstop_disconnect_rx = true; transmit.dword = "0x00000000"; transmit.lctl = false; transmit.hctl = false; for(int n = 0; n < 4; n++) transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); ldtstopx = true; ldtstop_disconnect_rx = false; expect_disable_receivers_phy = -210; transmitter->send_initial_value(210); expect_connected = 210; transmitter->send_init_sequence(0,0); transmit.dword = "0xABCDEF01"; transmit.lctl = true; transmit.hctl = true; transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); for(int n = 0; n < 5; n++) wait(); //////////////////////////////////////////////////////////////// // Testing protocol error (invalid CTL transition) //////////////////////////////////////////////////////////////// cout << "Testing protocol error" << endl; sc_bv<CAD_IN_DEPTH> phy_ctl_lk_buf; for(int n = 0; n < CAD_IN_DEPTH; n++){ phy_ctl_lk_buf[n] = (bool)(n % 2); } phy_ctl_lk = phy_ctl_lk_buf; phy_available_lk = true; expect_ctl_transition_error = 5; wait(); transmit.dword = "0x00000000"; transmit.lctl = true; transmit.hctl = true; for(int n = 0; n < 5; n++) transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); expect_ctl_transition_error = 0; resetx = false; expect_connected = -4; for(int n = 0; n < 5; n++){ wait(); } //////////////////////////////////////////////////////////////// // Testing protocol error (invalid CTL transition) because of reset //////////////////////////////////////////////////////////////// cout << "Testing protocol error because of reset" << endl; resetx = true; transmitter->send_init_sequence(0,0); expect_connected = 16; phy_ctl_lk_buf[0] = true; for(int n = 1; n < CAD_IN_DEPTH; n++){ phy_ctl_lk_buf[n] = false; } phy_ctl_lk = phy_ctl_lk_buf; phy_available_lk = true; wait(); expect_connected = -10; //Like reset signal transmit.dword = "0x00000000"; transmit.lctl = false; transmit.hctl = false; for(int n = 0; n < 2; n++) transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); resetx = false; for(int n = 0; n < 5; n++){ wait(); } //////////////////////////////////////////////////////////////// // Testing Retry mode disconnect from CD //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// // Testing Retry mode with protocol error //////////////////////////////////////////////////////////////// cout << "Testing protocol error with retry" << endl; resetx = true; csr_retry = true; transmitter->send_init_sequence(0,0); expect_connected = 16; for(int n = 0; n < CAD_IN_DEPTH; n++){ phy_ctl_lk_buf[n] = (bool)(n % 2); } phy_ctl_lk = phy_ctl_lk_buf; phy_available_lk = true; expect_ctl_transition_error = 5; expect_lk_initiate_retry_disconnect = 5; wait(); transmit.dword = "0x00000000"; transmit.lctl = true; transmit.hctl = true; for(int n = 0; n < 3; n++) transmitter->send_dword_link(transmit.dword,transmit.lctl,transmit.hctl); expect_ctl_transition_error = 0; resetx = false; expect_connected = -4; for(int n = 0; n < 5; n++){ wait(); } //////////////////////////////////////////////////////////////// // Done //////////////////////////////////////////////////////////////// cout << "Link testbench done" << endl; while(true) wait(); } void link_frame_rx_l3_tb::validate_outputs(){ while(true){ wait(); //Test correctness of lk_rx_connected if(!expect_connected) verify( lk_rx_connected.read() == false,"Link should not be connected yet"); else if(expect_connected > 0){ verify(!(expect_connected == 1 && lk_rx_connected.read() == false), "Link failed to connect"); if(!lk_rx_connected.read()) expect_connected--; else(expect_connected = 1); } else{ verify(!(expect_connected == -1 && lk_rx_connected.read() == true), "Link failed to disconnect"); if(lk_rx_connected.read()) expect_connected++; else expect_connected = 0; } //Test correctness of lk_disable_receivers_phy if(!expect_disable_receivers_phy) verify( lk_disable_receivers_phy.read() == false,"Link should not be disabled yet"); else if(expect_disable_receivers_phy > 0){ verify(!(expect_disable_receivers_phy == 1 && lk_disable_receivers_phy.read() == false), "Link failed to disable"); if(!lk_disable_receivers_phy.read()) expect_disable_receivers_phy--; else(expect_disable_receivers_phy = 1); } else{ verify(!(expect_disable_receivers_phy == -1 && lk_disable_receivers_phy.read() == true), "Link failed to re-enable"); if(lk_disable_receivers_phy.read()) expect_disable_receivers_phy++; else expect_disable_receivers_phy = 0; } //Test correctness of lk_update_link_width_csr if(!lk_link_failure_csr.read()){ if(!expect_link_width_update) verify( lk_update_link_width_csr.read() == false,"Unexpected update of link width"); else { verify(!(expect_link_width_update == 1 && lk_update_link_width_csr.read() == false), "Link failed to update link width"); if(!lk_update_link_width_csr.read()) expect_link_width_update--; else{ ostringstream o; o << "Invalid updated link width value, Expected: " << expected_link_width << " Received: " << lk_sampled_link_width_csr.read(); verify(expected_link_width == lk_sampled_link_width_csr.read(), o.str().c_str()); (expect_link_width_update = 0); } } } //Test correctness of lk_link_failure_csr if(!expect_link_failure) verify(lk_link_failure_csr.read() == false,"Unexpected link failure"); else{ verify(!(expect_link_failure == 1 && lk_link_failure_csr.read() == false), "Link failed to fail : the link was supposed to fail and didn't"); if(!lk_link_failure_csr.read()) expect_link_failure--; //else(expect_link_failure = 0); } //Test correctness of ctl_transition_error if(!expect_ctl_transition_error) verify(ctl_transition_error.read() == false,"Unexpected ctl transition error"); else{ verify(!(expect_ctl_transition_error == 1 && ctl_transition_error.read() == false), "Link failed produce CTL error when it should have"); if(!ctl_transition_error.read()) expect_ctl_transition_error--; } //Test correctness of lk_initiate_retry_disconnect if(!expect_lk_initiate_retry_disconnect) verify(lk_initiate_retry_disconnect.read() == false,"Unexpected retry sequence initiated"); else{ verify(!(expect_lk_initiate_retry_disconnect == 1 && lk_initiate_retry_disconnect.read() == false), "Link failed to initiate retry sequence when it should have"); if(!lk_initiate_retry_disconnect.read()) expect_lk_initiate_retry_disconnect--; else(expect_lk_initiate_retry_disconnect = 0); } //Test reception of data if(framed_data_available.read() && check_dword_reception){ verify(!(expected_transmission.empty()), "Unexpected data reception"); if(!expected_transmission.empty()){ LinkTransmission t = expected_transmission.front(); cout << "Data in front : L=" << t.lctl << " H=" << t.hctl << " D=" << t.dword.to_string(SC_HEX) << endl; cout << "Data received : L=" << framed_lctl.read() << " H=" << framed_hctl.read() << " D=" << framed_cad.read().to_string(SC_HEX) << endl; expected_transmission.pop(); verify((t.dword == framed_cad.read() && t.lctl == framed_lctl.read() && t.hctl == framed_hctl.read()), "Invalid data received"); } } } }