BESM6: Implemented WRU when no local console, added binary punchtape mode,

translated some comments.
This commit is contained in:
Leo Broukhis 2015-01-11 17:43:39 -08:00
parent c2cef3c051
commit 8f6e849ecf
7 changed files with 302 additions and 173 deletions

View file

@ -65,16 +65,27 @@ int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
extern const char *scp_errors[];
/* нехранящие биты ГРП должны сбрасываться путем обнуления тех регистров,
* сборкой которых они являются
/* Wired (non-registered) bits of interrupt registers (GRP and PRP)
* cannot be cleared by writing to the GRP and must be cleared by clearing
* the registers generating the corresponding interrupts.
*/
#define GRP_WIRED_BITS 01400743700000000LL
#define GRP_WIRED_BITS (GRP_DRUM1_FREE | GRP_DRUM2_FREE |\
GRP_CHAN3_DONE | GRP_CHAN4_DONE |\
GRP_CHAN5_DONE | GRP_CHAN6_DONE |\
GRP_CHAN3_FREE | GRP_CHAN4_FREE |\
GRP_CHAN5_FREE | GRP_CHAN6_FREE |\
GRP_CHAN7_FREE )
#define PRP_WIRED_BITS 0770000
/* So far irrelevant as none of the devices -
* punchcard I/O and punchtape output - had been implemented.
*/
#define PRP_WIRED_BITS (PRP_UVVK1_END | PRP_UVVK2_END |\
PRP_PCARD1_CHECK | PRP_PCARD2_CHECK |\
PRP_PCARD1_PUNCH | PRP_PCARD2_PUNCH |\
PRP_PTAPE1_PUNCH | PRP_PTAPE2_PUNCH )
int corr_stack;
int redraw_panel;
uint32 delay;
jmp_buf cpu_halt;
t_stat cpu_examine (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
@ -131,7 +142,7 @@ REG cpu_reg[] = {
};
MTAB cpu_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle, NULL, "Display idle detection mode" },
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle, NULL, "Enables idle detection mode" },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL, NULL, "Disables idle detection" },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "REQ", &cpu_req, NULL, NULL, "Sends a request interrupt" },
{ MTAB_XTD|MTAB_VDV, 0, "PANEL", "PANEL", &besm6_init_panel, NULL, NULL, "Displays graphical panel" },
@ -148,16 +159,16 @@ DEVICE cpu_dev = {
};
/*
* REG: псевдоустройство, содержащее латинские синонимы всех регистров.
* REG: A pseudo-device containing Latin synonyms of all CPU registers.
*/
REG reg_reg[] = {
{ "PC", &PC, 8, 15, 0, 1 }, /* счётчик адреса команды */
{ "RK", &RK, 8, 24, 0, 1 }, /* регистр выполняемой команды */
{ "Aex", &Aex, 8, 15, 0, 1 }, /* исполнительный адрес */
{ "ACC", &ACC, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* сумматор */
{ "RMR", &RMR, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* регистр младших разрядов */
{ "RAU", &RAU, 2, 6, 0, 1 }, /* режимы АУ */
{ "M1", &M[1], 8, 15, 0, 1 }, /* регистры-модификаторы */
{ "PC", &PC, 8, 15, 0, 1 }, /* program counter */
{ "RK", &RK, 8, 24, 0, 1 }, /* instruction register */
{ "Aex", &Aex, 8, 15, 0, 1 }, /* effective address */
{ "ACC", &ACC, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* accumulator */
{ "RMR", &RMR, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* LSB register */
{ "RAU", &RAU, 2, 6, 0, 1 }, /* ALU modes */
{ "M1", &M[1], 8, 15, 0, 1 }, /* index (modifier) registers */
{ "M2", &M[2], 8, 15, 0, 1 },
{ "M3", &M[3], 8, 15, 0, 1 },
{ "M4", &M[4], 8, 15, 0, 1 },
@ -171,19 +182,19 @@ REG reg_reg[] = {
{ "M14", &M[014], 8, 15, 0, 1 },
{ "M15", &M[015], 8, 15, 0, 1 },
{ "M16", &M[016], 8, 15, 0, 1 },
{ "M17", &M[017], 8, 15, 0, 1 }, /* указатель магазина */
{ "M20", &M[020], 8, 15, 0, 1 }, /* MOD - модификатор адреса */
{ "M21", &M[021], 8, 15, 0, 1 }, /* PSW - режимы УУ */
{ "M27", &M[027], 8, 15, 0, 1 }, /* SPSW - упрятывание режимов УУ */
{ "M32", &M[032], 8, 15, 0, 1 }, /* ERET - адрес возврата из экстракода */
{ "M33", &M[033], 8, 15, 0, 1 }, /* IRET - адрес возврата из прерывания */
{ "M34", &M[034], 8, 16, 0, 1 }, /* IBP - адрес прерывания по выполнению */
{ "M35", &M[035], 8, 16, 0, 1 }, /* DWP - адрес прерывания по чтению/записи */
{ "RUU", &RUU, 2, 9, 0, 1 }, /* ПКП, ПКЛ, РежЭ, РежПр, ПрИК, БРО, ПрК */
{ "GRP", &GRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* главный регистр прерываний */
{ "MGRP", &MGRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* маска ГРП */
{ "PRP", &PRP, 8, 24, 0, 1 }, /* периферийный регистр прерываний */
{ "MPRP", &MPRP, 8, 24, 0, 1 }, /* маска ПРП */
{ "M17", &M[017], 8, 15, 0, 1 }, /* also the stack pointer */
{ "M20", &M[020], 8, 15, 0, 1 }, /* MOD - address modifier register */
{ "M21", &M[021], 8, 15, 0, 1 }, /* PSW - CU modes */
{ "M27", &M[027], 8, 15, 0, 1 }, /* SPSW - saved CU modes */
{ "M32", &M[032], 8, 15, 0, 1 }, /* ERET - extracode return address */
{ "M33", &M[033], 8, 15, 0, 1 }, /* IRET - interrupt return address */
{ "M34", &M[034], 8, 16, 0, 1 }, /* IBP - instruction bkpt address */
{ "M35", &M[035], 8, 16, 0, 1 }, /* DWP - watchpoint address */
{ "RUU", &RUU, 2, 9, 0, 1 }, /* execution modes */
{ "GRP", &GRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* main interrupt reg */
{ "MGRP", &MGRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* mask of the above */
{ "PRP", &PRP, 8, 24, 0, 1 }, /* peripheral interrupt reg */
{ "MPRP", &MPRP, 8, 24, 0, 1 }, /* mask of the above*/
{ "BRZ0", &BRZ[0], 8, 50, 0, 1, NULL, NULL, REG_VMIO },
{ "BRZ1", &BRZ[1], 8, 50, 0, 1, NULL, NULL, REG_VMIO },
@ -245,7 +256,7 @@ char sim_name[] = "БЭСМ-6";
REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 1; /* максимальное количество слов в машинной команде */
int32 sim_emax = 1; /* max number of addressable units per instruction */
DEVICE *sim_devices[] = {
&cpu_dev,
@ -328,7 +339,7 @@ t_stat cpu_reset (DEVICE *dptr)
for (i=0; i<NREGS; ++i)
M[i] = 0;
/* Устройства ввода с перфокарт не готовы */
/* Punchcard readers not yet implemented thus not ready */
READY2 |= 042000000;
/* Регистр 17: БлП, БлЗ, ПОП, ПОК, БлПр */
@ -435,8 +446,8 @@ static void cmd_002 ()
MGRP = ACC;
break;
case 037:
/* Гашение главного регистра прерываний */
/* нехранящие биты невозможно погасить */
/* Clearing the main interrupt register: */
/* it is impossible to clear wired (stateless) bits this way */
GRP &= ACC | GRP_WIRED_BITS;
break;
case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71:
@ -471,8 +482,7 @@ static void cmd_002 ()
break;
default:
if ((Aex & 0340) == 0140) {
/* TODO: управление блокировкой схемы
* автоматического запуска */
/* TODO: watchdog reset mechanism */
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
}
/* Неиспользуемые адреса */
@ -493,8 +503,13 @@ static void cmd_033 ()
#endif
switch (Aex & 04177) {
case 0:
/* Точно неизвестно, что это такое, но драйвер МД
* иногда выдает команду "увв 0". */
/*
* Using an I/O control instruction with Aex == 0
* after issuing a 033 instruction with a non-zero Aex
* to send data to a device was required
* for some devices (e.g. printers) according to the docs.
* What is the exact purpose is unclear (timing, power, ???)
*/
break;
case 1: case 2:
/* Управление обменом с магнитными барабанами */
@ -562,7 +577,7 @@ static void cmd_033 ()
tty_send ((uint32) ACC & BITS(24));
break;
case 0141:
/* TODO: управление разметкой магнитной ленты */
/* TODO: formatting magnetic tape */
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
break;
case 0142:
@ -570,11 +585,12 @@ static void cmd_033 ()
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
break;
case 0147:
/* Запись в регистр управления электропитанием, */
/* не оказывает видимого эффекта на выполнение */
/* Writing to the power supply control register
* does not have any observable effect
*/
break;
case 0150: case 0151:
/* TODO: управление вводом с перфокарт */
/* TODO: reading from punchcards */
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
break;
case 0153:
@ -727,10 +743,9 @@ void check_initial_setup ()
*/
return;
}
if ((memory[TAKEN] & SETUP_REQS_ENABLED) == 0 ||
(memory[TAKEN] & ALL_REQS_ENABLED) != 0 ||
(MGRP & GRP_PANEL_REQ) == 0) {
/* Слишком рано, или уже не надо, или невовремя */
if ((memory[TAKEN] & SETUP_REQS_ENABLED) == 0 || /* not ready for setup */
(memory[TAKEN] & ALL_REQS_ENABLED) != 0 || /* all done */
(MGRP & GRP_PANEL_REQ) == 0) { /* not at the moment */
return;
}
@ -774,7 +789,7 @@ void check_initial_setup ()
/*
* Execute one instruction, placed on address PC:RUU_RIGHT_INSTR.
* Increment delay. When stopped, perform a longjmp to cpu_halt,
* When stopped, perform a longjmp to cpu_halt,
* sending a stop code.
*/
void cpu_one_inst ()
@ -782,6 +797,14 @@ void cpu_one_inst ()
int reg, opcode, addr, nextpc, next_mod;
t_value word;
/*
* Instruction execution time in 100 ns ticks; not really used
* as the amortized 1 MIPS instruction rate is assumed.
* The assignments of MEAN_TIME(x,y) to the delay variable
* are kept as a reference.
*/
uint32 delay;
corr_stack = 0;
word = mmu_fetch (PC);
if (RUU & RUU_RIGHT_INSTR)
@ -1668,7 +1691,11 @@ t_stat sim_instr (void)
}
}
if (PC > BITS(15)) { /* выход за пределы памяти */
if (PC > BITS(15) && IS_SUPERVISOR(RUU)) {
/*
* Runaway instruction execution in supervisor mode
* warrants attention.
*/
besm6_draw_panel();
return STOP_RUNOUT; /* stop simulation */
}
@ -1680,7 +1707,8 @@ t_stat sim_instr (void)
}
if (PRP & MPRP) {
/* регистр хранящий, сбрасывается программно */
/* There are interrupts pending in the peripheral
* interrupt register */
GRP |= GRP_SLAVE;
}
@ -1701,8 +1729,10 @@ t_stat sim_instr (void)
}
/*
* В 9-й части частота таймера 250 Гц (4 мс),
* в жизни - 50 Гц (20 мс).
* A 250 Hz clock as per the original documentation,
* and matching the available software binaries.
* Some installations used 50 Hz with a modified OS
* for a better user time/system time ratio.
*/
t_stat fast_clk (UNIT * this)
{
@ -1712,18 +1742,17 @@ t_stat fast_clk (UNIT * this)
++counter;
++tty_counter;
/*besm6_debug ("*** таймер 20 мсек");*/
GRP |= GRP_TIMER;
/* Медленный таймер: должен быть 16 Гц.
* Но от него почему-то зависит вывод на терминалы,
* поэтому ускорим. */
if ((counter & 3) == 0) {
/*besm6_debug ("*** таймер 80 мсек");*/
if ((counter & 15) == 0) {
/*
* The OS used the (undocumented, later addition) slow clock interrupt to initiate servicing
* terminal I/O. Its frequency was reportedly 16 Hz; 64 ms is a good enough approximation.
*/
GRP |= GRP_SLOW_CLK;
}
/* Перерисовка панели каждые 64 миллисекунды. */
/* Requesting panel redraw every 64 ms. */
if ((counter & 15) == 0) {
redraw_panel = 1;
}
@ -1741,7 +1770,7 @@ t_stat fast_clk (UNIT * this)
}
UNIT clocks[] = {
{ UDATA(fast_clk, UNIT_IDLE, 0), CLK_DELAY }, /* 40 р, 50 Гц */
{ UDATA(fast_clk, UNIT_IDLE, 0), CLK_DELAY }, /* Bit 40 of the GRP, 250 Hz */
};
t_stat clk_reset (DEVICE * dev)

View file

@ -114,19 +114,15 @@ enum {
((x) >> 48) == CONVOL_NUMBER)
/*
* Вычисление правдоподобного времени выполнения команды,
* зная количество тактов в УУ и среднее в АУ.
* Предполагаем, что в 50% случаев происходит совмещение
* выполнения, поэтому суммируем большее и половину
* от меньшего значения.
* An attempt to approximate instruction execution times.
* The arguments number of clock ticks spent on an instruction
* in the ALU and in the CU; the computed result assumes
* a 50% overlap in execution.
*/
#define MEAN_TIME(x,y) (x>y ? x+y/2 : x/2+y)
/*
* Считаем, что моделируеммая машина имеет опорную частоту 10 МГц.
*/
#define USEC 1 /* одна микросекунда - десять тактов */
#define MSEC (1000*USEC) /* одна миллисекунда */
#define USEC 1 /* 1 microsecond */
#define MSEC (1000*USEC) /* 1 millisecond */
#define CLK_TPS 250 /* Fast Clock Ticks Per Second (every 4ms) */
#define CLK_DELAY 4000 /* Uncalibrated instructions per clock tick */
@ -135,6 +131,7 @@ extern UNIT tty_unit[];
extern UNIT clocks[];
extern t_value memory [MEMSIZE];
extern t_value pult [8];
extern uint32 PC, RAU, RUU;
extern uint32 M[NREGS];
extern t_value BRZ[8], RP[8], GRP, MGRP;
@ -379,14 +376,15 @@ t_value besm6_pack (t_value val, t_value mask);
t_value besm6_unpack (t_value val, t_value mask);
/*
* Разряды главного регистра прерываний (ГРП)
* Внешние:
* Bits of the main interrupt register ГРП (GRP)
* External:
*/
#define GRP_PRN1_SYNC 04000000000000000LL /* 48 */
#define GRP_PRN2_SYNC 02000000000000000LL /* 47 */
#define GRP_DRUM1_FREE 01000000000000000LL /* 46 */
#define GRP_DRUM2_FREE 00400000000000000LL /* 45 */
#define GRP_VNIIEM 00300000000000000LL /* 44-43, placeholder */
#define GRP_UVVK1_SYNC 00200000000000000LL /* 44 */
#define GRP_UVVK2_SYNC 00100000000000000LL /* 43 */
#define GRP_FS1_SYNC 00040000000000000LL /* 42 */
#define GRP_FS2_SYNC 00020000000000000LL /* 41 */
#define GRP_TIMER 00010000000000000LL /* 40 */
@ -405,10 +403,10 @@ t_value besm6_unpack (t_value val, t_value mask);
#define GRP_CHAN5_FREE 00000000400000000LL /* 27 */
#define GRP_CHAN6_FREE 00000000200000000LL /* 26 */
#define GRP_CHAN7_FREE 00000000100000000LL /* 25 */
#define GRP_SERIAL 00000000001000000LL /* 19 */
#define GRP_SERIAL 00000000001000000LL /* 19, nonstandard */
#define GRP_WATCHDOG 00000000000002000LL /* 11 */
#define GRP_SLOW_CLK 00000000000001000LL /* 10 */
/* Внутренние: */
#define GRP_SLOW_CLK 00000000000001000LL /* 10, nonstandard */
/* Internal: */
#define GRP_DIVZERO 00000000034000000LL /* 23-21 */
#define GRP_OVERFLOW 00000000014000000LL /* 22-21 */
#define GRP_CHECK 00000000004000000LL /* 21 */
@ -426,6 +424,23 @@ t_value besm6_unpack (t_value val, t_value mask);
#define GRP_SET_BLOCK(x,m) (((x) & ~GRP_BLOCK_MASK) | ((m) & GRP_BLOCK_MASK))
#define GRP_SET_PAGE(x,m) (((x) & ~GRP_PAGE_MASK) | (((m)<<4) & GRP_PAGE_MASK))
/*
* Bits of the peripheral interrupt register ПРП (PRP)
*/
#define PRP_UVVK1_END 010000000 /* 22 */
#define PRP_UVVK2_END 004000000 /* 21 */
#define PRP_PCARD1_CHECK 002000000 /* 20 */
#define PRP_PCARD2_CHECK 001000000 /* 19 */
#define PRP_PCARD1_PUNCH 000400000 /* 18 */
#define PRP_PCARD2_PUNCH 000200000 /* 17 */
#define PRP_PTAPE1_PUNCH 000100000 /* 16 */
#define PRP_PTAPE2_PUNCH 000040000 /* 15 */
/* 14-13 unused */
#define PRP_CONS1_INPUT 000004000 /* 12 */
#define PRP_CONS2_INPUT 000002000 /* 11 */
#define PRP_CONS1_DONE 000001000 /* 10 */
#define PRP_CONS2_DONE 000000400 /* 9 */
/* Номер блока ОЗУ или номер страницы, вызвавших прерывание */
extern uint32 iintr_data;

View file

@ -89,6 +89,7 @@ DEVICE fs_dev = {
enum {
FS_IDLE,
FS_STARTING,
FS_BINARY,
FS_RUNNING,
FS_IMAGE,
FS_IMAGE_LAST = FS_IMAGE + CARD_LEN - 1,
@ -100,6 +101,8 @@ enum {
FS_TAIL,
} fs_state[2];
int fs_textmode[2];
/*
* Reset routine
*/
@ -116,10 +119,16 @@ t_stat fs_reset (DEVICE *dptr)
return SCPE_OK;
}
/*
* Attaches a raw binary file by default,
* with a -t switch attaches a prepared text file in UTF-8.
*/
t_stat fs_attach (UNIT *u, char *cptr)
{
t_stat s;
int num = u - fs_unit;
fs_textmode[num] = sim_switches & SWMASK('T');
sim_switches &= ~SWMASK('T');
s = attach_unit (u, cptr);
if (s != SCPE_OK)
return s;
@ -186,6 +195,20 @@ void fs_control (int num, uint32 cmd)
}
unsigned char unicode_to_gost (unsigned short val);
/*
* The UPP code is the GOST 10859 code with odd parity.
* UPP stood for "unit for preparation of punchards".
*/
static unsigned char unicode_to_upp (unsigned short ch) {
unsigned char ret;
ch = ret = unicode_to_gost (ch);
ch = (ch & 0x55) + ((ch >> 1) & 0x55);
ch = (ch & 0x33) + ((ch >> 2) & 0x33);
ch = (ch & 0x0F) + ((ch >> 4) & 0x0F);
return (ch & 1) ? ret : ret | 0x80;
}
static int utf8_getc (FILE *fin);
/*
@ -194,64 +217,66 @@ static int utf8_getc (FILE *fin);
*/
t_stat fs_event (UNIT *u)
{
static int cnt;
int num = u - fs_unit;
again:
if (fs_state[num] == FS_STARTING) {
/* По первому прерыванию после запуска двигателя ничего не читаем */
/* The first interrupt after starting the motor is dummy,
* no need to read anything from the attached file.
*/
FS[num] = 0;
fs_state[num] = FS_RUNNING;
} else if (fs_state[num] == FS_RUNNING) {
int ch;
/* переводы строк игнорируются */
while ((ch = utf8_getc (u->fileref)) == '\n');
cnt = 0;
fs_state[num] = fs_textmode[num] ? FS_RUNNING : FS_BINARY;
} else if (fs_state[num] == FS_BINARY) {
int ch = getc (u->fileref);
if (ch < 0) {
/* хвост ленты без пробивок */
FS[num] = 0;
fs_state[num] = FS_TAIL;
} else if (ch == '\f') {
} else {
FS[num] = ch;
}
} else if (fs_state[num] == FS_RUNNING) {
int ch;
/* Line separators are ignored in running text mode */
do ch = utf8_getc (u->fileref); while (ch == '\n' || ch == '\r');
if (ch < 0) {
/* the tail end of the tape has no holes */
FS[num] = 0;
fs_state[num] = FS_TAIL;
} else if (ch == (']' & 037)) {
/* Switching from running text mode to "virtual punchcard" mode and back
* is done with an ASCII GS (group separator) symbol ctrl-].
*/
fs_state[num] = FS_IMAGE;
goto again;
} else {
ch = FS[num] = unicode_to_gost (ch);
ch = (ch & 0x55) + ((ch >> 1) & 0x55);
ch = (ch & 0x33) + ((ch >> 2) & 0x33);
ch = (ch & 0x0F) + ((ch >> 4) & 0x0F);
if (ch & 1); else FS[num] |= 0x80;
FS[num] = unicode_to_upp (ch);
}
} else if (FS_IMAGE <= fs_state[num] && fs_state[num] <= FS_IMAGE_LAST) {
int ch = utf8_getc (u->fileref);
if (ch < 0) {
/* обрыв ленты */
/* premature end of tape */
FS[num] = 0;
fs_state[num] = FS_TAIL;
} else if (ch == '\r') {
/* always ignored */
goto again;
} else if (ch == '\n') {
/* идем дополнять образ карты нулевыми байтами */
/* Start returning zero bytes up to the end of the current "virtual punchard" */
fs_state[num] = FS_FILLUP + (fs_state[num] - FS_IMAGE);
goto again;
} else if (ch == '\f') {
} else if (ch == (']' & 037)) {
if (fs_state[num] != FS_IMAGE)
besm6_debug("<<< ENDA3 requested mid-card?");
fs_state[num] = FS_ENDA3;
goto again;
} else {
ch = FS[num] = unicode_to_gost (ch);
ch = (ch & 0x55) + ((ch >> 1) & 0x55);
ch = (ch & 0x33) + ((ch >> 2) & 0x33);
ch = (ch & 0x0F) + ((ch >> 4) & 0x0F);
if (ch & 1); else FS[num] |= 0x80;
++fs_state[num];
FS[num] = unicode_to_upp (ch);
if (++fs_state[num] == FS_TOOLONG) {
/* If a line is too long (> 120 chars), start the next "virtual punchcard" */
fs_state[num] = FS_IMAGE;
}
}
} else if (fs_state[num] == FS_TOOLONG) {
/* дочитываем до конца строки */
int ch;
besm6_debug("<<< too long???");
while ((ch = utf8_getc (u->fileref)) != '\n' && ch >= 0);
if (ch < 0) {
/* хвост ленты без пробивок */
FS[num] = 0;
fs_state[num] = FS_TAIL;
} else
goto again;
} else if (FS_FILLUP <= fs_state[num] && fs_state[num] <= FS_FILLUP_LAST) {
FS[num] = 0;
if (++fs_state[num] == FS_ENDA3) {
@ -278,15 +303,21 @@ int fs_read(int num) {
return FS[num];
}
/*
* Unlike the OS which uses GOST overline (approximated by ^) as a line separator
* in running text mode, the BESM-ALGOL programming system used a nonprintable
* character (0174) from the unused part of the codetable to allow compressing multiple
* source lines on a punchcard. To specify that character,
* we use ASCII RS (record separator) symbol ctrl-^.
*/
unsigned char
unicode_to_gost (unsigned short val)
{
static const unsigned char tab0 [256] = {
/* 00 - 07 */ 017, 017, 017, 017, 017, 017, 017, 017,
/* 08 - 0f */ 017, 017, 0214, 017, 017, 0174, 017, 017,
/* 08 - 0f */ 017, 017, 0214, 017, 017, 017, 017, 017,
/* 10 - 17 */ 017, 017, 017, 017, 017, 017, 017, 017,
/* 18 - 1f */ 017, 017, 017, 017, 017, 017, 017, 017,
/* 18 - 1f */ 017, 017, 017, 017, 017, 017, 0174, 017,
/* !"#$%&' */ 0017, 0133, 0134, 0034, 0127, 0126, 0121, 0033,
/* ()*+,-./ */ 0022, 0023, 0031, 0012, 0015, 0013, 0016, 0014,
/* 01234567 */ 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
@ -413,6 +444,11 @@ unicode_to_gost (unsigned short val)
case 0x83: return 0122;
}
break;
case 0x23:
switch ((unsigned char) val) {
case 0xe8: return 0020;
}
break;
case 0x25:
switch ((unsigned char) val) {
case 0xc7: return 0127;

View file

@ -97,6 +97,8 @@ t_stat vt_clk(UNIT *);
extern char *get_sim_sw (char *cptr);
extern int32 tmr_poll; /* calibrated clock timer poll */
int attached_console;
UNIT tty_unit [] = {
{ UDATA (vt_clk, UNIT_DIS|UNIT_IDLE, 0) }, /* fake unit, clock */
{ UDATA (NULL, UNIT_SEQ, 0) },
@ -228,6 +230,19 @@ t_stat vt_clk (UNIT * this)
t->rxb [t->rxbpi++] = '\3';
}
/*
* It the operator console is remote, we still need to probe the local keyboard
* for a WRU, say, 10 times a second.
*/
if (!attached_console) {
static int divider;
if (++divider == CLK_TPS/10) {
divider == 0;
if (SCPE_STOP == sim_poll_kbd())
stop_cpu = 1;
}
}
/* Polling sockets for transmission. */
tmxr_poll_tx (&tty_desc);
/* If the TTY system is not idle, schedule the next interrupt
@ -343,6 +358,7 @@ t_stat tty_attach (UNIT *u, char *cptr)
if (num <= TTY_MAX)
vt_mask |= 1 << (TTY_MAX - num);
besm6_debug ("*** console on T%03o", num);
attached_console = 1;
return SCPE_OK;
}
return SCPE_ALATT;

View file

@ -7,18 +7,18 @@ set cpu idle
;set disk debug
;
; Приводим барабаны в исходное состояние.
; Initializing the magnetic drums.
;
attach -n drum0 drum1x.bin
attach -n drum1 drum2x.bin
;
; Создаем рабочий диск.
; Initializing a scratch disk.
;
attach -n disk6 2052.bin
;
; Подключаем диски.
; Attaching system disks.
;
attach -e disk7 sbor2053.bin
attach -e disk5 krab2063.bin
@ -27,27 +27,47 @@ attach -e disk1 svs2048.bin
attach -e disk2 alt2048.bin
;
; Подключаем АЦПУ.
; Attaching an output file.
;
attach prn0 output.txt
attach -n prn0 output.txt
;
; Активируем операторский терминал,
; на который идут сообщения.
; Allowing telnet connections, port 4199.
;
attach tty 4199
;
; Attaching a terminal serving as the operator console.
;
; This works on UNIX-like systems.
attach tty1 console
; On Windows, a UTF-8 connnection works better over telnet.
; Use a different port for the operator console just in case.
;attach tty Line=1,4198
;set env PATH %PATH%;C:\Program Files (x86)\PuTTY
;! start putty telnet://localhost:4198
;
; Режимы по вкусу
; On Unix, telnet can also be used for the operator console.
; ! gnome-terminal -x sh -c "telnet localhost 4198" &
;
; Terminal modes (how to enter Cyrillics, should the backspace be erasing), etc.
; (authbs == authentic non-erasing)
;
; Using UTF-8 for input
; set tty1 unicode,authbs
;
; Entering Russian letters as lowercase Latin letters
; according to the standard Russian layout
;set tty1 jcuken,authbs
;
; Entering Russian letters as corresponding lowercase Latin letters.
; Q = "ya", W = "ve", Y = "yeru", J = "short I", X = "soft sign",
; C = "ts", V = "zhe", grave = "yu", tilde = "ch", { = "sh", } = "shch",
; | = "reverse e"
set tty1 qwerty,authbs
set -n tty1 log=tty1.txt
;
; Разрешаем подключение пользователей по telnet, порт 4199.
;
attach tty 4199
set tty2 authbs
set tty3 authbs
set tty4 authbs
@ -73,18 +93,30 @@ set tty23 authbs
set tty24 authbs
;
; Включение БРС/БРЗ для совместимости.
; Замедляет работу на 20%.
; Enabling the true LRU behavior of caches
; slows down the simulation speed ~20%
;
;set mmu cache
echo ###
echo ### Zeroing out the first page of RAM (as would be entered from
echo ### switch registers after powering up the machine,
echo ### likely about once a year or less).
echo ###
d -ml 1 xta, vtm 1777(1)
d -ml 2 atx (1), utm -1(1)
d -ml 3 v1m 2(1), stop
run 1
echo ###
echo ### Done; data cache registers are displayed above. An error message
echo ### would be usually displayed there after a STOP instruction.
echo ### Naturally, at the moment they all contain zeros. Booting the OS now...
echo ###
;
; Запуск ОС ДИСПАК.
; Booting OS DISPAK.
;
load boot_dispak.b6
; Происходит контроль числа по адресу 1031
d 1031 0
run 2000
;quit

View file

@ -1,10 +1,10 @@
# Attaching the input device
at fs0 input.txt
at -t fs0 input.txt
# Waiting for the end of initial setup
expect -r "ДATA.*\n"
do dispak.ini
# Now we're ready to send commands from the front panel
echo Requesting input from the punch tape reader (FS8)
echo Requesting input from the punch tape reader (FS8), it takes a few seconds
d 6 1
d 5 10
set cpu req
@ -14,6 +14,7 @@ go
# The process had been started, check state every 10 model seconds
send after=1000000 "WCPP\r"
expect -p -r "4199.*\n" send after=10000000 "WCPP\r"; go
expect -c "KЗ" step 10000000
expect -c "HET\r\n" step 10000
go
echo Enabling the printer (ONL A0)
@ -24,7 +25,7 @@ expect -r "ECT.*\n"
go
echo Checking for the printing to finish
send "HOMB\r"
expect -p -r "4199.*\n" send "HOMB\r"; go
expect -p -r "A0.*\n" send "HOMB\r"; go
expect -c "HET\r\n"
go
echo Done

View file

@ -1,6 +1,6 @@
ШИФР 419999 ЗС5^
EEВ1А3
*NAME PRIME NUMBERS
*NAME PRIME NUMBERS
* The ^L char before *NAME is important
* NO LIST Disable source listing by removing spaces between * and NO
*NO LOAD LIST Enable loader listing by adding 5 spaces between * and NO
@ -50,4 +50,4 @@ c------ Printing every 1000th prime number
*EXECUTE
* The ^L char after *END FILE is important
*END FILE
ЕКОНЕЦ
ЕКОНЕЦ