OdbDesignLib
OdbDesign ODB++ Parsing Library
NetlistFile.cpp
1 #include "NetlistFile.h"
2 #include "NetlistFile.h"
3 #include "NetlistFile.h"
4 #include "NetlistFile.h"
5 #include "NetlistFile.h"
6 #include "NetlistFile.h"
7 #include "NetlistFile.h"
8 #include "NetlistFile.h"
9 #include <fstream>
10 #include <sstream>
11 #include <Logger.h>
12 #include "../parse_error.h"
13 #include "../invalid_odb_error.h"
14 #include <climits>
15 
16 namespace Odb::Lib::FileModel::Design
17 {
18  NetlistFile::NetlistFile(std::filesystem::path path)
19  : m_path(path)
20  , m_optimized(false)
21  , m_staggered(Staggered::Unknown)
22  {
23  }
24 
25  NetlistFile::~NetlistFile()
26  {
27  m_netRecords.clear();
28  m_netRecordsByName.clear();
29  m_netPointRecords.clear();
30  }
31 
32  std::filesystem::path NetlistFile::GetPath() const
33  {
34  return m_path;
35  }
36 
37  std::string NetlistFile::GetName() const
38  {
39  return m_name;
40  }
41 
42  std::string NetlistFile::GetUnits() const
43  {
44  return m_units;
45  }
46 
47  bool NetlistFile::GetOptimized() const
48  {
49  return m_optimized;
50  }
51 
52  NetlistFile::Staggered NetlistFile::GetStaggered() const
53  {
54  return m_staggered;
55  }
56 
57  const NetlistFile::NetRecord::Vector& NetlistFile::GetNetRecords() const
58  {
59  return m_netRecords;
60  }
61 
62  const NetlistFile::NetRecord::StringMap& NetlistFile::GetNetRecordsByName() const
63  {
64  return m_netRecordsByName;
65  }
66 
67  const NetlistFile::NetPointRecord::Vector& NetlistFile::GetNetPointRecords() const
68  {
69  return m_netPointRecords;
70  }
71 
72  bool NetlistFile::Parse()
73  {
74  std::ifstream netlistFile;
75  int lineNumber = 0;
76  std::string line;
77 
78  try
79  {
80  m_name = std::filesystem::path(m_path).filename().string();
81 
82  loginfo("Parsing netlist: " + m_name + "...");
83 
84  auto netlistFilePath = m_path / "netlist";
85 
86  if (!std::filesystem::exists(netlistFilePath))
87  {
88  auto message = "netlist file does not exist: [" + m_path.string() + "]";
89  throw invalid_odb_error(message.c_str());
90  }
91 
92  else if (!std::filesystem::is_regular_file(netlistFilePath))
93  {
94  auto message = "netlist file is not a file: [" + m_path.string() + "]";
95  throw invalid_odb_error(message.c_str());
96  }
97 
98  netlistFile.open(netlistFilePath.string(), std::ios::in);
99  if (!netlistFile.is_open())
100  {
101  auto message = "unable to open netlist file: [" + m_path.string() + "]";
102  throw invalid_odb_error(message.c_str());
103  }
104 
105  while (std::getline(netlistFile, line))
106  {
107  lineNumber++;
108  if (!line.empty())
109  {
110  std::stringstream lineStream(line);
111 
112  if (line.find(COMMENT_TOKEN) == 0)
113  {
114  // comment line
115  }
116  else if (line.find(UNITS_TOKEN) == 0)
117  {
118  // units line
119  std::string token;
120  if (!std::getline(lineStream, token, '='))
121  {
122  throw_parse_error(m_path, line, token, lineNumber);
123  }
124  else if (!std::getline(lineStream, token, '='))
125  {
126  throw_parse_error(m_path, line, token, lineNumber);
127  }
128  m_units = token;
129  }
130  else if (line.find(HEADER_TOKEN) == 0)
131  {
132  // header line
133  std::string token;
134 
135  // H (throw away
136  lineStream >> token;
137 
138  // optimize(d)
139  lineStream >> token;
140  if (token != "optimize")
141  {
142  throw_parse_error(m_path, line, token, lineNumber);
143  }
144 
145  char optimized;
146  if (!(lineStream >> optimized))
147  {
148  throw_parse_error(m_path, line, token, lineNumber);
149  }
150 
151  if (optimized == 'Y' || std::tolower(optimized) == 'y')
152  {
153  m_optimized = true;
154  }
155  else if (optimized == 'N' || std::tolower(optimized) == 'n')
156  {
157  m_optimized = false;
158  }
159  else
160  {
161  throw_parse_error(m_path, line, token, lineNumber);
162  }
163 
164  // staggered (optional)
165  if (lineStream >> token && token == "staggered")
166  {
167  char staggered;
168  if (!(lineStream >> staggered))
169  {
170  throw_parse_error(m_path, line, token, lineNumber);
171  }
172 
173  if (staggered == 'Y' || std::tolower(staggered) == 'y')
174  {
175  m_staggered = Staggered::Yes;
176  }
177  else if (staggered == 'N' || std::tolower(staggered) == 'n')
178  {
179  m_staggered = Staggered::No;
180  }
181  else
182  {
183  throw_parse_error(m_path, line, token, lineNumber);
184  }
185  }
186  else
187  {
188  m_staggered = Staggered::Unknown;
189  }
190  }
191  else if (line.find(NetRecord::FIELD_TOKEN) == 0)
192  {
193  // net record line
194 
195  // net serial number
196  std::string token;
197  if (!(lineStream >> token))
198  {
199  throw_parse_error(m_path, line, token, lineNumber);
200  }
201 
202  auto strSerialNumber = token;
203  strSerialNumber.erase(0, 1); // remove leading '$'
204  auto ulSerialNumber = std::stoul(strSerialNumber);
205  if (ulSerialNumber > UINT_MAX)
206  {
207  throw_parse_error(m_path, line, token, lineNumber);
208  }
209 
210  auto unSerialNumber = static_cast<unsigned int>(ulSerialNumber);
211 
212  // net name
213  if (!(lineStream >> token))
214  {
215  throw_parse_error(m_path, line, token, lineNumber);
216  }
217 
218  auto& netName = token;
219 
220  auto pNetRecord = std::make_shared<NetRecord>();
221  pNetRecord->serialNumber = unSerialNumber;
222  pNetRecord->netName = netName;
223  m_netRecords.push_back(pNetRecord);
224  //m_netRecordsByName[pNetRecord->netName] = pNetRecord;
225  }
226  else // NetPointRecord (starts with an unsigned int, netNumber)
227  {
228  std::string token;
229  if (!(lineStream >> token))
230  {
231  throw_parse_error(m_path, line, token, lineNumber);
232  }
233 
234  auto ulNetNumber = std::stoul(token);
235  if (ulNetNumber >= UINT_MAX)
236  {
237  throw_parse_error(m_path, line, token, lineNumber);
238  }
239 
240  auto unNetNumber = static_cast<unsigned int>(ulNetNumber);
241 
242  auto pNetPointRecord = std::make_shared<NetPointRecord>();
243  pNetPointRecord->netNumber = unNetNumber;
244 
245  if (!(lineStream >> pNetPointRecord->radius))
246  {
247  throw_parse_error(m_path, line, token, lineNumber);
248  }
249 
250  if (!(lineStream >> pNetPointRecord->x))
251  {
252  throw_parse_error(m_path, line, token, lineNumber);
253  }
254 
255  if (!(lineStream >> pNetPointRecord->y))
256  {
257  throw_parse_error(m_path, line, token, lineNumber);
258  }
259 
260  // TODO: parse the rest of the NetPointRecord fields
261 
262  m_netPointRecords.push_back(pNetPointRecord);
263  }
264  }
265  }
266 
267  loginfo("Parsing netlist: " + m_name + " complete");
268 
269  netlistFile.close();
270  }
271  catch (parse_error& pe)
272  {
273  auto m = pe.toString("Parse Error:");
274  logerror(m);
275  // cleanup file
276  netlistFile.close();
277  throw pe;
278 
279  }
280  catch (std::exception& e)
281  {
282  parse_info pi(m_path, line, lineNumber);
283  const auto m = pi.toString();
284  logexception_msg(e, m);
285  netlistFile.close();
286  throw e;
287  }
288 
289  return true;
290  }
291 
292  std::unique_ptr<Odb::Lib::Protobuf::NetlistFile> NetlistFile::to_protobuf() const
293  {
294  std::unique_ptr<Odb::Lib::Protobuf::NetlistFile> pNetlistFileMessage(new Odb::Lib::Protobuf::NetlistFile);
295  pNetlistFileMessage->set_units(m_units);
296  pNetlistFileMessage->set_path(m_path.string());
297  pNetlistFileMessage->set_name(m_name);
298  pNetlistFileMessage->set_optimized(m_optimized);
299  pNetlistFileMessage->set_staggered(static_cast<Odb::Lib::Protobuf::NetlistFile::Staggered>(m_staggered));
300 
301  for (const auto& pNetRecord : m_netRecords)
302  {
303  auto pNetRecordMessage = pNetRecord->to_protobuf();
304  pNetlistFileMessage->add_netrecordss()->CopyFrom(*pNetRecordMessage);
305  }
306 
307  for (const auto& kvNetRecord : m_netRecordsByName)
308  {
309  (*pNetlistFileMessage->mutable_netrecordsbyname())[kvNetRecord.first] = *kvNetRecord.second->to_protobuf();
310  }
311 
312  for (const auto& pNetPointRecord : m_netPointRecords)
313  {
314  auto pNetPointRecordMessage = pNetPointRecord->to_protobuf();
315  pNetlistFileMessage->add_netpointrecords()->CopyFrom(*pNetPointRecordMessage);
316  }
317 
318  return pNetlistFileMessage;
319  }
320 
321  void NetlistFile::from_protobuf(const Odb::Lib::Protobuf::NetlistFile& message)
322  {
323  m_name = message.name();
324  m_path = message.path();
325  m_units = message.units();
326  m_optimized = message.optimized();
327  m_staggered = static_cast<Staggered>(message.staggered());
328 
329  for (const auto& netRecordMessage : message.netrecordss())
330  {
331  auto pNetRecord = std::make_shared<NetRecord>();
332  pNetRecord->from_protobuf(netRecordMessage);
333  m_netRecords.push_back(pNetRecord);
334  }
335 
336  for (const auto& kvNetRecord : message.netrecordsbyname())
337  {
338  auto pNetRecord = std::make_shared<NetRecord>();
339  pNetRecord->from_protobuf(kvNetRecord.second);
340  m_netRecordsByName[pNetRecord->netName] = pNetRecord;
341  }
342 
343  for (const auto& netPointRecordMessage : message.netpointrecords())
344  {
345  auto pNetPointRecord = std::make_shared<NetPointRecord>();
346  pNetPointRecord->from_protobuf(netPointRecordMessage);
347  m_netPointRecords.push_back(pNetPointRecord);
348  }
349  }
350 
351  std::unique_ptr<Odb::Lib::Protobuf::NetlistFile::NetRecord> NetlistFile::NetRecord::to_protobuf() const
352  {
353  std::unique_ptr<Odb::Lib::Protobuf::NetlistFile::NetRecord> pNetRecordMessage(new Odb::Lib::Protobuf::NetlistFile::NetRecord);
354  pNetRecordMessage->set_serialnumber(serialNumber);
355  pNetRecordMessage->set_netname(netName);
356  return pNetRecordMessage;
357  }
358 
359  void NetlistFile::NetRecord::from_protobuf(const Odb::Lib::Protobuf::NetlistFile::NetRecord& message)
360  {
361  serialNumber = message.serialnumber();
362  netName = message.netname();
363  }
364 
365  std::unique_ptr<Odb::Lib::Protobuf::NetlistFile::NetPointRecord> NetlistFile::NetPointRecord::to_protobuf() const
366  {
367  std::unique_ptr<Odb::Lib::Protobuf::NetlistFile::NetPointRecord> pNetPointRecordMessage(new Odb::Lib::Protobuf::NetlistFile::NetPointRecord);
368  pNetPointRecordMessage->set_netnumber(netNumber);
369  pNetPointRecordMessage->set_radius(radius);
370  pNetPointRecordMessage->set_x(x);
371  pNetPointRecordMessage->set_y(y);
372  pNetPointRecordMessage->set_epoint(std::to_string(epoint));
373  pNetPointRecordMessage->set_width(width);
374  pNetPointRecordMessage->set_exp(std::to_string(exp));
375  pNetPointRecordMessage->set_fiducialpoint(fiducialPoint);
376  pNetPointRecordMessage->set_height(height);
377  pNetPointRecordMessage->set_commentpoint(commentPoint);
378  pNetPointRecordMessage->set_netnumber(netNumber);
379  pNetPointRecordMessage->set_side(static_cast<Odb::Lib::Protobuf::NetlistFile::NetPointRecord::AccessSide>(side));
380  pNetPointRecordMessage->set_staggeredradius(staggeredRadius);
381  pNetPointRecordMessage->set_staggeredx(staggeredX);
382  pNetPointRecordMessage->set_staggeredy(staggeredY);
383  pNetPointRecordMessage->set_testexecutionside(std::to_string(testExecutionSide));
384  pNetPointRecordMessage->set_testpoint(testPoint);
385  pNetPointRecordMessage->set_viapoint(viaPoint);
386  pNetPointRecordMessage->set_fiducialpoint(fiducialPoint);
387  return pNetPointRecordMessage;
388  }
389 
390  void NetlistFile::NetPointRecord::from_protobuf(const Odb::Lib::Protobuf::NetlistFile::NetPointRecord& message)
391  {
392  netNumber = message.netnumber();
393  radius = message.radius();
394  x = message.x();
395  y = message.y();
396  if (message.epoint().empty())
397  {
398  epoint = message.epoint()[0];
399  }
400  width = message.width();
401  if (!message.exp().empty())
402  {
403  exp = message.exp()[0];
404  }
405  fiducialPoint = message.fiducialpoint();
406  height = message.height();
407  commentPoint = message.commentpoint();
408  netNumber = message.netnumber();
409  side = static_cast<AccessSide>(message.side());
410  staggeredRadius = message.staggeredradius();
411  staggeredX = message.staggeredx();
412  staggeredY = message.staggeredy();
413  if (!message.testexecutionside().empty())
414  {
415  testExecutionSide = message.testexecutionside()[0];
416  }
417  testPoint = message.testpoint();
418  viaPoint = message.viapoint();
419  fiducialPoint = message.fiducialpoint();
420  }
421 
422 
423 } // namespace Odb::Lib::FileModel::Design