HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
xdc_parser.cpp
Go to the documentation of this file.
2 #include "hal_core/netlist/net.h"
6 #include "xilinx_toolbox/types.h"
7 
8 #include <fstream>
9 #include <regex>
10 
11 namespace hal
12 {
13  namespace xilinx_toolbox
14  {
15  namespace
16  {
17  // TODO ignore comments
18  // TODO there is some weird escaping with curly braces happening
19  TokenStream<std::string> tokenize(std::stringstream& ss)
20  {
21  const std::string delimiters = " ";
22  std::string current_token;
23  u32 line_number = 0;
24 
25  std::string line;
26  bool escaped = false;
27 
28  std::vector<Token<std::string>> parsed_tokens;
29  while (std::getline(ss, line))
30  {
31  line_number++;
32 
33  for (char c : line)
34  {
35  // deal with escaping and strings
36  if (c == '\\')
37  {
38  escaped = true;
39  continue;
40  }
41  else if (escaped && std::isspace(c))
42  {
43  escaped = false;
44  continue;
45  }
46 
47  if (((!std::isspace(c) && delimiters.find(c) == std::string::npos) || escaped))
48  {
49  current_token += c;
50  }
51  else
52  {
53  if (!current_token.empty())
54  {
55  parsed_tokens.emplace_back(line_number, current_token);
56  current_token.clear();
57  }
58 
59  if (!std::isspace(c))
60  {
61  parsed_tokens.emplace_back(line_number, std::string(1, c));
62  }
63  }
64  }
65 
66  if (!current_token.empty())
67  {
68  parsed_tokens.emplace_back(line_number, current_token);
69  current_token.clear();
70  }
71  }
72 
73  return TokenStream(parsed_tokens, {}, {});
74  }
75 
76  Result<LOC> parse_LOC(TokenStream<std::string>& ts)
77  {
78  const auto loc_token = ts.consume();
79  std::string loc_str = loc_token.string;
80 
81  LOC new_loc;
82  new_loc.loc_name = loc_str;
83 
84  // test for pin names
85  const auto pin_pattern = std::regex("^[a-zA-Z]\\d+$");
86  std::smatch match;
87  if (std::regex_match(loc_str, match, pin_pattern))
88  {
89  return OK(new_loc);
90  }
91 
92  // test for slice type + x and y coordinates
93  const std::string loc_type_str = loc_str.substr(0, loc_str.find_first_of("_"));
94 
95  if (is_valid_enum<LOCType>(loc_type_str))
96  {
97  new_loc.loc_type = enum_from_string<LOCType>(loc_type_str);
98  }
99  else
100  {
101  return ERR("cannot parse LOC: encountered unknown LOC type '" + loc_type_str + "'" + " at line " + std::to_string(loc_token.number));
102  }
103 
104  loc_str = loc_str.substr(loc_type_str.size());
105  loc_str = loc_str.substr(std::string("_X").size());
106 
107  const std::string x_str = loc_str.substr(0, loc_str.find_first_of("Y"));
108 
109  loc_str = loc_str.substr(x_str.size());
110  loc_str = loc_str.substr(std::string("Y").size());
111 
112  const std::string y_str = loc_str;
113 
114  if (const auto res = utils::wrapped_stoull(x_str); res.is_ok())
115  {
116  new_loc.loc_x = res.get();
117  }
118  else
119  {
120  return ERR_APPEND(res.get_error(), "cannot parse LOC: failed to extract x position form " + loc_token.string + " at line " + std::to_string(loc_token.number));
121  }
122 
123  if (const auto res = utils::wrapped_stoull(y_str); res.is_ok())
124  {
125  new_loc.loc_y = res.get();
126  }
127  else
128  {
129  return ERR_APPEND(res.get_error(), "cannot parse LOC: failed to extract y position form " + loc_token.string + " at line " + std::to_string(loc_token.number));
130  }
131 
132  return OK(new_loc);
133  }
134 
135  Result<std::string> parse_single_cell(TokenStream<std::string>& ts)
136  {
137  const auto loc_token = ts.consume();
138  if (loc_token.string != "[get_cells")
139  {
140  return ERR("cannot parse cell name: expected token " + loc_token.string + " at line " + std::to_string(loc_token.number) + " to be exactly '[get_cells'");
141  }
142 
143  const auto cell_token = ts.consume();
144  std::string cell_str = cell_token.string;
145 
146  bool is_escpaed = cell_str.substr(0, 1) == "{" && cell_str.substr(cell_str.size() - 2, 1) == "}";
147 
148  if (cell_str.substr(cell_str.size() - 1, 1) != "]")
149  {
150  return ERR("cannot parse cell name: expected cell token '" + cell_str + " at line " + std::to_string(loc_token.number) + "' to end with ']'");
151  }
152 
153  cell_str = cell_str.substr(is_escpaed ? 1 : 0, cell_str.size() - (is_escpaed ? 2 : 1));
154 
155  return OK(cell_str);
156  }
157 
158  Result<std::unordered_map<std::string, CellData>> parse_tokens(TokenStream<std::string>& ts)
159  {
160  std::unordered_map<std::string, CellData> cell_data;
161 
162  while (true)
163  {
164  ts.consume_until("set_property");
165  if (ts.remaining() == 0)
166  {
167  break;
168  }
169 
170  ts.consume("set_property");
171 
172  if (ts.peek().string == "BEL")
173  {
174  ts.consume("BEL");
175 
176  const auto bel_type = enum_from_string<BELType>(ts.consume().string);
177 
178  if (const auto res = parse_single_cell(ts); res.is_ok())
179  {
180  cell_data[res.get()].bel_type = bel_type;
181  }
182  else
183  {
184  return ERR_APPEND(res.get_error(), "cannot parse xdc token stream: failed to extract cell name");
185  }
186  }
187  else if (ts.peek().string == "LOC")
188  {
189  ts.consume("LOC");
190 
191  LOC new_loc;
192  if (const auto res = parse_LOC(ts); res.is_ok())
193  {
194  new_loc = res.get();
195  }
196  else
197  {
198  return ERR_APPEND(res.get_error(), "cannot parse xdc token stream: failed to extract LOC");
199  }
200 
201  if (const auto res = parse_single_cell(ts); res.is_ok())
202  {
203  cell_data[res.get()].loc = new_loc;
204  }
205  else
206  {
207  return ERR_APPEND(res.get_error(), "cannot parse xdc token stream: failed to extract cell name");
208  }
209  }
210  else
211  {
212  ts.consume_current_line();
213  }
214  }
215 
216  return OK(cell_data);
217  }
218  } // namespace
219 
220  Result<std::monostate> parse_xdc_file(Netlist* nl, const std::filesystem::path& xdc_file)
221  {
222  return ERR("not implemented");
223 
224  // std::stringstream ss;
225  // std::ifstream ifs;
226  // ifs.open(xdc_file.string(), std::ifstream::in);
227  // if (!ifs.is_open())
228  // {
229  // return ERR("could not parse xdc file '" + xdc_file.string() + "' : unable to open file");
230  // }
231  // ss << ifs.rdbuf();
232  // ifs.close();
233 
234  // auto ts = xilinx_toolbox::tokenize(ss);
235 
236  // std::unordered_map<std::string, xilinx_toolbox::CellData> cell_data;
237  // // parse tokens
238  // try
239  // {
240  // if (auto res = xilinx_toolbox::parse_tokens(ts); res.is_error())
241  // {
242  // return ERR_APPEND(res.get_error(), "could not parse xdc '" + xdc_file.string() + "': unable to parse tokens");
243  // }
244  // else
245  // {
246  // cell_data = res.get();
247  // }
248  // }
249  // catch (TokenStream<std::string>::TokenStreamException& e)
250  // {
251  // if (e.line_number != (u32)-1)
252  // {
253  // return ERR("could not parse xdc '" + xdc_file.string() + "': " + e.message + " (line " + std::to_string(e.line_number) + ")");
254  // }
255  // else
256  // {
257  // return ERR("could not parse xdc '" + xdc_file.string() + "': " + e.message);
258  // }
259  // }
260 
261  // std::unordered_map<std::string, Gate*> gate_name_to_gate;
262  // for (const auto g : nl->get_gates())
263  // {
264  // gate_name_to_gate[g->get_name()] = g;
265  // }
266 
267  // for (const auto& [gate_name, cd] : cell_data)
268  // {
269  // if (const auto it = gate_name_to_gate.find(gate_name); it == gate_name_to_gate.end())
270  // {
271  // log_error("xilinx_toolbox", "Found gate name {} in xdc file but not in netlist!", gate_name);
272  // continue;
273  // }
274  // }
275 
276  // return OK({});
277  }
278  } // namespace xilinx_toolbox
279 } // namespace hal
u32 size
uint32_t u32
Definition: defines.h:41
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
#define ERR_APPEND(prev_error, message)
Definition: result.h:64
Result< u64 > wrapped_stoull(const std::string &s, const u32 base=10)
Definition: utils.cpp:696
Result< std::monostate > parse_xdc_file(Netlist *nl, const std::filesystem::path &xdc_file)
Parse an .xdc file and extract the position LOC and BEL data of each gate.
Definition: xdc_parser.cpp:220
Definition: defines.h:45
This file contains all functions related to the HAL plugin API.