Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2002.10.10;
Скачать: [xml.tar.bz2];

Вниз

Программная модель работы железа. Тип с двумя полями данных.   Найти похожие ветки 

 
lipskiy   (2002-09-13 23:25) [0]

Сначала вопрос.
Есть ли возможность описать тип (или ф-ю) с двумя полями данных так, чтобы к полям переменной этого типа не нужно было обращаться через точку. То есть при чтении этой переменной всегда бы читалось второе поле, а при записи всегда чтобы сначала первое поле переписывалось во второе, а затем в первое поле записывалось входное значение.
Нужно примерно так:

var i : integer;
X : TDualBuffer; // где TDualBuffer - некий тип с двумя полями данных типа integer (или любого другого типа)
begin
X:= 1; //Внутри происходит так: X.Out:= X.In; X.In:= 1;
X:= 3; //Внутри происходит так: X.Out:= X.In; X.In:= 3;
i:= X; // Здесь i должно получить значение 1, а не 3
X:= 5; //Внутри происходит так: X.Out:= X.In; X.In:= 5;
i:= X; // Здесь i должно получить значение 3, а не 5
end;


Важно, чтобы по коду программы, где вызываются переменные такого типа, не фигурировали никакие поля (типа X.In или X.Out) или параметры в скобках, а было просто написано X и при чтении, и при записи.

Если кому интересно, объясню зачем нужно такое извращение.

Есть такая задача - написать программную модель работы цифрового устройства.
Упрощенно, основное отличие работы железа от программы в том, что в цифровом железе всегда есть тактовая частота, и за один такт происходит любое число действий (не операций) ПАРАЛЛЕЛЬНО. То есть за интервал времени, измеряемый единицами наносекунд, одновременно переключается все защелки (триггеры), которые управляются тактовой частотой.
В программе же, напротив, за один "такт" выполняется только одна операция (здесь не рассматриваем многопоточность, так как даже потоки псевдопараллельны, все равно в данный момент времени выполняется только один поток), то есть программа умеет выполняться только ПОСЛЕДОВАТЕЛЬНО.

Для того, чтобы смоделировать работу железа, необходимо за один виток цикла последовательно выполнить все действия, которые железо выполнит параллельно за один такт частоты.

Здесь возникает проблема "протягивания" данных по последовательным цепям.
Вот простой пример.
В железе есть цепочка из трех D-триггеров, соединенных последовательно и управляемых единой тактовой частотой.
A, B, C.
Каждый триггер представляет собой ячейку памяти на один бит, или, интерпретируя с программной точки зрения, каждый триггер это булевская переменная, принимающая одно значение из двух возможных.
Физически триггер имеет вход и выход.
На выходе всегда имеется то значение, которое хранится в памяти триггера (0 или 1).
На вход подается значение, которое может быть записано в триггер.
Запись происходит только (например) по положительному перепаду тактовой частоты (когда она переключается из 0 в 1).

Как происходит работа цепочки триггеров.
Триггеры включены последовательно: A->B->C.
Выход триггера С висит в воздухе, а на вход триггера А будем подавать 0 или 1.
Изначально все триггеры имеют нулевое состояние: A=0, B=0, C=0.
Подадим на вход триггера А единицу (1).
В момент положительного перепада тактовой частоты параллельно происходит три действия: запись единицы в А, запись нуля из А в В, запись нуля из В в С.
В момент следующего перепада тактовой частоты произойдет аналогичная перезапись данных: в А снова запись 1, из А в В запись 1, из В в С запись нуля.

То есть данные перезаписываются последовательно слева направо, это сродни операции Shr в Дельфи - сдвижки на один бит вправо.

Так вот, вся проблема программного моделирования в том, что если я напишу в одном витке цикла так:
B:= A;
C:= B;
то это будет неверно, так как значение А за один "такт" (идин виток цикла) сразу же попадает в С, а должно за два такта.
Можно писать модель в обратной последовательности:
C:= B;
B:= A;
это будет логически верно, но совершенно ненаглядно по коду программы, писать в обратном порядке неприемлимо, так как модель должна будет постоянно модифицироваться, исследоваться, и все время думать наоборот тяжело.

Возникает такая идея, каждый триггер описать переменной сдвумя полями, типа записи.
При записи в такую переменную внутри нее сначала входное поле переписать в выходное, а затем уже заполнить входное новым значением. Это уже некоторое отступление от представления в железе, но другого варианта пока не вижу. Логически же работа в этом случае будет верной.

Так можно ли описать такой тип или написать такую функцию, чтобы обращение к ней в тексте кода выглядело как к обычной переменной?


 
MBo   (2002-09-14 06:31) [1]

