summaryrefslogtreecommitdiff
path: root/ext/dsent/model/electrical/router/RouterInputPort.cc
blob: b698d3d80a076c6eec995f830d9a2b7ab0591ab6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#include "model/electrical/router/RouterInputPort.h"

#include <cmath>
#include <vector>

#include "model/PortInfo.h"
#include "model/EventInfo.h"
#include "model/TransitionInfo.h"
#include "model/ModelGen.h"
#include "model/std_cells/StdCellLib.h"
#include "model/std_cells/StdCell.h"

namespace DSENT
{
    using std::ceil;
    using std::vector;
    using LibUtil::castStringVector;

    RouterInputPort::RouterInputPort(const String& instance_name_, const TechModel* tech_model_)
        : ElectricalModel(instance_name_, tech_model_)
    {
        initParameters();
        initProperties();
    }

    RouterInputPort::~RouterInputPort()
    {}

    void RouterInputPort::initParameters()
    {
        addParameterName("NumberVirtualNetworks");
        addParameterName("NumberVirtualChannelsPerVirtualNetwork");
        addParameterName("NumberBuffersPerVirtualChannel");
        addParameterName("NumberBitsPerFlit");
        addParameterName("BufferModel");
        return;
    }

    void RouterInputPort::initProperties()
    {
        return;
    }

    RouterInputPort* RouterInputPort::clone() const
    {
        // TODO 
        return NULL;
    }

    void RouterInputPort::constructModel()
    {
        // Get parameters
        unsigned int number_vns = getParameter("NumberVirtualNetworks").toUInt();
        const vector<unsigned int>& number_vcs_per_vn_vector = castStringVector<unsigned int>(getParameter("NumberVirtualChannelsPerVirtualNetwork").split("[,]"));
        const vector<unsigned int>& number_bufs_per_vc_vector = castStringVector<unsigned int>(getParameter("NumberBuffersPerVirtualChannel").split("[,]"));
        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
        const String& buffer_model = getParameter("BufferModel");

        ASSERT(number_vns > 0, "[Error] " + getInstanceName() + 
            " -> Number of virtual networks must be > 0!");
        ASSERT(number_vcs_per_vn_vector.size() == number_vns, "[Error] " + getInstanceName() + 
            " -> Expecting " + (String)number_vns + " number of vcs, got " + 
            getParameter("NumberVirtualChannelsPerVirtualNetwork"));
        for(unsigned int i = 0; i < number_vns; ++i)
        {
            ASSERT(number_vcs_per_vn_vector[i] > 0, "[Error] " + getInstanceName() + 
                " -> Number of virtual channels per virtual network must be > 0!");
        }
        ASSERT(number_bufs_per_vc_vector.size() == number_vns, "[Error] " + getInstanceName() + 
            " -> Expecting " + (String)number_vns + " number of bufs per vc, got " + 
            getParameter("NumberBuffersPerVirtualChannel"));
        for(unsigned int i = 0; i < number_vns; ++i)
        {
            ASSERT(number_bufs_per_vc_vector[i] > 0, "[Error] " + getInstanceName() + 
                " -> Number of buffers per virtual channel must be > 0!");
        }
        ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() + 
            " -> Number of bits per buffer must be > 0!");

        // Calculate total number of buffers needed in the RAM
        unsigned int total_number_vcs = 0;
        unsigned int total_number_bufs = 0;
        for(unsigned int i = 0; i < number_vns; ++i)
        {
            total_number_vcs += number_vcs_per_vn_vector[i];
            total_number_bufs += number_vcs_per_vn_vector[i] * number_bufs_per_vc_vector[i];
        }
        unsigned int number_addr_bits = (unsigned int)ceil(log2(total_number_bufs));

        getGenProperties()->set("TotalNumberVirtualChannels", total_number_vcs);
        getGenProperties()->set("TotalNumberBuffers", total_number_bufs);
        getGenProperties()->set("NumberAddressBits", number_addr_bits);
        getGenProperties()->set("NumberOutputs", 1);

        createInputPort("CK");
        createInputPort("FlitIn", makeNetIndex(0, number_bits_per_flit-1));
        createOutputPort("FlitOut", makeNetIndex(0, number_bits_per_flit-1));

