2 # yosys -- Yosys Open SYnthesis Suite
4 # Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 # Permission to use, copy, modify, and/or distribute this software for any
7 # purpose with or without fee is hereby granted, provided that the above
8 # copyright notice and this permission notice appear in all copies.
10 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 # Author Benedikt Tutzer
23 #Map c++ operator Syntax to Python functions
24 wrappable_operators
= {
35 #Restrict certain strings from being function names in Python
46 "continue" : "continue_",
60 "nonlocal" : "nonlocal_",
72 #These can be used without any explicit conversion
73 primitive_types
= ["void", "bool", "int", "double", "size_t", "std::string",
74 "string", "State", "char_p"]
78 #Ways to link between Python- and C++ Objects
79 class link_types(Enum
):
80 global_list
= 1 #Manage a global list of objects in C++, the Python
81 #object contains a key to find the corresponding C++
82 #object and a Pointer to the object to verify it is
83 #still the same, making collisions unlikely to happen
84 ref_copy
= 2 #The Python object contains a copy of the C++ object.
85 #The C++ object is deleted when the Python object gets
87 pointer
= 3 #The Python Object contains a pointer to it's C++
89 derive
= 4 #The Python-Wrapper is derived from the C++ object.
91 class attr_types(Enum
):
102 def __init__(self
, name
, classes
):
104 self
.classes
= classes
106 #Splits a list by the given delimiter, without splitting strings inside
107 #pointy-brackets (< and >)
108 def split_list(str_def
, delim
):
109 str_def
= str_def
.strip()
110 if len(str_def
) == 0:
112 if str_def
.count(delim
) == 0:
114 if str_def
.count("<") == 0:
115 return str_def
.split(delim
)
116 if str_def
.find("<") < str_def
.find(" "):
117 closing
= find_closing(str_def
[str_def
.find("<")+1:], "<", ">") + str_def
.find("<")
118 comma
= str_def
[closing
:].find(delim
)
121 comma
= closing
+ comma
123 comma
= str_def
.find(delim
)
124 rest
= split_list(str_def
[comma
+1:], delim
)
125 ret
= [str_def
[:comma
]]
126 if rest
!= None and len(rest
) != 0:
134 attr_type
= attr_types
.default
136 def __init__(self
, name
= "", cont
= None, attr_type
= attr_types
.default
):
139 self
.attr_type
= attr_type
144 if self
.name
in enum_names
:
145 text
= enum_by_name(self
.name
).namespace
+ "::" + self
.name
146 if self
.cont
!= None:
147 return known_containers
[self
.name
].typename
151 def gen_text_cpp(self
):
153 if self
.attr_type
== attr_types
.star
:
155 if self
.name
in primitive_types
:
156 return self
.name
+ postfix
157 if self
.name
in enum_names
:
158 return enum_by_name(self
.name
).namespace
+ "::" + self
.name
+ postfix
159 if self
.name
in classnames
:
160 return class_by_name(self
.name
).namespace
+ "::" + self
.name
+ postfix
162 if self
.cont
!= None:
164 for a
in self
.cont
.args
:
165 text
+= a
.gen_text_cpp() + ", "
171 def from_string(str_def
, containing_file
, line_number
):
172 str_def
= str_def
.strip()
173 if len(str_def
) == 0:
175 str_def
= str_def
.replace("RTLIL::SigSig", "std::pair<SigSpec, SigSpec>").replace("SigSig", "std::pair<SigSpec, SigSpec>")
179 t
.attr_type
= attr_types
.default
180 if str_def
.find("<") != -1:# and str_def.find("<") < str_def.find(" "):
181 candidate
= WContainer
.from_string(str_def
, containing_file
, line_number
)
182 if candidate
== None:
184 t
.name
= str_def
[:str_def
.find("<")]
186 if t
.name
.count("*") + t
.name
.count("&") > 1:
189 if t
.name
.count("*") == 1 or str_def
[0] == '*' or str_def
[-1] == '*':
190 t
.attr_type
= attr_types
.star
191 t
.name
= t
.name
.replace("*","")
192 elif t
.name
.count("&&") == 1:
193 t
.attr_type
= attr_types
.ampamp
194 t
.name
= t
.name
.replace("&&","")
195 elif t
.name
.count("&") == 1 or str_def
[0] == '&' or str_def
[-1] == '&':
196 t
.attr_type
= attr_types
.amp
197 t
.name
= t
.name
.replace("&","")
200 if(t
.name
not in known_containers
):
206 if str.startswith(str_def
, "unsigned "):
208 str_def
= str_def
[9:]
209 while str.startswith(str_def
, "long "):
210 prefix
= "long " + prefix
211 str_def
= str_def
[5:]
212 while str.startswith(str_def
, "short "):
213 prefix
= "short " + prefix
214 str_def
= str_def
[6:]
216 str_def
= str_def
.split("::")[-1]
218 if str_def
.count("*") + str_def
.count("&") >= 2:
221 if str_def
.count("*") == 1:
222 t
.attr_type
= attr_types
.star
223 str_def
= str_def
.replace("*","")
224 elif str_def
.count("&&") == 1:
225 t
.attr_type
= attr_types
.ampamp
226 str_def
= str_def
.replace("&&","")
227 elif str_def
.count("&") == 1:
228 t
.attr_type
= attr_types
.amp
229 str_def
= str_def
.replace("&","")
231 if len(str_def
) > 0 and str_def
.split("::")[-1] not in primitive_types
and str_def
.split("::")[-1] not in classnames
and str_def
.split("::")[-1] not in enum_names
:
234 if str_def
.count(" ") == 0:
235 t
.name
= (prefix
+ str_def
).replace("char_p", "char *")
240 #Represents a container-type
245 def from_string(str_def
, containing_file
, line_number
):
246 if str_def
== None or len(str_def
) < 4:
249 cont
.name
= str_def
[:str_def
.find("<")]
250 str_def
= str_def
[str_def
.find("<")+1:find_closing(str_def
, "<", ">")]
252 for arg
in split_list(str_def
, ","):
253 candidate
= WType
.from_string(arg
.strip(), containing_file
, line_number
)
254 if candidate
== None:
256 cont
.args
.append(candidate
)
259 #Translators between Python and C++ containers
263 typename
= "DefaultType"
264 orig_name
= "DefaultCpp"
267 def gen_type(c
, types
):
268 return "\nImplement a function that outputs the c++ type of this container here\n"
271 def translate(c
, varname
, types
, prefix
):
272 return "\nImplement a function translating a python container to a c++ container here\n"
275 def translate_cpp(c
, varname
, types
, prefix
, ref
):
276 return "\nImplement a function translating a c++ container to a python container here\n"
278 #Translates list-types (vector, pool, set), that only differ in their name and
279 #the name of the insertion function
280 class PythonListTranslator(Translator
):
281 typename
= "boost::python::list"
282 insert_name
= "Default"
284 #generate the c++ type string
286 def gen_type(c
, types
):
287 text
= c
.orig_name
+ "<"
288 if types
[0].name
in primitive_types
:
289 text
+= types
[0].name
290 elif types
[0].name
in known_containers
:
291 text
+= known_containers
[types
[0].name
].gen_type(types
[0].cont
.args
)
293 text
+= class_by_name(types
[0].name
).namespace
+ "::" + types
[0].name
294 if types
[0].attr_type
== attr_types
.star
:
299 #Generate C++ code to translate from a boost::python::list
301 def translate(c
, varname
, types
, prefix
):
302 text
= prefix
+ c
.gen_type(types
) + " " + varname
+ "___tmp;"
303 cntr_name
= "cntr_" + str(Translator
.tmp_cntr
)
304 Translator
.tmp_cntr
= Translator
.tmp_cntr
+ 1
305 text
+= prefix
+ "for(int " + cntr_name
+ " = 0; " + cntr_name
+ " < len(" + varname
+ "); " + cntr_name
+ "++)"
307 tmp_name
= "tmp_" + str(Translator
.tmp_cntr
)
308 Translator
.tmp_cntr
= Translator
.tmp_cntr
+ 1
309 if types
[0].name
in known_containers
:
310 text
+= prefix
+ "\t" + known_containers
[types
[0].name
].typename
+ " " + tmp_name
+ " = boost::python::extract<" + known_containers
[types
[0].name
].typename
+ ">(" + varname
+ "[" + cntr_name
+ "]);"
311 text
+= known_containers
[types
[0].name
].translate(tmp_name
, types
[0].cont
.args
, prefix
+"\t")
312 tmp_name
= tmp_name
+ "___tmp"
313 text
+= prefix
+ "\t" + varname
+ "___tmp." + c
.insert_name
+ "(" + tmp_name
+ ");"
314 elif types
[0].name
in classnames
:
315 text
+= prefix
+ "\t" + types
[0].name
+ "* " + tmp_name
+ " = boost::python::extract<" + types
[0].name
+ "*>(" + varname
+ "[" + cntr_name
+ "]);"
316 if types
[0].attr_type
== attr_types
.star
:
317 text
+= prefix
+ "\t" + varname
+ "___tmp." + c
.insert_name
+ "(" + tmp_name
+ "->get_cpp_obj());"
319 text
+= prefix
+ "\t" + varname
+ "___tmp." + c
.insert_name
+ "(*" + tmp_name
+ "->get_cpp_obj());"
321 text
+= prefix
+ "\t" + types
[0].name
+ " " + tmp_name
+ " = boost::python::extract<" + types
[0].name
+ ">(" + varname
+ "[" + cntr_name
+ "]);"
322 text
+= prefix
+ "\t" + varname
+ "___tmp." + c
.insert_name
+ "(" + tmp_name
+ ");"
326 #Generate C++ code to translate to a boost::python::list
328 def translate_cpp(c
, varname
, types
, prefix
, ref
):
329 text
= prefix
+ c
.typename
+ " " + varname
+ "___tmp;"
330 tmp_name
= "tmp_" + str(Translator
.tmp_cntr
)
331 Translator
.tmp_cntr
= Translator
.tmp_cntr
+ 1
333 text
+= prefix
+ "for(auto " + tmp_name
+ " : *" + varname
+ ")"
335 text
+= prefix
+ "for(auto " + tmp_name
+ " : " + varname
+ ")"
337 if types
[0].name
in classnames
:
338 if types
[0].attr_type
== attr_types
.star
:
339 text
+= prefix
+ "\t" + varname
+ "___tmp.append(" + types
[0].name
+ "::get_py_obj(" + tmp_name
+ "));"
341 text
+= prefix
+ "\t" + varname
+ "___tmp.append(*" + types
[0].name
+ "::get_py_obj(&" + tmp_name
+ "));"
342 elif types
[0].name
in known_containers
:
343 text
+= known_containers
[types
[0].name
].translate_cpp(tmp_name
, types
[0].cont
.args
, prefix
+ "\t", types
[0].attr_type
== attr_types
.star
)
344 text
+= prefix
+ "\t" + varname
+ "___tmp.append(" + tmp_name
+ "___tmp);"
346 text
+= prefix
+ "\t" + varname
+ "___tmp.append(" + tmp_name
+ ");"
350 #Sub-type for std::set
351 class SetTranslator(PythonListTranslator
):
352 insert_name
= "insert"
353 orig_name
= "std::set"
355 #Sub-type for std::vector
356 class VectorTranslator(PythonListTranslator
):
357 insert_name
= "push_back"
358 orig_name
= "std::vector"
361 class PoolTranslator(PythonListTranslator
):
362 insert_name
= "insert"
365 #Translates dict-types (dict, std::map), that only differ in their name and
366 #the name of the insertion function
367 class PythonDictTranslator(Translator
):
368 typename
= "boost::python::dict"
369 insert_name
= "Default"
372 def gen_type(c
, types
):
373 text
= c
.orig_name
+ "<"
374 if types
[0].name
in primitive_types
:
375 text
+= types
[0].name
376 elif types
[0].name
in known_containers
:
377 text
+= known_containers
[types
[0].name
].gen_type(types
[0].cont
.args
)
379 text
+= class_by_name(types
[0].name
).namespace
+ "::" + types
[0].name
380 if types
[0].attr_type
== attr_types
.star
:
383 if types
[1].name
in primitive_types
:
384 text
+= types
[1].name
385 elif types
[1].name
in known_containers
:
386 text
+= known_containers
[types
[1].name
].gen_type(types
[1].cont
.args
)
388 text
+= class_by_name(types
[1].name
).namespace
+ "::" + types
[1].name
389 if types
[1].attr_type
== attr_types
.star
:
394 #Generate c++ code to translate from a boost::python::dict
396 def translate(c
, varname
, types
, prefix
):
397 text
= prefix
+ c
.gen_type(types
) + " " + varname
+ "___tmp;"
398 text
+= prefix
+ "boost::python::list " + varname
+ "_keylist = " + varname
+ ".keys();"
399 cntr_name
= "cntr_" + str(Translator
.tmp_cntr
)
400 Translator
.tmp_cntr
= Translator
.tmp_cntr
+ 1
401 text
+= prefix
+ "for(int " + cntr_name
+ " = 0; " + cntr_name
+ " < len(" + varname
+ "_keylist); " + cntr_name
+ "++)"
403 key_tmp_name
= "key_tmp_" + str(Translator
.tmp_cntr
)
404 val_tmp_name
= "val_tmp_" + str(Translator
.tmp_cntr
)
405 Translator
.tmp_cntr
= Translator
.tmp_cntr
+ 1
407 if types
[0].name
in known_containers
:
408 text
+= prefix
+ "\t" + known_containers
[types
[0].name
].typename
+ " " + key_tmp_name
+ " = boost::python::extract<" + known_containers
[types
[0].name
].typename
+ ">(" + varname
+ "_keylist[ " + cntr_name
+ " ]);"
409 text
+= known_containers
[types
[0].name
].translate(key_tmp_name
, types
[0].cont
.args
, prefix
+"\t")
410 key_tmp_name
= key_tmp_name
+ "___tmp"
411 elif types
[0].name
in classnames
:
412 text
+= prefix
+ "\t" + types
[0].name
+ "* " + key_tmp_name
+ " = boost::python::extract<" + types
[0].name
+ "*>(" + varname
+ "_keylist[ " + cntr_name
+ " ]);"
414 text
+= prefix
+ "\t" + types
[0].name
+ " " + key_tmp_name
+ " = boost::python::extract<" + types
[0].name
+ ">(" + varname
+ "_keylist[ " + cntr_name
+ " ]);"
416 if types
[1].name
in known_containers
:
417 text
+= prefix
+ "\t" + known_containers
[types
[1].name
].typename
+ " " + val_tmp_name
+ " = boost::python::extract<" + known_containers
[types
[1].name
].typename
+ ">(" + varname
+ "[" + varname
+ "_keylist[ " + cntr_name
+ " ]]);"
418 text
+= known_containers
[types
[1].name
].translate(val_tmp_name
, types
[1].cont
.args
, prefix
+"\t")
419 val_tmp_name
= val_tmp_name
+ "___tmp"
420 elif types
[1].name
in classnames
:
421 text
+= prefix
+ "\t" + types
[1].name
+ "* " + val_tmp_name
+ " = boost::python::extract<" + types
[1].name
+ "*>(" + varname
+ "[" + varname
+ "_keylist[ " + cntr_name
+ " ]]);"
423 text
+= prefix
+ "\t" + types
[1].name
+ " " + val_tmp_name
+ " = boost::python::extract<" + types
[1].name
+ ">(" + varname
+ "[" + varname
+ "_keylist[ " + cntr_name
+ " ]]);"
425 text
+= prefix
+ "\t" + varname
+ "___tmp." + c
.insert_name
+ "(std::pair<" + types
[0].gen_text_cpp() + ", " + types
[1].gen_text_cpp() + ">("
427 if types
[0].name
not in classnames
:
430 if types
[0].attr_type
!= attr_types
.star
:
432 text
+= key_tmp_name
+ "->get_cpp_obj()"
435 if types
[1].name
not in classnames
:
438 if types
[1].attr_type
!= attr_types
.star
:
440 text
+= val_tmp_name
+ "->get_cpp_obj()"
441 text
+= "));\n" + prefix
+ "}"
444 #Generate c++ code to translate to a boost::python::dict
446 def translate_cpp(c
, varname
, types
, prefix
, ref
):
447 text
= prefix
+ c
.typename
+ " " + varname
+ "___tmp;"
448 tmp_name
= "tmp_" + str(Translator
.tmp_cntr
)
449 Translator
.tmp_cntr
= Translator
.tmp_cntr
+ 1
451 text
+= prefix
+ "for(auto " + tmp_name
+ " : *" + varname
+ ")"
453 text
+= prefix
+ "for(auto " + tmp_name
+ " : " + varname
+ ")"
455 if types
[1].name
in known_containers
:
456 text
+= prefix
+ "\tauto " + tmp_name
+ "_second = " + tmp_name
+ ".second;"
457 text
+= known_containers
[types
[1].name
].translate_cpp(tmp_name
+ "_second", types
[1].cont
.args
, prefix
+ "\t", types
[1].attr_type
== attr_types
.star
)
459 if types
[0].name
in classnames
:
460 text
+= prefix
+ "\t" + varname
+ "___tmp[" + types
[0].name
+ "::get_py_obj(" + tmp_name
+ ".first)] = "
461 elif types
[0].name
not in known_containers
:
462 text
+= prefix
+ "\t" + varname
+ "___tmp[" + tmp_name
+ ".first] = "
464 if types
[1].name
in classnames
:
465 if types
[1].attr_type
== attr_types
.star
:
466 text
+= types
[1].name
+ "::get_py_obj(" + tmp_name
+ ".second);"
468 text
+= "*" + types
[1].name
+ "::get_py_obj(&" + tmp_name
+ ".second);"
469 elif types
[1].name
in known_containers
:
470 text
+= tmp_name
+ "_second___tmp;"
472 text
+= tmp_name
+ ".second;"
477 class DictTranslator(PythonDictTranslator
):
478 insert_name
= "insert"
481 #Sub_type for std::map
482 class MapTranslator(PythonDictTranslator
):
483 insert_name
= "insert"
484 orig_name
= "std::map"
486 #Translator for std::pair. Derived from PythonDictTranslator because the
487 #gen_type function is the same (because both have two template parameters)
488 class TupleTranslator(PythonDictTranslator
):
489 typename
= "boost::python::tuple"
490 orig_name
= "std::pair"
492 #Generate c++ code to translate from a boost::python::tuple
494 def translate(c
, varname
, types
, prefix
):
495 text
= prefix
+ types
[0].name
+ " " + varname
+ "___tmp_0 = boost::python::extract<" + types
[0].name
+ ">(" + varname
+ "[0]);"
496 text
+= prefix
+ types
[1].name
+ " " + varname
+ "___tmp_1 = boost::python::extract<" + types
[1].name
+ ">(" + varname
+ "[1]);"
497 text
+= prefix
+ TupleTranslator
.gen_type(types
) + " " + varname
+ "___tmp("
498 if types
[0].name
.split(" ")[-1] in primitive_types
:
499 text
+= varname
+ "___tmp_0, "
501 text
+= varname
+ "___tmp_0.get_cpp_obj(), "
502 if types
[1].name
.split(" ")[-1] in primitive_types
:
503 text
+= varname
+ "___tmp_1);"
505 text
+= varname
+ "___tmp_1.get_cpp_obj());"
508 #Generate c++ code to translate to a boost::python::tuple
510 def translate_cpp(c
, varname
, types
, prefix
, ref
):
511 # if the tuple is a pair of SigSpecs (aka SigSig), then we need
512 # to call get_py_obj() on each item in the tuple
513 if types
[0].name
in classnames
:
514 first_var
= types
[0].name
+ "::get_py_obj(" + varname
+ ".first)"
516 first_var
= varname
+ ".first"
517 if types
[1].name
in classnames
:
518 second_var
= types
[1].name
+ "::get_py_obj(" + varname
+ ".second)"
520 second_var
= varname
+ ".second"
521 text
= prefix
+ TupleTranslator
.typename
+ " " + varname
+ "___tmp = boost::python::make_tuple(" + first_var
+ ", " + second_var
+ ");"
524 #Associate the Translators with their c++ type
526 "std::set" : SetTranslator
,
527 "std::vector" : VectorTranslator
,
528 "pool" : PoolTranslator
,
529 "dict" : DictTranslator
,
530 "std::pair" : TupleTranslator
,
531 "std::map" : MapTranslator
542 def __init__(self
, wtype
, varname
, is_const
= False, default_value
= None):
544 self
.varname
= varname
545 self
.is_const
= is_const
546 self
.default_value
= None
547 self
.container
= None
550 def from_string(str_def
, containing_file
, line_number
):
554 arg
= Attribute(None, None)
559 arg
.default_value
= None
561 if str.startswith(str_def
, "const "):
563 str_def
= str_def
[6:]
564 if str.startswith(str_def
, "unsigned "):
566 str_def
= str_def
[9:]
567 while str.startswith(str_def
, "long "):
568 prefix
= "long " + prefix
569 str_def
= str_def
[5:]
570 while str.startswith(str_def
, "short "):
571 prefix
= "short " + prefix
572 str_def
= str_def
[6:]
574 if str_def
.find("<") != -1 and str_def
.find("<") < str_def
.find(" "):
575 closing
= find_closing(str_def
[str_def
.find("<"):], "<", ">") + str_def
.find("<") + 1
576 arg
.wtype
= WType
.from_string(str_def
[:closing
].strip(), containing_file
, line_number
)
577 str_def
= str_def
[closing
+1:]
579 if str_def
.count(" ") > 0:
580 arg
.wtype
= WType
.from_string(prefix
+ str_def
[:str_def
.find(" ")].strip(), containing_file
, line_number
)
581 str_def
= str_def
[str_def
.find(" ")+1:]
583 arg
.wtype
= WType
.from_string(prefix
+ str_def
.strip(), containing_file
, line_number
)
587 if arg
.wtype
== None:
589 if str_def
.count("=") == 0:
590 arg
.varname
= str_def
.strip()
591 if arg
.varname
.find(" ") > 0:
594 arg
.varname
= str_def
[:str_def
.find("=")].strip()
595 if arg
.varname
.find(" ") > 0:
597 str_def
= str_def
[str_def
.find("=")+1:].strip()
598 arg
.default_value
= str_def
[arg
.varname
.find("=")+1:].strip()
599 if len(arg
.varname
) == 0:
602 if arg
.varname
[0] == '*':
603 arg
.wtype
.attr_type
= attr_types
.star
604 arg
.varname
= arg
.varname
[1:]
605 elif arg
.varname
[0] == '&':
606 if arg
.wtype
.attr_type
!= attr_types
.default
:
608 if arg
.varname
[1] == '&':
609 arg
.wtype
.attr_type
= attr_types
.ampamp
610 arg
.varname
= arg
.varname
[2:]
612 arg
.wtype
.attr_type
= attr_types
.amp
613 arg
.varname
= arg
.varname
[1:]
616 #Generates the varname. If the attribute has no name in the header file,
618 def gen_varname(self
):
619 if self
.varname
!= None:
621 if self
.wtype
.name
== "void":
624 self
.pos
= Attribute
.pos_counter
625 Attribute
.pos_counter
= Attribute
.pos_counter
+ 1
626 return "gen_varname_" + str(self
.pos
)
628 #Generates the text for the function headers with wrapper types
629 def gen_listitem(self
):
633 if self
.wtype
.name
in classnames
:
634 return prefix
+ self
.wtype
.name
+ "* " + self
.gen_varname()
635 if self
.wtype
.name
in known_containers
:
636 return prefix
+ known_containers
[self
.wtype
.name
].typename
+ " " + self
.gen_varname()
637 return prefix
+ self
.wtype
.name
+ " " + self
.gen_varname()
639 #Generates the test for the function headers with c++ types
640 def gen_listitem_cpp(self
):
645 if self
.wtype
.attr_type
== attr_types
.star
:
647 elif self
.wtype
.attr_type
== attr_types
.amp
:
649 elif self
.wtype
.attr_type
== attr_types
.ampamp
:
651 if self
.wtype
.name
in known_containers
:
652 return prefix
+ known_containers
[self
.wtype
.name
].gen_type(self
.wtype
.cont
.args
) + " " + infix
+ self
.gen_varname()
653 if self
.wtype
.name
in classnames
:
654 return prefix
+ class_by_name(self
.wtype
.name
).namespace
+ "::" + self
.wtype
.name
+ " " + infix
+ self
.gen_varname()
655 return prefix
+ self
.wtype
.name
+ " " + infix
+ self
.gen_varname()
657 #Generates the listitem withtout the varname, so the signature can be
659 def gen_listitem_hash(self
):
663 if self
.wtype
.name
in classnames
:
664 return prefix
+ self
.wtype
.name
+ "* "
665 if self
.wtype
.name
in known_containers
:
666 return known_containers
[self
.wtype
.name
].typename
667 return prefix
+ self
.wtype
.name
669 #Generate Translation code for the attribute
670 def gen_translation(self
):
671 if self
.wtype
.name
in known_containers
:
672 return known_containers
[self
.wtype
.name
].translate(self
.gen_varname(), self
.wtype
.cont
.args
, "\n\t\t")
675 #Generate Translation code from c++ for the attribute
676 def gen_translation_cpp(self
):
677 if self
.wtype
.name
in known_containers
:
678 return known_containers
[self
.wtype
.name
].translate_cpp(self
.gen_varname(), self
.wtype
.cont
.args
, "\n\t\t", self
.wtype
.attr_type
== attr_types
.star
)
681 #Generate Text for the call
683 ret
= self
.gen_varname()
684 if self
.wtype
.name
in known_containers
:
685 if self
.wtype
.attr_type
== attr_types
.star
:
686 return "&" + ret
+ "___tmp"
687 return ret
+ "___tmp"
688 if self
.wtype
.name
in classnames
:
689 if self
.wtype
.attr_type
!= attr_types
.star
:
691 return ret
+ "->get_cpp_obj()"
692 if self
.wtype
.name
== "char *" and self
.gen_varname() in ["format", "fmt"]:
693 return "\"%s\", " + self
.gen_varname()
694 if self
.wtype
.attr_type
== attr_types
.star
:
698 def gen_call_cpp(self
):
699 ret
= self
.gen_varname()
700 if self
.wtype
.name
.split(" ")[-1] in primitive_types
or self
.wtype
.name
in enum_names
:
701 if self
.wtype
.attr_type
== attr_types
.star
:
704 if self
.wtype
.name
not in classnames
:
705 if self
.wtype
.attr_type
== attr_types
.star
:
706 return "&" + ret
+ "___tmp"
707 return ret
+ "___tmp"
708 if self
.wtype
.attr_type
!= attr_types
.star
:
710 return self
.wtype
.name
+ "::get_py_obj(" + self
.gen_varname() + ")"
712 #Generate cleanup code
713 def gen_cleanup(self
):
714 if self
.wtype
.name
in primitive_types
or self
.wtype
.name
in classnames
or self
.wtype
.name
in enum_names
or not self
.wtype
.attr_type
== attr_types
.star
or (self
.wtype
.name
in known_containers
and self
.wtype
.attr_type
== attr_types
.star
):
716 return "\n\t\tdelete " + self
.gen_varname() + "___tmp;"
730 def __init__(self
, name
, link_type
, id_
, string_id
= None, hash_id
= None, needs_clone
= False):
732 self
.namespace
= None
733 self
.link_type
= link_type
735 self
.string_id
= string_id
736 self
.hash_id
= hash_id
737 self
.needs_clone
= needs_clone
740 self
.found_constrs
= []
742 def printable_constrs(self
):
744 for con
in self
.found_constrs
:
745 if not con
.protected
:
749 def gen_decl(self
, filename
):
750 long_name
= self
.namespace
+ "::" + self
.name
752 text
= "\n\t// WRAPPED from " + filename
753 text
+= "\n\tstruct " + self
.name
754 if self
.link_type
== link_types
.derive
:
755 text
+= " : public " + self
.namespace
+ "::" + self
.name
758 if self
.link_type
!= link_types
.derive
:
760 text
+= "\t\t" + long_name
+ "* ref_obj;\n"
762 if self
.link_type
== link_types
.ref_copy
or self
.link_type
== link_types
.pointer
:
763 text
+= "\n\t\t" + long_name
+ "* get_cpp_obj() const\n\t\t{\n\t\t\treturn ref_obj;\n\t\t}\n"
764 elif self
.link_type
== link_types
.global_list
:
765 text
+= "\t\t" + self
.id_
.wtype
.name
+ " " + self
.id_
.varname
+ ";\n"
766 text
+= "\n\t\t" + long_name
+ "* get_cpp_obj() const\n\t\t{"
767 text
+= "\n\t\t\t" + long_name
+ "* ret = " + long_name
+ "::get_all_" + self
.name
.lower() + "s()->at(this->" + self
.id_
.varname
+ ");"
768 text
+= "\n\t\t\tif(ret != NULL && ret == this->ref_obj)"
769 text
+= "\n\t\t\t\treturn ret;"
770 text
+= "\n\t\t\tthrow std::runtime_error(\"" + self
.name
+ "'s c++ object does not exist anymore.\");"
771 text
+= "\n\t\t\treturn NULL;"
774 #if self.link_type != link_types.pointer:
775 text
+= "\n\t\tstatic " + self
.name
+ "* get_py_obj(" + long_name
+ "* ref)\n\t\t{"
776 text
+= "\n\t\t\tif(ref == nullptr){"
777 text
+= "\n\t\t\t\tthrow std::runtime_error(\"" + self
.name
+ " does not exist.\");"
779 text
+= "\n\t\t\t" + self
.name
+ "* ret = (" + self
.name
+ "*)malloc(sizeof(" + self
.name
+ "));"
780 if self
.link_type
== link_types
.pointer
:
781 text
+= "\n\t\t\tret->ref_obj = ref;"
782 if self
.link_type
== link_types
.ref_copy
:
784 text
+= "\n\t\t\tret->ref_obj = ref->clone();"
786 text
+= "\n\t\t\tret->ref_obj = new "+long_name
+"(*ref);"
787 if self
.link_type
== link_types
.global_list
:
788 text
+= "\n\t\t\tret->ref_obj = ref;"
789 text
+= "\n\t\t\tret->" + self
.id_
.varname
+ " = ret->ref_obj->" + self
.id_
.varname
+ ";"
790 text
+= "\n\t\t\treturn ret;"
793 if self
.link_type
== link_types
.ref_copy
:
794 text
+= "\n\t\tstatic " + self
.name
+ "* get_py_obj(" + long_name
+ " ref)\n\t\t{"
795 text
+= "\n\t\t\t" + self
.name
+ "* ret = (" + self
.name
+ "*)malloc(sizeof(" + self
.name
+ "));"
797 text
+= "\n\t\t\tret->ref_obj = ref.clone();"
799 text
+= "\n\t\t\tret->ref_obj = new "+long_name
+"(ref);"
800 text
+= "\n\t\t\treturn ret;"
803 for con
in self
.found_constrs
:
804 text
+= con
.gen_decl()
805 for var
in self
.found_vars
:
806 text
+= var
.gen_decl()
807 for fun
in self
.found_funs
:
808 text
+= fun
.gen_decl()
811 if self
.link_type
== link_types
.derive
:
813 for fun
in self
.found_funs
:
814 if fun
.name
in duplicates
:
816 duplicates
[fun
.name
].gen_alias()
818 duplicates
[fun
.name
] = fun
820 text
+= "\n\t\t" + long_name
+ "* get_cpp_obj() const\n\t\t{\n\t\t\treturn (" + self
.namespace
+ "::" + self
.name
+"*)this;\n\t\t}\n"
821 text
+= "\n\t\tstatic " + self
.name
+ "* get_py_obj(" + long_name
+ "* ref)\n\t\t{"
822 text
+= "\n\t\t\treturn (" + self
.name
+ "*)ref;"
825 for con
in self
.found_constrs
:
826 text
+= con
.gen_decl_derive()
827 for var
in self
.found_vars
:
828 text
+= var
.gen_decl()
829 for fun
in self
.found_funs
:
830 text
+= fun
.gen_decl_virtual()
832 if self
.hash_id
!= None:
833 text
+= "\n\t\tunsigned int get_hash_py()"
835 text
+= "\n\t\t\treturn get_cpp_obj()->" + self
.hash_id
+ ";"
840 if self
.link_type
== link_types
.derive
:
841 text
+= "\n\tstruct " + self
.name
+ "Wrap : " + self
.name
+ ", boost::python::wrapper<" + self
.name
+ ">"
844 for con
in self
.found_constrs
:
845 text
+= con
.gen_decl_wrapperclass()
846 for fun
in self
.found_funs
:
847 text
+= fun
.gen_default_impl()
851 text
+= "\n\tstd::ostream &operator<<(std::ostream &ostr, const " + self
.name
+ " &ref)"
853 text
+= "\n\t\tostr << \"" + self
.name
854 if self
.string_id
!= None:
856 text
+= " << ref.get_cpp_obj()->" + self
.string_id
857 text
+= " << \"\\\"\""
859 text
+= " at \" << ref.get_cpp_obj()"
861 text
+= "\n\t\treturn ostr;"
867 def gen_funs(self
, filename
):
869 if self
.link_type
!= link_types
.derive
:
870 for con
in self
.found_constrs
:
871 text
+= con
.gen_def()
872 for var
in self
.found_vars
:
873 text
+= var
.gen_def()
874 for fun
in self
.found_funs
:
875 text
+= fun
.gen_def()
877 for var
in self
.found_vars
:
878 text
+= var
.gen_def()
879 for fun
in self
.found_funs
:
880 text
+= fun
.gen_def_virtual()
883 def gen_boost_py(self
):
884 text
= "\n\t\tclass_<" + self
.name
885 if self
.link_type
== link_types
.derive
:
886 text
+= "Wrap, boost::noncopyable"
887 text
+= ">(\"" + self
.name
+ "\""
888 if self
.printable_constrs() == 0 or not self
.contains_default_constr():
891 text
+= "\n\t\t\t.def(boost::python::self_ns::str(boost::python::self_ns::self))"
892 text
+= "\n\t\t\t.def(boost::python::self_ns::repr(boost::python::self_ns::self))"
893 for con
in self
.found_constrs
:
894 text
+= con
.gen_boost_py()
895 for var
in self
.found_vars
:
896 text
+= var
.gen_boost_py()
898 for fun
in self
.found_funs
:
899 text
+= fun
.gen_boost_py()
900 if fun
.is_static
and fun
.alias
not in static_funs
:
901 static_funs
.append(fun
.alias
)
902 for fun
in static_funs
:
903 text
+= "\n\t\t\t.staticmethod(\"" + fun
+ "\")"
905 if self
.hash_id
!= None:
906 text
+= "\n\t\t\t.def(\"__hash__\", &" + self
.name
+ "::get_hash_py)"
907 text
+= "\n\t\t\t;\n"
910 def contains_default_constr(self
):
911 for c
in self
.found_constrs
:
916 #CONFIGURE HEADER-FILES TO BE PARSED AND CLASSES EXPECTED IN THEM HERE
919 Source("kernel/celltypes",[
920 WClass("CellType", link_types
.pointer
, None, None, "type.hash()", True),
921 WClass("CellTypes", link_types
.pointer
, None, None, None, True)
924 Source("kernel/consteval",[
925 WClass("ConstEval", link_types
.pointer
, None, None, None, True)
928 Source("kernel/log",[]),
929 Source("kernel/register",[
930 WClass("Pass", link_types
.derive
, None, None, None, True),
933 Source("kernel/rtlil",[
934 WClass("IdString", link_types
.ref_copy
, None, "str()", "hash()"),
935 WClass("Const", link_types
.ref_copy
, None, "as_string()", "hash()"),
936 WClass("AttrObject", link_types
.ref_copy
, None, None, None),
937 WClass("Selection", link_types
.ref_copy
, None, None, None),
938 WClass("Monitor", link_types
.derive
, None, None, None),
939 WClass("CaseRule",link_types
.ref_copy
, None, None, None, True),
940 WClass("SwitchRule",link_types
.ref_copy
, None, None, None, True),
941 WClass("SyncRule", link_types
.ref_copy
, None, None, None, True),
942 WClass("Process", link_types
.ref_copy
, None, "name.c_str()", "name.hash()"),
943 WClass("SigChunk", link_types
.ref_copy
, None, None, None),
944 WClass("SigBit", link_types
.ref_copy
, None, None, "hash()"),
945 WClass("SigSpec", link_types
.ref_copy
, None, None, "hash()"),
946 WClass("Cell", link_types
.global_list
, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
947 WClass("Wire", link_types
.global_list
, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
948 WClass("Memory", link_types
.global_list
, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
949 WClass("Module", link_types
.global_list
, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
950 WClass("Design", link_types
.global_list
, Attribute(WType("unsigned int"), "hashidx_"), "hashidx_", "hash()")
953 #Source("kernel/satgen",[
956 #Source("libs/ezsat/ezsat",[
959 #Source("libs/ezsat/ezminisat",[
962 Source("kernel/sigtools",[
963 WClass("SigMap", link_types
.pointer
, None, None, None, True)
966 Source("kernel/yosys",[
969 Source("kernel/cost",[])
972 blacklist_methods
= ["YOSYS_NAMESPACE::Pass::run_register", "YOSYS_NAMESPACE::Module::Pow", "YOSYS_NAMESPACE::Module::Bu0", "YOSYS_NAMESPACE::CaseRule::optimize"]
974 enum_names
= ["State","SyncType","ConstFlags"]
976 enums
= [] #Do not edit
978 unowned_functions
= []
981 for source
in sources
:
982 for wclass
in source
.classes
:
983 classnames
.append(wclass
.name
)
985 def class_by_name(name
):
986 for source
in sources
:
987 for wclass
in source
.classes
:
988 if wclass
.name
== name
:
992 def enum_by_name(name
):
998 def find_closing(text
, open_tok
, close_tok
):
999 if text
.find(open_tok
) == -1 or text
.find(close_tok
) <= text
.find(open_tok
):
1000 return text
.find(close_tok
)
1001 return text
.find(close_tok
) + find_closing(text
[text
.find(close_tok
)+1:], open_tok
, close_tok
) + 1
1003 def unpretty_string(s
):
1005 while s
.find(" ") != -1:
1006 s
= s
.replace(" "," ")
1007 while s
.find("\t") != -1:
1008 s
= s
.replace("\t"," ")
1009 s
= s
.replace(" (","(")
1017 def from_string(str_def
, namespace
, line_number
):
1018 str_def
= str_def
.strip()
1019 if not str.startswith(str_def
, "enum "):
1021 if str_def
.count(";") != 1:
1023 str_def
= str_def
[5:]
1025 split
= str_def
.split(":")
1026 if(len(split
) != 2):
1028 enum
.name
= split
[0].strip()
1029 if enum
.name
not in enum_names
:
1032 if str_def
.count("{") != str_def
.count("}") != 1:
1034 if len(str_def
) < str_def
.find("}")+2 or str_def
[str_def
.find("}")+1] != ';':
1036 str_def
= str_def
.split("{")[-1].split("}")[0]
1038 for val
in str_def
.split(','):
1039 enum
.values
.append(val
.strip().split('=')[0].strip())
1040 enum
.namespace
= namespace
1043 def gen_boost_py(self
):
1044 text
= "\n\t\tenum_<" + self
.namespace
+ "::" + self
.name
+ ">(\"" + self
.name
+ "\")\n"
1045 for value
in self
.values
:
1046 text
+= "\t\t\t.value(\"" + value
+ "\"," + self
.namespace
+ "::" + value
+ ")\n"
1051 ret
= "Enum " + self
.namespace
+ "::" + self
.name
+ "(\n"
1052 for val
in self
.values
:
1053 ret
= ret
+ "\t" + val
+ "\n"
1057 return __str__(self
)
1062 containing_file
= None
1067 def __init__(self
, containing_file
, class_
):
1068 self
.orig_text
= "Auto generated default constructor"
1070 self
.containing_file
= containing_file
1071 self
.member_of
= class_
1072 self
.protected
= False
1074 def from_string(str_def
, containing_file
, class_
, line_number
, protected
= False):
1077 if str_def
.count("delete;") > 0:
1079 con
= WConstructor(containing_file
, class_
)
1080 con
.orig_text
= str_def
1082 con
.duplicate
= False
1083 con
.protected
= protected
1084 if str.startswith(str_def
, "inline "):
1085 str_def
= str_def
[7:]
1086 if not str.startswith(str_def
, class_
.name
+ "("):
1088 str_def
= str_def
[len(class_
.name
)+1:]
1089 found
= find_closing(str_def
, "(", ")")
1092 str_def
= str_def
[0:found
].strip()
1093 if len(str_def
) == 0:
1095 for arg
in split_list(str_def
, ","):
1096 parsed
= Attribute
.from_string(arg
.strip(), containing_file
, line_number
)
1099 con
.args
.append(parsed
)
1103 if self
.duplicate
or self
.protected
:
1105 text
= "\n\t\t// WRAPPED from \"" + self
.orig_text
.replace("\n"," ") + "\" in " + self
.containing_file
1106 text
+= "\n\t\t" + self
.member_of
.name
+ "("
1107 for arg
in self
.args
:
1108 text
+= arg
.gen_listitem() + ", "
1109 if len(self
.args
) > 0:
1114 def gen_decl_derive(self
):
1115 if self
.duplicate
or self
.protected
:
1117 text
= "\n\t\t// WRAPPED from \"" + self
.orig_text
.replace("\n"," ") + "\" in " + self
.containing_file
1118 text
+= "\n\t\t" + self
.member_of
.name
+ "("
1119 for arg
in self
.args
:
1120 text
+= arg
.gen_listitem() + ", "
1121 if len(self
.args
) > 0:
1124 if len(self
.args
) == 0:
1127 text
+= self
.member_of
.namespace
+ "::" + self
.member_of
.name
+ "("
1128 for arg
in self
.args
:
1129 text
+= arg
.gen_call() + ", "
1130 if len(self
.args
) > 0:
1135 def gen_decl_wrapperclass(self
):
1136 if self
.duplicate
or self
.protected
:
1138 text
= "\n\t\t// WRAPPED from \"" + self
.orig_text
.replace("\n"," ") + "\" in " + self
.containing_file
1139 text
+= "\n\t\t" + self
.member_of
.name
+ "Wrap("
1140 for arg
in self
.args
:
1141 text
+= arg
.gen_listitem() + ", "
1142 if len(self
.args
) > 0:
1145 if len(self
.args
) == 0:
1148 text
+= self
.member_of
.name
+ "("
1149 for arg
in self
.args
:
1150 text
+= arg
.gen_call() + ", "
1151 if len(self
.args
) > 0:
1156 def gen_decl_hash_py(self
):
1157 text
= self
.member_of
.name
+ "("
1158 for arg
in self
.args
:
1159 text
+= arg
.gen_listitem_hash() + ", "
1160 if len(self
.args
) > 0:
1166 if self
.duplicate
or self
.protected
:
1168 text
= "\n\t// WRAPPED from \"" + self
.orig_text
.replace("\n"," ") + "\" in " + self
.containing_file
1169 text
+= "\n\t" + self
.member_of
.name
+ "::" + self
.member_of
.name
+ "("
1170 for arg
in self
.args
:
1171 text
+= arg
.gen_listitem() + ", "
1172 if len(self
.args
) > 0:
1175 for arg
in self
.args
:
1176 text
+= arg
.gen_translation()
1177 if self
.member_of
.link_type
!= link_types
.derive
:
1178 text
+= "\n\t\tthis->ref_obj = new " + self
.member_of
.namespace
+ "::" + self
.member_of
.name
+ "("
1179 for arg
in self
.args
:
1180 text
+= arg
.gen_call() + ", "
1181 if len(self
.args
) > 0:
1183 if self
.member_of
.link_type
!= link_types
.derive
:
1185 if self
.member_of
.link_type
== link_types
.global_list
:
1186 text
+= "\n\t\tthis->" + self
.member_of
.id_
.varname
+ " = this->ref_obj->" + self
.member_of
.id_
.varname
+ ";"
1187 for arg
in self
.args
:
1188 text
+= arg
.gen_cleanup()
1192 def gen_boost_py(self
):
1193 if self
.duplicate
or self
.protected
or len(self
.args
) == 0:
1195 text
= "\n\t\t\t.def(init"
1198 text
+= a
.gen_listitem_hash() + ", "
1199 text
= text
[0:-2] + ">())"
1207 ret_attr_type
= attr_types
.default
1213 containing_file
= None
1218 def from_string(str_def
, containing_file
, class_
, line_number
, namespace
):
1219 if str_def
.count("delete;") > 0:
1222 func
.is_static
= False
1223 func
.is_inline
= False
1224 func
.is_virtual
= False
1225 func
.ret_attr_type
= attr_types
.default
1226 func
.is_operator
= False
1227 func
.member_of
= None
1228 func
.orig_text
= str_def
1230 func
.containing_file
= containing_file
1231 func
.member_of
= class_
1232 func
.duplicate
= False
1233 func
.namespace
= namespace
1234 str_def
= str_def
.replace("operator ","operator")
1235 if str.startswith(str_def
, "static "):
1236 func
.is_static
= True
1237 str_def
= str_def
[7:]
1239 func
.is_static
= False
1240 if str.startswith(str_def
, "inline "):
1241 func
.is_inline
= True
1242 str_def
= str_def
[7:]
1244 func
.is_inline
= False
1245 if str.startswith(str_def
, "virtual "):
1246 func
.is_virtual
= True
1247 str_def
= str_def
[8:]
1249 func
.is_virtual
= False
1251 if str_def
.count(" ") == 0:
1254 parts
= split_list(str_def
.strip(), " ")
1259 if part
in ["unsigned", "long", "short"]:
1260 prefix
+= part
+ " "
1269 func
.ret_type
= WType
.from_string(prefix
+ parts
[0], containing_file
, line_number
)
1271 if func
.ret_type
== None:
1275 for part
in parts
[2:]:
1276 str_def
= str_def
+ " " + part
1278 found
= str_def
.find("(")
1279 if found
== -1 or (str_def
.find(" ") != -1 and found
> str_def
.find(" ")):
1281 func
.name
= str_def
[:found
]
1282 str_def
= str_def
[found
:]
1283 if func
.name
.find("operator") != -1 and str.startswith(str_def
, "()("):
1285 str_def
= str_def
[2:]
1286 str_def
= str_def
[1:]
1287 if func
.name
.find("operator") != -1:
1288 func
.is_operator
= True
1289 if func
.name
.find("*") == 0:
1290 func
.name
= func
.name
.replace("*", "")
1291 func
.ret_type
.attr_type
= attr_types
.star
1292 if func
.name
.find("&&") == 0:
1293 func
.name
= func
.name
.replace("&&", "")
1294 func
.ret_type
.attr_type
= attr_types
.ampamp
1295 if func
.name
.find("&") == 0:
1296 func
.name
= func
.name
.replace("&", "")
1297 func
.ret_type
.attr_type
= attr_types
.amp
1299 found
= find_closing(str_def
, "(", ")")
1302 str_def
= str_def
[0:found
]
1303 if func
.name
in blacklist_methods
:
1305 if func
.namespace
!= None and func
.namespace
!= "":
1306 if (func
.namespace
+ "::" + func
.name
) in blacklist_methods
:
1308 if func
.member_of
!= None:
1309 if (func
.namespace
+ "::" + func
.member_of
.name
+ "::" + func
.name
) in blacklist_methods
:
1311 if func
.is_operator
and func
.name
.replace(" ","").replace("operator","").split("::")[-1] not in wrappable_operators
:
1314 testname
= func
.name
1315 if func
.is_operator
:
1316 testname
= testname
[:testname
.find("operator")]
1317 if testname
.count(")") != 0 or testname
.count("(") != 0 or testname
.count("~") != 0 or testname
.count(";") != 0 or testname
.count(">") != 0 or testname
.count("<") != 0 or testname
.count("throw") != 0:
1320 func
.alias
= func
.name
1321 if func
.name
in keyword_aliases
:
1322 func
.alias
= keyword_aliases
[func
.name
]
1323 str_def
= str_def
[:found
].strip()
1324 if(len(str_def
) == 0):
1326 for arg
in split_list(str_def
, ","):
1327 if arg
.strip() == "...":
1329 parsed
= Attribute
.from_string(arg
.strip(), containing_file
, line_number
)
1332 func
.args
.append(parsed
)
1335 def gen_alias(self
):
1336 self
.alias
= self
.name
1337 for arg
in self
.args
:
1338 self
.alias
+= "__" + arg
.wtype
.gen_text_cpp().replace("::", "_").replace("<","_").replace(">","_").replace(" ","").replace("*","").replace(",","")
1343 text
= "\n\t\t// WRAPPED from \"" + self
.orig_text
.replace("\n"," ") + "\" in " + self
.containing_file
1347 text
+= self
.ret_type
.gen_text() + " " + self
.alias
+ "("
1348 for arg
in self
.args
:
1349 text
+= arg
.gen_listitem()
1351 if len(self
.args
) > 0:
1356 def gen_decl_virtual(self
):
1359 if not self
.is_virtual
:
1360 return self
.gen_decl()
1361 text
= "\n\t\t// WRAPPED from \"" + self
.orig_text
.replace("\n"," ") + "\" in " + self
.containing_file
1362 text
+= "\n\t\tvirtual "
1365 text
+= self
.ret_type
.gen_text() + " py_" + self
.alias
+ "("
1366 for arg
in self
.args
:
1367 text
+= arg
.gen_listitem()
1369 if len(self
.args
) > 0:
1372 if len(self
.args
) == 0:
1376 for arg
in self
.args
:
1377 text
+= "\n\t\t\t(void)" + arg
.gen_varname() + ";"
1379 text
+= "\n\t\tvirtual "
1382 text
+= self
.ret_type
.gen_text() + " " + self
.name
+ "("
1383 for arg
in self
.args
:
1384 text
+= arg
.gen_listitem_cpp()
1386 if len(self
.args
) > 0:
1388 text
+= ") YS_OVERRIDE;\n"
1391 def gen_decl_hash_py(self
):
1392 text
= self
.ret_type
.gen_text() + " " + self
.alias
+ "("
1393 for arg
in self
.args
:
1394 text
+= arg
.gen_listitem_hash() + ", "
1395 if len(self
.args
) > 0:
1403 text
= "\n\t// WRAPPED from \"" + self
.orig_text
.replace("\n"," ") + "\" in " + self
.containing_file
1404 text
+= "\n\t" + self
.ret_type
.gen_text() + " "
1405 if self
.member_of
!= None:
1406 text
+= self
.member_of
.name
+ "::"
1407 text
+= self
.alias
+ "("
1408 for arg
in self
.args
:
1409 text
+= arg
.gen_listitem()
1411 if len(self
.args
) > 0:
1414 for arg
in self
.args
:
1415 text
+= arg
.gen_translation()
1417 if self
.ret_type
.name
!= "void":
1418 if self
.ret_type
.name
in known_containers
:
1419 text
+= self
.ret_type
.gen_text_cpp()
1421 text
+= self
.ret_type
.gen_text()
1422 if self
.ret_type
.name
in classnames
or (self
.ret_type
.name
in known_containers
and self
.ret_type
.attr_type
== attr_types
.star
):
1425 if self
.ret_type
.name
in classnames
:
1426 text
+= self
.ret_type
.name
+ "::get_py_obj("
1427 if self
.member_of
== None:
1428 text
+= "::" + self
.namespace
+ "::" + self
.alias
+ "("
1429 elif self
.is_static
:
1430 text
+= self
.member_of
.namespace
+ "::" + self
.member_of
.name
+ "::" + self
.name
+ "("
1432 text
+= "this->get_cpp_obj()->" + self
.name
+ "("
1433 for arg
in self
.args
:
1434 text
+= arg
.gen_call() + ", "
1435 if len(self
.args
) > 0:
1437 if self
.ret_type
.name
in classnames
:
1440 for arg
in self
.args
:
1441 text
+= arg
.gen_cleanup()
1442 if self
.ret_type
.name
!= "void":
1443 if self
.ret_type
.name
in classnames
:
1444 text
+= "\n\t\treturn *ret_;"
1445 elif self
.ret_type
.name
in known_containers
:
1446 text
+= known_containers
[self
.ret_type
.name
].translate_cpp("ret_", self
.ret_type
.cont
.args
, "\n\t\t", self
.ret_type
.attr_type
== attr_types
.star
)
1447 text
+= "\n\t\treturn ret____tmp;"
1449 text
+= "\n\t\treturn ret_;"
1453 def gen_def_virtual(self
):
1456 if not self
.is_virtual
:
1457 return self
.gen_def()
1458 text
= "\n\t// WRAPPED from \"" + self
.orig_text
.replace("\n"," ") + "\" in " + self
.containing_file
1462 text
+= self
.ret_type
.gen_text() + " " + self
.member_of
.name
+ "::" + self
.name
+ "("
1463 for arg
in self
.args
:
1464 text
+= arg
.gen_listitem_cpp()
1466 if len(self
.args
) > 0:
1469 for arg
in self
.args
:
1470 text
+= arg
.gen_translation_cpp()
1472 if self
.member_of
== None:
1473 text
+= "::" + self
.namespace
+ "::" + self
.alias
+ "("
1474 elif self
.is_static
:
1475 text
+= self
.member_of
.namespace
+ "::" + self
.member_of
.name
+ "::" + self
.name
+ "("
1477 text
+= "py_" + self
.alias
+ "("
1478 for arg
in self
.args
:
1479 text
+= arg
.gen_call_cpp() + ", "
1480 if len(self
.args
) > 0:
1482 if self
.ret_type
.name
in classnames
:
1485 for arg
in self
.args
:
1486 text
+= arg
.gen_cleanup()
1490 def gen_default_impl(self
):
1493 if not self
.is_virtual
:
1495 text
= "\n\n\t\t" + self
.ret_type
.gen_text() + " py_" + self
.alias
+ "("
1496 for arg
in self
.args
:
1497 text
+= arg
.gen_listitem() + ", "
1498 if len(self
.args
) > 0:
1501 call_string
= "py_" + self
.alias
+ "("
1502 for arg
in self
.args
:
1503 call_string
+= arg
.gen_varname() + ", "
1504 if len(self
.args
) > 0:
1505 call_string
= call_string
[0:-2]
1509 text
+= "\n\t\t\tif(boost::python::override py_" + self
.alias
+ " = this->get_override(\"py_" + self
.alias
+ "\"))"
1510 text
+= "\n\t\t\t\t" + call_string
1511 text
+= "\n\t\t\telse"
1512 text
+= "\n\t\t\t\t" + self
.member_of
.name
+ "::" + call_string
1515 text
+= "\n\n\t\t" + self
.ret_type
.gen_text() + " default_py_" + self
.alias
+ "("
1516 for arg
in self
.args
:
1517 text
+= arg
.gen_listitem() + ", "
1518 if len(self
.args
) > 0:
1521 text
+= "\n\t\t\tthis->" + self
.member_of
.name
+ "::" + call_string
1526 def gen_boost_py(self
):
1529 if self
.member_of
== None:
1532 text
= "\n\t\t\t.def"
1533 if len(self
.args
) > -1:
1534 if self
.ret_type
.name
in known_containers
:
1535 text
+= "<" + known_containers
[self
.ret_type
.name
].typename
+ " "
1537 text
+= "<" + self
.ret_type
.name
+ " "
1538 if self
.member_of
== None or self
.is_static
:
1541 text
+= "(" + self
.member_of
.name
+ "::*)("
1543 text
+= a
.gen_listitem_hash() + ", "
1544 if len(self
.args
) > 0:
1545 text
= text
[0:-2] + ")>"
1549 if self
.is_operator
:
1550 text
+= "(\"" + wrappable_operators
[self
.name
.replace("operator","")] + "\""
1552 if self
.member_of
!= None and self
.member_of
.link_type
== link_types
.derive
and self
.is_virtual
:
1553 text
+= "(\"py_" + self
.alias
+ "\""
1555 text
+= "(\"" + self
.alias
+ "\""
1556 if self
.member_of
!= None:
1557 text
+= ", &" + self
.member_of
.name
+ "::"
1558 if self
.member_of
.link_type
== link_types
.derive
and self
.is_virtual
:
1559 text
+= "py_" + self
.alias
1560 text
+= ", &" + self
.member_of
.name
+ "Wrap::default_py_" + self
.alias
1566 text
+= ", " + "YOSYS_PYTHON::" + self
.alias
+ ");"
1571 wtype
= attr_types
.default
1573 containing_file
= None
1578 def from_string(str_def
, containing_file
, class_
, line_number
, namespace
):
1580 member
.orig_text
= str_def
1583 member
.containing_file
= containing_file
1584 member
.member_of
= class_
1585 member
.namespace
= namespace
1586 member
.is_const
= False
1588 if str.startswith(str_def
, "const "):
1589 member
.is_const
= True
1590 str_def
= str_def
[6:]
1592 if str_def
.count(" ") == 0:
1595 parts
= split_list(str_def
.strip(), " ")
1600 if part
in ["unsigned", "long", "short"]:
1601 prefix
+= part
+ " "
1610 member
.wtype
= WType
.from_string(prefix
+ parts
[0], containing_file
, line_number
)
1612 if member
.wtype
== None:
1616 for part
in parts
[2:]:
1617 str_def
= str_def
+ " " + part
1619 if str_def
.find("(") != -1 or str_def
.find(")") != -1 or str_def
.find("{") != -1 or str_def
.find("}") != -1:
1622 found
= str_def
.find(";")
1626 found_eq
= str_def
.find("=")
1630 member
.name
= str_def
[:found
]
1631 str_def
= str_def
[found
+1:]
1632 if member
.name
.find("*") == 0:
1633 member
.name
= member
.name
.replace("*", "")
1634 member
.wtype
.attr_type
= attr_types
.star
1635 if member
.name
.find("&&") == 0:
1636 member
.name
= member
.name
.replace("&&", "")
1637 member
.wtype
.attr_type
= attr_types
.ampamp
1638 if member
.name
.find("&") == 0:
1639 member
.name
= member
.name
.replace("&", "")
1640 member
.wtype
.attr_type
= attr_types
.amp
1642 if(len(str_def
.strip()) != 0):
1645 if len(member
.name
.split(",")) > 1:
1647 for name
in member
.name
.split(","):
1648 name
= name
.strip();
1649 member_list
.append(WMember())
1650 member_list
[-1].orig_text
= member
.orig_text
1651 member_list
[-1].wtype
= member
.wtype
1652 member_list
[-1].name
= name
1653 member_list
[-1].containing_file
= member
.containing_file
1654 member_list
[-1].member_of
= member
.member_of
1655 member_list
[-1].namespace
= member
.namespace
1656 member_list
[-1].is_const
= member
.is_const
1662 text
= "\n\t\t" + self
.wtype
.gen_text() + " get_var_py_" + self
.name
+ "();\n"
1665 if self
.wtype
.name
in classnames
:
1666 text
+= "\n\t\tvoid set_var_py_" + self
.name
+ "(" + self
.wtype
.gen_text() + " *rhs);\n"
1668 text
+= "\n\t\tvoid set_var_py_" + self
.name
+ "(" + self
.wtype
.gen_text() + " rhs);\n"
1672 text
= "\n\t" + self
.wtype
.gen_text() + " " + self
.member_of
.name
+"::get_var_py_" + self
.name
+ "()"
1673 text
+= "\n\t{\n\t\t"
1674 if self
.wtype
.attr_type
== attr_types
.star
:
1675 text
+= "if(this->get_cpp_obj()->" + self
.name
+ " == NULL)\n\t\t\t"
1676 text
+= "throw std::runtime_error(\"Member \\\"" + self
.name
+ "\\\" is NULL\");\n\t\t"
1677 if self
.wtype
.name
in known_containers
:
1678 text
+= self
.wtype
.gen_text_cpp()
1680 text
+= self
.wtype
.gen_text()
1682 if self
.wtype
.name
in classnames
or (self
.wtype
.name
in known_containers
and self
.wtype
.attr_type
== attr_types
.star
):
1685 if self
.wtype
.name
in classnames
:
1686 text
+= self
.wtype
.name
+ "::get_py_obj("
1687 if self
.wtype
.attr_type
!= attr_types
.star
:
1689 text
+= "this->get_cpp_obj()->" + self
.name
1690 if self
.wtype
.name
in classnames
:
1694 if self
.wtype
.name
in classnames
:
1695 text
+= "\n\t\treturn *ret_;"
1696 elif self
.wtype
.name
in known_containers
:
1697 text
+= known_containers
[self
.wtype
.name
].translate_cpp("ret_", self
.wtype
.cont
.args
, "\n\t\t", self
.wtype
.attr_type
== attr_types
.star
)
1698 text
+= "\n\t\treturn ret____tmp;"
1700 text
+= "\n\t\treturn ret_;"
1706 ret
= Attribute(self
.wtype
, "rhs");
1708 if self
.wtype
.name
in classnames
:
1709 text
+= "\n\tvoid " + self
.member_of
.name
+ "::set_var_py_" + self
.name
+ "(" + self
.wtype
.gen_text() + " *rhs)"
1711 text
+= "\n\tvoid " + self
.member_of
.name
+ "::set_var_py_" + self
.name
+ "(" + self
.wtype
.gen_text() + " rhs)"
1713 text
+= ret
.gen_translation()
1714 text
+= "\n\t\tthis->get_cpp_obj()->" + self
.name
+ " = " + ret
.gen_call() + ";"
1719 def gen_boost_py(self
):
1720 text
= "\n\t\t\t.add_property(\"" + self
.name
+ "\", &" + self
.member_of
.name
+ "::get_var_py_" + self
.name
1721 if not self
.is_const
:
1722 text
+= ", &" + self
.member_of
.name
+ "::set_var_py_" + self
.name
1726 def concat_namespace(tuple_list
):
1727 if len(tuple_list
) == 0:
1730 for namespace
in tuple_list
:
1731 ret
+= "::" + namespace
[0]
1734 def calc_ident(text
):
1735 if len(text
) == 0 or text
[0] != ' ':
1737 return calc_ident(text
[1:]) + 1
1739 def assure_length(text
, length
, left
= False):
1740 if len(text
) > length
:
1741 return text
[:length
]
1743 return text
+ " "*(length
- len(text
))
1744 return " "*(length
- len(text
)) + text
1746 def parse_header(source
):
1747 debug("Parsing " + source
.name
+ ".pyh",1)
1748 source_file
= open(source
.name
+ ".pyh", "r")
1751 in_line
= source_file
.readline()
1757 source_text
.append(in_line
.replace("char *", "char_p ").replace("char* ", "char_p "))
1758 in_line
= source_file
.readline()
1764 private_segment
= False
1766 while i
< len(source_text
):
1767 line
= source_text
[i
].replace("YOSYS_NAMESPACE_BEGIN", " namespace YOSYS_NAMESPACE{").replace("YOSYS_NAMESPACE_END"," }")
1768 ugly_line
= unpretty_string(line
)
1770 if str.startswith(ugly_line
, "namespace "):# and ugly_line.find("std") == -1 and ugly_line.find("__") == -1:
1771 namespace_name
= ugly_line
[10:].replace("{","").strip()
1772 namespaces
.append((namespace_name
, ugly_line
.count("{")))
1773 debug("-----NAMESPACE " + concat_namespace(namespaces
) + "-----",3)
1777 if len(namespaces
) != 0:
1778 namespaces
[-1] = (namespaces
[-1][0], namespaces
[-1][1] + ugly_line
.count("{") - ugly_line
.count("}"))
1779 if namespaces
[-1][1] == 0:
1780 debug("-----END NAMESPACE " + concat_namespace(namespaces
) + "-----",3)
1785 if class_
== None and (str.startswith(ugly_line
, "struct ") or str.startswith(ugly_line
, "class")) and ugly_line
.count(";") == 0:
1787 struct_name
= ugly_line
.split(" ")[1].split("::")[-1]
1788 impl_namespaces
= ugly_line
.split(" ")[1].split("::")[:-1]
1789 complete_namespace
= concat_namespace(namespaces
)
1790 for namespace
in impl_namespaces
:
1791 complete_namespace
+= "::" + namespace
1792 debug("\tFound " + struct_name
+ " in " + complete_namespace
,2)
1793 class_
= (class_by_name(struct_name
), ugly_line
.count("{"))#calc_ident(line))
1794 if struct_name
in classnames
:
1795 class_
[0].namespace
= complete_namespace
1800 class_
= (class_
[0], class_
[1] + ugly_line
.count("{") - ugly_line
.count("}"))
1802 if class_
[0] == None:
1803 debug("\tExiting unknown class", 3)
1805 debug("\tExiting class " + class_
[0].name
, 3)
1807 private_segment
= False
1811 if class_
!= None and (line
.find("private:") != -1 or line
.find("protected:") != -1):
1812 private_segment
= True
1815 if class_
!= None and line
.find("public:") != -1:
1816 private_segment
= False
1822 if private_segment
and class_
!= None and class_
[0] != None:
1823 candidate
= WConstructor
.from_string(ugly_line
, source
.name
, class_
[0], i
, True)
1824 if candidate
!= None:
1825 debug("\t\tFound constructor of class \"" + class_
[0].name
+ "\" in namespace " + concat_namespace(namespaces
),2)
1826 class_
[0].found_constrs
.append(candidate
)
1830 if not private_segment
and (class_
== None or class_
[0] != None):
1832 candidate
= WFunction
.from_string(ugly_line
, source
.name
, class_
[0], i
, concat_namespace(namespaces
))
1834 candidate
= WFunction
.from_string(ugly_line
, source
.name
, None, i
, concat_namespace(namespaces
))
1835 if candidate
!= None and candidate
.name
.find("::") == -1:
1837 debug("\tFound unowned function \"" + candidate
.name
+ "\" in namespace " + concat_namespace(namespaces
),2)
1838 unowned_functions
.append(candidate
)
1840 debug("\t\tFound function \"" + candidate
.name
+ "\" of class \"" + class_
[0].name
+ "\" in namespace " + concat_namespace(namespaces
),2)
1841 class_
[0].found_funs
.append(candidate
)
1843 candidate
= WEnum
.from_string(ugly_line
, concat_namespace(namespaces
), i
)
1844 if candidate
!= None:
1845 enums
.append(candidate
)
1846 debug("\tFound enum \"" + candidate
.name
+ "\" in namespace " + concat_namespace(namespaces
),2)
1847 elif class_
!= None and class_
[1] == 1:
1848 candidate
= WConstructor
.from_string(ugly_line
, source
.name
, class_
[0], i
)
1849 if candidate
!= None:
1850 debug("\t\tFound constructor of class \"" + class_
[0].name
+ "\" in namespace " + concat_namespace(namespaces
),2)
1851 class_
[0].found_constrs
.append(candidate
)
1853 candidate
= WMember
.from_string(ugly_line
, source
.name
, class_
[0], i
, concat_namespace(namespaces
))
1854 if candidate
!= None:
1855 if type(candidate
) == list:
1857 debug("\t\tFound member \"" + c
.name
+ "\" of class \"" + class_
[0].name
+ "\" of type \"" + c
.wtype
.name
+ "\"", 2)
1858 class_
[0].found_vars
.extend(candidate
)
1860 debug("\t\tFound member \"" + candidate
.name
+ "\" of class \"" + class_
[0].name
+ "\" of type \"" + candidate
.wtype
.name
+ "\"", 2)
1861 class_
[0].found_vars
.append(candidate
)
1864 line
= unpretty_string(line
)
1865 while candidate
== None and j
+1 < len(source_text
) and line
.count(';') <= 1 and line
.count("(") >= line
.count(")"):
1867 line
= line
+ "\n" + unpretty_string(source_text
[j
])
1869 candidate
= WFunction
.from_string(ugly_line
, source
.name
, class_
[0], i
, concat_namespace(namespaces
))
1871 candidate
= WFunction
.from_string(ugly_line
, source
.name
, None, i
, concat_namespace(namespaces
))
1872 if candidate
!= None and candidate
.name
.find("::") == -1:
1874 debug("\tFound unowned function \"" + candidate
.name
+ "\" in namespace " + concat_namespace(namespaces
),2)
1875 unowned_functions
.append(candidate
)
1877 debug("\t\tFound function \"" + candidate
.name
+ "\" of class \"" + class_
[0].name
+ "\" in namespace " + concat_namespace(namespaces
),2)
1878 class_
[0].found_funs
.append(candidate
)
1880 candidate
= WEnum
.from_string(line
, concat_namespace(namespaces
), i
)
1881 if candidate
!= None:
1882 enums
.append(candidate
)
1883 debug("\tFound enum \"" + candidate
.name
+ "\" in namespace " + concat_namespace(namespaces
),2)
1886 candidate
= WConstructor
.from_string(line
, source
.name
, class_
[0], i
)
1887 if candidate
!= None:
1888 debug("\t\tFound constructor of class \"" + class_
[0].name
+ "\" in namespace " + concat_namespace(namespaces
),2)
1889 class_
[0].found_constrs
.append(candidate
)
1891 if candidate
!= None:
1894 line
= source_text
[i
].replace("YOSYS_NAMESPACE_BEGIN", " namespace YOSYS_NAMESPACE{").replace("YOSYS_NAMESPACE_END"," }")
1895 ugly_line
= unpretty_string(line
)
1896 if len(namespaces
) != 0:
1897 namespaces
[-1] = (namespaces
[-1][0], namespaces
[-1][1] + ugly_line
.count("{") - ugly_line
.count("}"))
1898 if namespaces
[-1][1] == 0:
1899 debug("-----END NAMESPACE " + concat_namespace(namespaces
) + "-----",3)
1902 class_
= (class_
[0] , class_
[1] + ugly_line
.count("{") - ugly_line
.count("}"))
1904 if class_
[0] == None:
1905 debug("\tExiting unknown class", 3)
1907 debug("\tExiting class " + class_
[0].name
, 3)
1909 private_segment
= False
1914 def debug(message
, level
):
1915 if level
<= debug
.debug_level
:
1918 def expand_function(f
):
1922 if arg
.default_value
!= None and (arg
.wtype
.name
.split(" ")[-1] in primitive_types
or arg
.wtype
.name
in enum_names
or (arg
.wtype
.name
in classnames
and arg
.default_value
== "nullptr")):
1923 fi
= copy
.deepcopy(f
)
1924 fi
.args
= copy
.deepcopy(arg_list
)
1926 arg_list
.append(arg
)
1930 def expand_functions():
1931 global unowned_functions
1933 for fun
in unowned_functions
:
1934 new_funs
.extend(expand_function(fun
))
1935 unowned_functions
= new_funs
1936 for source
in sources
:
1937 for class_
in source
.classes
:
1939 for fun
in class_
.found_funs
:
1940 new_funs
.extend(expand_function(fun
))
1941 class_
.found_funs
= new_funs
1943 def clean_duplicates():
1944 for source
in sources
:
1945 for class_
in source
.classes
:
1947 for fun
in class_
.found_funs
:
1948 if fun
.gen_decl_hash_py() in known_decls
:
1949 debug("Multiple declarations of " + fun
.gen_decl_hash_py(),3)
1950 other
= known_decls
[fun
.gen_decl_hash_py()]
1953 if fun
.gen_decl_hash_py() == other
.gen_decl_hash_py():
1954 fun
.duplicate
= True
1955 debug("Disabled \"" + fun
.gen_decl_hash_py() + "\"", 3)
1957 known_decls
[fun
.gen_decl_hash_py()] = fun
1959 for con
in class_
.found_constrs
:
1960 if con
.gen_decl_hash_py() in known_decls
:
1961 debug("Multiple declarations of " + con
.gen_decl_hash_py(),3)
1962 con
.duplicate
= True
1964 known_decls
.append(con
.gen_decl_hash_py())
1966 for fun
in unowned_functions
:
1967 if fun
.gen_decl_hash_py() in known_decls
:
1968 debug("Multiple declarations of " + fun
.gen_decl_hash_py(),3)
1969 fun
.duplicate
= True
1971 known_decls
.append(fun
.gen_decl_hash_py())
1973 def gen_wrappers(filename
, debug_level_
= 0):
1974 debug
.debug_level
= debug_level_
1975 for source
in sources
:
1976 parse_header(source
)
1983 col
= shutil
.get_terminal_size((80,20)).columns
1985 debug("-"*math
.floor((col
-7)/2)+"SUMMARY"+"-"*math
.ceil((col
-7)/2), 1)
1987 for source
in sources
:
1988 for class_
in source
.classes
:
1989 debug("Class " + assure_length(class_
.name
, len(max(classnames
, key
=len)), True) + " contains " + assure_length(str(len(class_
.found_vars
)), 3, False) + " member variables, "+ assure_length(str(len(class_
.found_funs
)), 3, False) + " methods and " + assure_length(str(len(class_
.found_constrs
)), 2, False) + " constructors", 1)
1990 if len(class_
.found_constrs
) == 0:
1991 class_
.found_constrs
.append(WConstructor(source
.name
, class_
))
1992 debug(str(len(unowned_functions
)) + " functions are unowned", 1)
1994 debug("Enum " + assure_length(enum
.name
, len(max(enum_names
, key
=len)), True) + " contains " + assure_length(str(len(enum
.values
)), 2, False) + " values", 1)
1996 wrapper_file
= open(filename
, "w+")
1999 * yosys -- Yosys Open SYnthesis Suite
2001 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
2003 * Permission to use, copy, modify, and/or distribute this software for any
2004 * purpose with or without fee is hereby granted, provided that the above
2005 * copyright notice and this permission notice appear in all copies.
2007 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
2008 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
2009 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
2010 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2011 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
2012 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2013 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2015 * This is a generated file and can be overwritten by make
2020 for source
in sources
:
2021 wrapper_file
.write("#include \""+source
.name
+".h\"\n")
2022 wrapper_file
.write("""
2023 #include <boost/python/module.hpp>
2024 #include <boost/python/class.hpp>
2025 #include <boost/python/wrapper.hpp>
2026 #include <boost/python/call.hpp>
2027 #include <boost/python.hpp>
2029 USING_YOSYS_NAMESPACE
2031 namespace YOSYS_PYTHON {
2034 for source
in sources
:
2035 for wclass
in source
.classes
:
2036 wrapper_file
.write("\n\tstruct " + wclass
.name
+ ";")
2038 wrapper_file
.write("\n")
2040 for source
in sources
:
2041 for wclass
in source
.classes
:
2042 wrapper_file
.write(wclass
.gen_decl(source
.name
))
2044 wrapper_file
.write("\n")
2046 for source
in sources
:
2047 for wclass
in source
.classes
:
2048 wrapper_file
.write(wclass
.gen_funs(source
.name
))
2050 for fun
in unowned_functions
:
2051 wrapper_file
.write(fun
.gen_def())
2053 wrapper_file
.write(""" struct Initializer
2056 if(!Yosys::yosys_already_setup())
2058 Yosys::log_streams.push_back(&std::cout);
2059 Yosys::log_error_stderr = true;
2060 Yosys::yosys_setup();
2064 Initializer(Initializer const &) {}
2067 Yosys::yosys_shutdown();
2071 BOOST_PYTHON_MODULE(libyosys)
2073 using namespace boost::python;
2075 class_<Initializer>("Initializer");
2076 scope().attr("_hidden") = new Initializer();
2080 wrapper_file
.write(enum
.gen_boost_py())
2082 for source
in sources
:
2083 for wclass
in source
.classes
:
2084 wrapper_file
.write(wclass
.gen_boost_py())
2086 for fun
in unowned_functions
:
2087 wrapper_file
.write(fun
.gen_boost_py())
2089 wrapper_file
.write("\n\t}\n}\n#endif")
2091 def print_includes():
2092 for source
in sources
:
2093 print(source
.name
+ ".pyh")