/* =============================================================================================

Backannotations in SI2DR Applications

Reading -- Bringing Backannotation data from EdaXML to the Vendor Environment
           Using the SI2DR interface

      A large part of the job of reading the EdaXML, and storing it
      memory, is done by the si2dr interface. A single call will read
      in the EdaXML file, and an si2dr database will be built in
      memory.

         si2drErrorT err;

         si2drReadDatabase("edaxml-file", SI2DR_FALSE, &err);

      From here, there are two paths you might follow in finding and
      printing the backannotations present in the EdaXML file.

      The first is to traverse the OccProps in the OccPropSet
      associated with the Backannotations. This is the "easiest", and
      the OccProps and OccPropSets were set up just for this purpose.

      The second is to traverse the Occurrence tree, and, from each
      occurrence, get its associated OccProp, and its properties.


=============================================================================================
Method 1 -- OccPropSets

      Designed for simple backannotation extraction, each
      backannotation property is connected to an "occProp" of a type
      corresponding to the Occurrence with which the property is
      associated.
      
      The OccPropSets are created and attached to the root cell in the
      hierarchy, along with DesignConfigs.

      The following code assumes that the value "cell" is a valid OID
      and belongs to the root cell. */

#include <stdio.h>
#include "si2dr.h"


extern int cheat_glob_dw; /* this was added for debug/testing purposes. */

/* prototypes */
void convert_occ_props_to_vendor1(si2drCellIdT cell);
void output_viewoccprop(si2drOccPropIdT     oprop);
void output_portoccprop(si2drOccPropIdT     oprop);
void output_netoccprop(si2drOccPropIdT     oprop);
void output_prop(char *path, si2drPropIdT prop);



void convert_occ_props_to_vendor1(si2drCellIdT cell)
{
	si2drErrorT  err;

	si2drOccPropSetsIdT opss;
    si2drOccPropSetIdT  ops;
    si2drOccPropsIdT    oprops;
    si2drOccPropIdT     oprop;
	si2drDesignConfigsIdT descfgs;
	si2drDesignConfigIdT  descfg;
	
	int count;
	
    /* this code will combine all the occPropSets into a single
      backannotation output; however, in real life, they should
      probably go into seperate files, one file per occPropSet. */


	descfgs = si2drCellGetDesignConfigs(cell,&err);
	for(descfg = si2drIterNextDesignConfig(descfgs,&err);
        si2drObjectIsNull(descfg,&err) == SI2DR_FALSE;
        descfg = si2drIterNextDesignConfig(descfgs,&err))
	{
		count = 0;
		opss = si2drDesignConfigGetOccPropSets(descfg,&err);
		for(ops = si2drIterNextOccPropSet(opss,&err);
			si2drObjectIsNull(ops,&err) == SI2DR_FALSE;
			ops = si2drIterNextOccPropSet(opss,&err))
		{
			oprops = si2drOccPropSetGetViewOccProps(ops,&err);
			while( !si2drObjectIsNull(oprop=si2drIterNextOccProp(oprops,&err),&err) )
			{
				output_viewoccprop(oprop);
			}
			si2drIterQuit(oprops,&err);
			
			oprops = si2drOccPropSetGetPortOccProps(ops,&err);
			while( !si2drObjectIsNull(oprop=si2drIterNextOccProp(oprops,&err),&err) )
			{
				output_portoccprop(oprop);
			}
			si2drIterQuit(oprops,&err);
			
			oprops = si2drOccPropSetGetNetOccProps(ops,&err);
			while( !si2drObjectIsNull(oprop=si2drIterNextOccProp(oprops,&err),&err) )
			{
				output_netoccprop(oprop);
			}
			si2drIterQuit(oprops,&err);
			count++;
		}
		si2drIterQuit(opss,&err);
		printf("There were %d OccPropSets in descfg %s\n", count, si2drNamedObjectGetName(descfg,&err));
	}
	si2drIterQuit(descfgs,&err);
}

