// rev 1.00
#pragma once
#include "CommonBus.h"

struct VM1_QBUS_WIRES
{
	uint64_t plx;               //wire[33:0]    // main microcode matrix output
	//input wire
	bool    pin_irq[4];         // radial interrupt requests, pin_irq[0] == pin_virq// vectored interrupt request
	bool    pin_dclo;           // processor reset
	bool    pin_aclo;           // power fail notification

	uint16_t pin_ad_in;         // data bus input
	bool    pin_sync_in;        // address strobe input
	bool    pin_dmgi;           // bus granted input
	bool    dma_in;             //
	bool    pin_dout_in;
	bool    pin_din_in;
	bool    pin_rply_in;
	bool    pin_init_in;
	bool    pin_dmr_in;
	bool    pin_sack_in;

	//output wire
	bool    pin_ctrl_ena;
	bool    pin_bsy_out;
	bool    pin_init_out;


	uint16_t pli;               //wire[10:0]    // interrupt priority encode matrix output
	bool    exc_uop;            //wire          // Undefined opcode found
	bool    exc_oat;            //wire          // Odd address trap detector
	bool    qbus_tena;          //wire          //
	bool    ir_clr;             //wire          //
	bool    ir_seq_rc;          //wire          //
	bool    plm_stb_rc;         //wire          // plm_register strobe source
	bool    plm_ena_fc;         //wire          //
	uint16_t plop;              //wire[7:0]
	bool    uplr_stb;           //wire          //
	uint8_t tplm_rc;            //wire[3:1]     //
	bool    reset_rc;           //wire          //
	bool    abort_rc;           //wire          //
	bool    mjres_rc;           //wire          //
	bool    sel_out;            //wire          //
	bool    dmr_out;            //wire          //
	bool    qbus_done;          //wire          //
	bool    rply_ack_fc;        //wire          //
	bool    din_done;           //wire          //
	bool    dmr_req_rc;
	bool    dout_req_rc;
	bool    dout_start;
	bool    qbus_flag_rc;       //wire          //
	bool    sync_stb;           //wire          //
	bool    sync_fedge;         //wire          //
	bool    qbus_nosr_rc;       //wire          //
	uint16_t x;                 //wire[15:0]    // X bus
	uint16_t y;                 //wire[15:0]    // Y bus
	uint8_t flag;               //wire[3:0]     //
	bool    au_astb;            //wire          //
	bool    au_qstbx;           //wire          //
	uint16_t rsw;                               // register select
	bool    vc_vsel, vc_csel;
	uint8_t alu_shift, shift_code;
	bool    au_swapX;
	bool    wait_areg_free, wait_write_complete;

	//ВЕ таймер
	bool    tve_reset;          //wire
	bool    tve_tclk128;        //wire          // prescaler /128 output
	bool    pin_spclk;          //wire          // external event on SP
	bool    tve_zero;           //wire          // timer counter zero value
	bool    tve_back;           //wire          // timer capture load

	void clear()
	{
		memset(this, 0, sizeof(VM1_QBUS_WIRES));
	};
	VM1_QBUS_WIRES &operator = (const VM1_QBUS_WIRES &src)
	{
		memcpy(this, &src, sizeof(VM1_QBUS_WIRES));
		return *this;
	};

	bool operator != (const VM1_QBUS_WIRES &src)
	{
		int n = memcmp(this, &src, sizeof(VM1_QBUS_WIRES));
		return (n != 0);
	};
	bool operator == (const VM1_QBUS_WIRES &src)
	{
		int n = memcmp(this, &src, sizeof(VM1_QBUS_WIRES));
		return (n == 0);
	};
};

