예제 #1
0
파일: rats.c 프로젝트: thequux/pcb
/* 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;
}
예제 #2
0
파일: rats.c 프로젝트: bert/pcb-update
/*
 * copy all connections from one net into another
 * and then remove the first net from its netlist
 */
static void
TransferNet (NetListTypePtr Netl, NetTypePtr SourceNet, NetTypePtr DestNet)
{
  ConnectionTypePtr conn;

  CONNECTION_LOOP (SourceNet);
  {
    conn = GetConnectionMemory (DestNet);
    *conn = *connection;
  }
  END_LOOP;
  DestNet->Style = SourceNet->Style;
  /* free the connection memory */
  FreeNetMemory (SourceNet);
  /* remove SourceNet from its netlist */
  *SourceNet = Netl->Net[--(Netl->NetN)];
  /* zero out old garbage */
  memset (&Netl->Net[Netl->NetN], 0, sizeof (NetType));
}
예제 #3
0
파일: rats.c 프로젝트: rlutz/pcb
/*!
 * \brief Copy all connections from one net into another and then remove
 * the first net from its netlist.
 */
static void
TransferNet (NetListType *Netl, NetType *SourceNet, NetType *DestNet)
{
  ConnectionType *conn;

  /* It would be worth checking if SourceNet is NULL here to avoid a segfault. Seb James. */
  CONNECTION_LOOP (SourceNet);
  {
    conn = GetConnectionMemory (DestNet);
    *conn = *connection;
  }
  END_LOOP;
  DestNet->Style = SourceNet->Style;
  /* free the connection memory */
  FreeNetMemory (SourceNet);
  /* remove SourceNet from its netlist */
  *SourceNet = Netl->Net[--(Netl->NetN)];
  /* zero out old garbage */
  memset (&Netl->Net[Netl->NetN], 0, sizeof (NetType));
}
예제 #4
0
파일: rats.c 프로젝트: rlutz/pcb
/*!
 * \brief 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 ConnectionType *, register ConnectionType *, register RouteStyleType *))
{
  NetListType *Nets, *Wantlist;
  NetType *lonesome;
  ConnectionType *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 ();
  Nets = (NetListType *)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, (PinType *) 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 ();
  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);
}
예제 #5
0
파일: rats.c 프로젝트: rlutz/pcb
/*!
 * \brief Determine existing interconnections of the net and gather into
 * sub-nets.
 *
 * Initially the netlist has each connection in its own individual net
 * afterwards there can be many fewer nets with multiple connections
 * each.
 */
static bool
GatherSubnets (NetListType *Netl, bool NoWarn, bool AndRats)
{
  NetType *a, *b;
  ConnectionType *conn;
  Cardinal m, n;
  bool Warned = false;

  for (m = 0; Netl->NetN > 0 && m < Netl->NetN; m++)
    {
      a = &Netl->Net[m];
      ClearFlagOnAllObjects (false, DRCFLAG);
      RatFindHook (a->Connection[0].type, a->Connection[0].ptr1,
                   a->Connection[0].ptr2, a->Connection[0].ptr2,
                   false, DRCFLAG, AndRats);
      /* now anybody connected to the first point has DRCFLAG set */
      /* so move those to this subnet */
      CLEAR_FLAG (DRCFLAG, (PinType *) a->Connection[0].ptr2);
      for (n = m + 1; n < Netl->NetN; n++)
	{
	  b = &Netl->Net[n];
	  /* There can be only one connection in net b */
	  if (TEST_FLAG (DRCFLAG, (PinType *) b->Connection[0].ptr2))
	    {
	      CLEAR_FLAG (DRCFLAG, (PinType *) b->Connection[0].ptr2);
	      TransferNet (Netl, b, a);
	      /* back up since new subnet is now at old index */
	      n--;
	    }
	}
      /* now add other possible attachment points to the subnet */
      /* e.g. line end-points and vias */
      /* don't add non-manhattan lines, the auto-router can't route to them */
      ALLLINE_LOOP (PCB->Data);
      {
	if (TEST_FLAG (DRCFLAG, line))
	  {
	    conn = GetConnectionMemory (a);
	    conn->X = line->Point1.X;
	    conn->Y = line->Point1.Y;
	    conn->type = LINE_TYPE;
	    conn->ptr1 = layer;
	    conn->ptr2 = line;
	    conn->group = GetLayerGroupNumberByPointer (layer);
	    conn->menu = NULL;	/* agnostic view of where it belongs */
	    conn = GetConnectionMemory (a);
	    conn->X = line->Point2.X;
	    conn->Y = line->Point2.Y;
	    conn->type = LINE_TYPE;
	    conn->ptr1 = layer;
	    conn->ptr2 = line;
	    conn->group = GetLayerGroupNumberByPointer (layer);
	    conn->menu = NULL;
	  }
      }
      ENDALL_LOOP;
      /* add polygons so the auto-router can see them as targets */
      ALLPOLYGON_LOOP (PCB->Data);
      {
	if (TEST_FLAG (DRCFLAG, polygon))
	  {
	    conn = GetConnectionMemory (a);
	    /* make point on a vertex */
	    conn->X = polygon->Clipped->contours->head.point[0];
	    conn->Y = polygon->Clipped->contours->head.point[1];
	    conn->type = POLYGON_TYPE;
	    conn->ptr1 = layer;
	    conn->ptr2 = polygon;
	    conn->group = GetLayerGroupNumberByPointer (layer);
	    conn->menu = NULL;	/* agnostic view of where it belongs */
	  }
      }
      ENDALL_LOOP;
      VIA_LOOP (PCB->Data);
      {
	if (TEST_FLAG (DRCFLAG, via))
	  {
	    conn = GetConnectionMemory (a);
	    conn->X = via->X;
	    conn->Y = via->Y;
	    conn->type = VIA_TYPE;
	    conn->ptr1 = via;
	    conn->ptr2 = via;
	    conn->group = bottom_group;
	  }
      }
      END_LOOP;
      if (!NoWarn)
	Warned |= CheckShorts (a->Connection[0].menu);
    }
  ClearFlagOnAllObjects (false, DRCFLAG);
  return (Warned);
}
예제 #6
0
파일: rats.c 프로젝트: rlutz/pcb
/*!
 * \brief Read the library-netlist build a true Netlist structure.
 */
