openMSX
CheckedRam.cc
Go to the documentation of this file.
1 #include "CheckedRam.hh"
2 #include "MSXCPU.hh"
3 #include "MSXMotherBoard.hh"
4 #include "DeviceConfig.hh"
5 #include "GlobalSettings.hh"
6 #include "StringSetting.hh"
7 #include "likely.hh"
8 #include "xrange.hh"
9 #include <cassert>
10 
11 namespace openmsx {
12 
13 [[nodiscard]] static std::bitset<CacheLine::SIZE> getBitSetAllTrue()
14 {
15  std::bitset<CacheLine::SIZE> result;
16  result.set();
17  return result;
18 }
19 
20 CheckedRam::CheckedRam(const DeviceConfig& config, const std::string& name,
21  static_string_view description, unsigned size)
22  : completely_initialized_cacheline(size / CacheLine::SIZE, false)
23  , uninitialized(size / CacheLine::SIZE, getBitSetAllTrue())
24  , ram(config, name, description, size)
25  , msxcpu(config.getMotherBoard().getCPU())
26  , umrCallback(config.getGlobalSettings().getUMRCallBackSetting())
27 {
28  umrCallback.getSetting().attach(*this);
29  init();
30 }
31 
33 {
34  umrCallback.getSetting().detach(*this);
35 }
36 
37 byte CheckedRam::read(unsigned addr)
38 {
39  unsigned line = addr >> CacheLine::BITS;
40  if (unlikely(!completely_initialized_cacheline[line])) {
41  if (unlikely(uninitialized[line][addr & CacheLine::LOW])) {
42  umrCallback.execute(addr, ram.getName());
43  }
44  }
45  return ram[addr];
46 }
47 
48 const byte* CheckedRam::getReadCacheLine(unsigned addr) const
49 {
50  return (completely_initialized_cacheline[addr >> CacheLine::BITS])
51  ? &ram[addr] : nullptr;
52 }
53 
54 byte* CheckedRam::getWriteCacheLine(unsigned addr) const
55 {
56  return (completely_initialized_cacheline[addr >> CacheLine::BITS])
57  ? const_cast<byte*>(&ram[addr]) : nullptr;
58 }
59 
60 byte* CheckedRam::getRWCacheLines(unsigned addr, unsigned size) const
61 {
62  // TODO optimize
63  unsigned num = size >> CacheLine::BITS;
64  unsigned first = addr >> CacheLine::BITS;
65  for (auto i : xrange(num)) {
66  if (!completely_initialized_cacheline[first + i]) {
67  return nullptr;
68  }
69  }
70  return const_cast<byte*>(&ram[addr]);
71 }
72 
73 void CheckedRam::write(unsigned addr, const byte value)
74 {
75  unsigned line = addr >> CacheLine::BITS;
76  if (unlikely(!completely_initialized_cacheline[line])) {
77  uninitialized[line][addr & CacheLine::LOW] = false;
78  if (unlikely(uninitialized[line].none())) {
79  completely_initialized_cacheline[line] = true;
80  // This invalidates way too much stuff. But because
81  // (locally) we don't know exactly how this class ie
82  // being used in the MSXDevice, there's no easy way to
83  // figure out what exactly should be invalidated.
84  //
85  // This is anyway only a debug feature (usually it's
86  // not in use), therefor it's OK to implement this in a
87  // easy/slow way rather than complex/fast.
88  msxcpu.invalidateAllSlotsRWCache(0, 0x10000);
89  }
90  }
91  ram[addr] = value;
92 }
93 
95 {
96  ram.clear();
97  init();
98 }
99 
100 void CheckedRam::init()
101 {
102  if (umrCallback.getValue().empty()) {
103  // there is no callback function,
104  // do as if everything is initialized
105  completely_initialized_cacheline.assign(
106  completely_initialized_cacheline.size(), true);
107  uninitialized.assign(
108  uninitialized.size(), std::bitset<CacheLine::SIZE>());
109  } else {
110  // new callback function, forget about initialized areas
111  completely_initialized_cacheline.assign(
112  completely_initialized_cacheline.size(), false);
113  uninitialized.assign(
114  uninitialized.size(), getBitSetAllTrue());
115  }
116  msxcpu.invalidateAllSlotsRWCache(0, 0x10000);
117 }
118 
119 void CheckedRam::update(const Setting& setting)
120 {
121  assert(&setting == &umrCallback.getSetting());
122  (void)setting;
123  init();
124 }
125 
126 } // namespace openmsx
openmsx::CheckedRam::CheckedRam
CheckedRam(const DeviceConfig &config, const std::string &name, static_string_view description, unsigned size)
Definition: CheckedRam.cc:20
openmsx::CheckedRam::getWriteCacheLine
byte * getWriteCacheLine(unsigned addr) const
Definition: CheckedRam.cc:54
unlikely
#define unlikely(x)
Definition: likely.hh:15
openmsx::Subject::detach
void detach(Observer< T > &observer)
Definition: Subject.hh:56
xrange
constexpr auto xrange(T e)
Definition: xrange.hh:155
openmsx::CheckedRam::~CheckedRam
~CheckedRam()
Definition: CheckedRam.cc:32
openmsx::CheckedRam::read
byte read(unsigned addr)
Definition: CheckedRam.cc:37
openmsx::DeviceConfig
Definition: DeviceConfig.hh:20
utf8::unchecked::size
size_t size(std::string_view utf8)
Definition: utf8_unchecked.hh:233
MSXCPU.hh
openmsx::Ram::getName
const std::string & getName() const
Definition: Ram.cc:96
openmsx::CheckedRam::getRWCacheLines
byte * getRWCacheLines(unsigned addr, unsigned size) const
Definition: CheckedRam.cc:60
openmsx::Subject::attach
void attach(Observer< T > &observer)
Definition: Subject.hh:50
CheckedRam.hh
likely.hh
StringSetting.hh
openmsx::CheckedRam::clear
void clear()
Definition: CheckedRam.cc:94
openmsx::MSXCPU::invalidateAllSlotsRWCache
void invalidateAllSlotsRWCache(word start, unsigned size)
Invalidate the CPU its cache for the interval [start, start + size) For example MSXMemoryMapper and M...
Definition: MSXCPU.cc:183
openmsx::TclCallback::getValue
TclObject getValue() const
Definition: TclCallback.cc:35
openmsx::CheckedRam::write
void write(unsigned addr, byte value)
Definition: CheckedRam.cc:73
openmsx::TclCallback::execute
TclObject execute()
Definition: TclCallback.cc:40
openmsx::CacheLine::SIZE
constexpr unsigned SIZE
Definition: CacheLine.hh:7
openmsx::TclCallback::getSetting
StringSetting & getSetting() const
Definition: TclCallback.hh:32
openmsx::TclObject::empty
bool empty() const
Definition: TclObject.hh:169
GlobalSettings.hh
openmsx::Ram::clear
void clear(byte c=0xff)
Definition: Ram.cc:52
openmsx::CacheLine::LOW
constexpr unsigned LOW
Definition: CacheLine.hh:9
static_string_view
static_string_view
Definition: static_string_view.hh:28
openmsx::CacheLine::BITS
constexpr unsigned BITS
Definition: CacheLine.hh:6
DeviceConfig.hh
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
MSXMotherBoard.hh
xrange.hh
openmsx::CheckedRam::getReadCacheLine
const byte * getReadCacheLine(unsigned addr) const
Definition: CheckedRam.cc:48