Lua

概要

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


6502

概要

CPU 6502をエミュレートするモジュールです。


モジュール

モジュール名説明
6502

モジュール情報

名前説明
/reset
/nmi
/irq
addressbusアドレスバス幅:16bit、データバス幅:8bit
regs
registerctrl
memoryctrl
cpuctrl

補足




8051/8052

概要

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はアドレスバスインタフェース経由でアクセスするため、ピン操作によるアクセスはできないため。
※3LEDなどを繋いでも点灯しません。
※4P0,P1,P2,P3レジスタはラッチの操作で、実際の入出力状態は接続先に依存するが、libvdmgrはそういった接続には対応していないため。



Z80

概要

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-900/H

概要

TLCS-900H シリーズのTMP95C061BFGマイコンをエミュレートするモジュールです。


エミュレート状況

機能状況
TLCS-900/H コア
割り込みコントローラ
外部割込み制御※1
ポート機能×※2
8ビットタイマー※3
16ビットタイマー×
A/Dコンバータ※4
UART×
ウォッチドッグタイマ×
チップセレクト
ウェイトコントローラ×
スタンバイ機能×
DRAM関係×
※1NMIのみ対応、他はエッジ固定。
※2 PA1/3は機能、PA90,PA2,PB0/1/4/5/7はポート固定、その他のポートは未実装。
※3PPG,PWM未対応。
※40chのみ。

モジュール

モジュール名説明
tmp95c061bfg

モジュール情報

名前説明
fc
prescaler
/RESET
/NMI
AM
P90
PA1
PA2
PA3
PB0
PB1
PB4
PB5
PB7
CS0
CS1
CS2
CS3
EXCS
cpuctrl
registerctrl
memoryctrl

補足




TD4

概要

CPU TD4をエミュレートするモジュールです。
簡易的なアセンブラを内蔵し、ソースファイル(.asm)を指定することでアセンブル+デバッグ情報の出力します。


モジュール

モジュール名説明
td4

モジュール情報

名前説明
asm
inp0 ~ inp3
outp0 ~ outp3
addressbus
cpuctrl
registerctrl
memoryctrl

補足

命令表を見ただけですので、正しく動作しているかわかりませんが、ラーメンタイマーが正しく動作すること、入力ポートに4つのボタン、出力ポートに4つのLEDを割り当て、押したボタンに対応するLEDが点灯することを確認してあります。




GMC-4

概要

GMC-4をエミュレートするモジュールです。
簡易的なアセンブラを内蔵し、ソースファイル(.asm)を指定することでアセンブル+デバッグ情報の出力します。


モジュール

モジュール名説明
gmc-4

モジュール情報

名前説明
download
asm
buzzer
led0 ~ led6
7seg0 ~ 7seg6
cpuctrl
registerctrl
memoryctrl
soundgen
input

補足

実機が手元にないので、CPUのクロック・音は適当に設定しています。
FX-マイコンのマニュアルに書かれているサンプルのいくつかは動作を確認しました。




LED

LED

概要

LEDをエミュレートするモジュールです。


モジュール

モジュール名説明
led

モジュール情報

名前説明
pin0 ~ pin31
imagegen

補足

1モジュールにつき、最大32個まで接続可能です。




7SEG

LED

概要

7セグメントLEDをエミュレートするモジュールです。


モジュール

モジュール名説明
7seg

モジュール情報

名前説明
pin0 ~ pin31
imagegen

補足

1モジュールにつき、最大4個まで接続可能です。




SC1602BSLB/SC1602BS*B

LED

概要

キャラクタLCDモジュール SC1602BSLB/SC1602BS*Bをエミュレートするモジュールです。


モジュール

モジュール名説明
sc1602bs

モジュール情報

名前説明
DB0 ~ DB7
R/W
RS
VO
E
Vdd
imagegen

補足

仕様書に書かれている機能、待ち時間など全てをエミュレートしているつもり。




SN76489

概要

サウンドジェネレータ SN76489をエミュレートするモジュールです。


モジュール

モジュール名説明
sn76489

モジュール情報

名前説明
D0 ~ D7
soundgen



波形表示

概要

ピンの状態を波形で表示するモジュールです。


画面説明

waveform

操作説明

名前波形上
左クリックブレーク設定※1カーソルA移動
右クリックなしカーソルB移動
マウスホイール表示倍率変更
※1クリックする度に、波形の立ち上がり時にブレーク(波形赤色)、立ち下がり時にブレーク(波形青色)、変化時にブレーク(波形紫色)、ブレークなし(波形緑色)を切り替えます。

モジュール

モジュール名説明
waveform

モジュール情報

名前説明
name0 ~ name31最大8文字。
b0~ b31
registerctrl
window

補足

最大32個のピンを表示でき、ピンの状態が変化した時に実行を停止させる機能があります。

波形が非常に見づらいため、オシロスコープの表示と操作方法に変更予定。




FFT/波形表示

概要

サウンドジェネレータから出力された波形を表示するモジュールです。


画面説明

fftwave

操作説明

名前を左クリックすると、表示が切り替わります。

名前説明
表示方法FFT対数、FFTリニア、波形表示の順に切り替わります。
窓関数ハニング、ハミング、ブラックマン、矩形表示の順に切り替わります。
描画チャンネルL/Rch、R/Lch、Lch、Rch表示の順に切り替わります。

モジュール

モジュール名説明
fftwave

モジュール情報

名前説明
windowウィンドウインタフェース。
soundサウンドジェネレータインタフェース。



参考資料

概要

今回作成するにあたり、下記サイト・書籍を参考に作成しました。
大変貴重な情報を公開していただき有難うございます。