NetListType *
ProcNetlist (LibraryType *net_menu)
{
  ConnectionType *connection;
  ConnectionType LastPoint;
  NetType *net;
  static NetListType *Wantlist = NULL;

  if (!net_menu->MenuN)
    return (NULL);
  FreeNetListMemory (Wantlist);
  free (Wantlist);
  badnet = false;

  /* find layer groups of the component side and solder side */
  bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE);
  top_group = GetLayerGroupNumberBySide (TOP_SIDE);

  Wantlist = (NetListType *)calloc (1, sizeof (NetListType));
  if (Wantlist)
    {
      ALLPIN_LOOP (PCB->Data);
      {
	pin->Spare = NULL;
	CLEAR_FLAG (DRCFLAG, pin);
      }
      ENDALL_LOOP;
      ALLPAD_LOOP (PCB->Data);
      {
	pad->Spare = NULL;
	CLEAR_FLAG (DRCFLAG, pad);
      }
      ENDALL_LOOP;
      MENU_LOOP (net_menu);
      {
	if (menu->Name[0] == '*' || menu->flag == 0)
	  {
	    badnet = true;
	    continue;
	  }
	net = GetNetMemory (Wantlist);
	if (menu->Style)
	  {
	    STYLE_LOOP (PCB);
	    {
	      if (style->Name && !NSTRCMP (style->Name, menu->Style))
		{
		  net->Style = style;
		  break;
		}
	    }
	    END_LOOP;
	  }
	else			/* default to NULL if none found */
	  net->Style = NULL;
	ENTRY_LOOP (menu);
	{
	  if (SeekPad (entry, &LastPoint, false))
	    {
	      if (TEST_FLAG (DRCFLAG, (PinType *) LastPoint.ptr2))
		Message (_
			 ("Error! Element %s pin %s appears multiple times in the netlist file.\n"),
			 NAMEONPCB_NAME ((ElementType *) LastPoint.ptr1),
			 (LastPoint.type ==
			  PIN_TYPE) ? ((PinType *) LastPoint.ptr2)->
			 Number : ((PadType *) LastPoint.ptr2)->Number);
	      else
		{
		  connection = GetConnectionMemory (net);
		  *connection = LastPoint;
		  /* indicate expect net */
		  connection->menu = menu;
		  /* mark as visited */
		  SET_FLAG (DRCFLAG, (PinType *) LastPoint.ptr2);
		  if (LastPoint.type == PIN_TYPE)
		    ((PinType *) LastPoint.ptr2)->Spare = (void *) menu;
		  else
		    ((PadType *) LastPoint.ptr2)->Spare = (void *) menu;
		}
	    }
	  else
	    badnet = true;
	  /* check for more pins with the same number */
	  for (; SeekPad (entry, &LastPoint, true);)
	    {
	      connection = GetConnectionMemory (net);
	      *connection = LastPoint;
	      /* indicate expect net */
	      connection->menu = menu;
	      /* mark as visited */
	      SET_FLAG (DRCFLAG, (PinType *) LastPoint.ptr2);
	      if (LastPoint.type == PIN_TYPE)
		((PinType *) LastPoint.ptr2)->Spare = (void *) menu;
	      else
		((PadType *) LastPoint.ptr2)->Spare = (void *) menu;
	    }
	}
	END_LOOP;
      }
      END_LOOP;
    }
  /* clear all visit marks */
  ALLPIN_LOOP (PCB->Data);
  {
    CLEAR_FLAG (DRCFLAG, pin);
  }
  ENDALL_LOOP;
  ALLPAD_LOOP (PCB->Data);
  {
    CLEAR_FLAG (DRCFLAG, pad);
  }
  ENDALL_LOOP;
  return (Wantlist);
}