Exemple #1
0
/* XXX: This is copied in large part from AddAllRats above; for
 * maintainability, AddAllRats probably wants to be tweaked to use this
 * version of the code so that we don't have duplication. */
NetListListType
CollectSubnets (bool SelectedOnly)
{
  NetListListType result = { 0, 0, NULL };
  NetListTypePtr Nets, Wantlist;
  NetTypePtr lonesome;
  ConnectionTypePtr onepin;

  /* the netlist library has the text form
   * ProcNetlist fills in the Netlist
   * structure the way the final routing
   * is supposed to look
   */
  Wantlist = ProcNetlist (&PCB->NetlistLib);
  if (!Wantlist)
    {
      Message (_("Can't add rat lines because no netlist is loaded.\n"));
      return result;
    }
  /* initialize finding engine */
  InitConnectionLookup ();
  SaveFindFlag (DRCFLAG);
  /* now we build another netlist (Nets) for each
   * net in Wantlist that shows how it actually looks now,
   * then fill in any missing connections with rat lines.
   *
   * we first assume each connection is separate
   * (no routing), then gather them into groups
   * if the net is all routed, the new netlist (Nets)
   * will have only one net entry.
   * Note that DrawShortestRats consumes all nets
   * from Nets, so *Nets is empty after the
   * DrawShortestRats call
   */
  NET_LOOP (Wantlist);
  {
    Nets = GetNetListMemory (&result);
    CONNECTION_LOOP (net);
    {
      if (!SelectedOnly
	  || TEST_FLAG (SELECTEDFLAG, (PinTypePtr) connection->ptr2))
	{
	  lonesome = GetNetMemory (Nets);
	  onepin = GetConnectionMemory (lonesome);
	  *onepin = *connection;
	  lonesome->Style = net->Style;
	}
    }
    END_LOOP;
    /* Note that AndRats is *FALSE* here! */
    GatherSubnets (Nets, SelectedOnly, false);
  }
  END_LOOP;
  FreeConnectionLookupMemory ();
  RestoreFindFlag ();
  return result;
}
Exemple #2
0
/* returns 0 on succes */
static int proc_short(PinType *pin, PadType *pad, int ignore)
{
	find_callback_t old_cb;
	Coord x, y;
	short_conn_t *n, **lut_by_oid, **lut_by_gid, *next;
	int gids;
	gr_t *g;
	void *S, *T;
	int *solution;
	int i, maxedges;
	int bad_gr = 0;

	if (!TEST_FLAG (ENABLEMINCUTFLAG, PCB))
		return bad_gr;

	if (!Settings.EnableMincut)
		return bad_gr;

	/* only one should be set, but one must be set */
	assert((pin != NULL) || (pad != NULL));
	assert((pin == NULL) || (pad == NULL));

	if (pin != NULL) {
		debprintf("short on pin!\n");
		SET_FLAG (WARNFLAG, pin);
		x = pin->X;
		y = pin->Y;
	}
	else if (pad != NULL) {
		debprintf("short on pad!\n");
		SET_FLAG (WARNFLAG, pad);
		if (TEST_FLAG (EDGE2FLAG, pad)) {
			x = pad->Point2.X;
			y = pad->Point2.Y;
		}
		else {
			x = pad->Point1.X;
			y = pad->Point1.Y;
		}
	}

		/* run only if net is not ignored */
	if (ignore)
		return 0;

short_conns = NULL;
num_short_conns = 0;
short_conns_maxid = 0;

	/* perform a search using MINCUTFLAG, calling back proc_short_cb() with the connections */
	old_cb = find_callback;
	find_callback = proc_short_cb;
	SaveFindFlag(MINCUTFLAG);
	LookupConnection (x, y, false, 1, MINCUTFLAG);

	debprintf("- alloced for %d\n", (short_conns_maxid+1));
	lut_by_oid = calloc(sizeof(short_conn_t *), (short_conns_maxid+1));
	lut_by_gid = calloc(sizeof(short_conn_t *), (num_short_conns+3));

	g = gr_alloc(num_short_conns+2);

	g->node2name = calloc(sizeof(char *), (num_short_conns+2));

	/* conn 0 is S and conn 1 is T and set up lookup arrays */
	for(n = short_conns, gids=2; n != NULL; n = n->next, gids++) {
		char *s, *typ;
		ElementType *parent;
		n->gid = gids;
		debprintf(" {%d} found %d %d/%p type %d from %d\n", n->gid, n->to_type, n->to->ID, n->to, n->type, n->from_id);
		lut_by_oid[n->to->ID] = n;
		lut_by_gid[n->gid] = n;
		
		s = malloc(256);
		parent = NULL;
		switch(n->to_type) {
			case PIN_TYPE: typ = "pin"; parent = ((PinType *)(n->to))->Element; break;
			case VIA_TYPE: typ = "via"; parent = ((PinType *)(n->to))->Element; break;
			case PAD_TYPE: typ = "pad"; parent = ((PadType *)(n->to))->Element; break;
			case LINE_TYPE: typ = "line"; break;
			default: typ="other"; break;
		}
		if (parent != NULL) {
			TextType *name;
			name = &parent->Name[1];
			if ((name->TextString == NULL) || (*name->TextString == '\0'))
				sprintf(s, "%s #%d \\nof #%d", typ, n->to->ID, parent->ID);
			else
				sprintf(s, "%s #%d \\nof %s", typ, n->to->ID, name->TextString);
		}
		else
			sprintf(s, "%s #%d", typ, n->to->ID);
		g->node2name[n->gid] = s;
	}
	g->node2name[0] = strdup("S");
	g->node2name[1] = strdup("T");

	/* calculate how many edges each node has and the max edge count */
	maxedges = 0;
	for(n = short_conns; n != NULL; n = n->next) {
		short_conn_t *from;

		n->edges++;
		if (n->edges > maxedges)
			maxedges = n->edges;

		if (n->from_id >= 0) {
			from = lut_by_oid[n->from_id];
			if (from == NULL) {
				/* no from means broken graph (multiple components) */
				if (n->from_id >= 2) { /* ID 0 and 1 are start/stop, there won't be from for them */
					fprintf(stderr, "rats_mincut.c error: graph has multiple components, bug in find.c (n->from_id=%d)!\n", n->from_id);
					bad_gr = 1;
				}
				continue;
			}
			from->edges++;
			if (from->edges > maxedges)
				maxedges = from->edges;
		}
	}


	S = NULL;
	T = NULL;
	for(n = short_conns; n != NULL; n = n->next) {
		short_conn_t *from;
		void *spare;

		spare = NULL;
		if (n->to_type == PIN_TYPE)
			spare = ((PinType *)n->to)->Spare;
		if (n->to_type == PAD_TYPE)
			spare = ((PadType *)n->to)->Spare;
		if (spare != NULL) {
			void *net = &(((LibraryMenuTypePtr)spare)->Name[2]);
			debprintf(" net=%s\n", net);
			if (S == NULL) {
				debprintf(" -> became S\n");
				S = net;
			}
			else if ((T == NULL) && (net != S)) {
				debprintf(" -> became T\n");
				T = net;
			}

			if (net == S)
				gr_add_(g, n->gid, 0, 100000);
			else if (net == T)
				gr_add_(g, n->gid, 1, 100000);
		}
		/* if we have a from object, look it up and make a connection between the two gids */
		if (n->from_id >= 0) {
			int weight;
			short_conn_t *from = lut_by_oid[n->from_id];

			from = lut_by_oid[n->from_id];
			/* weight: 1 for connections we can break, large value for connections we shall not break */
			if ((n->type == FCT_COPPER) || (n->type == FCT_START)) {
				/* connection to a pin/pad is slightly stronger than the
				   strongest obj-obj conn; obj-obj conns are weaker at junctions where many
				   objects connect */
				if ((n->from_type == PIN_TYPE) || (n->from_type == PAD_TYPE) || (n->to_type == PIN_TYPE) || (n->to_type == PAD_TYPE))
					weight = maxedges*2 + 2;
				else
					weight = maxedges*2 - n->edges - from->edges + 1;
			}
			else
				weight = 10000;
			if (from != NULL) {
				gr_add_(g, n->gid, from->gid, weight);
				debprintf(" CONN %d %d\n", n->gid, from->gid);
			}
		}
	}

/*#define MINCUT_DRAW*/
#ifdef MINCUT_DRAW
	{
		static int drw = 0;
		char gfn[256];
		drw++;
		sprintf(gfn, "A_%d_a", drw);
		debprintf("gfn=%s\n", gfn);
		gr_draw(g, gfn, "png");
	}
#endif

	if (!bad_gr) {
	solution = solve(g);

	if (solution != NULL) {
		debprintf("Would cut:\n");
		for(i = 0; solution[i] != -1; i++) {
			short_conn_t *s;
			debprintf("%d:", i);
			s = lut_by_gid[solution[i]];
			debprintf("%d %p", solution[i], s);
			if (s != NULL) {
				SET_FLAG (WARNFLAG, s->to);
				debprintf("  -> %d", s->to->ID);
			}
			debprintf("\n");
		}

		free(solution);
	}
	else {
		fprintf(stderr, "mincut didn't find a solution, falling back to the old warn\n");
		bad_gr=1;
	}
	}
	free(lut_by_oid);
	free(lut_by_gid);

	for(n = short_conns; n != NULL; n = next) {
		next = n->next;
		free(n);
	}


	ResetFoundLinesAndPolygons(false);
	ResetFoundPinsViasAndPads(false);
	RestoreFindFlag();

	find_callback = old_cb;
	return bad_gr;
}
Exemple #3
0
/* ---------------------------------------------------------------------------
 *  AddAllRats puts the rats nest into the layout from the loaded netlist
 *  if SelectedOnly is true, it will only draw rats to selected pins and pads
 */
