PDA

Просмотр полной версии : Быстрая и медленная память 128к



Hacker VBI
29.03.2013, 14:51
Можно что-нибудь внятное по этому поводу?
Не совсем понимаю, что где как будет исполняться и в чём причина.

SAM style
29.03.2013, 15:05
На английском: http://www.worldofspectrum.org/faq/reference/48kreference.htm#Contention

ZXMAK
29.03.2013, 22:07
Причина - тактирование процессора приостанавливается, если доступ к памяти происходит в определенные моменты времени в область памяти которая шарится между процессором и ula. Самое короткое и не запутанное поведение можешь посмотреть в реализации ULA классов оригинальных спектрумов в zxmak2

Hacker VBI
30.03.2013, 00:25
http://zxmak2.codeplex.com/SourceControl/changeset/view/22900#391359
Я вижу, что это связано с обращениями к памяти до #8000, и всё.
В общем, расположение кода лучше с #8000.

predatoralpha
30.03.2013, 02:19
http://zx.pk.ru/showthread.php?t=657

Hacker VBI
30.03.2013, 10:38
Спасибо

ZXMAK
30.03.2013, 21:47
http://zxmak2.codeplex.com/SourceControl/changeset/view/22900#391359
Я вижу, что это связано с обращениями к памяти до #8000, и всё.
В общем, расположение кода лучше с #8000.

нет, не только, вот ULA от Spectrum128:


protected override void WriteMem4000(ushort addr, byte value)
{
contendMemory();
base.WriteMem4000(addr, value);
}

protected override void WriteMemC000(ushort addr, byte value)
{
if ((m_pageC000 & 1) != 0)
contendMemory();
base.WriteMemC000(addr, value);
}

protected void ReadMem4000(ushort addr, ref byte value)
{
contendMemory();
}

protected void ReadMemC000(ushort addr, ref byte value)
{
if ((m_pageC000 & 1) != 0)
contendMemory();
}

#region The same as 48

private void WritePortAll(ushort addr, byte value, ref bool iorqge)
{
contendPortEarly(addr);
contendPortLate(addr);
if ((addr & 0x0001) == 0)
{
int frameTact = (int)((CPU.Tact - 2) % FrameTactCount);
UpdateState(frameTact);
PortFE = value;
}
}

private void ReadPortAll(ushort addr, ref byte value, ref bool iorqge)
{
contendPortEarly(addr);
contendPortLate(addr);
int frameTact = (int)((CPU.Tact - 1) % FrameTactCount);
base.ReadPortFF(frameTact, ref value);
}



тут есть и обращение к портам и к области #4000 и к #C000 (причем в зависимости от замапленой страницы)

Hacker VBI
02.04.2013, 12:12
Alexander Makeev, вообще некоторая неразбериха, смотрю.
Первый случай - одновременное обращение к 4000-8000 (видео)
второй - обращение к 1,3,5,7 страницам

TmK
02.04.2013, 22:42
Есть два важных момента:
1. Медленная и быстрая память
2. Отображение экрана/отображение бордюра

Тормоза на оригинальных машинах происходят когда отображается экран и идет обращение к медленной памяти. вот тока не помню обращение к 7ffd тоже считается обращению к медленной памяти или нет (вроде да).

Обращение к медленной памяти - выполнение кода в медленной памяти, команды чтения/записи в область медленной памяти (также и все остальные где используется обращение к памяти - RR(HL), PUSH(если стек в медленной памяти) и т.п.)

у zx128, zx+2 медленными являются страницы: 1,3,5,7 (быстрые 0,2,4,6)
у zx+2A, zx+3 медленными являются страницы: 4,6,5,7 (быстрые 0,1,2,3)

во всех zx с одним окном проецирования страниц память выглядит так:
#0000-#3FFF страница 0 (перекрытое ПЗУ)
#4000-#7FFF страница 5
#8000-#BFFF страница 2
#C000-#FFFF страница 0

соответственно:
#4000-#7FFF - всегда медленная память
#8000-#BFFF - всегда быстрая память
#C000-#FFFF - в зависимости от того какая страница туда впечатана

Про задержки - они разные в зависимости от текущего такта на который попало обращение к медленной памяти и модели:
http://www.worldofspectrum.org/faq/reference/128kreference.htm

ZXMAK
24.04.2013, 02:13
Смысл задержек - простой, если в момент обращения к медленной памяти юла читает память, то проц тормозится до момента когда юла закончит свои дела, по сути, пока луч летит по экранной области, т.е юла занимает память и проц вынужден ждать. Прикол еще в том что под обращением проца к памяти понимается не только реальное обращение, но и обращение к портам, а также некоторые промежуточные состояния проца, когда он активирует memrq, но rd и wr не активирует, т.е к памяти реально не обращается

Barmaley_m
24.04.2013, 17:00
а также некоторые промежуточные состояния проца, когда он активирует memrq, но rd и wr не активирует, т.е к памяти реально не обращается
А что это за состояния такие? Мне на ум приходит только "регенерация памяти" во время цикла M1. Младшие биты шины адреса в этом случае берутся из регистра R, а старшие - кажется, из регистра I. В связи с этим, если регистр I указывает на медленную память - то тормоза будут постоянно, получается? Независимо от того, где выполняется код и откуда читаются/записываются данные?