        // Create energy, power, and area results
        createElectricalResults();
        getEventInfo("Idle")->setStaticTransitionInfos();
        getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));

        addEventResult(new Result("ReadBuffer"));
        addEventResult(new Result("WriteBuffer"));

        // Init RAM
        const String& ram_name = "RAM";
        ElectricalModel* ram = ModelGen::createRAM(buffer_model, ram_name, getTechModel());
        ram->setParameter("NumberEntries", total_number_bufs);
        ram->setParameter("NumberBits", number_bits_per_flit);
        ram->construct();

        // Init DFF for read address
        vector<String> rd_addr_dff_names(number_addr_bits, "");
        vector<StdCell*> rd_addr_dffs(number_addr_bits, NULL);
        for(unsigned int i = 0; i < number_addr_bits; ++i)
        {
            rd_addr_dff_names[i] = "RDAddr_DFF" + (String)i;
            rd_addr_dffs[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", rd_addr_dff_names[i]);
            rd_addr_dffs[i]->construct();
        }

        // Connect RDAddr_DFFs
        for(unsigned int i = 0; i < number_addr_bits; ++i)
        {
            createNet("RDAddr_DFF_Out" + (String)i);

            portConnect(rd_addr_dffs[i], "CK", "CK");
            portConnect(rd_addr_dffs[i], "Q", "RDAddr_DFF_Out" + (String)i);
        }

        // Connect RAM
        portConnect(ram, "In", "FlitIn");
        for(unsigned int i = 0; i < number_addr_bits; ++i)
        {
            portConnect(ram, "WRAddr" + (String)i, "FlitIn", makeNetIndex(i));
            portConnect(ram, "RDAddr" + (String)i, "RDAddr_DFF_Out" + (String)i);
        }
        portConnect(ram, "WE", "FlitIn", makeNetIndex(number_bits_per_flit-1));
        portConnect(ram, "CK", "CK");
        portConnect(ram, "Out", "FlitOut");

        // Add area, power, event results 
        for(unsigned int i = 0; i < number_addr_bits; ++i)
        {
            addSubInstances(rd_addr_dffs[i], number_addr_bits);
            addElectricalSubResults(rd_addr_dffs[i], number_addr_bits);
        }
        addSubInstances(ram, 1.0);
        addElectricalSubResults(ram, 1.0);

        getEventResult("WriteBuffer")->addSubResult(ram->getEventResult("Write"), ram_name, 1.0);

        for(unsigned int i = 0; i < number_addr_bits; ++i)
        {
            getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("DFFD"), rd_addr_dff_names[i], number_addr_bits);
            getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("DFFQ"), rd_addr_dff_names[i], number_addr_bits);
            getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("CK"), rd_addr_dff_names[i], number_addr_bits);
        }
        getEventResult("ReadBuffer")->addSubResult(ram->getEventResult("Read"), ram_name, 1.0);

        return;
    }

    void RouterInputPort::propagateTransitionInfo()
    {
        // Update probability and activity
        unsigned int number_addr_bits = getGenProperties()->get("NumberAddressBits").toUInt();

        vector<ElectricalModel*> rd_addr_dffs(number_addr_bits, NULL);
        for(unsigned int i = 0; i < number_addr_bits; ++i)
        {
            rd_addr_dffs[i] = (ElectricalModel*)getSubInstance("RDAddr_DFF" + (String)i);
            assignPortTransitionInfo(rd_addr_dffs[i], "D", TransitionInfo());
            propagatePortTransitionInfo(rd_addr_dffs[i], "CK", "CK");
            rd_addr_dffs[i]->use();
        }

        ElectricalModel* ram = (ElectricalModel*)getSubInstance("RAM");

        // Setup default transition info
        const String& current_event = getGenProperties()->get("UseModelEvent");
        if(current_event != "Idle")
        {
            propagatePortTransitionInfo(ram, "In", "FlitIn");
            propagatePortTransitionInfo(ram, "CK", "CK");
            assignPortTransitionInfo(ram, "WE", TransitionInfo(0.0, 0.0, 1.0));
            for(unsigned int i = 0; i < number_addr_bits; ++i)
            {
                assignPortTransitionInfo(ram, "WRAddr" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
                assignPortTransitionInfo(ram, "RDAddr" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
            }
        }
        ram->use();
        // Set output probability
        propagatePortTransitionInfo("FlitOut", ram, "Out");
        return;
    }
} // namespace DSENT