File: connectivity_database.hpp

package info (click to toggle)
boost1.74 1.74.0%2Bds1-21
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 463,588 kB
  • sloc: cpp: 3,338,117; xml: 131,293; python: 33,088; ansic: 14,292; asm: 4,038; sh: 3,353; makefile: 1,193; perl: 1,036; yacc: 478; php: 212; ruby: 102; lisp: 24; sql: 13; csh: 6
file content (149 lines) | stat: -rw-r--r-- 6,652 bytes parent folder | download | duplicates (14)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
  Copyright 2010 Intel Corporation

  Use, modification and distribution are subject to the Boost Software License,
  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  http://www.boost.org/LICENSE_1_0.txt).
*/
//connectivity_database.hpp
#ifndef BOOST_POLYGON_TUTORIAL_CONNECTIVITY_DATABASE_HPP
#define BOOST_POLYGON_TUTORIAL_CONNECTIVITY_DATABASE_HPP
#include <boost/polygon/polygon.hpp>
#include <map>
#include <sstream>
#include "layout_database.hpp"
#include "layout_pin.hpp"

typedef std::map<std::string, layout_database > connectivity_database;

//map layout pin data type to boost::polygon::rectangle_concept
namespace boost { namespace polygon{
  template <>
  struct rectangle_traits<layout_pin> {
    typedef int coordinate_type;
    typedef interval_data<int> interval_type;
    static inline interval_type get(const layout_pin& pin, orientation_2d orient) {
      if(orient == HORIZONTAL)
        return interval_type(pin.xl, pin.xh);
      return interval_type(pin.yl, pin.yh);
    }
  };

  template <>
  struct geometry_concept<layout_pin> { typedef rectangle_concept type; };
}}

typedef boost::polygon::polygon_90_data<int> polygon;
typedef boost::polygon::polygon_90_set_data<int> polygon_set;

inline void populate_connected_component
(connectivity_database& connectivity, std::vector<polygon>& polygons, 
 std::vector<int> polygon_color, std::vector<std::set<int> >& graph, 
 std::size_t node_id, std::size_t polygon_id_offset, std::string& net, 
 std::vector<std::string>& net_ids, std::string net_prefix,
 std::string& layout_layer) {
  if(polygon_color[node_id] == 1)
    return;
  polygon_color[node_id] = 1;
  if(node_id < polygon_id_offset && net_ids[node_id] != net) {
    //merge nets in connectivity database
    //if one of the nets is internal net merge it into the other
    std::string net1 = net_ids[node_id];
    std::string net2 = net;
    if(net.compare(0, net_prefix.length(), net_prefix) == 0) {
      net = net1;
      std::swap(net1, net2);
    } else {
      net_ids[node_id] = net;
    }
    connectivity_database::iterator itr = connectivity.find(net1);
    if(itr != connectivity.end()) {
      for(layout_database::iterator itr2 = (*itr).second.begin();
          itr2 != (*itr).second.end(); ++itr2) {
        connectivity[net2][(*itr2).first].insert((*itr2).second);
      }
      connectivity.erase(itr);
    }
  }
  if(node_id >= polygon_id_offset)
    connectivity[net][layout_layer].insert(polygons[node_id - polygon_id_offset]);
  for(std::set<int>::iterator itr = graph[node_id].begin();
      itr != graph[node_id].end(); ++itr) {
    populate_connected_component(connectivity, polygons, polygon_color, graph, 
                                 *itr, polygon_id_offset, net, net_ids, net_prefix, layout_layer);
  }
}

inline void connect_layout_to_layer(connectivity_database& connectivity, polygon_set& layout, std::string layout_layer, std::string layer, std::string net_prefix, int& net_suffix) {
  if(layout_layer.empty())
    return;
  boost::polygon::connectivity_extraction_90<int> ce;
  std::vector<std::string> net_ids;
  for(connectivity_database::iterator itr = connectivity.begin(); itr != connectivity.end(); ++itr) {
    net_ids.push_back((*itr).first);
    ce.insert((*itr).second[layer]);
  }
  std::vector<polygon> polygons;
  layout.get_polygons(polygons);
  std::size_t polygon_id_offset = net_ids.size();
  for(std::size_t i = 0; i < polygons.size(); ++i) {
    ce.insert(polygons[i]);
  }
  std::vector<std::set<int> > graph(polygons.size() + net_ids.size(), std::set<int>());
  ce.extract(graph);
  std::vector<int> polygon_color(polygons.size() + net_ids.size(), 0);
  //for each net in net_ids populate connected component with net
  for(std::size_t node_id = 0; node_id < net_ids.size(); ++node_id) {
    populate_connected_component(connectivity, polygons, polygon_color, graph, node_id, 
                                 polygon_id_offset, net_ids[node_id], net_ids, 
                                 net_prefix, layout_layer);
  }
  //for each polygon_color that is zero populate connected compontent with net_prefix + net_suffix++
  for(std::size_t i = 0; i < polygons.size(); ++i) {
    if(polygon_color[i + polygon_id_offset] == 0) {
      std::stringstream ss(std::stringstream::in | std::stringstream::out);
      ss << net_prefix << net_suffix++;
      std::string internal_net; 
      ss >> internal_net;
      populate_connected_component(connectivity, polygons, polygon_color, graph, 
                                   i + polygon_id_offset, 
                                   polygon_id_offset, internal_net, net_ids, 
                                   net_prefix, layout_layer);
    }
  }
}

//given a layout_database we populate a connectivity database
inline void populate_connectivity_database(connectivity_database& connectivity, std::vector<layout_pin>& pins, layout_database& layout) {
  using namespace boost::polygon;
  using namespace boost::polygon::operators;
  for(std::size_t i = 0; i < pins.size(); ++i) {
    connectivity[pins[i].net][pins[i].layer].insert(pins[i]);
  }
  int internal_net_suffix = 0;
  //connect metal1 layout to pins which were on metal1
  connect_layout_to_layer(connectivity, layout["METAL1"], "METAL1", 
                          "METAL1", "__internal_net_", internal_net_suffix);
  //connect via0 layout to metal1
  connect_layout_to_layer(connectivity, layout["VIA0"], "VIA0", 
                          "METAL1", "__internal_net_", internal_net_suffix);
  //poly needs to have gates subtracted from it to prevent shorting through transistors
  polygon_set poly_not_gate = layout["POLY"] - layout["GATE"];
  //connect poly minus gate to via0
  connect_layout_to_layer(connectivity, poly_not_gate, "POLY", 
                          "VIA0", "__internal_net_", internal_net_suffix);
  //we don't want to short signals through transistors so we subtract the gate regions
  //from the diffusions
  polygon_set diff_not_gate = (layout["PDIFF"] + layout["NDIFF"]) - layout["GATE"];
  //connect diffusion minus gate to poly
  //Note that I made up the DIFF layer name for combined P and NDIFF
  connect_layout_to_layer(connectivity, diff_not_gate, "DIFF", 
                          "POLY", "__internal_net_", internal_net_suffix);
  //connect gate to poly to make connections through gates on poly
  connect_layout_to_layer(connectivity, layout["GATE"], "GATE", 
                          "POLY", "__internal_net_", internal_net_suffix);
  //now we have traced connectivity of the layout down to the transistor level
  //any polygons not connected to pins have been assigned internal net names
}

#endif