Annotation of nono/vm/bankram.cpp, revision 1.1.1.7

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.