1 /*
2     PADRING -- a padring generator for ASICs.
3 
4     Copyright (c) 2019, Niels Moseley <niels@symbioticeda.com>
5 
6     Permission to use, copy, modify, and/or distribute this software for any
7     purpose with or without fee is hereby granted, provided that the above
8     copyright notice and this permission notice appear in all copies.
9 
10     THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11     WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12     MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13     ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14     WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 
18 */
19 
20 #include <sstream>
21 #include <fstream>
22 #include <complex>
23 #include <math.h>
24 #include "logging.h"
25 #include "svgwriter.h"
26 
SVGWriter(std::ostream & os,uint32_t width,uint32_t height)27 SVGWriter::SVGWriter(std::ostream &os, uint32_t width, uint32_t height)
28     : m_svg(os),
29       m_width(width),
30       m_height(height)
31 {
32     writeHeader();
33 }
34 
~SVGWriter()35 SVGWriter::~SVGWriter()
36 {
37     m_svg.flush();
38     writeFooter();
39 }
40 
writeHeader()41 void SVGWriter::writeHeader()
42 {
43     m_svg << "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ";
44     m_svg << m_width << " " << m_height << "\">\n";
45 }
46 
writeFooter()47 void SVGWriter::writeFooter()
48 {
49     m_svg << "</svg>\n";
50 }
51 
52 
toSVGCoordinates(std::complex<double> & p) const53 std::complex<double> SVGWriter::toSVGCoordinates(std::complex<double> &p) const
54 {
55     return std::complex<double>(p.real(), m_height - p.imag());
56 }
57 
writeCell(const LayoutItem * item)58 void SVGWriter::writeCell(const LayoutItem *item)
59 {
60     if (item == nullptr)
61     {
62         return;
63     }
64 
65     double rot = 0.0;
66     double x = item->m_x;
67     double y = item->m_y;
68 
69     // regular cells have N,S,E,W,
70     // corner cells have NE,NW,SE,SW
71     if (item->m_location == "N")
72     {
73         // North orientation, rotation = 180 degrees
74         x += item->m_lefinfo->m_sx;
75         rot = 180.0;
76     }
77     else if (item->m_location == "S")
78     {
79         // South orientation, rotation = 0 degrees
80         //y += item->m_lefinfo->m_sy;
81     }
82     else if (item->m_location == "E")
83     {
84         // East orientation
85         rot = 90.0;
86     }
87     else if (item->m_location == "W")
88     {
89         // West
90         y += item->m_lefinfo->m_sx;
91         rot = 270.0;
92     }
93 
94     // do corners
95     if (item->m_location == "NW")
96     {
97         // North West orientation, rotation = 270 degrees
98         rot = 270.0;
99     }
100     else if (item->m_location == "SE")
101     {
102         // South East orientation, rotation = 90 degrees
103         x += item->m_lefinfo->m_sy;
104         rot = 90.0;
105     }
106     else if (item->m_location == "NE")
107     {
108         x += item->m_lefinfo->m_sx;
109         rot = 180.0;
110     }
111 
112     std::complex<double> ll = {0.0,0.0};
113     std::complex<double> ul = {0.0,item->m_lefinfo->m_sy};
114     std::complex<double> ur = {item->m_lefinfo->m_sx,item->m_lefinfo->m_sy};
115     std::complex<double> lr = {item->m_lefinfo->m_sx,0.0};
116 
117     std::complex<double> rr = {cos(3.1415927*rot/180.0), sin(3.1415927*rot/180.0)};
118 
119     ll *= rr;
120     ul *= rr;
121     ur *= rr;
122     lr *= rr;
123 
124     ll += std::complex<double>(x,y);
125     ul += std::complex<double>(x,y);
126     ur += std::complex<double>(x,y);
127     lr += std::complex<double>(x,y);
128 
129     ll = toSVGCoordinates(ll);
130     ul = toSVGCoordinates(ul);
131     ur = toSVGCoordinates(ur);
132     lr = toSVGCoordinates(lr);
133 
134     // draw cell outline
135     m_svg << "<polyline points=\"";
136     m_svg << ll.real() << " " << ll.imag() << " ";
137     m_svg << ul.real() << " " << ul.imag() << " ";
138     m_svg << ur.real() << " " << ur.imag() << " ";
139     m_svg << lr.real() << " " << lr.imag() << " ";
140     m_svg << ll.real() << " " << ll.imag() << "\" ";
141 
142     //
143     // colour palette
144     //
145     //  #BFE1F3 light blue
146     //  #179AA9 blue
147     //  #AAD355 green
148     //  #F9C908 yellow
149     //  #F25844 red
150     //
151 
152     //m_svg << "<rect x=\"" << x << "\" y=\"" << m_height-y << "\" ";
153     //m_svg << "width=\"" << sx << "\" height=\"" << sy << "\" ";
154     if (item->m_ltype == LayoutItem::TYPE_FILLER)
155     {
156         m_svg << "style=\"fill:#BFE1F3;stroke:#179AA9;stroke-width:0.25\" />\n";
157     }
158     else
159     {
160         m_svg << "style=\"fill:#FAAD35;stroke:#F25844;stroke-width:0.5\" />\n";
161     }
162 
163     // show cell orientation
164     {
165         double sw = item->m_lefinfo->m_sx * 0.2;
166         std::complex<double> p1 = {sw,0};
167         std::complex<double> p2 = {0.0,sw};
168 
169         if (item->m_flipped)
170         {
171             p1 = {item->m_lefinfo->m_sx - sw,0};
172             p2 = {item->m_lefinfo->m_sx, sw};
173         }
174 
175         p1 *= rr;
176         p2 *= rr;
177 
178         p1 += std::complex<double>(x,y);
179         p2 += std::complex<double>(x,y);
180 
181         p1 = toSVGCoordinates(p1);
182         p2 = toSVGCoordinates(p2);
183 
184         m_svg << "<polyline points=\"";
185         m_svg << p1.real() << " " << p1.imag() << " ";
186         m_svg << p2.real() << " " << p2.imag() << "\" ";
187         m_svg << "style=\"stroke:#F25844;stroke-width:0.75\" />\n";
188     }
189 
190     if (item->m_ltype == LayoutItem::TYPE_CORNER)
191     {
192         m_svg << "<circle cx=\"" << ll.real() << "\" cy=\"" << ll.imag() <<  "\" r=\"" << 5.0 << "\" style=\"fill:#000000\" />\n";
193     }
194 
195     std::complex<double> center = (ll + ur) / 2.0;
196     if (item->m_ltype != LayoutItem::TYPE_FILLER)
197     {
198         m_svg << "<text text-anchor=\"middle\" x=\"" << center.real() << "\" y=\"" << center.imag() << "\" class=\"small\">" << item->m_cellname << "</text>\n";
199         m_svg << "<text text-anchor=\"middle\" x=\"" << center.real() << "\" y=\"" << center.imag()+20 << "\" class=\"small\">" << item->m_instance << "</text>\n";
200     }
201 }
202