Далее, проц обращается к памяти также во время цикла подтверждения прерывания. Я слышал, что на оригинальных спеках есть проблемы еще и из-за этого, т.е. нельзя допускать чтобы регистр I указывал на медленную память. Поправьте, если я ошибаюсь.

И еще. Продолжительность тормозов, в наихудшем случае, как я понимаю - это если проц обратился к памяти в начале отображения строки. Поскольку пиксельная частота 7МГц - то один такт 3.5МГц - это четверть знакоместа, а всего в строке 32 знакомест, т.е. максимальная задержка будет 128 тактов, а потом, до начала отображения следующей строки, задержек не будет? Есть ли реализации "умного" доступа к медленной памяти, когда проц обращается к ней только когда он "знает", что не столкнется с юлой?

SAM style
24.04.2013, 17:28
И еще. Продолжительность тормозов, в наихудшем случае, как я понимаю - это если проц обратился к памяти в начале отображения строки. Поскольку пиксельная частота 7МГц - то один такт 3.5МГц - это четверть знакоместа, а всего в строке 32 знакомест, т.е. максимальная задержка будет 128 тактов, а потом, до начала отображения следующей строки, задержек не будет?Нет, проц затормаживается не на все 32 знакоместа, а только до того момента, как ULA отпустит память. Если не ошибаюсь, максимальная задержка - 6 тактов

TmK
25.04.2013, 01:04
Смысл задержек - простой, если в момент обращения к медленной памяти юла читает память, то проц тормозится до момента когда юла закончит свои дела, по сути, пока луч летит по экранной области, т.е юла занимает память и проц вынужден ждать. Прикол еще в том что под обращением проца к памяти понимается не только реальное обращение, но и обращение к портам, а также некоторые промежуточные состояния проца, когда он активирует memrq, но rd и wr не активирует, т.е к памяти реально не обращается

oO!!!
Примеры команд вызывающие промежуточное состояние плз? не особо осознал.

Дмитрий
25.04.2013, 08:43
В связи с этим, если регистр I указывает на медленную память - то тормоза будут постоянно, получается?

Я слышал, что на оригинальных спеках есть проблемы еще и из-за этого, т.е. нельзя допускать чтобы регистр I указывал на медленную память. Поправьте, если я ошибаюсь.

Поэтому меня Pawel/RS постоянно по рукам бил, когда я I и обработчик прерываний помещал в адресах #4000-#7fff. У них на Байтах тогда программы глючили и не работали.

goodboy
25.04.2013, 10:49
вот наглядный пример работы участка кода в быстрой и медленной странице памяти.
http://zx.pk.ru/attachment.php?attachmentid=38871&d=1356084928

introspec
25.04.2013, 17:12
Примеры команд вызывающие промежуточное состояние плз? не особо осознал.

Если я правильно понимаю, о чём идёт речь, halt будет наиболее очевидным примером такой команды: "Each cycle in the HALT state is a normal M1 (fetch) cycle except that the data received from the memory is ignored and a NOP instruction is forced internally to the CPU."

SAM style
25.04.2013, 17:46
Если я правильно понимаю, о чём идёт речь, halt будет наиболее очевидным примером такой команды: "Each cycle in the HALT state is a normal M1 (fetch) cycle except that the data received from the memory is ignored and a NOP instruction is forced internally to the CPU."Судя по написаному, чтение с адреса PC происходит как обычно (mreq+rd), но PC не увеличивается (?), а считанный на шину данных код не выполняется.

ZXMAK
26.04.2013, 00:31
oO!!!
Примеры команд вызывающие промежуточное состояние плз? не особо осознал.

например:
DJNZ disp - на 5 тактов выставляет значение PC на шину адреса
RET c - на 1 такт выставляет значение IR (это как-раз то, о чем Barmaley_m выше спрашивал ;))
DEC (HL) - на 1 такт выставляет значение HL
и т.п.

Barmaley_m
27.04.2013, 02:47
DJNZ disp - на 5 тактов выставляет значение PC на шину адреса
И при этом что, активируется MREQ?

ZXMAK
27.04.2013, 06:35
И при этом что, активируется MREQ?

При этом ula думает что идет обращение к памяти, активируется помоемому rd без mreq или наоборот :). Надо смотреть диаграммы, я честно говоря уже не помню подробностей.

Alex Rider
27.04.2013, 13:34
djnz, если не это самое nz, читает смещение из памяти. Почему бы не выставить /MREQ при этом? Так же делают все команды, имеющие аргументы за кодом собственно команды. Некоторые команды без аргументов и "не команды" (типа цикла подтверждения прерывания) тоже читают и пишут память. push, например.

ZXMAK
27.04.2013, 16:43
djnz, если не это самое nz, читает смещение из памяти. Почему бы не выставить /MREQ при этом? Так же делают все команды, имеющие аргументы за кодом собственно команды. Некоторые команды без аргументов и "не команды" (типа цикла подтверждения прерывания) тоже читают и пишут память. push, например.

Речь идет о моментах, когда НЕТ обращения к памяти или портам, т.к процессор устанавливает не все сигналы необходимые для выборки из памяти. Но юла думает что такое обращение идет и тормозит процессор.