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