Changeset 170


Ignore:
Timestamp:
Apr 10, 2019, 3:26:36 PM (5 years ago)
Author:
chronos
Message:
  • Added: Instruction write class.
  • Added: Execute CPU in background thread.
  • Fixed: DataPrefix opcodes now working.
  • Added: Show content of registers and memory. Show total number of CPU ticks.
Location:
branches/virtualcpu4
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • branches/virtualcpu4/UCpu.pas

    r169 r170  
    99
    1010type
    11   TAddress = DWord;
     11  TOpcode = (opNop, opHalt, opCopy, opLoadConst, opJump, opJumpZero, opJumpNotZero,
     12    opJumpRel, opNeg, opClear, opLoadMem, opStoreMem, opExchg, opPush, opPop,
     13    opCall, opRet, opAdd, opAddc, opSub, opSubc, opInc, opDec, opIn, opOut, opShl,
     14    opShr, opDataPrefix8, opDataPrefix16, opDataPrefix32, opDataPrefix64,
     15    opDataSize, opAddrSize);
     16  TAddress = QWord;
    1217  PAddress = ^TAddress;
    1318
     
    2530  TOutputEvent = procedure (Port: TAddress; Value: TRegister) of object;
    2631
     32  TCpuThread = class;
     33
    2734  { TCpu }
    2835
     
    3138    FOnInput: TInputEvent;
    3239    FOnOutput: TOutputEvent;
    33     Instructions: array of TInstructionEvent;
    34     AddressSize: TBitWidth;
    35     DataSize: TBitWidth;
     40    FRunning: Boolean;
     41    FTicks: Integer;
     42    Instructions: array[TOpcode] of TInstructionEvent;
    3643    DataSizeLast: TBitWidth;
     44    DataSizePrefix: TBitWidth;
    3745    Z: Boolean;
     46    Thread: TCpuThread;
    3847    procedure InstNop;
    3948    procedure InstHalt;
     
    6170    procedure InstOut;
    6271    procedure InstShr;
     72    procedure InstShl;
    6373    procedure InstDataPrefix8;
    6474    procedure InstDataPrefix16;
     
    7383    IP: TAddress;
    7484    SP: TAddress;
     85    AddressSize: TBitWidth;
     86    DataSize: TBitWidth;
    7587    procedure Run;
    76     procedure Step;
    77     function Read8: Byte;
    78     function Read16: Word;
    79     function Read32: DWord;
    80     function Read64: QWord;
     88    procedure Step; inline;
     89    procedure Start;
     90    procedure Stop;
     91    function Read8: Byte; inline;
     92    function Read16: Word; inline;
     93    function Read32: DWord; inline;
     94    function Read64: QWord; inline;
    8195    constructor Create;
     96    property Ticks: Integer read FTicks;
     97    property Running: Boolean read FRunning;
    8298    property OnInput: TInputEvent read FOnInput write FOnInput;
    8399    property OnOutput: TOutputEvent read FOnOutput write FOnOutput;
    84100  end;
    85101
     102 { TCpuThread }
     103
     104  TCpuThread = class(TThread)
     105    Cpu: TCpu;
     106    procedure Execute; override;
     107  end;
     108
    86109implementation
     110
     111{ TCpuThread }
     112
     113procedure TCpuThread.Execute;
     114begin
     115  Cpu.Run;
     116end;
    87117
    88118{ TCpu }
     
    468498end;
    469499
     500procedure TCpu.InstShl;
     501var
     502  R: Integer;
     503begin
     504  R := Read8;
     505  case DataSize of
     506    bw8: Registers[R].B := Registers[R].B shl Read8;
     507    bw16: Registers[R].W := Registers[R].W shl Read16;
     508    bw32: Registers[R].D := Registers[R].D shl Read32;
     509    bw64: Registers[R].Q := Registers[R].Q shl Read64;
     510  end;
     511end;
     512
    470513procedure TCpu.InstDataPrefix8;
    471514begin
    472   DataSizeLast := DataSize;
    473   DataSize := bw8;
     515  DataSizePrefix := bw8;
    474516end;
    475517
    476518procedure TCpu.InstDataPrefix16;
    477519begin
    478   DataSizeLast := DataSize;
    479   DataSize := bw16;
     520  DataSizePrefix := bw16;
    480521end;
    481522
    482523procedure TCpu.InstDataPrefix32;
    483524begin
    484   DataSizeLast := DataSize;
    485   DataSize := bw32;
     525  DataSizePrefix := bw32;
    486526end;
    487527
    488528procedure TCpu.InstDataPrefix64;
    489529begin
    490   DataSizeLast := DataSize;
    491   DataSize := bw64;
     530  DataSizePrefix := bw64;
    492531end;
    493532
     
    505544begin
    506545  Terminated := False;
     546  FTicks := 0;
    507547  DataSizeLast := bwNone;
    508   DataSize := bw16;
    509   AddressSize := bw16;
    510548  IP := 0;
     549  SP := Length(Memory);
    511550  while not Terminated do
    512551    Step;
     
    517556  Opcode: Byte;
    518557begin
     558  if DataSizePrefix <> bwNone then begin
     559    DataSizeLast := DataSize;
     560    DataSize := DataSizePrefix;
     561    DataSizePrefix := bwNone;
     562  end;
    519563  Opcode := Read8;
    520   if Opcode < Length(Instructions) then Instructions[Opcode]
     564  if Opcode < Length(Instructions) then Instructions[TOpcode(Opcode)]
    521565    else raise Exception.Create('Unsupported opcode ' + IntToStr(Opcode) + ' at address ' + IntToHex(IP, 8) + '.');
    522566  if DataSizeLast <> bwNone then begin
     
    525569  end;
    526570  IP := IP mod Length(Memory);
     571  Inc(FTicks);
     572end;
     573
     574procedure TCpu.Start;
     575begin
     576  if not Running then begin
     577    Terminated := False;
     578    Thread := TCpuThread.Create(True);
     579    Thread.Cpu := Self;
     580    Thread.Start;
     581    FRunning := True;
     582  end;
     583end;
     584
     585procedure TCpu.Stop;
     586begin
     587  if Running then begin
     588    Terminated := True;
     589    Thread.Terminate;
     590    Thread.WaitFor;
     591    FreeAndNil(Thread);
     592    FRunning := False;
     593  end;
    527594end;
    528595
     
    553620constructor TCpu.Create;
    554621begin
     622  DataSize := bw16;
     623  AddressSize := bw16;
    555624  SetLength(Memory, 1000);
    556625  SetLength(Registers, 32);
    557   SetLength(Instructions, 29);
    558   Instructions[0] := InstNop;
    559   Instructions[1] := InstHalt;
    560   Instructions[2] := InstCopy;
    561   Instructions[3] := InstLoadConst;
    562   Instructions[4] := InstJump;
    563   Instructions[5] := InstJumpRel;
    564   Instructions[6] := InstLoadMem;
    565   Instructions[7] := InstStoreMem;
    566   Instructions[8] := InstClear;
    567   Instructions[9] := InstNeg;
    568   Instructions[10] := InstExchg;
    569   Instructions[11] := InstPop;
    570   Instructions[12] := InstPush;
    571   Instructions[13] := InstCall;
    572   Instructions[14] := InstRet;
    573   Instructions[15] := InstAdd;
    574   Instructions[16] := InstInc;
    575   Instructions[17] := InstDec;
    576   Instructions[18] := InstIn;
    577   Instructions[19] := InstOut;
    578   Instructions[20] := InstSub;
    579   Instructions[21] := InstShr;
    580   Instructions[22] := InstAddc;
    581   Instructions[23] := InstDataSize;
    582   Instructions[24] := InstDataPrefix8;
    583   Instructions[25] := InstDataPrefix16;
    584   Instructions[26] := InstDataPrefix32;
    585   Instructions[27] := InstDataPrefix64;
    586   Instructions[28] := InstAddrSize;
     626  Instructions[opNop] := InstNop;
     627  Instructions[opHalt] := InstHalt;
     628  Instructions[opCopy] := InstCopy;
     629  Instructions[opLoadConst] := InstLoadConst;
     630  Instructions[opJump] := InstJump;
     631  Instructions[opJumpRel] := InstJumpRel;
     632  Instructions[opLoadMem] := InstLoadMem;
     633  Instructions[opStoreMem] := InstStoreMem;
     634  Instructions[opClear] := InstClear;
     635  Instructions[opNeg] := InstNeg;
     636  Instructions[opExchg] := InstExchg;
     637  Instructions[opPop] := InstPop;
     638  Instructions[opPush] := InstPush;
     639  Instructions[opCall] := InstCall;
     640  Instructions[opRet] := InstRet;
     641  Instructions[opAdd] := InstAdd;
     642  Instructions[opAddc] := InstAddc;
     643  Instructions[opSub] := InstSub;
     644  Instructions[opInc] := InstInc;
     645  Instructions[opDec] := InstDec;
     646  Instructions[opIn] := InstIn;
     647  Instructions[opOut] := InstOut;
     648  Instructions[opShr] := InstShr;
     649  Instructions[opShl] := InstShl;
     650  Instructions[opDataSize] := InstDataSize;
     651  Instructions[opDataPrefix8] := InstDataPrefix8;
     652  Instructions[opDataPrefix16] := InstDataPrefix16;
     653  Instructions[opDataPrefix32] := InstDataPrefix32;
     654  Instructions[opDataPrefix32] := InstDataPrefix64;
     655  Instructions[opAddrSize] := InstAddrSize;
    587656end;
    588657
  • branches/virtualcpu4/UFormMain.lfm

    r169 r170  
    1 object Form1: TForm1
    2   Left = 464
    3   Height = 300
    4   Top = 302
    5   Width = 400
    6   Caption = 'Form1'
    7   ClientHeight = 300
    8   ClientWidth = 400
     1object FormMain: TFormMain
     2  Left = 384
     3  Height = 613
     4  Top = 219
     5  Width = 1178
     6  Caption = 'VirtCpu4'
     7  ClientHeight = 613
     8  ClientWidth = 1178
    99  DesignTimePPI = 120
    1010  OnCreate = FormCreate
    1111  OnDestroy = FormDestroy
     12  OnShow = FormShow
    1213  LCLVersion = '2.0.0.4'
    13   object ButtonRun: TButton
    14     Left = 72
     14  object ButtonStart: TButton
     15    Left = 984
    1516    Height = 31
    16     Top = 79
     17    Top = 8
    1718    Width = 94
    18     Caption = 'Run'
    19     OnClick = ButtonRunClick
     19    Caption = 'Start'
     20    OnClick = ButtonStartClick
    2021    TabOrder = 0
    2122  end
     23  object ButtonStop: TButton
     24    Left = 984
     25    Height = 31
     26    Top = 48
     27    Width = 94
     28    Caption = 'Stop'
     29    OnClick = ButtonStopClick
     30    TabOrder = 1
     31  end
     32  object Label1: TLabel
     33    Left = 984
     34    Height = 20
     35    Top = 96
     36    Width = 35
     37    Caption = 'Ticks:'
     38    ParentColor = False
     39  end
     40  object ListViewRegisters: TListView
     41    Left = 8
     42    Height = 592
     43    Top = 8
     44    Width = 312
     45    Anchors = [akTop, akLeft, akBottom]
     46    Columns = <   
     47      item
     48        Caption = 'Register'
     49        Width = 100
     50      end   
     51      item
     52        Width = 180
     53      end>
     54    Font.Height = -17
     55    Font.Name = 'Liberation Mono'
     56    OwnerData = True
     57    ParentFont = False
     58    TabOrder = 2
     59    ViewStyle = vsReport
     60    OnData = ListViewRegistersData
     61  end
     62  object ListViewMemory: TListView
     63    Left = 328
     64    Height = 592
     65    Top = 8
     66    Width = 648
     67    Anchors = [akTop, akLeft, akBottom]
     68    Columns = <   
     69      item
     70        Caption = 'Address'
     71        Width = 100
     72      end   
     73      item
     74        Width = 500
     75      end>
     76    Font.Height = -17
     77    Font.Name = 'Liberation Mono'
     78    OwnerData = True
     79    ParentFont = False
     80    TabOrder = 3
     81    ViewStyle = vsReport
     82    OnData = ListViewMemoryData
     83  end
     84  object Timer1: TTimer
     85    Interval = 200
     86    OnTimer = Timer1Timer
     87    left = 96
     88    top = 144
     89  end
    2290end
  • branches/virtualcpu4/UFormMain.pas

    r169 r170  
    66
    77uses
    8   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, UCpu;
     8  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
     9  ComCtrls, UCpu, UInstructionWriter;
    910
    1011type
    1112
    12   { TForm1 }
     13  { TFormMain }
    1314
    14   TForm1 = class(TForm)
    15     ButtonRun: TButton;
    16     procedure ButtonRunClick(Sender: TObject);
     15  TFormMain = class(TForm)
     16    ButtonStart: TButton;
     17    ButtonStop: TButton;
     18    Label1: TLabel;
     19    ListViewMemory: TListView;
     20    ListViewRegisters: TListView;
     21    Timer1: TTimer;
     22    procedure ButtonStartClick(Sender: TObject);
     23    procedure ButtonStopClick(Sender: TObject);
    1724    procedure FormCreate(Sender: TObject);
    1825    procedure FormDestroy(Sender: TObject);
     26    procedure FormShow(Sender: TObject);
     27    procedure ListViewMemoryData(Sender: TObject; Item: TListItem);
     28    procedure ListViewRegistersData(Sender: TObject; Item: TListItem);
     29    procedure Timer1Timer(Sender: TObject);
    1930  private
    20 
     31    procedure ReloadMemoryDump;
     32    procedure ReloadRegisterDump;
     33    procedure LoadProgram;
    2134  public
    2235    Cpu: TCpu;
     36    InstructionWriter: TInstructionWriter;
    2337  end;
    2438
    2539var
    26   Form1: TForm1;
     40  FormMain: TFormMain;
    2741
    2842implementation
     
    3044{$R *.lfm}
    3145
    32 { TForm1 }
     46const
     47  ItemsPerLine = 16;
    3348
    34 procedure TForm1.ButtonRunClick(Sender: TObject);
     49{ TFormMain }
     50
     51procedure TFormMain.ButtonStartClick(Sender: TObject);
    3552begin
    36   Cpu.Run;
     53  Cpu.Start;
    3754end;
    3855
    39 procedure TForm1.FormCreate(Sender: TObject);
     56procedure TFormMain.ButtonStopClick(Sender: TObject);
     57begin
     58  Cpu.Stop;
     59end;
     60
     61procedure TFormMain.FormCreate(Sender: TObject);
    4062begin
    4163  Cpu := TCpu.Create;
     64  Cpu.DataSize := bw16;
     65  Cpu.AddressSize := bw16;
     66  InstructionWriter := TInstructionWriter.Create;
     67  InstructionWriter.Cpu := Cpu;
    4268end;
    4369
    44 procedure TForm1.FormDestroy(Sender: TObject);
     70procedure TFormMain.FormDestroy(Sender: TObject);
    4571begin
     72  InstructionWriter.Free;
    4673  Cpu.Free;
    4774end;
    4875
     76procedure TFormMain.FormShow(Sender: TObject);
     77begin
     78  LoadProgram;
     79end;
     80
     81procedure TFormMain.ListViewMemoryData(Sender: TObject; Item: TListItem);
     82var
     83  Line: string;
     84  I: Integer;
     85begin
     86  if Item.Index < Length(Cpu.Memory) div ItemsPerLine then begin
     87    Line := '';
     88    for I := 0 to ItemsPerLine - 1 do
     89      Line := Line + IntToHex(Cpu.Memory[Item.Index * ItemsPerLine + I], 2) + ' ';
     90    Item.Caption := IntToHex(Item.Index * ItemsPerLine, 8);
     91    Item.SubItems.Add(Line);
     92  end;
     93end;
     94
     95procedure TFormMain.ListViewRegistersData(Sender: TObject; Item: TListItem);
     96begin
     97  if Item.Index < Length(Cpu.Registers) + 2 then begin
     98    if Item.Index = 0 then begin
     99      Item.Caption := 'IP';
     100      Item.SubItems.Add(IntToHex(Cpu.IP, 16));
     101    end else
     102    if Item.Index = 1 then begin
     103      Item.Caption := 'SP';
     104      Item.SubItems.Add(IntToHex(Cpu.SP, 16));
     105    end else begin
     106      Item.Caption := 'R' + IntToStr(Item.Index - 2);
     107      Item.SubItems.Add(IntToHex(Cpu.Registers[Item.Index - 2].D, 16));
     108    end;
     109  end;
     110end;
     111
     112procedure TFormMain.Timer1Timer(Sender: TObject);
     113begin
     114  Label1.Caption := 'Ticks: ' + IntToStr(Cpu.Ticks);
     115  ReloadMemoryDump;
     116  ReloadRegisterDump;
     117end;
     118
     119procedure TFormMain.ReloadMemoryDump;
     120begin
     121  ListViewMemory.Items.Count := Length(Cpu.Memory) div ItemsPerLine;
     122  ListViewMemory.Refresh;
     123end;
     124
     125procedure TFormMain.ReloadRegisterDump;
     126begin
     127  ListViewRegisters.Items.Count := Length(Cpu.Registers);
     128  ListViewRegisters.Refresh;
     129end;
     130
     131procedure TFormMain.LoadProgram;
     132var
     133  R1: Byte;
     134  R2: Byte;
     135  LabelStart: Integer;
     136begin
     137  R1 := 1;
     138  R2 := 2;
     139  with InstructionWriter do begin
     140    LoadConst(R1, 100);
     141    LoadConst(R2, 100);
     142    LabelStart := IP;
     143    Increment(R1);
     144    DataPrefix8; StoreMem(R2, R1);
     145    Jump(LabelStart);
     146    Halt;
     147  end;
     148end;
     149
     150
    49151end.
    50152
  • branches/virtualcpu4/virtucpu4.lpi

    r169 r170  
    3232      </Item1>
    3333    </RequiredPackages>
    34     <Units Count="3">
     34    <Units Count="4">
    3535      <Unit0>
    3636        <Filename Value="virtucpu4.lpr"/>
     
    4040        <Filename Value="UFormMain.pas"/>
    4141        <IsPartOfProject Value="True"/>
    42         <ComponentName Value="Form1"/>
     42        <ComponentName Value="FormMain"/>
     43        <HasResources Value="True"/>
    4344        <ResourceBaseClass Value="Form"/>
    4445      </Unit1>
     
    4748        <IsPartOfProject Value="True"/>
    4849      </Unit2>
     50      <Unit3>
     51        <Filename Value="UInstructionWriter.pas"/>
     52        <IsPartOfProject Value="True"/>
     53      </Unit3>
    4954    </Units>
    5055  </ProjectOptions>
  • branches/virtualcpu4/virtucpu4.lpr

    r169 r170  
    1717  Application.Scaled:=True;
    1818  Application.Initialize;
    19   Application.CreateForm(TForm1, Form1);
     19  Application.CreateForm(TFormMain, FormMain);
    2020  Application.Run;
    2121end.
Note: See TracChangeset for help on using the changeset viewer.