void output_viewoccprop(si2drOccPropIdT     oprop)
{
	/* each occurrence has exactly 0 or 1 occprops attached to it. All
      properties attached to the occprop are backannotated data. */
	si2drPropIdT prop;
	si2drPropsIdT props;
	si2drStringT  designator= 0;
	char pathstrbuf[5000];
	si2drErrorT     err;

	/* get path to occ prop in string form */

	si2drStringT pathstr = si2drOccPropGetConcatenatedPathname(oprop,&err);
	strcpy(pathstrbuf,pathstr);

	designator = si2drViewOccPropGetDesignator(oprop, &err);
	if( designator && designator[0] )
		printf("BACKANN: %s: DESIGNATOR=%s\n", pathstrbuf, designator);

	props = si2drObjectGetProps(oprop,&err);
	while( !si2drObjectIsNull(prop=si2drIterNextProp(props,&err),&err) )
	{
		output_prop(pathstrbuf, prop);
	}
	cheat_glob_dw = 1;
	si2drIterQuit(props,&err);
	cheat_glob_dw = 0;
}

void output_portoccprop(si2drOccPropIdT     oprop)
{
	/* each occurrence has exactly 0 or 1 occprops attached to it. All
      properties attached to the occprop are backannotated data. */
	si2drPropIdT prop;
	si2drPropsIdT props;
	char pathstrbuf[5000];
	si2drErrorT     err;
	si2drStringT	designator;

	/* get path to occ prop in string form */

	si2drStringT pathstr = si2drOccPropGetConcatenatedPathname(oprop,&err);
	strcpy(pathstrbuf,pathstr);

	designator = si2drPortOccPropGetDesignator(oprop, &err);
	if( designator && designator[0] )
		printf("BACKANN: %s: DESIGNATOR=%s\n", pathstrbuf, designator);

	/* the other attributes (if your system can do something with
      them) could be called here: si2drPortOccPropGetDcFanInLoad(),
      etc */

	props = si2drObjectGetProps(oprop,&err);
	while( !si2drObjectIsNull(prop=si2drIterNextProp(props,&err),&err) )
	{
		output_prop(pathstrbuf, prop);
	}
	cheat_glob_dw = 1;
	si2drIterQuit(props,&err);
	cheat_glob_dw = 0;
}

void output_netoccprop(si2drOccPropIdT     oprop)
{
	/* each occurrence has exactly 0 or 1 occprops attached to it. All
      properties attached to the occprop are backannotated data. */
	si2drPropIdT prop;
	si2drPropsIdT props;
	char pathstrbuf[5000];
	si2drErrorT     err;

	/* get path to occ prop in string form */

	si2drStringT pathstr = si2drOccPropGetConcatenatedPathname(oprop,&err);
	strcpy(pathstrbuf,pathstr);

	props = si2drObjectGetProps(oprop,&err);
	while( !si2drObjectIsNull(prop=si2drIterNextProp(props,&err),&err) )
	{
		output_prop(pathstrbuf, prop);
	}
	cheat_glob_dw = 1;
	si2drIterQuit(props,&err);
	cheat_glob_dw = 0;
}

void output_prop(char *path, si2drPropIdT prop)
{
	char pnamebuf[5000];
	char pathstrbuf[5000];
	si2drValueTypeT type;
	si2drMiNoMaxT mnmval;
	si2drPointT   ptval;
	si2drErrorT     err;

	strcpy(pnamebuf,si2drNamedObjectGetName(prop,&err));
	type = si2drPropGetValueType(prop,&err);

	switch( type )
	{
	case SI2DR_INT32:
		printf("BACKANN: %s: %s=%d\n", path, pnamebuf,
			      si2drPropGetInt32Value(prop,&err));
		break;
		case SI2DR_FLOAT32:
		printf("BACKANN: %s: %s=%g\n", path, pnamebuf,
			      si2drPropGetFloat32Value(prop,&err));
		break;
	case SI2DR_STRING:
		printf("BACKANN: %s: %s=%s\n", path, pnamebuf,
			      si2drPropGetStringValue(prop,&err));
		break;
	case SI2DR_BOOLEAN:
		printf("BACKANN: %s: %s=%s\n", path, pnamebuf,
			      (si2drPropGetBooleanValue(prop,&err)? "TRUE" : "FALSE"));
		break;
	case SI2DR_MINOMAX:
		mnmval = si2drPropGetMiNoMaxValue(prop,&err);			
		printf("BACKANN: %s: %s=MINOMAX VAL\n", path,
                   pnamebuf); /* I decided not to cloud this example
                                 code with the complexity of minomax value printing.... */
		break;
	case SI2DR_POINT:
		ptval = si2drPropGetPointValue(prop,&err);
		printf("BACKANN: %s: %s=(%d,%d)\n", path, pnamebuf,
			      ptval.x, ptval.y);
		break;
	default:
		printf("BACKANN: %s: %s=%d\n", path, pnamebuf,
			      si2drPropGetInt32Value(prop,&err));
		break;
	
	}		
}