bool
AddAllRats (bool SelectedOnly, void (*funcp) (register ConnectionTypePtr, register ConnectionTypePtr, register RouteStyleTypePtr))
{
  NetListTypePtr Nets, Wantlist;
  NetTypePtr lonesome;
  ConnectionTypePtr onepin;
  bool changed, Warned = false;

  /* the netlist library has the text form
   * ProcNetlist fills in the Netlist
   * structure the way the final routing
   * is supposed to look
   */
  Wantlist = ProcNetlist (&PCB->NetlistLib);
  if (!Wantlist)
    {
      Message (_("Can't add rat lines because no netlist is loaded.\n"));
      return (false);
    }
  changed = false;
  /* initialize finding engine */
  InitConnectionLookup ();
  SaveFindFlag (DRCFLAG);
  Nets = (NetListTypePtr)calloc (1, sizeof (NetListType));
  /* now we build another netlist (Nets) for each
   * net in Wantlist that shows how it actually looks now,
   * then fill in any missing connections with rat lines.
   *
   * we first assume each connection is separate
   * (no routing), then gather them into groups
   * if the net is all routed, the new netlist (Nets)
   * will have only one net entry.
   * Note that DrawShortestRats consumes all nets
   * from Nets, so *Nets is empty after the
   * DrawShortestRats call
   */
  NET_LOOP (Wantlist);
  {
    CONNECTION_LOOP (net);
    {
      if (!SelectedOnly
	  || TEST_FLAG (SELECTEDFLAG, (PinTypePtr) connection->ptr2))
	{
	  lonesome = GetNetMemory (Nets);
	  onepin = GetConnectionMemory (lonesome);
	  *onepin = *connection;
	  lonesome->Style = net->Style;
	}
    }
    END_LOOP;
    Warned |= GatherSubnets (Nets, SelectedOnly, true);
    if (Nets->NetN > 0)
      changed |= DrawShortestRats (Nets, funcp);
  }
  END_LOOP;
  FreeNetListMemory (Nets);
  free (Nets);
  FreeConnectionLookupMemory ();
  RestoreFindFlag ();
  if (funcp)
    return (true);

  if (Warned || changed)
    Draw ();

  if (Warned)
    Settings.RatWarn = true;

  if (changed)
    {
      IncrementUndoSerialNumber ();
      if (PCB->Data->RatN > 0) 
	{
	  Message ("%d rat line%s remaining\n", PCB->Data->RatN,
		   PCB->Data->RatN > 1 ? "s" : "");
	}
      return (true);
    }
  if (!SelectedOnly && !Warned)
    {
      if (!PCB->Data->RatN && !badnet)
	Message (_("Congratulations!!\n"
		   "The layout is complete and has no shorted nets.\n"));
      else
	Message (_("Nothing more to add, but there are\n"
		   "either rat-lines in the layout, disabled nets\n"
		   "in the net-list, or missing components\n"));
    }
  return (false);
}