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