////////////////////////////////////////////////////////////////////////////////
//  INTEL CONFIDENTIAL
//
//  Copyright 2003 Intel Corporation All Rights Reserved.
//
//  The source code contained or described herein and all documents related to
//  the source code ("Material") are owned by Intel Corporation or its
//  suppliers or licensors.
//
//  Title to the Material remains with Intel Corporation or its suppliers and
//  licensors. The Material contains trade secrets and proprietary and
//  confidential information of Intel or its suppliers and licensors.
//  The Material is protected by worldwide copyright and trade secret laws and
//  treaty provisions. No part of the Material may be used, copied, reproduced,
//  modified, published, uploaded, posted, transmitted, distributed,
//  or disclosed in any way without Intel's prior express written permission.
//
//  No license under any patent, copyright, trade secret or other intellectual
//  property right is granted to or conferred upon you by disclosure
//  or delivery of the Materials, either expressly, by implication, inducement,
//  estoppel or otherwise. Any license under such intellectual property rights
//  must be express and approved by Intel in writing.
//
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// =============================================================================
//
// = PRODUCT
//      Intel(r) IXA SDK for the IXP2400 Network Processor
//
// = FILENAME
//      support_routines.ind
//
// = DESCRIPTION
//
// =============================================================================
////////////////////////////////////////////////////////////////////////////////

printf("Executing file: support_routines.ind\n");
//
// This script creates C interpreter functions which will be used to perform
// tests on the transactor.
//
//
// All of the register and memory access functions once contained within this file
//  and listed below have been moved to the transactor.  They have the same format
//  as listed below:
//
// set_swr(me, reg, data), get_swr(me, reg), watch_swr(me, reg), check_swr(me, reg, expect), dump_swr(me), init_swr(me, data)
// set_srd(me, reg, data), get_srd(me, reg), watch_srd(me, reg), check_srd(me, reg, expect), dump_srd(me), init_srd(me, data)
// set_dwr(me, reg, data), get_dwr(me, reg), watch_dwr(me, reg), check_dwr(me, reg, expect), dump_dwr(me), init_dwr(me, data)
// set_drd(me, reg, data), get_drd(me, reg), watch_drd(me, reg), check_drd(me, reg, expect), dump_drd(me), init_drd(me, data)
// set_nei(me, reg, data), get_nei(me, reg), watch_nei(me, reg), check_nei(me, reg, expect), dump_nei(me), init_nei(me, data)
// set_gpa(me, reg, data), get_gpa(me, reg), watch_gpa(me, reg), check_gpa(me, reg, expect), dump_gpa(me), init_gpa(me, data)
// set_gpb(me, reg, data), get_gpb(me, reg), watch_gpb(me, reg), check_gpb(me, reg, expect), dump_gpb(me), init_gpb(me, data)
// set_sram(addr, data), get_sram(addr), watch_sram(addr), check_sram(addr, expect), dump_sram(addr_lo, addr_hi), init_sram(addr_lo, addr_hi, data)
// set_scratch(addr, data), get_scratch(addr), watch_scratch(addr), check_scratch(addr, expect), dump_scratch(addr_lo, addr_hi), init_scratch(addr_lo, addr_hi, data)
// set_dram(addr, data), get_dram(addr), watch_dram(addr),check_dram(addr, expect), dump_dram(addr_lo, addr_hi), init_dram(addr_lo, addr_hi, data)
// set_rbuf(addr, data), get_rbuf(addr), watch_rbuf(addr), check_rbuf(addr, expect), dump_rbuf(addr_lo, addr_hi), init_rbuf(addr_lo, addr_hi, data)
// set_tbuf(addr, data), get_tbuf(addr), watch_tbuf(addr), check_tbuf(addr, expect), dump_tbuf(addr_lo, addr_hi), init_tbuf(addr_lo, addr_hi, data)
// get_lmem(me, addr), set_lmem(me, addr, data), watch_lmem(me, addr), check_lmem(me, addr, expect), dump_lmem(me, addr_lo, addr_hi), init_lmem(me, addr_lo, addr_hi, data)
// dump_gprs(me), dump_gprd(me), watch_gpr(me), watch_gprs(me)
//
//  FUNCTION KEY:
//	set_			sets the register or memory
//	get_			returns the contents of the register or memory
//	watch_			sets up a watch on the register or memory
//	check_			compares the contents of the register or memory, and returns PASS or FAIL
//	init_			initializes the class of register in a ME to a given value
//	dump_			prints out the entire initialized contents of the register or memory
//
// Registers are access by (ME#, register#) where:
//	ME# is the absolute ME number, 0..15
//	register# is the absolute register within that ME, 0..127
//
// The sram, dram, and scratch memories are accessed via a BYTE address,
// but aligning to a LW (ie setting address<1:0> to 0).
// The rbuf, and tbuf are accessed via entry#, and byte address within that entry,
// setting and getting a LW at that byte offset.
// Local memory is accessed by ME#, and LW address (0..639 decimal for Castine, 0..512 for Sausalito)
//
// Also some general purpose routines
//	init_me();
//	assemble("uCode filename");
//	load_ucode(me#, "uCode filename");
//	wakeup_me(me#);		// enable and wakeup all 8 contexts, set the PC's to 1
//	exec_ucode(me#, "uCode filename");	// assemble ucode, load into ME, init the ME registers, then wakeup the ME
//	start_test(me#, "testName");		// exec_ucode(), plus @testName_post.ind to define a checking routine
//	run_test(me#, "testName");		// start_test, then simulate some time, then check by calling testName_post()
//	run_test_sub(me#, "testName", "testDir");	// run_test()but execute it in a subdirectory testDir
//	run_8_tests(tname0, tname1, ...tname7)	// run 8 tests in parallel, each in it's own ME
//	check_test( # expected errors);
//	get_pc(me#);		// prints out PC context, and valid info, returns PC
//	dump_pcs();		// prints out PC info for all MEs
//	get/set_msf_csr(addr);	// Byte address, not implemented yet
//	dump_gprs(me#);		// dumps gpa, gpb, swr, srd for the given ME
//	dump_gprd(me#);		// dumps gpa, gpb, dwr, drd for the given ME
//	watch_gpr(me#);		// sets watches on all the registers in a given ME
//	un_error();		// recover from a simulation error condition
//

