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