diff options
author | Nilay Vaish <nilay@cs.wisc.edu> | 2014-10-11 15:02:23 -0500 |
---|---|---|
committer | Nilay Vaish <nilay@cs.wisc.edu> | 2014-10-11 15:02:23 -0500 |
commit | e8ed7b1d1b5bef31e9874f679a5797c2e00d06f1 (patch) | |
tree | 421c9c50377aa664958685914f5504c4c019e21f /ext/dsent/model/electrical/OR.cc | |
parent | a098fad174d8559037602b248b8e6f7f46bfebbb (diff) | |
download | gem5-e8ed7b1d1b5bef31e9874f679a5797c2e00d06f1.tar.xz |
ext: add the source code for DSENT
This patch adds a tool called DSENT to the ext/ directory. DSENT
is a tool that models power and area for on-chip networks. The next
patch adds a script for using the tool.
Diffstat (limited to 'ext/dsent/model/electrical/OR.cc')
-rw-r--r-- | ext/dsent/model/electrical/OR.cc | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/ext/dsent/model/electrical/OR.cc b/ext/dsent/model/electrical/OR.cc new file mode 100644 index 000000000..d948ff086 --- /dev/null +++ b/ext/dsent/model/electrical/OR.cc @@ -0,0 +1,239 @@ +#include "model/electrical/OR.h" + +#include <cmath> + +#include "model/PortInfo.h" +#include "model/TransitionInfo.h" +#include "model/EventInfo.h" +#include "model/std_cells/StdCellLib.h" +#include "model/std_cells/StdCell.h" +#include "model/timing_graph/ElectricalNet.h" + +namespace DSENT +{ + using std::ceil; + using std::floor; + + OR::OR(const String& instance_name_, const TechModel* tech_model_) + : ElectricalModel(instance_name_, tech_model_) + { + initParameters(); + initProperties(); + } + + OR::~OR() + {} + + void OR::initParameters() + { + addParameterName("NumberInputs"); + addParameterName("NumberBits"); + addParameterName("BitDuplicate", "TRUE"); + return; + } + + void OR::initProperties() + { + return; + } + + OR* OR::clone() const + { + // TODO + return NULL; + } + + void OR::constructModel() + { + // Get parameter + unsigned int number_inputs = getParameter("NumberInputs").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_bits > 0, "[Error] " + getInstanceName() + + " -> Number of bits must be > 0!"); + + + // Init ports + for(unsigned int i = 0; i < number_inputs; ++i) + { + createInputPort("In" + (String)i, makeNetIndex(0, number_bits-1)); + } + createOutputPort("Out", makeNetIndex(0, number_bits-1)); + + // Number of inputs on the 0 side + unsigned int or0_number_inputs = (unsigned int)ceil((double)number_inputs / 2.0); + // Number of inputs on the 1 side + unsigned int or1_number_inputs = (unsigned int)floor((double)number_inputs / 2.0); + + // Create area, power, and event results + createElectricalResults(); + createElectricalEventResult("OR"); + + getEventInfo("Idle")->setStaticTransitionInfos(); + + //Depending on whether we want to create a 1-bit instance and have it multiplied + //up by number of bits or actually instantiate number_bits of 1-bit instances. + //Recursively instantiates smaller ors + if(bit_duplicate || number_bits == 1) + { + // If it is just a 1-input or, just connect output to input + if(number_inputs == 1) + { + assign("Out", "In0"); + } + else + { + // If it is more than 1 input, instantiate two sub ors (OR_way0 and OR_way1) + // and create a final OR2 to OR them + const String& or0_name = "OR_way0"; + const String& or1_name = "OR_way1"; + const String& orf_name = "OR2_i" + (String)number_inputs; + + OR* or0 = new OR(or0_name, getTechModel()); + or0->setParameter("NumberInputs", or0_number_inputs); + or0->setParameter("NumberBits", 1); + or0->setParameter("BitDuplicate", "TRUE"); + or0->construct(); + + OR* or1 = new OR(or1_name, getTechModel()); + or1->setParameter("NumberInputs", or1_number_inputs); + or1->setParameter("NumberBits", 1); + or1->setParameter("BitDuplicate", "TRUE"); + or1->construct(); + + StdCell* orf = getTechModel()->getStdCellLib()->createStdCell("OR2", orf_name); + orf->construct(); + + // Create outputs of way0 and way1 ors with final or + createNet("way0_Out"); + createNet("way1_Out"); + portConnect(or0, "Out", "way0_Out"); + portConnect(or1, "Out", "way1_Out"); + portConnect(orf, "A", "way0_Out"); + portConnect(orf, "B", "way1_Out"); + + // Connect inputs to the sub ors. + for(unsigned int i = 0; i < or0_number_inputs; ++i) + { + createNet("way0_In" + (String)i); + portConnect(or0, "In" + (String)i, "way0_In" + (String)i); + assignVirtualFanin("way0_In" + (String)i, "In" + (String)i); + } + for(unsigned int i = 0; i < or1_number_inputs; ++i) + { + createNet("way1_In" + (String)i); + portConnect(or1, "In" + (String)i, "way1_In" + (String)i); + assignVirtualFanin("way1_In" + (String)i, "In" + (String)(i + or0_number_inputs)); + } + + // Connect outputs + createNet("OR2_Out"); + portConnect(orf, "Y", "OR2_Out"); + assignVirtualFanout("Out", "OR2_Out"); + + addSubInstances(or0, number_bits); + addElectricalSubResults(or0, number_bits); + addSubInstances(or1, number_bits); + addElectricalSubResults(or1, number_bits); + addSubInstances(orf, number_bits); + addElectricalSubResults(orf, number_bits); + + Result* or_event = getEventResult("OR"); + or_event->addSubResult(or0->getEventResult("OR"), or0_name, number_bits); + or_event->addSubResult(or1->getEventResult("OR"), or1_name, number_bits); + or_event->addSubResult(orf->getEventResult("OR2"), orf_name, number_bits); + + } + } + else + { + // Init a bunch of 1-bit ors + Result* or_event = getEventResult("OR"); + for(unsigned int n = 0; n < number_bits; ++n) + { + const String& or_name = "OR_bit" + (String)n; + + OR* ors = new OR(or_name, getTechModel()); + ors->setParameter("NumberInputs", number_inputs); + ors->setParameter("NumberBits", 1); + ors->setParameter("BitDuplicate", "TRUE"); + ors->construct(); + + for(unsigned int i = 0; i < number_inputs; ++i) + { + portConnect(ors, "In" + (String)i, "In" + (String)i, makeNetIndex(n)); + } + portConnect(ors, "Out", "Out", makeNetIndex(n)); + + addSubInstances(ors, 1.0); + addElectricalSubResults(ors, 1.0); + or_event->addSubResult(ors->getEventResult("OR"), or_name, 1.0); + } + } + return; + } + + void OR::propagateTransitionInfo() + { + // Get parameters + unsigned int number_inputs = getParameter("NumberInputs").toUInt(); + unsigned int number_bits = getParameter("NumberBits").toUInt(); + bool bit_duplicate = getParameter("BitDuplicate").toBool(); + + // Number of inputs on 0 side + unsigned int or0_number_inputs = (unsigned int)ceil((double)number_inputs / 2.0); + unsigned int or1_number_inputs = (unsigned int)floor((double)number_inputs / 2.0); + + if(bit_duplicate || number_bits == 1) + { + if(number_inputs == 1) + { + propagatePortTransitionInfo("Out", "In0"); + } + else + { + ElectricalModel* or0 = (ElectricalModel*)getSubInstance("OR_way0"); + for(unsigned int i = 0; i < or0_number_inputs; ++i) + { + propagatePortTransitionInfo(or0, "In" + (String)i, "In" + (String)i); + } + or0->use(); + + ElectricalModel* or1 = (ElectricalModel*)getSubInstance("OR_way1"); + for(unsigned int i = 0; i < or1_number_inputs; ++i) + { + propagatePortTransitionInfo(or1, "In" + (String)i, "In" + (String)i); + } + or1->use(); + + ElectricalModel* orf = (ElectricalModel*)getSubInstance("OR2_i" + (String)number_inputs); + propagatePortTransitionInfo(orf, "A", or0, "Out"); + propagatePortTransitionInfo(orf, "B", or1, "Out"); + orf->use(); + + // Set output probability + propagatePortTransitionInfo("Out", orf, "Y"); + } + } + else + { + for(unsigned int n = 0; n < number_bits; ++n) + { + ElectricalModel* or_bit = (ElectricalModel*)getSubInstance("OR_bit" + (String)n); + for(unsigned int i = 0; i < number_inputs; ++i) + { + propagatePortTransitionInfo(or_bit, "In" + (String)i, "In" + (String)i); + } + or_bit->use(); + } + + ElectricalModel* or_bit = (ElectricalModel*)getSubInstance("OR_bit0"); + propagatePortTransitionInfo("Out", or_bit, "Out"); + } + return; + } +} // namespace DSENT + |