Совсем без точки не получится, но одним свойством обойтись можно.
Обрати также внимание на TQueue

type
TQ=class
private
FFirst,FSecond:Integer;
function GetQQ: Integer;
procedure SetQQ(const Value: Integer);
published
property QQ:Integer read GetQQ write SetQQ;
end;


procedure TForm1.Button1Click(Sender: TObject);
var Q:TQ;
begin
Q:=TQ.Create;
Q.QQ:=1;
memo1.lines.add(IntToStr(q.qq));
Q.QQ:=2;
memo1.lines.add(IntToStr(q.qq));
Q.QQ:=3;
memo1.lines.add(IntToStr(q.qq));
Q.Free;
end;

{ TQ }

function TQ.GetQQ: Integer;
begin
Result:=FSecond;
end;

procedure TQ.SetQQ(const Value: Integer);
begin
FSecond:=FFirst;
FFirst := Value;
end;


 
TTCustomDelphiMaster   (2002-09-14 10:48) [2]

lipskiy © (13.09.02 23:25)
Вы создаете очень примитивную модель цифрового устройства. Используйте возможности ООП, они подойдут как нельзя кстати для такой задачи.
Создайте классы описывающие схему например такие

...
TTrig = class // Триггер
private
outxxx: boolean;
public
_in: TTrig;
_out: boolean;
procedure StartTick();
procedure EndTick();
end;

TQuartz = class(TObjectList) // Генератор частоты
public
procedure Tick();
end;

implementation

{$R *.DFM}
procedure TTrig.StartTick();
begin
if _in <> nil then
outxxx := _in._out;
end;

procedure TTrig.EndTick();
begin
if _in <> nil then
_out := outxxx;
end;

procedure TQuartz.Tick();
var
i: integer;
begin
for i:= 0 to Count-1 do
if (Items[i] is TTrig) then
TTrig(Items[i]).StartTick;
for i:= 0 to Count-1 do
if (Items[i] is TTrig) then
TTrig(Items[i]).EndTick;
end;

end.


Создайте несколько триггеров и кварц. Соедините их между собой с помощью TTrig._in. Подсоедините к генератору частоты (занесите триггеры в список TQuartz). Затем вызывайте TQuartz.Tick который имитирует 1 такт. Смотрите значения на выходах триггеров.


 
lipskiy   (2002-09-14 21:17) [3]

MBo © (14.09.02 06:31)
Да, этот вариант понятен, жаль, что без точки никак.
Но ведь есть же в Паскале, например, ф-я Port для работы с портами. Сейчас, к сожалению, Паскаля у меня нет и не могу глянуть исходники. Но мне кажется, что при чтении из порта и при записи в порт должен выполняться разный код. Тем не менее ф-я вызывается одинаково и для чтения и для записи, указывается только номер порта:
Port[$300]:= $100;
b:= Port[$300];
Как это делается, когда одна функция выполняет разный код при чтении и при записи?

TTCustomDelphiMaster © (14.09.02 10:48)
Именно примитивная модель мне и нужна. Цель модели - создать по ней живое устройство, просто переведя код Дельфи-программы в код VHDL-программы (языка программирования для чипов PLD, принципиальная схема которых формируется не паяльником, а программно, и грузиться в чип через интерфейс загрузки JTAG например). Поэтому модель должна быть максимально приближена к физическим элементам чипа, так как в устройствах PLD объектный принцип присутствует лишь отчасти и ненастолько гибок, как, например, в Дельфи.


 
lipskiy   (2002-09-14 21:25) [4]

TTCustomDelphiMaster © (14.09.02 10:48)
Но вообще идея интересная, надо обдумать, спасибо.


 
Mikhan   (2002-09-14 21:42) [5]

>Port[$300]:= $100;
>b:= Port[$300];

No problem, без точки, но с кв. скобками :) - свойство-массив со спецификатором default (как Strings[i] в TStringList )




 
lipskiy   (2002-09-15 02:22) [6]

Mikhan (14.09.02 21:42)
Угу, понятно...



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2002.10.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.01 c
1-31764
Hammer1
2002-10-01 09:08
2002.10.10
DELPHI и VB


1-31727
yaJohn
2002-09-30 12:36
2002.10.10
Вставить ActiveX в документ.


4-32055
SPeller
2002-08-22 20:44
2002.10.10
Скроллбар


1-31894
PaRL
2002-09-29 15:28
2002.10.10
Глобальные переменные.


1-31740
Chlavik
2002-09-27 20:12
2002.10.10
Броблемы с сохранением масива.......





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский