* -------------------------------------------------------------------------
* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*/
#include <stdexcept>
#include <exception>
#include <cstring>
#include "utils/CPythonUtils.h"
#include "core/PrecisionDebugger.h"
namespace MindStudioDebugger {
static PyObject* NewPrecisionDebugger(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
if (type == nullptr || type->tp_alloc == nullptr) {
throw std::runtime_error("PrecisionDebugger: type or alloc is nullptr.");
}
static PyObject *self = nullptr;
if (self == nullptr) {
self = type->tp_alloc(type, 0);
}
Py_XINCREF(self);
return self;
}
static int InitPrecisionDebugger(PyObject *self, PyObject *args, PyObject *kws)
{
if (PrecisionDebugger::GetInstance().HasInitialized()) {
return 0;
}
if (kws == nullptr) {
PyErr_SetString(PyExc_TypeError, "Need keywords arg'framework\'and \'config_path\'.");
return -1;
}
CPythonUtils::PythonDictObject kwArgs(kws);
std::string framework = kwArgs.GetItem("framework");
std::string cfgFile = kwArgs.GetItem("config_path");
if (PrecisionDebugger::GetInstance().Initialize(framework, cfgFile) != 0) {
PyErr_SetString(PyExc_RuntimeError, "Failed to load config, read log for more details.");
return -1;
}
return 0;
}
static PyObject* PrecisionDebuggerGetAttr(PyObject *self, PyObject *name)
{
CPythonUtils::PythonStringObject attr(name);
if (attr.IsNone()) {
PyErr_SetString(PyExc_TypeError, "Attribution should be a string.");
Py_RETURN_NONE;
}
const char* s = attr.ToString().c_str();
if (strcmp(s, "enable") == 0) {
return CPythonUtils::PythonObject::From(PrecisionDebugger::GetInstance().IsEnable()).NewRef();
} else if (strcmp(s, "current_step") == 0) {
return CPythonUtils::PythonObject::From(PrecisionDebugger::GetInstance().GetCurStep()).NewRef();
}
PyObject* ret = PyObject_GenericGetAttr(self, name);
if (ret == nullptr) {
PyErr_Format(PyExc_AttributeError, "\'PrecisionDebugger\' object has no attribute \'%s\'", attr);
Py_RETURN_NONE;
}
return ret;
}
static PyObject* PrecisionDebuggerStart(PyObject *self)
{
PrecisionDebugger::GetInstance().Start();
Py_RETURN_NONE;
}
static PyObject* PrecisionDebuggerStop(PyObject *self)
{
PrecisionDebugger::GetInstance().Stop();
Py_RETURN_NONE;
}
static PyObject* PrecisionDebuggerStep(PyObject *self)
{
PrecisionDebugger::GetInstance().Step();
Py_RETURN_NONE;
}
PyDoc_STRVAR(StartDoc,
"start($self, /)\n--\n\nEnable debug.");
PyDoc_STRVAR(StopDoc,
"stop($self, /)\n--\n\nDisable debug.");
PyDoc_STRVAR(StepDoc,
"step($self, [increment])\n--\n\nUpdata step.");
static PyMethodDef PrecisionDebuggerMethods[] = {
{"start", reinterpret_cast<PyCFunction>(PrecisionDebuggerStart), METH_NOARGS, StartDoc},
{"stop", reinterpret_cast<PyCFunction>(PrecisionDebuggerStop), METH_NOARGS, StopDoc},
{"step", reinterpret_cast<PyCFunction>(PrecisionDebuggerStep), METH_NOARGS, StepDoc},
{nullptr, nullptr, 0, nullptr}
};
PyTypeObject PyPrecisionDebuggerType = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"_msprobe_c._PrecisionDebugger",
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
PrecisionDebuggerGetAttr,
0,
0,
Py_TPFLAGS_DEFAULT,
0,
0,
0,
0,
0,
0,
0,
PrecisionDebuggerMethods,
0,
0,
&PyBaseObject_Type,
0,
0,
0,
0,
InitPrecisionDebugger,
0,
NewPrecisionDebugger,
PyObject_Del,
};
PyTypeObject* GetPyPrecisionDebuggerType()
{
static bool init = false;
if (!init) {
if (PyType_Ready(&PyPrecisionDebuggerType) < 0) {
return nullptr;
}
init = true;
}
return &PyPrecisionDebuggerType;
}
}