if (state_type(sr_chip_name) == 0) string sr_chip_name = "chip";
if (state_type(sr_chip_name_dot) == 0) string sr_chip_name_dot = "chip.";

if (state_type(sr_cpu_type)==0) int sr_cpu_type = 2;
if (state_type(sr_cpu_castine)==0) int sr_cpu_castine = 2;
if (state_type(sr_cpu_sausalito)==0) int sr_cpu_sausalito = 4;
if (state_type(sr_me_max)==0) int sr_me_max;
if (state_type(sr_me_per_cluster)==0) int sr_me_per_cluster;

if (state_type(sr_ustore)==0) string sr_ustore;

if (state_type(sr_pc)==0) string sr_pc;
if (state_type(sr_pc_valid)==0) string sr_pc_valid;
if (state_type(sr_pc_ctx)==0) string sr_pc_ctx;

if (state_type(sr_me_ctx_enable)==0) string sr_me_ctx_enable;
if (state_type(sr_me_wakeup)==0) string sr_me_wakeup;
if (state_type(sr_me_pc)==0) string sr_me_pc;
if (state_type(sr_me_signal)==0) string sr_me_signal;

if (state_type(sr_saus_rbuf_ele) == 0) string sr_saus_rbuf_ele;
if (state_type(sr_saus_tbuf_ele) == 0) string sr_saus_tbuf_ele;

if (state_type(assembler_path)==0) string assembler_path;

if (state_type(me_ustore)==0) 			string me_ustore;
if (state_type(me_pc_ctx)==0) 			string me_pc_ctx;
if (state_type(me_ctx_enable)==0) 		string me_ctx_enable;
if (state_type(me_wakeup_events)==0) 	string me_wakeup_events;
if (state_type(me_cc_enable) == 0)		string me_cc_enable;
if (state_type(me_parity_enable) == 0)	string me_parity_enable;
if (state_type(ctx_per_me) == 0)		int ctx_per_me;

