110448Snilay@cs.wisc.edu/* Copyright (c) 2012 Massachusetts Institute of Technology 210448Snilay@cs.wisc.edu * 310448Snilay@cs.wisc.edu * Permission is hereby granted, free of charge, to any person obtaining a copy 410448Snilay@cs.wisc.edu * of this software and associated documentation files (the "Software"), to deal 510448Snilay@cs.wisc.edu * in the Software without restriction, including without limitation the rights 610448Snilay@cs.wisc.edu * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 710448Snilay@cs.wisc.edu * copies of the Software, and to permit persons to whom the Software is 810448Snilay@cs.wisc.edu * furnished to do so, subject to the following conditions: 910448Snilay@cs.wisc.edu * 1010448Snilay@cs.wisc.edu * The above copyright notice and this permission notice shall be included in 1110448Snilay@cs.wisc.edu * all copies or substantial portions of the Software. 1210448Snilay@cs.wisc.edu * 1310448Snilay@cs.wisc.edu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1410448Snilay@cs.wisc.edu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1510448Snilay@cs.wisc.edu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1610448Snilay@cs.wisc.edu * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1710448Snilay@cs.wisc.edu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1810448Snilay@cs.wisc.edu * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 1910448Snilay@cs.wisc.edu * THE SOFTWARE. 2010448Snilay@cs.wisc.edu */ 2110448Snilay@cs.wisc.edu 2210447Snilay@cs.wisc.edu#include "model/electrical/Decoder.h" 2310447Snilay@cs.wisc.edu 2410447Snilay@cs.wisc.edu#include <cmath> 2510447Snilay@cs.wisc.edu 2610447Snilay@cs.wisc.edu#include "model/PortInfo.h" 2710447Snilay@cs.wisc.edu#include "model/EventInfo.h" 2810447Snilay@cs.wisc.edu#include "model/TransitionInfo.h" 2910447Snilay@cs.wisc.edu#include "model/std_cells/StdCellLib.h" 3010447Snilay@cs.wisc.edu#include "model/std_cells/StdCell.h" 3110447Snilay@cs.wisc.edu 3210447Snilay@cs.wisc.edunamespace DSENT 3310447Snilay@cs.wisc.edu{ 3410447Snilay@cs.wisc.edu using std::ceil; 3510447Snilay@cs.wisc.edu 3610447Snilay@cs.wisc.edu Decoder::Decoder(const String& instance_name_, const TechModel* tech_model_) 3710447Snilay@cs.wisc.edu : ElectricalModel(instance_name_, tech_model_) 3810447Snilay@cs.wisc.edu { 3910447Snilay@cs.wisc.edu initParameters(); 4010447Snilay@cs.wisc.edu initProperties(); 4110447Snilay@cs.wisc.edu } 4210447Snilay@cs.wisc.edu 4310447Snilay@cs.wisc.edu Decoder::~Decoder() 4410447Snilay@cs.wisc.edu {} 4510447Snilay@cs.wisc.edu 4610447Snilay@cs.wisc.edu void Decoder::initParameters() 4710447Snilay@cs.wisc.edu { 4810447Snilay@cs.wisc.edu addParameterName("NumberOutputs"); 4910447Snilay@cs.wisc.edu } 5010447Snilay@cs.wisc.edu 5110447Snilay@cs.wisc.edu void Decoder::initProperties() 5210447Snilay@cs.wisc.edu { 5310447Snilay@cs.wisc.edu return; 5410447Snilay@cs.wisc.edu } 5510447Snilay@cs.wisc.edu 5610447Snilay@cs.wisc.edu Decoder* Decoder::clone() const 5710447Snilay@cs.wisc.edu { 5810447Snilay@cs.wisc.edu // TODO 5910447Snilay@cs.wisc.edu return NULL; 6010447Snilay@cs.wisc.edu } 6110447Snilay@cs.wisc.edu 6210447Snilay@cs.wisc.edu void Decoder::constructModel() 6310447Snilay@cs.wisc.edu { 6410447Snilay@cs.wisc.edu // Get parameters 6510447Snilay@cs.wisc.edu unsigned int number_outputs = getParameter("NumberOutputs").toUInt(); 6610447Snilay@cs.wisc.edu 6710447Snilay@cs.wisc.edu ASSERT(number_outputs > 0, "[Error] " + getInstanceName() + " -> Number of outputs must be > 0!"); 6810447Snilay@cs.wisc.edu 6910447Snilay@cs.wisc.edu unsigned int number_addr_bits = (unsigned int)ceil(log2(number_outputs)); 7010447Snilay@cs.wisc.edu 7110447Snilay@cs.wisc.edu // Create ports 7210447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_addr_bits; ++i) 7310447Snilay@cs.wisc.edu { 7410447Snilay@cs.wisc.edu createInputPort("Addr" + (String)i); 7510447Snilay@cs.wisc.edu } 7610447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_outputs; ++i) 7710447Snilay@cs.wisc.edu { 7810447Snilay@cs.wisc.edu createOutputPort("Out" + (String)i); 7910447Snilay@cs.wisc.edu } 8010447Snilay@cs.wisc.edu 8110447Snilay@cs.wisc.edu // Create energy, power, and area results 8210447Snilay@cs.wisc.edu createElectricalResults(); 8310447Snilay@cs.wisc.edu createElectricalEventResult("Decode"); 8410447Snilay@cs.wisc.edu Result* decode_event = getEventResult("Decode"); 8510447Snilay@cs.wisc.edu 8610447Snilay@cs.wisc.edu getEventInfo("Idle")->setStaticTransitionInfos(); 8710447Snilay@cs.wisc.edu 8810447Snilay@cs.wisc.edu if(number_addr_bits == 0) 8910447Snilay@cs.wisc.edu { 9010447Snilay@cs.wisc.edu // Do not need a decoder 9110447Snilay@cs.wisc.edu } 9210447Snilay@cs.wisc.edu else if(number_addr_bits == 1) 9310447Snilay@cs.wisc.edu { 9410447Snilay@cs.wisc.edu const String& inv0_name = "Inv0"; 9510447Snilay@cs.wisc.edu 9610447Snilay@cs.wisc.edu StdCell* inv0 = getTechModel()->getStdCellLib()->createStdCell("INV", inv0_name); 9710447Snilay@cs.wisc.edu inv0->construct(); 9810447Snilay@cs.wisc.edu 9910447Snilay@cs.wisc.edu // Connect inputs and outputs 10010447Snilay@cs.wisc.edu portConnect(inv0, "A", "Addr0"); 10110447Snilay@cs.wisc.edu portConnect(inv0, "Y", "Out0"); 10210447Snilay@cs.wisc.edu assign("Out1", "Addr0"); 10310447Snilay@cs.wisc.edu 10410447Snilay@cs.wisc.edu // Add area, power, and event results 10510447Snilay@cs.wisc.edu addSubInstances(inv0, 1.0); 10610447Snilay@cs.wisc.edu addElectricalSubResults(inv0, 1.0); 10710447Snilay@cs.wisc.edu decode_event->addSubResult(inv0->getEventResult("INV"), inv0_name, 1.0); 10810447Snilay@cs.wisc.edu } 10910447Snilay@cs.wisc.edu else 11010447Snilay@cs.wisc.edu { 11110447Snilay@cs.wisc.edu unsigned int number_addr_bits_0 = (unsigned int)ceil((double)number_addr_bits / 2.0); 11210447Snilay@cs.wisc.edu unsigned int number_addr_bits_1 = (unsigned int)floor((double)number_addr_bits / 2.0); 11310447Snilay@cs.wisc.edu 11410447Snilay@cs.wisc.edu unsigned int number_outputs_0 = (unsigned int)pow(2.0, number_addr_bits_0); 11510447Snilay@cs.wisc.edu unsigned int number_outputs_1 = (unsigned int)ceil((double)number_outputs / (double)number_outputs_0); 11610447Snilay@cs.wisc.edu 11710447Snilay@cs.wisc.edu const String& dec0_name = "Dec_way0"; 11810447Snilay@cs.wisc.edu const String& dec1_name = "Dec_way1"; 11910447Snilay@cs.wisc.edu vector<String> nand2_names(number_outputs, ""); 12010447Snilay@cs.wisc.edu vector<String> inv_names(number_outputs, ""); 12110447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_outputs; ++i) 12210447Snilay@cs.wisc.edu { 12310447Snilay@cs.wisc.edu nand2_names[i] = "NAND2_" + (String)i; 12410447Snilay@cs.wisc.edu inv_names[i] = "INV_" + (String)i; 12510447Snilay@cs.wisc.edu } 12610447Snilay@cs.wisc.edu 12710447Snilay@cs.wisc.edu Decoder* dec0 = new Decoder(dec0_name, getTechModel()); 12810447Snilay@cs.wisc.edu dec0->setParameter("NumberOutputs", number_outputs_0); 12910447Snilay@cs.wisc.edu dec0->construct(); 13010447Snilay@cs.wisc.edu 13110447Snilay@cs.wisc.edu Decoder* dec1 = new Decoder(dec1_name, getTechModel()); 13210447Snilay@cs.wisc.edu dec1->setParameter("NumberOutputs", number_outputs_1); 13310447Snilay@cs.wisc.edu dec1->construct(); 13410447Snilay@cs.wisc.edu 13510447Snilay@cs.wisc.edu vector<StdCell*> nand2s(number_outputs, NULL); 13610447Snilay@cs.wisc.edu vector<StdCell*> invs(number_outputs, NULL); 13710447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_outputs; ++i) 13810447Snilay@cs.wisc.edu { 13910447Snilay@cs.wisc.edu nand2s[i] = getTechModel()->getStdCellLib()->createStdCell("NAND2", nand2_names[i]); 14010447Snilay@cs.wisc.edu nand2s[i]->construct(); 14110447Snilay@cs.wisc.edu invs[i] = getTechModel()->getStdCellLib()->createStdCell("INV", inv_names[i]); 14210447Snilay@cs.wisc.edu invs[i]->construct(); 14310447Snilay@cs.wisc.edu } 14410447Snilay@cs.wisc.edu 14510447Snilay@cs.wisc.edu // Connect inputs and outputs 14610447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_addr_bits_0; ++i) 14710447Snilay@cs.wisc.edu { 14810447Snilay@cs.wisc.edu portConnect(dec0, "Addr" + (String)i, "Addr" + (String)i); 14910447Snilay@cs.wisc.edu } 15010447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_addr_bits_1; ++i) 15110447Snilay@cs.wisc.edu { 15210447Snilay@cs.wisc.edu portConnect(dec1, "Addr" + (String)i, "Addr" + (String)(i + number_addr_bits_0)); 15310447Snilay@cs.wisc.edu } 15410447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_outputs_0; ++i) 15510447Snilay@cs.wisc.edu { 15610447Snilay@cs.wisc.edu createNet("way0Out" + (String)i); 15710447Snilay@cs.wisc.edu portConnect(dec0, "Out" + (String)i, "way0Out" + (String)i); 15810447Snilay@cs.wisc.edu } 15910447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_outputs_1; ++i) 16010447Snilay@cs.wisc.edu { 16110447Snilay@cs.wisc.edu createNet("way1Out" + (String)i); 16210447Snilay@cs.wisc.edu portConnect(dec1, "Out" + (String)i, "way1Out" + (String)i); 16310447Snilay@cs.wisc.edu } 16410447Snilay@cs.wisc.edu 16510447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_outputs; ++i) 16610447Snilay@cs.wisc.edu { 16710447Snilay@cs.wisc.edu createNet("nand" + (String)i + "Out"); 16810447Snilay@cs.wisc.edu portConnect(nand2s[i], "A", "way0Out" + (String)(i%number_outputs_0)); 16910447Snilay@cs.wisc.edu portConnect(nand2s[i], "B", "way1Out" + (String)((unsigned int)floor(i/number_outputs_0))); 17010447Snilay@cs.wisc.edu portConnect(nand2s[i], "Y", "nand" + (String)i + "Out"); 17110447Snilay@cs.wisc.edu portConnect(invs[i], "A", "nand" + (String)i + "Out"); 17210447Snilay@cs.wisc.edu portConnect(invs[i], "Y", "Out" + (String)i); 17310447Snilay@cs.wisc.edu } 17410447Snilay@cs.wisc.edu 17510447Snilay@cs.wisc.edu // Add area, power, and event results 17610447Snilay@cs.wisc.edu addSubInstances(dec0, 1.0); 17710447Snilay@cs.wisc.edu addElectricalSubResults(dec0, 1.0); 17810447Snilay@cs.wisc.edu decode_event->addSubResult(dec0->getEventResult("Decode"), dec0_name, 1.0); 17910447Snilay@cs.wisc.edu addSubInstances(dec1, 1.0); 18010447Snilay@cs.wisc.edu addElectricalSubResults(dec1, 1.0); 18110447Snilay@cs.wisc.edu decode_event->addSubResult(dec1->getEventResult("Decode"), dec1_name, 1.0); 18210447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_outputs; ++i) 18310447Snilay@cs.wisc.edu { 18410447Snilay@cs.wisc.edu addSubInstances(nand2s[i], 1.0); 18510447Snilay@cs.wisc.edu addElectricalSubResults(nand2s[i], 1.0); 18610447Snilay@cs.wisc.edu decode_event->addSubResult(nand2s[i]->getEventResult("NAND2"), nand2_names[i], 1.0); 18710447Snilay@cs.wisc.edu 18810447Snilay@cs.wisc.edu addSubInstances(invs[i], 1.0); 18910447Snilay@cs.wisc.edu addElectricalSubResults(invs[i], 1.0); 19010447Snilay@cs.wisc.edu decode_event->addSubResult(invs[i]->getEventResult("INV"), inv_names[i], 1.0); 19110447Snilay@cs.wisc.edu } 19210447Snilay@cs.wisc.edu } 19310447Snilay@cs.wisc.edu return; 19410447Snilay@cs.wisc.edu } 19510447Snilay@cs.wisc.edu 19610447Snilay@cs.wisc.edu void Decoder::propagateTransitionInfo() 19710447Snilay@cs.wisc.edu { 19810447Snilay@cs.wisc.edu // The only thing can be updated are the input probabilities 19910447Snilay@cs.wisc.edu unsigned int number_outputs = getParameter("NumberOutputs").toUInt(); 20010447Snilay@cs.wisc.edu 20110447Snilay@cs.wisc.edu unsigned int number_addr_bits = (unsigned int)ceil(log2(number_outputs)); 20210447Snilay@cs.wisc.edu 20310447Snilay@cs.wisc.edu if(number_addr_bits == 0) 20410447Snilay@cs.wisc.edu { 20510447Snilay@cs.wisc.edu // Do not need a decoder 20610447Snilay@cs.wisc.edu } 20710447Snilay@cs.wisc.edu else if(number_addr_bits == 1) 20810447Snilay@cs.wisc.edu { 20910447Snilay@cs.wisc.edu ElectricalModel* inv0 = (ElectricalModel*)getSubInstance("Inv0"); 21010447Snilay@cs.wisc.edu propagatePortTransitionInfo(inv0, "A", "Addr0"); 21110447Snilay@cs.wisc.edu inv0->use(); 21210447Snilay@cs.wisc.edu 21310447Snilay@cs.wisc.edu // Since # addr bits is 1, the output 0 is directly connected 21410447Snilay@cs.wisc.edu propagatePortTransitionInfo("Out0", inv0, "Y"); 21510447Snilay@cs.wisc.edu propagatePortTransitionInfo("Out1", "Addr0"); 21610447Snilay@cs.wisc.edu } 21710447Snilay@cs.wisc.edu else 21810447Snilay@cs.wisc.edu { 21910447Snilay@cs.wisc.edu unsigned int number_addr_bits_0 = (unsigned int)ceil((double)number_addr_bits / 2.0); 22010447Snilay@cs.wisc.edu unsigned int number_addr_bits_1 = (unsigned int)floor((double)number_addr_bits / 2.0); 22110447Snilay@cs.wisc.edu 22210447Snilay@cs.wisc.edu unsigned int number_outputs_0 = (unsigned int)pow(2.0, number_addr_bits_0); 22310447Snilay@cs.wisc.edu 22410447Snilay@cs.wisc.edu // Update decoders with probabilities 22510447Snilay@cs.wisc.edu ElectricalModel* dec0 = (ElectricalModel*)getSubInstance("Dec_way0"); 22610447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_addr_bits_0; ++i) 22710447Snilay@cs.wisc.edu { 22810447Snilay@cs.wisc.edu propagatePortTransitionInfo(dec0, "Addr" + (String)i, "Addr" + (String)i); 22910447Snilay@cs.wisc.edu } 23010447Snilay@cs.wisc.edu dec0->use(); 23110447Snilay@cs.wisc.edu ElectricalModel* dec1 = (ElectricalModel*)getSubInstance("Dec_way1"); 23210447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_addr_bits_1; ++i) 23310447Snilay@cs.wisc.edu { 23410447Snilay@cs.wisc.edu propagatePortTransitionInfo(dec1, "Addr" + (String)i, "Addr" + (String)(i + number_addr_bits_0)); 23510447Snilay@cs.wisc.edu } 23610447Snilay@cs.wisc.edu dec1->use(); 23710447Snilay@cs.wisc.edu 23810447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_outputs; ++i) 23910447Snilay@cs.wisc.edu { 24010447Snilay@cs.wisc.edu ElectricalModel* nand2 = (ElectricalModel*)getSubInstance("NAND2_" + (String)i); 24110447Snilay@cs.wisc.edu propagatePortTransitionInfo(nand2, "A", dec0, "Out" + (String)(i%number_outputs_0)); 24210447Snilay@cs.wisc.edu propagatePortTransitionInfo(nand2, "B", dec1, "Out" + (String)((unsigned int)floor(i/number_outputs_0))); 24310447Snilay@cs.wisc.edu nand2->use(); 24410447Snilay@cs.wisc.edu 24510447Snilay@cs.wisc.edu ElectricalModel* inv = (ElectricalModel*)getSubInstance("INV_" + (String)i); 24610447Snilay@cs.wisc.edu propagatePortTransitionInfo(inv, "A", nand2, "Y"); 24710447Snilay@cs.wisc.edu inv->use(); 24810447Snilay@cs.wisc.edu 24910447Snilay@cs.wisc.edu propagatePortTransitionInfo("Out" + (String)i, inv, "Y"); 25010447Snilay@cs.wisc.edu } 25110447Snilay@cs.wisc.edu } 25210447Snilay@cs.wisc.edu return; 25310447Snilay@cs.wisc.edu } 25410447Snilay@cs.wisc.edu 25510447Snilay@cs.wisc.edu} // namespace DSENT 25610447Snilay@cs.wisc.edu 257