1 // mep-cache.cxx - An implementation of the Cache for the
2 // Toshiba Media Processor (MeP). -*- C++ -*-
4 // Copyright (C) 2004, 2005 Red Hat.
5 // This file is part of SID and is licensed under the GPL.
6 // See the file COPYING.SID for conditions for redistribution.
12 #include <sidcomputil.h>
13 #include <sidattrutil.h>
14 #include <sidpinutil.h>
15 #include <sidbusutil.h>
16 #include <sidmiscutil.h>
24 #include "mep-cache.h"
27 using namespace sidutil;
32 mep_cache::mep_cache (unsigned assoc, unsigned cache_sz, unsigned line_sz,
33 cache_replacement_algorithm& replacer)
34 : blocking_cache_component (this, assoc, cache_sz, line_sz, replacer, *(new mep_cache_line_factory (*this))),
37 clear_tag_pin (this, & mep_cache::clear_tag),
38 endian_set_pin (this, & mep_cache::endian_set_pin_handler)
40 add_accessor ("tag-test-mem", &tag_test_mem);
41 add_accessor ("data-test-mem", &data_test_mem);
42 add_pin ("clear-tag", &clear_tag_pin);
43 add_pin ("endian-set!", & this->endian_set_pin);
44 add_attribute ("endian", &endianness);
48 mep_cache::endian_set_pin_handler(sid::host_int_4 v)
53 this->endianness = endian_big;
56 this->endianness = endian_little;
59 // XXX: warning message?
65 mep_cache::write_tag (unsigned way, int index, cache_tag atag)
70 host_int_4 address = (way * cache_size / 2) + (index * line_size);
71 if (endianness == endian_big)
73 big_int_4 data = atag;
74 tag_test_mem->write (address, data);
78 little_int_4 data = atag;
79 tag_test_mem->write (address, data);
84 mep_cache::read_tag (unsigned way, int index)
89 host_int_4 address = (way * cache_size / 2) + (index * line_size);
90 if (endianness == endian_big)
93 tag_test_mem->read (address, atag);
97 tag_test_mem->read (address, atag);
101 #define DEFN_METHOD(DataType) \
102 /* Insert a datum into the line at the given index, starting at byte offset. */ \
104 mep_cache::write_data (unsigned way, int index, unsigned offset, DataType new_data) \
106 if (! data_test_mem) \
108 host_int_4 address = (way * cache_size / 2) + (index * line_size) + offset; \
109 data_test_mem->write (address, new_data); \
111 /* Extract a datum from the line at the given index, starting at byte offset. */ \
113 mep_cache::read_data (unsigned way, int index, unsigned offset, DataType& new_data) const \
115 if (! data_test_mem) \
117 host_int_4 address = (way * cache_size / 2) + (index * line_size) + offset; \
118 data_test_mem->read (address, new_data); \
121 DEFN_METHOD (sid::big_int_1)
122 DEFN_METHOD (sid::big_int_2)
123 DEFN_METHOD (sid::big_int_4)
124 DEFN_METHOD (sid::big_int_8)
125 DEFN_METHOD (sid::little_int_1)
126 DEFN_METHOD (sid::little_int_2)
127 DEFN_METHOD (sid::little_int_4)
128 DEFN_METHOD (sid::little_int_8)
132 mep_cache::clear_tag (host_int_4 addr)
134 cache_tag tag = acache.addr_to_tag (addr);
135 cache_line* line = acache.find (tag);
136 if (line && line->valid_p ())
138 mep_cache_line *mep_line = dynamic_cast<mep_cache_line*> (line);
140 mep_line->clear_tag ();
145 mep_cache::dump_data (unsigned way, int index) const
147 for (unsigned i = 0; i < line_size; i++)
149 sid::little_int_1 data;
150 read_data (way, index, i, data);
151 cerr << setw (2) << setfill ('0') << static_cast<unsigned> (data);
156 mep_cache::configure (const string &config)
158 // Call up to the base class first
159 blocking_cache_component::configure (config);
161 // Now handle relevent configuration for us.
162 if (config.size () <= 13)
164 if (config.substr (0, 13) == "model-busses=")
166 set_attribute_value ("blockable?", config.substr (13));
171 // ----------------------------------------
173 mep_cache_line::mep_cache_line (unsigned line_size, unsigned index, unsigned way, mep_cache &c) :
179 // Compute a shift amount for removing the index from an address.
180 index_shift = log2 (my_size);
182 // Compute a mask for extracting the tag index
183 unsigned assoc = my_cache.assoc ();
184 unsigned size = my_cache.size ();
185 unsigned indices = size / assoc / line_size;
186 index_mask = (1 << log2 (indices)) - 1;
188 // Compute a mask for extracting the address tag.
189 int non_address_bits = log2 (size) - log2 (assoc);
190 address_mask = ~((1 << non_address_bits) - 1);
193 // Get the line's tag.
195 mep_cache_line::set_raw_tag (cache_tag atag)
197 // Tag is already shifted to the index.
198 assert (my_index == ((atag >> index_shift) & index_mask));
199 my_cache.write_tag (my_way, my_index, atag);
203 mep_cache_line::set_tag (cache_tag atag)
205 // Tag is already shifted to the index.
206 assert (my_index == (atag & index_mask));
207 atag <<= index_shift;
209 cache_tag oldtag = raw_tag ();
210 oldtag &= ~address_mask;
211 oldtag |= atag & address_mask;
212 my_cache.write_tag (my_way, my_index, oldtag);
216 mep_cache_line::clear_tag ()
218 // Clear the tag bits as well as the dirty and valid bits.
219 // Leave the R bit intact.
220 cache_tag oldtag = raw_tag ();
222 my_cache.write_tag (my_way, my_index, oldtag);
226 mep_cache_line::raw_tag () const
228 assert (my_index >= 0);
229 cache_tag atag = my_cache.read_tag (my_way, my_index);
230 // Add the index back into the tag
231 atag |= my_index << index_shift;
236 mep_cache_line::tag () const
238 return raw_tag () >> index_shift;
241 // Mark the line dirty or clean.
243 mep_cache_line::dirty ()
245 assert (my_index >= 0);
246 cache_tag atag = raw_tag ();
252 mep_cache_line::clean ()
254 assert (my_index >= 0);
255 cache_tag atag = raw_tag ();
260 // Mark the line valid or invalid.
262 mep_cache_line::validate ()
264 assert (my_index >= 0);
265 cache_tag atag = raw_tag ();
271 mep_cache_line::invalidate ()
273 assert (my_index >= 0);
274 cache_tag atag = raw_tag ();
279 // Maintain the R bit
281 mep_cache_line::get_R () const
283 assert (my_index >= 0);
284 cache_tag atag = raw_tag ();
285 return (atag >> 2) & 0x1;
289 mep_cache_line::set_R (int R)
291 assert (my_index >= 0);
292 cache_tag atag = raw_tag ();
294 atag |= (R & 0x1) << 2;
298 // Lock or unlock the line.
300 mep_cache_line::lock ()
306 mep_cache_line::unlock ()
311 // Is the line dirty?
313 mep_cache_line::dirty_p () const
315 assert (my_index >= 0);
316 cache_tag atag = raw_tag ();
317 return (atag & 0x2) != 0;
320 // Is the line valid?
322 mep_cache_line::valid_p () const
324 assert (my_index >= 0);
325 cache_tag atag = raw_tag ();
326 return (atag & 0x1) != 0;
329 // Is the line locked?
331 mep_cache_line::locked_p () const
333 return false; // Lines can't be locked
336 #define DEFN_METHOD(DataType) \
337 /* Insert a datum into the line, starting at byte offset. */ \
339 mep_cache_line::insert (unsigned offset, DataType new_data) \
341 assert (offset + sizeof (new_data) <= my_size); \
342 assert (my_index >= 0); \
343 my_cache.write_data (my_way, my_index, offset, new_data); \
346 /* Extract a datum from the line, starting at byte offset. */ \
348 mep_cache_line::extract (unsigned offset, DataType& new_data) const \
350 assert (offset + sizeof (new_data) <= my_size); \
351 assert (my_index >= 0); \
352 my_cache.read_data (my_way, my_index, offset, new_data); \
355 DEFN_METHOD (sid::big_int_1)
356 DEFN_METHOD (sid::big_int_2)
357 DEFN_METHOD (sid::big_int_4)
358 DEFN_METHOD (sid::big_int_8)
359 DEFN_METHOD (sid::little_int_1)
360 DEFN_METHOD (sid::little_int_2)
361 DEFN_METHOD (sid::little_int_4)
362 DEFN_METHOD (sid::little_int_8)
365 // Dump a line in human readable form to cout.
367 mep_cache_line::dump_data () const
369 assert (my_index >= 0);
370 my_cache.dump_data (my_way, my_index);
373 // ----------------------------------------
375 // Choose a line to replace in a cache set. Return it, if successful
377 mep_assoc_replacement_algorithm::expell (cache_set &set)
379 // Check the R bit in way 0 for the index of the line to be replaced.
380 cache_line *line = &set[0];
381 mep_cache_line *mep_line = dynamic_cast<mep_cache_line*> (line);
383 int R = mep_line->get_R ();
384 assert (R == 0 || R == 1);
386 // Reset the bit so the other line is replaced next time.
387 mep_line->set_R (! R);