From e8ed7b1d1b5bef31e9874f679a5797c2e00d06f1 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Sat, 11 Oct 2014 15:02:23 -0500 Subject: 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. --- ext/dsent/model/electrical/BarrelShifter.cc | 241 ++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 ext/dsent/model/electrical/BarrelShifter.cc (limited to 'ext/dsent/model/electrical/BarrelShifter.cc') diff --git a/ext/dsent/model/electrical/BarrelShifter.cc b/ext/dsent/model/electrical/BarrelShifter.cc new file mode 100644 index 000000000..b951fc566 --- /dev/null +++ b/ext/dsent/model/electrical/BarrelShifter.cc @@ -0,0 +1,241 @@ +#include "model/electrical/BarrelShifter.h" +#include "model/electrical/Multiplexer.h" + +#include + +#include "model/PortInfo.h" +#include "model/TransitionInfo.h" +#include "model/EventInfo.h" +#include "model/timing_graph/ElectricalDriverMultiplier.h" +#include "model/timing_graph/ElectricalNet.h" +#include "model/std_cells/StdCell.h" +#include "model/std_cells/StdCellLib.h" + +namespace DSENT +{ + BarrelShifter::BarrelShifter(const String& instance_name_, const TechModel* tech_model_) + : ElectricalModel(instance_name_, tech_model_) + { + initParameters(); + initProperties(); + } + + BarrelShifter::~BarrelShifter() + {} + + void BarrelShifter::initParameters() + { + addParameterName("NumberBits"); + addParameterName("ShiftIndexMin"); + addParameterName("ShiftIndexMax"); + addParameterName("BitDuplicate", "TRUE"); + return; + } + + void BarrelShifter::initProperties() + { + return; + } + + BarrelShifter* BarrelShifter::clone() const + { + return NULL; + } + + void BarrelShifter::constructModel() + { + // Get parameters + unsigned int number_bits = getParameter("NumberBits"); + unsigned int number_shift_bits = (unsigned int)ceil(log2((double) number_bits)); + unsigned int shift_index_min = getParameter("ShiftIndexMin"); + unsigned int shift_index_max = getParameter("ShiftIndexMax"); + bool bit_duplicate = (bool) getParameter("BitDuplicate"); + + ASSERT(number_bits > 0, "[Error] " + getInstanceName() + " -> Number of bits must be > 0!"); + // No need to check these if there arent any shifts + if (number_shift_bits > 0) + { + ASSERT(shift_index_min <= number_shift_bits, + "[Error] " + getInstanceName() + " -> Min shift index must be >= 0 and <= " + + "the total number of shift bits!"); + ASSERT(shift_index_max >= shift_index_min && shift_index_max <= number_shift_bits, + "[Error] " + getInstanceName() + " -> Max shift index must be >= minimum shift index and <= " + + "the total number of shift bits!"); + } + + //Construct electrical ports + //Create each input port + createInputPort( "In", makeNetIndex(0, number_bits-1)); + //Create output + createOutputPort( "Out", makeNetIndex(0, number_bits-1)); + + //Create shift ports (which only exists if there is something to shift) + if (shift_index_min != number_shift_bits) + for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) + createInputPort( "Shift" + (String) i); + + //Create energy, power, and area results + createElectricalResults(); + createElectricalEventResult("BarrelShift"); + //Set conditions during idle event + getEventInfo("Idle")->setStaticTransitionInfos(); + + //If the input is only 1-bit, connect input to output and be done + if (number_shift_bits == 0 || (shift_index_min == number_shift_bits)) + assign("Out", "In"); + else + { + for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) + { + //Create internally buffered shift select signals + createNet("Shift_b" + (String) i); + createNet("Shift_i" + (String) i); + } + + // Create shift and shifted signals + for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) + { + unsigned int current_shifts = (unsigned int)pow(2, i); + const String& n = (String) current_shifts; + //Instantiate and connect intermediate nets. In a barrel-shifter, the nets do + //all the "shifting" and the muxes just select which to take + createNet("R_" + n, makeNetIndex(0, number_bits-1)); //wire R_n[number_bits-1:0] + createNet("RS_" + n, makeNetIndex(0, number_bits-1)); //wire RS_n[number_bits-1:0] + + //Implements the shifts + //assign RS_n[number_bits-1:number_bits-current_shifts] = R_n[current_shifts-1:0]; + assign("RS_" + n, makeNetIndex(number_bits-current_shifts, number_bits-1), + "R_" + n, makeNetIndex(0, current_shifts-1)); + //assign RS_n[number_bits-current_shifts-1:0] = R_n[current_shifts:number_bits-1]; + assign("RS_" + n, makeNetIndex(0, number_bits-current_shifts-1), + "R_" + n, makeNetIndex(current_shifts, number_bits-1)); + } + + const String& n_max = (String) pow(2, shift_index_max+1); + const String& n_min = (String) pow(2, shift_index_min); + // Create the R_(max) net + createNet("R_" + n_max, makeNetIndex(0, number_bits-1)); + // Set R_1 to be the input + assign("R_" + n_min, "In"); + // Set R_(max) to be the output + assign("Out", "R_" + n_max, makeNetIndex(0, number_bits-1)); + + for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) + { + unsigned int current_shifts = (unsigned int)pow(2, i); + const String& n = (String) current_shifts; + const String& n_next = (String) (current_shifts * 2); + + const String& buf_inv_0_name = "ShiftBufInv0_" + (String) n; + const String& buf_inv_1_name = "ShiftBufInv1_" + (String) n; + // Create shift buffer inverters + StdCell* buf_inv_0 = getTechModel()->getStdCellLib()->createStdCell("INV", buf_inv_0_name); + buf_inv_0->construct(); + StdCell* buf_inv_1 = getTechModel()->getStdCellLib()->createStdCell("INV", buf_inv_1_name); + buf_inv_1->construct(); + + // Connect up shift buffer inverters + portConnect(buf_inv_0, "A", "Shift" + (String) i); + portConnect(buf_inv_0, "Y", "Shift_b" + (String) i); + portConnect(buf_inv_1, "A", "Shift_b" + (String) i); + portConnect(buf_inv_1, "Y", "Shift_i" + (String) i); + + // Add area, power, and event results for inverters + addSubInstances(buf_inv_0, 1.0); + addSubInstances(buf_inv_1, 1.0); + addElectricalSubResults(buf_inv_0, 1.0); + addElectricalSubResults(buf_inv_1, 1.0); + getEventResult("BarrelShift")->addSubResult(buf_inv_0->getEventResult("INV"), buf_inv_0_name, 1.0); + getEventResult("BarrelShift")->addSubResult(buf_inv_1->getEventResult("INV"), buf_inv_1_name, 1.0); + + //Instantiate 2:1 multiplexers, one for each shift bit. + const String& mux_name = "SRL" + n; + Multiplexer* mux = new Multiplexer(mux_name, getTechModel()); + mux->setParameter("NumberInputs", 2); + mux->setParameter("NumberBits", number_bits); + mux->setParameter("BitDuplicate", bit_duplicate); + mux->construct(); + + //Just have to connect the In0 and In1 inputs of the mux to the + //non-shifted and shifted intermediate signals, respectively. + portConnect(mux, "In0", "R_" + n); + portConnect(mux, "In1", "RS_" + n); + //Selector connects to the shift signal for that index + portConnect(mux, "Sel0", "Shift_i" + (String) i); + //Connect mux output + portConnect(mux, "Out", "R_" + n_next); + + //Add area, power, and event results for each mux + addSubInstances(mux, 1.0); + addElectricalSubResults(mux, 1.0); + getEventResult("BarrelShift")->addSubResult(mux->getEventResult("Mux"), mux_name, 1.0); + } + } + return; + } + + void BarrelShifter::propagateTransitionInfo() + { + // The only thing can be updated are the input probabilities...so we will update them + unsigned int number_bits = (unsigned int) getParameter("NumberBits"); + unsigned int number_shift_bits = (unsigned int) ceil(log2((double) number_bits)); + unsigned int shift_index_min = getParameter("ShiftIndexMin"); + unsigned int shift_index_max = getParameter("ShiftIndexMax"); + + // Keep track of the multiplexer of the last stage + ElectricalModel* last_mux = NULL; + // We only need to update stuff if we are not shifting by exact multiples + // of number of input bits + if (shift_index_min < number_shift_bits) + { + for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) + { + unsigned int current_shifts = (unsigned int)pow(2, i); + String n = (String) current_shifts; + + // Set the + const String& buf_inv_0_name = "ShiftBufInv0_" + (String) n; + const String& buf_inv_1_name = "ShiftBufInv1_" + (String) n; + const String& mux_name = "SRL" + n; + + // Set the transition infos for the inverter buffers + ElectricalModel* buf_inv_0 = (ElectricalModel*) getSubInstance(buf_inv_0_name); + propagatePortTransitionInfo(buf_inv_0, "A", "Shift" + (String) i); + buf_inv_0->use(); + + ElectricalModel* buf_inv_1 = (ElectricalModel*) getSubInstance(buf_inv_1_name); + propagatePortTransitionInfo(buf_inv_1, "A", buf_inv_0, "Y"); + buf_inv_1->use(); + + // Set the transition infos for the shift multiplexers + ElectricalModel* mux = (ElectricalModel*) getSubInstance(mux_name); + propagatePortTransitionInfo(mux, "Sel0", buf_inv_1, "Y"); + if (last_mux == NULL) + { + propagatePortTransitionInfo(mux, "In0", "In"); + propagatePortTransitionInfo(mux, "In1", "In"); + } + else + { + propagatePortTransitionInfo(mux, "In0", last_mux, "Out"); + propagatePortTransitionInfo(mux, "In1", last_mux, "Out"); + } + mux->use(); + + // Set this to be the last mux visted + last_mux = mux; + } + } + + // If there isn't anything to shift + if (last_mux == NULL) + propagatePortTransitionInfo("Out", "In"); + // Take the transition info of the last mux + else + propagatePortTransitionInfo("Out", last_mux, "Out"); + + return; + } + +} // namespace DSENT + -- cgit v1.2.3