// putting the setting of variables within a code block {} stops the printout
// of the return value when executing
{

if (sr_cpu_type == sr_cpu_castine) {
	sr_me_max = 16;
	sr_me_per_cluster = 8;
} else {
	sr_me_max = 8;
	sr_me_per_cluster = 4;
}

me_ustore 		= 	sr_chip_name_dot+"tc%d.t%d.tu.ram_ustore(%d,%d,%d)";
me_pc_ctx		=	sr_chip_name_dot+"tc%d.t%d.thc.tx.TX_PC_CTX_%d_RT";
me_ctx_enable	=	sr_chip_name_dot+"tc%d.t%d.thc.tx.TX_CTX_%d_ENABLE_RT";
me_wakeup_events=	sr_chip_name_dot+"tc%d.t%d.thc.tx.TX_CTX_%d_WAKEUP_EVENTS_RT";
me_cc_enable	=	sr_chip_name_dot+"tc%d.t%d.thc.ti.csr_cc_enable_cu_rt";
me_parity_enable=	sr_chip_name_dot+"tc%d.t%d.thc.td.parity_enable_r";
ctx_per_me		=	8;

sr_ustore = sr_chip_name_dot+"tc%d.t%d.tu.ram_ustore";

sr_pc = sr_chip_name_dot+"tc%d.t%d.tp.p3_uaddr_r";
sr_pc_valid = sr_chip_name_dot+"tc%d.t%d.thc.ti.p3_valid_wt";
sr_pc_ctx = sr_chip_name_dot+"tc%d.t%d.thc.tk.p3_ctx_r";

sr_me_ctx_enable = sr_chip_name_dot+"tc%d.t%d.thc.tx.TX_CTX_%d_ENABLE_RT";
sr_me_wakeup = sr_chip_name_dot+"tc%d.t%d.thc.tx.TX_CTX_%d_WAKEUP_EVENTS_RT";
sr_me_pc = sr_chip_name_dot+"tc%d.t%d.thc.tx.TX_PC_CTX_%d_RT";
sr_me_signal = sr_chip_name_dot+"tc%d.t%d.thc.tx.TX_CTX_%d_SIG_EVENTS_RT";

sr_saus_rbuf_ele = sr_chip_name_dot+"msf_unit_i0.msf_unit.cpp_if.rbuf.dt_rbuf.mem_%d[%d]"; // mem bank [1-4] and 9 bit addr
sr_saus_tbuf_ele = sr_chip_name_dot+"msf_unit_i0.msf_unit.cpp_if.tbuf.dt_tbuf.mem_%d[%d]"; // mem bank [1-4] and 9 bit addr

// This gives the absolute path to the assembler area.
// NOTE: \'s get interpreted so double the \\'s, also there is a parsing problem ending with \\"
// so put some character at the end and then remove it.
assembler_path = "C:\\vmod_local_data_workstation\\MEv2_assembler\\Release_BL-1_beta-6\\ ";
assembler_path = assembler_path.left(assembler_path.length()-1);
}

// declare i for general index/counting use in tests/watches, etc...
if (state_type(i)==0) int i;

// declare some standard constants
if (state_type(PASS)==0) int PASS;
if (state_type(FAIL)==0) int FAIL;
if (state_type(TRUE)==0) int TRUE = 1;
if (state_type(FALSE)==0) int FALSE = 0;
if (state_type(XVALUE)==0) int XVALUE;

