HAL
vhdl_parser.cpp
Go to the documentation of this file.
2 
3 #include "netlist_test_utils.h"
4 #include "gate_library_test_utils.h"
5 
6 #include <filesystem>
7 
8 namespace hal {
9 
10  class VHDLParserTest : public ::testing::Test {
11  protected:
12  virtual void SetUp()
13  {
14  NO_COUT_BLOCK;
15  test_utils::init_log_channels();
16  test_utils::create_sandbox_directory();
17  }
18 
19  virtual void TearDown()
20  {
21  test_utils::remove_sandbox_directory();
22  }
23  };
24 
25  /* net_0
26  * .--= INV (0) =------.
27  * net_global_in | '-= net_global_out
28  * ------------| .-= AND3 (2) = ----------
29  * | | =
30  * '--= |
31  * AND2 (1) =-----'
32  * = net_1
33  */
40  TEST_F(VHDLParserTest, check_main_example) {
41  TEST_START
42  std::string netlist_input("-- Device\t: device_name\n"
43  "library IEEE;\n"
44  "use IEEE.STD_LOGIC_1164.ALL;\n"
45  "library SIMPRIM;\n"
46  "use SIMPRIM.VCOMPONENTS.ALL;\n"
47  "use SIMPRIM.VPKG.ALL;\n"
48  "\n"
49  "entity TEST_Comp is\n"
50  " port (\n"
51  " net_global_in : in STD_LOGIC := 'X';\n"
52  " net_global_out : out STD_LOGIC := 'X';\n"
53  " );\n"
54  "end TEST_Comp;\n"
55  "\n"
56  "architecture STRUCTURE of TEST_Comp is\n"
57  " signal net_0 : STD_LOGIC;\n"
58  " signal net_1 : STD_LOGIC;\n"
59  "begin\n"
60  " gate_0 : BUF\n"
61  " port map (\n"
62  " I => net_global_in,\n"
63  " O => net_0\n"
64  " );\n"
65  " gate_1 : AND2\n"
66  " port map (\n"
67  " I0 => net_global_in,\n"
68  " I1 => net_global_in,\n"
69  " O => net_1\n"
70  " );\n"
71  " gate_2 : AND3\n"
72  " port map (\n"
73  " I0 => net_0,\n"
74  " I1 => net_1,\n"
75  " O => net_global_out\n"
76  " );\n"
77  "end STRUCTURE;\n"
78  "");
79  const GateLibrary* gate_lib = test_utils::get_gate_library();
80  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
81  VHDLParser vhdl_parser;
82  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
83  ASSERT_TRUE(nl_res.is_ok());
84  std::unique_ptr<Netlist> nl = nl_res.get();
85  ASSERT_NE(nl, nullptr);
86 
87  // Check if the device name is parsed correctly
88  EXPECT_EQ(nl->get_design_name(), "TEST_Comp");
89 
90  // Check if the gates are parsed correctly
91  ASSERT_EQ(nl->get_gates(test_utils::gate_type_filter("BUF")).size(), 1);
92  Gate* gate_0 = *(nl->get_gates(test_utils::gate_type_filter("BUF")).begin());
93  ASSERT_EQ(nl->get_gates(test_utils::gate_type_filter("AND2")).size(), 1);
94  Gate* gate_1 = *(nl->get_gates(test_utils::gate_type_filter("AND2")).begin());
95  ASSERT_EQ(nl->get_gates(test_utils::gate_type_filter("AND3")).size(), 1);
96  Gate* gate_2 = *(nl->get_gates(test_utils::gate_type_filter("AND3")).begin());
97 
98  ASSERT_NE(gate_0, nullptr);
99  EXPECT_EQ(gate_0->get_name(), "gate_0");
100 
101  ASSERT_NE(gate_1, nullptr);
102  EXPECT_EQ(gate_1->get_name(), "gate_1");
103 
104  ASSERT_NE(gate_2, nullptr);
105  EXPECT_EQ(gate_2->get_name(), "gate_2");
106 
107  // Check if the nets are parsed correctly
108  Net* net_0 = *(nl->get_nets(test_utils::net_name_filter("net_0")).begin());
109  Net* net_1 = *(nl->get_nets(test_utils::net_name_filter("net_1")).begin());
110  Net* net_global_in = *(nl->get_nets(test_utils::net_name_filter("net_global_in")).begin());
111  Net*
112  net_global_out = *(nl->get_nets(test_utils::net_name_filter("net_global_out")).begin());
113 
114  ASSERT_NE(net_0, nullptr);
115  EXPECT_EQ(net_0->get_name(), "net_0");
116  ASSERT_EQ(net_0->get_sources().size(), 1);
117  EXPECT_EQ(net_0->get_sources()[0], test_utils::get_endpoint(gate_0, "O"));
118  std::vector<Endpoint*> exp_net_0_dsts = {test_utils::get_endpoint(gate_2, "I0")};
120  std::vector<Endpoint*>({test_utils::get_endpoint(gate_2,
121  "I0")})));
122 
123  ASSERT_NE(net_1, nullptr);
124  EXPECT_EQ(net_1->get_name(), "net_1");
125  ASSERT_EQ(net_1->get_sources().size(), 1);
126  EXPECT_EQ(net_1->get_sources()[0], test_utils::get_endpoint(gate_1, "O"));
128  std::vector<Endpoint*>({test_utils::get_endpoint(gate_2,
129  "I1")})));
130 
131  ASSERT_NE(net_global_in, nullptr);
132  EXPECT_EQ(net_global_in->get_name(), "net_global_in");
133  EXPECT_EQ(net_global_in->get_sources().size(), 0);
134  EXPECT_TRUE(test_utils::vectors_have_same_content(net_global_in->get_destinations(),
135  std::vector<Endpoint*>({test_utils::get_endpoint(gate_0,
136  "I"),
137  test_utils::get_endpoint(gate_1,
138  "I0"),
139  test_utils::get_endpoint(gate_1,
140  "I1")})));
141  EXPECT_TRUE(nl->is_global_input_net(net_global_in));
142 
143  ASSERT_NE(net_global_out, nullptr);
144  EXPECT_EQ(net_global_out->get_name(), "net_global_out");
145  ASSERT_EQ(net_global_out->get_sources().size(), 1);
146  EXPECT_EQ(net_global_out->get_sources()[0], test_utils::get_endpoint(gate_2, "O"));
147  EXPECT_TRUE(net_global_out->get_destinations().empty());
148  EXPECT_TRUE(nl->is_global_output_net(net_global_out));
149 
150  EXPECT_EQ(nl->get_global_input_nets().size(), 1);
151  EXPECT_EQ(nl->get_global_output_nets().size(), 1);
152 
153  TEST_END
154  }
155 
161  TEST_F(VHDLParserTest, check_whitespace_chaos_) {
162 
163  TEST_START
164  {
165  std::string netlist_input("-- Device\t: device_name\n"
166  "library IEEE;use IEEE.STD_LOGIC_1164.ALL;library SIMPRIM;\n"
167  "use SIMPRIM.VCOMPONENTS.ALL;use SIMPRIM.VPKG.ALL;\n"
168  "entity TEST_Comp is port(net_global_in:in STD_LOGIC := 'X';net_global_out\n"
169  "\n"
170  " : out STD_LOGIC := 'X';);end TEST_Comp;architecture \n"
171  " STRUCTURE of TEST_Comp is signal net_0 : STD_LOGIC;\n"
172  "signal net_1 : STD_LOGIC;\n"
173  "begin gate_0 : BUF port map(\n"
174  " I => net_global_in,\n"
175  " \n"
176  " \t O => net_0\n"
177  " );\n"
178  " gate_1 : AND2\n"
179  " port map ( I0 \n\t"
180  " => net_global_in\n"
181  " \t,\n"
182  " I1 => net_global_in,O => net_1);\n"
183  "gate_2:AND3 port map(I0 => net_0,I1 => net_1,O => net_global_out);end STRUCTURE;");
184  const GateLibrary* gate_lib = test_utils::get_gate_library();
185  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
186  VHDLParser vhdl_parser;
187  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
188  ASSERT_TRUE(nl_res.is_ok());
189  std::unique_ptr<Netlist> nl = nl_res.get();
190  ASSERT_NE(nl, nullptr);
191 
192  // Check if the gates are parsed correctly
193  ASSERT_EQ(nl->get_gates(test_utils::gate_type_filter("BUF")).size(), 1);
194  Gate* gate_0 = *(nl->get_gates(test_utils::gate_type_filter("BUF")).begin());
195  ASSERT_EQ(nl->get_gates(test_utils::gate_type_filter("AND2")).size(), 1);
196  Gate* gate_1 = *(nl->get_gates(test_utils::gate_type_filter("AND2")).begin());
197  ASSERT_EQ(nl->get_gates(test_utils::gate_type_filter("AND3")).size(), 1);
198  Gate* gate_2 = *(nl->get_gates(test_utils::gate_type_filter("AND3")).begin());
199 
200  ASSERT_NE(gate_0, nullptr);
201  EXPECT_EQ(gate_0->get_name(), "gate_0");
202 
203  ASSERT_NE(gate_1, nullptr);
204  EXPECT_EQ(gate_1->get_name(), "gate_1");
205 
206  ASSERT_NE(gate_2, nullptr);
207  EXPECT_EQ(gate_2->get_name(), "gate_2");
208 
209  // Check if the nets are parsed correctly
210  Net* net_0 = *(nl->get_nets(test_utils::net_name_filter("net_0")).begin());
211  Net* net_1 = *(nl->get_nets(test_utils::net_name_filter("net_1")).begin());
212  Net*
213  net_global_in = *(nl->get_nets(test_utils::net_name_filter("net_global_in")).begin());
214  Net*
215  net_global_out = *(nl->get_nets(test_utils::net_name_filter("net_global_out")).begin());
216 
217  ASSERT_NE(net_0, nullptr);
218  EXPECT_EQ(net_0->get_name(), "net_0");
219  ASSERT_EQ(net_0->get_sources().size(), 1);
220  EXPECT_EQ(net_0->get_sources()[0], test_utils::get_endpoint(gate_0, "O"));
221  std::vector<Endpoint*> exp_net_0_dsts = {test_utils::get_endpoint(gate_2, "I0")};
223  std::vector<Endpoint*>({test_utils::get_endpoint(gate_2,
224  "I0")})));
225 
226  ASSERT_NE(net_1, nullptr);
227  EXPECT_EQ(net_1->get_name(), "net_1");
228  ASSERT_EQ(net_1->get_sources().size(), 1);
229  EXPECT_EQ(net_1->get_sources()[0], test_utils::get_endpoint(gate_1, "O"));
231  std::vector<Endpoint*>({test_utils::get_endpoint(gate_2,
232  "I1")})));
233 
234  ASSERT_NE(net_global_in, nullptr);
235  EXPECT_EQ(net_global_in->get_name(), "net_global_in");
236  EXPECT_EQ(net_global_in->get_sources().size(), 0);
237  EXPECT_TRUE(test_utils::vectors_have_same_content(net_global_in->get_destinations(),
238  std::vector<Endpoint*>({test_utils::get_endpoint(gate_0,
239  "I"),
240  test_utils::get_endpoint(gate_1,
241  "I0"),
242  test_utils::get_endpoint(gate_1,
243  "I1")})));
244  EXPECT_TRUE(nl->is_global_input_net(net_global_in));
245 
246  ASSERT_NE(net_global_out, nullptr);
247  EXPECT_EQ(net_global_out->get_name(), "net_global_out");
248  ASSERT_EQ(net_global_out->get_sources().size(), 1);
249  EXPECT_EQ(net_global_out->get_sources()[0], test_utils::get_endpoint(gate_2, "O"));
250  EXPECT_TRUE(net_global_out->get_destinations().empty());
251  EXPECT_TRUE(nl->is_global_output_net(net_global_out));
252 
253  EXPECT_EQ(nl->get_global_input_nets().size(), 1);
254  EXPECT_EQ(nl->get_global_output_nets().size(), 1);
255  }
256  TEST_END
257  }
258 
264  TEST_F(VHDLParserTest, check_pin_assignments) {
265 
266  TEST_START
267  { // test gate pin assignment by name
269 
270  std::string netlist_input(
271  "entity top is "
272  " port ( "
273  " a, b : in STD_LOGIC; "
274  " c : out STD_LOGIC; "
275  " ); "
276  "end top; "
277  "\n"
278  "architecture top_arch of top is "
279  "begin "
280  " gate_0 : AND2 "
281  " port map ( "
282  " I0 => a, "
283  " I1 => b, "
284  " O => c "
285  " ); "
286  " gate_1 : AND2 "
287  " port map ( "
288  " I1 => b, "
289  " O => c "
290  " ); "
291  " gate_2 : AND2 "
292  " port map ( "
293  " O => c "
294  " ); "
295  "end top_arch;");
296 
297  const GateLibrary* gate_lib = test_utils::get_gate_library();
298  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
299  VHDLParser vhdl_parser;
300  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
301  ASSERT_TRUE(nl_res.is_ok());
302  std::unique_ptr<Netlist> nl = nl_res.get();
303  ASSERT_NE(nl, nullptr);
304 
305  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_0")).size(), 1);
306  Gate* gate_0 = nl->get_gates(test_utils::gate_filter("AND2", "gate_0")).front();
307  EXPECT_EQ(gate_0->get_fan_in_endpoint("I0")->get_net()->get_name(), "a");
308  EXPECT_EQ(gate_0->get_fan_in_endpoint("I1")->get_net()->get_name(), "b");
309  EXPECT_EQ(gate_0->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
310 
311  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_1")).size(), 1);
312  Gate* gate_1 = nl->get_gates(test_utils::gate_filter("AND2", "gate_1")).front();
313  EXPECT_EQ(gate_1->get_fan_in_endpoint("I0"), nullptr);
314  EXPECT_EQ(gate_1->get_fan_in_endpoint("I1")->get_net()->get_name(), "b");
315  EXPECT_EQ(gate_1->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
316 
317  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_2")).size(), 1);
318  Gate* gate_2 = nl->get_gates(test_utils::gate_filter("AND2", "gate_2")).front();
319  EXPECT_EQ(gate_2->get_fan_in_endpoint("I0"), nullptr);
320  EXPECT_EQ(gate_2->get_fan_in_endpoint("I1"), nullptr);
321  EXPECT_EQ(gate_2->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
322  }
323  { // test gate pin assignment by name with open pins
325 
326  std::string netlist_input(
327  "entity top is "
328  " port ( "
329  " a, b : in STD_LOGIC; "
330  " c : out STD_LOGIC; "
331  " ); "
332  "end top; "
333  "\n"
334  "architecture top_arch of top is "
335  "begin "
336  " gate_0 : AND2 "
337  " port map ( "
338  " I0 => a, "
339  " I1 => b, "
340  " O => c "
341  " ); "
342  " gate_1 : AND2 "
343  " port map ( "
344  " I0 => open, "
345  " I1 => b, "
346  " O => c "
347  " ); "
348  " gate_2 : AND2 "
349  " port map ( "
350  " I0 => open, "
351  " I1 => open, "
352  " O => c "
353  " ); "
354  "end top_arch;");
355 
356  const GateLibrary* gate_lib = test_utils::get_gate_library();
357  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
358  VHDLParser vhdl_parser;
359  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
360  ASSERT_TRUE(nl_res.is_ok());
361  std::unique_ptr<Netlist> nl = nl_res.get();
362  ASSERT_NE(nl, nullptr);
363 
364  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_0")).size(), 1);
365  Gate* gate_0 = nl->get_gates(test_utils::gate_filter("AND2", "gate_0")).front();
366  EXPECT_EQ(gate_0->get_fan_in_endpoint("I0")->get_net()->get_name(), "a");
367  EXPECT_EQ(gate_0->get_fan_in_endpoint("I1")->get_net()->get_name(), "b");
368  EXPECT_EQ(gate_0->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
369 
370  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_1")).size(), 1);
371  Gate* gate_1 = nl->get_gates(test_utils::gate_filter("AND2", "gate_1")).front();
372  EXPECT_EQ(gate_1->get_fan_in_endpoint("I0"), nullptr);
373  EXPECT_EQ(gate_1->get_fan_in_endpoint("I1")->get_net()->get_name(), "b");
374  EXPECT_EQ(gate_1->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
375 
376  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_2")).size(), 1);
377  Gate* gate_2 = nl->get_gates(test_utils::gate_filter("AND2", "gate_2")).front();
378  EXPECT_EQ(gate_2->get_fan_in_endpoint("I0"), nullptr);
379  EXPECT_EQ(gate_2->get_fan_in_endpoint("I1"), nullptr);
380  EXPECT_EQ(gate_2->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
381  }
382  { // test gate pin assignment by order
384 
385  std::string netlist_input(
386  "entity top is "
387  " port ( "
388  " a, b : in STD_LOGIC; "
389  " c : out STD_LOGIC; "
390  " ); "
391  "end top; "
392  "\n"
393  "architecture top_arch of top is "
394  "begin "
395  " gate_0 : AND2 port map (a, b, c); "
396  " gate_1 : AND2 port map (a, b); "
397  " gate_2 : AND2 port map (a); "
398  "end top_arch;");
399 
400  const GateLibrary* gate_lib = test_utils::get_gate_library();
401  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
402  VHDLParser vhdl_parser;
403  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
404  ASSERT_TRUE(nl_res.is_ok());
405  std::unique_ptr<Netlist> nl = nl_res.get();
406  ASSERT_NE(nl, nullptr);
407 
408  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_0")).size(), 1);
409  Gate* gate_0 = nl->get_gates(test_utils::gate_filter("AND2", "gate_0")).front();
410  EXPECT_EQ(gate_0->get_fan_in_endpoint("I0")->get_net()->get_name(), "a");
411  EXPECT_EQ(gate_0->get_fan_in_endpoint("I1")->get_net()->get_name(), "b");
412  EXPECT_EQ(gate_0->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
413 
414  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_1")).size(), 1);
415  Gate* gate_1 = nl->get_gates(test_utils::gate_filter("AND2", "gate_1")).front();
416  EXPECT_EQ(gate_1->get_fan_in_endpoint("I0")->get_net()->get_name(), "a");
417  EXPECT_EQ(gate_1->get_fan_in_endpoint("I1")->get_net()->get_name(), "b");
418  EXPECT_EQ(gate_1->get_fan_out_endpoint("O"), nullptr);
419 
420  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_2")).size(), 1);
421  Gate* gate_2 = nl->get_gates(test_utils::gate_filter("AND2", "gate_2")).front();
422  EXPECT_EQ(gate_2->get_fan_in_endpoint("I0")->get_net()->get_name(), "a");
423  EXPECT_EQ(gate_2->get_fan_in_endpoint("I1"), nullptr);
424  EXPECT_EQ(gate_2->get_fan_out_endpoint("O"), nullptr);
425  }
426  { // test gate pin assignment by order with open pins
428 
429  std::string netlist_input(
430  "entity top is "
431  " port ( "
432  " a, b : in STD_LOGIC; "
433  " c : out STD_LOGIC; "
434  " ); "
435  "end top; "
436  "\n"
437  "architecture top_arch of top is "
438  "begin "
439  " gate_0 : AND2 port map (a, b, c); "
440  " gate_1 : AND2 port map (open, b, c); "
441  " gate_2 : AND2 port map (open, open, c); "
442  "end top_arch;");
443 
444  const GateLibrary* gate_lib = test_utils::get_gate_library();
445  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
446  VHDLParser vhdl_parser;
447  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
448  ASSERT_TRUE(nl_res.is_ok());
449  std::unique_ptr<Netlist> nl = nl_res.get();
450  ASSERT_NE(nl, nullptr);
451 
452  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_0")).size(), 1);
453  Gate* gate_0 = nl->get_gates(test_utils::gate_filter("AND2", "gate_0")).front();
454  EXPECT_EQ(gate_0->get_fan_in_endpoint("I0")->get_net()->get_name(), "a");
455  EXPECT_EQ(gate_0->get_fan_in_endpoint("I1")->get_net()->get_name(), "b");
456  EXPECT_EQ(gate_0->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
457 
458  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_1")).size(), 1);
459  Gate* gate_1 = nl->get_gates(test_utils::gate_filter("AND2", "gate_1")).front();
460  EXPECT_EQ(gate_1->get_fan_in_endpoint("I0"), nullptr);
461  EXPECT_EQ(gate_1->get_fan_in_endpoint("I1")->get_net()->get_name(), "b");
462  EXPECT_EQ(gate_1->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
463 
464  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND2", "gate_2")).size(), 1);
465  Gate* gate_2 = nl->get_gates(test_utils::gate_filter("AND2", "gate_2")).front();
466  EXPECT_EQ(gate_2->get_fan_in_endpoint("I0"), nullptr);
467  EXPECT_EQ(gate_2->get_fan_in_endpoint("I1"), nullptr);
468  EXPECT_EQ(gate_2->get_fan_out_endpoint("O")->get_net()->get_name(), "c");
469  }
470  { // test module pin assignment by name
472 
473  std::string netlist_input(
474  "entity sub_mod is "
475  " port ( "
476  " as, bs : in STD_LOGIC; "
477  " cs : out STD_LOGIC; "
478  " ); "
479  "end sub_mod; "
480  "\n"
481  "architecture sub_arch of sub_mod is "
482  "begin "
483  " gate_0 : AND2 "
484  " port map ( "
485  " I0 => as, "
486  " I1 => bs, "
487  " O => cs "
488  " ); "
489  "end sub_arch;"
490  "\n"
491  "entity top is "
492  " port ( "
493  " a, b : in STD_LOGIC; "
494  " c : out STD_LOGIC; "
495  " ); "
496  "end top; "
497  "\n"
498  "architecture top_arch of top is "
499  "begin "
500  " inst_0 : sub_mod "
501  " port map ( "
502  " as => a, "
503  " bs => b, "
504  " cs => c "
505  " ); "
506  " inst_1 : sub_mod "
507  " port map ( "
508  " bs => b, "
509  " cs => c "
510  " ); "
511  " inst_2 : sub_mod "
512  " port map ( "
513  " cs => c "
514  " ); "
515  "end top_arch;");
516 
517  const GateLibrary* gate_lib = test_utils::get_gate_library();
518  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
519  VHDLParser vhdl_parser;
520  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
521  ASSERT_TRUE(nl_res.is_ok());
522  std::unique_ptr<Netlist> nl = nl_res.get();
523  ASSERT_NE(nl, nullptr);
524 
525  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_0")).size(), 1);
526  Module* inst_0 = nl->get_modules(test_utils::module_name_filter("inst_0")).front();
527  const auto pins_0 = inst_0->get_pins();
528  EXPECT_EQ(pins_0.size(), 3);
529  EXPECT_EQ(pins_0.at(0)->get_name(), "as");
530  EXPECT_EQ(pins_0.at(0)->get_net()->get_name(), "a");
531  EXPECT_EQ(pins_0.at(1)->get_name(), "bs");
532  EXPECT_EQ(pins_0.at(1)->get_net()->get_name(), "b");
533  EXPECT_EQ(pins_0.at(2)->get_name(), "cs");
534  EXPECT_EQ(pins_0.at(2)->get_net()->get_name(), "c");
535 
536  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_1")).size(), 1);
537  Module* inst_1 = nl->get_modules(test_utils::module_name_filter("inst_1")).front();
538  const auto pins_1 = inst_1->get_pins();
539  EXPECT_EQ(pins_1.size(), 2);
540  EXPECT_EQ(pins_1.at(0)->get_name(), "bs");
541  EXPECT_EQ(pins_1.at(0)->get_net()->get_name(), "b");
542  EXPECT_EQ(pins_1.at(1)->get_name(), "cs");
543  EXPECT_EQ(pins_1.at(1)->get_net()->get_name(), "c");
544 
545  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_2")).size(), 1);
546  Module* inst_2 = nl->get_modules(test_utils::module_name_filter("inst_2")).front();
547  const auto pins_2 = inst_2->get_pins();
548  EXPECT_EQ(pins_2.size(), 1);
549  EXPECT_EQ(pins_2.at(0)->get_name(), "cs");
550  EXPECT_EQ(pins_2.at(0)->get_net()->get_name(), "c");
551  }
552  { // test module pin assignment by name with open pins
554 
555  std::string netlist_input(
556  "entity sub_mod is "
557  " port ( "
558  " as, bs : in STD_LOGIC; "
559  " cs : out STD_LOGIC; "
560  " ); "
561  "end sub_mod; "
562  "\n"
563  "architecture sub_arch of sub_mod is "
564  "begin "
565  " gate_0 : AND2 "
566  " port map ( "
567  " I0 => as, "
568  " I1 => bs, "
569  " O => cs "
570  " ); "
571  "end sub_arch;"
572  "\n"
573  "entity top is "
574  " port ( "
575  " a, b : in STD_LOGIC; "
576  " c : out STD_LOGIC; "
577  " ); "
578  "end top; "
579  "\n"
580  "architecture top_arch of top is "
581  "begin "
582  " inst_0 : sub_mod "
583  " port map ( "
584  " as => a, "
585  " bs => b, "
586  " cs => c "
587  " ); "
588  " inst_1 : sub_mod "
589  " port map ( "
590  " as => open, "
591  " bs => b, "
592  " cs => c "
593  " ); "
594  " inst_2 : sub_mod "
595  " port map ( "
596  " as => open, "
597  " bs => open, "
598  " cs => c "
599  " ); "
600  "end top_arch;");
601 
602  const GateLibrary* gate_lib = test_utils::get_gate_library();
603  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
604  VHDLParser vhdl_parser;
605  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
606  ASSERT_TRUE(nl_res.is_ok());
607  std::unique_ptr<Netlist> nl = nl_res.get();
608  ASSERT_NE(nl, nullptr);
609 
610  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_0")).size(), 1);
611  Module* inst_0 = nl->get_modules(test_utils::module_name_filter("inst_0")).front();
612  const auto pins_0 = inst_0->get_pins();
613  EXPECT_EQ(pins_0.size(), 3);
614  EXPECT_EQ(pins_0.at(0)->get_name(), "as");
615  EXPECT_EQ(pins_0.at(0)->get_net()->get_name(), "a");
616  EXPECT_EQ(pins_0.at(1)->get_name(), "bs");
617  EXPECT_EQ(pins_0.at(1)->get_net()->get_name(), "b");
618  EXPECT_EQ(pins_0.at(2)->get_name(), "cs");
619  EXPECT_EQ(pins_0.at(2)->get_net()->get_name(), "c");
620 
621  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_1")).size(), 1);
622  Module* inst_1 = nl->get_modules(test_utils::module_name_filter("inst_1")).front();
623  const auto pins_1 = inst_1->get_pins();
624  EXPECT_EQ(pins_1.size(), 2);
625  EXPECT_EQ(pins_1.at(0)->get_name(), "bs");
626  EXPECT_EQ(pins_1.at(0)->get_net()->get_name(), "b");
627  EXPECT_EQ(pins_1.at(1)->get_name(), "cs");
628  EXPECT_EQ(pins_1.at(1)->get_net()->get_name(), "c");
629 
630  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_2")).size(), 1);
631  Module* inst_2 = nl->get_modules(test_utils::module_name_filter("inst_2")).front();
632  const auto pins_2 = inst_2->get_pins();
633  EXPECT_EQ(pins_2.size(), 1);
634  EXPECT_EQ(pins_2.at(0)->get_name(), "cs");
635  EXPECT_EQ(pins_2.at(0)->get_net()->get_name(), "c");
636  }
637  { // test module pin assignment by order
639 
640  std::string netlist_input(
641  "entity sub_mod is "
642  " port ( "
643  " as, bs : in STD_LOGIC; "
644  " cs : out STD_LOGIC; "
645  " ); "
646  "end sub_mod; "
647  "\n"
648  "architecture sub_arch of sub_mod is "
649  "begin "
650  " gate_0 : AND2 port map (as, bs, cs); "
651  "end sub_arch;"
652  "\n"
653  "entity top is "
654  " port ( "
655  " a, b : in STD_LOGIC; "
656  " c : out STD_LOGIC; "
657  " ); "
658  "end top; "
659  "\n"
660  "architecture top_arch of top is "
661  "begin "
662  " inst_0 : sub_mod port map (a, b, c); "
663  " inst_1 : sub_mod port map (a, b); "
664  " inst_2 : sub_mod port map (a); "
665  "end top_arch;");
666 
667  const GateLibrary* gate_lib = test_utils::get_gate_library();
668  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
669  VHDLParser vhdl_parser;
670  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
671  ASSERT_TRUE(nl_res.is_ok());
672  std::unique_ptr<Netlist> nl = nl_res.get();
673  ASSERT_NE(nl, nullptr);
674 
675  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_0")).size(), 1);
676  Module* inst_0 = nl->get_modules(test_utils::module_name_filter("inst_0")).front();
677  const auto pins_0 = inst_0->get_pins();
678  EXPECT_EQ(pins_0.size(), 3);
679  EXPECT_EQ(pins_0.at(0)->get_name(), "as");
680  EXPECT_EQ(pins_0.at(0)->get_net()->get_name(), "a");
681  EXPECT_EQ(pins_0.at(1)->get_name(), "bs");
682  EXPECT_EQ(pins_0.at(1)->get_net()->get_name(), "b");
683  EXPECT_EQ(pins_0.at(2)->get_name(), "cs");
684  EXPECT_EQ(pins_0.at(2)->get_net()->get_name(), "c");
685 
686  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_1")).size(), 1);
687  Module* inst_1 = nl->get_modules(test_utils::module_name_filter("inst_1")).front();
688  const auto pins_1 = inst_1->get_pins();
689  EXPECT_EQ(pins_1.size(), 2);
690  EXPECT_EQ(pins_1.at(0)->get_name(), "as");
691  EXPECT_EQ(pins_1.at(0)->get_net()->get_name(), "a");
692  EXPECT_EQ(pins_1.at(1)->get_name(), "bs");
693  EXPECT_EQ(pins_1.at(1)->get_net()->get_name(), "b");
694 
695  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_2")).size(), 1);
696  Module* inst_2 = nl->get_modules(test_utils::module_name_filter("inst_2")).front();
697  const auto pins_2 = inst_2->get_pins();
698  EXPECT_EQ(pins_2.size(), 1);
699  EXPECT_EQ(pins_2.at(0)->get_name(), "as");
700  EXPECT_EQ(pins_2.at(0)->get_net()->get_name(), "a");
701  }
702  { // test module pin assignment by order with open pins
704 
705  std::string netlist_input("entity sub_mod is "
706  " port ( "
707  " as, bs : in STD_LOGIC; "
708  " cs : out STD_LOGIC; "
709  " ); "
710  "end sub_mod; "
711  "\n"
712  "architecture sub_arch of sub_mod is "
713  "begin "
714  " gate_0 : AND2 port map (as, bs, cs); "
715  "end sub_arch;"
716  "\n"
717  "entity top is "
718  " port ( "
719  " a, b : in STD_LOGIC; "
720  " c : out STD_LOGIC; "
721  " ); "
722  "end top; "
723  "\n"
724  "architecture top_arch of top is "
725  "begin "
726  " inst_0 : sub_mod port map (a, b, c); "
727  " inst_1 : sub_mod port map (open, b, c); "
728  " inst_2 : sub_mod port map (open, open, c); "
729  "end top_arch;");
730 
731  const GateLibrary* gate_lib = test_utils::get_gate_library();
732  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
733  VHDLParser vhdl_parser;
734  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
735  ASSERT_TRUE(nl_res.is_ok());
736  std::unique_ptr<Netlist> nl = nl_res.get();
737  ASSERT_NE(nl, nullptr);
738 
739  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_0")).size(), 1);
740  Module* inst_0 = nl->get_modules(test_utils::module_name_filter("inst_0")).front();
741  const auto pins_0 = inst_0->get_pins();
742  EXPECT_EQ(pins_0.size(), 3);
743  EXPECT_EQ(pins_0.at(0)->get_name(), "as");
744  EXPECT_EQ(pins_0.at(0)->get_net()->get_name(), "a");
745  EXPECT_EQ(pins_0.at(1)->get_name(), "bs");
746  EXPECT_EQ(pins_0.at(1)->get_net()->get_name(), "b");
747  EXPECT_EQ(pins_0.at(2)->get_name(), "cs");
748  EXPECT_EQ(pins_0.at(2)->get_net()->get_name(), "c");
749 
750  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_1")).size(), 1);
751  Module* inst_1 = nl->get_modules(test_utils::module_name_filter("inst_1")).front();
752  const auto pins_1 = inst_1->get_pins();
753  EXPECT_EQ(pins_1.size(), 2);
754  EXPECT_EQ(pins_1.at(0)->get_name(), "bs");
755  EXPECT_EQ(pins_1.at(0)->get_net()->get_name(), "b");
756  EXPECT_EQ(pins_1.at(1)->get_name(), "cs");
757  EXPECT_EQ(pins_1.at(1)->get_net()->get_name(), "c");
758 
759  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_2")).size(), 1);
760  Module* inst_2 = nl->get_modules(test_utils::module_name_filter("inst_2")).front();
761  const auto pins_2 = inst_2->get_pins();
762  EXPECT_EQ(pins_2.size(), 1);
763  EXPECT_EQ(pins_2.at(0)->get_name(), "cs");
764  EXPECT_EQ(pins_2.at(0)->get_net()->get_name(), "c");
765  }
766  { // test pass-through module
768 
769  std::string netlist_input(
770  "entity sub_sub_mod is "
771  " port ( "
772  " ass, bss : in STD_LOGIC; "
773  " css : out STD_LOGIC; "
774  " ); "
775  "end sub_sub_mod; "
776  "\n"
777  "architecture sub_sub_arch of sub_sub_mod is "
778  "begin "
779  " gate_0 : AND2 "
780  " port map ( "
781  " I0 => ass, "
782  " I1 => bss, "
783  " O => css "
784  " ); "
785  "end sub_sub_arch;"
786  "\n"
787  "entity sub_mod is "
788  " port ( "
789  " as, bs : in STD_LOGIC; "
790  " cs : out STD_LOGIC; "
791  " ); "
792  "end sub_mod; "
793  "\n"
794  "architecture sub_arch of sub_mod is "
795  "begin "
796  " mid : sub_sub_mod "
797  " port map ( "
798  " ass => as, "
799  " bss => bs, "
800  " css => cs "
801  " ); "
802  "end sub_arch;"
803  "\n"
804  "entity top is "
805  " port ( "
806  " a, b : in STD_LOGIC; "
807  " c : out STD_LOGIC; "
808  " ); "
809  "end top; "
810  "\n"
811  "architecture top_arch of top is "
812  "begin "
813  " inst_0 : sub_mod "
814  " port map ( "
815  " as => a, "
816  " bs => b, "
817  " cs => c "
818  " ); "
819  " inst_1 : sub_mod "
820  " port map ( "
821  " as => open, "
822  " bs => b, "
823  " cs => c "
824  " ); "
825  " inst_2 : sub_mod "
826  " port map ( "
827  " as => open, "
828  " bs => open, "
829  " cs => c "
830  " ); "
831  "end top_arch;");
832 
833  const GateLibrary* gate_lib = test_utils::get_gate_library();
834  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
835  VHDLParser vhdl_parser;
836  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
837  ASSERT_TRUE(nl_res.is_ok());
838  std::unique_ptr<Netlist> nl = nl_res.get();
839  ASSERT_NE(nl, nullptr);
840 
841  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_0")).size(), 1);
842  Module* inst_0 = nl->get_modules(test_utils::module_name_filter("inst_0")).front();
843  const auto pins_0 = inst_0->get_pins();
844  EXPECT_EQ(pins_0.size(), 3);
845  EXPECT_EQ(pins_0.at(0)->get_name(), "as");
846  EXPECT_EQ(pins_0.at(0)->get_net()->get_name(), "a");
847  EXPECT_EQ(pins_0.at(1)->get_name(), "bs");
848  EXPECT_EQ(pins_0.at(1)->get_net()->get_name(), "b");
849  EXPECT_EQ(pins_0.at(2)->get_name(), "cs");
850  EXPECT_EQ(pins_0.at(2)->get_net()->get_name(), "c");
851 
852  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_1")).size(), 1);
853  Module* inst_1 = nl->get_modules(test_utils::module_name_filter("inst_1")).front();
854  const auto pins_1 = inst_1->get_pins();
855  EXPECT_EQ(pins_1.size(), 2);
856  EXPECT_EQ(pins_1.at(0)->get_name(), "bs");
857  EXPECT_EQ(pins_1.at(0)->get_net()->get_name(), "b");
858  EXPECT_EQ(pins_1.at(1)->get_name(), "cs");
859  EXPECT_EQ(pins_1.at(1)->get_net()->get_name(), "c");
860 
861  ASSERT_EQ(nl->get_modules(test_utils::module_name_filter("inst_2")).size(), 1);
862  Module* inst_2 = nl->get_modules(test_utils::module_name_filter("inst_2")).front();
863  const auto pins_2 = inst_2->get_pins();
864  EXPECT_EQ(pins_2.size(), 1);
865  EXPECT_EQ(pins_2.at(0)->get_name(), "cs");
866  EXPECT_EQ(pins_2.at(0)->get_net()->get_name(), "c");
867  }
868  TEST_END
869  }
870 
876  TEST_F(VHDLParserTest, check_generic_map) {
877 
878  TEST_START
879  {
880  // Store an instance of all possible data types in one Gate + some special cases
881  std::string netlist_input("-- Device\t: device_name\n"
882  "entity TEST_Comp is "
883  " port ( "
884  " net_global_input : in STD_LOGIC := 'X'; "
885  " ); "
886  "end TEST_Comp; "
887  "architecture STRUCTURE of TEST_Comp is "
888  "begin"
889  " gate_0 : BUF"
890  " generic map("
891  " key_integer => 1234,"
892  " key_floating_point => 1.234,"
893  " key_string => \"test_string\","
894  " key_bit_vector_hex => X\"abc\"," // <- all values are 0xABC
895  " key_bit_vector_dec => D\"2748\","
896  " key_bit_vector_oct => O\"5274\","
897  " key_bit_vector_bin => B\"1010_1011_1100\","
898  // special characters in '"'
899  " key_negative_comma_string => \"test,1,2,3\","
900  " key_negative_float_string => \"1.234\","
901  // -- VHDL specific Data Types:
902  " key_boolean => true,"
903  " key_time => 1.234sec,"
904  " key_bit_value => '1'"
905 
906  " )"
907  " port map ( "
908  " I => net_global_input "
909  " ); "
910  "end STRUCTURE;");
911  const GateLibrary* gate_lib = test_utils::get_gate_library();
912  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
913  VHDLParser vhdl_parser;
914  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
915  ASSERT_TRUE(nl_res.is_ok());
916  std::unique_ptr<Netlist> nl = nl_res.get();
917  ASSERT_NE(nl, nullptr);
918 
919  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("BUF", "gate_0")).size(), 1);
920  Gate* gate_0 = *nl->get_gates(test_utils::gate_filter("BUF", "gate_0")).begin();
921 
922  // Integers are stored in their hex representation
923  EXPECT_EQ(gate_0->get_data("generic", "key_integer"), std::make_tuple("integer", "1234"));
924  EXPECT_EQ(gate_0->get_data("generic", "key_floating_point"),
925  std::make_tuple("floating_point", "1.234"));
926  EXPECT_EQ(gate_0->get_data("generic", "key_string"), std::make_tuple("string", "test_string"));
927  EXPECT_EQ(gate_0->get_data("generic", "key_bit_vector_hex"),
928  std::make_tuple("bit_vector", "ABC"));
929  EXPECT_EQ(gate_0->get_data("generic", "key_bit_vector_dec"),
930  std::make_tuple("bit_vector", "ABC"));
931  EXPECT_EQ(gate_0->get_data("generic", "key_bit_vector_oct"),
932  std::make_tuple("bit_vector", "ABC"));
933  EXPECT_EQ(gate_0->get_data("generic", "key_bit_vector_bin"),
934  std::make_tuple("bit_vector", "ABC"));
935  // Special Characters
936  EXPECT_EQ(gate_0->get_data("generic", "key_negative_comma_string"),
937  std::make_tuple("string", "test,1,2,3"));
938  EXPECT_EQ(gate_0->get_data("generic", "key_negative_float_string"),
939  std::make_tuple("string", "1.234"));
940  // -- VHDL specific Data Types:
941  EXPECT_EQ(gate_0->get_data("generic", "key_boolean"), std::make_tuple("boolean", "true"));
942  EXPECT_EQ(gate_0->get_data("generic", "key_time"), std::make_tuple("time", "1.234sec"));
943  EXPECT_EQ(gate_0->get_data("generic", "key_bit_value"), std::make_tuple("bit_value", "1"));
944  }
945  TEST_END
946  }
947 
953  TEST_F(VHDLParserTest, check_net_vectors) {
954  TEST_START
955  {
956  // Use two logic vectors with dimension 1. One uses the 'downto' the other the 'to' statement
957  /*
958  * n_vec_1 n_vec_2
959  * =-----------= =-----------=
960  * =-----------= =-----------=
961  * global_in ---= gate_0 =-----------= gate_1 =-----------= gate_2 =--- global_out
962  * =-----------= =-----------=
963  *
964  */
965  std::string netlist_input("-- Device\t: device_name \n"
966  "entity TEST_Comp is "
967  " port ( "
968  " net_global_in : in STD_LOGIC := 'X'; "
969  " net_global_out : out STD_LOGIC := 'X'; "
970  " ); "
971  "end TEST_Comp; "
972  "architecture STRUCTURE of TEST_Comp is "
973  " signal n_vec_1 : STD_LOGIC_VECTOR ( 3 downto 0 ); "
974  " signal n_vec_2 : STD_LOGIC_VECTOR ( 0 to 3 ); "
975  "begin "
976  " gate_0 : COMB14 "
977  " port map ( "
978  " I => net_global_in, "
979  " O0 => n_vec_1(0), "
980  " O1 => n_vec_1(1), "
981  " O2 => n_vec_1(2), "
982  " O3 => n_vec_1(3) "
983  " ); "
984  " gate_1 : COMB44 "
985  " port map ( "
986  " I0 => n_vec_1(0), "
987  " I1 => n_vec_1(1), "
988  " I2 => n_vec_1(2), "
989  " I3 => n_vec_1(3), "
990  " O0 => n_vec_2(0), "
991  " O1 => n_vec_2(1), "
992  " O2 => n_vec_2(2), "
993  " O3 => n_vec_2(3) "
994  " ); "
995  " gate_2 : COMB41 "
996  " port map ( "
997  " I0 => n_vec_2(0), "
998  " I1 => n_vec_2(1), "
999  " I2 => n_vec_2(2), "
1000  " I3 => n_vec_2(3), "
1001  " O => net_global_out "
1002  " ); "
1003  "end STRUCTURE;");
1004  const GateLibrary* gate_lib = test_utils::get_gate_library();
1005  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1006  VHDLParser vhdl_parser;
1007  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1008  ASSERT_TRUE(nl_res.is_ok());
1009  std::unique_ptr<Netlist> nl = nl_res.get();
1010  ASSERT_NE(nl, nullptr);
1011 
1012  // Check that all nets are created and connected correctly
1013  EXPECT_EQ(nl->get_nets().size(),
1014  10); // net_global_in + net_global_out + 4 nets in n_vec_1 + 4 nets in n_vec_2
1015  for (auto net_name : std::set<std::string>({"n_vec_1(0)", "n_vec_1(1)", "n_vec_1(2)", "n_vec_1(3)",
1016  "n_vec_2(0)", "n_vec_2(1)", "n_vec_2(2)", "n_vec_2(3)"})) {
1017  ASSERT_EQ(nl->get_nets(test_utils::net_name_filter(net_name)).size(), 1);
1018  }
1019  for (unsigned i = 0; i < 4; i++) {
1020  std::string i_str = std::to_string(i);
1021  Net*
1022  n_vec_1_i = *nl->get_nets(test_utils::net_name_filter("n_vec_1(" + i_str + ")")).begin();
1023  Net*
1024  n_vec_2_i = *nl->get_nets(test_utils::net_name_filter("n_vec_2(" + i_str + ")")).begin();
1025  ASSERT_EQ(n_vec_1_i->get_sources().size(), 1);
1026  EXPECT_EQ(n_vec_1_i->get_sources()[0]->get_pin()->get_name(), "O" + i_str);
1027  EXPECT_EQ((*n_vec_1_i->get_destinations().begin())->get_pin()->get_name(), "I" + i_str);
1028  ASSERT_EQ(n_vec_2_i->get_sources().size(), 1);
1029  EXPECT_EQ(n_vec_2_i->get_sources()[0]->get_pin()->get_name(), "O" + i_str);
1030  EXPECT_EQ((*n_vec_2_i->get_destinations().begin())->get_pin()->get_name(), "I" + i_str);
1031  }
1032  }
1033  {
1034  // Use a logic vector of dimension two
1035  std::string netlist_input("-- Device\t: device_name\n"
1036  "entity TEST_Comp is "
1037  " port ( "
1038  " net_global_in : in STD_LOGIC := 'X'; "
1039  " net_global_out : out STD_LOGIC := 'X'; "
1040  " ); "
1041  "end TEST_Comp; "
1042  "architecture STRUCTURE of TEST_Comp is "
1043  " signal n_vec : STD_LOGIC_VECTOR2 ( 0 to 1, 2 to 3 ); "
1044  "begin "
1045  " gate_0 : COMB14 "
1046  " port map ( "
1047  " I => net_global_in, "
1048  " O0 => n_vec(0,2), "
1049  " O1 => n_vec(0,3), "
1050  " O2 => n_vec(1, 2), "
1051  " O3 => n_vec(1, 3) "
1052  " ); "
1053  " gate_1 : COMB41 "
1054  " port map ( "
1055  " I0 => n_vec(0, 2), "
1056  " I1 => n_vec(0, 3), "
1057  " I2 => n_vec(1, 2), "
1058  " I3 => n_vec(1, 3), "
1059  " O => net_global_out "
1060  " ); "
1061  "end STRUCTURE;");
1062  const GateLibrary* gate_lib = test_utils::get_gate_library();
1063  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1064  VHDLParser vhdl_parser;
1065  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1066  ASSERT_TRUE(nl_res.is_ok());
1067  std::unique_ptr<Netlist> nl = nl_res.get();
1068  ASSERT_NE(nl, nullptr);
1069 
1070  // Check that all nets are created and connected correctly
1071  EXPECT_EQ(nl->get_nets().size(), 6); // net_global_in + global_out + 4 nets in n_vec
1072  unsigned pin = 0;
1073  for (auto n : std::vector<std::string>({"n_vec(0)(2)", "n_vec(0)(3)", "n_vec(1)(2)", "n_vec(1)(3)"})) {
1074  ASSERT_FALSE(nl->get_nets(test_utils::net_name_filter(n)).empty());
1075  Net* n_vec_i_j = *nl->get_nets(test_utils::net_name_filter(n)).begin();
1076  ASSERT_EQ(n_vec_i_j->get_sources().size(), 1);
1077  EXPECT_EQ(n_vec_i_j->get_sources()[0]->get_pin()->get_name(), "O" + std::to_string(pin));
1078  EXPECT_EQ((*n_vec_i_j->get_destinations().begin())->get_pin()->get_name(), "I" + std::to_string(pin));
1079  pin++;
1080  }
1081  }
1082  {
1083  // Use a Net vector of dimension three
1084  std::string netlist_input("-- Device\t: device_name\n"
1085  "entity TEST_Comp is "
1086  " port ( "
1087  " net_global_in : in STD_LOGIC := 'X'; "
1088  " net_global_out : out STD_LOGIC := 'X'; "
1089  " ); "
1090  "end TEST_Comp; "
1091  "architecture STRUCTURE of TEST_Comp is "
1092  " signal n_vec : STD_LOGIC_VECTOR3 ( 0 to 1, 1 downto 0, 0 to 1 ); "
1093  "begin "
1094  " gate_0 : COMB18 "
1095  " port map ( "
1096  " I => net_global_in, "
1097  " O0 => n_vec(0, 0, 0), "
1098  " O1 => n_vec(0, 0, 1), "
1099  " O2 => n_vec(0, 1, 0), "
1100  " O3 => n_vec(0, 1, 1), "
1101  " O4 => n_vec(1, 0, 0), "
1102  " O5 => n_vec(1, 0, 1), "
1103  " O6 => n_vec(1, 1, 0), "
1104  " O7 => n_vec(1, 1, 1) "
1105  " ); "
1106  " gate_1 : COMB81 "
1107  " port map ( "
1108  " I0 => n_vec(0, 0, 0), "
1109  " I1 => n_vec(0, 0, 1), "
1110  " I2 => n_vec(0, 1, 0), "
1111  " I3 => n_vec(0, 1, 1), "
1112  " I4 => n_vec(1, 0, 0), "
1113  " I5 => n_vec(1, 0, 1), "
1114  " I6 => n_vec(1, 1, 0), "
1115  " I7 => n_vec(1, 1, 1), "
1116  " O => net_global_out "
1117  " ); "
1118  "end STRUCTURE;");
1119  const GateLibrary* gate_lib = test_utils::get_gate_library();
1120  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1121  VHDLParser vhdl_parser;
1122  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1123  ASSERT_TRUE(nl_res.is_ok());
1124  std::unique_ptr<Netlist> nl = nl_res.get();
1125  ASSERT_NE(nl, nullptr);
1126 
1127  // Check that all nets are created and connected correctly
1128  EXPECT_EQ(nl->get_nets().size(), 10); // net_global_in + net_global_out + 8 nets in n_vec
1129  std::vector<std::string> net_idx
1130  ({"(0)(0)(0)", "(0)(0)(1)", "(0)(1)(0)", "(0)(1)(1)", "(1)(0)(0)", "(1)(0)(1)", "(1)(1)(0)",
1131  "(1)(1)(1)"});
1132  for (size_t idx = 0; idx < 8; idx++) {
1133  ASSERT_FALSE(nl->get_nets(test_utils::net_name_filter("n_vec" + net_idx[idx])).empty());
1134  Net*
1135  n_vec_i_j = *nl->get_nets(test_utils::net_name_filter("n_vec" + net_idx[idx])).begin();
1136  ASSERT_EQ(n_vec_i_j->get_sources().size(), 1);
1137  EXPECT_EQ(n_vec_i_j->get_sources()[0]->get_pin()->get_name(), "O" + std::to_string(idx));
1138  EXPECT_EQ((*n_vec_i_j->get_destinations().begin())->get_pin()->get_name(), "I" + std::to_string(idx));
1139  }
1140  }
1141  TEST_END
1142  }
1143 
1149  TEST_F(VHDLParserTest, check_special_nets) {
1150 
1151  TEST_START
1152  {
1153  std::string netlist_input("-- Device\t: device_name\n"
1154  "entity TEST_Comp is "
1155  " port ( "
1156  " net_global_out_0 : out STD_LOGIC; "
1157  " net_global_out_1 : out STD_LOGIC; "
1158  " net_global_out_2 : out STD_LOGIC; "
1159  " net_global_out_3 : out STD_LOGIC "
1160  " ); "
1161  "end TEST_Comp; "
1162  "architecture STRUCTURE of TEST_Comp is "
1163  "begin "
1164  " gate_0 : BUF "
1165  " port map ( "
1166  " I => '0', "
1167  " O => net_global_out_0 "
1168  " ); "
1169  " gate_1 : BUF "
1170  " port map ( "
1171  " I => '1', "
1172  " O => net_global_out_1 "
1173  " ); "
1174  " gate_2 : BUF "
1175  " port map ( "
1176  " I => 'Z', "
1177  " O => net_global_out_2 "
1178  " ); "
1179  " gate_3 : BUF "
1180  " port map ( "
1181  " I => 'X', "
1182  " O => net_global_out_3 "
1183  " ); "
1184  "end STRUCTURE;");
1185  const GateLibrary* gate_lib = test_utils::get_gate_library();
1186  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1187  VHDLParser vhdl_parser;
1188  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1189  ASSERT_TRUE(nl_res.is_ok());
1190  std::unique_ptr<Netlist> nl = nl_res.get();
1191  ASSERT_NE(nl, nullptr);
1192 
1193  Gate* gate_0 = *nl->get_gates(test_utils::gate_filter("BUF", "gate_0")).begin();
1194  ASSERT_NE(gate_0, nullptr);
1195  Gate* gate_1 = *nl->get_gates(test_utils::gate_filter("BUF", "gate_1")).begin();
1196  ASSERT_NE(gate_1, nullptr);
1197  Gate* gate_2 = *nl->get_gates(test_utils::gate_filter("BUF", "gate_2")).begin();
1198  ASSERT_NE(gate_2, nullptr);
1199  Gate* gate_3 = *nl->get_gates(test_utils::gate_filter("BUF", "gate_3")).begin();
1200  ASSERT_NE(gate_3, nullptr);
1201 
1202  // check whether net '0' was created and is connected to a GND gate through input pin "I"
1203  Net* net_gnd = gate_0->get_fan_in_net("I");
1204  ASSERT_NE(net_gnd, nullptr);
1205  EXPECT_EQ(net_gnd->get_name(), "'0'");
1206  ASSERT_EQ(net_gnd->get_sources().size(), 1);
1207  ASSERT_NE(net_gnd->get_sources()[0]->get_gate(), nullptr);
1208  EXPECT_TRUE(net_gnd->get_sources()[0]->get_gate()->is_gnd_gate());
1209 
1210  // check whether net '1' was created and is connected to a VCC gate through input pin "I"
1211  Net* net_vcc = gate_1->get_fan_in_net("I");
1212  ASSERT_NE(net_vcc, nullptr);
1213  EXPECT_EQ(net_vcc->get_name(), "'1'");
1214  ASSERT_EQ(net_vcc->get_sources().size(), 1);
1215  ASSERT_NE(net_vcc->get_sources()[0]->get_gate(), nullptr);
1216  EXPECT_TRUE(net_vcc->get_sources()[0]->get_gate()->is_vcc_gate());
1217 
1218  // check whether input pin "I" remains unconnected for 'Z' assignment
1219  ASSERT_EQ(gate_2->get_fan_in_net("I"), nullptr);
1220 
1221  // check whether input pin "I" remains unconnected for 'X' assignment
1222  ASSERT_EQ(gate_2->get_fan_in_net("I"), nullptr);
1223  }
1224  TEST_END
1225  }
1226 
1235  TEST_F(VHDLParserTest, check_multiple_entities) {
1236 
1237  TEST_START
1238  {
1239  // Create a new entity with an attribute that is used once by the main entity
1240  /* ---------------------------------------------.
1241  * | child_mod |
1242  * | |
1243  * global_in ---=| gate_0 |=---=---=| gate_0_child |=---=| gate_1_child |=---=---=| gate_1 |=--- global_out
1244  * | |
1245  * '---------------------------------------------'
1246  */
1247 
1248  std::string netlist_input("-- Device\t: device_name\n"
1249  "entity MODULE_CHILD is "
1250  " attribute child_attribute : string; "
1251  " attribute child_attribute of MODULE_CHILD : entity is \"child_attribute_value\"; "
1252  " port ( "
1253  " child_in : in STD_LOGIC; "
1254  " child_out : out STD_LOGIC "
1255  " ); "
1256  "end MODULE_CHILD; "
1257  "architecture STRUCTURE_CHILD of MODULE_CHILD is "
1258  " signal net_0_child : STD_LOGIC; "
1259  " attribute child_net_attribute : string; "
1260  " attribute child_net_attribute of child_in : signal is \"child_net_attribute_value\"; "
1261  "begin "
1262  " gate_0_child : BUF "
1263  " port map ( "
1264  " I => child_in, "
1265  " O => net_0_child "
1266  " ); "
1267  " gate_1_child : BUF "
1268  " port map ( "
1269  " I => net_0_child, "
1270  " O => child_out "
1271  " ); "
1272  "end STRUCTURE_CHILD; "
1273  ""
1274  "entity MODULE_TOP is "
1275  " port ( "
1276  " net_global_in : in STD_LOGIC; "
1277  " net_global_out : out STD_LOGIC "
1278  " ); "
1279  "end MODULE_TOP; "
1280  "architecture STRUCTURE of MODULE_TOP is "
1281  " signal net_0 : STD_LOGIC; "
1282  " signal net_1 : STD_LOGIC; "
1283  " "
1284  "begin "
1285  " gate_0 : BUF "
1286  " port map ( "
1287  " I => net_global_in, "
1288  " O => net_0 "
1289  " ); "
1290  " child_mod : MODULE_CHILD "
1291  " port map ( "
1292  " child_in => net_0, "
1293  " child_out => net_1 "
1294  " ); "
1295  " gate_1 : BUF "
1296  " port map ( "
1297  " I => net_1, "
1298  " O => net_global_out "
1299  " ); "
1300  "end ENT_TOP;");
1301  const GateLibrary* gate_lib = test_utils::get_gate_library();
1302  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1303  VHDLParser vhdl_parser;
1304  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1305  ASSERT_TRUE(nl_res.is_ok());
1306  std::unique_ptr<Netlist> nl = nl_res.get();
1307  ASSERT_NE(nl, nullptr);
1308 
1309  // check gates
1310  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("BUF", "gate_0")).size(), 1);
1311  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("BUF", "gate_1")).size(), 1);
1312  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("BUF", "gate_0_child")).size(), 1);
1313  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("BUF", "gate_1_child")).size(), 1);
1314  Gate* gate_0 = *nl->get_gates(test_utils::gate_filter("BUF", "gate_0")).begin();
1315  Gate* gate_1 = *nl->get_gates(test_utils::gate_filter("BUF", "gate_1")).begin();
1316  Gate* gate_0_child = *nl->get_gates(test_utils::gate_filter("BUF", "gate_0_child")).begin();
1317  Gate* gate_1_child = *nl->get_gates(test_utils::gate_filter("BUF", "gate_1_child")).begin();
1318 
1319  // check nets
1320  ASSERT_EQ(nl->get_nets(test_utils::net_name_filter("net_0")).size(), 1);
1321  ASSERT_EQ(nl->get_nets(test_utils::net_name_filter("net_1")).size(), 1);
1322  ASSERT_EQ(nl->get_nets(test_utils::net_name_filter("net_global_in")).size(), 1);
1323  ASSERT_EQ(nl->get_nets(test_utils::net_name_filter("net_global_out")).size(), 1);
1324  ASSERT_EQ(nl->get_nets(test_utils::net_name_filter("net_0_child")).size(), 1);
1325  Net* net_0 = *nl->get_nets(test_utils::net_name_filter("net_0")).begin();
1326  Net* net_1 = *nl->get_nets(test_utils::net_name_filter("net_1")).begin();
1327  Net* net_global_in = *nl->get_nets(test_utils::net_name_filter("net_global_in")).begin();
1328  Net* net_global_out = *nl->get_nets(test_utils::net_name_filter("net_global_out")).begin();
1329  Net* net_0_child = *nl->get_nets(test_utils::net_name_filter("net_0_child")).begin();
1330 
1331  // check connections
1332  EXPECT_EQ(gate_0->get_fan_in_net("I"), net_global_in);
1333  EXPECT_EQ(gate_0->get_fan_out_net("O"), net_0);
1334  EXPECT_EQ(gate_1->get_fan_in_net("I"), net_1);
1335  EXPECT_EQ(gate_1->get_fan_out_net("O"), net_global_out);
1336  EXPECT_EQ(gate_0_child->get_fan_in_net("I"), net_0);
1337  EXPECT_EQ(gate_0_child->get_fan_out_net("O"), net_0_child);
1338  EXPECT_EQ(gate_1_child->get_fan_in_net("I"), net_0_child);
1339  EXPECT_EQ(gate_1_child->get_fan_out_net("O"), net_1);
1340 
1341  // check modules
1342  Module* top_mod = nl->get_top_module();
1343  ASSERT_NE(top_mod, nullptr);
1344  EXPECT_TRUE(top_mod->is_top_module());
1345  EXPECT_EQ(top_mod->get_name(), "top_module");
1346  EXPECT_EQ(top_mod->get_type(), "MODULE_TOP");
1347  ASSERT_EQ(top_mod->get_submodules().size(), 1);
1348  Module* child_mod = *top_mod->get_submodules().begin();
1349  ASSERT_NE(child_mod, nullptr);
1350  EXPECT_EQ(child_mod->get_name(), "child_mod");
1351  EXPECT_EQ(child_mod->get_type(), "MODULE_CHILD");
1352  EXPECT_EQ(top_mod->get_gates(), std::vector<Gate*>({gate_0, gate_1}));
1353  EXPECT_EQ(child_mod->get_gates(), std::vector<Gate*>({gate_0_child, gate_1_child}));
1354 
1355  // check attributes
1356  EXPECT_EQ(net_0->get_data("attribute", "child_net_attribute"), std::make_tuple("string", "child_net_attribute_value"));
1357  EXPECT_EQ(child_mod->get_data("attribute", "child_attribute"), std::make_tuple("string", "child_attribute_value"));
1358  }
1359  {
1360  // Create a netlist with the following MODULE hierarchy (assigned gates in '()'):
1361  /*
1362  * .---- CHILD_TWO --- (gate_child_two)
1363  * |
1364  * .----- CHILD_ONE-+
1365  * | |
1366  * TOP_MODULE -+ +---- CHILD_TWO --- (gate_child_two)
1367  * | |
1368  * | '---- (gate_child_one)
1369  * |
1370  * +----- CHILD_TWO --- (gate_child_two)
1371  * |
1372  * '---- (gate_top)
1373  *
1374  */
1375  // Testing the correct build of the Module hierarchy. Moreover the correct substitution of Gate and Net names,
1376  // which would be added twice (because an entity can be used multiple times) is tested as well.
1377 
1378  std::string netlist_input("-- Device\t: device_name \n"
1379  "entity ENT_CHILD_TWO is "
1380  " port ( "
1381  " I_c2 : in STD_LOGIC; "
1382  " O_c2 : out STD_LOGIC "
1383  " ); "
1384  "end ENT_CHILD_TWO; "
1385  "architecture STRUCTURE_CHILD_TWO of ENT_CHILD_TWO is "
1386  "begin "
1387  " gate_child_two : BUF "
1388  " port map ( "
1389  " I => I_c2, "
1390  " O => O_c2 "
1391  " ); "
1392  "end STRUCTURE_CHILD_TWO; "
1393  " "
1394  "entity ENT_CHILD_ONE is "
1395  " port ( "
1396  " I_c1 : in STD_LOGIC; "
1397  " O_c1 : out STD_LOGIC"
1398  " ); "
1399  "end ENT_CHILD_ONE; "
1400  "architecture STRUCTURE_CHILD_ONE of ENT_CHILD_ONE is "
1401  " signal net_child_0 : STD_LOGIC; "
1402  " signal net_child_1 : STD_LOGIC; "
1403  "begin "
1404  " gate_0_ent_two : ENT_CHILD_TWO "
1405  " port map ( "
1406  " I_c2 => I_c1, "
1407  " O_c2 => net_child_0 "
1408  " ); "
1409  " gate_1_ent_two : ENT_CHILD_TWO "
1410  " port map ( "
1411  " I_c2 => net_child_0, "
1412  " O_c2 => net_child_1 "
1413  " ); "
1414  " gate_child_one : BUF "
1415  " port map ( "
1416  " I => net_child_1, "
1417  " O => O_c1 "
1418  " ); "
1419  "end STRUCTURE_CHILD_ONE; "
1420  " "
1421  "entity ENT_TOP is "
1422  " port ( "
1423  " net_global_in : in STD_LOGIC; "
1424  " net_global_out : out STD_LOGIC "
1425  " ); "
1426  "end ENT_TOP; "
1427  "architecture STRUCTURE of ENT_TOP is "
1428  " signal net_0 : STD_LOGIC; "
1429  " signal net_1 : STD_LOGIC; "
1430  "begin "
1431  " child_one_mod : ENT_CHILD_ONE "
1432  " port map ( "
1433  " I_c1 => net_global_in, "
1434  " O_c1 => net_0 "
1435  " ); "
1436  " child_two_mod : ENT_CHILD_TWO "
1437  " port map ( "
1438  " I_c2 => net_0, "
1439  " O_c2 => net_1 "
1440  " ); "
1441  " gate_top : BUF "
1442  " port map ( "
1443  " I => net_1, "
1444  " O => net_global_out "
1445  " ); "
1446  "end ENT_TOP;");
1447  const GateLibrary* gate_lib = test_utils::get_gate_library();
1448  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1449  VHDLParser vhdl_parser;
1450  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1451  ASSERT_TRUE(nl_res.is_ok());
1452  std::unique_ptr<Netlist> nl = nl_res.get();
1453 
1454  // Test if all modules are created and assigned correctly
1455  ASSERT_NE(nl, nullptr);
1456  EXPECT_EQ(nl->get_gates().size(), 5); // 3 * gate_child_two + gate_child_one + gate_top
1457  EXPECT_EQ(nl->get_modules().size(), 5); // 3 * ENT_CHILD_TWO + ENT_CHILD_ONE + ENT_TOP
1458  Module* top_module = nl->get_top_module();
1459 
1460  ASSERT_EQ(top_module->get_submodules().size(), 2);
1461  Module* top_child_one = *top_module->get_submodules().begin();
1462  Module* top_child_two = *(++top_module->get_submodules().begin());
1463  if (top_child_one->get_submodules().empty()) {
1464  std::swap(top_child_one, top_child_two);
1465  }
1466 
1467  ASSERT_EQ(top_child_one->get_submodules().size(), 2);
1468  Module* one_child_0 = *(top_child_one->get_submodules().begin());
1469  Module* one_child_1 = *(++top_child_one->get_submodules().begin());
1470 
1471  // Test if all names that are used multiple times are substituted correctly
1472  std::string module_suffix = "";
1473 
1474  EXPECT_EQ(top_child_one->get_name(), "child_one_mod");
1475 
1476  EXPECT_TRUE(utils::starts_with(top_child_two->get_name(), "child_two_mod" + module_suffix));
1477  EXPECT_TRUE(utils::starts_with(one_child_0->get_name(), "gate_0_ent_two" + module_suffix));
1478  EXPECT_TRUE(utils::starts_with(one_child_1->get_name(), "gate_1_ent_two" + module_suffix));
1479  // All 3 names should be unique
1480  EXPECT_EQ(std::set<std::string>({top_child_two->get_name(), one_child_0->get_name(),
1481  one_child_1->get_name()}).size(), 3);
1482 
1483  // Test if the Gate names are substituted correctly as well (gate_child_two is used multiple times)
1484  std::string gate_suffix = "";
1485 
1486  ASSERT_EQ(top_module->get_gates().size(), 1);
1487  EXPECT_EQ((*top_module->get_gates().begin())->get_name(), "gate_top");
1488 
1489  ASSERT_EQ(top_child_one->get_gates().size(), 1);
1490  EXPECT_EQ((*top_child_one->get_gates().begin())->get_name(), "gate_child_one");
1491 
1492  ASSERT_EQ(top_child_two->get_gates().size(), 1);
1493  ASSERT_EQ(one_child_0->get_gates().size(), 1);
1494  ASSERT_EQ(one_child_1->get_gates().size(), 1);
1495  Gate* gate_child_two_0 = *top_child_two->get_gates().begin();
1496  Gate* gate_child_two_1 = *one_child_0->get_gates().begin();
1497  Gate* gate_child_two_2 = *one_child_1->get_gates().begin();
1498 
1499  EXPECT_TRUE(utils::starts_with(gate_child_two_0->get_name(), "child_two_mod/gate_child_two" + gate_suffix));
1500  EXPECT_TRUE(utils::starts_with(gate_child_two_1->get_name(), "gate_0_ent_two/gate_child_two" + gate_suffix));
1501  EXPECT_TRUE(utils::starts_with(gate_child_two_2->get_name(), "gate_1_ent_two/gate_child_two" + gate_suffix));
1502  // All 3 names should be unique
1503  EXPECT_EQ(std::set<std::string>({gate_child_two_0->get_name(), gate_child_two_1->get_name(),
1504  gate_child_two_2->get_name()}).size(), 3);
1505  }
1506  {
1507  // Create a netlist as follows and test its creation (due to request):
1508  /* - - - - - - - - - - - - - - - - - - - - - - .
1509  * ' mod '
1510  * ' mod_inner/mod_out '
1511  * ' .------------------. '
1512  * 'mod_in | | 'net_0
1513  * net_global_in ----=------=| gate_a |=---+---=| gate_b |= '---=----=| gate_top |=---- net_global_out
1514  * ' '
1515  * ' '
1516  * '- - - - - - - - - - - - - - - - - - - - - - '
1517  */
1518  std::string netlist_input("-- Device\t: device_name\n"
1519  "entity ENT_MODULE is "
1520  " port ( "
1521  " mod_in : in STD_LOGIC := 'X'; "
1522  " mod_out : out STD_LOGIC := 'X'; "
1523  " ); "
1524  "end ENT_MODULE; "
1525  "architecture STRUCTURE_MODULE of ENT_MODULE is "
1526  " signal mod_inner : STD_LOGIC; "
1527  "begin "
1528  " mod_inner <= mod_out; "
1529  " gate_a : BUF "
1530  " port map ( "
1531  " I => mod_in, "
1532  " O => mod_inner "
1533  " ); "
1534  " gate_b : BUF "
1535  " port map ( "
1536  " I => mod_inner "
1537  " ); "
1538  "end STRUCTURE_MODULE;\n"
1539  "---------------------------------------\n"
1540  "entity ENT_TOP is "
1541  " port ( "
1542  " net_global_in : in STD_LOGIC := 'X'; "
1543  " net_global_out : out STD_LOGIC := 'X'; "
1544  " ); "
1545  "end ENT_TOP; "
1546  "architecture STRUCTURE_TOP of ENT_TOP is "
1547  " signal net_0 : STD_LOGIC; "
1548  "begin "
1549  " mod : ENT_MODULE "
1550  " port map ( "
1551  " mod_in => net_global_in, "
1552  " mod_out => net_0 "
1553  " ); "
1554  " gate_top : BUF "
1555  " port map ( "
1556  " I => net_0, "
1557  " O => net_global_out "
1558  " ); "
1559  "end STRUCTURE_TOP;");
1560  const GateLibrary* gate_lib = test_utils::get_gate_library();
1561  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1562  VHDLParser vhdl_parser;
1563  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1564  ASSERT_TRUE(nl_res.is_ok());
1565  std::unique_ptr<Netlist> nl = nl_res.get();
1566 
1567  // Test if all modules are created and assigned correctly
1568  ASSERT_NE(nl, nullptr);
1569  EXPECT_EQ(nl->get_gates().size(), 3); // 1 in top + 2 in mod
1570  EXPECT_EQ(nl->get_modules().size(), 2); // top + mod
1571  Module* top_module = nl->get_top_module();
1572 
1573  ASSERT_EQ(top_module->get_submodules().size(), 1);
1574  Module* mod = *top_module->get_submodules().begin();
1575 
1576  ASSERT_EQ(mod->get_gates(test_utils::gate_name_filter("gate_a")).size(), 1);
1577  ASSERT_EQ(mod->get_gates(test_utils::gate_name_filter("gate_b")).size(), 1);
1578  ASSERT_EQ(nl->get_gates(test_utils::gate_name_filter("gate_top")).size(), 1);
1579  Gate* gate_a = *mod->get_gates(test_utils::gate_name_filter("gate_a")).begin();
1580  Gate* gate_b = *mod->get_gates(test_utils::gate_name_filter("gate_b")).begin();
1581  Gate* gate_top = *nl->get_gates(test_utils::gate_name_filter("gate_top")).begin();
1582 
1583  Net* mod_out = gate_a->get_fan_out_net("O");
1584  ASSERT_NE(mod_out, nullptr);
1585  ASSERT_EQ(mod->get_output_nets().size(), 1);
1586  EXPECT_EQ(*mod->get_output_nets().begin(), mod_out);
1587 
1589  std::vector<Endpoint*>({test_utils::get_endpoint(gate_b,
1590  "I"),
1591  test_utils::get_endpoint(
1592  gate_top,
1593  "I")})));
1594 
1595  }
1596  {
1597  // Testing the correct naming of gates and nets that occur in multiple modules by
1598  // creating the following netlist:
1599 
1600  /* MODULE_B
1601  * . - - - - - - - - - - - - - - - - - - - - - .
1602  * ' .-----------------. shared_net_name .--------------. '
1603  * ' | |=----------------=| | ' net_0
1604  * net_global_in ---=---=| shared_gate_name |=----------------=| gate_b |=----=-- ...
1605  * ' '------------------' net_b '---------------' '
1606  * ' - - - - - - - - - - - - - - - - - - - - - '
1607  *
1608  * MODULE_A
1609  * . - - - - - - - - - - - - - - - - - - - - - .
1610  * ' .-----------------. shared_net_name .--------------. '
1611  * net_0 ' | |=----------------=| | ' net_1
1612  * ... ---=---=| shared_gate_name |=----------------=| gate_a |=----=-- ...
1613  * ' '------------------' net_a '---------------' '
1614  * ' - - - - - - - - - - - - - - - - - - - - - '
1615  *
1616  * MODULE_B
1617  * net_1 . - - . net_2
1618  * ... --- = ... =-------=| gate_top |=--- net_global_out
1619  * ' - - '
1620  */
1621  std::string netlist_input("-- Device\t: device_name\n"
1622  "entity MODULE_A is\n"
1623  " port (\n"
1624  " I_A : in STD_LOGIC := 'X';\n"
1625  " O_A : out STD_LOGIC := 'X';\n"
1626  " );\n"
1627  "end MODULE_A;\n"
1628  "architecture STRUCT_MODULE_A of MODULE_A is\n"
1629  " signal shared_net_name : STD_LOGIC;\n"
1630  " signal net_a : STD_LOGIC;\n"
1631  "begin\n"
1632  " shared_gate_name : COMB12\n"
1633  " port map (\n"
1634  " I => I_A,\n"
1635  " O0 => shared_net_name,\n"
1636  " O1 => net_a\n"
1637  " );\n"
1638  " gate_a : COMB21\n"
1639  " port map (\n"
1640  " I0 => shared_net_name,\n"
1641  " I1 => net_a,\n"
1642  " O => O_A\n"
1643  " );\n"
1644  "end STRUCT_MODULE_A;\n"
1645  "-----\n"
1646  "entity MODULE_B is\n"
1647  " port (\n"
1648  " I_B : in STD_LOGIC := 'X';\n"
1649  " O_B : out STD_LOGIC := 'X';\n"
1650  " );\n"
1651  "end MODULE_B;\n"
1652  "architecture STRUCT_MODULE_B of MODULE_B is\n"
1653  " signal shared_net_name : STD_LOGIC;\n"
1654  " signal net_b : STD_LOGIC;\n"
1655  "begin\n"
1656  " shared_gate_name : COMB12\n"
1657  " port map (\n"
1658  " I => I_B,\n"
1659  " O0 => shared_net_name,\n"
1660  " O1 => net_b\n"
1661  " );\n"
1662  " gate_b : COMB21\n"
1663  " port map (\n"
1664  " I0 => shared_net_name,\n"
1665  " I1 => net_b,\n"
1666  " O => O_B\n"
1667  " );\n"
1668  "end STRUCT_MODULE_B;\n"
1669  "-----\n"
1670  "entity ENT_TOP is\n"
1671  " port (\n"
1672  " net_global_in : in STD_LOGIC := 'X';\n"
1673  " net_global_out : out STD_LOGIC := 'X';\n"
1674  " );\n"
1675  "end ENT_TOP;\n"
1676  "architecture STRUCTURE_TOP of ENT_TOP is\n"
1677  " signal net_0 : STD_LOGIC;\n"
1678  " signal net_1 : STD_LOGIC;\n"
1679  " signal net_2 : STD_LOGIC;\n"
1680  "begin\n"
1681  " mod_b_0 : MODULE_B\n"
1682  " port map (\n"
1683  " I_B => net_global_in,\n"
1684  " O_B => net_0\n"
1685  " );\n"
1686  " mod_a_0 : MODULE_A\n"
1687  " port map (\n"
1688  " I_A => net_0,\n"
1689  " O_A => net_1\n"
1690  " );\n"
1691  " mod_b_1 : MODULE_B\n"
1692  " port map (\n"
1693  " I_B => net_1,\n"
1694  " O_B => net_2\n"
1695  " );\n"
1696  " gate_top : BUF\n"
1697  " port map (\n"
1698  " I => net_2,\n"
1699  " O => net_global_out\n"
1700  " );\n"
1701  "end STRUCTURE_TOP;");
1702  const GateLibrary* gate_lib = test_utils::get_gate_library();
1703  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1704  VHDLParser vhdl_parser;
1705  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1706  ASSERT_TRUE(nl_res.is_ok());
1707  std::unique_ptr<Netlist> nl = nl_res.get();
1708 
1709  // Test if all modules are created and assigned correctly
1710  ASSERT_NE(nl, nullptr);
1711 
1712  // ISSUE: Seems not to be correct. For example net_b occurs two times, but is named net_b__[3]__ and net_b__[4]__
1713  // or shared_net_name occurs 3 times and is labeled with 4,5,6
1714 
1715  Net* glob_in = *nl->get_global_input_nets().begin();
1716  ASSERT_NE(glob_in, nullptr);
1717  ASSERT_EQ(glob_in->get_destinations().size(), 1);
1718 
1719  Gate* shared_gate_0 = (*glob_in->get_destinations().begin())->get_gate();
1720  ASSERT_NE(shared_gate_0, nullptr);
1721 
1722  // Get all gates from left to right
1723  std::vector<Gate*> nl_gates = {shared_gate_0};
1724  std::vector<std::string> suc_pin = {"O0","O","O0","O","O0","O"};
1725  for(size_t idx = 0; idx < suc_pin.size(); idx++){
1726  ASSERT_NE(nl_gates[idx]->get_successor(suc_pin[idx]), nullptr);
1727  Gate* next_gate = nl_gates[idx]->get_successor(suc_pin[idx])->get_gate();
1728  ASSERT_NE(next_gate, nullptr);
1729  nl_gates.push_back(next_gate);
1730  }
1731 
1732  // Get all nets from left to right (and from top to bottom)
1733  std::vector<Net*> nl_nets = {glob_in};
1734  std::vector<std::pair<Gate*, std::string>> net_out_gate_and_pin = {{nl_gates[0], "O0"}, {nl_gates[0], "O1"}, {nl_gates[1], "O"}, {nl_gates[2], "O0"},
1735  {nl_gates[2], "O1"}, {nl_gates[3], "O"}, {nl_gates[4], "O0"}, {nl_gates[4], "O1"}, {nl_gates[5], "O"}, {nl_gates[6], "O"}};
1736  for(size_t idx = 0; idx < net_out_gate_and_pin.size(); idx++){
1737  Net* next_net = (net_out_gate_and_pin[idx].first)->get_fan_out_net(net_out_gate_and_pin[idx].second);
1738  ASSERT_NE(next_net, nullptr);
1739  nl_nets.push_back(next_net);
1740  }
1741 
1742  // Check that the gate names are correct
1743  std::vector<std::string> nl_gate_names;
1744  for(Gate* g : nl_gates) nl_gate_names.push_back(g->get_name());
1745  std::vector<std::string> expected_gate_names = {"mod_b_0/shared_gate_name", "mod_b_0/gate_b", "mod_a_0/shared_gate_name", "gate_a", "mod_b_1/shared_gate_name", "mod_b_1/gate_b", "gate_top"};
1746  EXPECT_EQ(nl_gate_names, expected_gate_names);
1747 
1748  // Check that the net names are correct
1749  std::vector<std::string> nl_net_names;
1750  for(Net* n : nl_nets) nl_net_names.push_back(n->get_name());
1751  std::vector<std::string> expected_net_names = {"net_global_in", "mod_b_0/shared_net_name", "mod_b_0/net_b", "net_0", "mod_a_0/shared_net_name", "net_a", "net_1", "mod_b_1/shared_net_name", "mod_b_1/net_b", "net_2", "net_global_out"};
1752  EXPECT_EQ(nl_net_names, expected_net_names);
1753 
1754  }
1755 
1756  TEST_END
1757  }
1758 
1769  TEST_F(VHDLParserTest, check_direct_assignment) {
1770  TEST_START
1771  {
1772  // Build up a master-slave hierarchy as follows:
1773  /* .--- net_slave_1 (is global input)
1774  * net_master <--- net_slave_0 <--+
1775  * '--- net_slave_2
1776  */
1777  // Testing the correct creation of the master Net by considering the inheritance of the attributes and connections
1778  // of its slaves (vhdl specific)
1779  std::string netlist_input("-- Device\t: device_name\n"
1780  "entity TEST_Comp is "
1781  " port ( "
1782  " net_global_in : in STD_LOGIC := 'X'; "
1783  " net_global_out : out STD_LOGIC := 'X'; "
1784  " net_master: in STD_LOGIC := 'X'; "
1785  " ); "
1786  "end TEST_Comp; "
1787  "architecture STRUCTURE of TEST_Comp is "
1788  " signal net_slave_0 : STD_LOGIC; "
1789  " signal net_slave_2 : STD_LOGIC; "
1790  " signal net_slave_1 : STD_LOGIC; "
1791  " attribute slave_0_attr : string; " // <- signal attributes are vhdl specific
1792  " attribute slave_0_attr of net_slave_0 : signal is \"slave_0_attr\"; "
1793  " attribute slave_1_attr : string; "
1794  " attribute slave_1_attr of net_slave_1 : signal is \"slave_1_attr\"; "
1795  " attribute slave_2_attr : string; "
1796  " attribute slave_2_attr of net_slave_2 : signal is \"slave_2_attr\"; "
1797  " attribute master_attr : string; "
1798  " attribute master_attr of net_master : signal is \"master_attr\"; "
1799  "begin "
1800  " net_slave_1 <= net_slave_0; "
1801  " net_slave_2 <= net_slave_0; "
1802  " net_master <= net_slave_0; "
1803  " gate_0 : BUF "
1804  " port map ( "
1805  " I => net_global_in, "
1806  " O => net_slave_0 "
1807  " ); "
1808  " gate_1 : AND3 "
1809  " port map ( "
1810  " I0 => net_master, "
1811  " I1 => net_slave_1, "
1812  " I2 => net_slave_2, "
1813  " O => net_global_out "
1814  " ); "
1815  "end STRUCTURE;");
1816  const GateLibrary* gate_lib = test_utils::get_gate_library();
1817  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1818  VHDLParser vhdl_parser;
1819  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1820  ASSERT_TRUE(nl_res.is_ok());
1821  std::unique_ptr<Netlist> nl = nl_res.get();
1822 
1823  ASSERT_NE(nl, nullptr);
1824  EXPECT_EQ(nl->get_nets().size(), 3); // global_in + global_out + net_master
1825  ASSERT_EQ(nl->get_nets(test_utils::net_name_filter("net_master")).size(), 1);
1826  Net* net_master = *nl->get_nets(test_utils::net_name_filter("net_master")).begin();
1827 
1828  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("BUF", "gate_0")).size(), 1);
1829  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("AND3", "gate_1")).size(), 1);
1830 
1831  Gate* g_0 = *nl->get_gates(test_utils::gate_filter("BUF", "gate_0")).begin();
1832  Gate* g_1 = *nl->get_gates(test_utils::gate_filter("AND3", "gate_1")).begin();
1833 
1834  // Check the connections
1835  EXPECT_EQ(g_0->get_fan_out_net("O"), net_master);
1836  EXPECT_EQ(g_1->get_fan_in_net("I0"), net_master);
1837  EXPECT_EQ(g_1->get_fan_in_net("I1"), net_master);
1838  EXPECT_EQ(g_1->get_fan_in_net("I2"), net_master);
1839 
1840  // Check that net_master becomes also a global input
1841  EXPECT_TRUE(net_master->is_global_input_net());
1842 
1843  // VHDL specific: Check the Net attribute propagation
1844  EXPECT_EQ(net_master->get_data("attribute", "master_attr"),
1845  std::make_tuple("string", "master_attr"));
1846  EXPECT_EQ(net_master->get_data("attribute", "slave_0_attr"),
1847  std::make_tuple("string", "slave_0_attr"));
1848  EXPECT_EQ(net_master->get_data("attribute", "slave_1_attr"),
1849  std::make_tuple("string", "slave_1_attr"));
1850  EXPECT_EQ(net_master->get_data("attribute", "slave_2_attr"),
1851  std::make_tuple("string", "slave_2_attr"));
1852  }
1853  {
1854  // Create a cyclic master-slave Net hierarchy (first master net should survive)
1855  NO_COUT_TEST_BLOCK;
1856  std::string netlist_input("-- Device\t: device_name\n"
1857  "entity TEST_Comp is "
1858  " port ( "
1859  " net_global_in : in STD_LOGIC := 'X'; "
1860  " net_global_out : out STD_LOGIC := 'X'; "
1861  " ); "
1862  "end TEST_Comp; "
1863  "architecture STRUCTURE of TEST_Comp is "
1864  " signal net_0 : STD_LOGIC; "
1865  " signal net_1 : STD_LOGIC; "
1866  "begin "
1867  " net_0 <= net_1; "
1868  " net_1 <= net_0; "
1869  " gate_0 : BUF "
1870  " port map ( "
1871  " I => net_global_in, "
1872  " O => net_0 "
1873  " ); "
1874  " gate_1 : BUF "
1875  " port map ( "
1876  " I => net_1, "
1877  " O => net_global_out "
1878  " ); "
1879  "end STRUCTURE;");
1880  const GateLibrary* gate_lib = test_utils::get_gate_library();
1881  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1882  VHDLParser vhdl_parser;
1883  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1884  ASSERT_TRUE(nl_res.is_ok());
1885  std::unique_ptr<Netlist> nl = nl_res.get();
1886 
1887  ASSERT_NE(nl, nullptr);
1888  EXPECT_EQ(nl->get_nets().size(), 3); // global_in + global_out + net_0
1889  EXPECT_EQ(nl->get_nets(test_utils::net_name_filter("net_0")).size(), 1);
1890  }
1891  {
1892  //Testing the assignment of logic vectors
1893  std::string netlist_input("-- Device\t: device_name\n"
1894  "entity TEST_Comp is "
1895  " port ( "
1896  " net_global_in : in STD_LOGIC := 'X'; "
1897  " net_global_out : out STD_LOGIC := 'X'; "
1898  " ); "
1899  "end TEST_Comp; "
1900  "architecture STRUCTURE of TEST_Comp is "
1901  " signal net_slave : STD_LOGIC_VECTOR ( 0 to 3 ); "
1902  " signal net_master : STD_LOGIC_VECTOR ( 0 to 3 ); "
1903  "begin "
1904  " net_master <= net_slave; "
1905  " gate_0 : BUF "
1906  " port map ( "
1907  " I => net_global_in, "
1908  " O => net_slave(0) "
1909  " ); "
1910  " gate_1 : AND3 "
1911  " port map ( "
1912  " I0 => net_master(0), "
1913  " I1 => net_slave(1), "
1914  " I2 => net_slave(2), "
1915  " O => net_global_out "
1916  " ); "
1917  "end STRUCTURE;");
1918  const GateLibrary* gate_lib = test_utils::get_gate_library();
1919  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1920  VHDLParser vhdl_parser;
1921  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1922  ASSERT_TRUE(nl_res.is_ok());
1923  std::unique_ptr<Netlist> nl = nl_res.get();
1924 
1925  ASSERT_NE(nl, nullptr);
1926 
1927  ASSERT_EQ(nl->get_gates(test_utils::gate_name_filter("gate_0")).size(), 1);
1928  ASSERT_EQ(nl->get_gates(test_utils::gate_name_filter("gate_1")).size(), 1);
1929  Gate* gate_0 = *nl->get_gates(test_utils::gate_name_filter("gate_0")).begin();
1930  Gate* gate_1 = *nl->get_gates(test_utils::gate_name_filter("gate_1")).begin();
1931 
1932  ASSERT_NE(gate_0->get_fan_out_net("O"), nullptr);
1933  ASSERT_NE(gate_1->get_fan_in_net("I0"), nullptr);
1934  ASSERT_NE(gate_1->get_fan_in_net("I1"), nullptr);
1935  ASSERT_NE(gate_1->get_fan_in_net("I2"), nullptr);
1936 
1937  EXPECT_EQ(gate_0->get_fan_out_net("O")->get_name(), "net_master(0)");
1938  EXPECT_EQ(gate_1->get_fan_in_net("I0")->get_name(), "net_master(0)");
1939  EXPECT_EQ(gate_1->get_fan_in_net("I1")->get_name(), "net_master(1)");
1940  EXPECT_EQ(gate_1->get_fan_in_net("I2")->get_name(), "net_master(2)");
1941 
1942  }
1943  TEST_END
1944  }
1945 
1951  TEST_F(VHDLParserTest, check_pin_group_port_assignment) {
1952 
1953  TEST_START
1954  {
1955  // Connect an entire output pin group with global input nets by using a binary string (B"0101")
1956  std::string netlist_input("-- Device\t: device_name\n"
1957  "entity TEST_Comp is\n"
1958  " port (\n"
1959  " );\n"
1960  "end TEST_Comp;\n"
1961  "architecture STRUCTURE of TEST_Comp is\n"
1962  "begin\n"
1963  " gate_0 : RAM\n"
1964  " port map (\n"
1965  " ADDR => B\"0101\"\n"
1966  " );\n"
1967  "end STRUCTURE;");
1968  const GateLibrary* gate_lib = test_utils::get_gate_library();
1969  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
1970  VHDLParser vhdl_parser;
1971  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
1972  ASSERT_TRUE(nl_res.is_ok());
1973  std::unique_ptr<Netlist> nl = nl_res.get();
1974 
1975  ASSERT_NE(nl, nullptr);
1976  ASSERT_FALSE(nl->get_gates(test_utils::gate_filter("RAM", "gate_0")).empty());
1977  Gate* gate_0 = *(nl->get_gates(test_utils::gate_filter("RAM", "gate_0")).begin());
1978 
1979  Net* net_0 = gate_0->get_fan_in_net("ADDR(0)");
1980  ASSERT_NE(net_0, nullptr);
1981  EXPECT_EQ(net_0->get_name(), "'1'");
1982 
1983  Net* net_1 = gate_0->get_fan_in_net("ADDR(1)");
1984  ASSERT_NE(net_1, nullptr);
1985  EXPECT_EQ(net_1->get_name(), "'0'");
1986 
1987  Net* net_2 = gate_0->get_fan_in_net("ADDR(2)");
1988  ASSERT_NE(net_2, nullptr);
1989  EXPECT_EQ(net_2->get_name(), "'1'");
1990 
1991  Net* net_3 = gate_0->get_fan_in_net("ADDR(3)");
1992  ASSERT_NE(net_3, nullptr);
1993  EXPECT_EQ(net_3->get_name(), "'0'");
1994  }
1995  {
1996  // Connect a vector of output pins with a vector of nets (O(0) with l_vec(0),...,O(4) with l_vec(4))
1997  std::string netlist_input("-- Device\t: device_name\n"
1998  "entity TEST_Comp is\n"
1999  " port (\n"
2000  " );\n"
2001  "end TEST_Comp;\n"
2002  "architecture STRUCTURE of TEST_Comp is\n"
2003  " signal l_vec : STD_LOGIC_VECTOR ( 3 downto 0 );\n"
2004  "begin\n"
2005  " gate_0 : RAM\n"
2006  " port map (\n"
2007  " DATA_OUT => l_vec\n"
2008  " );\n"
2009  "end STRUCTURE;");
2010  const GateLibrary* gate_lib = test_utils::get_gate_library();
2011  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2012  VHDLParser vhdl_parser;
2013  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2014  ASSERT_TRUE(nl_res.is_ok());
2015  std::unique_ptr<Netlist> nl = nl_res.get();
2016 
2017  ASSERT_NE(nl, nullptr);
2018  ASSERT_FALSE(nl->get_gates(test_utils::gate_filter("RAM", "gate_0")).empty());
2019  Gate* gate_0 = *(nl->get_gates(test_utils::gate_filter("RAM", "gate_0")).begin());
2020 
2021  EXPECT_EQ(gate_0->get_fan_out_nets().size(), 4);
2022 
2023  Net* net_0 = gate_0->get_fan_out_net("DATA_OUT(0)");
2024  ASSERT_NE(net_0, nullptr);
2025  EXPECT_EQ(net_0->get_name(), "l_vec(0)");
2026 
2027  Net* net_1 = gate_0->get_fan_out_net("DATA_OUT(1)");
2028  ASSERT_NE(net_1, nullptr);
2029  EXPECT_EQ(net_1->get_name(), "l_vec(1)");
2030 
2031  Net* net_2 = gate_0->get_fan_out_net("DATA_OUT(2)");
2032  ASSERT_NE(net_2, nullptr);
2033  EXPECT_EQ(net_2->get_name(), "l_vec(2)");
2034 
2035  Net* net_3 = gate_0->get_fan_out_net("DATA_OUT(3)");
2036  ASSERT_NE(net_3, nullptr);
2037  EXPECT_EQ(net_3->get_name(), "l_vec(3)");
2038  }
2039  // ---- Vhdl specific: Pin ranges ----
2040  {
2041  // Connect a vector of output pins with a vector of nets by using the to and the downto statment
2042  std::string netlist_input("-- Device\t: device_name\n"
2043  "entity TEST_Comp is\n"
2044  " port (\n"
2045  " );\n"
2046  "end TEST_Comp;\n"
2047  "architecture STRUCTURE of TEST_Comp is\n"
2048  " signal l_vec : STD_LOGIC_VECTOR ( 3 downto 0 );\n"
2049  "begin\n"
2050  " gate_0 : RAM\n"
2051  " port map (\n"
2052  " DATA_OUT(3 downto 2) => l_vec(2 downto 1)\n"
2053  " );\n"
2054  "end STRUCTURE;");
2055  const GateLibrary* gate_lib = test_utils::get_gate_library();
2056  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2057  VHDLParser vhdl_parser;
2058  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2059  ASSERT_TRUE(nl_res.is_ok());
2060  std::unique_ptr<Netlist> nl = nl_res.get();
2061 
2062  ASSERT_NE(nl, nullptr);
2063  ASSERT_FALSE(nl->get_gates(test_utils::gate_filter("RAM", "gate_0")).empty());
2064  Gate* gate_0 = *(nl->get_gates(test_utils::gate_filter("RAM", "gate_0")).begin());
2065 
2066  EXPECT_EQ(gate_0->get_fan_out_nets().size(), 2);
2067 
2068  Net* net_1 = gate_0->get_fan_out_net("DATA_OUT(3)");
2069  ASSERT_NE(net_1, nullptr);
2070  EXPECT_EQ(net_1->get_name(), "l_vec(2)");
2071 
2072  Net* net_2 = gate_0->get_fan_out_net("DATA_OUT(2)");
2073  ASSERT_NE(net_2, nullptr);
2074  EXPECT_EQ(net_2->get_name(), "l_vec(1)");
2075  }
2076  {
2077  // Connect a vector of output pins with a vector of nets by using the to and the downto statment (flipped around)
2078  std::string netlist_input("-- Device\t: device_name\n"
2079  "entity TEST_Comp is\n"
2080  " port (\n"
2081  " );\n"
2082  "end TEST_Comp;\n"
2083  "architecture STRUCTURE of TEST_Comp is\n"
2084  " signal l_vec : STD_LOGIC_VECTOR ( 3 downto 0 );\n"
2085  "begin\n"
2086  " gate_0 : RAM\n"
2087  " port map (\n"
2088  " DATA_OUT(2 to 3) => l_vec(2 downto 1)\n"
2089  " );\n"
2090  "end STRUCTURE;");
2091  const GateLibrary* gate_lib = test_utils::get_gate_library();
2092  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2093  VHDLParser vhdl_parser;
2094  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2095  ASSERT_TRUE(nl_res.is_ok());
2096  std::unique_ptr<Netlist> nl = nl_res.get();
2097 
2098  ASSERT_NE(nl, nullptr);
2099  ASSERT_FALSE(nl->get_gates(test_utils::gate_filter("RAM", "gate_0")).empty());
2100  Gate* gate_0 = *(nl->get_gates(test_utils::gate_filter("RAM", "gate_0")).begin());
2101 
2102  EXPECT_EQ(gate_0->get_fan_out_nets().size(), 2);
2103 
2104  Net* net_1 = gate_0->get_fan_out_net("DATA_OUT(2)");
2105  ASSERT_NE(net_1, nullptr);
2106  EXPECT_EQ(net_1->get_name(), "l_vec(2)");
2107 
2108  Net* net_2 = gate_0->get_fan_out_net("DATA_OUT(3)");
2109  ASSERT_NE(net_2, nullptr);
2110  EXPECT_EQ(net_2->get_name(), "l_vec(1)");
2111  }
2112  TEST_END
2113  }
2114 
2115  /*#########################################################################
2116  VHDL Specific Tests (Tests that can not be directly applied to Verilog)
2117  #########################################################################*/
2118 
2124  TEST_F(VHDLParserTest, check_comments) {
2125 
2126  TEST_START
2127  {
2128  // Store an instance of all possible data types in one Gate
2129  std::string netlist_input("-- Device\t: device_name\n"
2130  "entity TEST_Comp is "
2131  " port ( "
2132  " net_global_input : in STD_LOGIC := 'X'; "
2133  " ); "
2134  "end TEST_Comp; "
2135  "architecture STRUCTURE of TEST_Comp is "
2136  "begin"
2137  " test_gate : BUF"
2138  " generic map(\n"
2139  " no_comment_0 => 123, -- comment_0 => 123, \t --comment_1 => 123\n"
2140  " no_comment_1 => 123,\n"
2141  " -- comment_2 => 123,\n"
2142  " no_comment_2 => 123\n"
2143  " )\n"
2144  " port map ( "
2145  " I => net_global_input "
2146  " ); "
2147  "end STRUCTURE;");
2148  const GateLibrary* gate_lib = test_utils::get_gate_library();
2149  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2150  VHDLParser vhdl_parser;
2151  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2152  ASSERT_TRUE(nl_res.is_ok());
2153  std::unique_ptr<Netlist> nl = nl_res.get();
2154 
2155  ASSERT_NE(nl, nullptr);
2156  ASSERT_EQ(nl->get_gates(test_utils::gate_filter("BUF", "test_gate")).size(), 1);
2157  Gate* test_gate = *nl->get_gates(test_utils::gate_filter("BUF", "test_gate")).begin();
2158 
2159  // Test that the comments did not removed other parts (all no_comment_n generics should be created)
2160  for (std::string key : std::set<std::string>({"no_comment_0", "no_comment_1", "no_comment_2"})) {
2161  EXPECT_NE(test_gate->get_data("generic", key), std::make_tuple("", ""));
2162  if (test_gate->get_data("generic", key) == std::make_tuple("", "")) {
2163  std::cout << "comment test failed for: " << key << std::endl;
2164  }
2165  }
2166 
2167  // Test that the comments are not interpreted (all comment_n generics shouldn't be created)
2168  for (std::string key : std::set<std::string>({"comment_0", "comment_1", "comment_2"})) {
2169  EXPECT_EQ(test_gate->get_data("generic", key), std::make_tuple("", ""));
2170  if (test_gate->get_data("generic", key) != std::make_tuple("", "")) {
2171  std::cout << "comment failed for: " << key << std::endl;
2172  }
2173  }
2174  }
2175  TEST_END
2176  }
2177 
2183  TEST_F(VHDLParserTest, check_attributes) {
2184 
2185  TEST_START
2186  {
2187  // Add a custom attribute for a Gate
2188  std::string netlist_input("-- Device\t: device_name\n"
2189  "entity TEST_Comp is\n"
2190  " port (\n"
2191  " net_global_in : in STD_LOGIC := 'X';\n"
2192  " net_global_out : out STD_LOGIC := 'X';\n"
2193  " );\n"
2194  "end TEST_Comp;\n"
2195  "architecture STRUCTURE of TEST_Comp is\n"
2196  " attribute attri_name : attri_type;\n"
2197  " attribute attri_name of gate_0 : label is attri_value;\n"
2198  "begin\n"
2199  " gate_0 : BUF\n"
2200  " port map (\n"
2201  " I => net_global_in,\n"
2202  " O => net_global_out\n"
2203  " );\n"
2204  "end STRUCTURE;");
2205  const GateLibrary* gate_lib = test_utils::get_gate_library();
2206  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2207  VHDLParser vhdl_parser;
2208  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2209  ASSERT_TRUE(nl_res.is_ok());
2210  std::unique_ptr<Netlist> nl = nl_res.get();
2211 
2212  ASSERT_NE(nl, nullptr);
2213  ASSERT_EQ(nl->get_gates(test_utils::gate_type_filter("BUF")).size(), 1);
2214  Gate* attri_gate = *nl->get_gates(test_utils::gate_type_filter("BUF")).begin();
2215  EXPECT_EQ(attri_gate->get_data("attribute", "attri_name"),
2216  std::make_tuple("attri_type", "attri_value"));
2217  }
2218  {
2219  // Add a custom attribute for a Net
2220  std::string netlist_input("-- Device\t: device_name\n"
2221  "entity TEST_Comp is\n"
2222  " port (\n"
2223  " net_global_in : in STD_LOGIC := 'X';\n"
2224  " net_global_out : out STD_LOGIC := 'X';\n"
2225  " );\n"
2226  "end TEST_Comp;\n"
2227  "architecture STRUCTURE of TEST_Comp is\n"
2228  " signal net_0 : STD_LOGIC;\n"
2229  " attribute attri_name : attri_type;\n"
2230  " attribute attri_name of net_0 : signal is \"attri_value\";\n"
2231  "begin\n"
2232  " gate_0 : BUF\n"
2233  " port map (\n"
2234  " I => net_global_in,\n"
2235  " O => net_0\n"
2236  " );\n"
2237  " gate_1 : BUF\n"
2238  " port map (\n"
2239  " I => net_0,\n"
2240  " O => net_global_out\n"
2241  " );\n"
2242  "end STRUCTURE;");
2243  const GateLibrary* gate_lib = test_utils::get_gate_library();
2244  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2245  VHDLParser vhdl_parser;
2246  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2247  ASSERT_TRUE(nl_res.is_ok());
2248  std::unique_ptr<Netlist> nl = nl_res.get();
2249 
2250  ASSERT_NE(nl, nullptr);
2251  ASSERT_EQ(nl->get_nets(test_utils::net_name_filter("net_0")).size(), 1);
2252  Net* attri_net = *nl->get_nets(test_utils::net_name_filter("net_0")).begin();
2253  EXPECT_NE(attri_net, nullptr);
2254  EXPECT_EQ(attri_net->get_data("attribute", "attri_name"),
2255  std::make_tuple("attri_type", "attri_value"));
2256  }
2257  {
2258  // Use atrribute strings with special characters (',','.')
2259  std::string netlist_input("-- Device\t: device_name\n"
2260  "entity TEST_Comp is\n"
2261  " port (\n"
2262  " net_global_in : in STD_LOGIC := 'X';\n"
2263  " net_global_out : out STD_LOGIC := 'X';\n"
2264  " );\n"
2265  "end TEST_Comp;\n"
2266  "architecture STRUCTURE of TEST_Comp is\n"
2267  " signal net_0 : STD_LOGIC;\n"
2268  " attribute attri_comma_string : attri_type_0;\n"
2269  " attribute attri_comma_string of net_0 : signal is \"test, 1, 2, 3\";\n"
2270  " attribute attri_float_string : attri_type_1;\n"
2271  " attribute attri_float_string of gate_0 : label is \"1.234\";\n"
2272  "begin\n"
2273  " gate_0 : BUF\n"
2274  " port map (\n"
2275  " I => net_global_in,\n"
2276  " O => net_0\n"
2277  " );\n"
2278  " gate_1 : BUF\n"
2279  " port map (\n"
2280  " I => net_0,\n"
2281  " O => net_global_out\n"
2282  " );\n"
2283  "end STRUCTURE;");
2284  const GateLibrary* gate_lib = test_utils::get_gate_library();
2285  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2286  VHDLParser vhdl_parser;
2287  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2288  ASSERT_TRUE(nl_res.is_ok());
2289  std::unique_ptr<Netlist> nl = nl_res.get();
2290 
2291  ASSERT_NE(nl, nullptr);
2292  ASSERT_EQ(nl->get_nets(test_utils::net_name_filter("net_0")).size(), 1);
2293  Net* attri_net = *nl->get_nets(test_utils::net_name_filter("net_0")).begin();
2294  EXPECT_NE(attri_net, nullptr);
2295 
2296  ASSERT_EQ(nl->get_gates(test_utils::gate_name_filter("gate_0")).size(), 1);
2297  Gate* attri_gate = *nl->get_gates(test_utils::gate_name_filter("gate_0")).begin();
2298 
2299  // Check the attributes
2300  EXPECT_EQ(attri_net->get_data("attribute", "attri_comma_string"),
2301  std::make_tuple("attri_type_0", "test, 1, 2, 3"));
2302  EXPECT_EQ(attri_gate->get_data("attribute", "attri_float_string"),
2303  std::make_tuple("attri_type_1", "1.234"));
2304  }
2305  TEST_END
2306  }
2307 
2313  TEST_F(VHDLParserTest, check_lib_prefix) {
2314  TEST_START
2315  // The prefix of the library SIMPRIM.VCOMPONENTS should be removed from the INV Gate type
2316  std::string netlist_input("-- Device\t: device_name\n"
2317  "library SIMPRIM;\n"
2318  "use SIMPRIM.VCOMPONENTS.ALL;\n"
2319  "entity TEST_Comp is\n"
2320  " port (\n"
2321  " net_global_input : in STD_LOGIC := 'X';\n"
2322  " );\n"
2323  "end TEST_Comp;\n"
2324  "architecture STRUCTURE of TEST_Comp is\n"
2325  "begin\n"
2326  " gate_0 : SIMPRIM.VCOMPONENTS.BUF\n"
2327  " port map (\n"
2328  " I => net_global_input\n"
2329  " );\n"
2330  "end STRUCTURE;");
2331  const GateLibrary* gate_lib = test_utils::get_gate_library();
2332  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2333  VHDLParser vhdl_parser;
2334  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2335  ASSERT_TRUE(nl_res.is_ok());
2336  std::unique_ptr<Netlist> nl = nl_res.get();
2337 
2338  ASSERT_NE(nl, nullptr);
2339 
2340  EXPECT_EQ(nl->get_gates(test_utils::gate_type_filter("BUF")).size(), 1);
2341  TEST_END
2342  }
2343 
2350  TEST_F(VHDLParserTest, check_component) {
2351 
2352  TEST_START
2353  /*{ // NOTE: Currently Unsupported
2354  // Add a component in the architecture header and instantiate a Gate of it
2355  std::string netlist_input("-- Device\t: device_name\n"
2356  "entity TEST_Comp is\n"
2357  " port (\n"
2358  " net_global_in : in STD_LOGIC := 'X';\n"
2359  " net_global_out : out STD_LOGIC := 'X';\n"
2360  " );\n"
2361  "end TEST_Comp;\n"
2362  "architecture STRUCTURE of TEST_Comp is\n"
2363  " component COMP_GATE\n"
2364  " port (\n"
2365  " COMP_IN : in STD_LOGIC;\n"
2366  " COMP_OUT : out STD_LOGIC;\n"
2367  " COMP_INOUT : in STD_LOGIC;\n"
2368  " );\n"
2369  " end component ;\n"
2370  "begin\n"
2371  " gate_0 : COMP_GATE\n"
2372  " port map (\n"
2373  " COMP_IN => net_global_in,\n"
2374  " COMP_OUT => net_global_out\n"
2375  " );\n"
2376  "end STRUCTURE;");
2377  test_def::capture_stdout();
2378  VHDLParser vhdl_parser;
2379  std::unique_ptr<Netlist> nl = vhdl_parser.parse_and_instantiate(g_lib_name);
2380  if (nl == nullptr) {
2381  std::cout << test_def::get_captured_stdout();
2382  } else {
2383  test_def::get_captured_stdout();
2384  }
2385  ASSERT_NE(nl, nullptr);
2386  ASSERT_EQ(nl->get_gates(gate_type_filter("COMP_GATE")).size(), 1);
2387  Gate* comp_gate = *nl->get_gates(gate_type_filter("COMP_GATE")).begin();
2388  EXPECT_NE(comp_gate->get_fan_in_net("COMP_IN"), nullptr);
2389  EXPECT_NE(comp_gate->get_fan_out_net("COMP_OUT"), nullptr);
2390  // EXPECT_EQ(comp_gate->get_inout_pin_types(), std::vector<std::string>({"COMP_INOUT"}));
2391  }*/
2392 
2393  TEST_END
2394  }
2395 
2401  TEST_F(VHDLParserTest, check_invalid_input) {
2402  TEST_START
2403  // ------ Tests that are present in booth parsers ------
2404  {
2405  // Try to connect to a pin, that does not exist
2406  NO_COUT_TEST_BLOCK;
2407  std::string netlist_input("-- Device\t: device_name\n"
2408  "entity TEST_Comp is\n"
2409  " port (\n"
2410  " global_in: in STD_LOGIC := 'X';\n"
2411  " );\n"
2412  "end TEST_Comp;\n"
2413  "architecture STRUCTURE of TEST_Comp is\n"
2414  "begin\n"
2415  " gate_0 : BUF\n"
2416  " port map (\n"
2417  " NON_EXISTING_PIN => global_in\n"
2418  " );\n"
2419  "end STRUCTURE;");
2420  const GateLibrary* gate_lib = test_utils::get_gate_library();
2421  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2422  VHDLParser vhdl_parser;
2423  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2424  EXPECT_TRUE(nl_res.is_error());
2425  }
2426  {
2427  // Use an unknown Gate type (not in Gate library)
2428  NO_COUT_TEST_BLOCK;
2429  std::string netlist_input("-- Device\t: device_name\n"
2430  "entity TEST_Comp is\n"
2431  " port (\n"
2432  " net_global_in : in STD_LOGIC := 'X';\n"
2433  " net_global_out : out STD_LOGIC := 'X';\n"
2434  " );\n"
2435  "end TEST_Comp;\n"
2436  "architecture STRUCTURE of TEST_Comp is\n"
2437  "begin\n"
2438  " gate_0 : UNKNOWN_GATE_TYPE\n"
2439  " port map (\n"
2440  " I => net_global_in,\n"
2441  " O => net_global_out\n"
2442  " );\n"
2443  "end STRUCTURE;");
2444  const GateLibrary* gate_lib = test_utils::get_gate_library();
2445  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2446  VHDLParser vhdl_parser;
2447  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2448  EXPECT_TRUE(nl_res.is_error());
2449  }
2450  {
2451  // The input does not contain any entity (is empty)
2452  NO_COUT_TEST_BLOCK;
2453  std::string netlist_input("");
2454  const GateLibrary* gate_lib = test_utils::get_gate_library();
2455  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2456  VHDLParser vhdl_parser;
2457  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2458  EXPECT_TRUE(nl_res.is_error());
2459  }
2460  /* non-used entity _WILL_ create problems (erroneously considered as top module)
2461  {
2462  // Create a non-used entity (should not create any problems...)
2463  NO_COUT_TEST_BLOCK;
2464  std::string netlist_input("-- Device\t: device_name\n"
2465  "entity IGNORE_ME is\n"
2466  " port (\n"
2467  " min : in STD_LOGIC := 'X';\n"
2468  " mout : out STD_LOGIC := 'X';\n"
2469  " );\n"
2470  "end TEST_Comp;\n"
2471  "architecture STRUCTURE of IGNORE_ME is\n"
2472  "begin\n"
2473  " gate_0 : BUF\n"
2474  " port map (\n"
2475  " I => min,\n"
2476  " O => mout\n"
2477  " );\n"
2478  "end STRUCTURE;\n"
2479  ""
2480  "entity TEST_Comp is\n"
2481  " port (\n"
2482  " net_global_in : in STD_LOGIC := 'X';\n"
2483  " net_global_out : out STD_LOGIC := 'X';\n"
2484  " );\n"
2485  "end TEST_Comp;\n"
2486  "architecture STRUCTURE of TEST_Comp is\n"
2487  "begin\n"
2488  " gate_0 : BUF\n"
2489  " port map (\n"
2490  " I => net_global_in,\n"
2491  " O => net_global_out\n"
2492  " );\n"
2493  "end STRUCTURE;");
2494  auto vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2495  VHDLParser vhdl_parser;
2496  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, m_gl);
2497  ASSERT_TRUE(nl_res.is_ok());
2498  std::unique_ptr<Netlist> nl = nl_res.get();
2499 
2500  EXPECT_NE(nl, nullptr);
2501  }
2502  */
2503  if(test_utils::known_issue_tests_active())
2504  {
2505  // Use non-numeric ranges (invalid) (ISSUE: stoi failure l.827)
2506  std::string netlist_input("-- Device\t: device_name\n"
2507  "entity TEST_Comp is\n"
2508  " port (\n"
2509  " );\n"
2510  "end TEST_Comp;\n"
2511  "architecture STRUCTURE of TEST_Comp is\n"
2512  " signal l_vec : STD_LOGIC_VECTOR ( 4 downto 0 );\n"
2513  "begin\n"
2514  " gate_0 : RAM\n"
2515  " port map (\n"
2516  " O(p downto q) => l_vec(p downto q)\n" // <- fails booth independently (l.827)
2517  " );\n"
2518  "end STRUCTURE;");
2519  const GateLibrary* gate_lib = test_utils::get_gate_library();
2520  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2521  VHDLParser vhdl_parser;
2522  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2523  EXPECT_TRUE(nl_res.is_error());
2524  }
2525  // ------ VHDL specific tests ------
2526  {
2527  // The entity contains unknown direction keywords (neither 'in', 'out' nor 'inout')
2528  NO_COUT_TEST_BLOCK;
2529  std::string netlist_input("-- Device\t: device_name\n"
2530  "entity TEST_Comp is\n"
2531  " port (\n"
2532  " net_global_input : invalid_direction STD_LOGIC := 'X';\n" // <- invalid direction
2533  " );\n"
2534  "end TEST_Comp;\n"
2535  "architecture STRUCTURE of TEST_Comp is\n"
2536  "begin\n"
2537  " gate_0 : BUF\n"
2538  " port map (\n"
2539  " O => net_global_input\n"
2540  " );\n"
2541  "end STRUCTURE;");
2542  const GateLibrary* gate_lib = test_utils::get_gate_library();
2543  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2544  VHDLParser vhdl_parser;
2545  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2546  EXPECT_TRUE(nl_res.is_error());
2547  }
2548  {
2549  // The architecture contains an invalid keyword (neither 'signal' nor 'attribute')
2550  NO_COUT_TEST_BLOCK;
2551  std::string netlist_input("-- Device\t: device_name\n"
2552  "entity TEST_Comp is\n"
2553  " port (\n"
2554  " net_global_input : in STD_LOGIC := 'X';\n"
2555  " );\n"
2556  "end TEST_Comp;\n"
2557  "architecture STRUCTURE of TEST_Comp is\n"
2558  "unknown_keyword some_signal : STD_LOGIC;" // <- invalid keyword
2559  "begin\n"
2560  " gate_0 : BUF\n"
2561  " port map (\n"
2562  " O => net_global_input\n"
2563  " );\n"
2564  "end STRUCTURE;");
2565  const GateLibrary* gate_lib = test_utils::get_gate_library();
2566  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2567  VHDLParser vhdl_parser;
2568  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2569  EXPECT_TRUE(nl_res.is_error());
2570  }
2571  {
2572  // Testing incorrect data_types in the "generic map" block
2573  NO_COUT_TEST_BLOCK;
2574  std::string netlist_input("-- Device\t: device_name\n"
2575  "entity TEST_Comp is\n"
2576  " port (\n"
2577  " net_global_input : in STD_LOGIC := 'X';\n"
2578  " );\n"
2579  "end TEST_Comp;\n"
2580  "architecture STRUCTURE of TEST_Comp is\n"
2581  "begin\n"
2582  " gate_0 : BUF\n"
2583  " generic map(\n"
2584  " key_invalid_type => Inv4lid_type\n" // <- The format of 'Inv4lid_type' matches with no data_type
2585  " )\n"
2586  " port map (\n"
2587  " I => net_global_input\n"
2588  " );\n"
2589  "end STRUCTURE;");
2590  const GateLibrary* gate_lib = test_utils::get_gate_library();
2591  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2592  VHDLParser vhdl_parser;
2593  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2594  EXPECT_TRUE(nl_res.is_error());
2595  }
2596  {
2597  // Leave the 'port map' block empty (Gate is not connected)
2598  // NO_COUT_TEST_BLOCK;
2599  std::string netlist_input("-- Device\t: device_name\n"
2600  "entity TEST_Comp is\n"
2601  " port (\n"
2602  " );\n"
2603  "end TEST_Comp;\n"
2604  "architecture STRUCTURE of TEST_Comp is\n"
2605  "begin\n"
2606  " gate_0 : BUF\n"
2607  " port map (\n"
2608  " );\n"
2609  "end STRUCTURE;");
2610  const GateLibrary* gate_lib = test_utils::get_gate_library();
2611  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2612  VHDLParser vhdl_parser;
2613  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2614  ASSERT_TRUE(nl_res.is_ok());
2615  std::unique_ptr<Netlist> nl = nl_res.get();
2616  ASSERT_NE(nl, nullptr);
2617  ASSERT_FALSE(nl->get_gates(test_utils::gate_filter("BUF", "gate_0")).empty());
2618  Gate* gate_0 = *nl->get_gates(test_utils::gate_filter("BUF", "gate_0")).begin();
2619  EXPECT_TRUE(gate_0->get_fan_out_nets().empty());
2620  EXPECT_TRUE(gate_0->get_fan_in_nets().empty());
2621  }
2622  {
2623  // Use an undeclared attribute (an attribute of type 'unknown' should be created)
2624  NO_COUT_TEST_BLOCK;
2625  std::string netlist_input("-- Device\t: device_name\n"
2626  "entity TEST_Comp is\n"
2627  " port (\n"
2628  " net_global_in : in STD_LOGIC := 'X';\n"
2629  " net_global_out : out STD_LOGIC := 'X';\n"
2630  " );\n"
2631  "end TEST_Comp;\n"
2632  "architecture STRUCTURE of TEST_Comp is\n"
2633  " attribute attri_name of gate_0 : label is attri_value;\n"
2634  "begin\n"
2635  " gate_0 : BUF\n"
2636  " port map (\n"
2637  " I => net_global_in,\n"
2638  " O => net_global_out\n"
2639  " );\n"
2640  "end STRUCTURE;");
2641  const GateLibrary* gate_lib = test_utils::get_gate_library();
2642  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2643  VHDLParser vhdl_parser;
2644  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2645  ASSERT_TRUE(nl_res.is_ok());
2646  std::unique_ptr<Netlist> nl = nl_res.get();
2647 
2648  EXPECT_NE(nl, nullptr);
2649  ASSERT_EQ(nl->get_gates(test_utils::gate_type_filter("BUF")).size(), 1);
2650  Gate* attri_gate = *nl->get_gates(test_utils::gate_type_filter("BUF")).begin();
2651  EXPECT_EQ(attri_gate->get_data("attribute", "attri_name"),
2652  std::make_tuple("unknown", "attri_value"));
2653  }
2654  {
2655  // Use the 'attribute'-keyword in an unexpected way
2656  NO_COUT_TEST_BLOCK;
2657  std::string netlist_input("-- Device\t: device_name\n"
2658  "entity TEST_Comp is\n"
2659  " port (\n"
2660  " net_global_in : in STD_LOGIC := 'X';\n"
2661  " net_global_out : out STD_LOGIC := 'X';\n"
2662  " );\n"
2663  "end TEST_Comp;\n"
2664  "architecture STRUCTURE of TEST_Comp is\n"
2665  " attribute WAMBO;\n" // <- attributes do not work like this
2666  "begin\n"
2667  " gate_0 : BUF\n"
2668  " port map (\n"
2669  " I => net_global_in,\n"
2670  " O => net_global_out\n"
2671  " );\n"
2672  "end STRUCTURE;");
2673  const GateLibrary* gate_lib = test_utils::get_gate_library();
2674  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2675  VHDLParser vhdl_parser;
2676  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2677  EXPECT_TRUE(nl_res.is_error());
2678  }
2679  {
2680  // The amount of bounds does not match with the vector dimension (vhdl specific)
2681  NO_COUT_TEST_BLOCK;
2682  std::string netlist_input("-- Device\t: device_name\n"
2683  "entity TEST_Comp is\n"
2684  " port (\n"
2685  " net_global_input : in STD_LOGIC := 'X';\n"
2686  " );\n"
2687  "end TEST_Comp;\n"
2688  "architecture STRUCTURE of TEST_Comp is\n"
2689  " signal n_vec : STD_LOGIC_VECTOR3 ( 0 to 1, 0 to 1);\n" // <- two bounds, but dimension 3
2690  "begin\n"
2691  " gate_0 : BUF\n"
2692  " port map (\n"
2693  " O => net_global_input\n"
2694  " );\n"
2695  "end STRUCTURE;");
2696  const GateLibrary* gate_lib = test_utils::get_gate_library();
2697  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2698  VHDLParser vhdl_parser;
2699  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2700  EXPECT_TRUE(nl_res.is_error());
2701  }
2702  {
2703  // The ranges of the pin vectors do not match in size
2704  std::string netlist_input("-- Device\t: device_name\n"
2705  "entity TEST_Comp is\n"
2706  " port (\n"
2707  " );\n"
2708  "end TEST_Comp;\n"
2709  "architecture STRUCTURE of TEST_Comp is\n"
2710  " signal l_vec : STD_LOGIC_VECTOR ( 0 to 3 );\n"
2711  "begin\n"
2712  " gate_0 : RAM\n"
2713  " port map (\n"
2714  " DATA_OUT(0 to 2) => l_vec(0 to 3)\n"
2715  " );\n"
2716  "end STRUCTURE;");
2717  const GateLibrary* gate_lib = test_utils::get_gate_library();
2718  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2719  VHDLParser vhdl_parser;
2720  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2721  EXPECT_TRUE(nl_res.is_error());
2722  }
2723  {
2724  // The right side of a pin assignment does no match any vector format
2725  NO_COUT_TEST_BLOCK;
2726  std::string netlist_input("-- Device\t: device_name\n"
2727  "entity TEST_Comp is\n"
2728  " port (\n"
2729  " );\n"
2730  "end TEST_Comp;\n"
2731  "architecture STRUCTURE of TEST_Comp is\n"
2732  "begin\n"
2733  " gate_0 : RAM\n"
2734  " port map (\n"
2735  " ADDR(1 to 3) => Unkn0wn_Format\n" // <- unknown format
2736  " );\n"
2737  "end STRUCTURE;");
2738  const GateLibrary* gate_lib = test_utils::get_gate_library();
2739  std::filesystem::path vhdl_file = test_utils::create_sandbox_file("netlist.v", netlist_input);
2740  VHDLParser vhdl_parser;
2741  auto nl_res = vhdl_parser.parse_and_instantiate(vhdl_file, gate_lib);
2742  EXPECT_TRUE(nl_res.is_error());
2743  }
2744  TEST_END
2745  }
2746 } //namespace hal
std::tuple< std::string, std::string > get_data(const std::string &category, const std::string &key) const
Net * get_net() const
Definition: endpoint.cpp:33
Gate * get_gate() const
Definition: endpoint.cpp:23
Definition: gate.h:58
Net * get_fan_in_net(const std::string &pin_name) const
Definition: gate.cpp:617
const std::vector< Net * > & get_fan_in_nets() const
Definition: gate.cpp:591
Net * get_fan_out_net(const std::string &pin_name) const
Definition: gate.cpp:761
const std::string & get_name() const
Definition: gate.cpp:105
Endpoint * get_fan_in_endpoint(const std::string &pin_name) const
Definition: gate.cpp:679
Endpoint * get_successor(const std::string &pin_name) const
Definition: gate.cpp:1018
const std::vector< Net * > & get_fan_out_nets() const
Definition: gate.cpp:735
Endpoint * get_fan_out_endpoint(const std::string &pin_name) const
Definition: gate.cpp:823
std::vector< ModulePin * > get_pins(const std::function< bool(ModulePin *)> &filter=nullptr) const
Definition: module.cpp:871
bool is_top_module() const
Definition: module.cpp:312
const std::vector< Gate * > & get_gates() const
Definition: module.cpp:391
std::string get_name() const
Definition: module.cpp:87
std::vector< Module * > get_submodules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=false) const
Definition: module.cpp:259
std::string get_type() const
Definition: module.cpp:106
const std::unordered_set< Net * > & get_output_nets() const
Definition: module.cpp:545
Definition: net.h:58
const std::string & get_name() const
Definition: net.cpp:98
std::vector< Endpoint * > get_destinations(const std::function< bool(Endpoint *ep)> &filter=nullptr) const
Definition: net.cpp:426
bool is_global_input_net() const
Definition: net.cpp:480
std::vector< Endpoint * > get_sources(const std::function< bool(Endpoint *ep)> &filter=nullptr) const
Definition: net.cpp:264
Result< std::unique_ptr< Netlist > > parse_and_instantiate(const std::filesystem::path &file_path, const GateLibrary *gate_library)
virtual void TearDown()
Definition: vhdl_parser.cpp:19
virtual void SetUp()
Definition: vhdl_parser.cpp:12
GateLibrary * get_gate_library(const std::string &file_path)
CORE_API bool starts_with(const T &s, const T &start)
Definition: utils.h:167
bool vectors_have_same_content(std::vector< T > vec_1, std::vector< T > vec_2)
Definition: utils.h:78
TEST_F(HGLParserTest, check_library)
Definition: hgl_parser.cpp:26
n
Definition: test.py:6