From d8e82643e6ce8590be9ba41c294b9ccd36fbeef1 Mon Sep 17 00:00:00 2001 From: Damien Dupuis Date: Tue, 10 May 2011 14:25:49 +0000 Subject: [PATCH] Adding Boost::Python wrapping --- vlsisapd/src/spice/src/CMakeLists.txt | 22 +-- vlsisapd/src/spice/src/PySpice.cpp | 150 ++++++++++++++++++ .../src/vlsisapd/spice/PySTLMapWrapper.h | 87 ++++++++++ .../src/spice/src/vlsisapd/spice/Subckt.h | 16 +- 4 files changed, 256 insertions(+), 19 deletions(-) create mode 100644 vlsisapd/src/spice/src/PySpice.cpp create mode 100644 vlsisapd/src/spice/src/vlsisapd/spice/PySTLMapWrapper.h diff --git a/vlsisapd/src/spice/src/CMakeLists.txt b/vlsisapd/src/spice/src/CMakeLists.txt index 89f88910..713beeee 100644 --- a/vlsisapd/src/spice/src/CMakeLists.txt +++ b/vlsisapd/src/spice/src/CMakeLists.txt @@ -13,22 +13,22 @@ SET ( cpps Circuit.cpp Subckt.cpp Value.cpp ) -#SET ( pycpps PySpice.cpp -# ) +SET ( pycpps PySpice.cpp + ) ADD_LIBRARY(spice ${cpps}) TARGET_LINK_LIBRARIES(spice) SET_TARGET_PROPERTIES(spice PROPERTIES VERSION 1.0 SOVERSION 1) INSTALL(TARGETS spice DESTINATION lib${LIB_SUFFIX} ) -#IF(Boost_FOUND) -# ADD_LIBRARY(pySPICE MODULE ${pycpps}) -# SET_TARGET_PROPERTIES(pySPICE PROPERTIES -# OUTPUT_NAME "SPICE" -# PREFIX "" -# ) -# TARGET_LINK_LIBRARIES(pySPICE spice ${Boost_LIBRARIES} ${PYTHON_LIBRARIES}) -# INSTALL(TARGETS pySPICE DESTINATION ${PYTHON_SITE_PACKAGES}) -#ENDIF(Boost_FOUND) +IF(Boost_FOUND) + ADD_LIBRARY(pySPICE MODULE ${pycpps}) + SET_TARGET_PROPERTIES(pySPICE PROPERTIES + OUTPUT_NAME "SPICE" + PREFIX "" + ) + TARGET_LINK_LIBRARIES(pySPICE spice ${Boost_LIBRARIES} ${PYTHON_LIBRARIES}) + INSTALL(TARGETS pySPICE DESTINATION ${PYTHON_SITE_PACKAGES}) +ENDIF(Boost_FOUND) INSTALL(FILES ${hpps} DESTINATION include/vlsisapd/spice) diff --git a/vlsisapd/src/spice/src/PySpice.cpp b/vlsisapd/src/spice/src/PySpice.cpp new file mode 100644 index 00000000..5afb3dcd --- /dev/null +++ b/vlsisapd/src/spice/src/PySpice.cpp @@ -0,0 +1,150 @@ +using namespace std; + +#include +#include +using namespace boost::python; + +#include "vlsisapd/spice/Instances.h" +#include "vlsisapd/spice/Sources.h" +#include "vlsisapd/spice/Subckt.h" +#include "vlsisapd/spice/Circuit.h" +#include "vlsisapd/spice/SpiceException.h" + +#include "vlsisapd/spice/PySTLMapWrapper.h" + +namespace SPICE { +void translator(SpiceException const& e) { + PyErr_SetString(PyExc_UserWarning, e.what()); +} + +// for optional arguments +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(addLibrary_overloads, addLibrary, 1, 2); + +BOOST_PYTHON_MODULE(SPICE) { + + // vector and map wrapping for Spice::Instance + class_ >("ConnectorsVector") + .def(vector_indexing_suite >()) + ; + STL_MAP_WRAPPING(std::string, std::string, "ParametersMap") + // class SPICE::Instance + class_("Instance", init()) + // accessors + .def("getName" , &Instance::getName ) + .def("getModel" , &Instance::getModel ) + .def("getParameterValue", &Instance::getParameterValue ) + // modifiers + .def("addConnector", &Instance::addConnector ) + .def("addParameter", &Instance::addParameter ) + // stl containers + .def("getConnectors", &Instance::getConnectors, return_value_policy()) + .def("getParameters", &Instance::getParameters, return_value_policy()) + ; + + // class SPICE::Mosfet + class_ >("Mosfet", init()) + // accessors + .def("getDrain" , &Mosfet::getDrain ) + .def("getGrid" , &Mosfet::getGrid ) + .def("getSource", &Mosfet::getSource ) + .def("getBulk" , &Mosfet::getBulk ) + ; + + // class SPICE::Capacitor + class_ >("Capacitor", init()) + // accessors + .def("getPositive", &Capacitor::getPositive ) + .def("getNegative", &Capacitor::getNegative ) + .def("getValue" , &Capacitor::getValue ) + ; + + // class SPICE::Resistor + class_ >("Resistor", init()) + // accessors + .def("getFirst" , &Resistor::getFirst ) + .def("getSecond", &Resistor::getSecond ) + .def("getValue" , &Resistor::getValue ) + ; + + // class SPICE::Source !! abstract class !! + class_("Source", no_init) + // accessors + .def("getName" , &Source::getName ) + .def("getPositive", &Source::getPositive ) + .def("getNegative", &Source::getNegative ) + .def("getValue" , &Source::getValue ) + ; + + // class SPICE::Voltage + class_ >("Voltage", init()) + ; + + // class SPICE::Current + class_ >("Current", init()) + ; + + + // vector indexing for Spice::Subckt + // InterfacesVector = ConnectorsVector already exists + class_ >("InstancesVector") + .def(vector_indexing_suite, true>()) + ; + // ParametersMap is already defined + // class SPICE::Subckt + class_("Subckt", init()) + // accessors + .def("getName", &Subckt::getName ) + // modifiers + .def("addInterface", &Subckt::addInterface ) + .def("addInstance" , &Subckt::addInstance ) + .def("addParameter", &Subckt::addParameter ) + // stl containers + .def("getInterfaces", &Subckt::getInterfaces, return_value_policy()) + .def("getInstances" , &Subckt::getInstances , return_value_policy()) + .def("getParameters", &Subckt::getParameters, return_value_policy()) + ; + + // vector indexing for Spice::Circuit + class_ > > ("LibrariesVector") + .def(vector_indexing_suite > >()) + ; + // InstancesVector already exists + // ParametersMap = OptionsMap already exists + class_ >("SourcesVector") + .def(vector_indexing_suite >()) + ; + class_ >("SubcktsVector") + .def(vector_indexing_suite >()) + ; + // class SPICE::Circuit + class_("Circuit", init<>()) + // properties + .add_property("title", &Circuit::getTitle, &Circuit::setTitle ) + // modifiers + .def("addInclude" , &Circuit::addInclude ) + .def("addLibrary" , &Circuit::addLibrary , addLibrary_overloads()) + .def("addInstance" , &Circuit::addInstance ) + .def("addSource" , &Circuit::addSource ) + .def("addOption" , &Circuit::addOption ) + .def("addParameter" , &Circuit::addParameter ) + .def("addSubckt" , &Circuit::addSubckt , return_value_policy()) + // stl containers + .def("getIncludes" , &Circuit::getIncludes , return_value_policy()) + .def("getLibraries" , &Circuit::getLibraries , return_value_policy()) + .def("getOptions" , &Circuit::getOptions , return_value_policy()) + .def("getParameters", &Circuit::getParameters, return_value_policy()) + .def("getSubckts" , &Circuit::getSubckts , return_value_policy()) + .def("getInstances" , &Circuit::getInstances , return_value_policy()) + .def("getSources" , &Circuit::getSources , return_value_policy()) + // others + .def("readFromFile" , &Circuit::readFromFile , return_value_policy()) + .staticmethod("readFromFile") + .def("writeToFile" , &Circuit::writeToFile ) + + ; + + // SpiceException translator + register_exception_translator(translator) + ; +} +} diff --git a/vlsisapd/src/spice/src/vlsisapd/spice/PySTLMapWrapper.h b/vlsisapd/src/spice/src/vlsisapd/spice/PySTLMapWrapper.h new file mode 100644 index 00000000..2cb7bfb1 --- /dev/null +++ b/vlsisapd/src/spice/src/vlsisapd/spice/PySTLMapWrapper.h @@ -0,0 +1,87 @@ +#include + +#include + +namespace SPICE { +// since we want to wrap std::map with cimple pointers (no boost::shared_ptr), +// we cannot use map_indexing_suite which has not the right return_value_policy. +// std::maps with no points value are wrapped using map_indexing_suite technique. +// +// This templated map_item struct is intended to be used for 'manual' wrapping: +template +struct map_item { + typedef std::map Map; + + static Val get(Map & self, const Key idx) { + if (self.find(idx) == self.end()) { + PyErr_SetString(PyExc_KeyError,"Map key not found"); + throw_error_already_set(); + } + return self[idx]; + } + + static void set(Map& self, const Key idx, const Val val) { self[idx]=val; } + static void del(Map& self, const Key n) { self.erase(n); } + static bool in (Map const& self, const Key n) { return self.find(n) != self.end(); } + + static list keys(Map const& self) { + list t; + for(typename Map::const_iterator it = self.begin() ; it!=self.end() ; ++it) + t.append(it->first); + return t; + } + + static list values(Map const& self) { + list t; + for(typename Map::const_iterator it=self.begin(); it!=self.end(); ++it) + t.append(it->second); + return t; + } + + static list items(Map const& self) { + list t; + for(typename Map::const_iterator it=self.begin(); it!=self.end(); ++it) + t.append( make_tuple(it->first, it->second) ); + return t; + } +}; + +#define STL_MAP_WRAPPING_PTR(KEY_TYPE, VALUE_TYPE, PYTHON_TYPE_NAME) \ + class_ >((std::string(PYTHON_TYPE_NAME)+std::string("DATA")).c_str()) \ + .def_readonly ("key" , &std::pair::first ) \ + .def_readwrite("value", &std::pair::second) \ + ; \ + class_ >(PYTHON_TYPE_NAME) \ + .def("__len__" , &std::map::size) \ + .def("__iter__" , boost::python::iterator, return_internal_reference<> >()) \ + .def("__getitem__" , &map_item().get, return_internal_reference<>()) \ + .def("__setitem__" , &map_item().set ) \ + .def("__delitem__" , &map_item().del ) \ + .def("__contains__", &map_item().in ) \ + .def("clear" , &std::map::clear ) \ + .def("has_key" , &map_item().in ) \ + .def("keys" , &map_item().keys ) \ + .def("values" , &map_item().values) \ + .def("items" , &map_item().items ) \ + ; + +#define STL_MAP_WRAPPING(KEY_TYPE, VALUE_TYPE, PYTHON_TYPE_NAME) \ + class_ >((std::string(PYTHON_TYPE_NAME)+std::string("DATA")).c_str()) \ + .def_readonly ("key" , &std::pair::first ) \ + .def_readwrite("value", &std::pair::second) \ + ; \ + class_ >(PYTHON_TYPE_NAME) \ + .def("__len__" , &std::map::size) \ + .def("__iter__" , boost::python::iterator, return_internal_reference<> >()) \ + .def("__getitem__" , &map_item().get ) \ + .def("__setitem__" , &map_item().set ) \ + .def("__delitem__" , &map_item().del ) \ + .def("__contains__", &map_item().in ) \ + .def("clear" , &std::map::clear ) \ + .def("has_key" , &map_item().in ) \ + .def("keys" , &map_item().keys ) \ + .def("values" , &map_item().values) \ + .def("items" , &map_item().items ) \ + ; + +} // namespace diff --git a/vlsisapd/src/spice/src/vlsisapd/spice/Subckt.h b/vlsisapd/src/spice/src/vlsisapd/spice/Subckt.h index 66830a10..5428b5e8 100644 --- a/vlsisapd/src/spice/src/vlsisapd/spice/Subckt.h +++ b/vlsisapd/src/spice/src/vlsisapd/spice/Subckt.h @@ -20,20 +20,20 @@ class Subckt { Subckt(std::string name): _name(name), _interfaces(), _instances(), _parameters() {} ~Subckt() {} - inline std::string getName(); - inline std::vector& getInterfaces(); - inline std::vector& getInstances(); - inline std::map& getParameters(); + inline const std::string getName(); + inline const std::vector& getInterfaces(); + inline const std::vector& getInstances(); + inline const std::map& getParameters(); inline void addInterface(std::string); inline void addInstance (Instance*); void addParameter(std::string, std::string); }; -inline std::string Subckt::getName() { return _name; } -inline std::vector& Subckt::getInterfaces() { return _interfaces; } -inline std::vector& Subckt::getInstances() { return _instances; } -inline std::map& Subckt::getParameters() { return _parameters; } +inline const std::string Subckt::getName() { return _name; } +inline const std::vector& Subckt::getInterfaces() { return _interfaces; } +inline const std::vector& Subckt::getInstances() { return _instances; } +inline const std::map& Subckt::getParameters() { return _parameters; } inline void Subckt::addInterface(std::string name) { _interfaces.push_back(name); } inline void Subckt::addInstance(Instance* inst) { _instances.push_back(inst); }