/* =============================================================================================

Method 2: Traversing the Occurrence Tree

      In this method, the occurrence tree is traversed. A function,
      OccGetDerivedProps(), is used on each occurrence to iterate over
      the occprop props.

      Recursion on the ViewOcc's is the easiest way to traverse the
      tree...

	  In the following code, remember that an instOcc is also a
      ViewOcc.

	  And, remember that a TopOcc is also a viewOcc.
    */

/* prototypes */
void convert_occ_props_to_vendor2(si2drCellIdT cell);
void traverse_view_occs(si2drViewOccIdT viewOcc);




void convert_occ_props_to_vendor2(si2drCellIdT cell)
{
	si2drErrorT  err;
	si2drDesignConfigsIdT dconfs;
	si2drDesignConfigIdT  dconf;
	si2drTopOccIdT topOcc;

	dconfs = si2drCellGetDesignConfigs(cell,&err);
	while( !si2drObjectIsNull(dconf=si2drIterNextDesignConfig(dconfs,&err),&err) )
	{
		/* this code will combine all the designconfigs together into
	      a single output. In real life, however, the backannotations
	      from each designconfig should most likely be kept separate from
    	  the others... */
		printf("About to get the topOcc\n");
		
		topOcc = si2drDesignConfigGetTopOcc(dconf,&err);
		if( !si2drObjectIsNull( topOcc, &err) )
		{
			printf( "about to traverse the topOcc\n");
			
			traverse_view_occs(topOcc);
		}
	}
	si2drIterQuit(dconfs,&err);
}
	


