#include "ObjProNet/dfnode.h"

#include "ObjProUsr/cbuf.h"
#include "ObjProGen/outtok.h"
#include "ObjProGui/intfc.h"
#include "ObjProGui/remmen.h"
#include "ObjProGui/user.h"
#include "ObjProGui/dynmnu.h"
#include "ObjProArith/typout.h"
#include "ObjProGui/array.h"
#include "ObjProGui/interinit.h"
#include "ObjProGen/stattyp.h"
#include "ObjProGui/circbufc.h"
static EntityList * CircBufDesNodeList = 0 ;
static InteractiveEntity * IntEntCircBufDes ;
void CircBufDesNodesInit();
CircBufDes::CircBufDes (const char * Name, int32 Size, int32 TargetSize, 
		int16 TargetSizeGoal, int16 TargetControlGoal, 
		int32 MaxTargetSize, int32 MinTargetSize):
	BufferDescript(Name, CircBufferType, Size)
,
	Size_1(Size),
	TargetSize_2(TargetSize),
	TargetSizeGoal_3(TargetSizeGoal),
	TargetControlGoal_4(TargetControlGoal),
	MaxTargetSize_5(MaxTargetSize),
	MinTargetSize_6(MinTargetSize)
{
	if (!CircBufDesNodeList) CircBufDesNodesInit() ;
	CircBufDesNodeList->Append(MakeDeclaredEntity(this, IntEntCircBufDes)) ;
	InitArithType(TheArithType);
	NewMenuItem("CircBufDes",GetName());
} // end constructor

CircBufDes::~CircBufDes()
{
	TheMenuServer->DeleteMenuItem("CircBufDes",GetName());
	CircBufDesNodeList->Delete(GetName()) ;
} // end destructor

int CircBufDes::CheckSafeDelete()
{
	int Safe_Check_Return = BufferDescript::CheckSafeDelete();
	if (!Safe_Check_Return) return 0;
	return 1;
} // end check safe delete

CircBufDes * CircBufDesDef;

static UserEntity * MakeCircBufDes(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith = (ArithType::ArithCapabilities) TheArithType) ;
int CircBufDes::CppList(OutTokens& Out, CppListCmds Cmd)
{
	return IntEntCircBufDes->CppList(Out,Cmd,this);
}

