Skip to content

Commit

Permalink
Fix and testing (#60)
Browse files Browse the repository at this point in the history
* Fix and testing

* coverage

* refine python dump verilog

* error testing
  • Loading branch information
xtofalex authored Apr 4, 2024
1 parent 2915ab3 commit 87b97f3
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/snl/formats/verilog/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ SET(HEADERS
)

add_library(naja_snl_verilog SHARED ${SOURCES})
target_link_libraries(naja_snl_verilog naja_verilog naja_snl_pyloader)
target_link_libraries(naja_snl_verilog naja_verilog naja_snl)

target_include_directories(naja_snl_verilog PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/frontend
Expand Down
2 changes: 1 addition & 1 deletion src/snl/python/snl_wrapping/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ set(SOURCES
)

Python3_add_library(naja_snl_python SHARED ${SOURCES})
target_link_libraries(naja_snl_python PUBLIC naja_snl)
target_link_libraries(naja_snl_python PUBLIC naja_snl_verilog)
target_include_directories(naja_snl_python PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

Python3_add_library(snl MODULE PySNL.cpp)
Expand Down
16 changes: 11 additions & 5 deletions src/snl/python/snl_wrapping/PySNLBusNetBit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

#include "PyInterface.h"
#include "PySNLDesign.h"

#include "SNLBusNetBit.h"
#include "PySNLBusNet.h"

namespace PYSNL {

Expand All @@ -16,10 +15,17 @@ using namespace naja::SNL;
#undef ACCESS_OBJECT
#undef ACCESS_CLASS
#define ACCESS_OBJECT parent_.parent_.parent_.object_
#define ACCESS_CLASS(_pyObject) &(_pyObject->parent_)
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(BusNetBit, net, function)
#define ACCESS_CLASS(_pyObject) &(_pyObject->parent_)
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(SNLBusNetBit, function)

DirectGetIntMethod(PySNLBusNetBit_getBit, getBit, PySNLBusNetBit, SNLBusNetBit)
GetObjectMethod(BusNetBit, BusNet, getBus)

PyMethodDef PySNLBusNetBit_Methods[] = {
{ "getBit", (PyCFunction)PySNLBusNetBit_getBit, METH_NOARGS,
"get SNLBusNetBit Bit value"},
{ "getBus", (PyCFunction)PySNLBusNetBit_getBus, METH_NOARGS,
"get SNLBusNetBit Bus net"},
{NULL, NULL, 0, NULL} /* sentinel */
};

Expand All @@ -29,4 +35,4 @@ DBoLinkCreateMethod(SNLBusNetBit)
PyTypeSNLFinalObjectWithSNLIDLinkPyType(SNLBusNetBit)
PyTypeObjectDefinitions(SNLBusNetBit)

}
}
15 changes: 10 additions & 5 deletions src/snl/python/snl_wrapping/PySNLBusTermBit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "PyInterface.h"
#include "PySNLDesign.h"
#include "PySNLBusTerm.h"

namespace PYSNL {

Expand All @@ -15,19 +16,23 @@ using namespace naja::SNL;
#undef ACCESS_CLASS
#define ACCESS_OBJECT parent_.parent_.parent_.parent_.object_
#define ACCESS_CLASS(_pyObject) &(_pyObject->parent_)
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(Instance, instance, function)
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(SNLBusTermBit, function)



PyTypeObjectDefinitions(SNLBusTermBit)
DirectGetIntMethod(PySNLBusTermBit_getBit, getBit, PySNLBusTermBit, SNLBusTermBit)
GetObjectMethod(BusTermBit, BusTerm, getBus)

PyMethodDef PySNLBusTermBit_Methods[] = {
{ "getBit", (PyCFunction)PySNLBusTermBit_getBit, METH_NOARGS,
"get SNLBusTermBit Bit value"},
{ "getBus", (PyCFunction)PySNLBusTermBit_getBus, METH_NOARGS,
"get SNLBusTermBit Bus term"},
{NULL, NULL, 0, NULL} /* sentinel */
};

DBoLinkCreateMethod(SNLBusTermBit)
DBoDeallocMethod(SNLBusTermBit)
PyTypeObjectDefinitions(SNLBusTermBit)

PyTypeSNLFinalObjectWithSNLIDLinkPyType(SNLBusTermBit)

}
}
27 changes: 23 additions & 4 deletions src/snl/python/snl_wrapping/PySNLDesign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "SNLDesign.h"
#include "SNLDesignModeling.h"
#include "SNLVRLDumper.h"

namespace PYSNL {

Expand Down Expand Up @@ -99,6 +100,22 @@ static PyObject* PySNLDesign_clone(PySNLDesign* self, PyObject* args) {
return PySNLDesign_Link(newDesign);
}

static PyObject* PySNLDesign_dumpVerilog(PySNLDesign* self, PyObject* args) {
const char* arg0 = nullptr;
const char* arg1 = nullptr;
if (not PyArg_ParseTuple(args, "ss:SNLDesign.dumpVerilog", &arg0, &arg1)) {
setError("malformed SNLDesign.dumpVerilog method");
return nullptr;
}
METHOD_HEAD("SNLDesign.dumpVerilog()")
SNLTRY
SNLVRLDumper dumper;
dumper.setTopFileName(arg1);
dumper.dumpDesign(selfObject, std::filesystem::path(arg0));
SNLCATCH
Py_RETURN_NONE;
}

static PyObject* PySNLDesign_addCombinatorialArcs(PySNLDesign* self, PyObject* args) {
PyObject* arg0 = nullptr;
PyObject* arg1 = nullptr;
Expand Down Expand Up @@ -320,9 +337,9 @@ PyMethodDef PySNLDesign_Methods[] = {
"get SNLDesign name"},
{ "isAnonymous", (PyCFunction)PySNLDesign_isAnonymous, METH_NOARGS,
"Returns True if the SNLDesign is anonymous"},
{"getDB", (PyCFunction)PySNLDesign_getDB, METH_NOARGS,
{ "getDB", (PyCFunction)PySNLDesign_getDB, METH_NOARGS,
"Returns the SNLDesign owner SNLDB."},
{"getLibrary", (PyCFunction)PySNLDesign_getLibrary, METH_NOARGS,
{ "getLibrary", (PyCFunction)PySNLDesign_getLibrary, METH_NOARGS,
"Returns the SNLDesign owner SNLLibrary."},
{ "getTerm", (PyCFunction)PySNLDesign_getTerm, METH_VARARGS,
"retrieve a SNLTerm."},
Expand Down Expand Up @@ -356,10 +373,12 @@ PyMethodDef PySNLDesign_Methods[] = {
"get a container of SNLInstances."},
{ "getParameters", (PyCFunction)PySNLDesign_getParameters, METH_NOARGS,
"get a container of SNLParameters."},
{"destroy", (PyCFunction)PySNLDesign_destroy, METH_NOARGS,
{ "destroy", (PyCFunction)PySNLDesign_destroy, METH_NOARGS,
"destroy this SNLDesign."},
{"clone", (PyCFunction)PySNLDesign_clone, METH_VARARGS,
{ "clone", (PyCFunction)PySNLDesign_clone, METH_VARARGS,
"clone this SNLDesign."},
{ "dumpVerilog", (PyCFunction)PySNLDesign_dumpVerilog, METH_VARARGS,
"dump verilog file of this SNLDesign."},
{NULL, NULL, 0, NULL} /* sentinel */
};

Expand Down
2 changes: 1 addition & 1 deletion src/snl/snl/kernel/SNLBusNet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ SNLNet* SNLBusNet::clone(SNLDesign* design) const {
auto newBus = new SNLBusNet(design, id_, msb_, lsb_, name_);
newBus->createBits();
for (size_t i=0; i<bits_.size(); i++) {
bits_[i]->cloneComponents(getBitAtPosition(i));
bits_[i]->cloneComponents(newBus->bits_[i]);
}
return newBus;
}
Expand Down
2 changes: 1 addition & 1 deletion test/snl/python/snl_wrapping/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ add_test(NAME naja-python-tests

set_tests_properties(naja-python-tests
PROPERTIES ENVIRONMENT
"PYTHONPATH=${PROJECT_BINARY_DIR}/src/snl/python/snl_wrapping:$ENV{PYTHONPATH}"
"PYTHONPATH=${PROJECT_BINARY_DIR}/src/snl/python/snl_wrapping:$ENV{PYTHONPATH};SNL_WRAPPING_TEST_PATH=${CMAKE_CURRENT_BINARY_DIR}"
)
4 changes: 4 additions & 0 deletions test/snl/python/snl_wrapping/test_snldesign.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ def testParameterClashErrors(self):
with self.assertRaises(RuntimeError) as context: snl.SNLParameter.create_string(design, "MODE", "DEFAULT")
with self.assertRaises(RuntimeError) as context: snl.SNLParameter.create_boolean(design, "INVERTED", True)

def testDumpVerilogError(self):
self.assertIsNotNone(self.lib)
design = snl.SNLDesign.create(self.lib, "DESIGN")
with self.assertRaises(RuntimeError) as context: design.dumpVerilog("ERROR")

def testDestroy(self):
design = snl.SNLDesign.create(self.lib, "DESIGN")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import unittest
import snl

class SNLDesignUniquifyTest(unittest.TestCase):
class SNLDesignCloneTest1(unittest.TestCase):
def setUp(self):
universe = snl.SNLUniverse.create()
db = snl.SNLDB.create(universe)
Expand All @@ -22,7 +22,7 @@ def tearDown(self):
if snl.SNLUniverse.get():
snl.SNLUniverse.get().destroy()

def testUniquifyInterface0(self):
def testCloneInterface0(self):
newDesign = self.design.clone()
self.assertIsNotNone(newDesign)
self.assertNotEqual(self.design, newDesign)
Expand All @@ -36,7 +36,7 @@ def testUniquifyInterface0(self):
newParametersSize = sum(1 for p in newDesign.getParameters())
self.assertEqual(parametersSize, newParametersSize)

def testUniquifyInterface1(self):
def testCloneInterface1(self):
newDesign = self.design.clone("cloned")
self.assertIsNotNone(newDesign)
self.assertNotEqual(self.design, newDesign)
Expand Down
81 changes: 81 additions & 0 deletions test/snl/python/snl_wrapping/test_snldesign_clone2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# SPDX-FileCopyrightText: 2023 The Naja authors <https://github.com/najaeda/naja/blob/main/AUTHORS>
#
# SPDX-License-Identifier: Apache-2.0

import unittest
import os
import shutil
import snl

class SNLDesignCloneTest2(unittest.TestCase):
def setUp(self):
universe = snl.SNLUniverse.create()
db = snl.SNLDB.create(universe)
primitives = snl.SNLLibrary.createPrimitives(db)
self.prim = snl.SNLDesign.createPrimitive(primitives, "PRIM")
primi = snl.SNLScalarTerm.create(self.prim, snl.SNLTerm.Direction.Input, "I")
primo = snl.SNLBusTerm.create(self.prim, 1, 0, snl.SNLTerm.Direction.Output, "O")
lib = snl.SNLLibrary.create(db)
self.design = snl.SNLDesign.create(lib, "DESIGN")
i0 = snl.SNLScalarTerm.create(self.design, snl.SNLTerm.Direction.Input, "I0")
i0Net = snl.SNLScalarNet.create(self.design, "I0")
i0.setNet(i0Net)
i1 = snl.SNLBusTerm.create(self.design, snl.SNLTerm.Direction.Input, -5, 4, "I1")
i1Net = snl.SNLBusNet.create(self.design, -5, 4, "I1")
i1.setNet(i1Net)
o = snl.SNLScalarTerm.create(self.design, snl.SNLTerm.Direction.Output, "O")
oNet = snl.SNLScalarNet.create(self.design, "O")
o.setNet(oNet)
ins0 = snl.SNLInstance.create(self.design, self.prim, "INS0")
ins0.getInstTerm(ins0.getModel().getScalarTerm("I")).setNet(i0Net)
n0 = snl.SNLBusNet.create(self.design, 1, 0, "N0")
ins0.getInstTerm(ins0.getModel().getBusTerm("O").getBit(1)).setNet(n0.getBit(0))
ins1 = snl.SNLInstance.create(self.design, self.prim, "INS1")
ins1.getInstTerm(ins1.getModel().getScalarTerm("I")).setNet(n0.getBit(0))

def tearDown(self):
del self.design
if snl.SNLUniverse.get():
snl.SNLUniverse.get().destroy()

def testCloneInterface(self):
newDesign = self.design.clone()
self.assertIsNotNone(newDesign)
self.assertNotEqual(self.design, newDesign)
self.assertTrue(newDesign.isAnonymous())
self.assertEqual(self.design.getLibrary(), newDesign.getLibrary())
self.assertEqual(self.design.getDB(), newDesign.getDB())
termsSize = sum(1 for t in self.design.getTerms())
newTermsSize = sum(1 for t in newDesign.getTerms())
self.assertEqual(termsSize, newTermsSize)
parametersSize = sum(1 for p in self.design.getParameters())
newParametersSize = sum(1 for p in newDesign.getParameters())
self.assertEqual(parametersSize, newParametersSize)

def testClone(self):
newDesign = self.design.clone("cloned")
self.assertIsNotNone(newDesign)
bench_dir = os.environ.get('SNL_WRAPPING_TEST_PATH')
self.assertIsNotNone(bench_dir)
bench_dir = os.path.join(bench_dir, "snldesign_clone2")
if os.path.exists(bench_dir):
shutil.rmtree(bench_dir)
os.makedirs(bench_dir)
newDesign.dumpVerilog(os.path.join(bench_dir), "cloned.v")

n0 = newDesign.getNet("N0")
self.assertIsNotNone(n0)
self.assertIsInstance(n0, snl.SNLBusNet)
self.assertEqual(1, n0.getMSB())
self.assertEqual(0, n0.getLSB())
self.assertEqual(2, n0.getSize())
self.assertEqual(2, sum(1 for b in n0.getBits()))
n0b0 = n0.getBit(0)
self.assertIsNotNone(n0b0)
self.assertIsInstance(n0b0, snl.SNLBusNetBit)
self.assertEqual(0, n0b0.getBit())
self.assertEqual(n0, n0b0.getBus())
self.assertEqual(2, sum(1 for c in n0b0.getComponents()))

if __name__ == '__main__':
unittest.main()
4 changes: 4 additions & 0 deletions test/snl/python/snl_wrapping/test_snlnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ def testComponents(self):
i1NetList = list(i1Net.getComponents())
self.assertEqual(3, len(i1NetList))
self.assertEqual(topI1.getBit(0), i1NetList[0])
self.assertEqual(topI1, topI1.getBit(0).getBus())
self.assertEqual(0, topI1.getBit(0).getBit())
self.assertEqual(ins1.getInstTerm(self.model.getScalarTerm("i1")), i1NetList[1])
self.assertEqual(ins2.getInstTerm(self.model.getScalarTerm("i1")), i1NetList[2])

Expand Down Expand Up @@ -168,6 +170,8 @@ def testRenameNet(self):
self.assertEqual(i1Net, self.design.getNet("I3"))
self.assertIsNone(self.design.getNet("I0"))
self.assertIsNone(self.design.getNet("I1"))
self.assertEqual(i1Net, i1Net.getBit(0).getBus())
self.assertEqual(0, i1Net.getBit(0).getBit())

def testErrors(self):
self.assertIsNotNone(self.design)
Expand Down
21 changes: 21 additions & 0 deletions test/snl/snl/kernel/SNLDesignCloneTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,15 @@ TEST_F(SNLDesignCloneTest, testCloneInterface2) {
}

TEST_F(SNLDesignCloneTest, testClone0) {
//before cloning
{
auto net1 = design_->getBusNet(SNLName("net1"));
ASSERT_NE(nullptr, net1);
auto net1Bit0 = net1->getBit(0);
ASSERT_NE(nullptr, net1Bit0);
ASSERT_EQ(2, net1Bit0->getComponents().size());
}

auto newDesign = design_->clone();
ASSERT_NE(nullptr, newDesign);
EXPECT_TRUE(newDesign->isAnonymous());
Expand All @@ -221,6 +230,18 @@ TEST_F(SNLDesignCloneTest, testClone0) {
compareParameters(design_, newDesign);
compareInstances(design_, newDesign);
compareNets(design_, newDesign);

//dive into bus connection
auto net1 = design_->getBusNet(SNLName("net1"));
ASSERT_NE(nullptr, net1);
auto newNet1 = newDesign->getBusNet(SNLName("net1"));
ASSERT_NE(nullptr, newNet1);
auto net1Bit0 = net1->getBit(0);
ASSERT_NE(nullptr, net1Bit0);
auto newNet1Bit0 = newNet1->getBit(0);
ASSERT_NE(nullptr, newNet1Bit0);
ASSERT_EQ(2, net1Bit0->getComponents().size());
ASSERT_EQ(2, newNet1Bit0->getComponents().size());
}

TEST_F(SNLDesignCloneTest, testCloneCompare) {
Expand Down

0 comments on commit 87b97f3

Please sign in to comment.