{
PASS = 1;
FAIL = 0;
TRUE = 1;
FALSE = 0;
XVALUE = 0xbad00bad;
}
//
// tc_num and me_num map from an absolute me number (0..15) to t_cluster and me within the t_cluster
//
int tc_num(int me) {
	if 	((0 <= me) && (me < sr_me_per_cluster)) return 0;
	else if ((sr_me_per_cluster <= me) && (me < sr_me_max)) return 1;
	else {
		printf("WARNING: routine tc_num takes an absolute ME# in the range 0..%d, given %d\n", sr_me_max-1, me);
		return 0xbad;
	}
}
int me_num(int me) {
	if 	((0<=me) && (me < sr_me_per_cluster)) return me;
	else if ((sr_me_per_cluster <= me) && (me < sr_me_max)) return (me - sr_me_per_cluster);
	else {
		printf("WARNING: routine me_num takes an absolute ME# in the range 0..%d, given %d\n", sr_me_max-1, me);
		return 0xbad;
	}
}

// RBUF SAUSALITO MSF
// 		addrs: 13 bit byte addrs.
// 		data : 4 bytes
void set_saus_rbuf(int addr, int data) {

	string sig_name;
	int eleAddr;
	int bankNum;

	if (addr >= 0x2000) addr -= 0x2000;

  	eleAddr = (addr>>4);
	bankNum = ((addr>>2) & 3) +1;

	bankNum = 5 - bankNum;
	if (bankNum == 4) {
		bankNum = 3;
	}
	else if (bankNum == 3) {
		bankNum = 4;
	}
	else if (bankNum == 2) {
		bankNum = 1;
	}
	else if (bankNum == 1) {
		bankNum = 2;
	}

	sig_name.format(sr_saus_rbuf_ele, bankNum, eleAddr);
	state(sig_name) = data;

	return;
}

int get_saus_rbuf(int addr) {

	string sig_name;
	int eleAddr;
	int bankNum;

	if (addr >= 0x2000) addr -= 0x2000;

  	eleAddr = (addr>>4);
	bankNum = ((addr>>2) & 3) +1;

	bankNum = 5 - bankNum;
	if (bankNum == 4) {
		bankNum = 3;
	}
	else if (bankNum == 3) {
		bankNum = 4;
	}
	else if (bankNum == 2) {
		bankNum = 1;
	}
	else if (bankNum == 1) {
		bankNum = 2;
	}

	sig_name.format(sr_saus_rbuf_ele, bankNum, eleAddr);

	if (valid_elements(state(sig_name))) {
		return state(sig_name);
	} else {
		return XVALUE;
	}
}

void set_saus_tbuf(int addr, int data) {

	string sig_name;
	int eleAddr;
	int bankNum;

	if (addr >= 0x2000) addr -= 0x2000;

  	eleAddr = (addr>>4);
	bankNum = ((addr>>2) & 3) +1;

	bankNum = 5 - bankNum;

	sig_name.format(sr_saus_tbuf_ele, bankNum, eleAddr);
	state(sig_name) = data;

	return;
}

int get_saus_tbuf(int addr) {

	string sig_name;
	int eleAddr;
	int bankNum;

	if (addr >= 0x2000) addr -= 0x2000;

  	eleAddr = (addr>>4);
	bankNum = ((addr>>2) & 3) +1;

	bankNum = 5 - bankNum;

	sig_name.format(sr_saus_tbuf_ele, bankNum, eleAddr);

	if (valid_elements(state(sig_name))) {
		return state(sig_name);
	} else {
		return XVALUE;
	}
}

void dump_saus_rbuf(int addr_lo, int addr_hi) {

	int i;

	for(i=(addr_hi&(~0x3)); i>=(addr_lo&(~0x3)); i-=4) {
		printf("RBUF[0x%04x] = 0x%08x\n", i, get_saus_rbuf(i));
	}
	return;
}

void dump_saus_tbuf(int addr_lo, int addr_hi) {

	int i;

	for(i=(addr_hi&(~0x3)); i>=(addr_lo&(~0x3)); i-=4) {
		printf("TBUF[0x%04x] = 0x%08x\n", i, get_saus_tbuf(i));
	}
	return;
}

//
//	init all the registers in a given me to a given data value
//
void init_me(int me, int data) {
	me_init_set_variables(me);
	return;
}
void wakeup_me(int me) {

	printf("wake up all contexts ...\n");
	wakeup_ctx_all(me);

	return;
}