void CircBufDes::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeCircBufDes(Out,EntityReqDescribeFull,*IntEntCircBufDes, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("Size");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("determines the buffer size for interactive execution.");
		Out.NextFillOut("The larger the");
		Out.NextFillOut("buffer is the more efficiently the nodes can execute");
		Out.NextFillOut("and the greater the delay that is possible in the");
		Out.NextFillOut("network. If the buffers are too small the network may");
		Out.NextFillOut("lock up without processing all input data.");
		Out.NextQuoteOut("TargetSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetTargetSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the desired size of the buffer used in code");
		Out.NextFillOut("prepared for execution on the target processor.");
		Out.NextFillOut("An analysis will determine if this size is adequate");
		Out.NextFillOut("and if it is larger than will be of benefit. The");
		Out.NextFillOut("size will be optimized based");
		Out.NextFillOut("on this target size as an approximate goal.");
		Out.NextQuoteOut("TargetSizeGoal");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetTargetSizeGoal()));
		Out.NextFillOut(")");
		Out.NextFillOut("determines whether the buffer will be made");
		Out.NextFillOut("larger or smaller then the selected size when the selected");
		Out.NextFillOut("size is not optimal. If");
		Out.NextQuoteOut("TargetSizeGoal");
		Out.NextFillOut("is 0 that space");
		Out.NextFillOut("will be minimized. If");
		Out.NextQuoteOut("TargetSizeGoal");
		Out.NextFillOut("is 1 then execution");
		Out.NextFillOut("overhead will be minimized.");
		Out.NextQuoteOut("TargetControlGoal");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetTargetControlGoal()));
		Out.NextFillOut(")");
		Out.NextFillOut("determines how execution is controlled.");
		Out.NextFillOut("If it is 0 then the buffer size is fixed and the amount");
		Out.NextFillOut("of data available in the buffer is computed before each");
		Out.NextFillOut("execution step. If");
		Out.NextQuoteOut("TargetControlGoal");
		Out.NextFillOut("is 1 then each");
		Out.NextFillOut("node is executed according to a fixed predetermined");
		Out.NextFillOut("schedule and the buffer size is optimized to this schedule.");
		Out.NextFillOut("Nodes with feedback or that require excessively large");
		Out.NextFillOut("buffers are defaulted to execute without fixed");
		Out.NextFillOut("sequences. Fixed sequence execution provides more efficient");
		Out.NextFillOut("execution at the expense of larger buffer requirements.");
		Out.NextQuoteOut("MaxTargetSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetMaxTargetSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the maximum size allowed for any");
		Out.NextFillOut("single buffer. It can force the use of a non fixed sequence");
		Out.NextFillOut("scheduler or even result in an error message if the network");
		Out.NextFillOut("cannot run without deadlock with this size buffer.");
		Out.NextQuoteOut("MinTargetSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetMinTargetSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the minimum size allowed for any");
		Out.NextFillOut("single buffer. Setting this to a larger value can improve");
		Out.NextFillOut("execution efficiency at the cost of more memory.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntCircBufDes->GetOneParameter("Size")->
			IntP->CurrentValue = Size_1;
		IntEntCircBufDes->GetOneParameter("TargetSize")->
			IntP->CurrentValue = TargetSize_2;
		IntEntCircBufDes->GetOneParameter("TargetSizeGoal")->
			IntP->CurrentValue = TargetSizeGoal_3;
		IntEntCircBufDes->GetOneParameter("TargetControlGoal")->
			IntP->CurrentValue = TargetControlGoal_4;
		IntEntCircBufDes->GetOneParameter("MaxTargetSize")->
			IntP->CurrentValue = MaxTargetSize_5;
		IntEntCircBufDes->GetOneParameter("MinTargetSize")->
			IntP->CurrentValue = MinTargetSize_6;
		break;
	}
} // end  list entity switch