void traverse_view_occs(si2drViewOccIdT viewOcc)
{
	si2drInstOccsIdT instOccs;
	si2drInstOccIdT instOcc;
	si2drNetOccsIdT netOccs;
	si2drNetOccIdT  netOcc;
	si2drOccPropIdT  occProp;
	si2drPortOccsIdT portOccs;
	si2drPortOccIdT portOcc;
	si2drPropsIdT   props;
	si2drPropIdT	prop;
	si2drErrorT     err;
	si2drStringT	designator;
	char pathstrbuf[5000];
	si2drOccMemPathT   occPath;

	printf("looking at viewoccs...\n");
	instOccs = si2drViewOccGetInstOccs(viewOcc,&err);
	while( !si2drObjectIsNull(instOcc=si2drIterNextInstOcc(instOccs,&err),&err) )
	{
		/* get path to occ prop in string form */

		si2drStringT pathstr = si2drOccGetConcatenatedPathname(viewOcc,&err);
		strcpy(pathstrbuf,pathstr);
		printf("looking at viewocc\n");

		traverse_view_occs(instOcc); /* RECURSIVE CALL */

		/* putting the recursion before the print => results in bottom-up
           listings; putting it after will give top-down
           listings... */


	}
	si2drIterQuit(instOccs,&err);

	/* Another method-- get path to occ prop in struct form */
		
	occPath = si2drOccGetPath(viewOcc,&err);

	occProp = si2drOccGetOccProp(viewOcc,&err);
	designator = si2drViewOccPropGetDesignator(occProp, &err);
	if( designator && designator[0] )
		printf("BACKANN: %s: DESIGNATOR=%s\n", pathstrbuf, designator);
	
	
	props = si2drOccGetDerivedProps(viewOcc,SI2DR_MERGE_OCC_PROPS,&err);
	while( !si2drObjectIsNull(prop=si2drIterNextDerivedProp(props,&err),&err) )
	{
		output_prop(pathstrbuf, prop);
	}
	si2drIterQuit(props,&err);
	
	/* a viewOcc also contains NetOccs and PortOccs. Traverse and
	   print these now  */
	
	netOccs = si2drViewOccGetNetOccs(viewOcc,SI2DR_ITER_SCALARS, &err);
	while( !si2drObjectIsNull(netOcc=si2drIterNextNetOcc(netOccs,&err),&err) )
	{
		si2drStringT pathstr = si2drOccGetConcatenatedPathname(netOcc,&err);
		strcpy(pathstrbuf,pathstr);
		printf("looking at netocc\n");
		
		/* Another method-- get path to occ prop in struct form */
		
		occPath = si2drOccGetPath(netOcc,&err);
		
		props = si2drOccGetDerivedProps(netOcc,SI2DR_MERGE_OCC_PROPS,&err);
		while( !si2drObjectIsNull(prop=si2drIterNextDerivedProp(props,&err),&err) )
		{
			output_prop(pathstrbuf, prop);
		}
		si2drIterQuit(props,&err);
	}
	si2drIterQuit(netOccs,&err);
	
	portOccs = si2drViewOccGetPortOccs(viewOcc,SI2DR_ITER_SCALARS, &err);
	while( !si2drObjectIsNull(portOcc=si2drIterNextPortOcc(portOccs,&err),&err) )
	{
		si2drStringT pathstr = si2drOccGetConcatenatedPathname(portOcc,&err);
		strcpy(pathstrbuf,pathstr);
		printf("looking at portocc %s\n", pathstrbuf);
		
		/* Another method-- get path to occ prop in struct form */
		
		occPath = si2drOccGetPath(portOcc,&err);
		
		occProp = si2drOccGetOccProp(portOcc,&err);
		designator = si2drPortOccPropGetDesignator(occProp, &err);
		if( designator && designator[0] )
			printf("BACKANN: %s: DESIGNATOR=%s\n", pathstrbuf, designator);
		
		/* the other portOccProp attributes could be handled here
		   also, like DcMaxFanIn, etc. */
		
		props = si2drOccGetDerivedProps(portOcc,SI2DR_MERGE_OCC_PROPS,&err);
		while( !si2drObjectIsNull(prop=si2drIterNextDerivedProp(props,&err),&err) )
		{
			output_prop(pathstrbuf, prop);
		}
		si2drIterQuit(props,&err);
	}
	si2drIterQuit(portOccs,&err);
	
}

/* =============================================================================================
=============================================================================================

Writing -- Converting the Vendor Backannotation Format to EdaXML

      The application writer has to traverse his internal database,
      and build a representation of the design , as well as an
      occurrence tree for the design. This process usually involves
      highly vendor-specific interfaces.

      Once the si2dr representation has been built, the design can be
      written to an EdaXML file with a single call.

      Without mentioning any vendor-specific functions, we
      can still outline the si2dr functions that would be utilized to
      do this.

      Something to note about this process: If the vendor database
      only has one view (schematic/netlist) per cell, then generating
      the occurrence tree is almost trivial. If there is a possibility
      of more than one view, then a view selection process must be
      utilized to choose which view to traverse (eg. gate vs
      transistor, etc). Also, vendor specific functions to truncate
      the occurrence tree (forcing hierarchical elements to be "leaf"
      elements, and not traversing any deeper) might be possible.

   */


/* definitions */

typedef enum backann_objtype 
{ 
	BA_OBJ_ANY, 
	BA_OBJ_VIEW, 
	BA_OBJ_NET,
	BA_OBJ_PORT 
} backann_objtype;

