RouterInputPort.cc revision 10447
1#include "model/electrical/router/RouterInputPort.h"
2
3#include <cmath>
4#include <vector>
5
6#include "model/PortInfo.h"
7#include "model/EventInfo.h"
8#include "model/TransitionInfo.h"
9#include "model/ModelGen.h"
10#include "model/std_cells/StdCellLib.h"
11#include "model/std_cells/StdCell.h"
12
13namespace DSENT
14{
15    using std::ceil;
16    using std::vector;
17    using LibUtil::castStringVector;
18
19    RouterInputPort::RouterInputPort(const String& instance_name_, const TechModel* tech_model_)
20        : ElectricalModel(instance_name_, tech_model_)
21    {
22        initParameters();
23        initProperties();
24    }
25
26    RouterInputPort::~RouterInputPort()
27    {}
28
29    void RouterInputPort::initParameters()
30    {
31        addParameterName("NumberVirtualNetworks");
32        addParameterName("NumberVirtualChannelsPerVirtualNetwork");
33        addParameterName("NumberBuffersPerVirtualChannel");
34        addParameterName("NumberBitsPerFlit");
35        addParameterName("BufferModel");
36        return;
37    }
38
39    void RouterInputPort::initProperties()
40    {
41        return;
42    }
43
44    RouterInputPort* RouterInputPort::clone() const
45    {
46        // TODO
47        return NULL;
48    }
49
50    void RouterInputPort::constructModel()
51    {
52        // Get parameters
53        unsigned int number_vns = getParameter("NumberVirtualNetworks").toUInt();
54        const vector<unsigned int>& number_vcs_per_vn_vector = castStringVector<unsigned int>(getParameter("NumberVirtualChannelsPerVirtualNetwork").split("[,]"));
55        const vector<unsigned int>& number_bufs_per_vc_vector = castStringVector<unsigned int>(getParameter("NumberBuffersPerVirtualChannel").split("[,]"));
56        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
57        const String& buffer_model = getParameter("BufferModel");
58
59        ASSERT(number_vns > 0, "[Error] " + getInstanceName() +
60            " -> Number of virtual networks must be > 0!");
61        ASSERT(number_vcs_per_vn_vector.size() == number_vns, "[Error] " + getInstanceName() +
62            " -> Expecting " + (String)number_vns + " number of vcs, got " +
63            getParameter("NumberVirtualChannelsPerVirtualNetwork"));
64        for(unsigned int i = 0; i < number_vns; ++i)
65        {
66            ASSERT(number_vcs_per_vn_vector[i] > 0, "[Error] " + getInstanceName() +
67                " -> Number of virtual channels per virtual network must be > 0!");
68        }
69        ASSERT(number_bufs_per_vc_vector.size() == number_vns, "[Error] " + getInstanceName() +
70            " -> Expecting " + (String)number_vns + " number of bufs per vc, got " +
71            getParameter("NumberBuffersPerVirtualChannel"));
72        for(unsigned int i = 0; i < number_vns; ++i)
73        {
74            ASSERT(number_bufs_per_vc_vector[i] > 0, "[Error] " + getInstanceName() +
75                " -> Number of buffers per virtual channel must be > 0!");
76        }
77        ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() +
78            " -> Number of bits per buffer must be > 0!");
79
80        // Calculate total number of buffers needed in the RAM
81        unsigned int total_number_vcs = 0;
82        unsigned int total_number_bufs = 0;
83        for(unsigned int i = 0; i < number_vns; ++i)
84        {
85            total_number_vcs += number_vcs_per_vn_vector[i];
86            total_number_bufs += number_vcs_per_vn_vector[i] * number_bufs_per_vc_vector[i];
87        }
88        unsigned int number_addr_bits = (unsigned int)ceil(log2(total_number_bufs));
89
90        getGenProperties()->set("TotalNumberVirtualChannels", total_number_vcs);
91        getGenProperties()->set("TotalNumberBuffers", total_number_bufs);
92        getGenProperties()->set("NumberAddressBits", number_addr_bits);
93        getGenProperties()->set("NumberOutputs", 1);
94
95        createInputPort("CK");
96        createInputPort("FlitIn", makeNetIndex(0, number_bits_per_flit-1));
97        createOutputPort("FlitOut", makeNetIndex(0, number_bits_per_flit-1));
98
99        // Create energy, power, and area results
100        createElectricalResults();
101        getEventInfo("Idle")->setStaticTransitionInfos();
102        getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
103
104        addEventResult(new Result("ReadBuffer"));
105        addEventResult(new Result("WriteBuffer"));
106
107        // Init RAM
108        const String& ram_name = "RAM";
109        ElectricalModel* ram = ModelGen::createRAM(buffer_model, ram_name, getTechModel());
110        ram->setParameter("NumberEntries", total_number_bufs);
111        ram->setParameter("NumberBits", number_bits_per_flit);
112        ram->construct();
113
114        // Init DFF for read address
115        vector<String> rd_addr_dff_names(number_addr_bits, "");
116        vector<StdCell*> rd_addr_dffs(number_addr_bits, NULL);
117        for(unsigned int i = 0; i < number_addr_bits; ++i)
118        {
119            rd_addr_dff_names[i] = "RDAddr_DFF" + (String)i;
120            rd_addr_dffs[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", rd_addr_dff_names[i]);
121            rd_addr_dffs[i]->construct();
122        }
123
124        // Connect RDAddr_DFFs
125        for(unsigned int i = 0; i < number_addr_bits; ++i)
126        {
127            createNet("RDAddr_DFF_Out" + (String)i);
128
129            portConnect(rd_addr_dffs[i], "CK", "CK");
130            portConnect(rd_addr_dffs[i], "Q", "RDAddr_DFF_Out" + (String)i);
131        }
132
133        // Connect RAM
134        portConnect(ram, "In", "FlitIn");
135        for(unsigned int i = 0; i < number_addr_bits; ++i)
136        {
137            portConnect(ram, "WRAddr" + (String)i, "FlitIn", makeNetIndex(i));
138            portConnect(ram, "RDAddr" + (String)i, "RDAddr_DFF_Out" + (String)i);
139        }
140        portConnect(ram, "WE", "FlitIn", makeNetIndex(number_bits_per_flit-1));
141        portConnect(ram, "CK", "CK");
142        portConnect(ram, "Out", "FlitOut");
143
144        // Add area, power, event results
145        for(unsigned int i = 0; i < number_addr_bits; ++i)
146        {
147            addSubInstances(rd_addr_dffs[i], number_addr_bits);
148            addElectricalSubResults(rd_addr_dffs[i], number_addr_bits);
149        }
150        addSubInstances(ram, 1.0);
151        addElectricalSubResults(ram, 1.0);
152
153        getEventResult("WriteBuffer")->addSubResult(ram->getEventResult("Write"), ram_name, 1.0);
154
155        for(unsigned int i = 0; i < number_addr_bits; ++i)
156        {
157            getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("DFFD"), rd_addr_dff_names[i], number_addr_bits);
158            getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("DFFQ"), rd_addr_dff_names[i], number_addr_bits);
159            getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("CK"), rd_addr_dff_names[i], number_addr_bits);
160        }
161        getEventResult("ReadBuffer")->addSubResult(ram->getEventResult("Read"), ram_name, 1.0);
162
163        return;
164    }
165
166    void RouterInputPort::propagateTransitionInfo()
167    {
168        // Update probability and activity
169        unsigned int number_addr_bits = getGenProperties()->get("NumberAddressBits").toUInt();
170
171        vector<ElectricalModel*> rd_addr_dffs(number_addr_bits, NULL);
172        for(unsigned int i = 0; i < number_addr_bits; ++i)
173        {
174            rd_addr_dffs[i] = (ElectricalModel*)getSubInstance("RDAddr_DFF" + (String)i);
175            assignPortTransitionInfo(rd_addr_dffs[i], "D", TransitionInfo());
176            propagatePortTransitionInfo(rd_addr_dffs[i], "CK", "CK");
177            rd_addr_dffs[i]->use();
178        }
179
180        ElectricalModel* ram = (ElectricalModel*)getSubInstance("RAM");
181
182        // Setup default transition info
183        const String& current_event = getGenProperties()->get("UseModelEvent");
184        if(current_event != "Idle")
185        {
186            propagatePortTransitionInfo(ram, "In", "FlitIn");
187            propagatePortTransitionInfo(ram, "CK", "CK");
188            assignPortTransitionInfo(ram, "WE", TransitionInfo(0.0, 0.0, 1.0));
189            for(unsigned int i = 0; i < number_addr_bits; ++i)
190            {
191                assignPortTransitionInfo(ram, "WRAddr" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
192                assignPortTransitionInfo(ram, "RDAddr" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
193            }
194        }
195        ram->use();
196        // Set output probability
197        propagatePortTransitionInfo("FlitOut", ram, "Out");
198        return;
199    }
200} // namespace DSENT
201
202