struct VM1_QBUS_REGS
{
	uint64_t plm;               //reg[33:0]     // main matrix result register (first stage)
	uint64_t plr;               //reg[33:0]     // main matrix result register (last stage)
	bool    exc_dbl[4];         //reg[3:0]      // double error detector
	bool    sop_out[4];         //reg[3:0]      //
	uint16_t plrt;              //reg[8:6]      //
	uint16_t plrtz;             //reg[8:6]      //
	bool    init_out[3];        //reg[2:0]      //
	bool    rply_ack[4];        //reg[3:0]      //
	bool    qbus_aseq[2];       //reg[1:0]      // address request sequencer
	uint16_t gpr[16];           //reg[15:0]     // register array
	uint16_t mj;                //reg[14:0]     // microcode stage and condition register
	uint16_t ir;                //reg[15:0]     // instruction register (last stage)
	uint16_t ira;               //reg[15:0]     // instruction register (first stage)
	uint32_t rq;                //reg[19:0]     // interrupt request register
	bool    aclo;               //reg           // ACLO falling edge detectors
	bool    acok;               //reg           // ACLO raising edge detectors
	bool    irq2;               //reg           // IRQ2 falling edge detectors
	bool    irq3;               //reg           // IRQ3 falling edge detectors
	bool    uop;                //reg           // undefined operation latch
	bool    qbto;               //reg           // I/O bus timeout & OAT latch
	bool    ivto;               //reg           // IAKO bus timeout latch
	bool    start_irq;          //reg           // raised by 1777x2 register write
	uint16_t qbus_timer;        //reg[5:0]      // qbus timeout counter
	bool    qbus_tovf;          //reg           // Qbus timer overflow latch
	uint8_t vsel;               //reg[3:0]      // vector selection register
	uint8_t plir;               //reg[3:1]      // pli[10:8:6:4] outputs latch
	bool    plir0;              //reg[0]        // pli[10:8:6:4] outputs latch
	bool    ir_stb2;            //reg           // instruction register strobe
	bool    ir_set;             //reg           //
	bool    ir_stop;            //reg           //
	bool    ir_seq;             //reg           //
	bool    pli_req;            //reg           // source and latch
	bool    plm_stb;            //reg           // plm_register strobe latch
	bool    plm1x, plm2x;       //reg           //
	bool    plm1x_hl;           //reg           //
	bool    plm_ena;            //reg           //
	bool    mj_stb1, mj_stb2;   //reg           //
	bool    psw_stb, psw_stbc;  //reg           //
	bool    psw_mj;             //reg           //
	bool    plm23_wait;         //reg           //
	bool    plm23_ichk;         //reg           //
	uint8_t tplm;               //reg[3:1]      //
	uint8_t tplmz;              //reg[3:1]      //
	bool    reset;              //reg           // global device hardware reset
	bool    abort;              //reg           // odd address. bus hang, invalid opcode
	bool    mjres;              //reg           // reset microcode state machine
	bool    mjres_h;            //reg           //
	bool    abort_tm;           //reg           //
	uint16_t sel_reg;           //reg           // peripheral block selectors
	bool    sel_xx;             //              //
	bool    rply_s2, rply_s3;   //reg           // disable rply generation if start_irq active
	bool    dmr_req;            //reg           //
	bool    dmr_req_l;          //reg           //
	bool    iako_out_lh;        //reg           //
	bool    iak_flag;           //reg           //
	bool    iako_oe;            //reg           //
	bool    oe_set;             //reg           //
	bool    oe_clr;             //reg           //
	bool    dout_done;          //reg           //
	bool    dout_req;           //reg           //
	bool    dout_out;           //reg           //
	bool    dout_out_l;         //reg           //
	bool    din_out;            //reg           //
	bool    din_out_l;          //reg           //
	bool    dmgi_in_l;          //reg           //
	bool    qbus_adr;           //reg           //
	bool    qbus_req;           //reg           //
	bool    qbus_win;           //reg           //
	bool    qbus_win_h;         //reg           //
	bool    qbus_own_fp;        //reg           //
	bool    qbus_own_rp;        //reg           //
	bool    qbus_flag;          //reg           //
	bool    sack_out;           //reg           //
	bool    sync_out;           //reg           //
	bool    sync_out_h;         //reg           //
	bool    sync_ena;           //reg           //
	bool    qbus_nosr_h;        //reg           //
	bool    qbus_gnt_l;         //reg           //
	bool    qbus_free_h;        //reg           //
	uint8_t reg_csr;            //reg[2:0]      // 177700: control register
	uint16_t reg_vec;           //reg[15:0]     // 177702: start vector register
	uint8_t reg_err;            //reg[7:0]      // 177704: error register
	uint8_t freg;               //reg[3:0]      //
	bool    ustb, ustb_h;       //reg           //
	bool    ustb1, ustb1_h;     //reg           //
	bool    ustb1_hl;           //reg           //
	bool    alu_busy_fp;        //reg           // ALU busy (not ready phase shifted)
	bool    alu_busy_rp;        //reg           //
	bool    alu_nrdy;           //reg           // ALU not ready
	bool    au_alsl, au_alsh;   //reg           // ALU result strobes
	bool    au_hibyte;          //reg           //
	uint16_t areg;              //reg[15:0]     // ALU A register (Q-bus address)
	uint16_t xreg;              //reg[15:0]     // ALU X parameter register
	uint16_t yreg;              //reg[15:0]     // ALU Y parameter register
	uint16_t vmux;              //reg[15:0]     // variable for vector multiplexer
	uint16_t cmux;              //reg[15:0]     // variable for constant multiplexer
	uint8_t xadr;               //reg[3:0]
	uint8_t yadr;               //reg[3:0]

	//ВЕ таймер
	uint16_t tve_limit;         //reg[15:0]     // timer reload & capture register
	uint16_t tve_count;         //reg[15:0]     // timer counter register
	uint8_t tve_csr;            //reg[7:0]      // timer control register
	uint8_t tve_pre;            //reg[6:0]      // clock prescaler counter
	uint8_t tve_div;            //reg[5:0]      // timer clock divisor
	uint16_t tve_edge;
	bool    tve_tclk;           //reg           // selected timer clock
	bool    tve_tclk4;          //reg           // prescaler /4 output
	bool    tve_zprev;          //reg           // zero value edge detector
	bool    tve_intrq[2];       //reg[1:0]      // hidden interrupt request

	void clear()
	{
		memset(this, 0, sizeof(VM1_QBUS_REGS));
	};
	VM1_QBUS_REGS &operator = (const VM1_QBUS_REGS &src)
	{
		memcpy(this, &src, sizeof(VM1_QBUS_REGS));
		return *this;
	};
	bool operator != (const VM1_QBUS_REGS &src)
	{
		int n = memcmp(this, &src, sizeof(VM1_QBUS_REGS));
		return (n != 0);
	};
	bool operator == (const VM1_QBUS_REGS &src)
	{
		int n = memcmp(this, &src, sizeof(VM1_QBUS_REGS));
		return (n == 0);
	};
};

//input-output, набор сигналов процессора, которых нет в МПИ, но которые есть у процессора
struct VM1_IO
{
	//IOPINS

	bool    pin_ena;        //input         // processor clock enable
	bool    pin_sp;         //input         // peripheral timer input
	uint16_t    pin_pa;         //input[1:0]    // processor number

	void clear()
	{
		pin_pa  = 0;        //номер процессора на шине (0..3)
		pin_ena = false;    //разрешающий сигнал (true - активно)
		pin_sp  = false;    //резервный вход ВЕ-таймера
	};
};

enum CPU_TYPE
{
	CPU_VM1A,
	CPU_VM1G
};