typedef enum backann_type 
{ 
	BA_TYP_PROP, 
	BA_TYP_DESIGNATOR,
	BA_TYP_DCFANINLOAD, 
	BA_TYP_DCFANOUTLOAD, 
	BA_TYP_DCMAXFANIN,
	BA_TYP_DCMAXFANOUT, 
	BA_TYP_ACLOAD, 
	BA_TYP_PORTDELAY,
	BA_TYP_PORTLOADDELAY 
} backann_type;

struct backann
{
	backann_objtype type;
	backann_type    btype;
	si2drOccMemPathT path;  /* the parsed array of instance path elements to the occ to attach this backann to */
	si2drStringT    name;  /* serves as name of prop or attribute */
	si2drValueTypeT prop_type; /* used only for props */
	union
	{
		si2drInt32T  val_int;
		si2drStringT val_str;
		si2drFloat32T val_float;
		si2drBooleanT val_bool;
		si2drMiNoMaxT val_minomax;
		si2drPointT	  val_point;
	} prop_val;
	si2drStringT designator;      /* used only for designators */
	si2drDerivationT derivation;  /* used only for portDelay attrs */
	si2drMiNoMaxT timedelay;
	si2drMiNoMaxT capval_range;   /* used for AC&PortDelay */
	si2drPortDelaySpecT *spec;
	si2drFloat32T num;            /* used for the DCFAN stuff */
};


/* prototypes */
void create_si2dr_designconfig(si2drCellIdT rootcell,
                               si2drNetlistViewIdT root_view, 
                               char *descfg_name );
void build_tree(si2drViewOccIdT viewocc, 
                si2drNetlistViewIdT nv,
                si2drInstIdT nvs_inst);

int vendor_get_backannotation(struct backann **backann_array);
si2drOccIdT find_obj_by_path(si2drTopOccIdT topOcc, si2drOccMemPathT path);
void add_backannotation(si2drTopOccIdT topOcc, si2drOccPropSetIdT occPropSet);



void create_si2dr_designconfig(si2drCellIdT rootcell,
                               si2drNetlistViewIdT root_view, 
                               char *descfg_name )
{

	si2drOccPropSetIdT    ops;
	si2drDesignConfigIdT  descfg;
	si2drErrorT           err;
	si2drTopOccIdT        topocc;


    /* this function assumes that the hierarchy has already been built
      in the si2dr database. */

	descfg = si2drCellCreateDesignConfig(rootcell, descfg_name, root_view, &err);

	ops = si2drCellCreateOccPropSet(rootcell, descfg_name, &err);

	topocc = si2drDesignConfigCreateTopOcc(descfg, &err);

	/* the topocc represents the root view. It is also a ViewOcc. */

	/* one method for generating the data:
	   copy the hierarchy from the netlist views
	   then, place the backannotation into the occurrence tree */
	
	/* for each node in the occurrence tree, you need the
      corresponding view in the cell. If there's only one view, then
      it's simple to pick, otherwise, the vendor toolset hopefully has
      some way to get the proper view. */

	
	build_tree( topocc, root_view, 	 si2drPIGetNullId(&err));	
	add_backannotation(topocc, ops);	
}

extern si2drNetlistViewIdT vendor_inst_get_view(si2drInstIdT inst);  /* this function is
            provided by the vendor application writer; it looks up the
            describer cell, and picks one of the views for it. It may need
            more information, like the path; this can be included */


/* In the following func, the viewOcc has a corresponding
      netlistlistview, nv. The inst is the inst that corresponds to
      this viewocc's instocc */

