Skip to content

Commit

Permalink
load verilog
Browse files Browse the repository at this point in the history
  • Loading branch information
nanocoh committed Nov 12, 2024
1 parent 7d14f2c commit 1e47805
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 95 deletions.
6 changes: 3 additions & 3 deletions src/snl/python/snl_wrapping/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ set(SOURCES
PySNLNets.cpp PySNLBitNets.cpp PySNLScalarNets.cpp PySNLBusNets.cpp
PySNLInstances.cpp PySNLInstTerms.cpp PySNLPath.cpp PySNLOccurrence.cpp
PySNLNetComponentOccurrence.cpp PySNLInstTermOccurrence.cpp PySNLInstTermOccurrences.cpp
PySNLEquipotential.cpp PySNLUniquifier.cpp
PySNLEquipotential.cpp PySNLUniquifier.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../pyloader/SNLPyLoader.cpp
)

Python3_add_library(naja_snl_python SHARED ${SOURCES})
target_link_libraries(naja_snl_python PUBLIC naja_snl_verilog naja_bne naja_snl_dump)
target_include_directories(naja_snl_python PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(naja_snl_python PUBLIC naja_snl_verilog naja_bne naja_snl_dump naja_snl_liberty)
target_include_directories(naja_snl_python PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../pyloader/)

Python3_add_library(snl MODULE PySNL.cpp)

Expand Down
251 changes: 164 additions & 87 deletions src/snl/python/snl_wrapping/PySNLDB.cpp
Original file line number Diff line number Diff line change
@@ -1,116 +1,193 @@
// SPDX-FileCopyrightText: 2023 The Naja authors <https://github.com/najaeda/naja/blob/main/AUTHORS>
// SPDX-FileCopyrightText: 2023 The Naja authors
// <https://github.com/najaeda/naja/blob/main/AUTHORS>
//
// SPDX-License-Identifier: Apache-2.0

#include "PySNLDB.h"

#include "PyInterface.h"
#include "PySNLUniverse.h"
#include "PySNLLibrary.h"
#include "PySNLLibraries.h"
#include "PySNLLibrary.h"
#include "PySNLUniverse.h"

#include "SNLDB.h"

#include <Python.h>
#include <filesystem>
#include "SNLCapnP.h"
#include <Python.h>
#include "SNLLibertyConstructor.h"
#include "SNLPyLoader.h"
#include "SNLUtils.h"
#include "SNLVRLConstructor.h"
#include "SNLVRLDumper.h"

#include <fstream>
#include <iostream>

namespace PYSNL
{
namespace PYSNL {

using namespace naja::SNL;
using namespace naja::SNL;

#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(SNLDB, function)

static PyObject *PySNLDB_create(PyObject *, PyObject *args)
{
PyObject *arg = nullptr;
if (not PyArg_ParseTuple(args, "O:SNLDB.create", &arg))
{
setError("malformed SNLDB create");
return nullptr;
}
if (not IsPySNLUniverse(arg))
{
setError("SNLDB create argument should be a SNLUniverse");
return nullptr;
}
auto universe = PYSNLUNIVERSE_O(arg);
SNLDB *db = nullptr;
TRY
db = SNLDB::create(universe);
SNLCATCH
return PySNLDB_Link(db);
static PyObject* PySNLDB_create(PyObject*, PyObject* args) {
PyObject* arg = nullptr;
if (not PyArg_ParseTuple(args, "O:SNLDB.create", &arg)) {
setError("malformed SNLDB create");
return nullptr;
}
if (not IsPySNLUniverse(arg)) {
setError("SNLDB create argument should be a SNLUniverse");
return nullptr;
}
auto universe = PYSNLUNIVERSE_O(arg);
SNLDB* db = nullptr;
TRY db = SNLDB::create(universe);
SNLCATCH
return PySNLDB_Link(db);
}

static PyObject *PySNLDB_loadSNL(PyObject *, PyObject *args)
{
PyObject *arg = nullptr;
if (not PyArg_ParseTuple(args, "O:SNLDB.loadSNL", &arg))
{
setError("malformed SNLDB loadSNL");
return nullptr;
}
if (not PyUnicode_Check(arg))
{
static PyObject* PySNLDB_loadSNL(PyObject*, PyObject* args) {
PyObject* arg = nullptr;
if (not PyArg_ParseTuple(args, "O:SNLDB.loadSNL", &arg)) {
setError("malformed SNLDB loadSNL");
return nullptr;
}
if (not PyUnicode_Check(arg)) {
setError("SNLDB loadSNL argument should be a file path");
return nullptr;
}
SNLDB* db = nullptr;
const std::filesystem::path path(PyUnicode_AsUTF8(arg));
if (SNLUniverse::get() == nullptr) {
SNLUniverse::create();
}
TRY db = SNLCapnP::load(path);
SNLCATCH
return PySNLDB_Link(db);
}

PyObject* PySNLDB_dumpSNL(PySNLDB* self, PyObject* args) {
PyObject* arg = nullptr;
if (not PyArg_ParseTuple(args, "O:SNLDB.dumpSNL", &arg)) {
setError("malformed SNLDB dumpSNL");
Py_RETURN_FALSE;
}
if (not PyUnicode_Check(arg)) {
setError("SNLDB dumpSNL argument should be a file path");
Py_RETURN_FALSE;
}
SNLCapnP::dump(self->object_, PyUnicode_AsUTF8(arg));
// return true to python
Py_RETURN_TRUE;
}

static PyObject* PySNLDB_loadVerilog(PyObject*, PyObject* args) {
PyObject* arg0 = nullptr;
PyObject* arg1 = nullptr;
if (not PyArg_ParseTuple(args, "OO:SNLDB.loadVerilog", &arg0, &arg1)) {
setError("malformed SNLDB loadVerilog");
return nullptr;
}
if (not PyList_Check(arg0) || not PyList_Check(arg1)) {
setError("malformed SNLDesign.loadVerilog method");
return nullptr;
}
SNLDB* db = nullptr;
SNLLibrary* primitivesLibrary = nullptr;
db = SNLDB::create(SNLUniverse::get());
primitivesLibrary =
SNLLibrary::create(db, SNLLibrary::Type::Primitives, SNLName("PRIMS"));
for (int i = 0; i < PyList_Size(arg0); ++i) {
PyObject* object = PyList_GetItem(arg0, i);
if (not PyUnicode_Check(object)) {
setError("SNLDB loadSNL argument should be a file path");
return nullptr;
}
SNLDB *db = nullptr;
const std::filesystem::path path(PyUnicode_AsUTF8(arg));
if (SNLUniverse::get() == nullptr)
{
SNLUniverse::create();
std::string pathStr = PyUnicode_AsUTF8(object);
const std::filesystem::path path(pathStr);

auto extension = path.extension();
if (extension.empty()) {
std::exit(EXIT_FAILURE);
} else if (extension == ".py") {
SNLPyLoader::loadPrimitives(primitivesLibrary, path);
} else if (extension == ".lib") {
SNLLibertyConstructor constructor(primitivesLibrary);
constructor.construct(path);
} else {
std::exit(EXIT_FAILURE);
}
TRY
db = SNLCapnP::load(path);
SNLCATCH
return PySNLDB_Link(db);
}

PyObject *PySNLDB_dumpSNL(PySNLDB *self, PyObject *args)
{
PyObject *arg = nullptr;
if (not PyArg_ParseTuple(args, "O:SNLDB.dumpSNL", &arg))
{
setError("malformed SNLDB dumpSNL");
Py_RETURN_FALSE;
}
if (not PyUnicode_Check(arg))
{
setError("SNLDB dumpSNL argument should be a file path");
Py_RETURN_FALSE;
auto designLibrary = SNLLibrary::create(db, SNLName("DESIGN"));
SNLVRLConstructor constructor(designLibrary);
using Paths = std::vector<std::filesystem::path>;
Paths inputPaths;
for (int i = 0; i < PyList_Size(arg1); ++i) {
PyObject* object = PyList_GetItem(arg1, i);
if (not PyUnicode_Check(object)) {
setError("SNLDB loadSNL argument should be a file path");
return nullptr;
}
SNLCapnP::dump(self->object_, PyUnicode_AsUTF8(arg));
// return true to python
Py_RETURN_TRUE;
std::string pathStr = PyUnicode_AsUTF8(object);
const std::filesystem::path path(pathStr);
inputPaths.push_back(path);
}
constructor.construct(inputPaths);
auto top = SNLUtils::findTop(designLibrary);
if (top) {
SNLUniverse::get()->setTopDesign(top);
} else {
setError("No top design was found after parsing verilog");
}
return PySNLDB_Link(db);
}

GetObjectByName(SNLDB, SNLLibrary, getLibrary)
GetContainerMethod(DB, Library, Libraries, Libraries)

DBoDestroyAttribute(PySNLDB_destroy, PySNLDB)

PyMethodDef PySNLDB_Methods[] = {
{"create", (PyCFunction)PySNLDB_create, METH_VARARGS | METH_STATIC,
"create a SNLDB."},
{"loadSNL", (PyCFunction)PySNLDB_loadSNL, METH_VARARGS | METH_STATIC,
"create a SNLDB from SNL format."},
{"dumpSNL", (PyCFunction)PySNLDB_dumpSNL, METH_VARARGS,
"dump this SNLDB to SNL format."},
{"getLibrary", (PyCFunction)PySNLDB_getLibrary, METH_VARARGS,
"retrieve a SNLLibrary."},
{"getLibraries", (PyCFunction)PySNLDB_getLibraries, METH_NOARGS,
"get a container of SNLLibraries."},
{"destroy", (PyCFunction)PySNLDB_destroy, METH_NOARGS,
"destroy this SNLDB."},
{NULL, NULL, 0, NULL} /* sentinel */
};

DBoDeallocMethod(SNLDB)

DBoLinkCreateMethod(SNLDB)
PyTypeSNLFinalObjectWithSNLIDLinkPyType(SNLDB)
PyTypeObjectDefinitions(SNLDB)

PyObject* PySNLDB_dumpVerilog(PySNLDB* self, PyObject* args) {
PyObject* arg = nullptr;
if (not PyArg_ParseTuple(args, "O:SNLDB.dumpSNL", &arg)) {
setError("malformed SNLDB dumpSNL");
Py_RETURN_FALSE;
}
if (not PyUnicode_Check(arg)) {
setError("SNLDB dumpSNL argument should be a file path");
Py_RETURN_FALSE;
}
std::ofstream output(PyUnicode_AsUTF8(arg));
SNLVRLDumper dumper;
dumper.setSingleFile(true);
dumper.dumpDesign(self->object_->getTopDesign(), output);
// return true to python
Py_RETURN_TRUE;
}

GetObjectByName(SNLDB, SNLLibrary, getLibrary)
GetContainerMethod(DB, Library, Libraries, Libraries)

DBoDestroyAttribute(PySNLDB_destroy, PySNLDB)
PyMethodDef PySNLDB_Methods[] = {
{"create", (PyCFunction)PySNLDB_create,
METH_VARARGS | METH_STATIC, "create a SNLDB."},
{"loadSNL", (PyCFunction)PySNLDB_loadSNL,
METH_VARARGS | METH_STATIC, "create a SNLDB from SNL format."},
{"dumpSNL", (PyCFunction)PySNLDB_dumpSNL, METH_VARARGS,
"dump this SNLDB to SNL format."},
{"loadVerilog", (PyCFunction)PySNLDB_loadVerilog,
METH_VARARGS | METH_STATIC, "create a SNLDB from SNL format."},
{"dumpVerilog", (PyCFunction)PySNLDB_dumpVerilog, METH_VARARGS,
"dump this SNLDB to SNL format."},
{"getLibrary", (PyCFunction)PySNLDB_getLibrary, METH_VARARGS,
"retrieve a SNLLibrary."},
{"getLibraries", (PyCFunction)PySNLDB_getLibraries, METH_NOARGS,
"get a container of SNLLibraries."},
{"destroy", (PyCFunction)PySNLDB_destroy, METH_NOARGS,
"destroy this SNLDB."},
{NULL, NULL, 0, NULL} /* sentinel */
};

DBoDeallocMethod(SNLDB)

DBoLinkCreateMethod(SNLDB) PyTypeSNLFinalObjectWithSNLIDLinkPyType(SNLDB)
PyTypeObjectDefinitions(SNLDB)
} // namespace PYSNL
15 changes: 10 additions & 5 deletions test/snl/python/snl_wrapping/test_snldb.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,22 @@ def test(self):
with self.assertRaises(SystemError) as context: db.dumpSNL(u)
with self.assertRaises(SystemError) as context: db.dumpSNL()
del db

def testVerilog(self):
u = snl.SNLUniverse.get()
self.assertIsNotNone(u)
designs = ["../../formats/verilog/benchmarks/test0.v"]
primitives = ["../../formats/liberty/benchmarks/asap7_excerpt/test0.lib"]
db = snl.SNLDB.loadVerilog(primitives, designs)
db.dumpVerilog("./test_verilog")
del db

def testLoad(self):
u = snl.SNLUniverse.get()
self.assertIsNotNone(u)
db1 = snl.SNLDB.loadSNL("./test_snl")
self.assertIsNotNone(db1)
del db1
snl.SNLUniverse.get().destroy()
db1 = snl.SNLDB.loadSNL("./test_snl")
self.assertIsNotNone(db1)
del db1

def testDestroy(self):
u = snl.SNLUniverse.get()
Expand All @@ -44,7 +49,7 @@ def testDestroy(self):

def testCreationError(self):
u = snl.SNLUniverse.get()
#db = snl.SNLDB.create(u)
db = snl.SNLDB.create(u)
with self.assertRaises(RuntimeError) as context: snl.SNLDB.create()
with self.assertRaises(RuntimeError) as context: snl.SNLDB.create("ERROR")
with self.assertRaises(RuntimeError) as context: snl.SNLDB.loadSNL(u)
Expand Down

0 comments on commit 1e47805

Please sign in to comment.