Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

# Initializing the Project
After the project is cloned, you must fetch external packages.
Use the following command to do this. Only do this if the 'packages'
directory is not present:

```
% ivpm update
```

# Building the Project
There are two steps required to build the native components of
the project:

```
% ./packages/python/bin/python setup.py build_ext --inplace
% ./packages/python/bin/python -m build -n .
```

# Running Tests
Unit tests can be run using the following command:

```
% PYTHONPATH=$(pwd)/src ./packages/python/bin/pytest -s tests/unit
```
4 changes: 3 additions & 1 deletion scripts/gen_py_if.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,9 @@ def main():

args = parser.parse_args()

include_pref = {"Py_", "PyDict_", "PyEval_", "PyErr_", "PyImport_",
include_pref = {"Py_", "PyDict_", "PyEval_", "PyErr_",
"PyFloat_",
"PyImport_",
"PyIter_", "PyList_",
"PyLong_", "PyObject_", "PySet_",
"PyTuple_", "PyUnicode_", "PyGILState_"}
Expand Down
1 change: 1 addition & 0 deletions src/hdl_if/impl/call/call_proxy_dpi.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def invoke_hdl_f(
self,
method_name : str,
args : tuple):

return self.ep.invoke_hdl_f(
self.obj_id,
method_name,
Expand Down
26 changes: 22 additions & 4 deletions src/hdl_if/impl/call/gen_sv_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,9 @@ def gen_tf_impl(self, m : MethodDef):
pass
else:
self.println("pyhdl_if::PyObject __res;")
if m.rtype is not None:
self.println("%s __ret;" % self.svtype(m.rtype))
self.println("pyhdl_if::PyGILState_STATE state = pyhdl_if::PyGILState_Ensure();")
self.println("pyhdl_if::PyObject __args = pyhdl_if::PyTuple_New(%d);" % len(m.params))
for i,p in enumerate(m.params):
self.println("void'(pyhdl_if::PyTuple_SetItem(__args, %d, %s));" % (
Expand All @@ -366,10 +369,17 @@ def gen_tf_impl(self, m : MethodDef):
if m.kind == MethodKind.ExpTask:
self.println("pyhdl_if::pyhdl_if_invokePyTask(__res, m_obj, \"%s\", __args);" % (
m.name,))
self.println("pyhdl_if::PyGILState_Release(state);")
else:
self.println("__res = pyhdl_if::pyhdl_if_invokePyFunc(m_obj, \"%s\", __args);" % (
m.name,))
self.println("return %s(__res);" % self.py2sv_func(m.rtype))
if m.rtype is not None:
self.println("__ret = %s(__res);" % self.py2sv_func(m.rtype))

self.println("pyhdl_if::PyGILState_Release(state);")

if m.rtype is not None:
self.println("return __ret;")

self.dec_ind()

Expand Down Expand Up @@ -454,6 +464,7 @@ def gen_func_dispatch(self, api):
self.println("virtual function pyhdl_if::PyObject invokeFunc(string method, pyhdl_if::PyObject args);")
self.inc_ind()
self.println("pyhdl_if::PyObject __ret = pyhdl_if::None;")
self.println("pyhdl_if::PyGILState_STATE state = pyhdl_if::PyGILState_Ensure();")
self.println("case (method)")
self.inc_ind()
for m in api.methods:
Expand Down Expand Up @@ -500,21 +511,24 @@ def gen_func_dispatch(self, api):
self.dec_ind()
self.println("endcase")
self.println()
self.println("pyhdl_if::PyGILState_Release(state);")
self.println("return __ret;")
self.dec_ind()
self.println("endfunction")

def py2sv_func(self, type):
type_m = {
ctypes.c_bool : "PyLong_AsLong",
ctypes.c_bool : "py_as_bool",
ctypes.c_byte : "PyLong_AsLong",
ctypes.c_char : "PyLong_AsLong",
ctypes.c_double : "real",
ctypes.c_double : "py_as_double",
float : "py_as_double",
ctypes.c_int : "PyLong_AsLong",
ctypes.c_int8 : "PyLong_AsLong",
ctypes.c_int16 : "PyLong_AsLong",
ctypes.c_int32 : "PyLong_AsLong",
ctypes.c_int64 : "PyLong_AsLongLong",
int : "PyLong_AsLongLong",
ctypes.c_uint8 : "PyLong_AsLong",
ctypes.c_uint16 : "PyLong_AsLong",
ctypes.c_uint32 : "PyLong_AsLong",
Expand All @@ -531,12 +545,14 @@ def sv2py_func(self, type, var):
ctypes.c_bool : "PyLong_FromLong",
ctypes.c_byte : "PyLong_FromLong",
ctypes.c_char : "PyLong_FromLong",
ctypes.c_double : "real",
ctypes.c_double : "PyFloat_FromDouble",
float : "PyFloat_FromDouble",
ctypes.c_int : "PyLong_FromLong",
ctypes.c_int8 : "PyLong_FromLong",
ctypes.c_int16 : "PyLong_FromLong",
ctypes.c_int32 : "PyLong_FromLong",
ctypes.c_int64 : "PyLong_FromLongLong",
int : "PyLong_FromLongLong",
ctypes.c_uint8 : "PyLong_FromLong",
ctypes.c_uint16 : "PyLong_FromLong",
ctypes.c_uint32 : "PyLong_FromLong",
Expand All @@ -556,11 +572,13 @@ def svtype(self, type):
ctypes.c_byte : "byte",
ctypes.c_char : "byte",
ctypes.c_double : "real",
float : "real",
ctypes.c_int : "int",
ctypes.c_int8 : "byte",
ctypes.c_int16 : "shortint",
ctypes.c_int32 : "int",
ctypes.c_int64 : "longint",
int : "longint",
ctypes.c_uint8 : "byte unsigned",
ctypes.c_uint16 : "shortint unsigned",
ctypes.c_uint32 : "int unsigned",
Expand Down
1 change: 0 additions & 1 deletion src/hdl_if/impl/call/imp_func_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ def __call__(self, api_self, *args, **kwargs):

proxy : CallProxy = getattr(api_self, "_proxy")

print("args: %s" % str(args), flush=True)
return proxy.invoke_hdl_f(
self._md.name,
args
Expand Down
55 changes: 44 additions & 11 deletions src/hdl_if/share/dpi/py_utils.svh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,44 @@ function automatic py_object py_from_str(string str);
return ret;
endfunction

function automatic string py_as_str(PyObject hndl);
string ret = PyUnicode_AsUTF8(hndl);
return ret;
endfunction

function automatic bit py_as_bool(PyObject hndl);
longint ret = PyLong_AsLong(hndl);

if (ret == -1 && PyErr_Occurred() != null) begin
PyErr_Print();
end

return (ret != 0);
endfunction

function automatic longint py_as_long(PyObject hndl);
longint ret = PyLong_AsLong(hndl);

if (ret == -1 && PyErr_Occurred() != null) begin
PyErr_Print();
end

return ret;
endfunction

function automatic real py_as_double(PyObject hndl);
real ret = 0.0;

ret = PyFloat_AsDouble(hndl);
if (ret == -1 && PyErr_Occurred() != null) begin
$display("Error occurred");
PyErr_Print();
end

return ret;
endfunction


/**
* Import a module
*/
Expand All @@ -66,6 +104,8 @@ function automatic py_object py_call_builtin(string name, py_tuple args, py_dict
PyObject ret_o;
py_object ret = null;

`PYHDL_IF_ENTER(("py_call_builtin %0s", name));

Py_IncRef(args.obj);
builtins = PyEval_GetBuiltins();
Py_IncRef(builtins);
Expand All @@ -90,26 +130,19 @@ function automatic py_object py_call_builtin(string name, py_tuple args, py_dict
return null;
end


$display("--> PyObject_Call");
$display("func: %0p", func);
$display("args: %0p", args.obj);
$display("kwargs: %0p", kwargs.obj);
ret_o = PyObject_Call(
func,
args.obj,
func,
args.obj,
kwargs.obj);
$display("<-- PyObject_Call");

$display("ret_o=%0p", ret_o);

if (ret_o == null) begin
$display("ret_o is null");
PyErr_Print();
end else begin
ret = new(ret_o);
end

`PYHDL_IF_LEAVE(("py_call_builtin %0s", name));

return ret;
endfunction

Expand Down
2 changes: 2 additions & 0 deletions src/hdl_if/share/dpi/pyhdl_if.sv
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ package pyhdl_if;

function automatic PyObject pyhdl_pi_if_HandleErr(PyObject obj);
if (obj == null) begin
$display("--> HandleErr");
PyErr_Print();
$display("<-- HandleErr");
end
return obj;
endfunction
Expand Down
24 changes: 24 additions & 0 deletions tests/unit/data/datatypes/datatypes_int_imp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import ctypes as ct
import hdl_if as hif

@hif.api
class IntImp(object):

@hif.imp
def add(self, a : ct.c_int, b : ct.c_int) -> ct.c_int: pass

@hif.exp
def test(self) -> ct.c_int:
status = 0

try:
for i in range(10):
for j in range(10):
result = self.add(i, j)

if result != i+j:
status = 1
except Exception as e:
print("Exception: %s" % str(e), flush=True)

return status
31 changes: 31 additions & 0 deletions tests/unit/data/datatypes/datatypes_int_imp.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package datatypes_int_imp;
import datatypes_int_imp_pkg::*;

class IntImpImpl extends IntImp;
function int add(int a, int b);
return a+b;
endfunction
endclass
endpackage

module top;
import pyhdl_if::*;
import datatypes_int_imp::*;

initial begin
automatic IntImpImpl int_imp = new();
automatic int status = 0, fp;

$display("Hello World!");
status = int_imp.test();

fp = $fopen("status.txt", "w");
if (status == 0) begin
$fwrite(fp, "PASS:\n");
end else begin
$fwrite(fp, "FAIL:\n");
end
$fclose(fp);
$finish;
end
endmodule
11 changes: 11 additions & 0 deletions tests/unit/data/datatypes/datatypes_real_exp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

import ctypes as ct
import hdl_if as hif

@hif.api
class RealExp(object):

@hif.exp
def add(self, a : ct.c_double, b : ct.c_double) -> ct.c_double:
ret = a + b
return ret
37 changes: 37 additions & 0 deletions tests/unit/data/datatypes/datatypes_real_exp.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

package datatypes_real_exp;
endpackage


module top;
import pyhdl_if::*;
import datatypes_real_exp_pkg::*;

initial begin
automatic RealExp real_exp = new();
automatic int i, j;
automatic real result;
automatic int status = 0, fp;

for (i=0; i<10; i++) begin
for (j=0; j<10; j++) begin
result = real_exp.add(real'(i), real'(j));
if (result != (real'(i) + real'(j))) begin
$display("Error: %0d+%0d: expect %0f ; receive %0f",
i, j, (real'(i) + real'(j)), result);
status = 1;
end
end
end

fp = $fopen("status.txt", "w");
if (status == 0) begin
$fwrite(fp, "PASS:\n");
end else begin
$fwrite(fp, "FAIL:\n");
end
$fclose(fp);
$finish;
end
endmodule

26 changes: 26 additions & 0 deletions tests/unit/data/datatypes/datatypes_real_imp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

import ctypes as ct
import hdl_if as hif

@hif.api
class RealImp(object):

@hif.imp
def add(self, a : ct.c_double, b : ct.c_double) -> ct.c_double: pass

@hif.exp
def test(self) -> ct.c_int:
status = 0

try:
result = self.add(0, 0)
# for i in range(10):
# for j in range(10):
# result = self.add(i, j)

# if result != i+j:
# status = 1
except Exception as e:
print("Exception: %s" % str(e), flush=True)

return status
Loading
Loading