OpenCores
URL https://opencores.org/ocsvn/ht_tunnel/ht_tunnel/trunk

Subversion Repositories ht_tunnel

[/] [ht_tunnel/] [tags/] [START/] [rtl/] [systemc/] [core_synth/] [synth_control_packet.cpp] - Rev 19

Compare with Previous | Blame | View Log

//synth_control_packet.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 ***** */
 
#ifndef SYNTH_CONTROL_PACKET_CPP
#define SYNTH_CONTROL_PACKET_CPP
 
#include "synth_datatypes.h"
 
/**
	To parse a cmd vector
*/
PacketCommand getPacketCommand(const sc_bv<6> &cmd){
 
	//Check the command vector against all known
	//sequences
	sc_uint<6> command_value = cmd;
 
	PacketCommand return_val;
 
	switch(command_value){
	case 0:
		return_val = NOP;
		break;
	case 0x3F: //0b111111
		return_val = SYNC;
		break;
	case 0x30: //0b110000
		return_val = RD_RESPONSE;
		break;
	case 0x33: //0b110011
		return_val = TGTDONE;
		break;
	case 0x3A: //0b111010
		return_val = BROADCAST;
		break;
	case 0x3C: //0b111100
		return_val = FENCE;
		break;
	case 0x3D: //0b111101
		return_val = ATOMIC;
		break;
	case 0x37: //0b110111
		return_val = EXTENDED_FLOW;
		break;
	case 0x3E: //0b111110
		return_val = ADDR_EXT;
		break;
	case 0x02: //0b000010
		return_val = FLUSH;
		break;
	default:
		if(command_value.range(4 , 3) == 1){//		if(command_value.range(4 , 3) == "01"){
			return_val = WRITE;
		}
		else if(command_value.range(5 , 4) == 1){//else if(command_value.range(5 , 4) == "01"){
			return_val = READ;
		}
		else{
			return_val = RESERVED_CMD;
		}
 
	}
	return return_val;
}
 
/**
	To know the type of packet from a command vector
*/
PacketType getPacketType(const sc_bv<6> &cmd){
 
	PacketType return_val;
 
	sc_bv<6> cmd_buf = cmd;//Workaround for a synthesis problem
 
	//Check the command vector against all known
	//sequences
	if(cmd_buf == "000000" || cmd_buf == "111111" || cmd_buf == "110111"){
		return_val = INFO;
	}
	else if(cmd_buf == "110000" || cmd_buf == "110011"){
		return_val = RESPONSE;		
	}
	else if(cmd_buf.range(5 , 3) == "001" || cmd_buf.range(5 , 3) == "101"
		|| cmd_buf.range(5 , 4) == "01" || cmd_buf == "111010"
		|| cmd_buf == "111100" || cmd_buf == "111101" || cmd_buf == "000010")
	{
		return_val = REQUEST; 	   
	}
	else if(cmd_buf == "111101"){
		return_val = ADDR_EXT_TYPE;
	}
	else{
		return_val = RESERVED_TYPE;
	}
	return return_val;
}
 
bool isDwordPacket(const sc_bv<64> &pkt, const PacketCommand &cmd){
	bool return_val;
 
	switch(cmd){
	case WRITE:
	case READ:
	case BROADCAST:
	case ATOMIC:
	case RESERVED_CMD:
		return_val = false;
		break;
	case EXTENDED_FLOW:
		return_val = !(bool)((sc_bit)pkt[6]);
		break;
	//case ADDR_EXT:
	//case FLUSH:
	//case NOP:
	//case SYNC:
	//case RD_RESPONSE:
	//case TGTDONE:
	//case FENCE:
	default:
		return_val = true;
 
	}
	return return_val;
 
}
 
VirtualChannel getVirtualChannel(const sc_bv<64> &pkt, const PacketCommand &cmd){
 
	VirtualChannel return_val;
 
	switch(cmd){
	case WRITE:
		if(pkt[5] == true){
			return_val = VC_POSTED;
		}
		else{
			return_val = VC_NON_POSTED;	
		}
		break;
	case ATOMIC:
	case FLUSH:
	case READ:
		return_val = VC_NON_POSTED;
		break;
	case FENCE:
	case BROADCAST:
		return_val = VC_POSTED;
		break;
 
	case RD_RESPONSE:
	case TGTDONE:
		return_val = VC_RESPONSE;
		break;
 
	//case SYNC:
	//case RESERVED_CMD:
	//case ADDR_EXT:
	//case NOP:
	//case EXTENDED_FLOW:
	default:
		return_val = VC_NONE;
 
	}
	return return_val;
}
 
