URL
https://opencores.org/ocsvn/ht_tunnel/ht_tunnel/trunk
Subversion Repositories ht_tunnel
[/] [ht_tunnel/] [tags/] [START/] [rtl/] [systemc/] [flow_control_l2/] [flow_control_l3.h] - Rev 19
Compare with Previous | Blame | View Log
//flow_control_l3.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): * Jean-Francois Belanger * 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 "../core_synth/synth_datatypes.h" #include "../core_synth/constants.h" #ifndef FLOW_CONTROL_L3_H #define FLOW_CONTROL_L3_H ///State machine possible state list enum fc_state { NOP_SENT, ///< Sending a nop FWD_CMD32_SENT,/**< Sending the first dword of command packet from the reordering of the other side of the tunnel*/ FWD_CMD64_FIRST_SENT,///< Sending first dword packet (of a quad word packet) from reordering FWD_CMD64_SECOND_SENT,///< Sending second dword packet (of a quad word packet) from reordering NOP_SENT_IN_FWD,/**< Sending nop in the middle of transmission of data from reordering of the other side of the tunnel*/ FWD_DATA_SENT, ///< Sending data from reordering of the other side of the tunnel CSR_CMD_SENT, ///< Sending a packet from CSR EH_CMD_SENT, ///< Sending a packet from the error handler USER_CMD32_SENT, ///< Sending a dword packet from user fifo USER_CMD64_FIRST_SENT,///< Sending first dword packet (of a quad word packet) from user fifo USER_CMD64_SECOND_SENT,///< Sending second dword packet (of a quad word packet) from user fifo USER_DATA_SENT, ///< Sending data from the User Interface data buffers CSR_DATA_SENT, ///< Sending data from the CSR ERROR_DATA_SENT, ///< Sending data from the Error Handler NOP_SENT_IN_USER,///< Sending nop in the middle of transmission of data from UI NOP_SENT_IN_CSR,///< Sending nop in the middle of transmission of data from CSR NOP_SENT_IN_EH,///< Sending nop in the middle of transmission of data from EH LDTSTOP_DISCONNECT,///< State where we end up when the link is stopped through LDTSTOP, *not retry mode* #ifdef RETRY_MODE_ENABLED RETRY_SEND_DISCONNECT,///< Send disconnects NOP to initiate the retry sequence RETRY_WAIT_FOR_ACK,/**< After a retry disconnect, wait for the next node to send the it's RxNextPacketToAck value so that we know were to start the histor playback*/ RETRY_CMD32_SENT,///< Sending a dword packet from history buffer RETRY_CMD64_FIRST_SENT,///< Sending first dword packet (of a quad word packet) from history buffer RETRY_CMD64_SECOND_SENT,///< Sending second dword packet (of a quad word packet) from history buffer RETRY_DATA_SENT,///< Sending data payload of a history packet RETRY_SEND_DISCONNECT_CRC,///< Sends the CRC associated with the disconnect nop RETRY_WAIT_FOR_RX_DISCONNECT,/**< Wait for RX to disconnect before attempting to reconnect TX */ RETRY_WAIT_FOR_ACK_AND_BUFFER_COUNT_SENT,/**< After a retry disconnect, wait for the next node to send the it's RxNextPacketToAck value so that we know were to start the history playback. Retry also requires that we advertise at least the same amount of buffers then we had before the retry sequence, so we also wait until all our free buffers have been advertised as free*/ RETRY_WAIT_FOR_ACK_AND_BUFFER_COUNT_SENT_CRC,/**< When in the state RETRY_WAIT_FOR_ACK_AND_BUFFER_COUNT_SENT, we send nop. Since we are in retry mode, we are also required to send the CRC's of the nop */ RETRY_SEND_CMD_CRC,///< Send CRC of a history packet SEND_CMD_CRC,///< Send the CRC of a packet with no data associated SEND_NOP_CRC,///<Send the crc of a nop packet SEND_DATA_CRC,///< Send the CRC of a packet with data associated NOP_CRC_SENT_IN_FWD,///< Send the CRC of a nop inserted in a FWD data transfer NOP_CRC_SENT_IN_USER,///<Send the CRC of a nop inserted in a UI data transfer NOP_CRC_SENT_IN_CSR,///< Send the CRC of a nop inserted in a CSR data transfer NOP_CRC_SENT_IN_EH,///< Send the CRC of a nop inserted in a EH data transfer RETRY_NOP_SENT,///< Send a nop while playing back history RETRY_NOP_CRC_SENT,///< Sending the CRC of a nop packet while playing back history RETRY_NOP_SENT_IN_DATA,/**< Send a nop while playing back history, in the middle of a data packet*/ RETRY_NOP_CRC_SENT_IN_DATA/**< Sending the CRC of a nop packet while playing back history, in the middle of a data packet*/ #endif }; //State values for storing if we are sending a chain enum fc_chain_state { NO_CHAIN_STATE,FWD_CHAIN_STATE,USER_CHAIN_STATE}; /// Finite state machine of the flow control /**see flow_control_l2.h for explanation of the role of the flow_control*/ class flow_control_l3 : public sc_module { public: //Signals to internal FIFO ///If there is a packet that can be sent from the internal user fifo sc_in <bool> fifo_user_available ; ///The packet to be sent from the user fifo sc_in <sc_bv<64> > fifo_user_packet; ///The packet fifo_user_packet is being consumed sc_out<bool> consume_user_fifo; ///Hold the packet so it doesn't change after sending the first dword sc_out<bool> hold_user_fifo; /** These signals are not necessary, but they are registered in the user_fifo to accelerate the combinatorial path of this module. */ //@{ ///Virtual channel of the ::fifo_user_packet sc_in<VirtualChannel> fifo_user_packet_vc; ///If ::fifo_user_packet is a double word packet (as opposed to a quad word, word = 16 bits) sc_in<bool> fifo_user_packet_dword; ///If ::fifo_user_packet has any data associated sc_in<bool> fifo_user_packet_data_asociated; #ifdef RETRY_MODE_ENABLED ///The command of fifo_user_packet sc_in<PacketCommand > fifo_user_packet_command; #endif ///Size of ::fifo_user_packet data in dwords minus 1 sc_in<bool> fifo_user_packet_isChain; ///If ::fifo_user_packet has the chain bit on (also checks if it's a posted packet) sc_in<sc_uint<4> > fifo_user_packet_data_count_m1; //@} //Signals to error handler ///If the error handler has a packet available to send sc_in <bool> eh_available_fc ; ///Acknowledge that the packet from the error handler has been read sc_out <bool> fc_ack_eh; ///The dword to be sent from the errorhandler sc_in <sc_bv<32> > eh_cmd_data_fc; //Signals to CSR ///CSR has a packet to be sent sc_in <bool> csr_available_fc; ///Acknowledge that the packet from the CSR has been read sc_out <bool> fc_ack_csr; ///The dword to be sent from the CSR sc_in <sc_bv<32> > csr_dword_fc; //Signals to Reordering ///Reordering has a packet to be sent sc_in <bool> ro_available_fwd; ///Reordering requests that a nop be sent to notify of free buffers sc_in <bool> ro_nop_req_fc; ///Packt to send from reordering sc_in <syn_ControlPacketComplete> ro_packet_fwd; sc_in<VirtualChannel> ro_packet_vc_fwd; ///To consume the data from the reordering_l2 module sc_out<bool> fwd_ack_ro; //Signals to User Interface ///To read data from the userinterface buffers sc_out <bool> fc_consume_data_ui; ///The virtual channel of the data to fetch from the user interface buffers sc_out<VirtualChannel> fc_data_vc_ui; //Signals from databuffer from other side ///Databuffer requests that a nop be sent to notify of free buffers sc_in <bool> db_nop_req_fc; ///The address to read data from the databuffer from the other side sc_out <sc_uint<BUFFERS_ADDRESS_WIDTH> > fwd_address_db; ///Read the data from the databuffer of the other side sc_out <bool> fwd_read_db; ///The virtual channel to read data from the databuffer from the other side sc_out<VirtualChannel> fwd_vctype_db; ///To erase the data packet sc_out <bool> fwd_erase_db; //Signals from nop_framer ///The next packet to send should be a nop sc_in <bool> nop_next_to_send; ///nophandler should generate disconnect nops sc_out<bool> generate_disconnect_nop; ///If there are buffer to be notified as free with a nop sc_in<bool> has_nop_buffers_to_send; //Signals to fairness ///If the local side has priority sc_in<bool> local_priority; ///If a local packet is issued (can be sent or reserved to send when buffers available) sc_out<bool> local_packet_issued; //Signals to rx_farend_cnt ///The VC of the packet currenlty being sent and if it has data (one hot encoding) sc_out <sc_bv<6> > current_sent_type; ///Status of the buffers of every VC's for command and data buffers /**Set if it has free buffer (one hot encoding) ResponseData bit 0 Response bit 1 NonPostData bit 2 NonPostCmd bit 3 PostData bit 4 PostCmd bit 5 */ sc_in<sc_bv<6> > fwd_next_node_buffer_status_ro; #ifdef RETRY_MODE_ENABLED ///Clear the count of buffers for the next HT node to zero sc_out <bool> clear_farend_count; //Misc signals ///Link requests that we start a retry disconnect sequence sc_in <bool> lk_initiate_retry_disconnect; ///Force the link to disconnect /**Disconnect will occur after the current dword is done sending*/ sc_out <bool> fc_disconnect_lk; ///Command decoder requests that we start a retry disconnect sequence sc_in <bool> cd_initiate_retry_disconnect; #endif //Signal to multiplexer ///Select which signal to send to link sc_out <sc_uint<4> > fc_ctr_mux; //Signals to link ///LCTL output signal sc_out <bool> fc_lctl_lk; ///HCTL output signal sc_out <bool> fc_hctl_lk; ///For the link to consume data we send to it sc_in <bool> lk_consume_fc; #ifdef RETRY_MODE_ENABLED ///If the RX part of the link is connected sc_in <bool> lk_rx_connected; #endif //Misc signals ///If a nop is being sent to the link sc_out <bool> fc_nop_sent; ///Reset sc_in <bool> resetx; ///LDTSTOP# - Stop the transfer of data to save power sc_in <bool> ldtstopx; ///Clock sc_in_clk clock; ///Configuration register bit to turn the transmitter off //sc_in <bool> csr_transmitteroff; ///A nop was just received - new ack value and new freed buffers value sc_in<bool> nop_received; #ifdef RETRY_MODE_ENABLED ///If we are in retry mode sc_in<bool> csr_retry; //History signals ///Packet from the output of the history buffers sc_in <sc_bv<32> > history_packet; ///Everything in the history buffers has bee played back sc_in <bool > history_playback_done; ///When the history is ready to begin playback sc_in <bool > history_playback_ready; ///Start to replay the content of the history buffer sc_out <bool > begin_history_playback; ///Interrupt the replay of the content of the history buffer sc_out <bool > stop_history_playback; ///To read the data from the history buffer sc_out <bool > consume_history; ///The amount of dwords left in the history sc_in <bool > room_available_in_history; ///Add a dword to the current history entry /** You must have created an history entry before entering dwords in it... */ sc_out <bool > add_to_history; ///Start a new history entry (packet) of size new_history_entry_size_m1 sc_out <bool > new_history_entry; ///Size of the new history entry sc_out<sc_uint<5> > new_history_entry_size_m1; //Signals to CRC unit ///Calculate the CRC on the current output to the link sc_out<bool> calculate_crc; ///Clear the current calculated CRC value sc_out<bool> clear_crc; ///Calculate the CRC on the current output to the link for nop packets sc_out<bool> calculate_nop_crc; ///Calculate the CRC on the current output to the link for nop packets sc_out<bool> clear_nop_crc; ///If we should output the current calculated CRC sc_out<bool> select_crc_output; ///If we should output the current calculated nop CRC sc_out<bool> select_nop_crc_output; ///Next value of ::fc_disconnect_lk sc_signal <bool> next_fc_disconnect_lk; ///Next value of ::calculate_nop_crc sc_signal<bool> next_calculate_nop_crc; ///Next value of ::calculate_crc sc_signal<bool> next_calculate_crc; ///Next value of ::select_crc_output sc_signal<bool> next_select_crc_output; ///Next value of ::select_nop_crc_output sc_signal<bool> next_select_nop_crc_output; #endif ///Saved value of fwd_vctype_db sc_signal<VirtualChannel> buffered_fwd_vctype_db; ///Saved value of fwd_address_db sc_signal <sc_uint<BUFFERS_ADDRESS_WIDTH> > buffered_fwd_address_db; ///The next value fc_data_vc_ui will take sc_signal<VirtualChannel> buffered_fc_data_vc_ui; ///Registered value of ::lk_rx_connected sc_signal<bool> registered_lk_rx_connected; ///Registered value of ::registered_lk_initiate_retry_disconnect sc_signal<bool> registered_lk_initiate_retry_disconnect; //Buffer signals to link ///LCTL output signal sc_signal<bool> next_fc_lctl_lk; ///HCTL output signal sc_signal <bool> next_fc_hctl_lk; ///Next value of next_data_cnt sc_signal<sc_uint<4> > next_data_cnt; ///The number of dwords left to send all the data payload of a packet sc_signal<sc_uint<4> > data_cnt; ///Next value of ::has_data sc_signal<bool > next_has_data; ///If there is still data to be sent for the current packet sc_signal<bool > has_data; ///Next value of chain_current_state sc_signal<fc_chain_state> next_chain_current_state; ///The current state for sending posted packets that have chain bits /** When sending a posted packet that has chain bit set, it means it is a chain of packets that cannot be seperated by inserting other posted packets, so we remember it by going in a chain state*/ sc_signal<fc_chain_state> chain_current_state; ///The next value curr_state will take (at rising edge of the clock) sc_signal <fc_state> next_state; ///The current state of the flow_control_l3 sc_signal <fc_state> curr_state; #ifdef RETRY_MODE_ENABLED ///Register to store that a retry disconnect has been initiated sc_signal<bool> retry_disconnect_initiated; ///To clear the retry_disconnect_initiated signal sc_signal<bool> clear_retry_disconnect_initiated; ///Register to store if we have received at least one ack (a nop packet) from //the other link /** It is important to wait for this to be set before replaying the history in a retry sequence, to be sure that we start playing back the history at the right position*/ sc_signal<bool> received_ack; #endif ///Register to reserve a local fairness spot for a VC sc_signal<bool> fairness_vc_reserved[3]; ///next value of fairness_vc_reserved sc_signal<bool> next_fairness_vc_reserved[3]; ///Signals calculated by ::find_next_state() //@{ sc_signal <fc_state> found_next_state; sc_signal<bool> found_load_fwd_pkt; sc_signal<bool> found_load_eh_pkt; sc_signal<bool> found_load_csr_pkt; sc_signal<bool> found_load_user_fifo_pkt; sc_signal<bool> found_hold_user_fifo_pkt; sc_signal<fc_chain_state> found_next_chain_current_state; sc_signal<sc_bv<6> > found_current_sent_type; sc_signal<sc_uint<4> > found_fc_ctr_mux; sc_signal<bool> found_generate_disconnect_nop; sc_signal<bool> found_fc_nop_sent; sc_signal<VirtualChannel> found_fwd_vctype_db; sc_signal<sc_uint<BUFFERS_ADDRESS_WIDTH> > found_fwd_address_db; sc_signal<sc_uint<4> > found_next_data_cnt; sc_signal<bool> found_next_has_data; sc_signal<VirtualChannel> found_fc_data_vc_ui; sc_signal<bool> found_local_packet_issued; sc_signal<bool> found_next_fairness_vc_reserved[3]; #ifdef RETRY_MODE_ENABLED sc_signal<sc_uint<5> > found_new_history_entry_size_m1; sc_signal<bool > found_new_history_entry; sc_signal<bool> found_next_calculate_crc; sc_signal<bool> found_next_calculate_nop_crc; #endif //@} #ifdef RETRY_MODE_ENABLED ///Signals calculated by ::find_next_retry_state() //@{ sc_signal<sc_uint<4> > foundh_fc_ctr_mux; sc_signal<bool> foundh_fc_nop_sent; sc_signal<fc_state> foundh_next_state; sc_signal<bool> foundh_next_fc_lctl_lk; sc_signal<bool> foundh_next_fc_hctl_lk; sc_signal<bool> foundh_next_calculate_nop_crc; sc_signal<bool> foundh_next_calculate_crc; sc_signal<sc_uint<4> > foundh_next_data_cnt; sc_signal<bool> foundh_next_has_data; sc_signal<sc_bv<6> > foundh_current_sent_type; sc_signal<bool> foundh_consume_history; sc_signal<bool> foundh_generate_disconnect_nop; //@} #endif ///The clocked process for the state machine void fc_fsm_state( void ); ///Finds the next state of the flow_control_l3 void fc_fsm( void ); ///Verify that that type of packet can be sent to the other link /** @param vc The virtual channel to verify @param data If we are looking at the data buffers. false for command buffers @return If a packet of VirtulChannel vc and that does (data==true) or does not(data==false) can be sent to the next HT node. The next HT node must have enough free buffers to accept the packet */ bool verify_buffer_status (VirtualChannel vc , bool data); ///Find the one hot encoded value of what packet type is being sent void set_found_sent_type (VirtualChannel vc , bool data); ///Find the next state to go in when a new packet has to be sent (combinatory process) /** @description This part needs a bit of explaining. The method find_next_state finds what is the next thing we need to do when not in a retry sequence and also finds the different outputs of the design. It is called after a packet has finished being sent : we are ready so send a new packet. This needs to be done at multiple places in the code. If the function is called directly from the state machine, during synthesis, the function will be embeded multiple times in the states machines. Since the method is quite big, it really blows up the size of the final verilog or vhdl code, making it VERY long to synthesize afterwards. To cut back on this time, the method find_next_state is a combinatory process which set signals named found_*, then the state machine can calls ::set_next_state() to set the outputs to what was found in the next state. This way, only the assignation is placed in the state machine during synthesis. */ void find_next_state(); ///Set what ::find_next_state() has found void set_next_state(); ///Methods to go to specific state while also setting correct outputs //@{ void go_NOP_SENT(); void go_NOP_SENT_IN_FWD(); void go_NOP_SENT_IN_USER(); void go_NOP_SENT_IN_EH(); void go_NOP_SENT_IN_CSR(); void go_FWD_DATA_SENT(); void go_USER_DATA_SENT(); void go_ERROR_DATA_SENT(); void go_CSR_DATA_SENT(); void go_LDTSTOP_DISCONNECT(); #ifdef RETRY_MODE_ENABLED void go_RETRY_NOP_SENT(); void go_SEND_DATA_CRC(); void go_RETRY_NOP_SENT_IN_DATA(); void go_SEND_CMD_CRC(); void go_RETRY_SEND_CMD_CRC_DATA(); void go_RETRY_SEND_CMD_CRC(); void go_RETRY_DATA_SENT(); void go_RETRY_SEND_DISCONNECT(); void go_NOP_CRC_SENT_IN_FWD(); #endif //@} #ifdef RETRY_MODE_ENABLED ///Find the next state during retry mode(combinatory process) /** @description This is the equivalent of the ::find_next_state() , except that it is for when we are in a retry sequence */ void find_next_retry_state(); ///Set what ::find_next_retry_state() has found void go_next_retry_state(); ///Find the one hot encoded value of what packet type is being sent void set_foundh_sent_type (VirtualChannel vc , bool data); #endif ///SystemC Macro SC_HAS_PROCESS(flow_control_l3); ///Macro CTOR SystemC - flow_control_l3 constructor flow_control_l3(sc_module_name name); }; #endif