|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2023 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // Nereid バンクメモリ
9: //
10:
11: // バンクメモリはロングワード単位でホストバイトオーダ配置なので、
12: // バイトアクセス、ワードアクセス時は HLB(), HLW() マクロを使用のこと。
13:
14: #include "bankram.h"
15: #include "config.h"
1.1.1.6 root 16: #include "mpu.h"
1.1 root 17:
18: // コンストラクタ
1.1.1.3 root 19: BankRAMDevice::BankRAMDevice(uint objid_, int ram_size_MB)
1.1 root 20: : inherited(objid_)
21: {
22: // ram_size_MB は正数のみ。負数は親側で処理する。
23: assert(ram_size_MB >= 0);
24:
25: ram_size = ram_size_MB * 1024 * 1024;
26: // 初期化は Init() で行う
27: }
28:
29: // デストラクタ
30: BankRAMDevice::~BankRAMDevice()
31: {
32: }
33:
34: // 初期化
35: bool
36: BankRAMDevice::Init()
37: {
1.1.1.5 root 38: ram.reset(new(std::nothrow) uint8[ram_size]);
39: if ((bool)ram == false) {
1.1.1.7 ! root 40: warnx("Could not allocate %u bytes at %s", ram_size, __method__);
1.1.1.5 root 41: return false;
42: }
1.1 root 43:
1.1.1.7 ! root 44: wait = busdata::Wait(1 * mpu->GetClock_tsec());
1.1.1.6 root 45:
1.1 root 46: return true;
47: }
48:
49: // 電源オン/リセット
50: void
51: BankRAMDevice::ResetHard(bool poweron)
52: {
53: if (poweron) {
54: // ノイズで埋めたいがとりあえず。
55: memset(&ram[0], 0, ram_size);
56: }
57:
58: // リセットでクリアされる。
59: SetPage(0);
1.1.1.2 root 60:
1.1.1.3 root 61: memset(&accstat_read[0], 0, AccStat::BANKLEN);
62: memset(&accstat_write[0], 0, AccStat::BANKLEN);
1.1 root 63: }
64:
65: inline uint32
66: BankRAMDevice::Decoder(uint32 addr) const
67: {
68: return pageaddr + (addr & 0xffff);
69: }
70:
1.1.1.2 root 71: busdata
1.1.1.3 root 72: BankRAMDevice::Read(busaddr addr)
1.1 root 73: {
1.1.1.3 root 74: uint32 offset = Decoder(addr.Addr());
75: busdata data;
1.1 root 76:
1.1.1.3 root 77: accstat_read[offset >> AccStat::SHIFT] = AccStat::READ;
1.1 root 78:
1.1.1.3 root 79: data = *(uint32 *)&ram[offset & ~3U];
80: putlog(4, "$%06x ($%06x) -> $%08x", addr.Addr(), offset, data.Data());
1.1.1.6 root 81: data |= wait;
1.1.1.3 root 82: data |= BusData::Size4;
1.1 root 83: return data;
84: }
85:
1.1.1.2 root 86: busdata
1.1.1.3 root 87: BankRAMDevice::Write(busaddr addr, uint32 data)
1.1 root 88: {
1.1.1.3 root 89: uint32 offset = Decoder(addr.Addr());
90: uint32 reqsize = addr.GetSize();
91: uint32 datasize = std::min(4 - (offset & 3U), reqsize);
92:
93: accstat_write[offset >> AccStat::SHIFT] = AccStat::WRITE;
94:
95: if (datasize == 4) {
96: putlog(3, "$%06x ($%06x) <- $%08x", addr.Addr(), offset, data);
97: *(uint32 *)&ram[offset] = data;
98: } else if (datasize == 1) {
99: data >>= (reqsize - datasize) * 8;
100: putlog(3, "$%06x ($%06x) <- $%02x", addr.Addr(), offset, data);
101: ram[HLB(offset)] = data;
102: } else {
103: data >>= (reqsize - datasize) * 8;
104: putlog(3, "$%06x ($%06x) <- $%0*x", addr.Addr(), offset,
105: datasize * 2, data);
106: for (int i = datasize - 1; i >= 0; i--) {
107: ram[HLB(offset + i)] = data;
108: data >>= 8;
109: }
110: }
1.1 root 111:
1.1.1.6 root 112: busdata r = wait;
1.1.1.3 root 113: r |= BusData::Size4;
114: return r;
1.1 root 115: }
116:
1.1.1.2 root 117: busdata
1.1.1.3 root 118: BankRAMDevice::Peek1(uint32 addr)
1.1 root 119: {
120: uint32 offset = Decoder(addr);
121: return ram[HLB(offset)];
122: }
123:
1.1.1.2 root 124: bool
1.1.1.3 root 125: BankRAMDevice::Poke1(uint32 addr, uint32 data)
1.1 root 126: {
127: if ((int32)data >= 0) {
128: uint32 offset = Decoder(addr);
129: ram[HLB(offset)] = data;
130: }
1.1.1.2 root 131: return true;
1.1 root 132: }
133:
134: void
135: BankRAMDevice::SetPage(uint32 page_)
136: {
137: page = page_;
138: // XXX 4MB の時の折返し確認
139: pageaddr = (page << 16) & (ram_size - 1);
140:
141: putlog(2, "Page <- $%02x", page);
142: }
1.1.1.2 root 143:
144: void
145: BankRAMDevice::FetchAccStat(uint8 *acc)
146: {
1.1.1.3 root 147: // 要素が8バイトと分かっていればこれだけで済む。
148: static_assert(AccStat::BANKLEN == 8, "");
149:
1.1.1.2 root 150: // R|W をマージしながらコピー。
1.1.1.3 root 151: uint64 tmp;
152: tmp = *(uint64 *)&accstat_read[0];
153: tmp |= *(uint64 *)&accstat_write[0];
154: *(uint64 *)acc = tmp;
1.1.1.2 root 155:
156: // 読んだのでリセット。
1.1.1.3 root 157: memset(&accstat_read[0], 0, AccStat::BANKLEN);
158: memset(&accstat_write[0], 0, AccStat::BANKLEN);
1.1.1.2 root 159: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.