URL
https://opencores.org/ocsvn/ht_tunnel/ht_tunnel/trunk
Subversion Repositories ht_tunnel
[/] [ht_tunnel/] [trunk/] [rtl/] [systemc/] [reordering_l2/] [response_vc_l3.cpp] - Rev 19
Compare with Previous | Blame | View Log
//response_vc_l3.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> * Laurent Aubray * * 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 "response_vc_l3.h" /// Basic constructor response_vc_l3::response_vc_l3(sc_module_name name): sc_module(name) { SC_METHOD(clocked_process); sensitive_pos << clk; sensitive_neg << resetx; SC_METHOD(select_and_drive_output); for(int n = 0; n < NB_OF_BUFFERS;n++){ sensitive << packet_addr_register[n] #ifdef ENABLE_REORDERING << packet_passpw_register[n] #endif << destination_registers[n]; } } #ifdef SYSTEMC_SIM response_vc_l3::~response_vc_l3(){ } #endif #ifdef ENABLE_REORDERING /** @description To determine if two packets should be switched because the low packet is more important than the high packet. -If low packet has more priority than high packet and passing does not break ordering rules, returns 1 -If high packet has more priority than low packet and passing does not break ordering rules, returns 0 -If two packets have identical priority or passing one another breaks ordering rules, returns compare_with_higher @param high_pkt_complete The higher packet (packet currently ahead) @param low_pkt_complete The lower packet (packet currently behind) @param low_buffer_free If low_pkt_complete is a valid packet @param high_buffer_free If high_pkt_complete is a valid packet @param compare_with_higher If the packet (low) is currently compared with the higher packet, or the lower packet. Normally, this function should make abstraction that the high_pkt_complete can actually be lower, but when two packets have the same priority, we don't want them to be switched so we return the compare_with_higher value as an answer @return if the low packet should pass the high packet */ bool response_vc_l3::evaluate_switch_packets( bool high_passPW, bool low_passPW, bool high_buffer_free, bool low_buffer_free, sc_uint<MAX_PASSPW_P1_LOG2_COUNT> high_pass_count, sc_uint<MAX_PASSPW_P1_LOG2_COUNT> low_pass_count, /*Normally, this function should make abstraction that the high_pkt_complete can actually be lower, but when two packets have the same priority, we don't want them to be switched so we return the compare_with_higher value as an answer*/ bool compare_with_higher) { bool select_low; //If a packet has been switched the maximum of time, we don't switch it! if(high_pass_count == MAX_PASSPW_COUNT || low_pass_count == MAX_PASSPW_COUNT){ select_low = compare_with_higher; } else{ if(low_passPW && !high_passPW) select_low = true; else if(!low_passPW && high_passPW) select_low = false; else select_low = compare_with_higher; } return (select_low || low_buffer_free) && !high_buffer_free; } #endif void response_vc_l3::clocked_process() { if(!resetx.read()){ /////////////////////////////////////////// // Reset of internal registers /////////////////////////////////////////// for(int n = 0; n < NB_OF_BUFFERS; n++){ destination_registers[n] = 0; packet_addr_register[n] = 0; #ifdef ENABLE_REORDERING packet_passpw_register[n] = false; pass_count[n] = 0; #endif } #ifdef ENABLE_REORDERING compare_with_higher = 0; #endif buffers_cleared = 0; vc_overflow = false; } else{ update_internal_registers(); } } void response_vc_l3::select_and_drive_output(){ //Packet selected to be output to accepted destination sc_bv<NB_OF_BUFFERS> selected_accepted_tmp; //Packet selected to be output to forward destination sc_bv<NB_OF_BUFFERS> selected_forward_tmp; //If a packet was found for accepted destination bool selected_accepted_found; //If a packet was found for forward destination bool selected_forward_found; select_top_packet(selected_accepted_tmp,selected_accepted_found, selected_forward_tmp,selected_forward_found); drive_output(selected_accepted_tmp,selected_accepted_found, selected_forward_tmp,selected_forward_found); selected_accepted = selected_accepted_tmp; selected_forward = selected_forward_tmp; } void response_vc_l3::update_internal_registers() { //First, handle deletion of buffers : modify the destination vector //so that it takes into account buffers deleted sc_bv<2> destination_with_deletion[NB_OF_BUFFERS]; bool deleted_packet_for_accepted = false; bool deleted_packet_for_forward = false; for(int n = 0; n < NB_OF_BUFFERS; n++){ //Now, is that packet being output and deleted? bool accepted_deleted = (acknowledge[ACCEPTED_DEST].read()) && (sc_bit)selected_accepted.read()[n]; //If deleted, update it's value if(accepted_deleted){ destination_with_deletion[n][ACCEPTED_DEST] = 0; } else{ destination_with_deletion[n][ACCEPTED_DEST] = (sc_bit)destination_registers[n].read()[ACCEPTED_DEST]; } //Now, is that packet being output and deleted? bool forward_deleted = (acknowledge[FWD_DEST].read()) && (sc_bit)selected_forward.read()[n]; //If deleted, update it's value if(forward_deleted){ destination_with_deletion[n][FWD_DEST] = 0; } else{ destination_with_deletion[n][FWD_DEST] = (sc_bit)destination_registers[n].read()[FWD_DEST]; } //If the packet was consumed for the accepted destination and //does not have any more destination, the packet has been deleted if(accepted_deleted && (!(sc_bit)destination_with_deletion[n][ACCEPTED_DEST] && !(sc_bit)destination_with_deletion[n][FWD_DEST])){ deleted_packet_for_accepted = true; } //If the packet was consumed for the forward destination and //does not have any more destination, the packet has been deleted if(forward_deleted && (!(sc_bit)destination_with_deletion[n][FWD_DEST] && !(sc_bit)destination_with_deletion[n][FWD_DEST])){ deleted_packet_for_forward = true; } } /////////////////////////////////////////////////////////// //Send to the nophandler how many packets have been deleted /////////////////////////////////////////////////////////// bool same_position_accepted_forward_packets = selected_accepted.read() == selected_forward.read(); sc_bv<2> buffers_cleared_tmp; if(deleted_packet_for_forward && deleted_packet_for_accepted){ if(same_position_accepted_forward_packets){ buffers_cleared_tmp = "01"; } else{ buffers_cleared_tmp = "11"; } } else{ buffers_cleared_tmp[ACCEPTED_DEST] = deleted_packet_for_accepted; buffers_cleared_tmp[FWD_DEST] = deleted_packet_for_forward; } buffers_cleared = buffers_cleared_tmp; /** We're trying to keep the packets compacted on the bottom. Every time a new packet is received though, packets must moved up. We could directly use the in_packet_destination to calculate if packets should be moved up, but it takes quite a while to computer so it's not a good idea. A compromise is to attempt to keep the first buffer free unless all buffers are taken. So we move up when the first buffer has a packet, all buffers are full. */ bool buffer_full[NB_OF_BUFFERS]; for(int n = 0; n < NB_OF_BUFFERS; n++){ buffer_full[n] = (sc_bit)destination_registers[n].read()[0] || (sc_bit)destination_registers[n].read()[1]; } //Check if the buffers are all full bool all_full = true; for(int n = 1; n < NB_OF_BUFFERS; n++){ all_full = all_full && buffer_full[n]; } //Move things up if packet in first buffer unless everything is full bool moving_up = buffer_full[0] && !(all_full); //Calculate individual move_up vectors, to compact any holes left by //consumed packets. Packets will move_up until a hole is filled bool move_up[NB_OF_BUFFERS]; move_up[0] = moving_up; //Create the new first destination vector sc_bv<2> new_first_destination; new_first_destination[0] = in_packet_destination[0].read(); new_first_destination[1] = in_packet_destination[1].read(); #ifndef ENABLE_REORDERING //////////////////////////////////////// // Simple algorithm without reordering // Packets move up in the buffers when there is free room //////////////////////////////////////// for(int n = 1; n < NB_OF_BUFFERS; n++){ bool all_full_above_entry = true; for(int i = 1; i < NB_OF_BUFFERS; i++){ if(i > n) all_full_above_entry = all_full_above_entry && buffer_full[i]; } move_up[n] = moving_up && !all_full_above_entry; } //Unless all buffers are full, read the incoming packet. This avoids //using the in_packet_destination which comes late if(!((sc_bit)destination_registers[NB_OF_BUFFERS-1].read()[0] || (sc_bit)destination_registers[NB_OF_BUFFERS-1].read()[1])){ packet_addr_register[0] = in_packet_addr.read(); destination_registers[0] = new_first_destination; } else{ packet_addr_register[0] = packet_addr_register[0]; destination_registers[0] = destination_registers[0]; } for(int n = 1; n < NB_OF_BUFFERS; n++){ if(move_up[n]){ packet_addr_register[n] = packet_addr_register[n-1].read(); destination_registers[n] = destination_with_deletion[n-1]; } else{ packet_addr_register[n] = packet_addr_register[n].read(); destination_registers[n] = destination_with_deletion[n]; } } #else //toggle compare_with_higher at every clock cycle //except don't toggle when move_up is true, because packets are //shifted one pos compare_with_higher = compare_with_higher.read() ^ !moving_up; for(int n = 0; n < (NB_OF_BUFFERS/2); n++){ bool all_full_above_entry = true; for(int i = 1; i < NB_OF_BUFFERS; i++){ if(i > n*2+2) all_full_above_entry = all_full_above_entry && buffer_full[i]; } //This is tad bit hard to explain. The only reason that we don't want //to move up is if the buffer is free and that the new packet can come //in the buffer 1 without having move_up. //Assume impair number of buffers move_up[n*2+1] = moving_up && (!all_full_above_entry || !buffer_full[n*2+1] || !buffer_full[n*2+2] || !buffer_full[n*2] && !compare_with_higher.read() && !unitid_reorder_disable.read()); move_up[n*2+2] = moving_up && (!all_full_above_entry || !buffer_full[n*2+2] || !buffer_full[n*2+1] && compare_with_higher.read() && !unitid_reorder_disable.read()); } //////////////////////////////////////// //Decide what buffers should be switched //////////////////////////////////////// bool switch_packets[NB_OF_BUFFERS/2]; bool lower_buffer_free[NB_OF_BUFFERS/2]; sc_bv<NB_OF_BUFFERS> buffer_free; //Look at which registers are free and store in vector. for(int n = 0; n < NB_OF_BUFFERS; n++){ buffer_free[n] = !(sc_bit)destination_registers[n].read()[ACCEPTED_DEST] && !(sc_bit)destination_registers[n].read()[FWD_DEST]; } //With the compare_with_higher signal, choose which packets are //to be compared bool lower_passPW[NB_OF_BUFFERS]; sc_uint<MAX_PASSPW_P1_LOG2_COUNT> lower_pass_count[NB_OF_BUFFERS/2]; for(int n = 0; n < NB_OF_BUFFERS/2; n++){ if(compare_with_higher.read()){ lower_passPW[n] = packet_passpw_register[2 * (n + 1)]; lower_buffer_free[n] = (sc_bit)buffer_free[2 * (n + 1)]; lower_pass_count[n] = pass_count[2 * (n + 1)].read(); } else{ lower_passPW[n] = packet_passpw_register[2 * n]; lower_buffer_free[n] = (sc_bit)buffer_free[2 * n]; lower_pass_count[n] = pass_count[2 * n].read(); } } //Calculate if packets should be switched for(int n = 0; n < NB_OF_BUFFERS/2; n++){ if(unitid_reorder_disable.read()){ switch_packets[n] = compare_with_higher.read(); } else{ switch_packets[n] = evaluate_switch_packets( packet_passpw_register[2*n+1].read(),lower_passPW[n], (sc_bit)buffer_free[2 * n + 1],lower_buffer_free[n], pass_count[2*n+1].read(),lower_pass_count[n], compare_with_higher.read()); } } ////////////////////////////////////////////////////////////////////// //With the deleted packets and switch signals, store the right packets ////////////////////////////////////////////////////////////////////// //It's the same logic for pair and impair registers, with the exception //of the first, second and last buffer. That's why there's a minimum of //3 buffers //Special case : first register sc_uint<3> first_case_selector; first_case_selector[0] = !(((sc_bit)destination_registers[NB_OF_BUFFERS-1].read()[0] || (sc_bit)destination_registers[NB_OF_BUFFERS-1].read()[1]) && ((sc_bit)destination_registers[0].read()[0] || (sc_bit)destination_registers[0].read()[1]));//buffer not full first_case_selector[1] = compare_with_higher.read(); first_case_selector[2] = (sc_bit)switch_packets[0]; switch(first_case_selector){ case 1: case 3: case 5: case 7: destination_registers[0] = new_first_destination; packet_addr_register[0] = in_packet_addr; packet_passpw_register[0] = in_packet_passpw; pass_count[0] = 0; break; case 4: destination_registers[0] = destination_with_deletion[1]; packet_addr_register[0] = packet_addr_register[1]; packet_passpw_register[0] = packet_passpw_register[1]; pass_count[0] = pass_count[1].read()+1; break; default: destination_registers[0] = destination_with_deletion[0]; packet_addr_register[0] = packet_addr_register[0]; packet_passpw_register[0] = packet_passpw_register[0]; pass_count[0] = pass_count[0].read(); } //Special case : second register sc_uint<4> second_case_selector; second_case_selector[0] = move_up[1]; second_case_selector[1] = compare_with_higher.read(); second_case_selector[2] = (sc_bit)switch_packets[0]; second_case_selector[3] = !((sc_bit)destination_registers[0].read()[0] || (sc_bit)destination_registers[0].read()[1]);//register 0 empty sc_uint<MAX_PASSPW_P1_LOG2_COUNT+1> original_pass_count1; switch(second_case_selector){ case 1: case 3: case 4: case 7: case 11: case 15: destination_registers[1] = destination_with_deletion[0]; packet_addr_register[1] = packet_addr_register[0]; packet_passpw_register[1] = packet_passpw_register[0]; original_pass_count1 = pass_count[0].read(); break; case 2: case 10: destination_registers[1] = destination_with_deletion[2]; packet_addr_register[1] = packet_addr_register[2]; packet_passpw_register[1] = packet_passpw_register[2]; original_pass_count1 = pass_count[2].read(); break; default: destination_registers[1] = destination_with_deletion[1]; packet_addr_register[1] = packet_addr_register[1]; packet_passpw_register[1] = packet_passpw_register[1]; original_pass_count1 = pass_count[1].read(); } bool increase_pass_count1; switch(second_case_selector){ case 2: case 5: case 10: increase_pass_count1 = true; break; default: increase_pass_count1 = false; } pass_count[1] = original_pass_count1+sc_uint<1>(increase_pass_count1); //Special case : last register sc_uint<3> last_case_selector; last_case_selector[0] = move_up[NB_OF_BUFFERS-1]; last_case_selector[1] = compare_with_higher.read(); last_case_selector[2] = (sc_bit)switch_packets[NB_OF_BUFFERS/2 - 1]; switch(last_case_selector){ case 1: case 2: case 3: case 7: destination_registers[NB_OF_BUFFERS - 1] = destination_with_deletion[NB_OF_BUFFERS - 2]; packet_addr_register[NB_OF_BUFFERS - 1] = packet_addr_register[NB_OF_BUFFERS - 2]; packet_passpw_register[NB_OF_BUFFERS - 1] = packet_passpw_register[NB_OF_BUFFERS - 2]; pass_count[NB_OF_BUFFERS - 1] = pass_count[NB_OF_BUFFERS - 2].read(); break; case 5: destination_registers[NB_OF_BUFFERS - 1] = destination_with_deletion[NB_OF_BUFFERS - 3]; packet_addr_register[NB_OF_BUFFERS - 1] = packet_addr_register[NB_OF_BUFFERS - 3]; packet_passpw_register[NB_OF_BUFFERS - 1] = packet_passpw_register[NB_OF_BUFFERS - 3]; pass_count[NB_OF_BUFFERS - 1] = pass_count[NB_OF_BUFFERS - 3].read(); break; default: destination_registers[NB_OF_BUFFERS - 1] = destination_with_deletion[NB_OF_BUFFERS - 1]; packet_addr_register[NB_OF_BUFFERS - 1] = packet_addr_register[NB_OF_BUFFERS - 1]; packet_passpw_register[NB_OF_BUFFERS - 1] = packet_passpw_register[NB_OF_BUFFERS - 1]; pass_count[NB_OF_BUFFERS - 1] = pass_count[NB_OF_BUFFERS - 1].read(); } //Generic case for(int n = 0; n < NB_OF_BUFFERS/2 - 1; n++){ //Pair register (if starting from 0) sc_uint<4> pair_case_selector; pair_case_selector[0] = (sc_bit)switch_packets[n + 1]; pair_case_selector[1] = (sc_bit)switch_packets[n]; pair_case_selector[2] = move_up[2 * n + 3]; pair_case_selector[3] = compare_with_higher.read(); sc_uint<MAX_PASSPW_P1_LOG2_COUNT+1> original_pass_count_pair; switch(pair_case_selector){ case 1: case 3: case 4: case 6: case 14: case 15: destination_registers[2 * n + 3] = destination_with_deletion[2 * n + 2]; packet_addr_register[2 * n + 3] = packet_addr_register[2 * n + 2]; packet_passpw_register[2 * n + 3] = packet_passpw_register[2 * n + 2]; original_pass_count_pair = pass_count[2 * n + 2].read(); break; case 8: case 10: destination_registers[2 * n + 3] = destination_with_deletion[2 * n + 4]; packet_addr_register[2 * n + 3] = packet_addr_register[2 * n + 4]; packet_passpw_register[2 * n + 3] = packet_passpw_register[2 * n + 4]; original_pass_count_pair = pass_count[2 * n + 4].read(); break; case 12: case 13: destination_registers[2 * n + 3] = destination_with_deletion[2 * n + 1]; packet_addr_register[2 * n + 3] = packet_addr_register[2 * n + 1]; packet_passpw_register[2 * n + 3] = packet_passpw_register[2 * n + 1]; original_pass_count_pair = pass_count[2 * n + 1].read(); break; default: destination_registers[2 * n + 3] = destination_with_deletion[2 * n + 3]; packet_addr_register[2 * n + 3] = packet_addr_register[2 * n + 3]; packet_passpw_register[2 * n + 3] = packet_passpw_register[2 * n + 3]; original_pass_count_pair = pass_count[2 * n + 3].read(); } bool increment_pair_pass_count; switch(pair_case_selector){ case 8: case 10: increment_pair_pass_count = buffer_full[2 * n + 3]; break; case 5: case 7: increment_pair_pass_count = buffer_full[2 * n + 2]; break; default: increment_pair_pass_count = false; } pass_count[2 * n + 3] = original_pass_count_pair + sc_uint<1>(increment_pair_pass_count); //Impair register (if starting from 0) sc_uint<4> impair_case_selector; impair_case_selector[0] = (sc_bit)switch_packets[n + 1]; impair_case_selector[1] = (sc_bit)switch_packets[n]; impair_case_selector[2] = move_up[2 * n + 2]; impair_case_selector[3] = compare_with_higher.read(); sc_uint<MAX_PASSPW_P1_LOG2_COUNT+1> original_pass_count_impair; switch(impair_case_selector){ case 4: case 5: case 8: case 9: case 14: case 15: destination_registers[2 * n + 2] = destination_with_deletion[2 * n + 1]; packet_addr_register[2 * n + 2] = packet_addr_register[2 * n + 1]; packet_passpw_register[2 * n + 2] = packet_passpw_register[2 * n + 1]; original_pass_count_impair = pass_count[2 * n + 1].read(); break; case 1: case 3: destination_registers[2 * n + 2] = destination_with_deletion[2 * n + 3]; packet_addr_register[2 * n + 2] = packet_addr_register[2 * n + 3]; packet_passpw_register[2 * n + 2] = packet_passpw_register[2 * n + 3]; original_pass_count_impair = pass_count[2 * n + 3].read(); break; case 6: case 7: destination_registers[2 * n + 2] = destination_with_deletion[2 * n]; packet_addr_register[2 * n + 2] = packet_addr_register[2 * n]; packet_passpw_register[2 * n + 2] = packet_passpw_register[2 * n]; original_pass_count_impair = pass_count[2 * n].read(); break; default: destination_registers[2 * n + 2] = destination_with_deletion[2 * n + 2]; packet_addr_register[2 * n + 2] = packet_addr_register[2 * n + 2]; packet_passpw_register[2 * n + 2] = packet_passpw_register[2 * n + 2]; original_pass_count_impair = pass_count[2 * n + 2].read(); } bool increment_impair_pass_count; switch(impair_case_selector){ case 1: case 3: //destination_registers[2 * n + 2] = destination_with_deletion[2 * n + 3]; increment_impair_pass_count = buffer_full[2 * n + 2]; break; case 12: case 13: increment_impair_pass_count = buffer_full[2 * n + 1]; break; default: increment_impair_pass_count = false; } pass_count[2 * n + 2] = original_pass_count_impair + sc_uint<1>(increment_impair_pass_count); } #endif //Check to log overflow errors vc_overflow = ((sc_bit)destination_registers[NB_OF_BUFFERS-1].read()[0] || (sc_bit)destination_registers[NB_OF_BUFFERS-1].read()[1]) && ((sc_bit)destination_registers[0].read()[0] || (sc_bit)destination_registers[0].read()[1]) && ((sc_bit)new_first_destination[0] || (sc_bit)new_first_destination[1]); } void response_vc_l3::drive_output(sc_bv<NB_OF_BUFFERS> selected_accepted, bool selected_accepted_found, sc_bv<NB_OF_BUFFERS> selected_forward, bool selected_forward_found) { //================================================ //Output the packet that were found by the encoder //================================================ sc_uint<LOG2_NB_OF_BUFFERS> out_packet_addr_accepted = 0; #ifdef ENABLE_REORDERING bool out_packet_passpw_accepted = false; #endif //This is a AND-OR for(int n = 0; n < NB_OF_BUFFERS; n++){ //AND the packet with the selected bit sc_uint<LOG2_NB_OF_BUFFERS> select_out_packet_addr; #ifdef ENABLE_REORDERING bool select_out_packet_passpw; #endif for(int i = 0; i < LOG2_NB_OF_BUFFERS; i++) select_out_packet_addr[i] = (sc_bit)packet_addr_register[n].read()[i] && (sc_bit)selected_accepted[n]; #ifdef ENABLE_REORDERING select_out_packet_passpw = packet_passpw_register[n].read() && (sc_bit)selected_accepted[n]; #endif //OR together all packets. Since only one packet is selected, the output will be that packet out_packet_addr_accepted = out_packet_addr_accepted | select_out_packet_addr; #ifdef ENABLE_REORDERING out_packet_passpw_accepted = out_packet_passpw_accepted || select_out_packet_passpw; #endif } //Output the packet out_packet_addr[ACCEPTED_DEST] = out_packet_addr_accepted; #ifdef ENABLE_REORDERING out_packet_passpw[ACCEPTED_DEST] = out_packet_passpw_accepted; #endif sc_uint<LOG2_NB_OF_BUFFERS> out_packet_addr_forward = 0; #ifdef ENABLE_REORDERING bool out_packet_passpw_forward = false; #endif for(int n = 0; n < NB_OF_BUFFERS; n++){ //AND the packet with the selected bit sc_uint<LOG2_NB_OF_BUFFERS> select_out_packet_addr; #ifdef ENABLE_REORDERING bool select_out_packet_passpw; #endif for(int i = 0; i < LOG2_NB_OF_BUFFERS; i++) select_out_packet_addr[i] = (sc_bit)packet_addr_register[n].read()[i] && (sc_bit)selected_forward[n]; #ifdef ENABLE_REORDERING select_out_packet_passpw = packet_passpw_register[n].read() && (sc_bit)selected_forward[n]; #endif //OR together all packets. Since only one packet is selected, the output will be that packet out_packet_addr_forward = out_packet_addr_forward | select_out_packet_addr; #ifdef ENABLE_REORDERING out_packet_passpw_forward = out_packet_passpw_forward || select_out_packet_passpw; #endif } out_packet_addr[FWD_DEST] = out_packet_addr_forward; #ifdef ENABLE_REORDERING out_packet_passpw[FWD_DEST] = out_packet_passpw_forward; #endif packet_available[ACCEPTED_DEST] = selected_accepted_found; packet_available[FWD_DEST] = selected_forward_found; } void response_vc_l3::select_top_packet(sc_bv<NB_OF_BUFFERS> &selected_accepted, bool &selected_accepted_found, sc_bv<NB_OF_BUFFERS> &selected_forward, bool &selected_forward_found) { //==================================== //Encoder for the Accepted destination //==================================== sc_bv<NB_OF_BUFFERS> accepted_to_encode; //Start by copying the signal for(int n = 0; n < NB_OF_BUFFERS; n++){ accepted_to_encode[n] = (sc_bit)destination_registers[n].read()[ACCEPTED_DEST]; } //Tree of or to find if there is a packet bool found_accepted = accepted_to_encode.or_reduce(); //Find what is the highest packet in the buffers sc_bv<NB_OF_BUFFERS> accepted_one_hot; //If top packet if full, then it is the chosen packet accepted_one_hot[NB_OF_BUFFERS-1] = accepted_to_encode[NB_OF_BUFFERS-1]; //For all other positions, check that it is full and all higher buffers are empty for(int n = 0; n < (NB_OF_BUFFERS-1); n++){ //Commented because SystemC synthesis tool cannot take part vectors //that use a loop variable *even* if the loop is unrolled //...go figure //accepted_one_hot[n] = (sc_bit)accepted_to_encode[n] && // (~(accepted_to_encode.range(NB_OF_BUFFERS-1,n+1))).and_reduce(); //I really hope the synthesis simplifies this because it's an awfull hack... bool accepted_ahead = false; for(int i = NB_OF_BUFFERS-1; i > 0;i--){ if(i>n) accepted_ahead = accepted_ahead || (sc_bit)accepted_to_encode[i]; } accepted_one_hot[n] = (sc_bit)accepted_to_encode[n] && !accepted_ahead; } //=================================== //Encoder for the Forward destination //=================================== sc_bv<NB_OF_BUFFERS> forward_to_encode; //Start by copying the signal for(int n = 0; n < NB_OF_BUFFERS; n++){ forward_to_encode[n] = (sc_bit)destination_registers[n].read()[FWD_DEST]; } //Tree of or to find if there is a packet bool found_forward = forward_to_encode.or_reduce(); //Find what is the highest packet in the buffers sc_bv<NB_OF_BUFFERS> forward_one_hot; //If top packet if full, then it is the chosen packet forward_one_hot[NB_OF_BUFFERS-1] = forward_to_encode[NB_OF_BUFFERS-1]; //For all other positions, check that it is full and all higher buffers are empty for(int n = 0; n < (NB_OF_BUFFERS-1); n++){ //Same as for accepted loop, RTL compiler problems //forward_one_hot[n] = (sc_bit)forward_to_encode[n] && // (~(forward_to_encode.range(NB_OF_BUFFERS-1,n+1))).and_reduce(); bool forwarded_ahead = false; for(int i = NB_OF_BUFFERS-1; i > 0;i--){ if(i>n) forwarded_ahead = forwarded_ahead || (sc_bit)forward_to_encode[i]; } forward_one_hot[n] = (sc_bit)forward_to_encode[n] && !forwarded_ahead; } //Share the result with the rest of the module for the deletion of packets selected_accepted = accepted_one_hot; selected_forward = forward_one_hot; selected_accepted_found = found_accepted; selected_forward_found = found_forward; } #ifndef SYSTEMC_SIM #include "../core_synth/synth_control_packet.cpp" #endif