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.
22 #ifdef YOSYS_ENABLE_PLUGINS
29 typedef void (*ffi_fptr
) ();
31 static ffi_fptr
resolve_fn (std::string symbol_name
)
33 if (symbol_name
.find(':') != std::string::npos
)
35 int pos
= symbol_name
.find(':');
36 std::string plugin_name
= symbol_name
.substr(0, pos
);
37 std::string real_symbol_name
= symbol_name
.substr(pos
+1);
39 while (loaded_plugin_aliases
.count(plugin_name
))
40 plugin_name
= loaded_plugin_aliases
.at(plugin_name
);
42 if (loaded_plugins
.count(plugin_name
) == 0)
43 log_error("unable to resolve '%s': can't find plugin `%s'\n", symbol_name
.c_str(), plugin_name
.c_str());
45 void *symbol
= dlsym(loaded_plugins
.at(plugin_name
), real_symbol_name
.c_str());
47 if (symbol
== nullptr)
48 log_error("unable to resolve '%s': can't find symbol `%s' in plugin `%s'\n",
49 symbol_name
.c_str(), real_symbol_name
.c_str(), plugin_name
.c_str());
51 return (ffi_fptr
) symbol
;
54 for (auto &it
: loaded_plugins
) {
55 void *symbol
= dlsym(it
.second
, symbol_name
.c_str());
56 if (symbol
!= nullptr)
57 return (ffi_fptr
) symbol
;
60 void *symbol
= dlsym(RTLD_DEFAULT
, symbol_name
.c_str());
61 if (symbol
!= nullptr)
62 return (ffi_fptr
) symbol
;
64 log_error("unable to resolve '%s'.\n", symbol_name
.c_str());
67 AST::AstNode
*AST::dpi_call(const std::string
&rtype
, const std::string
&fname
, const std::vector
<std::string
> &argtypes
, const std::vector
<AstNode
*> &args
)
69 AST::AstNode
*newNode
= nullptr;
70 union { double f64
; float f32
; int32_t i32
; } value_store
[args
.size() + 1];
71 ffi_type
*types
[args
.size() + 1];
72 void *values
[args
.size() + 1];
76 log("Calling DPI function `%s' and returning `%s':\n", fname
.c_str(), rtype
.c_str());
78 log_assert(GetSize(args
) == GetSize(argtypes
));
79 for (int i
= 0; i
< GetSize(args
); i
++) {
80 if (argtypes
[i
] == "real") {
81 log(" arg %d (%s): %f\n", i
, argtypes
[i
].c_str(), args
[i
]->asReal(args
[i
]->is_signed
));
82 value_store
[i
].f64
= args
[i
]->asReal(args
[i
]->is_signed
);
83 values
[i
] = &value_store
[i
].f64
;
84 types
[i
] = &ffi_type_double
;
85 } else if (argtypes
[i
] == "shortreal") {
86 log(" arg %d (%s): %f\n", i
, argtypes
[i
].c_str(), args
[i
]->asReal(args
[i
]->is_signed
));
87 value_store
[i
].f32
= args
[i
]->asReal(args
[i
]->is_signed
);
88 values
[i
] = &value_store
[i
].f32
;
89 types
[i
] = &ffi_type_double
;
90 } else if (argtypes
[i
] == "integer") {
91 log(" arg %d (%s): %lld\n", i
, argtypes
[i
].c_str(), (long long)args
[i
]->asInt(args
[i
]->is_signed
));
92 value_store
[i
].i32
= args
[i
]->asInt(args
[i
]->is_signed
);
93 values
[i
] = &value_store
[i
].i32
;
94 types
[i
] = &ffi_type_sint32
;
96 log_error("invalid argtype '%s' for argument %d.\n", argtypes
[i
].c_str(), i
);
100 if (rtype
== "integer") {
101 types
[args
.size()] = &ffi_type_slong
;
102 values
[args
.size()] = &value_store
[args
.size()].i32
;
103 } else if (rtype
== "shortreal") {
104 types
[args
.size()] = &ffi_type_float
;
105 values
[args
.size()] = &value_store
[args
.size()].f32
;
106 } else if (rtype
== "real") {
107 types
[args
.size()] = &ffi_type_double
;
108 values
[args
.size()] = &value_store
[args
.size()].f64
;
110 log_error("invalid rtype '%s'.\n", rtype
.c_str());
113 if ((status
= ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, args
.size(), types
[args
.size()], types
)) != FFI_OK
)
114 log_error("ffi_prep_cif failed: status %d.\n", status
);
116 ffi_call(&cif
, resolve_fn(fname
.c_str()), values
[args
.size()], values
);
118 if (rtype
== "real") {
119 newNode
= new AstNode(AST_REALVALUE
);
120 newNode
->realvalue
= value_store
[args
.size()].f64
;
121 log(" return realvalue: %g\n", newNode
->asReal(true));
122 } else if (rtype
== "shortreal") {
123 newNode
= new AstNode(AST_REALVALUE
);
124 newNode
->realvalue
= value_store
[args
.size()].f32
;
125 log(" return realvalue: %g\n", newNode
->asReal(true));
127 newNode
= AstNode::mkconst_int(value_store
[args
.size()].i32
, false);
128 log(" return integer: %lld\n", (long long)newNode
->asInt(true));
136 #else /* YOSYS_ENABLE_PLUGINS */
138 YOSYS_NAMESPACE_BEGIN
140 AST::AstNode
*AST::dpi_call(const std::string
&, const std::string
&fname
, const std::vector
<std::string
>&, const std::vector
<AstNode
*>&)
142 log_error("Can't call DPI function `%s': this version of yosys is built without plugin support\n", fname
.c_str());
147 #endif /* YOSYS_ENABLE_PLUGINS */