cache.h

Go to the documentation of this file.
00001 //    sampalib.org ESL library and tools
00002 //    Copyright (C) 2007  Thierry Grellier
00003 //
00004 //    This program is free software; you can redistribute it and/or modify
00005 //    it under the terms of the GNU General Public License version 2 as
00006 //    published by the Free Software Foundation.
00007 //
00008 //    This program is distributed in the hope that it will be useful,
00009 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //    GNU General Public License for more details.
00012 //
00013 //    You should have received a copy of the GNU General Public License along
00014 //    with this program; if not, write to the Free Software Foundation, Inc.,
00015 //    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016 //
00017 //    contact: www.sampalib.org
00018 
00019 #ifndef _SAMPA_COMPONENT_CACHE_H_
00020 #define _SAMPA_COMPONENT_CACHE_H_
00021 
00022 #include "sampa/core/module.h"
00023 
00024 namespace Sampa {
00025 
00026   class Cache : public Module {
00027   public:
00028     Cache(const Name&);
00029 
00030     void bind_inst_initiator(Initiator*);
00031     void bind_data_initiator(Initiator*);
00032     Target* get_inst_target() { return &p_inst_slave; }
00033     Target* get_data_target() { return &p_data_slave; }
00034 
00035     void bind_inst_target(Target*);
00036     void bind_data_target(Target*);
00037     Initiator* get_inst_initiator() { return &p_inst_master; }
00038     Initiator* get_data_initiator() { return &p_data_master; }
00039 
00040   private:
00041     bool recieve_inst_response(const Response&);
00042     {
00043       if (m_inst_responses_pipe.is_empty())
00044         e_inst_response.notify_in_n_rising(m_response_pipeline_depth);
00045       short idx = m_inst_response_pipe.push();
00046       m_inst_response[idx]      = response;
00047       m_inst_response_date[idx] = get_rising_count();
00048       return true;
00049     }
00050 
00051     bool recieve_data_response(const Response& response)
00052     {
00053       if (m_data_responses_pipe.is_empty())
00054         e_data_response.notify_in_n_rising(m_response_pipeline_depth);
00055       short idx = m_inst_response_pipe.push();
00056       m_data_response[idx]      = response;
00057       m_data_response_date[idx] = get_rising_count();
00058       return true;
00059     }
00060 
00061     bool recieve_inst_request(const Request& req) {
00062       if (m_burst-- == 0) {
00063         m_inst_req.schedule(req);
00064         m_burst += req.get_burst();
00065       }
00066       return true;
00067     }
00068 
00069     bool recieve_data_request(const Request&);
00070 
00071     void fill_instruction() {
00072       if (m_inst_line_fill_pending) {
00073         m_inst_line_fill_pending = false;
00074         m_inst_req_out = m_inst_req;
00075         if (inst_miss()) {
00076           e_inst_request.notify_in_n_rising(2);
00077         }
00078       } else {
00079         // 1 cycle to fill line read buffer
00080 
00081       }
00082       if (m_pending_inst_resp > 0) {
00083         m_pending_inst_resp--;
00084         p_inst_slave->send_response(m_inst_req); 
00085       }
00086     }
00087 
00088     void forward_data_request()
00089     {
00090       if (read_pending > 0) {
00091       } else if (eviction) {
00092       }
00093     }
00094 
00095     void forward_data_response()
00096     {
00097       short idx = m_inst_response_pipe.pop();
00098       p_inst_slave->send_response(m_inst_responses[idx]);
00099       if (!m_inst_response_pipe.is_empty())
00100         e_inst_response.notify_in_n_rising(m_inst_responses_date[m_inst_response_pipe.peek()]+m_response_pipeline_depth- get_rising_count());
00101     }
00102 
00103     void forward_inst_response()
00104     {
00105       short idx = m_inst_response_pipe.pop();
00106       p_inst_slave->send_response(m_inst_responses[idx]);
00107       if (!m_inst_response_pipe.is_empty())
00108         e_inst_response.notify_in_n_rising(m_inst_responses_date[m_inst_response_pipe.peek()]+m_response_pipeline_depth- get_rising_count());
00109     }
00110 
00111     AdaptingTarget    p_inst_slave;
00112     AdaptingTarget    p_data_slave;
00113     AdaptingInitiator p_inst_master;
00114     AdaptingInitiator p_data_master;
00115 
00116     EventSingle       e_inst_response;
00117     EventSingle       e_data_response;
00118     IntParameter      m_response_pipeline_depth;
00119     Array<Response>   m_inst_responses;
00120     Array<Response>   m_data_responses;
00121     Gated<Request>    m_inst_req;
00122     Gated<Request>    m_data_req;
00123   };
00124 }
00125 
00126 #endif
00127 bool read_hit(const Address& address)
00128 {
00129   return (cacheable(address) && sampa_rand01() >=  m_read_miss_ratio);
00130 }
00131 
00132 bool inst_hit(const Address& address)
00133 {
00134   return (cacheable(address) && sampa_rand01() >=  m_inst_miss_ratio);
00135 }
00136 
00137 bool write_hit(const Address& address)
00138 {
00139   return (cacheable(address) && sampa_rand01() >=  m_write_miss_ratio);
00140 }
00141 
00142 bool eviction_hit(const Address& address)
00143 {
00144   return (cacheable(address) && sampa_rand01() >= m_eviction_miss_ratio);
00145 }
00146 
00147 void process_data()
00148 {
00149   switch (state) {
00150     case EVALUATE:
00151       if (request.get_command() == READ) {
00152         // linefill
00153         if (read_hit(request.get_address())) {
00154           state = READ_HIT;
00155           e_forward.notify_in_n_rising(2);
00156           set_next_trigger(e_forward);
00157         } else {
00158           state = READ_MISS; // maybe non cacheable
00159           e_forward.notify_in_n_rising(1);
00160           set_next_trigger(e_forward);
00161         }
00162       } else if (request.get_burst() > 1) {
00163         // eviction from L1
00164         e_forward.notify_in_n_rising(1);
00165         set_next_trigger(e_forward);
00166         if (eviction_hit(request.get_address())) {
00167           state = EVICTION_HIT;
00168         } else if (m_write_though) {
00169           // must write
00170           state = EVICTION_MISS;
00171         } else if (eviction()) {
00172           // must make space for the eviction!
00173           state = EVICTION_BACK_EVICTION;
00174         } else {
00175           // just tmp
00176           state = STALL_EVICTION;
00177         }
00178       } else {
00179         // write
00180         e_forward.notify_in_n_rising(1);
00181         set_next_trigger(e_forward);
00182         if (hit()) {
00183           state = WRITE_HIT;
00184         } else if (m_write_through) {
00185           state = WRITE_MISS;
00186         } else {
00187           // need to fill cache first, before writing
00188           m_write_pending = true;
00189           state = MISS;
00190         }
00191       }
00192       m_burst += req.get_burst();
00193       if (hit()) {
00194         state = HIT;
00195         e_forward.notify_in_n_rising(2);
00196         set_next_trigger(e_forward);
00197       } else {
00198         state = MISS;
00199         e_forward.notify_in_n_rising(1);
00200       }
00201       break;
00202     case READ_HIT:
00203       set_next_trigger(p_data_slave->get_response_accepted_event());
00204       state = READ_HIT_NEXT;
00205       // no break !
00206     case READ_HIT_NEXT:
00207       p_inst_slave->send_response();
00208       if (m_burst-- = 0) {
00209         state = EVALUATE;
00210         p_data_slave->accept_request();
00211         set_next_trigger(p_data_slave->get_request_accepted_event());
00212       }
00213       break;
00214     case MISS:
00215       if (m_pending_eviction) {
00216         // stall until completed
00217         set_next_trigger();
00218         break;
00219       }
00220       set_next_trigger(p_inst_master->get_request_accepted_event());
00221       state = MISS_NEXT;
00222       // no break !
00223     case MISS_NEXT:
00224       p_inst_master->send_request();
00225       if (m_burst-- != 0) break;
00226       if (eviction()) {
00227         m_eviction_requested |= 1<<INST;
00228         if (m_eviction_pending > 0) {
00229           state = STALL_EVICTION;
00230           set_next_trigger(e_eviction_granted[INST]);
00231           break;
00232         }
00233       }
00234       // no break !
00235     case STALL_EVICTION:
00236       state = EVALUATE;
00237       p_inst_slave->accept_request();
00238       set_next_trigger(p_inst_slave->get_request_accepted_event());
00239       break; 
00240   }
00241 }
00242 
00243 void forward_data_request()
00244 {
00245   if (m_linefill_pending) {
00246     p_data_master->send_request();
00247     if (--m_linefill_pending == 0) {
00248       set_next_trigger(e_data_req_forward);
00249       if (m_eviction_requested != NONE)
00250         e_data_req_forward.notify_next_cycle();
00251     }
00252   } else if (m_eviction_pending > 0) {
00253     p_data_master->send_request();
00254     if (--m_eviction_pending == 0) {
00255       set_next_trigger(e_data_req_forward);
00256       if (m_eviction_requested != NONE)
00257         e_data_req_forward.notify_next_cycle();
00258     }
00259   } else if (m_linefill_requested) {
00260     m_linefill_pending = m_linefill_req.get_burst() - 1;
00261     p_data_master->send_request(m_linefill_req);
00262     set_next_trigger(p_data_master->get_request_accepted_event());
00263   } else if (m_eviction_requested) {
00264     m_eviction_elected = 1 - m_eviction_elected;
00265     if (!(m_eviction_requested&(1+m_eviction_elected)))
00266       m_eviction_elected = 1 - m_eviction_elected);
00267     m_eviction_requested &= ~(1+m_eviction_elected);     // deassert
00268     e_eviction_granted[m_eviction_elected].notify_next_cycle(); // unblock if stalled
00269     m_eviction_pending = m_eviction_req.get_burst() - 1;
00270     p_data_master->send_request(m_eviction_req);
00271     set_next_trigger(p_data_master->get_request_accepted_event());
00272   }
00273 }
00274 
00275 void process_inst()
00276 {
00277   switch (state) {
00278     case EVALUATE:
00279       m_burst += req.get_burst();
00280       if (hit()) {
00281         state = HIT;
00282         e_forward.notify_in_n_rising(2); // hit calc + line read buffer fill
00283         set_next_trigger(e_forward);
00284       } else {
00285         state = MISS;
00286         e_forward.notify_in_n_rising(1); // hit calc
00287       }
00288       break;
00289     case HIT:
00290       set_next_trigger(p_inst_slave->get_response_accepted_event());
00291       state = HIT_NEXT;
00292       // no break !
00293     case HIT_NEXT:
00294       p_inst_slave->send_response();
00295       if (m_burst-- = 0) {
00296         state = EVALUATE;
00297         p_inst_master->accept_request();
00298         set_next_trigger(p_inst_master->get_request_accepted_event());
00299       }
00300       break;
00301     case MISS:
00302       set_next_trigger(p_inst_master->get_request_accepted_event());
00303       state = MISS_NEXT;
00304       // no break !
00305     case MISS_NEXT:
00306       p_inst_master->send_request();
00307       if (m_burst-- != 0) break;
00308       if (eviction()) {
00309         m_eviction_requested |= 1<<INST;
00310         if (m_eviction_pending > 0) {
00311           state = STALL_EVICTION;
00312           set_next_trigger(e_eviction_granted[INST]);
00313           break;
00314         }
00315       }
00316       // no break !
00317     case STALL_EVICTION:
00318       state = EVALUATE;
00319       p_inst_slave->accept_request();
00320       set_next_trigger(p_inst_slave->get_request_accepted_event());
00321       break; 
00322   }
00323 }
00324 

Generated on Sat Feb 16 16:23:15 2008 for Sampa by  doxygen 1.5.3