bool isChain(const sc_bv<64> &pkt){
	bool return_val;
	//if(posted && write && bit chain)
	if(pkt.range(5 , 3) == "101" &&
	   pkt[19] == true) return_val = true;
	else return_val = false;
	return return_val;
}
 
///Packet has data associated
/**
		To know if there is a data packet associated with this control
		packet
 
		@return If the packet has data associated
*/	
bool hasDataAssociated(const PacketCommand &cmd){
	bool return_val;
 
	switch(cmd){
	case WRITE:
	case RD_RESPONSE:
	case ATOMIC:
		return_val = true;
		break;
 
	//case TGTDONE:
	//case SYNC:
	//case RESERVED_CMD:
	//case ADDR_EXT:
	//case NOP:
	//case EXTENDED_FLOW:
	//case FLUSH:
	//case BROADCAST:
	//case FENCE:
	//case READ:
	default:
		return_val = false;
		break;
 
	}
 
	return return_val;
 
}
 
///Get the length-1 of the data associated
/**
		Gets the number of doublewords of data associated with this ctl packet
		minus 1.  So a returned number of 0 represents 1 doubleWord.
		If there is no data associated, the result is undefined.
		The number returned also includes the doubleword mask in a byte write
 
		@return Length-1 of data associated with the packet, or undefined
		if the packet has no data associated
*/
sc_uint<4> getDataLengthm1(const sc_bv<64> &pkt){
	sc_uint<4> return_val;
 
	//If a byte read (cmd starts by 01 for read, and pkt[2]=0 for byte
	if(pkt[5] == false && pkt[4] == true && pkt[2] == false){
		//DataLength is Doubleword
		return_val = 0;
	}
	else{
		sc_bv<4> temp = pkt.range(25,22);
		return_val = temp;
	}
	return return_val;
}
 
bool getPassPW(const sc_bv<64> &pkt){
	return (sc_bit)(pkt[15]);
}
 
bool getResponsePassPW(const sc_bv<32> &pkt){
	return (sc_bit)(pkt[15]);
}
 
sc_uint<40> getRequestAddr(const sc_bv<64> &request_pkt, const PacketCommand &cmd){
	sc_uint<40> addr = 0;
 
	//If the packet only has 32 bits, dont return an address
	//of only zeros, its the job of the caller to check before calling
	//
	//if(!isDwordPacket(request_pkt,cmd)) {
 
		//Copy the standard range of addresses
		addr.range(39,3) = sc_bv<37>(request_pkt.range(63,27));
 
		//Copy the last bit of the address.  An exception is made for
		//the ATOMIC packet, that has this bit always at 0
		if(cmd != ATOMIC) addr[2] = sc_bit(request_pkt[26]);
	//}
 
	//Return the address
	return addr;
}
 
 
sc_uint<5> getUnitID(const sc_bv<64> &pkt){
	return sc_bv<5>(pkt.range(12,8));
}
 
bool request_getCompatOrIsoc(const sc_bv<64> &pkt){
	return sc_bit(pkt[21]);
}
 
 
 
bool isInAddressRange(const sc_bv<64> &pkt,  const PacketCommand &cmd, const sc_uint<32> &low,
										 const sc_uint<32> &high) {
	bool isInAddressRange_val = false;
	if(!isDwordPacket(pkt,cmd)){
		sc_uint<32> addr = getRequestAddr(pkt,cmd).range(39,8);
		isInAddressRange_val = (addr >= low && addr < high);
	}
	return isInAddressRange_val;
}
 
#ifdef SYSTEMC_SIM
 
bool isInAddressRange(const sc_bv<64> &pkt,  const PacketCommand &cmd, const sc_uint<40> &low,
										 const sc_uint<40> &high) {
	bool isInAddressRange_val = false;
	if(!isDwordPacket(pkt,cmd)){
		sc_uint<40> addr = getRequestAddr(pkt,cmd);
		isInAddressRange_val = (addr >= low && addr < high);
	}
	return isInAddressRange_val;
}
 
										 bool isInAddressRange(const sc_bv<64> &pkt,  const PacketCommand &cmd, const sc_bv<40> &low, const sc_bv<40> &high) {
	//Start by converting the strings to uint
	sc_uint<40> low_uint(low);
	sc_uint<40> high_uint(high);
 
	//Call the function taking uints
	return isInAddressRange(pkt,cmd,low_uint,high_uint);
}
#endif
 