static ValueType * SetTargetSize(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				int32 TargetSize =
			Param->GetIntParameterValue("TargetSize");
		((CircBufDes *) This)->SetTargetSize(TargetSize);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * SetTargetSizeGoal(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				int16 TargetSizeGoal =
			Param->GetIntParameterValue("TargetSizeGoal");
		((CircBufDes *) This)->SetTargetSizeGoal(TargetSizeGoal);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * SetTargetControlGoal(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				int16 TargetControlGoal =
			Param->GetIntParameterValue("TargetControlGoal");
		((CircBufDes *) This)->SetTargetControlGoal(TargetControlGoal);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * SetMaxTargetSize(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				int32 MaxTargetSize =
			Param->GetIntParameterValue("MaxTargetSize");
		((CircBufDes *) This)->SetMaxTargetSize(MaxTargetSize);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * SetMinTargetSize(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				int32 MinTargetSize =
			Param->GetIntParameterValue("MinTargetSize");
		((CircBufDes *) This)->SetMinTargetSize(MinTargetSize);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * AssignToEdit(OutTokens& Out,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
case EntityReqDescribeFull:
		Out.NextQuoteOut("AssignToEdit");
		Out.NextFillOut("makes this the descriptor for the network currently");
		Out.NextFillOut("being edited. If a previous descriptor was assigned it will be");
		Out.NextFillOut("overwritten.");
		Out.NewLine();

	break ;
case EntityReqCall:
		{
		((CircBufDes * )This)->AssignToEdit(
		);		}
	}
	return 0;
}

void CircBufDesNodesInit()
{
	if (CircBufDesNodeList)  return ;

	static StringParam CircBufDesNameParam =
		{"CircBufDes", MakeNewEntityName, 0, LegalEntityName};
	static IntParam CircBufDesSizeParam = {
		 2048, 0,  0,  1, 0, 2.14748e+09};
	static IntParam CircBufDesTargetSizeParam = {
		 512, 0,  0,  0, 0, 2.14748e+09};
	static IntParam CircBufDesTargetSizeGoalParam = {
		 0, 0,  0,  0,  0,  1};
	static IntParam CircBufDesTargetControlGoalParam = {
		 1, 0,  0,  0,  0,  1};
	static IntParam CircBufDesMaxTargetSizeParam = {
		 4096, 0,  0,  1, 0, 2.14748e+09};
	static IntParam CircBufDesMinTargetSizeParam = {
		 32, 0,  0,  1, 0, 2.14748e+09};

	static OneParameter CircBufDesParArray[] = {
		{"Name", 0, "node name", 0, 0, &CircBufDesNameParam},
		{"Size", 0, 
			"buffer size in words",
			&CircBufDesSizeParam},
		{"TargetSize", 0, 
			"desired buffer size in target code",
			&CircBufDesTargetSizeParam, 0, 0, 0, 0, 1},
		{"TargetSizeGoal", 0, 
			"target buffer size goal (0 minimize size, 1 maximize size)",
			&CircBufDesTargetSizeGoalParam, 0, 0, 0, 0, 1},
		{"TargetControlGoal", 0, 
			"control goal (0 fixed buffer size, 1 fixed sequence)",
			&CircBufDesTargetControlGoalParam, 0, 0, 0, 0, 1},
		{"MaxTargetSize", 0, 
			"maximum size for any single buffer",
			&CircBufDesMaxTargetSizeParam, 0, 0, 0, 0, 1},
		{"MinTargetSize", 0, 
			"minimum size for any single buffer",
			&CircBufDesMinTargetSizeParam, 0, 0, 0, 0, 1},
		{0}
	};

	static OneParameter SetTargetSizeCircBufDesList[] = {
		{"TargetSize", 0, "desired buffer size in target code",
			 &CircBufDesTargetSizeParam, 0, 0, 0, 0, 1},
			{0}
	};
	UserParameters * SetTargetSizeMemberParam = new UserParameters
		(SetTargetSizeCircBufDesList);

	Procedure * SetMemberProcTargetSize = new Procedure("SetTargetSize", SetTargetSize,
		 SetTargetSizeMemberParam, "void");
	static OneParameter SetTargetSizeGoalCircBufDesList[] = {
		{"TargetSizeGoal", 0, "target buffer size goal (0 minimize size, 1 maximize size)",
			 &CircBufDesTargetSizeGoalParam, 0, 0, 0, 0, 1},
			{0}
	};
	UserParameters * SetTargetSizeGoalMemberParam = new UserParameters
		(SetTargetSizeGoalCircBufDesList);

	Procedure * SetMemberProcTargetSizeGoal = new Procedure("SetTargetSizeGoal", SetTargetSizeGoal,
		 SetTargetSizeGoalMemberParam, "void");
	static OneParameter SetTargetControlGoalCircBufDesList[] = {
		{"TargetControlGoal", 0, "control goal (0 fixed buffer size, 1 fixed sequence)",
			 &CircBufDesTargetControlGoalParam, 0, 0, 0, 0, 1},
			{0}
	};
	UserParameters * SetTargetControlGoalMemberParam = new UserParameters
		(SetTargetControlGoalCircBufDesList);

	Procedure * SetMemberProcTargetControlGoal = new Procedure("SetTargetControlGoal", SetTargetControlGoal,
		 SetTargetControlGoalMemberParam, "void");
	static OneParameter SetMaxTargetSizeCircBufDesList[] = {
		{"MaxTargetSize", 0, "maximum size for any single buffer",
			 &CircBufDesMaxTargetSizeParam, 0, 0, 0, 0, 1},
			{0}
	};
	UserParameters * SetMaxTargetSizeMemberParam = new UserParameters
		(SetMaxTargetSizeCircBufDesList);

	Procedure * SetMemberProcMaxTargetSize = new Procedure("SetMaxTargetSize", SetMaxTargetSize,
		 SetMaxTargetSizeMemberParam, "void");
	static OneParameter SetMinTargetSizeCircBufDesList[] = {
		{"MinTargetSize", 0, "minimum size for any single buffer",
			 &CircBufDesMinTargetSizeParam, 0, 0, 0, 0, 1},
			{0}
	};
	UserParameters * SetMinTargetSizeMemberParam = new UserParameters
		(SetMinTargetSizeCircBufDesList);

	Procedure * SetMemberProcMinTargetSize = new Procedure("SetMinTargetSize", SetMinTargetSize,
		 SetMinTargetSizeMemberParam, "void");
	static OneParameter AssignToEditCircBufDesList[] = {
		{0}
	};
	UserParameters * AssignToEditMemberParam = new UserParameters
		(AssignToEditCircBufDesList);

	Procedure * MemberProcAssignToEdit = new Procedure("AssignToEdit", AssignToEdit,
		AssignToEditMemberParam, "void", 0, "assign this descriptor to the network currently being edited");
static ValueType * CircBufDesMembers[7] ;
	int ii = 0 ;
	CircBufDesMembers[ii++] = new ValueType(DecProcedure, SetMemberProcTargetSize) ;
	CircBufDesMembers[ii++] = new ValueType(DecProcedure, SetMemberProcTargetSizeGoal) ;
	CircBufDesMembers[ii++] = new ValueType(DecProcedure, SetMemberProcTargetControlGoal) ;
	CircBufDesMembers[ii++] = new ValueType(DecProcedure, SetMemberProcMaxTargetSize) ;
	CircBufDesMembers[ii++] = new ValueType(DecProcedure, SetMemberProcMinTargetSize) ;
	CircBufDesMembers[ii++] = new ValueType(DecProcedure, MemberProcAssignToEdit) ;
	CircBufDesMembers[ii++] = 0 ;
	CircBufDesNodeList = new EntityList;
	IntEntCircBufDes = new InteractiveEntity("CircBufDes", CircBufDesNodeList,
		MakeCircBufDes, InteractiveBuffer, "cbuf.h",
		CircBufDesMembers, "BufferDescript");
	IntEntCircBufDes->SetParameters(new UserParameters(CircBufDesParArray));
	TheNodes->Append(IntEntCircBufDes);
} // end initalization

static UserEntity * MakeCircBufDes(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith)
{
	switch(Request) {
case EntityReqDescribe:

case EntityReqDescribeFull:
		Out.NextFillOut("After a network has been completely described, it is necessary");
		Out.NextFillOut("to provide physical buffers for all the connection paths between");
		Out.NextFillOut("nodes. This is done by first defining a");
		Out.NextFillOut("`BufferDescriptor'");
		Out.NextFillOutConcat(".");
		Out.NextFillOut("And then using this descriptor in the network member function");
		Out.NextFillOut("`AssignBuffers'");
		Out.NextFillOutConcat(". (If you do not do this manually it will");
		Out.NextFillOut("be done automatically before executing a network using");
		Out.NextFillOut("the default buffer descriptor.)");
		Out.NextQuoteOut("CircBufDes");
		Out.NextFillOut("describes circular buffers. There");
		Out.NextFillOut("is a single parameter for this descriptor. It specifies the");
		Out.NextFillOut("size (");
		Out.NextFillOutConcat("Size");
		Out.NextFillOutConcat(") of the buffer. Other parameters describe");
		Out.NextFillOut("the constraints on buffer size for generating target processor");
		Out.NextFillOut("code.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		int32 Size =
			IntNode.GetIntParameterValue("Size");
		int32 TargetSize =
			IntNode.GetIntParameterValue("TargetSize");
		int16 TargetSizeGoal =
			IntNode.GetIntParameterValue("TargetSizeGoal");
		int16 TargetControlGoal =
			IntNode.GetIntParameterValue("TargetControlGoal");
		int32 MaxTargetSize =
			IntNode.GetIntParameterValue("MaxTargetSize");
		int32 MinTargetSize =
			IntNode.GetIntParameterValue("MinTargetSize");
		return new CircBufDes(Name, Size, TargetSize, TargetSizeGoal, TargetControlGoal, MaxTargetSize, MinTargetSize);

	}
	}
	return 0;
}

static InitObj LocalInit(CircBufDesNodesInit, "CircBufDes", "BufferDescript");

