110448Snilay@cs.wisc.edu/* Copyright (c) 2014 Mark D. Hill and David A. Wood 210448Snilay@cs.wisc.edu * All rights reserved. 310448Snilay@cs.wisc.edu * 410448Snilay@cs.wisc.edu * Redistribution and use in source and binary forms, with or without 510448Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are 610448Snilay@cs.wisc.edu * met: redistributions of source code must retain the above copyright 710448Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer; 810448Snilay@cs.wisc.edu * redistributions in binary form must reproduce the above copyright 910448Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer in the 1010448Snilay@cs.wisc.edu * documentation and/or other materials provided with the distribution; 1110448Snilay@cs.wisc.edu * neither the name of the copyright holders nor the names of its 1210448Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from 1310448Snilay@cs.wisc.edu * this software without specific prior written permission. 1410448Snilay@cs.wisc.edu * 1510448Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1610448Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1710448Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1810448Snilay@cs.wisc.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1910448Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2010448Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2110448Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2210448Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2310448Snilay@cs.wisc.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2410448Snilay@cs.wisc.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2510448Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2610448Snilay@cs.wisc.edu */ 2710448Snilay@cs.wisc.edu 2810448Snilay@cs.wisc.edu#include <Python.h> 2910448Snilay@cs.wisc.edu#include <cstdio> 3010448Snilay@cs.wisc.edu 3110448Snilay@cs.wisc.edu#include "DSENT.h" 3210448Snilay@cs.wisc.edu#include "libutil/String.h" 3310448Snilay@cs.wisc.edu#include "model/Model.h" 3410448Snilay@cs.wisc.edu 3510448Snilay@cs.wisc.eduusing namespace std; 3610448Snilay@cs.wisc.eduusing namespace LibUtil; 3710448Snilay@cs.wisc.edu 3810448Snilay@cs.wisc.edustatic PyObject *DSENTError; 3910448Snilay@cs.wisc.edustatic PyObject* dsent_initialize(PyObject*, PyObject*); 4010448Snilay@cs.wisc.edustatic PyObject* dsent_finalize(PyObject*, PyObject*); 4110448Snilay@cs.wisc.edustatic PyObject* dsent_computeRouterPowerAndArea(PyObject*, PyObject*); 4210448Snilay@cs.wisc.edustatic PyObject* dsent_computeLinkPower(PyObject*, PyObject*); 4310448Snilay@cs.wisc.edu 4410448Snilay@cs.wisc.edu// Create DSENT configuration map. This map is supposed to retain all 4510448Snilay@cs.wisc.edu// the information between calls to initialize() and finalize(). 4610448Snilay@cs.wisc.edumap<String, String> params; 4710448Snilay@cs.wisc.eduDSENT::Model *ms_model; 4810448Snilay@cs.wisc.edu 4910448Snilay@cs.wisc.edu 5010448Snilay@cs.wisc.edustatic PyMethodDef DSENTMethods[] = { 5110448Snilay@cs.wisc.edu {"initialize", dsent_initialize, METH_O, 5210448Snilay@cs.wisc.edu "initialize dsent using a config file."}, 5310448Snilay@cs.wisc.edu 5410448Snilay@cs.wisc.edu {"finalize", dsent_finalize, METH_NOARGS, 5510448Snilay@cs.wisc.edu "finalize dsent by dstroying the config object"}, 5610448Snilay@cs.wisc.edu 5710448Snilay@cs.wisc.edu {"computeRouterPowerAndArea", dsent_computeRouterPowerAndArea, 5810448Snilay@cs.wisc.edu METH_VARARGS, "compute quantities related power consumption of a router"}, 5910448Snilay@cs.wisc.edu 6010448Snilay@cs.wisc.edu {"computeLinkPower", dsent_computeLinkPower, METH_O, 6110448Snilay@cs.wisc.edu "compute quantities related power consumption of a link"}, 6210448Snilay@cs.wisc.edu 6310448Snilay@cs.wisc.edu {NULL, NULL, 0, NULL} 6410448Snilay@cs.wisc.edu}; 6510448Snilay@cs.wisc.edu 6610448Snilay@cs.wisc.edu 6710448Snilay@cs.wisc.eduPyMODINIT_FUNC 6810448Snilay@cs.wisc.eduinitdsent(void) 6910448Snilay@cs.wisc.edu{ 7010448Snilay@cs.wisc.edu PyObject *m; 7110448Snilay@cs.wisc.edu 7210448Snilay@cs.wisc.edu m = Py_InitModule("dsent", DSENTMethods); 7310448Snilay@cs.wisc.edu if (m == NULL) return; 7410448Snilay@cs.wisc.edu 7510448Snilay@cs.wisc.edu DSENTError = PyErr_NewException("dsent.error", NULL, NULL); 7610448Snilay@cs.wisc.edu Py_INCREF(DSENTError); 7710448Snilay@cs.wisc.edu PyModule_AddObject(m, "error", DSENTError); 7810448Snilay@cs.wisc.edu 7910448Snilay@cs.wisc.edu ms_model = nullptr; 8010448Snilay@cs.wisc.edu} 8110448Snilay@cs.wisc.edu 8210448Snilay@cs.wisc.edu 8310448Snilay@cs.wisc.edustatic PyObject * 8410448Snilay@cs.wisc.edudsent_initialize(PyObject *self, PyObject *arg) 8510448Snilay@cs.wisc.edu{ 8610448Snilay@cs.wisc.edu const char *config_file = PyString_AsString(arg); 8710448Snilay@cs.wisc.edu //Read the arguments sent from the python script 8810448Snilay@cs.wisc.edu if (!config_file) { 8910448Snilay@cs.wisc.edu Py_RETURN_NONE; 9010448Snilay@cs.wisc.edu } 9110448Snilay@cs.wisc.edu 9210448Snilay@cs.wisc.edu // Initialize DSENT 9310448Snilay@cs.wisc.edu ms_model = DSENT::initialize(config_file, params); 9410448Snilay@cs.wisc.edu Py_RETURN_NONE; 9510448Snilay@cs.wisc.edu} 9610448Snilay@cs.wisc.edu 9710448Snilay@cs.wisc.edu 9810448Snilay@cs.wisc.edustatic PyObject * 9910448Snilay@cs.wisc.edudsent_finalize(PyObject *self, PyObject *args) 10010448Snilay@cs.wisc.edu{ 10110448Snilay@cs.wisc.edu // Finalize DSENT 10210448Snilay@cs.wisc.edu DSENT::finalize(params, ms_model); 10310448Snilay@cs.wisc.edu ms_model = nullptr; 10410448Snilay@cs.wisc.edu Py_RETURN_NONE; 10510448Snilay@cs.wisc.edu} 10610448Snilay@cs.wisc.edu 10710448Snilay@cs.wisc.edu 10810448Snilay@cs.wisc.edustatic PyObject * 10910448Snilay@cs.wisc.edudsent_computeRouterPowerAndArea(PyObject *self, PyObject *args) 11010448Snilay@cs.wisc.edu{ 11110448Snilay@cs.wisc.edu uint64_t frequency; 11210448Snilay@cs.wisc.edu unsigned int num_in_port; 11310448Snilay@cs.wisc.edu unsigned int num_out_port; 11410448Snilay@cs.wisc.edu unsigned int num_vclass; 11510448Snilay@cs.wisc.edu unsigned int num_vchannels; 11610448Snilay@cs.wisc.edu unsigned int num_buffers; 11710448Snilay@cs.wisc.edu 11810448Snilay@cs.wisc.edu unsigned int flit_width; 11910448Snilay@cs.wisc.edu const char *input_port_buffer_model; 12010448Snilay@cs.wisc.edu const char *crossbar_model; 12110448Snilay@cs.wisc.edu const char *sa_arbiter_model; 12210448Snilay@cs.wisc.edu const char *clk_tree_model; 12310448Snilay@cs.wisc.edu unsigned int clk_tree_num_levels; 12410448Snilay@cs.wisc.edu const char *clk_tree_wire_layer; 12510448Snilay@cs.wisc.edu double clk_tree_wire_width_mult; 12610448Snilay@cs.wisc.edu 12710448Snilay@cs.wisc.edu // Read the arguments sent from the python script 12810448Snilay@cs.wisc.edu if (!PyArg_ParseTuple(args, "KIIIIII", &frequency, &num_in_port, 12910448Snilay@cs.wisc.edu &num_out_port, &num_vclass, &num_vchannels, 13010448Snilay@cs.wisc.edu &num_buffers, &flit_width)) { 13110448Snilay@cs.wisc.edu Py_RETURN_NONE; 13210448Snilay@cs.wisc.edu } 13310448Snilay@cs.wisc.edu 13410448Snilay@cs.wisc.edu assert(frequency > 0.0); 13510448Snilay@cs.wisc.edu assert(num_in_port != 0); 13610448Snilay@cs.wisc.edu assert(num_out_port != 0); 13710448Snilay@cs.wisc.edu assert(num_vclass != 0); 13810448Snilay@cs.wisc.edu assert(flit_width != 0); 13910448Snilay@cs.wisc.edu 14010448Snilay@cs.wisc.edu vector<unsigned int> num_vchannels_vec(num_vclass, num_vchannels); 14110448Snilay@cs.wisc.edu vector<unsigned int> num_buffers_vec(num_vclass, num_buffers); 14210448Snilay@cs.wisc.edu // DSENT outputs 14310448Snilay@cs.wisc.edu map<string, double> outputs; 14410448Snilay@cs.wisc.edu 14510448Snilay@cs.wisc.edu params["Frequency"] = String(frequency); 14610448Snilay@cs.wisc.edu params["NumberInputPorts"] = String(num_in_port); 14710448Snilay@cs.wisc.edu params["NumberOutputPorts"] = String(num_out_port); 14810448Snilay@cs.wisc.edu params["NumberVirtualNetworks"] = String(num_vclass); 14910448Snilay@cs.wisc.edu params["NumberVirtualChannelsPerVirtualNetwork"] = 15010448Snilay@cs.wisc.edu vectorToString<unsigned int>(num_vchannels_vec); 15110448Snilay@cs.wisc.edu params["NumberBuffersPerVirtualChannel"] = 15210448Snilay@cs.wisc.edu vectorToString<unsigned int>(num_buffers_vec); 15310448Snilay@cs.wisc.edu params["NumberBitsPerFlit"] = String(flit_width); 15410448Snilay@cs.wisc.edu 15510448Snilay@cs.wisc.edu // Run DSENT 15610448Snilay@cs.wisc.edu DSENT::run(params, ms_model, outputs); 15710448Snilay@cs.wisc.edu 15810448Snilay@cs.wisc.edu // Store outputs 15910448Snilay@cs.wisc.edu PyObject *r = PyTuple_New(outputs.size()); 16010448Snilay@cs.wisc.edu int index = 0; 16110448Snilay@cs.wisc.edu 16210448Snilay@cs.wisc.edu // Prepare the output. The assumption is that all the output 16310448Snilay@cs.wisc.edu for (const auto &it : outputs) { 16410448Snilay@cs.wisc.edu PyObject *s = PyTuple_New(2); 16510448Snilay@cs.wisc.edu PyTuple_SetItem(s, 0, PyString_FromString(it.first.c_str())); 16610448Snilay@cs.wisc.edu PyTuple_SetItem(s, 1, PyFloat_FromDouble(it.second)); 16710448Snilay@cs.wisc.edu 16810448Snilay@cs.wisc.edu PyTuple_SetItem(r, index, s); 16910448Snilay@cs.wisc.edu index++; 17010448Snilay@cs.wisc.edu } 17110448Snilay@cs.wisc.edu 17210448Snilay@cs.wisc.edu return r; 17310448Snilay@cs.wisc.edu} 17410448Snilay@cs.wisc.edu 17510448Snilay@cs.wisc.edu 17610448Snilay@cs.wisc.edustatic PyObject * 17710448Snilay@cs.wisc.edudsent_computeLinkPower(PyObject *self, PyObject *arg) 17810448Snilay@cs.wisc.edu{ 17910448Snilay@cs.wisc.edu uint64_t frequency = PyLong_AsLongLong(arg); 18010448Snilay@cs.wisc.edu 18110448Snilay@cs.wisc.edu // Read the arguments sent from the python script 18210448Snilay@cs.wisc.edu if (frequency == -1) { 18310448Snilay@cs.wisc.edu Py_RETURN_NONE; 18410448Snilay@cs.wisc.edu } 18510448Snilay@cs.wisc.edu 18610448Snilay@cs.wisc.edu // DSENT outputs 18710448Snilay@cs.wisc.edu map<string, double> outputs; 18810448Snilay@cs.wisc.edu params["Frequency"] = String(frequency); 18910448Snilay@cs.wisc.edu 19010448Snilay@cs.wisc.edu // Run DSENT 19110448Snilay@cs.wisc.edu DSENT::run(params, ms_model, outputs); 19210448Snilay@cs.wisc.edu 19310448Snilay@cs.wisc.edu // Store outputs 19410448Snilay@cs.wisc.edu PyObject *r = PyTuple_New(outputs.size()); 19510448Snilay@cs.wisc.edu int index = 0; 19610448Snilay@cs.wisc.edu 19710448Snilay@cs.wisc.edu // Prepare the output. The assumption is that all the output 19810448Snilay@cs.wisc.edu for (const auto &it : outputs) { 19910448Snilay@cs.wisc.edu PyObject *s = PyTuple_New(2); 20010448Snilay@cs.wisc.edu PyTuple_SetItem(s, 0, PyString_FromString(it.first.c_str())); 20110448Snilay@cs.wisc.edu PyTuple_SetItem(s, 1, PyFloat_FromDouble(it.second)); 20210448Snilay@cs.wisc.edu 20310448Snilay@cs.wisc.edu PyTuple_SetItem(r, index, s); 20410448Snilay@cs.wisc.edu index++; 20510448Snilay@cs.wisc.edu } 20610448Snilay@cs.wisc.edu 20710448Snilay@cs.wisc.edu return r; 20810448Snilay@cs.wisc.edu} 20910448Snilay@cs.wisc.edu 21010448Snilay@cs.wisc.edustatic PyObject * 21110448Snilay@cs.wisc.edudsent_printAvailableModels(PyObject* self, PyObject *args) 21210448Snilay@cs.wisc.edu{ 21310448Snilay@cs.wisc.edu} 214