2014-10-11 23:16:00 +02:00
|
|
|
/* Copyright (c) 2012 Massachusetts Institute of Technology
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2014-10-11 22:02:23 +02:00
|
|
|
#include "model/electrical/MultiplexerCrossbar.h"
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
#include "model/PortInfo.h"
|
|
|
|
#include "model/EventInfo.h"
|
|
|
|
#include "model/TransitionInfo.h"
|
|
|
|
#include "model/timing_graph/ElectricalNet.h"
|
|
|
|
#include "model/electrical/Multiplexer.h"
|
|
|
|
|
|
|
|
namespace DSENT
|
|
|
|
{
|
|
|
|
using std::ceil;
|
|
|
|
using std::vector;
|
|
|
|
|
|
|
|
MultiplexerCrossbar::MultiplexerCrossbar(const String& instance_name_, const TechModel* tech_model_)
|
|
|
|
: ElectricalModel(instance_name_, tech_model_)
|
|
|
|
{
|
|
|
|
initParameters();
|
|
|
|
initProperties();
|
|
|
|
}
|
|
|
|
|
|
|
|
MultiplexerCrossbar::~MultiplexerCrossbar()
|
|
|
|
{}
|
|
|
|
|
|
|
|
void MultiplexerCrossbar::initParameters()
|
|
|
|
{
|
|
|
|
addParameterName("NumberInputs");
|
|
|
|
addParameterName("NumberOutputs");
|
|
|
|
addParameterName("NumberBits");
|
|
|
|
addParameterName("BitDuplicate", "TRUE");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MultiplexerCrossbar::initProperties()
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MultiplexerCrossbar* MultiplexerCrossbar::clone() const
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MultiplexerCrossbar::constructModel()
|
|
|
|
{
|
|
|
|
// Get Parameters
|
|
|
|
unsigned int number_inputs = getParameter("NumberInputs").toUInt();
|
|
|
|
unsigned int number_outputs = getParameter("NumberOutputs").toUInt();
|
|
|
|
unsigned int number_bits = getParameter("NumberBits").toUInt();
|
|
|
|
bool bit_duplicate = getParameter("BitDuplicate").toBool();
|
|
|
|
|
|
|
|
ASSERT(number_inputs > 0, "[Error] " + getInstanceName() + " -> Number of inputs must be > 0!");
|
|
|
|
ASSERT(number_outputs > 0, "[Error] " + getInstanceName() + " -> Number of outputs must be > 0!");
|
|
|
|
ASSERT(number_bits > 0, "[Error] " + getInstanceName() + " -> Number of bits must be > 0!");
|
|
|
|
|
|
|
|
unsigned int number_selects = (unsigned int)ceil(log2((double)number_inputs));
|
|
|
|
getGenProperties()->set("NumberSelectsPerPort", number_selects);
|
|
|
|
|
|
|
|
// Construct electrical ports and nets
|
|
|
|
// Create input ports
|
|
|
|
for(unsigned int i = 0; i < number_inputs; ++i)
|
|
|
|
{
|
|
|
|
createInputPort("In" + (String)i, makeNetIndex(0, number_bits-1));
|
|
|
|
}
|
|
|
|
// Create select signals
|
|
|
|
for(unsigned int i = 0; i < number_outputs; ++i)
|
|
|
|
{
|
|
|
|
for(unsigned int j = 0; j < number_selects; ++j)
|
|
|
|
{
|
|
|
|
createInputPort(String::format("Sel%d_%d", i, j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Create output ports
|
|
|
|
for(unsigned int i = 0; i < number_outputs; ++i)
|
|
|
|
{
|
|
|
|
createOutputPort("Out" + (String)i, makeNetIndex(0, number_bits-1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create energy, power, and area results
|
|
|
|
addAreaResult(new AtomicResult("CrossbarWire"));
|
|
|
|
addAreaResult(new AtomicResult("CrossbarFill"));
|
|
|
|
createElectricalResults();
|
|
|
|
getEventInfo("Idle")->setStaticTransitionInfos();
|
|
|
|
createElectricalEventResult("Multicast0");
|
|
|
|
getEventInfo("Multicast0")->setStaticTransitionInfos();
|
|
|
|
for(unsigned int i = 1; i <= number_outputs; ++i)
|
|
|
|
{
|
|
|
|
createElectricalEventResult("Multicast" + (String)i);
|
|
|
|
EventInfo* event_info = getEventInfo("Multicast" + (String)i);
|
|
|
|
// Assuming that In0 is sending to Out0, Out1, ..., Outi
|
|
|
|
// and other input ports are static
|
|
|
|
for(unsigned int j = 1; j < number_inputs; ++j)
|
|
|
|
{
|
|
|
|
event_info->setStaticTransitionInfo("In" + (String)j);
|
|
|
|
}
|
|
|
|
for(unsigned int j = i; j < number_outputs; ++j)
|
|
|
|
{
|
|
|
|
for(unsigned int k = 0; k < number_selects; ++k)
|
|
|
|
{
|
|
|
|
event_info->setStaticTransitionInfo(String::format("Sel%d_%d", j, k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
createElectricalEventResult("Crossbar");
|
|
|
|
|
|
|
|
// Initiate multiplexers
|
|
|
|
vector<String> mux_names(number_outputs, "");
|
|
|
|
vector<Multiplexer*> muxs(number_outputs, NULL);
|
|
|
|
for(unsigned int i = 0; i < number_outputs; ++i)
|
|
|
|
{
|
|
|
|
mux_names[i] = "Mux" + (String)i;
|
|
|
|
muxs[i] = new Multiplexer(mux_names[i], getTechModel());
|
|
|
|
muxs[i]->setParameter("NumberInputs", number_inputs);
|
|
|
|
muxs[i]->setParameter("NumberBits", number_bits);
|
|
|
|
muxs[i]->setParameter("BitDuplicate", bit_duplicate);
|
|
|
|
muxs[i]->construct();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect inputs and outputs to multiplexers
|
|
|
|
for(unsigned int i = 0; i < number_outputs; ++i)
|
|
|
|
{
|
|
|
|
// Connect inputs
|
|
|
|
for(unsigned int j = 0; j < number_inputs; ++j)
|
|
|
|
{
|
|
|
|
portConnect(muxs[i], "In" + (String)j, "In" + (String)j, makeNetIndex(0, number_bits-1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect select signals
|
|
|
|
for(unsigned int j = 0; j < number_selects; ++j)
|
|
|
|
{
|
|
|
|
portConnect(muxs[i], "Sel" + (String)j, String::format("Sel%d_%d", i, j));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect outputs
|
|
|
|
portConnect(muxs[i], "Out", "Out" + (String)i, makeNetIndex(0, number_bits-1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add area, power, and event results for each mux
|
|
|
|
for(unsigned int i = 0; i < number_outputs; ++i)
|
|
|
|
{
|
|
|
|
addSubInstances(muxs[i], 1.0);
|
|
|
|
addElectricalSubResults(muxs[i], 1.0);
|
|
|
|
for(unsigned int j = 0; j <= number_outputs; ++j)
|
|
|
|
{
|
|
|
|
getEventResult("Multicast" + (String)j)->addSubResult(muxs[i]->getEventResult("Mux"), mux_names[i], 1.0);
|
|
|
|
}
|
|
|
|
getEventResult("Crossbar")->addSubResult(muxs[i]->getEventResult("Mux"), mux_names[i], 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Estimate wiring area
|
|
|
|
const String& crossbar_wire_layer = "Intermediate";
|
|
|
|
addElectricalWireSubResult(crossbar_wire_layer, getAreaResult("CrossbarWire"), "Self", 1.0);
|
|
|
|
double wire_width = getTechModel()->get("Wire->" + crossbar_wire_layer + "->MinWidth").toDouble();
|
|
|
|
double wire_spacing = getTechModel()->get("Wire->" + crossbar_wire_layer + "->MinSpacing").toDouble();
|
|
|
|
double wire_pitch = wire_width + wire_spacing;
|
|
|
|
double wire_area = (number_bits * number_inputs * wire_pitch) * (number_bits * number_outputs * wire_pitch);
|
|
|
|
getAreaResult("CrossbarWire")->setValue(wire_area);
|
|
|
|
|
|
|
|
// Add filler area
|
|
|
|
getAreaResult("Active")->addSubResult(getAreaResult("CrossbarFill"), "Self", 1.0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MultiplexerCrossbar::updateModel()
|
|
|
|
{
|
|
|
|
// Update all sub instances
|
|
|
|
Model::updateModel();
|
|
|
|
|
|
|
|
// Update filler area
|
|
|
|
// Total Active area = max(stdcell active area, wiring area);
|
|
|
|
double wire_area = getAreaResult("CrossbarWire")->calculateSum();
|
|
|
|
double active_area = getAreaResult("Active")->calculateSum();
|
|
|
|
double fill_area = 0.0;
|
|
|
|
if(active_area < wire_area)
|
|
|
|
{
|
|
|
|
fill_area = wire_area - active_area;
|
|
|
|
}
|
|
|
|
getAreaResult("CrossbarFill")->setValue(fill_area);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MultiplexerCrossbar::propagateTransitionInfo()
|
|
|
|
{
|
|
|
|
// The only thing can be updated are the input probabilities
|
|
|
|
const unsigned int number_inputs = getParameter("NumberInputs").toUInt();
|
|
|
|
const unsigned int number_outputs = getParameter("NumberOutputs").toUInt();
|
|
|
|
|
|
|
|
const unsigned int number_selects = getGenProperties()->get("NumberSelectsPerPort").toUInt();
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < number_outputs; ++i)
|
|
|
|
{
|
|
|
|
ElectricalModel* muxi = (ElectricalModel*)getSubInstance("Mux" + (String)i);
|
|
|
|
for(unsigned int j = 0; j < number_inputs; ++j)
|
|
|
|
{
|
|
|
|
propagatePortTransitionInfo(muxi, "In" + (String)j, "In" + (String)j);
|
|
|
|
}
|
|
|
|
for(unsigned int j = 0; j < number_selects; ++j)
|
|
|
|
{
|
|
|
|
propagatePortTransitionInfo(muxi, "Sel" + (String)j, String::format("Sel%d_%d", i, j));
|
|
|
|
}
|
|
|
|
muxi->use();
|
|
|
|
|
|
|
|
// Set output probability
|
|
|
|
propagatePortTransitionInfo("Out" + (String)i, muxi, "Out");
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace DSENT
|
|
|
|
|