diff options
Diffstat (limited to 'src/intersim2/.svn/pristine/12')
3 files changed, 1340 insertions, 0 deletions
diff --git a/src/intersim2/.svn/pristine/12/125686d82b0fb03524a1bd1dc36fd9172006e780.svn-base b/src/intersim2/.svn/pristine/12/125686d82b0fb03524a1bd1dc36fd9172006e780.svn-base new file mode 100644 index 0000000..f7e44a8 --- /dev/null +++ b/src/intersim2/.svn/pristine/12/125686d82b0fb03524a1bd1dc36fd9172006e780.svn-base @@ -0,0 +1,673 @@ +// $Id$ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior University + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "booksim.hpp" +#include <string> +#include <sstream> +#include <iostream> +#include <cstdlib> + +#include "chaos_router.hpp" +#include "random_utils.hpp" +#include "globals.hpp" + +ChaosRouter::ChaosRouter( const Configuration& config, + Module *parent, const string & name, int id, + int inputs, int outputs ) + : Router( config, + parent, name, + id, + inputs, outputs ) +{ + int i; + + if ( inputs != outputs ) { + Error( "Chaos router must have equal number of input and output ports" ); + } + + _buffer_size = config.GetInt( "vc_buf_size" ); + assert(_buffer_size >= config.GetInt( "const_flits_per_packet" )); + + _multi_queue_size = config.GetInt( "multi_queue_size" ); + + _cur_channel = 0; + _read_stall = 0; + + // Routing + + string rf = config.GetStr("routing_function") + "_" + config.GetStr("topology"); + map<string, tRoutingFunction>::iterator rf_iter = gRoutingFunctionMap.find(rf); + if(rf_iter == gRoutingFunctionMap.end()) { + Error("Invalid routing function: " + rf); + } + _rf = rf_iter->second; + + _input_route.resize(_inputs); + + for ( i = 0; i < _inputs; ++i ) { + _input_route[i] = new OutputSet( ); + } + + _mq_route.resize(_multi_queue_size); + + for ( i = 0; i < _multi_queue_size; ++i ) { + _mq_route[i] = new OutputSet( ); + } + + // Alloc pipelines (to simulate processing/transmission delays) + + _crossbar_pipe = + new PipelineFIFO<Flit>( this, "crossbar_pipeline", _outputs, + _crossbar_delay ); + + // Input and output queues + + _input_frame.resize(_inputs); + _output_frame.resize(_outputs); + _multi_queue.resize(_multi_queue_size); + + _credit_queue.resize(_inputs); + + _input_state.resize(_inputs, empty); + _input_output_match.resize(_inputs, -1); + _input_mq_match.resize(_inputs, -1); + + _output_matched.resize(_outputs, false); + _next_queue_cnt.resize(_outputs, 0); + + _multi_match.resize(_multi_queue_size, -1); + _mq_age.resize(_multi_queue_size); + _mq_matched.resize(_multi_queue_size, false); + _multi_state.resize(_multi_queue_size, empty); + + for ( i = 0; i < _multi_queue_size; ++i ) { + _multi_state[i] = empty; + _multi_match[i] = -1; + _mq_matched[i] = false; + } +} + +ChaosRouter::~ChaosRouter( ) +{ + int i; + + delete _crossbar_pipe; + + for ( i = 0; i < _inputs; ++i ) { + delete _input_route[i]; + } + + for ( i = 0; i < _multi_queue_size; ++i ) { + delete _mq_route[i]; + } +} + +void ChaosRouter::ReadInputs( ) +{ + Flit *f; + Credit *c; + + for ( int input = 0; input < _inputs; ++input ) { + f = _input_channels[input]->Receive(); + + if ( f ) { + _input_frame[input].push( f ); + + if ( f->watch ) { + *gWatchOut << GetSimTime() << " | " << FullName() << " | " + << "Flit arriving at " << FullName() + << " on channel " << input << endl + << *f; + } + + switch( _input_state[input] ) { + case empty: + if ( f->head ) { + if ( f->tail ) { + _input_state[input] = full; + } else { + _input_state[input] = filling; + } + _rf( this, f, input, _input_route[input], false ); + } else { + cout << *f; + Error( "Empty buffer received non-head flit!" ); + } + break; + + case filling: + if ( f->tail ) { + _input_state[input] = full; + } else if ( f->head ) { + Error( "Input buffer received another head before previous tail!" ); + } + break; + + case full: + Error( "Received flit while full!" ); + break; + + case leaving: + if ( f->head ) { + _input_state[input] = shared; + + if ( f->tail ) { + Error( "Received single-flit packet in leaving state!" ); + } + } else { + cout << *f; + Error( "Received non-head flit while packet leaving!" ); + } + break; + + case cut_through: + if ( f->tail ) { + _input_state[input] = leaving; + } + if ( f->head ) { + cout << *f; + Error( "Received head flit in cut through buffer!" ); + } + break; + + case shared: + if ( f->head ) { + Error( "Shared buffer received another head!" ); + } else if ( f->tail ) { + cout << "Input " << input << endl; + cout << *f; + Error( "Shared buffer received another tail!" ); + } + break; + } + } + } + + // Process incoming credits + + for ( int output = 0; output < _outputs; ++output ) { + c = _output_credits[output]->Receive(); + + if ( c ) { + _next_queue_cnt[output]--; + + if ( _next_queue_cnt[output] < 0 ) { + Error( "Next queue count fell below zero!" ); + } + + c->Free(); + } + } +} + +void ChaosRouter::_InternalStep( ) +{ + _NextInterestingChannel( ); + _OutputAdvance( ); + + _crossbar_pipe->Advance( ); +} + +void ChaosRouter::WriteOutputs( ) +{ + _SendFlits( ); + _SendCredits( ); +} + +bool ChaosRouter::_IsInjectionChan( int chan ) const +{ + return ( chan == _inputs - 1 ); +} + +bool ChaosRouter::_IsEjectionChan( int chan ) const +{ + return ( chan == _outputs - 1 ); +} + +bool ChaosRouter::_InputReady( int input ) const +{ + bool ready = false; + + if ( ( _input_state[input] == filling ) || + ( _input_state[input] == full ) ) { + ready = true; + } + + return ready; +} + +bool ChaosRouter::_OutputFull( int out ) const +{ + return ( _output_frame[out].size( ) >= (size_t)_buffer_size ); +} + +bool ChaosRouter::_OutputAvail( int out ) const +{ + return ( ( !_output_matched[out] ) && ( _output_frame[out].empty( ) ) ); + //&& ( _next_queue_cnt[out] == 0 ) ); + //return ( ( !_output_matched[out] ) && !_OutputFull( out ) ); +} + +bool ChaosRouter::_MultiQueueFull( int mq ) const +{ + return ( _multi_queue[mq].size( ) >= (size_t)_buffer_size ); +} + +int ChaosRouter::_InputForOutput( int output ) const +{ + // return an input that prefers this output + + int input; + int offset = RandomInt( _inputs - 1 ); + bool match = false; + + for ( int i = 0; ( i < _inputs ) && ( !match ); ++i ) { + input = ( i + offset ) % _inputs; + + if ( _InputReady( input ) && + ( ! _input_route[input]->OutputEmpty( output ) ) ) { + match = true; + } + } + + return match ? input : -1; +} + +int ChaosRouter::_MultiQueueForOutput( int output ) const +{ + // return oldest multi queue that prefers the output, + // or if none prefer and the multi queue is full, + // return a random entry + + int mq_oldest = -1; + int mq_age; + + int m, r; + + bool isfull = true; + + for ( int i = 0; i < _multi_queue_size; ++i ) { + if ( ( _multi_match[i] == -1 ) && + ( ( _multi_state[i] == full ) || + ( _multi_state[i] == filling ) ) ) { + + if ( ( !_mq_route[i]->OutputEmpty( output ) ) && + ( ( mq_oldest == -1 ) || ( _mq_age[i] > mq_age ) ) ) { + mq_oldest = i; + mq_age = _mq_age[i]; + } + } + + // deroute only if all queues contain head flits ... + + if ( ( _multi_state[i] != full ) && + ( _multi_state[i] != filling ) && + ( _multi_state[i] != shared ) ) { + isfull = false; + } + } + + // Don't deroute MQs to the ejection channel + if ( ( mq_oldest == -1 ) && isfull && + ( !_IsEjectionChan( output ) ) ) { + r = RandomInt( _multi_queue_size - 1 ); + + // Find first routable multi-queue + for ( int i = 0; i < _multi_queue_size; ++i ) { + m = ( i + r ) % _multi_queue_size; + if ( ( _multi_state[m] == filling ) || + ( _multi_state[m] == full ) ) { + mq_oldest = m; + //cout << "DEROUTING at " << FullName() << endl; + break; + } + } + + if ( mq_oldest == -1 ) { + cout << "write stall" << endl; + } + } + + return mq_oldest; +} + +int ChaosRouter::_FindAvailMultiQueue( ) const +{ + // return any empty multi queue slot + + int avail = -1; + + for ( int i = 0; i < _multi_queue_size; ++i ) { + if ( ( !_MultiQueueFull( i ) ) && + ( !_mq_matched[i] ) ) { + avail = i; + break; + } + } + + return avail; +} + +void ChaosRouter::_NextInterestingChannel( ) +{ + bool interesting; + + int mq_index; + int in_index; + int mq_avail; + + int c; + + interesting = false; + mq_index = -1; + in_index = -1; + + // A channel is interesting if + // + // ( output frame available and + // ( ( a multiqueue packet wants output channel ) or + // ( an input packet wants output channel ) or + // ( the multiqueue is full ) ) ) + // or + // ( the packet at the input channel is stalled ) + + for ( c = 0; ( c < _inputs ) && ( !interesting ); ++c ) { + if ( _OutputAvail( _cur_channel ) ) { + mq_index = _MultiQueueForOutput( _cur_channel ); + in_index = _InputForOutput( _cur_channel ); + + if ( ( mq_index != -1 ) || ( in_index != -1 ) ) { + interesting = true; + } + } + + if ( _input_state[_cur_channel] == full ) { + interesting = true; + } + + if ( !interesting ) { + _cur_channel = ( _cur_channel + 1 ) % _inputs; + } + } + + if ( interesting ) { + //cout << _cur_channel << " is interesting at " << FullName() << endl; + + if ( mq_index != -1 ) { + //cout << "Match for multi-queue " << mq_index << " at " << FullName() + // << ", output matched = " << _output_matched[_cur_channel] << endl; + + _output_matched[_cur_channel] = true; + _multi_match[mq_index] = _cur_channel; + } else if ( in_index != -1 ) { + _output_matched[_cur_channel] = true; + _input_output_match[in_index] = _cur_channel; + + //cout << "Match for input " << in_index << " at " << FullName() << endl; + + if ( _input_state[in_index] == full ) { + _input_state[in_index] = leaving; + } else if ( _input_state[in_index] == filling ) { + _input_state[in_index] = cut_through; + } else { + Error( "Tried to route input through crossbar that was not full or filling!" ); + } + } + + // Any non-injection channel that is routable is + // directed to the multi-queue + if ( ( ( _input_state[_cur_channel] == filling ) || + ( _input_state[_cur_channel] == full ) ) && + ( !_IsInjectionChan( _cur_channel ) ) ) { + ++_read_stall; + } else { + // go to next channel for the next cycle + _cur_channel = ( _cur_channel + 1 ) % _inputs; + _read_stall = 0; + } + } + + if ( _read_stall > 0 ) { + mq_avail = _FindAvailMultiQueue( ); + + if ( mq_avail != -1 ) { + if ( _input_state[_cur_channel] == full ) { + _input_state[_cur_channel] = leaving; + } else if ( _input_state[_cur_channel] == filling ) { + _input_state[_cur_channel] = cut_through; + } else { + cout << "Input " << _cur_channel << " state = " + << _input_state[_cur_channel] << endl; + Error( "Tried to route input throught multi-queue that was not full or filling!" ); + } + + _input_mq_match[_cur_channel] = mq_avail; + _mq_matched[mq_avail] = true; + + // go to next channel for the next cycle + _cur_channel = ( _cur_channel + 1 ) % _inputs; + _read_stall = 0; + } else { + ++_read_stall; + //cout << "stalling at input " << _cur_channel << " (count = " << _read_stall << ")" << endl; + } + } +} + +void ChaosRouter::_OutputAdvance( ) +{ + Flit *f, *f2; + Credit *c; + bool advanced; + int mq; + + _crossbar_pipe->WriteAll( 0 ); + + for ( int i = 0; i < _inputs; ++i ) { + if ( ( ( _input_output_match[i] != -1 ) || + ( _input_mq_match[i] != -1 ) ) && + ( !_input_frame[i].empty( ) ) ) { + + advanced = false; + f = _input_frame[i].front( ); + + /*if ( ! ) { + + } else { + cout << "Input = " << i + << ", input_output_match = " << _input_output_match[i] + << ", input_mq_match = " << _input_mq_match[i] << endl; + Error( "Input queue empty, but matched!" ); + }*/ + + if ( _input_output_match[i] != -1 ) { + if ( f->tail ) { + _output_matched[_input_output_match[i]] = false; + } + + _crossbar_pipe->Write( f, _input_output_match[i] ); + + if ( f->watch ) { + *gWatchOut << GetSimTime() << " | " << FullName() << " | " + << "Flit traversing crossbar from input queue " + << i << " at " + << FullName() << endl + << *f; + } + + advanced = true; + + } else if ( !_MultiQueueFull( _input_mq_match[i] ) ) { + + mq = _input_mq_match[i]; + + if ( f->head ) { + _rf( this, f, i, _mq_route[mq], false ); + _mq_age[mq] = 0; + + if ( _multi_state[mq] == empty ) { + _multi_state[mq] = filling; + } else if ( _multi_state[mq] == leaving ) { + _multi_state[mq] = shared; + } else { + Error( "Multi-queue received head while not empty or leaving!" ); + } + } + + if ( f->tail ) { + _mq_matched[mq] = false; + + if ( _multi_state[mq] == filling ) { + _multi_state[mq] = full; + } else if ( _multi_state[mq] == cut_through ) { + _multi_state[mq] = leaving; + } else { + Error( "Multi-queue received tail while not filling or cutting-through!" ); + } + } + + _multi_queue[mq].push( f ); + + if ( f->watch ) { + *gWatchOut << GetSimTime() << " | " << FullName() << " | " + << "Flit stored in multiqueue at " + << FullName() << endl + << "State = " << _multi_state[mq] << endl + << *f; + } + + advanced = true; + } + + if ( advanced ) { + _input_frame[i].pop( ); + + if ( f->tail ) { // last in packet, update state + if ( _input_state[i] == leaving ) { + _input_state[i] = empty; + } else if ( _input_state[i] == shared ) { + _input_state[i] = filling; + f2 = _input_frame[i].front( ); + // update routes + _rf( this, f2, i, _input_route[i], false ); + } + + _input_output_match[i] = -1; + _input_mq_match[i] = -1; + } + + c = Credit::New( ); + c->vc.insert(0); + _credit_queue[i].push( c ); + } + } + } + + for ( int m = 0; m < _multi_queue_size; ++m ) { + if ( _multi_match[m] != -1 ) { + if ( _multi_queue[m].empty( ) ) { + cout << "State = " << _multi_state[m] << endl; + Error( "Multi queue empty, but matched!" ); + } + assert( !_multi_queue[m].empty( ) ); + f = _multi_queue[m].front( ); + _multi_queue[m].pop( ); + + _crossbar_pipe->Write( f, _multi_match[m] ); + + if ( f->watch ) { + *gWatchOut << GetSimTime() << " | " << FullName() << " | " + << "Flit traversing crossbar from multiqueue slot " + << m << " at " + << FullName() << endl + << *f; + } + + if ( f->head ) { + if ( _multi_state[m] == filling ) { + _multi_state[m] = cut_through; + } else if ( _multi_state[m] == full ) { + _multi_state[m] = leaving; + } else { + Error( "Multi-queue sent head while not filling or full!" ); + } + } + + if ( f->tail ) { + _output_matched[_multi_match[m]] = false; + _multi_match[m] = -1; + + if ( _multi_state[m] == shared ) { + _multi_state[m] = filling; + } else if ( _multi_state[m] == leaving ) { + _multi_state[m] = empty; + } else { + cout << "State = " << _multi_state[m] << endl; + cout << *f; + Error( "Multi-queue sent tail while not leaving or shared!" ); + } + } + } + + _mq_age[m]++; + } +} + + +void ChaosRouter::_SendFlits( ) +{ + for ( int output = 0; output < _outputs; ++output ) { + Flit *f = _crossbar_pipe->Read( output ); + + if ( f ) { + _output_frame[output].push( f ); + f->hops++; + } + + if ( ( _next_queue_cnt[output] < _buffer_size ) && + ( !_output_frame[output].empty( ) ) ) { + _output_channels[output]->Send( _output_frame[output].front( ) ); + _output_frame[output].pop( ); + ++_next_queue_cnt[output]; + } + } +} + +void ChaosRouter::_SendCredits( ) +{ + for ( int input = 0; input < _inputs; ++input ) { + if ( !_credit_queue[input].empty( ) ) { + Credit *c = _credit_queue[input].front( ); + _credit_queue[input].pop( ); + _input_credits[input]->Send( c ); + } + } +} + +void ChaosRouter::Display( ostream & os ) const +{ +} diff --git a/src/intersim2/.svn/pristine/12/1260dd25f0b77d1694bc40d60681090fdb77e795.svn-base b/src/intersim2/.svn/pristine/12/1260dd25f0b77d1694bc40d60681090fdb77e795.svn-base new file mode 100644 index 0000000..6488ea4 --- /dev/null +++ b/src/intersim2/.svn/pristine/12/1260dd25f0b77d1694bc40d60681090fdb77e795.svn-base @@ -0,0 +1,186 @@ +// $Id$ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior University + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _POWER_MODULE_HPP_ +#define _POWER_MODULE_HPP_ + +#include <map> + +#include "module.hpp" +#include "network.hpp" +#include "config_utils.hpp" +#include "flitchannel.hpp" +#include "switch_monitor.hpp" +#include "buffer_monitor.hpp" + +struct wire{ + double L; + double K; + double M; + double N; +}; + +class Power_Module : public Module { + +protected: + //network undersimulation + Network * net; + int classes; + //all channels are this width + double channel_width; + //resimulate all with channel_width decremented by channel_sweep until 0 + double channel_sweep; + //write result to a tabbed format to file + string output_file_name; + + //buffer depth + double depthVC; + //vcs + double numVC; + + //store the property of wires based on length + map<double, wire> wire_map; + + //////////////////////////////////Constants///////////////////////////// + //wire length in (mm) + double wire_length; + //////////Metal Parameters//////////// + // Wire left/right coupling capacitance [ F/mm ] + double Cw_cpl ; + // Wire up/down groudn capacitance [ F/mm ] + double Cw_gnd ; + double Cw ; + double Rw ; + // metal pitch [mm] + double MetalPitch ; + + + //////////Device Parameters//////////// + + double LAMBDA ; // [um/LAMBDA] + double Cd ; // [F/um] (for Delay) + double Cg ; // [F/um] (for Delay) + double Cgdl ; // [F/um] (for Delay) + + double Cd_pwr; // [F/um] (for Power) + double Cg_pwr ; // [F/um] (for Power) + + double IoffN ; // [A/um] + double IoffP ; // [A/um] + // Leakage from bitlines, two-port cell [A] + double IoffSRAM; + // [Ohm] ( D1=1um Inverter) + double R ; + // [F] ( D1=1um Inverter - for Power ) + double Ci_delay; + // [F] ( D1=1um Inverter - for Power ) + double Co_delay ; + + double Ci ; + double Co ; + double Vdd ; + double FO4 ; + double tCLK ; + double fCLK ; + + double H_INVD2; + double W_INVD2; + double H_DFQD1; + double W_DFQD1; + double H_ND2D1; + double W_ND2D1; + double H_SRAM; + double W_SRAM; + double ChannelPitch ; + double CrossbarPitch; + ////////////////////////////////End of Constants///////////////////////////// + + /////////////results/////////////////// + double totalTime; + double channelWirePower; + double channelClkPower; + double channelDFFPower; + double channelLeakPower; + double inputReadPower; + double inputWritePower; + double inputLeakagePower; + double switchPower; + double switchPowerCtrl; + double switchPowerLeak; + double outputPower; + double outputPowerClk; + double outputCtrlPower; + double channelArea; + double switchArea; + double inputArea; + double outputArea; + double maxInputPort; + double maxOutputPort; + + + //////////////////////// + + //channels + void calcChannel(const FlitChannel * f); + wire const & wireOptimize(double l); + double powerRepeatedWire(double L, double K, double M, double N); + double powerRepeatedWireLeak (double K, double M, double N); + double powerWireClk (double M, double W); + double powerWireDFF(double M, double W, double alpha); + + //memory + void calcBuffer(const BufferMonitor *bm); + double powerWordLine(double memoryWidth, double memoryDepth); + double powerMemoryBitRead(double memoryDepth); + double powerMemoryBitWrite(double memoryDepth); + double powerMemoryBitLeak(double memoryDepth ); + + //switch + void calcSwitch(const SwitchMonitor *sm); + double powerCrossbar(double width, double inputs, double outputs, double from, double to); + double powerCrossbarCtrl(double width, double inputs, double outputs); + double powerCrossbarLeak (double width, double inputs, double outputs); + + //output + double powerOutputCtrl(double width); + + //area + + double areaChannel (double K, double N, double M); + double areaCrossbar(double Inputs, double Outputs) ; + double areaInputModule(double Words) ; + double areaOutputModule(double Outputs); + +public: + Power_Module(Network * net, const Configuration &config); + ~Power_Module(); + + void run(); + + +}; +#endif diff --git a/src/intersim2/.svn/pristine/12/129d383ada436691b3879ee38f72c6420d1b3b86.svn-base b/src/intersim2/.svn/pristine/12/129d383ada436691b3879ee38f72c6420d1b3b86.svn-base new file mode 100644 index 0000000..6aa2d53 --- /dev/null +++ b/src/intersim2/.svn/pristine/12/129d383ada436691b3879ee38f72c6420d1b3b86.svn-base @@ -0,0 +1,481 @@ +// $Id$ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior University + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "booksim.hpp" +#include <iostream> +#include <sstream> +#include <cassert> +#include "allocator.hpp" + +///////////////////////////////////////////////////////////////////////// +//Allocator types +#include "maxsize.hpp" +#include "pim.hpp" +#include "islip.hpp" +#include "loa.hpp" +#include "wavefront.hpp" +#include "selalloc.hpp" +#include "separable_input_first.hpp" +#include "separable_output_first.hpp" +// +///////////////////////////////////////////////////////////////////////// + +//================================================== +// Allocator base class +//================================================== + +Allocator::Allocator( Module *parent, const string& name, + int inputs, int outputs ) : +Module( parent, name ), _inputs( inputs ), _outputs( outputs ), _dirty( false ) +{ + _inmatch.resize(_inputs, -1); + _outmatch.resize(_outputs, -1); +} + +void Allocator::Clear( ) +{ + if(_dirty) { + _inmatch.assign(_inputs, -1); + _outmatch.assign(_outputs, -1); + _dirty = false; + } +} + +void Allocator::AddRequest( int in, int out, int label, int in_pri, + int out_pri ) { + + assert( ( in >= 0 ) && ( in < _inputs ) ); + assert( ( out >= 0 ) && ( out < _outputs ) ); + assert( label >= 0 ); + _dirty = true; +} + +int Allocator::OutputAssigned( int in ) const +{ + assert( ( in >= 0 ) && ( in < _inputs ) ); + + return _inmatch[in]; +} + +int Allocator::InputAssigned( int out ) const +{ + assert( ( out >= 0 ) && ( out < _outputs ) ); + + return _outmatch[out]; +} + +void Allocator::PrintGrants( ostream * os ) const +{ + if(!os) os = &cout; + + *os << "Input grants = [ "; + for ( int input = 0; input < _inputs; ++input ) { + if(_inmatch[input] >= 0) { + *os << input << " -> " << _inmatch[input] << " "; + } + } + *os << "], output grants = [ "; + for ( int output = 0; output < _outputs; ++output ) { + if(_outmatch[output] >= 0) { + *os << output << " -> " << _outmatch[output] << " "; + } + } + *os << "]." << endl; +} + +//================================================== +// DenseAllocator +//================================================== + +DenseAllocator::DenseAllocator( Module *parent, const string& name, + int inputs, int outputs ) : + Allocator( parent, name, inputs, outputs ) +{ + _request.resize(_inputs); + + for ( int i = 0; i < _inputs; ++i ) { + _request[i].resize(_outputs); + for ( int j = 0; j < _outputs; ++j ) { + _request[i][j].label = -1; + } + } +} + +void DenseAllocator::Clear( ) +{ + for ( int i = 0; i < _inputs; ++i ) { + for ( int j = 0; j < _outputs; ++j ) { + _request[i][j].label = -1; + } + } + Allocator::Clear(); +} + +int DenseAllocator::ReadRequest( int in, int out ) const +{ + assert( ( in >= 0 ) && ( in < _inputs ) ); + assert( ( out >= 0 ) && ( out < _outputs ) ); + + return _request[in][out].label; +} + +bool DenseAllocator::ReadRequest( sRequest &req, int in, int out ) const +{ + assert( ( in >= 0 ) && ( in < _inputs ) ); + assert( ( out >= 0 ) && ( out < _outputs ) ); + + req = _request[in][out]; + + return ( req.label >= 0 ); +} + +void DenseAllocator::AddRequest( int in, int out, int label, + int in_pri, int out_pri ) +{ + Allocator::AddRequest(in, out, label, in_pri, out_pri); + assert( _request[in][out].label == -1 ); + + _request[in][out].label = label; + _request[in][out].in_pri = in_pri; + _request[in][out].out_pri = out_pri; +} + +void DenseAllocator::RemoveRequest( int in, int out, int label ) +{ + assert( ( in >= 0 ) && ( in < _inputs ) ); + assert( ( out >= 0 ) && ( out < _outputs ) ); + + _request[in][out].label = -1; +} + +bool DenseAllocator::InputHasRequests( int in ) const +{ + for(int out = 0; out < _outputs; ++out) { + if(_request[in][out].label >= 0) { + return true; + } + } + return false; +} + +bool DenseAllocator::OutputHasRequests( int out ) const +{ + for(int in = 0; in < _inputs; ++in) { + if(_request[in][out].label >= 0) { + return true; + } + } + return false; +} + +int DenseAllocator::NumInputRequests( int in ) const +{ + int result = 0; + for(int out = 0; out < _outputs; ++out) { + if(_request[in][out].label >= 0) { + ++result; + } + } + return result; +} + +int DenseAllocator::NumOutputRequests( int out ) const +{ + int result = 0; + for(int in = 0; in < _inputs; ++in) { + if(_request[in][out].label >= 0) { + ++result; + } + } + return result; +} + +void DenseAllocator::PrintRequests( ostream * os ) const +{ + if(!os) os = &cout; + + *os << "Input requests = [ "; + for ( int input = 0; input < _inputs; ++input ) { + bool print = false; + ostringstream ss; + for ( int output = 0; output < _outputs; ++output ) { + const sRequest & req = _request[input][output]; + if ( req.label >= 0 ) { + print = true; + ss << output << "@" << req.in_pri << " "; + } + } + if(print) { + *os << input << " -> [ " << ss.str() << "] "; + } + } + *os << "], output requests = [ "; + for ( int output = 0; output < _outputs; ++output ) { + bool print = false; + ostringstream ss; + for ( int input = 0; input < _inputs; ++input ) { + const sRequest & req = _request[input][output]; + if ( req.label >= 0 ) { + print = true; + ss << input << "@" << req.out_pri << " "; + } + } + if(print) { + *os << output << " -> [ " << ss.str() << "] "; + } + } + *os << "]." << endl; +} + +//================================================== +// SparseAllocator +//================================================== + +SparseAllocator::SparseAllocator( Module *parent, const string& name, + int inputs, int outputs ) : + Allocator( parent, name, inputs, outputs ) +{ + _in_req.resize(_inputs); + _out_req.resize(_outputs); +} + + +void SparseAllocator::Clear( ) +{ + for ( int i = 0; i < _inputs; ++i ) { + if(!_in_req[i].empty()) + _in_req[i].clear( ); + } + + for ( int j = 0; j < _outputs; ++j ) { + if(!_out_req[j].empty()) + _out_req[j].clear( ); + } + + _in_occ.clear( ); + _out_occ.clear( ); + + Allocator::Clear(); +} + +int SparseAllocator::ReadRequest( int in, int out ) const +{ + sRequest r; + + if ( ! ReadRequest( r, in, out ) ) { + r.label = -1; + } + + return r.label; +} + +bool SparseAllocator::ReadRequest( sRequest &req, int in, int out ) const +{ + bool found; + + assert( ( in >= 0 ) && ( in < _inputs ) ); + assert( ( out >= 0 ) && ( out < _outputs ) ); + + map<int, sRequest>::const_iterator match = _in_req[in].find(out); + if ( match != _in_req[in].end( ) ) { + req = match->second; + found = true; + } else { + found = false; + } + + return found; +} + +void SparseAllocator::AddRequest( int in, int out, int label, + int in_pri, int out_pri ) +{ + Allocator::AddRequest(in, out, label, in_pri, out_pri); + assert( _in_req[in].count(out) == 0 ); + assert( _out_req[out].count(in) == 0 ); + + // insert into occupied inputs set if + // input is currently empty + if ( _in_req[in].empty( ) ) { + _in_occ.insert(in); + } + + // similarly for the output + if ( _out_req[out].empty( ) ) { + _out_occ.insert(out); + } + + sRequest req; + req.port = out; + req.label = label; + req.in_pri = in_pri; + req.out_pri = out_pri; + + _in_req[in][out] = req; + + req.port = in; + + _out_req[out][in] = req; +} + +void SparseAllocator::RemoveRequest( int in, int out, int label ) +{ + assert( ( in >= 0 ) && ( in < _inputs ) ); + assert( ( out >= 0 ) && ( out < _outputs ) ); + + assert( _in_req[in].count( out ) > 0 ); + assert( _in_req[in][out].label == label ); + _in_req[in].erase( out ); + + // remove from occupied inputs list if + // input is now empty + if ( _in_req[in].empty( ) ) { + _in_occ.erase(in); + } + + // similarly for the output + assert( _out_req[out].count( in ) > 0 ); + assert( _out_req[out][in].label == label ); + _out_req[out].erase( in ); + + if ( _out_req[out].empty( ) ) { + _out_occ.erase(out); + } +} + +bool SparseAllocator::InputHasRequests( int in ) const +{ + return _in_occ.count(in) > 0; +} + +bool SparseAllocator::OutputHasRequests( int out ) const +{ + return _out_occ.count(out) > 0; +} + +int SparseAllocator::NumInputRequests( int in ) const +{ + return _in_occ.count(in); +} + +int SparseAllocator::NumOutputRequests( int out ) const +{ + return _out_occ.count(out); +} + +void SparseAllocator::PrintRequests( ostream * os ) const +{ + map<int, sRequest>::const_iterator iter; + + if(!os) os = &cout; + + *os << "Input requests = [ "; + for ( int input = 0; input < _inputs; ++input ) { + if(!_in_req[input].empty()) { + *os << input << " -> [ "; + for ( iter = _in_req[input].begin( ); + iter != _in_req[input].end( ); iter++ ) { + *os << iter->second.port << "@" << iter->second.in_pri << " "; + } + *os << "] "; + } + } + *os << "], output requests = [ "; + for ( int output = 0; output < _outputs; ++output ) { + if(!_out_req[output].empty()) { + *os << output << " -> "; + *os << "[ "; + for ( iter = _out_req[output].begin( ); + iter != _out_req[output].end( ); iter++ ) { + *os << iter->second.port << "@" << iter->second.out_pri << " "; + } + *os << "] "; + } + } + *os << "]." << endl; +} + +//================================================== +// Global allocator allocation function +//================================================== + +Allocator *Allocator::NewAllocator( Module *parent, const string& name, + const string &alloc_type, + int inputs, int outputs, + Configuration const * const config ) +{ + Allocator *a = 0; + + string alloc_name; + string param_str; + size_t left = alloc_type.find_first_of('('); + if(left == string::npos) { + alloc_name = alloc_type; + } else { + alloc_name = alloc_type.substr(0, left); + size_t right = alloc_type.find_last_of(')'); + if(right == string::npos) { + param_str = alloc_type.substr(left+1); + } else { + param_str = alloc_type.substr(left+1, right-left-1); + } + } + if ( alloc_name == "max_size" ) { + a = new MaxSizeMatch( parent, name, inputs, outputs ); + } else if ( alloc_name == "pim" ) { + int iters = param_str.empty() ? (config ? config->GetInt("alloc_iters") : 1) : atoi(param_str.c_str()); + a = new PIM( parent, name, inputs, outputs, iters ); + } else if ( alloc_name == "islip" ) { + int iters = param_str.empty() ? (config ? config->GetInt("alloc_iters") : 1) : atoi(param_str.c_str()); + a = new iSLIP_Sparse( parent, name, inputs, outputs, iters ); + } else if ( alloc_name == "loa" ) { + a = new LOA( parent, name, inputs, outputs ); + } else if ( alloc_name == "wavefront" ) { + a = new Wavefront( parent, name, inputs, outputs ); + } else if ( alloc_name == "rr_wavefront" ) { + a = new Wavefront( parent, name, inputs, outputs, true ); + } else if ( alloc_name == "select" ) { + int iters = param_str.empty() ? (config ? config->GetInt("alloc_iters") : 1) : atoi(param_str.c_str()); + a = new SelAlloc( parent, name, inputs, outputs, iters ); + } else if (alloc_name == "separable_input_first") { + string arb_type = param_str.empty() ? (config ? config->GetStr("arb_type") : "round_robin") : param_str; + a = new SeparableInputFirstAllocator( parent, name, inputs, outputs, + arb_type ); + } else if (alloc_name == "separable_output_first") { + string arb_type = param_str.empty() ? (config ? config->GetStr("arb_type") : "round_robin") : param_str; + a = new SeparableOutputFirstAllocator( parent, name, inputs, outputs, + arb_type ); + } + +//================================================== +// Insert new allocators here, add another else if +//================================================== + + + return a; +} + |
