Lua 5.4.3で、以下の機能を持つモジュールを作成することが可能です。
| 関数名 | 説明 |
|---|---|
| vdmod_setMemoryInfo | メモリーウィンドウに表示する場合、メモリーに関する情報を設定します。 この関数は起動時に呼ぶ必要があります。 |
| vdmod_setCpuCtrlInfo | ブレークポイント数の設定と、CPUから見たメモリー空間を設定します。 この関数は起動時に呼ぶ必要があります。 |
| vdmod_addRegister | レジスタウィンドウに表示する内容を追加します。 親子関係の指定が可能。 この関数は起動時に呼ぶ必要があります。 |
| vdmod_stopClockGen | クロックジェネレータを停止(デバッガを停止状態へ遷移)します。 停止条件を指定することが可能です。 |
| vdmod_attachClockEvent | 半クロック単位で動作するクロックイベントを追加、指定クロック経過後にonEventProcessイベントを発生させます。 最大8個動かすことができ、0番目のクロックイベントは最優先(主にI/O制御用)で動作します。 既に追加している状態でこの関数を呼ぶと、再設定します。 |
| vdmod_detachClockEvent | 追加したクロックイベントを取り外します。 |
| vdmod_readPin | 入力ピンの状態を読みます。 |
| vdmod_writePin | 出力ピンへ状態を出力します。 |
| vdmod_readAddressBus | 外部のアドレスバスからデータを読み込みます。 データ幅はコンフィグファイルで指定したものになります。 |
| vdmod_writeAddressBus | 外部のアドレスバスへデータを書き込みます。 データ幅は8/16/32から選択します。 |
| vdmod_writeLog | デバッガのログへ文字列を書き込みます。 エラー・警告・情報アイコンを指定する時は、エスケープシーケンスを使用します。 |
| 関数名 | 説明 |
|---|---|
| onBuildComplete | コンフィグファイルから環境の構築が完了した時に通知されます。 |
| onDestroy | 環境が破棄された時に通知されます。 |
| onReset | リセットされた時に通知されます。 |
| onStart | 動作開始時に通知されます。 |
| onStop | 動作停止時に通知されます。 |
| onWritePin | 入力ピンの状態に変化があった時に通知されます。 |
| onEventProcess | vdmod_attachClockEventで指定したクロックが経過した時に通知されます。 |
| onGetInstAddress | 命令を実行しているアドレスを取得する時に通知されます。 |
| onSetInstAddress | 命令を実行するアドレスを設定する時に通知されます。 |
| onSetBreakpoint | ブレークポイント設定時に通知されます。 |
| onDeleteBreakpoint | ブレークポイント破棄時に通知されます。 |
| onStepIn | ステップイン実行時に通知されます。 |
| onStepOver | ステップアウト実行時に通知されます。 |
| onCreateInstString | 指定アドレスの文字列を生成する時に通知されます。 |
| onGetRegister | レジスター取得時に通知されます。 |
| onSetRegister | レジスター設定時に通知されます。 |
| onReadAddressBus | 内部アドレスバスからデータを読み込む時に通知されます。 |
| onWriteAddressBus | 内部アドレスバスへデータを書き込む時に通知されます。 |
Luaの処理が速いらしいので対応してみました。
どの程度のパフォーマンスがでるか未確認ですが、この言語を初めて使用してみましたので、とりあえずTD4のLua版を作成しました。
Luaを知ったのが数か月前で、プログラムを組んだのが初めてなので使用方法が正しいか分かりませんが、ソースは以下となります。
m_clockFreq = 0 -- クロック周波数
m_baseClock = 0 -- ベースクロック
m_breakFlag = 0 -- 停止フラグ(bit1:ブレークポイント, bit0:ステップイン・アウト実行)
m_bkpt = -1 -- ブレークポイント(-1 時は無効)
m_regPC = 0 -- プログラムカウンタ
m_regA = 0 -- A レジスタ
m_regB = 0 -- B レジスタ
m_regC = 0 -- C フラグ
m_regClock = 1 -- クロック数
m_mnemonic = { -- ニーモニック
[0] = "ADD A, ",
[1] = "MOV A, B",
[2] = "IN A",
[3] = "MOV A, ",
[4] = "MOV B, A",
[5] = "ADD B, ",
[6] = "IN B",
[7] = "MOV B, ",
[8] = "DB 0x",
[9] = "OUT B",
[10] = "DB 0x",
[11] = "OUT %",
[12] = "DB 0x",
[13] = "DB 0x",
[14] = "JNC ",
[15] = "JMP ",
}
m_mnemonicType = { -- ニーモニック引数種類(0:引数なし, 1:2進数(4bit), 2:10進数(4bit), 3:16進数(4bit), 4:16進数(8bit))
[0] = 2,
[1] = 0,
[2] = 0,
[3] = 2,
[4] = 0,
[5] = 2,
[6] = 0,
[7] = 2,
[8] = 4,
[9] = 0,
[10] = 4,
[11] = 1,
[12] = 4,
[13] = 4,
[14] = 3,
[15] = 3,
}
m_inst = { -- 命令処理
-- --------------------------------
-- ADD A, Im
-- --------------------------------
[0] = function(opcode)
value = m_regA + (opcode & 15)
m_regA = value & 15
m_regC = value >> 4
end,
-- --------------------------------
-- MOV A, B
-- --------------------------------
[1] = function(opcode)
m_regA = m_regB
m_regC = 0
end,
-- --------------------------------
-- IN A
-- --------------------------------
[2] = function(opcode)
m_regA = (vdmod_readPin(4) ) |
(vdmod_readPin(5)<<1) |
(vdmod_readPin(6)<<2) |
(vdmod_readPin(7)<<3)
m_regC = 0
end,
-- --------------------------------
-- MOV A, Im
-- --------------------------------
[3] = function(opcode)
m_regA = opcode & 15
m_regC = value >> 4
end,
-- --------------------------------
-- MOV B, A
-- --------------------------------
[4] = function(opcode)
m_regB = m_regA
m_regC = 0
end,
-- --------------------------------
-- ADD B, Im
-- --------------------------------
[5] = function(opcode)
value = m_regB + (opcode & 15)
m_regB = value & 15
m_regC = value >> 4
end,
-- --------------------------------
-- IN B
-- --------------------------------
[6] = function(opcode)
m_regB = (vdmod_readPin(4) ) |
(vdmod_readPin(5)<<1) |
(vdmod_readPin(6)<<2) |
(vdmod_readPin(7)<<3)
m_regC = 0
end,
-- --------------------------------
-- MOV B, Im
-- --------------------------------
[7] = function(opcode)
m_regB = opcode & 15
m_regC = value >> 4
end,
-- --------------------------------
-- OUT B
-- --------------------------------
[9] = function(opcode)
vdmod_writePin(0, m_regB &1)
vdmod_writePin(1, (m_regB>>1)&1)
vdmod_writePin(2, (m_regB>>2)&1)
vdmod_writePin(3, (m_regB>>3)&1)
m_regC = 0
end,
-- --------------------------------
-- OUT Im
-- --------------------------------
[11] = function(opcode)
vdmod_writePin(0, opcode &1)
vdmod_writePin(1, (opcode>>1)&1)
vdmod_writePin(2, (opcode>>2)&1)
vdmod_writePin(3, (opcode>>3)&1)
m_regC = 0
end,
-- --------------------------------
-- JNC Im
-- --------------------------------
[14] = function(opcode)
if m_regC == 0 then
m_regPC = opcode & 15
else
m_regC = 0
end
end,
-- --------------------------------
-- JMP Im
-- --------------------------------
[15] = function(opcode)
m_regPC = opcode & 15
m_regC = 0
end,
-- --------------------------------
-- 未定義命令
-- --------------------------------
[8] = function(opcode) vdmod_stopClockGen(3) end,
[10] = function(opcode) vdmod_stopClockGen(3) end,
[12] = function(opcode) vdmod_stopClockGen(3) end,
[13] = function(opcode) vdmod_stopClockGen(3) end,
}
vdmod_setCpuCtrlInfo(1, 0, 15)
vdmod_setMemoryInfo("memory", 0, 15)
vdmod_addRegister("PC", 4)
vdmod_addRegister("A", 4)
vdmod_addRegister("B", 4)
vdmod_addRegister("C", 1)
vdmod_addRegister("CLOCK", 10)
-- ------------------------------------------------
-- 構築完了通知
-- ------------------------------------------------
function onBuildComplete(clockFreq)
m_clockFreq = clockFreq
m_baseClock = clockFreq // m_regClock
end
-- ------------------------------------------------
-- 破棄通知
-- ------------------------------------------------
function onDestroy()
end
-- ------------------------------------------------
-- リセット通知
-- ------------------------------------------------
function onReset(hard)
m_breakFlag = m_breakFlag & 2
m_regPC = 0
m_regA = 0
m_regB = 0
m_regC = 0
vdmod_attachClockEvent(1, 1)
vdmod_writePin(0, 0)
vdmod_writePin(1, 0)
vdmod_writePin(2, 0)
vdmod_writePin(3, 0)
end
-- ------------------------------------------------
-- 動作開始通知
-- ------------------------------------------------
function onStart()
end
-- ------------------------------------------------
-- 動作停止通知
-- ------------------------------------------------
function onStop()
end
-- ------------------------------------------------
-- ピン書き込み通知
-- ------------------------------------------------
function onWritePin(pin, value)
end
-- ------------------------------------------------
-- イベント処理
-- ------------------------------------------------
function onEventProcess(index)
-- 命令実行
opcode = vdmod_readAddressBus(m_regPC)
m_regPC = (m_regPC + 1) & 15
m_inst[opcode>>4](opcode)
-- 停止処理
if m_breakFlag ~= 0 then
if (m_breakFlag & 1) == 1 then -- ステップイン・アウト
m_breakFlag = m_breakFlag & ~1
vdmod_stopClockGen(1)
elseif m_regPC == m_bkpt then -- ブレークポイント
vdmod_stopClockGen(2)
end
end
return m_baseClock
end
-- ------------------------------------------------
-- インストラクションアドレス取得通知
-- ------------------------------------------------
function onGetInstAddress()
return m_regPC
end
-- ------------------------------------------------
-- インストラクションアドレス取得通知
-- ------------------------------------------------
function onSetInstAddress(address)
m_regPC = address & 15
end
-- ------------------------------------------------
-- ブレークポイント設定通知
-- ------------------------------------------------
function onSetBreakpoint(address)
-- ブレークポイント設定中なら無視
if (m_breakFlag & 2) == 2 then
return false
end
m_breakFlag = m_breakFlag | 2
m_bkpt = address
return true
end
-- ------------------------------------------------
-- ブレークポイント解除通知
-- ------------------------------------------------
function onDeleteBreakpoint(address)
-- ブレークポイント解除中なら無視
if (m_breakFlag & 2) == 0 then
return false
end
m_breakFlag = m_breakFlag & ~2
m_bkpt = -1
return true
end
-- ------------------------------------------------
-- ステップイン通知
-- ------------------------------------------------
function onStepIn()
m_breakFlag = m_breakFlag | 1
end
-- ------------------------------------------------
-- ステップオーバー通知
-- ------------------------------------------------
function onStepOver()
m_breakFlag = m_breakFlag | 1
end
-- ------------------------------------------------
-- 指定アドレスの命令文字列作成通知
-- ------------------------------------------------
function onCreateInstString(address)
opcode = vdmod_readAddressBus(address&15)
inst = opcode >> 4
str = string.format("%X %02X %s", address, opcode, m_mnemonic[inst])
type = m_mnemonicType[inst]
if type == 1 then -- bit
str = str .. ((opcode>>3)&1) .. ((opcode>>2)&1) .. ((opcode>>1)&1) .. (opcode&1)
elseif type == 2 then -- 4bit
str = str .. (opcode&15)
elseif type == 3 then -- address
str = str .. string.format("%X", opcode&15)
elseif type == 4 then -- 8bit
str = str .. string.format("%02X", opcode)
end
return 1, str
end
-- ------------------------------------------------
-- レジスタ取得通知
-- ------------------------------------------------
function onGetRegister(index)
if index == 0 then
return m_regPC
elseif index == 1 then
return m_regA
elseif index == 2 then
return m_regB
elseif index == 3 then
return m_regC
else
return m_regClock
end
end
-- ------------------------------------------------
-- レジスタ設定通知
-- ------------------------------------------------
function onSetRegister(index, value)
if index == 0 then
m_regPC = value & 15
elseif index == 1 then
m_regA = value & 15
elseif index == 2 then
m_regB = value & 15
elseif index == 3 then
m_regC = value & 1
else
if value < 1 then
value = 1
elseif value > 1000 then
value = 1000
end
m_regClock = value
m_baseClock = m_clockFreq // m_regClock
vdmod_attachClockEvent(1, m_baseClock)
end
end
-- ------------------------------------------------
-- アドレスバス読み込み通知
-- ------------------------------------------------
function onReadAddressBus(address)
return vdmod_readAddressBus(address)
end
-- ------------------------------------------------
-- アドレスバス書き込み通知
-- ------------------------------------------------
function onWriteAddressBus(address, value, size)
vdmod_writeAddressBus(address, value, size)
end
vdmgr 0.2.4をダウンロードするとTD4のLua版が既に"script/td4.lua"にあるので、このファイルをconfigへコピーすることで動作確認が行えます(システム名、TD4(Lua))。
また、汎用ロジックICの74HC08(ソースはscript以下)程度なら、以下のような短いソースで実現可能です。
-- pin3 = pin1 and pin2
-- pin6 = pin4 and pin5
-- pin8 = pin9 and pin10
-- pin11 = pin12 and pin13
function updatePin()
vdmod_writePin(3, vdmod_readPin(1) & vdmod_readPin(2))
vdmod_writePin(6, vdmod_readPin(4) & vdmod_readPin(5))
vdmod_writePin(8, vdmod_readPin(9) & vdmod_readPin(10))
vdmod_writePin(11, vdmod_readPin(12) & vdmod_readPin(13))
end
function onReset(hard)
updatePin()
end
function onStop(hard)
updatePin()
end
function onWritePin(pin, value)
vdmod_attachClockEvent(0, 1)
end
function onEventProcess(index)
updatePin()
end
CPU 6502をエミュレートするモジュールです。
| モジュール名 | 説明 |
|---|---|
| 6502 |
| 名前 | 説明 |
|---|---|
| /reset | |
| /nmi | |
| /irq | |
| addressbus | アドレスバス幅:16bit、データバス幅:8bit |
| regs | |
| registerctrl | |
| memoryctrl | |
| cpuctrl |
MCS-51アーキテクチャのCPU 8051/8052をエミュレートするモジュールです。
| モジュール名 | 説明 |
|---|---|
| 8051 | 内蔵ROM:4KB,内蔵RAM:128Byte |
| 8052 | 内蔵ROM:8KB,内蔵RAM:256Byte,タイマ2 |
| 名前 | 説明 |
|---|---|
| download | |
| P2 | |
| RST | |
| /EA | |
| P0.0 ~ P0.7 | |
| P1.0 ~ P1.7 | |
| P2.0 ~ P2.7 | |
| P3.0 ~ P3.7 | |
| code | |
| data | |
| cpuctrl | |
| registerctrl | |
| memoryctrl |
以下の制限があります。
| ※1 | 外部RAMのみ使用している時に、MOVX A,@Ri, MOVX @Ri,Aを使用する場合、コントロールのP2へ指定したビット以外は汎用のポートとして使用可能。 |
| ※2 | 外部ROM,RAMはアドレスバスインタフェース経由でアクセスするため、ピン操作によるアクセスはできないため。 |
| ※3 | LEDなどを繋いでも点灯しません。 |
| ※4 | P0,P1,P2,P3レジスタはラッチの操作で、実際の入出力状態は接続先に依存するが、libvdmgrはそういった接続には対応していないため。 |
CPU Z80をエミュレートするモジュールです。
| モジュール名 | 説明 |
|---|---|
| z80 |
| 名前 | 説明 |
|---|---|
| download | |
| P2 | |
| RST | |
| /EA | |
| P0.0 ~ P0.7 | |
| P1.0 ~ P1.7 | |
| P2.0 ~ P2.7 | |
| P3.0 ~ P3.7 | |
| code | |
| data | |
| cpuctrl | |
| registerctrl | |
| memoryctrl |
TLCS-900H シリーズのTMP95C061BFGマイコンをエミュレートするモジュールです。
| 機能 | 状況 |
|---|---|
| TLCS-900/H コア | ○ |
| 割り込みコントローラ | ○ |
| 外部割込み制御 | △※1 |
| ポート機能 | ×※2 |
| 8ビットタイマー | △※3 |
| 16ビットタイマー | × |
| A/Dコンバータ | △※4 |
| UART | × |
| ウォッチドッグタイマ | × |
| チップセレクト | ○ |
| ウェイトコントローラ | × |
| スタンバイ機能 | × |
| DRAM関係 | × |
| ※1 | NMIのみ対応、他はエッジ固定。 |
| ※2 | PA1/3は機能、PA90,PA2,PB0/1/4/5/7はポート固定、その他のポートは未実装。 |
| ※3 | PPG,PWM未対応。 |
| ※4 | 0chのみ。 |
| モジュール名 | 説明 |
|---|---|
| tmp95c061bfg |
| 名前 | 説明 |
|---|---|
| fc | |
| prescaler | |
| /RESET | |
| /NMI | |
| AM | |
| P90 | |
| PA1 | |
| PA2 | |
| PA3 | |
| PB0 | |
| PB1 | |
| PB4 | |
| PB5 | |
| PB7 | |
| CS0 | |
| CS1 | |
| CS2 | |
| CS3 | |
| EXCS | |
| cpuctrl | |
| registerctrl | |
| memoryctrl |
CPU TD4をエミュレートするモジュールです。
簡易的なアセンブラを内蔵し、ソースファイル(.asm)を指定することでアセンブル+デバッグ情報の出力します。
| モジュール名 | 説明 |
|---|---|
| td4 |
| 名前 | 説明 |
|---|---|
| asm | |
| inp0 ~ inp3 | |
| outp0 ~ outp3 | |
| addressbus | |
| cpuctrl | |
| registerctrl | |
| memoryctrl |
命令表を見ただけですので、正しく動作しているかわかりませんが、ラーメンタイマーが正しく動作すること、入力ポートに4つのボタン、出力ポートに4つのLEDを割り当て、押したボタンに対応するLEDが点灯することを確認してあります。
GMC-4をエミュレートするモジュールです。
簡易的なアセンブラを内蔵し、ソースファイル(.asm)を指定することでアセンブル+デバッグ情報の出力します。
| モジュール名 | 説明 |
|---|---|
| gmc-4 |
| 名前 | 説明 |
|---|---|
| download | |
| asm | |
| buzzer | |
| led0 ~ led6 | |
| 7seg0 ~ 7seg6 | |
| cpuctrl | |
| registerctrl | |
| memoryctrl | |
| soundgen | |
| input |
実機が手元にないので、CPUのクロック・音は適当に設定しています。
FX-マイコンのマニュアルに書かれているサンプルのいくつかは動作を確認しました。
LEDをエミュレートするモジュールです。
| モジュール名 | 説明 |
|---|---|
| led |
| 名前 | 説明 |
|---|---|
| pin0 ~ pin31 | |
| imagegen |
1モジュールにつき、最大32個まで接続可能です。
7セグメントLEDをエミュレートするモジュールです。
| モジュール名 | 説明 |
|---|---|
| 7seg |
| 名前 | 説明 |
|---|---|
| pin0 ~ pin31 | |
| imagegen |
1モジュールにつき、最大4個まで接続可能です。