sc_bv<4> request_getSeqID(const sc_bv<64> &pkt){
	sc_bv<4> temp;
	temp.range(3,2) = pkt.range(7,6);
	temp.range(1,0) = pkt.range(14,13);
	return temp;
}
 
bool write_getDataError(const sc_bv<64> &pkt) {
	bool dataError;
	if(pkt[5] == true) dataError = sc_bit(pkt[20]);
	else dataError = false;
	return dataError;
}
 
ResponseError response_getResponseError(const sc_bv<64> &pkt) {
	ResponseError error;
	if(pkt[20] == false){
		if(pkt[28] == false) error = RE_NORMAL;
		error = RE_DATA_ERROR;
	}
	else{
		if(pkt[28] == false) error = RE_TARGET_ABORT;
		error = RE_MASTER_ABORT;
	}
	return error;
}
 
sc_bv<5> request_getSrcTag(const sc_bv<64> &pkt) {
	return pkt.range(20,16);
}
 
sc_bv<32> generateReadResponse(const sc_bv<5> &unitID,
						 const sc_bv<5> &srcTag,
						 const sc_bv<2> &rqUID,
						 const sc_bv<4> &count,
						 bool bridge,
						 ResponseError error,
						 bool passPW,
						 bool isoc)
{
	sc_bv<32> packet = 0;
	packet.range(25,22) = count;
 
	sc_bv<6> packet_command = "110000"; 
	packet.range(5,0) = packet_command;
	packet.range(12,8) = unitID;
	packet.range(20,16) = srcTag;
	packet.range(31,30) = rqUID;
 
	//Error 0 => bv[20]
	//Error 1 => bv[28]
 
	if(error == RE_NORMAL || error == RE_DATA_ERROR)
		packet[20] = false;
	else
		packet[20] = true;
 
	if(error == RE_NORMAL || error == RE_TARGET_ABORT)
		packet[28] = false;
	else
		packet[28] = true;
 
	packet[14] = bridge;
	packet[15] = passPW;
	packet[7] = isoc;
 
	return packet;
}
 
sc_bv<32> generateTargetDone(const sc_bv<5> &unitID,
						 const sc_bv<5> &srcTag,
						 const sc_bv<2> &rqUID,
						 bool bridge,
						 ResponseError error,
						 bool passPW,
						 bool isoc){
	sc_bv<32> packet = 0;
	sc_bv<6> packet_command = "110011";
	packet.range(5,0) = packet_command;
	packet.range(12,8) = unitID;
	packet.range(20,16) = srcTag;
	packet.range(31,30) = rqUID;
 
	//Error 0 => bv[20]
	//Error 1 => bv[28]
 
	if(error == RE_NORMAL || error == RE_DATA_ERROR)
		packet[20] = false;
	else
		packet[20] = true;
 
	if(error == RE_NORMAL || error == RE_TARGET_ABORT)
		packet[28] = false;
	else
		packet[28] = true;
 
	packet[14] = bridge;
	packet[15] = passPW;
	packet[7] = isoc;
 
	return packet;
}
 
 
sc_uint<5> getPacketSizeWithDatam1(const sc_bv<64> &pkt, const PacketCommand &cmd){
	sc_uint<5> pkt_size;
	sc_uint<2> packet_size_selector;
	packet_size_selector[1] = isDwordPacket(pkt,cmd);
	packet_size_selector[0] = hasDataAssociated(cmd);
 
	sc_uint<4> datalength_m1 = getDataLengthm1(pkt);
 
	switch(packet_size_selector){
		case 3:
			pkt_size = datalength_m1 + 1;
			break;
		case 2:
			pkt_size = 0;
			break;
		case 1:
			pkt_size = datalength_m1 + 2;
			break;
		default:
			pkt_size = 1;
	}
	return pkt_size;
}
 
sc_uint<5> getDwordPacketSizeWithDatam1(const sc_bv<64> &pkt, const PacketCommand &cmd){
	sc_uint<5> pkt_size;
	if(hasDataAssociated(cmd)){
		pkt_size = getDataLengthm1(pkt) + 1;
	}
	else{
		pkt_size = 0;
	}
	return pkt_size;
}
 
#endif
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.