void load_ucode(int me, string filename) {

	if (filename == "nop"){
		printf("No microcode for ME%d\n", me);
		return;
	}
	string command;
	string sig_name;
	sig_name.format(sr_ustore, tc_num(me), me_num(me) );
	command = "load_ixc " + sig_name + " " + filename;
//
// here's where we load ucode via the "load_ixc" command
//
	cmd(command);
	return;
}

int assemble(string filename) {
	string cmd;
	int assemble_status;

	string full_assem_path = project_dir();
	full_assem_path += "\\..\\..\\Mev2_Workbench\\uca.exe ";
	full_assem_path += " ";
	full_assem_path = full_assem_path.left(full_assem_path.length() - 1);
	printf("Assembler directory set to: %s\n", full_assem_path);

	string file_found = valid_file(full_assem_path);
	if (file_found.is_empty())
	{
		printf("unable to find assembler uca.exe in %s\n", full_assem_path);
		printf("Defaulting to uca.exe found in your PATH environment variable\n");
	
		cmd = "uca -CPU=2 -r " + filename + " > " + filename + "_assemble.log" ;
	}
	else {
		printf("Found assembler in path %s\n", full_assem_path);
		cmd = full_assem_path + "-CPU=2 -r " + filename + " > "+filename + "_assemble.log";
	}
	
	printf("%s\n", cmd);
	assemble_status = system(cmd);
	if (!assemble_status) {
	    printf("Assemble of uCode successful, check %s_assemble.log for warnings\n", filename);
	    return PASS;
	} else {
	    rec_error("Assemble of uCode returned errors, check %s_assemble.log for ERROR messages\n", filename);
	    return FAIL;
	}
}
void exec_ucode_ctx_mask(int me, string tname, int ctx_mask, int mode) {

	if (tname == "nop"){
		printf("No microcode for ME%d\n", me);
		return;
	}

	// assumes we have just complete init_castine, and that all support routines are defined
	if (mode == 0){
		assemble(tname);
	}
//	load_ucode(me, tname);


	// Initialize this ME as needed
	init_me(me, 0);

	//	follow the same execute sequence as ME testbench
	//printf("executing me_init(%d)\n",me);
	//me_init(me, me);

	printf("executing load_ucode()\n");
	load_ucode(me, tname);
	wakeup_ctx_mask(me, ctx_mask);

	sim.error_handle_mode = 30;

	return;
}

void exec_ucode(int me, string tname) {
	exec_ucode_ctx_mask(me, tname, 0xff, 0);
	return;
}

void start_test_ctx_mask(int me, string tname, int ctx_mask) {
	string command;

	exec_ucode_ctx_mask(me, tname, ctx_mask, 0);

	// conditionally define the post routine
	// if(state_type(immed_post)==0) cmd("@immed_post");
	command = "if(state_type(" +tname+ "_post) ==0) cmd(\"@" + tname + "_post\");" ;
//	printf("%s\n", command);
	cmd(command);

	return;
}

void start_test(int me, string tname) {
	start_test_ctx_mask(me, tname, 0xff);
	return;
}

void run_test_ctx_mask(int me, string tname, int ctx_mask) {
	string command;

	start_test_ctx_mask(me, tname, ctx_mask);

	cmd("go 500");

	// execute the post routine against the me we are using
	command.format("%s_post(%d);", tname, me);
	cmd(command);

	return;
}

void run_8_list_file(int me, string tname1, string tname2, string tname3, string tname4, string tname5, string tname6, string tname7, string tname8){
	
	exec_ucode_ctx_mask(me++, tname1, 0xff, 1);
	exec_ucode_ctx_mask(me++, tname2, 0xff, 1);
	exec_ucode_ctx_mask(me++, tname3, 0xff, 1);
	exec_ucode_ctx_mask(me++, tname4, 0xff, 1);
	exec_ucode_ctx_mask(me++, tname5, 0xff, 1);
	exec_ucode_ctx_mask(me++, tname6, 0xff, 1);
	exec_ucode_ctx_mask(me++, tname7, 0xff, 1);
	exec_ucode_ctx_mask(me++, tname8, 0xff, 1);

}

void run_16_list_file(string tname1, string tname2, string tname3, string tname4, string tname5, string tname6, string tname7, string tname8, string tname9, string tname10, string tname11, string tname12, string tname13, string tname14, string tname15, string tname16){
	run_8_list_file(0, tname1, tname2, tname3, tname4, tname5, tname6, tname7, tname8);
	run_8_list_file(8, tname9, tname10, tname11, tname12, tname13, tname14, tname15, tname16);
}

void run_test(int me, string tname) {
	run_test_ctx_mask(me, tname, 0xff);
	return;
}


// same as above, but move into the subdirectory, run the test, then move back up
void run_test_sub_ctx_mask(int me, int ctx_mask, string tname, string subdir) {
	string command;

	command = "cd "+ subdir;
	cmd(command);

	run_test_ctx_mask(me, tname, ctx_mask);
	
	command = "cd ..";
	cmd(command);
	return;
}
void run_test_sub(int me, string tname, string subdir) {
	run_test_sub_ctx_mask(me, 0xff, tname, subdir);
	return;
}

void run_16_tests(string tname0, string tname1, string tname2, string tname3, string tname4, string tname5, string tname6, string tname7, string tname8, string tname9, string tnamea, string tnameb, string tnamec, string tnamed, string tnamee, string tnamef ) {
	string command;
	int me;

	me = 0;
	start_test(me++, tname0);
	start_test(me++, tname1);
	start_test(me++, tname2);
	start_test(me++, tname3);
	start_test(me++, tname4);
	start_test(me++, tname5);
	start_test(me++, tname6);
	start_test(me++, tname7);
	start_test(me++, tname8);
	start_test(me++, tname9);
	start_test(me++, tnamea);
	start_test(me++, tnameb);
	start_test(me++, tnamec);
	start_test(me++, tnamed);
	start_test(me++, tnamee);
	start_test(me++, tnamef);

	cmd("goto 500");

	me = 0;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname0, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname1, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname2, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname3, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname4, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname5, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname6, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname7, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname8, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname9, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tnamea, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tnameb, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tnamec, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tnamed, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tnamee, me);
	cmd(command);
	me++;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tnamef, me);
	cmd(command);
	me++;

	return;
}
void run_16_tests_1_post(string tname0, string tname1, string tname2, string tname3, string tname4, string tname5, string tname6, string tname7, string tname8, string tname9, string tnamea, string tnameb, string tnamec, string tnamed, string tnamee, string tnamef ) {
	string command;
	int me;

	me = 0;
	start_test(me++, tname0);
	exec_ucode(me++, tname1);
	exec_ucode(me++, tname2);
	exec_ucode(me++, tname3);
	exec_ucode(me++, tname4);
	exec_ucode(me++, tname5);
	exec_ucode(me++, tname6);
	exec_ucode(me++, tname7);
	exec_ucode(me++, tname8);
	exec_ucode(me++, tname9);
	exec_ucode(me++, tnamea);
	exec_ucode(me++, tnameb);
	exec_ucode(me++, tnamec);
	exec_ucode(me++, tnamed);
	exec_ucode(me++, tnamee);
	exec_ucode(me++, tnamef);

	cmd("goto 500");

	me = 0;
	// execute the post routine against the me it was started in
	command.format("%s_post(%d);", tname0, me);
	cmd(command);

	return;
}
void run_16_tests_1_post_sub(string tname0, string tname1, string tname2, string tname3, string tname4, string tname5, string tname6, string tname7, string tname8, string tname9, string tnamea, string tnameb, string tnamec, string tnamed, string tnamee, string tnamef, string subdir) {
	string command;

	command = "cd "+ subdir;
	cmd(command);

	run_16_tests_1_post(tname0, tname1, tname2, tname3, tname4, tname5, tname6, tname7, tname8, tname9, tnamea, tnameb, tnamec, tnamed, tnamee, tnamef);
	
	command = "cd ..";
	cmd(command);
	return;
}
void run_8_tests(string tname0, string tname1, string tname2, string tname3, string tname4, string tname5, string tname6, string tname7) {
	string command;
	int me;

run_16_tests( tname0,  tname1,  tname2,  tname3,  tname4,  tname5,  tname6,  tname7, "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop");

	return;
}