キャラクタLCDモジュール SC1602BSLB/SC1602BS*Bをエミュレートするモジュールです。
| モジュール名 | 説明 |
|---|---|
| sc1602bs |
| 名前 | 説明 |
|---|---|
| DB0 ~ DB7 | |
| R/W | |
| RS | |
| VO | |
| E | |
| Vdd | |
| imagegen |
仕様書に書かれている機能、待ち時間など全てをエミュレートしているつもり。
サウンドジェネレータ SN76489をエミュレートするモジュールです。
| モジュール名 | 説明 |
|---|---|
| sn76489 |
| 名前 | 説明 |
|---|---|
| D0 ~ D7 | |
| soundgen |
ピンの状態を波形で表示するモジュールです。
| 名前 | 波形上 | |
|---|---|---|
| 左クリック | ブレーク設定※1 | カーソルA移動 |
| 右クリック | なし | カーソルB移動 |
| マウスホイール | 表示倍率変更 | ← |
| ※1 | クリックする度に、波形の立ち上がり時にブレーク(波形赤色)、立ち下がり時にブレーク(波形青色)、変化時にブレーク(波形紫色)、ブレークなし(波形緑色)を切り替えます。 |
| モジュール名 | 説明 |
|---|---|
| waveform |
| 名前 | 説明 |
|---|---|
| name0 ~ name31 | 最大8文字。 |
| b0~ b31 | |
| registerctrl | |
| window |
最大32個のピンを表示でき、ピンの状態が変化した時に実行を停止させる機能があります。
波形が非常に見づらいため、オシロスコープの表示と操作方法に変更予定。
サウンドジェネレータから出力された波形を表示するモジュールです。
名前を左クリックすると、表示が切り替わります。
| 名前 | 説明 |
|---|---|
| 表示方法 | FFT対数、FFTリニア、波形表示の順に切り替わります。 |
| 窓関数 | ハニング、ハミング、ブラックマン、矩形表示の順に切り替わります。 |
| 描画チャンネル | L/Rch、R/Lch、Lch、Rch表示の順に切り替わります。 |
| モジュール名 | 説明 |
|---|---|
| fftwave |
| 名前 | 説明 |
|---|---|
| window | ウィンドウインタフェース。 |
| sound | サウンドジェネレータインタフェース。 |
今回作成するにあたり、下記サイト・書籍を参考に作成しました。
大変貴重な情報を公開していただき有難うございます。