void build_tree(si2drViewOccIdT viewocc, 
                si2drNetlistViewIdT nv,
                si2drInstIdT nvs_inst)
{
	si2drInstIdT		  inst;
	si2drInstsIdT		  insts;
	si2drNetIdT		  	  net;
	si2drNetsIdT		  nets;
	si2drPortIdT		  	  port;
	si2drPortsIdT		  ports;
	si2drErrorT           err;
	si2drViewOccIdT   instocc;

	insts = si2drNetlistViewGetInsts(nv,&err);
	while( !si2drObjectIsNull(inst=si2drIterNextInst(insts,&err),&err) )
	{
		si2drNetlistViewIdT view;

		view = vendor_inst_get_view(inst); 

		si2drViewOccCreateInstOcc(viewocc, inst, view, &err);
		build_tree(instocc, view, inst); /* recursive descent */
	}
	si2drIterQuit(insts,&err);
	
	ports = si2drNetlistViewGetPorts(nv,SI2DR_ITER_SCALARS,&err); /*let's do a scalar rep. */
	while( !si2drObjectIsNull(port=si2drIterNextPort(ports,&err),&err) )
	{
		si2drViewOccCreatePortOcc(viewocc, port, &err);
	}
	si2drIterQuit(ports,&err);

	/* replicating the net connectivity in the occurrences is not
      necc. for generation of EdaXML; so we just add the nets in the
      occurrence tree that would be bacannotated to */
	
	nets = si2drNetlistViewGetNets(nv,SI2DR_ITER_SCALARS,&err); /*let's do a scalar rep. */
	while( !si2drObjectIsNull(net=si2drIterNextNet(nets,&err),&err) )
	{

		/* what am I doing in the code below? I reason that a net
	      connected to a port below the topocc is really part of the
	      net at the next level up. So I output all the top level
	      nets, and just the ones that are not connected to ports at
	      lower levels of hierarchy. */

		if( !si2drObjectIsNull(nvs_inst,&err) ) /* below topocc */
		{
			si2drPortsIdT netports = si2drNetGetPorts(net,&err);
			si2drPortIdT  netport = si2drIterNextPort(netports,&err);
		
			if( si2drObjectIsNull(netport,&err) )
			si2drViewOccCreateNetOcc(viewocc, net, &err);
		}
		else /* at topocc */
		{
			/* every net get added */
			si2drViewOccCreateNetOcc(viewocc, net, &err);
		}
	}
	si2drIterQuit(nets,&err);

}

int vendor_get_backannotation(struct backann **backann_array)
{
  /* this routine is provided at the vendor level. It's job is to get
      the backannotation data and convert it into the above defined
      representation; */
  /* it should read out the vendor data, and return an array of struct
      backann. the return value is the number of backannotation
      structs in the array. */
	
}

/* The struct backann method is just one way to do this translation
      from vendor backannotation to OccProp. This process could be
      streamlined by doing it all in one func, in one pass. */

si2drOccIdT find_obj_by_path(si2drTopOccIdT topOcc, si2drOccMemPathT path)
{
	/* try shots in the dark! */
	si2drOccIdT Occ;
	si2drErrorT err;

	Occ = si2drTopOccFindViewOccByPath(topOcc, path.path, &err);
	if( !si2drObjectIsNull(Occ,&err) )
		return Occ;
	Occ = si2drTopOccFindNetOccByPath(topOcc, path.path, &err);
	if( !si2drObjectIsNull(Occ,&err) )
		return Occ;
	Occ = si2drTopOccFindPortOccByPath(topOcc, path.path, path.memberPath, &err);
	if( !si2drObjectIsNull(Occ,&err) )
		return Occ;
	printf("Could not find Occurrence with path\n");
	return si2drPIGetNullId(&err);
}