//	return 1 if pass condition is met, otherwise return 0
int check_test(int num_error) {
	int pass = 0;
	if (sim.cumulative_error_count == num_error) {
		printf("SUCCESS");
		printf("SUCCESS\n");
		pass = 1;
	} else {
		printf("FAIL");
		printf("FAIL\n");
		pass = 0;
	}
	return pass;
}	

int get_pc(int me) {
	int pc;
	int valid;
	int ctx;

	string sig_name;
	sig_name.format(sr_pc, tc_num(me), me_num(me), reg);
	pc = state(sig_name);
	sig_name.format(sr_pc_valid, tc_num(me), me_num(me));
	valid = state(sig_name);
	sig_name.format(sr_pc_ctx, tc_num(me), me_num(me));
	ctx = state(sig_name);

	printf("P3 PC for ME %2d is: %4d=0x%4x, active Context is: 0x%x, valid is: %x\n", me, pc, pc, ctx, valid);

	return pc;
}

void dump_pcs() {
	int i;
	for(i=0; i< sr_me_max; i++) get_pc(i);
	return;
}

void un_error() {
	printf("clearing error conditions, beware the side effects of previous errors\n");
	sim.halt = 0;
	sim.error_count = 0;
	sim.error_handle_mode = 20;
	return;
}

void me_init_set_variables(int me){

	printf("init cc enable bit ...\n");
	set_CC_ENABLE_x(me, 1);

	printf("disable  parity check ...\n");
	set_PARITY_ENABLE_x(me, 0);

}

void wakeup_ctx(int me, int ctxs) {

	printf("wakeup ctx=0x%x, me=0x%x\n", ctxs, me);

	set_CTX_x_ENABLE(me, 1, ctxs);
	set_CTX_x_WAKEUP_EVENTS(me, 0x1, ctxs);
	set_PC_CTX_x(me, 0, ctxs);

}

void disable_ctx(int me, int ctxs) {

	set_CTX_x_ENABLE(me, 0, ctxs);
	return;
}

void wakeup_ctx_all(int me){
	int i;

	for(i = 0; i < ctx_per_me; i++){
		wakeup_ctx(me, i);
	}
}

void wakeup_ctx_mask(int me, int ctx_mask){
	int i;

	for(i = 0; i < ctx_per_me; i++){
		if ( (ctx_mask>>i)&1 ) {
			wakeup_ctx(me, i);
		}
	}
}

void set_CTX_x_ENABLE(int me, int value, int ctx){
	string ctx_enable_sig;

	ctx_enable_sig.format(me_ctx_enable, tc_num(me), me_num(me), ctx);

	state(ctx_enable_sig)	=	value;
}

void set_CTX_x_WAKEUP_EVENTS(int me, int value, int ctx){
	string ctx_wakeup_events_sig;

	ctx_wakeup_events_sig.format(me_wakeup_events, tc_num(me), me_num(me), ctx);

	state(ctx_wakeup_events_sig)	=	value;
}

void set_PC_CTX_x(int me, int value, int ctx){
	string pc_ctx_sig;

	pc_ctx_sig.format(me_pc_ctx, tc_num(me), me_num(me), ctx);

	state(pc_ctx_sig)	=	value;
}

void set_RESET_x(int me, int value){
	string reset_sig;

	reset_sig.format(me_reset, tc_num(me), me_num(me));
	state(reset_sig)	=	value;

}
	
void set_CC_ENABLE_x(int me, int value){
	string cc_enable_sig;

	cc_enable_sig.format(me_cc_enable, tc_num(me), me_num(me));
	state(cc_enable_sig)	=	value;
}

void set_PARITY_ENABLE_x(int me, int value){
	string parity_enable_sig;

	parity_enable_sig.format(me_parity_enable, tc_num(me), me_num(me));
	state(parity_enable_sig)	=	value;
}
