3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-09-30 13:19:05 +00:00

hotfix: fix new log functions being incompatible with pyosys

Modify python wrapper generator script with corner-case handlers such that functions that start with `log_formatted` have the format string coerced to `"%s"` and also have an alias without the `_formatted` part.
This commit is contained in:
Mohamed Gaber 2025-09-13 17:15:24 +03:00 committed by Lofty
parent 6b3a7e2440
commit 9fa27dae3c

View file

@ -71,7 +71,7 @@ keyword_aliases = {
#These can be used without any explicit conversion #These can be used without any explicit conversion
primitive_types = ["void", "bool", "int", "double", "size_t", "std::string", primitive_types = ["void", "bool", "int", "double", "size_t", "std::string",
"string", "State", "char_p", "std::source_location", "source_location"] "string", "string_view", "std::string_view", "State", "char_p", "std::source_location", "source_location"]
from enum import Enum from enum import Enum
@ -557,6 +557,7 @@ class Attribute:
default_value = None default_value = None
pos = None pos = None
pos_counter = 0 pos_counter = 0
coerce_arg = None
def __init__(self, wtype, varname, is_const = False, default_value = None): def __init__(self, wtype, varname, is_const = False, default_value = None):
self.wtype = wtype self.wtype = wtype
@ -566,7 +567,7 @@ class Attribute:
self.container = None self.container = None
@staticmethod @staticmethod
def from_string(str_def, containing_file, line_number): def from_string(str_def, containing_file, line_number, *, owner_fn_name=""):
if len(str_def) < 3: if len(str_def) < 3:
return None return None
orig = str_def orig = str_def
@ -630,6 +631,14 @@ class Attribute:
else: else:
arg.wtype.attr_type = attr_types.amp arg.wtype.attr_type = attr_types.amp
arg.varname = arg.varname[1:] arg.varname = arg.varname[1:]
# special exception: format strings
if arg.wtype.name in ["std::string_view", "string_view"]:
if arg.varname == "format":
arg.coerce_arg = '"%s"'
elif arg.varname == "prefix" and "warning" in owner_fn_name:
arg.coerce_arg = '"Warning: "'
return arg return arg
#Generates the varname. If the attribute has no name in the header file, #Generates the varname. If the attribute has no name in the header file,
@ -1391,7 +1400,7 @@ class WFunction:
for i, arg in enumerate(args): for i, arg in enumerate(args):
if arg.strip() == "...": if arg.strip() == "...":
continue continue
parsed = Attribute.from_string(arg.strip(), containing_file, line_number) parsed = Attribute.from_string(arg.strip(), containing_file, line_number, owner_fn_name=func.name)
if parsed == None: if parsed == None:
return None return None
# Only allow std::source_location as defaulted last argument, and # Only allow std::source_location as defaulted last argument, and
@ -1431,6 +1440,8 @@ class WFunction:
text += "static " text += "static "
text += self.ret_type.gen_text() + " " + self.alias + "(" text += self.ret_type.gen_text() + " " + self.alias + "("
for arg in self.args: for arg in self.args:
if arg.coerce_arg:
continue
text += arg.gen_listitem() text += arg.gen_listitem()
text += ", " text += ", "
if len(self.args) > 0: if len(self.args) > 0:
@ -1497,6 +1508,8 @@ class WFunction:
text += self.member_of.name + "::" text += self.member_of.name + "::"
text += self.alias + "(" text += self.alias + "("
for arg in self.args: for arg in self.args:
if arg.coerce_arg:
continue
text += arg.gen_listitem() text += arg.gen_listitem()
text += ", " text += ", "
if len(self.args) > 0: if len(self.args) > 0:
@ -1516,13 +1529,14 @@ class WFunction:
if self.ret_type.name in classnames: if self.ret_type.name in classnames:
text += self.ret_type.name + "::get_py_obj(" text += self.ret_type.name + "::get_py_obj("
if self.member_of == None: if self.member_of == None:
text += "::" + self.namespace + "::" + self.alias + "(" text += "::" + self.namespace + "::" + self.name + "("
elif self.is_static: elif self.is_static:
text += self.member_of.namespace + "::" + self.member_of.name + "::" + self.name + "(" text += self.member_of.namespace + "::" + self.member_of.name + "::" + self.name + "("
else: else:
text += "this->get_cpp_obj()->" + self.name + "(" text += "this->get_cpp_obj()->" + self.name + "("
for arg in self.args: for arg in self.args:
text += arg.gen_call() + ", " text += arg.coerce_arg or arg.gen_call()
text += ", "
if len(self.args) > 0: if len(self.args) > 0:
text = text[:-2] text = text[:-2]
if self.ret_type.name in classnames: if self.ret_type.name in classnames:
@ -1639,6 +1653,8 @@ class WFunction:
else: else:
text += "(" + self.member_of.name + "::*)(" text += "(" + self.member_of.name + "::*)("
for a in self.args: for a in self.args:
if a.coerce_arg:
continue
text += a.gen_listitem_hash() + ", " text += a.gen_listitem_hash() + ", "
if len(self.args) > 0: if len(self.args) > 0:
text = text[0:-2] + f"){self.gen_post_qualifiers(True)}>" text = text[0:-2] + f"){self.gen_post_qualifiers(True)}>"
@ -2122,6 +2138,16 @@ def parse_header(source):
if class_ == None: if class_ == None:
debug("\tFound unowned function \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2) debug("\tFound unowned function \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2)
unowned_functions.append(candidate) unowned_functions.append(candidate)
# generate log aliases
if candidate.name.startswith("log_formatted"):
alias = candidate.name.replace("log_formatted", "log")
if alias == "log_string":
alias = "log"
copied_candidate = copy.copy(candidate)
copied_candidate.alias = alias
unowned_functions.append(copied_candidate)
else: else:
debug("\t\tFound function \"" + candidate.name + "\" of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2) debug("\t\tFound function \"" + candidate.name + "\" of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2)
class_[0].found_funs.append(candidate) class_[0].found_funs.append(candidate)
@ -2359,6 +2385,8 @@ def gen_wrappers(filename, debug_level_ = 0):
#include <boost/iostreams/stream.hpp> #include <boost/iostreams/stream.hpp>
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
using std::string_view;
namespace YOSYS_PYTHON { namespace YOSYS_PYTHON {
[[noreturn]] static void log_python_exception_as_error() { [[noreturn]] static void log_python_exception_as_error() {