URL
https://opencores.org/ocsvn/ht_tunnel/ht_tunnel/trunk
Subversion Repositories ht_tunnel
[/] [ht_tunnel/] [tags/] [START/] [bench/] [flow_control_l2/] [flow_control_l2_tb/] [flow_control_l2_tb.h] - Rev 21
Go to most recent revision | Compare with Previous | Blame | View Log
//flow_control_l2_tb.h /* ***** 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 ***** */ #ifndef FLOW_CONTROL_L2_TB_H #define FLOW_CONTROL_L2_TB_H #include "../../../rtl/systemc/core_synth/synth_datatypes.h" #include "../../../rtl/systemc/core_synth/constants.h" #include <deque> #include <string> #define NOP_COUNTER_DELAY 20 ///Testbench for the complete flow_control_l2 module /** The flow_control_l2 module is BIG, so testing it is a HUGE job. This testbench covers a couple of simple cases but in no way covers all the functionality. */ class flow_control_l2_tb : public sc_module { public: ///Delay before nop frees buffers /** The testbench simulates the flow control credits, so when packets are received, flow control credits are eventually freed and sent to the flow control module. This is number of cycles of delay there is between the time packets are received and the moment credit are freed */ static const int nop_counter_delay; ///Maximum number of data buffers there are in the simulated next node static const unsigned next_node_databuffers_maximum[3]; ///Maximum number of command buffers there are in the simulated next node static const unsigned next_node_buffers_maximum[3]; ///A structure that represents a packet of data struct PacketData{ int size;///< Size (number of dwords), from 1 to 16 int dwords[16];///< actual data sc_bv<64> associated_control_pkt;///< The command packet associated with this data }; ///A structure to identify an entry in the data buffers struct DataBufferEntry{ sc_uint<BUFFERS_ADDRESS_WIDTH> address;///<Unique address of the entry VirtualChannel vc;///<Virtual channel of the entry int size;///< Size (number of dwords), from 1 to 16 int dwords[16];///< actual data }; ///From what source is the flow control currently sending a packet enum FlowControlStatus{ FC_SENDING_CSR, FC_SENDING_EH, FC_SENDING_FWD, FC_SENDING_UI, FC_NONE }; ///An output value of the flow control module, contains 32 bits dword and CTL values struct OutputDword{ sc_bv<32> dword; bool lctl; bool hctl; }; ///Flow control informatino contained in a nop packet struct NopInfo{ sc_bv<12> nop_information; sc_uint<8> nop_ack_value; bool nop_received; }; ///Structure representing a history entry struct HistoryEntry{ sc_bv<64> pkt;///<The command packet sc_uint<8> nop_ack_value;///<Ack value of the entry (part of HT spec!) unsigned data_size;///<Number of dwords of data unsigned data[16];///<The actual data unsigned crc;///Per packet CRC of the entry }; ///Exception that can be thrown struct TestbenchError{ std::string message; }; /// The Clock sc_in<bool> clk; /// Reset signal sc_out<bool> resetx; ///LDTSTOP# signal sc_out<bool> ldtstopx; // USER_FIFO ///The packet the user interface wants to send sc_out <sc_bv<64> > ui_packet_fc; ///If it there is a packet available to be sent sc_out <bool> ui_available_fc; ///The VC's that can accept packets currently sc_in <sc_bv<3> > fc_user_fifo_ge2_ui; ///The VC in which the flow control wants to read data from the UI data buffer sc_in <VirtualChannel> fc_data_vc_ui; ///The data from the UI buffers sc_out <sc_bv<32> > ui_data_fc; ///To consume the data from the UI buffers sc_in <bool> fc_consume_data_ui; // Forward -- FC //If there is a packet to be sent from the reordering from the other side sc_out <bool> ro_available_fwd; ///The packet to send sc_out <syn_ControlPacketComplete > ro_packet_fwd; ///The VirtualChannel of the packet to send sc_out <VirtualChannel > ro_packet_vc_fwd; ///To acknoledge that the packet has been consumed sc_in <bool> fwd_ack_ro; //LINK ///The dword to send to the other link sc_in <sc_bv<32> > fc_dword_lk; ///The LCTL control signal to send along with the data sc_in <bool> fc_lctl_lk; ///The HCTL control signal to send along with the data sc_in <bool> fc_hctl_lk; ///The link consumes the data we are sending sc_out <bool> lk_consume_fc; #ifdef RETRY_MODE_ENABLED ///Force the link to disconnect sc_in <bool> fc_disconnect_lk; ///This signal is active when the RX side of the link is connected sc_out <bool> lk_rx_connected; ///If the link wants to initiate a retry disconnect sc_out <bool> lk_initiate_retry_disconnect; ///If we are in the mode retry sc_out <bool> csr_retry; //Command decoder /**Turns on when a disconnect sequence is initiated All buffer counts are zeroed and we must replay all packets that have not been acked*/ sc_out <bool> cd_initiate_retry_disconnect; #endif //DATA BUFFER ///The address where to read the data sc_in <sc_uint<BUFFERS_ADDRESS_WIDTH> > fwd_address_db; ///The VC in which to read the data sc_in <VirtualChannel> fwd_vctype_db; ///To read (consume) the data at the address specified sc_in <bool> fwd_read_db; ///The data received from the data buffer sc_out <sc_bv<32> > db_data_fwd; ///Buffer count information from RO and DB for sending nop's ///The buffers the ro can notify as being free to the HT node we are connected to sc_out <sc_bv<6> > ro_buffer_cnt_fc; ///The buffers the ro can notify as being free to the HT node we are connected to sc_out <sc_bv<6> > db_buffer_cnt_fc; //Connexion Error handler FLOW control ///Acknoledge that the dword has been read sc_in <bool> fc_ack_eh; ///The dword to send (command packet or data payload) sc_out <sc_bv<32> > eh_cmd_data_fc; ///If there is a dword to send sc_out <bool> eh_available_fc; //Connexion CSR -- FLOW control ///Acknoledge that the dword has been read sc_in <bool> fc_ack_csr; ///If there is a dword to send sc_out <bool> csr_available_fc; ///The dword to send (command packet or data payload) sc_out <sc_bv<32> > csr_dword_fc; ///If we are to turn the transmitter off sc_out <bool> csr_transmitteroff; ///This bit forces a single stomp to be sent sc_out<bool> csr_force_single_stomp_fc; ///This bit forces a single CRC error to be sent sc_out<bool> csr_force_single_error_fc; ///Once a stomp is sent, we clear the signal to send the stomp sc_in<bool> fc_clear_single_error_csr; ///Once a CRC error is sent, we clear the signal to send the error sc_in<bool> fc_clear_single_stomp_csr; //Connexion pour les NOP request ///Databuffer requests that a nop be sent. sc_out <bool> db_nop_req_fc; ///Reordering requests that a nop be sent. sc_out <bool> ro_nop_req_fc; ///A nop was just sent sc_in <bool> fc_nop_sent; // NOP info packet ///The buffer information received in a nop sc_out<sc_bv<12> > cd_nopinfo_fc; ///If a nop was just received sc_out<bool> cd_nop_received_fc; ///Let the reordering know which buffers are free in the next node sc_in <sc_bv<6> > fwd_next_node_buffer_status_ro; #ifdef RETRY_MODE_ENABLED ///The packet that is acked in the nop (for retry mode) /** When we receive this ack value, we can erase the packet associated with that number (and all the previous ones) from our buffers. */ sc_out<sc_uint<8> > cd_nop_ack_value_fc; ///CD maitains a count of valid packet received, that count is then sent in nops sc_out<sc_uint<8> > cd_rx_next_pkt_to_ack_fc; ////////////////////////////////////////// // Memory interface - synchronous ///////////////////////////////////////// sc_in<bool> history_memory_write; sc_in<sc_uint<LOG2_HISTORY_MEMORY_SIZE> > history_memory_write_address; sc_in<sc_bv<32> > history_memory_write_data; sc_in<sc_uint<LOG2_HISTORY_MEMORY_SIZE> > history_memory_read_address; sc_out<sc_bv<32> > history_memory_output; ///Actual content of the simulated memory unsigned history_memory[HISTORY_MEMORY_SIZE]; #endif ///This containes packets sent to the user fifo /** The TB does not strictly test that the user fifo extracts the correct packet (the user_fifo testbench is there for that), but it does keep track of all packet sent and extracted from the user_fifo to make sure they are valid */ std::deque<sc_bv<64> > user_packets; ///Data associated with the user packets /**This will be used to generate inputs to the flow_control when it wants to access the data associated with the packets read from the user_fifo*/ std::deque<PacketData> user_data[3]; ///VC of the data being read by the flow_control VirtualChannel current_user_data_vc; ///VC of the data currently being received by the UI /** UI takes a cycle to update it's output, so this variable keeps track of what is currently on the ouput (what was requested last cycle) */ VirtualChannel current_user_data_vc_output; ///Packet that are expected to be outputed /**Most packet are read from various sources, so once they are read, we can expect what it is going to be outputed. This does not cover all packets though : for example user packets are internal to the flow_control_2 module so there is no way to predict that it will be output, at least with black box testing.*/ std::deque<OutputDword> expected_output; ///History structure of the design std::deque<HistoryEntry> history; ///Status of the design : what it is currently sending FlowControlStatus fc_status; ///Data of the databuffer entry /** A real databuffer is not simulated. When a packet is sent from the command buffers, the address is noted and stored and checking when the flow control module tries to check the data. This variable stores the data of the entry */ DataBufferEntry databuffer_data; ///Virtual channel of the databuffer entry currently being output /** Databuffer has a latency of 1 cycle before data is correct on the output. This variable store information about what is currently being output (what was requested last cycle)*/ VirtualChannel databuffer_output_vc; ///Address of the databuffer entry currently being output /** Databuffer has a latency of 1 cycle before data is correct on the output. This variable store information about what is currently being output (what was requested last cycle)*/ unsigned databuffer_output_addr; ///SystemC Macro SC_HAS_PROCESS(flow_control_l2_tb); ///Module constructor flow_control_l2_tb(sc_module_name name); ///Controls percentage of change of generating packet from different sources /** Will vary throughout different stages of the testbench */ //@{ int percent_chance_from_eh; int percent_chance_from_csr; int percent_chance_from_fwd; int percent_chance_from_ui; //@{ ///Number of dwords of data left to send (or sent) from the different sources //@{ unsigned data_left_eh; unsigned data_left_csr; unsigned data_sent_ui; unsigned data_sent_db; //@{ ///Controls percentage of change of requesting nop packet to be sent /** Will vary throughout different stages of the testbench */ //@{ int percent_chance_nop_req_db; int percent_chance_nop_req_ro; //@{ ///Controls percentage of change of requesting nop packet to received /** Will vary throughout different stages of the testbench */ int percent_chance_nop_received; ///Per packet CRC calcualted for packets with no data associated unsigned crc1; ///Per packet CRC calcualted for packets with data associated unsigned crc2; //This is the number of buffers that are free (command and data) unsigned next_node_buffers_free[3]; unsigned next_node_databuffers_free[3]; //This is the number of buffers that have been advertised as being free through //nops as seen by the next node (does not take into account the nop delay) unsigned next_node_buffers_advertised[3]; unsigned next_node_databuffers_advertised[3]; //This is the number of buffers that have been advertised as being free through //nops as seen by the current node (takes into account the nop delay) unsigned buffers_available[3]; unsigned databuffers_available[3]; /** verify_output() MUST run after produce_inputs, so when produce_inputs is done, do a notification */ sc_event input_produced; ///Nop delay is done simply be shifting data inside an array NopInfo nop_delay[NOP_COUNTER_DELAY]; ///<Variable used to track the construction of the history structure /** The history structure is build from reading the output of the flow_control module. All these variables are used to build up the current_history_entry which is then stored in the history\ structure */ HistoryEntry current_history_entry; bool history_second_dword_next; bool history_crc_next; int history_data_count; bool history_ignore_nop_crc; int history_ack_value; ///The count of packet received (for the retry mode) sc_uint<8> next_node_ack_value_pending; sc_uint<8> next_node_ack_value; ///If the dword of the flow control should be ignored when calculating the ack valeu /** For the history structure, every entry has an ack value. This value is updated by observing the control packets sent from flow_control output. When the first dword of a quad word packet is sent, ignore_next_dword_for_ack is set so that the second dword is simply ignored. */ bool ignore_next_dword_for_ack; ///If we are in a retry sequence (set by start retry sequence) bool retry_sequence; ///The simulated history structure std::deque<HistoryEntry> retry_playback_history; ///Next dword will be second dword of command packet bool retry_second_dword_next; ///CRC of entry is next bool retry_crc_next; ///Nop can be inserted in stream, after a nop, we expect a Nop CRC /**Nop crc will be contained in expected dword structure*/ bool retry_expect_nop_crc; ///The amount of data that has been received for an entry int retry_data_count; ///Set after a command packet, if it has data associated to it (in retry sequence) /**Cleared when all data is received*/ bool retry_receive_data; ///Link is disconnected for retry reasons /** When the flow_control says to the link to disconnect, it takes some cycles before the output is correct again (the link would take some cycles to correctly reconnect. So when a retry sequence is started, retry_disconnect is set until fc_disconnect_lk is false so that the flow_control output is ignored. */ bool retry_disconnect; ///Becomes true when an error is detected bool error; ///Simulates the history memory as if it was a real memory void simulate_memory(); ///Set some variables that control global behavious of Testbench over time /** It set the percentage of chance of all the */ void control_testbench(); ///Produces random packets for all inputs of the flow_control void produce_inputs(); ///Verifies that the output of the design is correct void verify_output(); ///Generate a random response packet /** @param pkt The generated packet returned by address @param data_size The generated packet data size returned by address */ void generate_random_response(sc_bv<32> &pkt, unsigned &data_size); ///Generate a random posted packet /** @param pkt The generated packet returned by address @param data_size The generated packet data size returned by address */ void generate_random_posted(sc_bv<64> &pkt, unsigned &data_size); ///Generate a random non posted packet /** @param pkt The generated packet returned by address @param data_size The generated packet data size returned by address */ void generate_random_nposted(sc_bv<64> &pkt, unsigned &data_size); ///Generate a random packet of any Virtual Channel /** @param pkt The generated packet returned by address @param data_size The generated packet data size returned by address */ VirtualChannel generate_random_packet(sc_bv<64> &pkt, unsigned &data_size); ///Generate a random 32-bit vecgtor /** @param vector The random vector returned by address */ void getRandomVector(sc_bv<32> &vector); ///Generate a random 64-bit vecgtor /** @param vector The random vector returned by address */ void getRandomVector(sc_bv<64> &vector); ///Add data packet to the list of packet sent to FC from UI /** @param datalength The number of dwords of data @param ui_vc The virtual channel of the packet @param associated_control_packet The command packet associated to the data packet */ void add_ui_data_packet(unsigned datalength, VirtualChannel ui_vc, sc_bv<64> &associated_control_packet); ///Sets the databuffer_data variable /** @param datalength The number of dwords of data @param ui_vc The virtual channel of the packet @param associated_control_packet The command packet associated to the data packet */ void update_databuffer_entry(unsigned datalength, VirtualChannel ui_vc, sc_uint<4> &data_address); ///Update CRC1 /** @param dword Dword to use to calculate the new value of CRC1 @param dword LCTL value to use to calculate the new value of CRC1 @param dword HCTL value to use to calculate the new value of CRC1 */ void calculate_crc1(sc_bv<32> dword,bool lctl, bool hctl); ///Update CRC2 /** @param dword Dword to use to calculate the new value of CRC2 @param dword LCTL value to use to calculate the new value of CRC2 @param dword HCTL value to use to calculate the new value of CRC2 */ void calculate_crc2(sc_bv<32> dword,bool lctl, bool hctl); ///Updates a CRC with 34 bits of data /** @param crc The CRC to update (by address) @param data The 34 bits to calculate the CRC on */ void calculate_crc(unsigned &crc,sc_bv<34> &data); ///Clears all next node buffer status /** This clears all information about the number of free buffers and the number of advertised buffers */ void clear_next_node_information(); ///Adds the CRC of a data packet to the list of expected dwords /**@param data The data packet with it's associated command packet */ void add_expected_crc_for_packet(PacketData &data); ///Takes care of everything necessary to verify when a retry sequence is start /** Should be called when a disconnect nop is received in retry mode : it will take care of expecting the CRC that will follow the NOP*/ void start_retry_sequence(); ///Checks correctness of what is sent in retry sequence /** Called by verify_output when in the retry sequence */ void manage_retry_sequence(); ///Manages the history of packet sent /** From the output of the flow_control , a history of packet sent is build so that when a retry sequence occurs, what is resent by the flow control can be compared to what is stored in that history*/ void manage_history(); ///Frees random number of buffers in the next node /** Flow control sends packets to the next node, which would fill buffers in a real system. These real packets would eventually be read and the buffers freed. So this method randomly frees buffers*/ void free_buffers(); ///Updates the buffers count and ack number on the other side when packets are received void manage_ack_buffer_count(); ///Generates nops from the next node (acks history and frees buffers) void send_next_node_nops(); }; ///Function to allow to output the status to an outputstream ostream &operator<<(ostream &out,const flow_control_l2_tb::FlowControlStatus fc_status); #endif
Go to most recent revision | Compare with Previous | Blame | View Log