|
|
nono 1.7.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// MPU (共通部分)
//
// Device
// | +-----------+
// +--| MPUDevice | (全 MPU の共通部)
// +-----------+
// |
// | +---------------+
// +--| MainMPUDevice | (680x0/88xx0 の共通部)
// | +---------------+
// | |
// | +-- MPU680x0Device
// | +-- MPU88xx0Device
// |
// +-- MPU64180Device
#include "mpu.h"
#include "config.h"
#include "debugger.h"
#include "event.h"
#include "mainbus.h"
#include "scheduler.h"
#include "syncer.h"
//
// 全 MPU 共通
//
// コンストラクタ
MPUDevice::MPUDevice(uint objid_)
: inherited(objid_)
{
}
// デストラクタ
MPUDevice::~MPUDevice()
{
}
// 初期化
bool
MPUDevice::Init()
{
debugger = GetDebugger();
auto evman = GetEventManager();
exec_event = evman->Regist(this, NULL, "MPU Execute");
return true;
}
void
MPUDevice::ResetHard(bool poweron)
{
inherited::ResetHard(poweron);
last_vector = -1;
}
void
MPUDevice::PowerOff()
{
scheduler->StopEvent(exec_event);
}
int32
MPUDevice::GetAndResetLastVector()
{
auto vector = last_vector;
last_vector = -1;
return vector;
}
//
// メイン MPU (680x0/88xx0) 共通部
//
// コンストラクタ
MainMPUDevice::MainMPUDevice()
: inherited(OBJ_MPU)
{
}
// デストラクタ
MainMPUDevice::~MainMPUDevice()
{
}
// 初期化
bool
MainMPUDevice::Init()
{
if (inherited::Init() == false) {
return false;
}
mainbus = GetMainbusDevice();
syncer = GetSyncer();
// MPU クロック。
// 設定の "mpu-clock" は MHz 単位だが、変数 clock_khz は kHz 単位。
int val;
const ConfigItem& item = gConfig->Find("mpu-clock");
if (item.TryFixedDecimal(&val, 3) == false) {
item.Err();
return false;
}
clock_khz = (uint)val;
// 1MHz 未満はエラー。実際 10MHz 未満でもいい気がするけど
if (clock_khz < 1000) {
item.Err();
return false;
}
clock_tsec = 1_msec / clock_khz;
if (clock_tsec < 1) {
item.Err("Clock speed too high");
return false;
}
// キャッシュを無効にするテスト用。
force_disable_dcache = gConfig->Find("mpu-force-disable-dcache").AsBool();
force_disable_icache = gConfig->Find("mpu-force-disable-icache").AsBool();
scheduler->ConnectMessage(MessageID::MPU_TRACE_MAIN, this,
ToMessageCallback(&MainMPUDevice::TraceMessage));
return true;
}
// MPU トレース状態設定要求メッセージ
void
MainMPUDevice::TraceMessage(MessageID msgid, uint32 arg)
{
// リセット中は SetTrace しない
if (resetting) {
return;
}
// デバッガから MPU のトレース状態を設定してくれと言われた
SetTrace((bool)arg);
}
void
MainMPUDevice::ChangeState(uint32 new_state)
{
// new_mode (CPU_STATE_*) と
// NotifyCPUMode() の引数 Syncer::SYNCMODE_CPU_* は
// 実は同じ値なのでそのまま渡してよいことにする。
static_assert(CPU_STATE_NORMAL == Syncer::SYNCMODE_CPU_NORMAL, "");
static_assert(CPU_STATE_STOP == Syncer::SYNCMODE_CPU_STOP, "");
static_assert(CPU_STATE_HALT == Syncer::SYNCMODE_CPU_HALT, "");
if (cpu_state != new_state) {
cpu_state = new_state;
// スケジューラに通知
syncer->NotifyCPUMode(cpu_state);
}
}
// Round Mode (モニタ表示用)
/*static*/ const char * const
MainMPUDevice::rmstr[4] = {
"Near",
"Zero",
"Minus",
"Plus",
};
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.