void add_backannotation(si2drTopOccIdT topOcc, si2drOccPropSetIdT occPropSet)
{
	int num_backann, i;
	struct backann *backann_array;
	si2drErrorT err;
	si2drOccIdT Occ;
	si2drOccPropIdT occProp;
	si2drPropIdT prop;

	num_backann = vendor_get_backannotation(&backann_array);
	
	for(i=0;i<num_backann;i++)
	{
		struct backann *x = &backann_array[i]; /* shorthand! */
		switch( x->type )
		{
		case BA_OBJ_ANY:
			/* sometimes you just don't know what the object is. */
			Occ = find_obj_by_path(topOcc, x->path);
		case BA_OBJ_VIEW:
			Occ = si2drTopOccFindViewOccByPath(topOcc, x->path.path, &err);
			break;
		case BA_OBJ_NET:
			Occ = si2drTopOccFindNetOccByPath(topOcc, x->path.path, &err);
			break;
		case BA_OBJ_PORT:
			Occ = si2drTopOccFindPortOccByPath(topOcc, x->path.path, x->path.memberPath, &err);
			break;
		}
		if( si2drObjectIsNull(Occ,&err) )
			continue; 

		occProp = si2drOccGetOccProp(Occ, &err);
		if( si2drObjectIsNull(occProp,&err) )
			occProp = si2drOccCreateOccProp(Occ, occPropSet, &err);
		/* set the value */
		switch( x->btype )
		{
		case BA_TYP_PROP: /* the most common case */
			prop = si2drObjectCreateProp(occProp, x->name, &err);
			switch( x->prop_type )
			{

		    case SI2DR_INT32:
				si2drPropSetInt32Value(prop,x->prop_val.val_int, &err);
				break;
    	    case SI2DR_STRING:
				si2drPropSetStringValue(prop,x->prop_val.val_str, &err);
				break;
    	    case SI2DR_FLOAT32:
				si2drPropSetFloat32Value(prop,x->prop_val.val_float, &err);
				break;
    	    case SI2DR_BOOLEAN:
				si2drPropSetBooleanValue(prop,x->prop_val.val_bool, &err);
				break;
    	    case SI2DR_MINOMAX:
				si2drPropSetMiNoMaxValue(prop,x->prop_val.val_minomax, &err);
				break;
    	    case SI2DR_POINT:
				si2drPropSetPointValue(prop,x->prop_val.val_point, &err);
				break;
    	    case SI2DR_EXPRESSION:
				si2drPropSetStringValue(prop,x->prop_val.val_str, &err);
				break;
			}
			break;
		case BA_TYP_DESIGNATOR: /* the next most common case */
			if( x->type == BA_OBJ_VIEW )
				si2drViewOccPropCreateDesignator(occProp, x->designator, &err);
			else if( x->type == BA_OBJ_PORT )
				si2drPortOccPropCreateDesignator(occProp, x->designator, &err);
			else
				printf("designator attached to wrong object!\n");
			break;

		case BA_TYP_DCFANINLOAD:
			if( x->type == BA_OBJ_PORT )
				si2drPortOccPropCreateDcFanInLoad(occProp, x->num, &err);
			else
				printf("DcFanInLoad attached to wrong object!\n");
			break;
		case BA_TYP_DCFANOUTLOAD:
			if( x->type == BA_OBJ_PORT )
				si2drPortOccPropCreateDcFanOutLoad(occProp, x->num, &err);
			else
				printf("DcFanOutLoad attached to wrong object!\n");
			break;
		case BA_TYP_DCMAXFANIN:
			if( x->type == BA_OBJ_PORT )
				si2drPortOccPropCreateDcMaxFanIn(occProp, x->num, &err);
			else
				printf("DcMaxFanIn attached to wrong object!\n");
			break;
		case BA_TYP_DCMAXFANOUT:
			if( x->type == BA_OBJ_PORT )
				si2drPortOccPropCreateDcMaxFanOut(occProp, x->num, &err);
			else
				printf("DcMaxFanOut attached to wrong object!\n");
			break;
		case BA_TYP_ACLOAD:
			if( x->type == BA_OBJ_PORT )
				si2drPortOccPropCreateAcLoad(occProp, x->capval_range, &err);
			else
				printf("AcLoad attached to wrong object!\n");
			break;
		case BA_TYP_PORTDELAY:
			if( x->type == BA_OBJ_PORT )
				si2drPortOccPropCreatePortDelay( occProp, x->name, x->derivation, x->timedelay, x->spec,&err);
			else
				printf("PortDelay attached to wrong object!\n");
			break;

		case BA_TYP_PORTLOADDELAY:
			if( x->type == BA_OBJ_PORT )
				si2drPortOccPropCreatePortLoadDelay( occProp, x->name, x->derivation, x->timedelay, x->capval_range, x->spec,&err);
			else
				printf("PortLoadDelay attached to wrong object!\n");
			break;
		}
	}
}
