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