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