1#include "NetlistFile.h"
2#include "NetlistFile.h"
4#include "../parse_error.h"
5#include "../invalid_odb_error.h"
9#include "../../Constants.h"
15#include "../parse_info.h"
16#include "netlistfile.pb.h"
17#include "../../Text/Utf8Sanitizer.h"
19using namespace std::filesystem;
21namespace Odb::Lib::FileModel::Design
23 NetlistFile::NetlistFile(std::filesystem::path path)
26 , m_staggered(Staggered::Unknown)
30 NetlistFile::~NetlistFile()
33 m_netRecordsByName.clear();
34 m_netPointRecords.clear();
37 std::filesystem::path NetlistFile::GetPath()
const
42 std::string NetlistFile::GetName()
const
47 std::string NetlistFile::GetUnits()
const
52 bool NetlistFile::GetOptimized()
const
57 NetlistFile::Staggered NetlistFile::GetStaggered()
const
62 const NetlistFile::NetRecord::Vector& NetlistFile::GetNetRecords()
const
67 const NetlistFile::NetRecord::StringMap& NetlistFile::GetNetRecordsByName()
const
69 return m_netRecordsByName;
72 const NetlistFile::NetPointRecord::Vector& NetlistFile::GetNetPointRecords()
const
74 return m_netPointRecords;
77 bool NetlistFile::Parse()
79 std::ifstream netlistFile;
85 m_name = std::filesystem::path(m_path).filename().string();
87 loginfo(
"Parsing netlist: " + m_name +
"...");
89 auto netlistFilePath = m_path /
"netlist";
91 if (!std::filesystem::exists(netlistFilePath))
93 auto message =
"netlist file does not exist: [" + m_path.string() +
"]";
94 throw invalid_odb_error(message.c_str());
97 else if (!std::filesystem::is_regular_file(netlistFilePath))
99 auto message =
"netlist file is not a file: [" + m_path.string() +
"]";
100 throw invalid_odb_error(message.c_str());
103 netlistFile.open(netlistFilePath.string(), std::ios::in);
104 if (!netlistFile.is_open())
106 auto message =
"unable to open netlist file: [" + m_path.string() +
"]";
107 throw invalid_odb_error(message.c_str());
110 while (std::getline(netlistFile, line))
115 std::stringstream lineStream(line);
117 if (line.find(Constants::COMMENT_TOKEN) == 0)
121 else if (line.find(Constants::UNITS_TOKEN) == 0)
125 if (!std::getline(lineStream, token,
'='))
127 throw_parse_error(m_path, line, token, lineNumber);
129 else if (!std::getline(lineStream, token,
'='))
131 throw_parse_error(m_path, line, token, lineNumber);
135 else if (line.find(HEADER_TOKEN) == 0)
145 if (token !=
"optimize")
147 throw_parse_error(m_path, line, token, lineNumber);
151 if (!(lineStream >> optimized))
153 throw_parse_error(m_path, line, token, lineNumber);
156 if (optimized ==
'Y' || std::tolower(optimized) ==
'y')
160 else if (optimized ==
'N' || std::tolower(optimized) ==
'n')
166 throw_parse_error(m_path, line, token, lineNumber);
170 if (lineStream >> token && token == STAGGERED_KEY)
173 if (!(lineStream >> staggered))
175 throw_parse_error(m_path, line, token, lineNumber);
178 if (staggered ==
'Y' || std::tolower(staggered) ==
'y')
180 m_staggered = Staggered::Yes;
182 else if (staggered ==
'N' || std::tolower(staggered) ==
'n')
184 m_staggered = Staggered::No;
188 throw_parse_error(m_path, line, token, lineNumber);
193 m_staggered = Staggered::Unknown;
196 else if (line.find(NetRecord::FIELD_TOKEN) == 0)
202 if (!(lineStream >> token))
204 throw_parse_error(m_path, line, token, lineNumber);
207 auto strSerialNumber = token;
208 strSerialNumber.erase(0, 1);
209 auto ulSerialNumber = std::stoul(strSerialNumber);
210 if (ulSerialNumber > UINT_MAX)
212 throw_parse_error(m_path, line, token, lineNumber);
215 auto unSerialNumber =
static_cast<unsigned int>(ulSerialNumber);
218 if (!(lineStream >> token))
220 throw_parse_error(m_path, line, token, lineNumber);
223 auto& netName = token;
225 auto pNetRecord = std::make_shared<NetRecord>();
226 pNetRecord->serialNumber = unSerialNumber;
227 pNetRecord->netName = netName;
228 m_netRecords.push_back(pNetRecord);
234 if (!(lineStream >> token))
236 throw_parse_error(m_path, line, token, lineNumber);
239 auto ulNetNumber = std::stoul(token);
240 if (ulNetNumber >= UINT_MAX)
242 throw_parse_error(m_path, line, token, lineNumber);
245 auto unNetNumber =
static_cast<unsigned int>(ulNetNumber);
247 auto pNetPointRecord = std::make_shared<NetPointRecord>();
248 pNetPointRecord->netNumber = unNetNumber;
250 if (!(lineStream >> pNetPointRecord->radius))
252 throw_parse_error(m_path, line, token, lineNumber);
255 if (!(lineStream >> pNetPointRecord->x))
257 throw_parse_error(m_path, line, token, lineNumber);
260 if (!(lineStream >> pNetPointRecord->y))
262 throw_parse_error(m_path, line, token, lineNumber);
267 m_netPointRecords.push_back(pNetPointRecord);
272 loginfo(
"Parsing netlist: " + m_name +
" complete");
276 catch (parse_error& pe)
278 auto m = pe.toString(
"Parse Error:");
285 catch (std::exception& e)
287 parse_info pi(m_path, line, lineNumber);
288 const auto m = pi.toString();
289 logexception_msg(e, m);
297 std::unique_ptr<Protobuf::NetlistFile> NetlistFile::to_protobuf()
const
299 std::unique_ptr<Protobuf::NetlistFile> pNetlistFileMessage(
new Protobuf::NetlistFile);
300 pNetlistFileMessage->set_units(Odb::Lib::Text::ToUtf8(m_units));
301 pNetlistFileMessage->set_path(Odb::Lib::Text::ToUtf8(m_path.string()));
302 pNetlistFileMessage->set_name(Odb::Lib::Text::ToUtf8(m_name));
303 pNetlistFileMessage->set_optimized(m_optimized);
304 pNetlistFileMessage->set_staggered(
static_cast<Protobuf::NetlistFile::Staggered
>(m_staggered));
306 for (
const auto& pNetRecord : m_netRecords)
308 auto pNetRecordMessage = pNetRecord->to_protobuf();
309 pNetlistFileMessage->add_netrecordss()->CopyFrom(*pNetRecordMessage);
312 for (
const auto& kvNetRecord : m_netRecordsByName)
314 (*pNetlistFileMessage->mutable_netrecordsbyname())[Odb::Lib::Text::ToUtf8(kvNetRecord.first)] = *kvNetRecord.second->to_protobuf();
317 for (
const auto& pNetPointRecord : m_netPointRecords)
319 auto pNetPointRecordMessage = pNetPointRecord->to_protobuf();
320 pNetlistFileMessage->add_netpointrecords()->CopyFrom(*pNetPointRecordMessage);
323 return pNetlistFileMessage;
326 void NetlistFile::from_protobuf(
const Protobuf::NetlistFile& message)
328 m_name = message.name();
329 m_path = message.path();
330 m_units = message.units();
331 m_optimized = message.optimized();
332 m_staggered =
static_cast<Staggered
>(message.staggered());
334 for (
const auto& netRecordMessage : message.netrecordss())
336 auto pNetRecord = std::make_shared<NetRecord>();
337 pNetRecord->from_protobuf(netRecordMessage);
338 m_netRecords.push_back(pNetRecord);
341 for (
const auto& kvNetRecord : message.netrecordsbyname())
343 auto pNetRecord = std::make_shared<NetRecord>();
344 pNetRecord->from_protobuf(kvNetRecord.second);
345 m_netRecordsByName[pNetRecord->netName] = pNetRecord;
348 for (
const auto& netPointRecordMessage : message.netpointrecords())
350 auto pNetPointRecord = std::make_shared<NetPointRecord>();
351 pNetPointRecord->from_protobuf(netPointRecordMessage);
352 m_netPointRecords.push_back(pNetPointRecord);
356 bool NetlistFile::Save(std::ostream& os)
358 os <<
'H' <<
" optimize " << (m_optimized ?
'Y' :
'N') <<
"staggered " << (m_staggered == Staggered::Yes ?
'Y' :
'N') << std::endl;
359 os << Constants::UNITS_TOKEN <<
" = " << m_units << std::endl;
361 for (
const auto& netRecord : m_netRecords)
363 os << NetRecord::FIELD_TOKEN << netRecord->serialNumber <<
" " << netRecord->netName << std::endl;
366 for (
const auto& netPointRecord : m_netPointRecords)
368 netPointRecord->Save(os);
375 bool NetlistFile::Save(
const std::filesystem::path& directory)
377 auto netlistDir = directory / m_name;
378 if (!create_directory(netlistDir))
return false;
380 std::ofstream netlistFile(netlistDir /
"netlist");
381 if (!netlistFile.is_open())
return false;
382 if (! Save(netlistFile))
return false;
388 std::unique_ptr<Protobuf::NetlistFile::NetRecord> NetlistFile::NetRecord::to_protobuf()
const
390 std::unique_ptr<Protobuf::NetlistFile::NetRecord> pNetRecordMessage(
new Protobuf::NetlistFile::NetRecord);
391 pNetRecordMessage->set_serialnumber(serialNumber);
392 pNetRecordMessage->set_netname(Odb::Lib::Text::ToUtf8(netName));
393 return pNetRecordMessage;
396 void NetlistFile::NetRecord::from_protobuf(
const Protobuf::NetlistFile::NetRecord& message)
398 serialNumber = message.serialnumber();
399 netName = message.netname();
402 std::unique_ptr<Protobuf::NetlistFile::NetPointRecord> NetlistFile::NetPointRecord::to_protobuf()
const
404 std::unique_ptr<Protobuf::NetlistFile::NetPointRecord> pNetPointRecordMessage(
new Protobuf::NetlistFile::NetPointRecord);
405 pNetPointRecordMessage->set_netnumber(netNumber);
406 pNetPointRecordMessage->set_radius(radius);
407 pNetPointRecordMessage->set_x(x);
408 pNetPointRecordMessage->set_y(y);
409 pNetPointRecordMessage->set_epoint(std::to_string(epoint));
410 pNetPointRecordMessage->set_width(width);
411 pNetPointRecordMessage->set_exp(std::to_string(exp));
412 pNetPointRecordMessage->set_fiducialpoint(fiducialPoint);
413 pNetPointRecordMessage->set_height(height);
414 pNetPointRecordMessage->set_commentpoint(commentPoint);
415 pNetPointRecordMessage->set_netnumber(netNumber);
416 pNetPointRecordMessage->set_side(
static_cast<Protobuf::NetlistFile::NetPointRecord::AccessSide
>(side));
417 pNetPointRecordMessage->set_staggeredradius(staggeredRadius);
418 pNetPointRecordMessage->set_staggeredx(staggeredX);
419 pNetPointRecordMessage->set_staggeredy(staggeredY);
420 pNetPointRecordMessage->set_testexecutionside(std::to_string(testExecutionSide));
421 pNetPointRecordMessage->set_testpoint(testPoint);
422 pNetPointRecordMessage->set_viapoint(viaPoint);
423 pNetPointRecordMessage->set_fiducialpoint(fiducialPoint);
424 return pNetPointRecordMessage;
427 void NetlistFile::NetPointRecord::from_protobuf(
const Protobuf::NetlistFile::NetPointRecord& message)
429 netNumber = message.netnumber();
430 radius = message.radius();
433 if (message.epoint().empty())
435 epoint = message.epoint()[0];
437 width = message.width();
438 if (!message.exp().empty())
440 exp = message.exp()[0];
442 fiducialPoint = message.fiducialpoint();
443 height = message.height();
444 commentPoint = message.commentpoint();
445 netNumber = message.netnumber();
446 side =
static_cast<AccessSide
>(message.side());
447 staggeredRadius = message.staggeredradius();
448 staggeredX = message.staggeredx();
449 staggeredY = message.staggeredy();
450 if (!message.testexecutionside().empty())
452 testExecutionSide = message.testexecutionside()[0];
454 testPoint = message.testpoint();
455 viaPoint = message.viapoint();
456 fiducialPoint = message.fiducialpoint();
459 bool NetlistFile::NetPointRecord::Save(std::ostream& os)