2010-07-27:

Co tam mam na warsztacie, czyli HWFramework

hwframework:medium:c++
Po CONFidence stwierdziłem, że fajnie byłoby się pobawić różnymi starymi rozwiązaniami sprzętowo-software'owymi, typu ANTIC i P/M, HAM6, itd. Jak to osiągnąć?

Oczywistym rozwiązaniem jest sprawić sobie poszczególne kawałki hardware'u, tj. np. Atari 800 XL, Amigę z AGA, etc, a następnie zainstalować/skolekcjonować/załatwić jakieś (I)DE/SDK, po czym przejść do zabawy w/w rozwiązaniami.
Innym rozwiązaniem jest ściągnięcie istniejących, i działających całkiem nieźle, emulatorów Atari, Amigi, etc - rozwiązanie tanie i szybkie :)
Jest jeszcze trzeci sposób - można samemu stworzyć emulator takiego chipu, może nie idealnie 1:1 zgodnego z oryginałem, ale coś podobnego i tym się pobawić - niewątpliwie ma to pewne dodatkowe walory poznawczo-rozwojowe.
Można iść jeszcze o krok dalej i zrobić framework do tworzenia takich emulatorów - i tym właśnie jest^H^H^H^H^H ma być HWFramework.

HWFramework 0.0.1 prealpha 1


Konkretniej rzecz biorąc, HWFramework ma być:
* frameworkiem edukacyjnym
* szkieletem do tworzenia emulatorów systemów komputerowych
* zbiorem emulatorów zewnętrznych urządzeń (typu monitor, klawiatura, myszka, głośniki, etc)
* oraz zbiorem emulatorów pewnych typowych urządzeń systemowych (np. kontroler pamięci, timer, etc)
A to wszystko w C++ i do tego open source.

Istotne jest dla mnie, aby przy pomocy HWFramework można było stworzyć kompletny system komputerowy, włączając w to kartę graficzną, CPU, kartę sieciową, etc.

Cały projekt ma charakter strikte edukacyjny - HWFramework nigdy nie będzie specjalnie szybki (przy testach dostałem 1.5MHz max póki co), jak i również nie będzie się nadawał do tworzenia działających real-time emulatorów istniejących systemów komputerowych - wynika to choćby z założeń jakie poczyniłem podczas projektowania całości, tj.:
* jest tylko jedna, duża, wspólna magistrala dla wszystkich urządzeń, w której minimalną jednostką przesyłu jest BAJT (a nie bit jak można by oczekiwać)
* jest tylko jeden zegar taktowany z jedną częstotliwością, na cały system
* jest tylko jeden sterownik przerwań (chociaż tutaj się zastanawiam czy jest on w ogóle potrzebny ;p)
Powyższe założenia ułatwiają definiowanie nowego systemu komputerowego (np. nie trzeba deklarować które porty jednego urządzenia są połączone z którymi portami innego urządzenia), ale też skutecznie uniemożliwiają odtworzenie np. pełnej architektury x86 (coś za coś).

OK, a teraz, po co komu to? ;)

Ręka do góry kogo ciekawiło np. jak działa karta graficzna? Noo, więc korzystając z HWFramework zainteresowana osoba może sobie stworzyć dowolną (ograniczoną jedynie wyobraźnią i zegarem) kartę graficzną, czyli:
* wymyślić jak karta graficzna ma działać (np. VRAM dostępny dla głównego CPU przez kontroler pamięci, zaimplementowany tryb 320x200x8bit z paletą kolorów)
* zaprojektować i zaimplementować procesor dla karty graficznej (rejestry, zestaw instrukcji, etc)
* napisać firmware pod ten procesor, który z jednej strony udostępni głównemu CPU pewne API, a z drugiej strony będzie realizować protokół przesyłania danych do monitora CRT
* napisać testowy program na główny CPU :)
* a potem dodać trochę bajerów, typu bliter, sprite'y, HAM6, może nawet jakieś 3D! ;>

Z projektem w zasadzie dopiero ruszyłem, i zrobione jest tylko kilka rzeczy:
* główny szkielet (porty, przerwania, klasa bazowa dla CPU)
* emulator CRT z częściowo zaimplementowaną funkcjonalnością (jakiś detali brakuje)
* prosty emulator kontrolera pamięci (z wbudowaną pamięcią 64KB i 16-bitową szyną adresową; planuje dodać jeszcze trochę ciekawszy kontroler)
* jakiś fragment testowego CPU i testowego kodu

Nadal brakuje sporej części funkcjonalności, jak i najważniejszego - dokumentacji całości. Ale pewnie w przyszłości

W każdym razie, poniżej znajduje się link do paczki z obecną wersją frameworku (0.0.1.prealpha.1). Pewnie za jakiś czas wrzucę nową wersję z lepszym kontrolerem pamięci i jakimś lepszym przykładowym CPU i przykładową kartą graficzną, a potem zastanowię się czy projekt warto dalej rozwijać :)

No i tyle :)

hwframework_release_0_0_1_prealpha_1.zip (414 KB, Source + Windows EXE)

P.S. chwilowo kod działa tylko na Windows z uwagi na moduł CRT który korzysta z WinAPI, ale docelowo przejdę na SDL

Comments:

2010-07-27 21:51:36 = mt3o
{
>Ręka do góry kogo ciekawiło np. jak działa karta graficzna
Niektórzy z tego powodu mają przedmiot więcej do zaliczenia we wrześniu...
Projekt ciekawy, tylko obawiam się, że bez solidnych podstaw teoretycznych dotyczących sprzętu ciężko będzie zbudować cokolwiek mającego ręce i nogi, w oparciu o twój framework.

> jest tylko jeden sterownik przerwań (chociaż tutaj się zastanawiam czy jest on w ogóle potrzebny ;p)
Jak bez sterownika przerwań zrobisz to, co zwykle robi sterownik przerwań? Chociażby obsługę klawiatury? Nie bardzo mogę to sobie wyobrazić, możesz napisać coś więcej albo wskazać jakiś tekst na ten temat?
}
2010-07-27 21:56:25 = MeMeK
{
gr8 ;> Sam myślałem kiedyś nad takim projektem emulatora fizycznego systemu komputerowego z DMA, magistralami itp. Jednak z braku czasu był on ciągle odkładany na "później" :> hf & gl
}
2010-07-27 23:32:57 = Gynvael Coldwind
{
@mt3o
Hehehe, cóż, kampania wrześniowa, na studiach co roku ;)
Anyway, jak pisałem, jest to framework edukacyjny, więc chodzi właśnie o to by przetestować własne pomysły i nabyć trochę wiedzy, a niekoniecznie już ją mieć ;)
Zresztą, nie wszystko co ciekawe musi mieć ręce i nogi - to nie komercyjne aplikacji ;)

Ad przerwania - no właśnie po zaimplementowaniu szkieletu okazało się, że przerwania są niejako redundantne względem portów na poziomie "wnętrza" CPU. Tj. mimo braku przerwań w szkielecie, można i tak je uzyskać w CPU - i w zasadzie właśnie tak jest to robione w CPU czy mikrokontrolerach, tj. sterownik przerwań nie jest globalny, tylko lokalny, w chipie.
Więc to, że je usunę ze szkieletu, nie znaczy że się ich pozbędę ;) Po prostu zmienię miejsce implementacji ;)

@MeMeK
Hehe zachęcam w takim razie do pobawienia się z powyższym frameworkiem (może jeszcze nie teraz, a przy okazji następnej wersji ;>) ;>


}
2010-07-28 06:48:25 = al kvazir ibn szatan
{
Wrzuciłbyś to na githuba zamiast zipy jak w XX wieku załączać
}
2010-07-28 09:00:53 = Marwy
{
A co jest złego z zipami?
}
2010-07-28 13:03:11 = Gynvael Coldwind
{
@al kvazir ibn szatan
Jak zdecyduje się rozwijać projekt, to pewnie wrzucę na jakieś github, google code czy inny sourceforge, ale, jak pisałem w poście, póki co decyzję o tym odroczyłem ;)
Poza tym, nie widzę nic złego w paczkach .zip ;)
}
2010-07-28 15:34:55 = Agares
{
Paczki zip ssą, bo nie można przeglądać kodu on-line.

A co do samego projektu, to całkiem ciekawy, choć z drugiej strony trochę szkoda że są te wszystkie ograniczenia(wybacz, jestem idealistą, zwłaszcza jeśli marudzę komuś innemu :D). Ale i tak pogratulować, bo wyobrażam sobie ile to pracy napisać takie cudo.
}
2010-07-28 17:39:48 = Gynvael Coldwind
{
@Agares
Szczerze to nie przekonuje mnie Twój argument ;)
Moim zdaniem dużo wygodniej kod przegląda się na dysku, korzystając z przystosowanych do tego narzędzi, niż via browser ;)

Szczerze to moim zdaniem te ograniczenia aż tak bardzo nie ograniczają, jeśli się pamięta jaki jest cel tego projektu ;)
}
2010-07-28 18:04:38 = mh
{
Paczki zip ssą, bo mamy .tar.xz ;)
}
2010-07-28 18:14:43 = Gynvael Coldwind
{
@mh
^_-
}
2010-07-28 18:51:03 = al kvazir ibn szatan
{
kod z paczek zip słabo się forkuje (BTW: jaka licencja?)
}
2010-07-28 19:30:59 = raphael
{
Podeślij jakieś linki o tym jak programować kartę graficzną lub inne urządzenia. Trzeba odświeżyć stary projekt.
Ja napisałbym do tego jakiś Asembler, bo ciężko tak w Nasmie pisać. Też się zbieram bo sam to hexeditem 'kompilowałem'. Dałoby się też, co pasuje do projektu, 'generator Asemblerów'.
*.tar.gz lepiej :)
}
2010-07-28 20:35:45 = Gynvael Coldwind
{
@al kvazir ibn szatan
A tam, forki "na stałe" robi się tak samo prosto :D
Co do licencji, jeszcze nieokreślona (co widać po jej braku w paczce ;>)
}
2010-07-28 20:39:03 = Gynvael Coldwind
{
@raphael
Linków brak ;)
Co do assemblera, to hmm, szczerze to nie widzę powodu. System makr w nasm doskonale się nadaje do przerobienia nasma na assembler dowolnego procesora ;)
Zresztą w paczce w test.asm widać to w akcji:

--test.asm--
[bits 16]

; MyCPU Assembler
; 16-bit Registers: r0 - r6
; 16-bit Instruction Pointer: pc alias r7
; Opcodes:
; opcode cycles desc
; 00 rX rY 1 mov <rX>, <rY>
; 01 rX rY 1 add <rX>, <rY>
; 02 rX imm16 1 ldi <rX>, imm16
; 03 rX addr 2+ (avg 2.5) ldr <rX>, addr
; FF 1 hlt
;
; ldr instruction cycle count depend on the
; response time of the RAM controler; this is
; at least one cycle for decode and comunication
; with the ram controler, and another cycle to get
; the data back; however, if the RAM controler is
; very busy, this can take many cycles

%define r0 0x00
%define r1 0x01
%define r2 0x02
%define r3 0x03
%define r4 0x04
%define r5 0x05
%define r6 0x06
%define r7 0x07
%define pc 0x07

%macro mov 2
db 0x00, %1, %2
%endmacro

%macro add 2
db 0x01, %1, %2
%endmacro

%macro ldi 2
db 0x02, %1
dw %2
%endmacro

%macro ldr 2
db 0x03, %1
dw %2
%endmacro

%macro hlt 0
db 0xff
%endmacro

start:
ldi r0, 0x1234
mov r1, r0
add r0, r1
ldr r1, 0x1234
hlt

--EOF test.asm--
}
2010-07-29 14:32:55 = Ahmed
{
Gyn tęsknisz za ośmiobitowcami co? :) Mam nadzieję, że stare zakurzone "Bajtki" i "Komputer" weźmiesz do Zurich'u (przynajmniej tą zdigitalizowaną część ;) ). Pozdrawiam!
}
2010-07-29 14:55:03 = Dreadlish
{
Z prędkością nie jest źle - by można było wrzucić jeszcze ommit-framepointer i może by troche przyśpieszył.
}
2010-07-29 21:26:52 = Gynvael Coldwind
{
@Ahmed
Trochę tak hehehehe :) Może nie tyle tęsknie, co chciałbym mieć trochę czasu żeby się nimi pobawić, tak na porządnie ;)
Anyway, "Bajtki" w żadnym wypadku nie zakurzone ;> Leżą na półce i od czasu do czasu je przeglądam - ludzie wtedy mieli kapitalne pomysły ;> Np. jakiś czas temu mi wpadł w oczy artykuł "jak zrobić kartę muzyczną do spectrum" ;D
Anyway, ofc do Zurichu jadą ze mną;D

@Dreadlish
Fanael wczoraj testował różne opcje i do 1.9 MHz wyciągnął, więc jest znośnie ;)
Mam kilka pomysłów na wykorzystanie kilku core'ów, może to też coś da, szczególnie przy większej liczbie urządzeń - z tego co wstępnie przeglądałem, to wystarczy, że natychmiastowy zapis do portu (jak jest teraz) zastąpię opóźnionym zapisem, tj. wykonywanym na koniec cyklu (+ dodam ofc wymagane synchronizacje dostepu), i tyle zmian ;)
}
2010-07-30 07:05:02 = Malcom
{
Od dawna co jakis czas przewija mi sie pomysl emulacji 6502 (C64), moze tym razem sie uda nie piszac wszystkiego od zera ;)
}
2010-07-30 17:20:40 = Fanael
{
Nawet do 2 MHz udało się dojść (jeśli dobrze pamiętam to przy pomocy 'g++ -O3 -march=native -fomit-frame-pointer -fno-exceptions -mfpmath=sse -mpush-args -mno-accumulate-outgoing-args -mno-stack-arg-probe', gcc 4.5.0), z tym, że nie bardzo można to porównywać z szybkością podaną w notce, bo widocznie mój komp jest szybszy niż Gyna (exek z paczki osiągał 1.7 MHz) ;>
}
2010-07-31 11:09:07 = Dreadlish
{
U mnie na pc wyciąga 2.3 bez niczego - procesor robi swoje 3x3.3GHz, na 2x2 oscyluje między 1.6-1.8 na czystym.
}
2010-07-31 12:06:50 = Dreadlish
{
Udało mi się uzyskać średnie 2.6MHz przy takiej linii G++:
-Wall -Wextra -O3 -mmmx -msse -msse2 -msse3 -mno-align-stringops -fomit-frame-pointer -fno-exceptions -mfpmath=sse -mpush-args -mno-accumulate-outgoing-args -mno-stack-arg-probe

Nie radze używać -momit-leaf-frame-pointer, ani -minline-all-stringops, bo zaniżają wynik. Próbowałem też zrobić z O2 - program nie chciał się nawet włączyć.
}
2010-08-01 21:28:12 = Gynvael Coldwind
{
@Malcom
Kurcze, nie jestem pewien czy ten framework się nada, z uwagi na uproszczenia o których pisałem... Ale może, może ;)

@Fanael, Dreadlish
Dobrze wiedzieć ;)
Zachęcam do testów porównawczych z następną wersją która się pojawi (jestem bardzo ciekaw co z tej optymalki przyszłej wyjdzie).
}
2010-08-19 08:24:42 = Makdaam
{
Mi się to bardzo skojarzyło z symulatorem układów logicznych napisanych w verilogu czy innym vhdlu. Na laborkach z elektroniki pisaliśmy różne projekty na FPGA, AFAIR kumpel zrobił tester do monitorów VGA, a ja sterownik do obsługi klawiatury PS/2... tylko, że to by było zbyt ogólne/powolne, żeby emulować całego 8bitowca na PC.

Gratuluję pomysłu :)
}
2010-10-10 18:17:56 = Malcolm
{
Mnie też zaciekawiła optymalizacja frameworka. Oryginał ~2.1, z flagami Dreadlish'a ~2,3. Moja wersja po małych przeróbkach ~3.1 (msvc) ;-) Zastanawia mnie też czy na pewno potrzeby jest tam random_shuffle? Funkcja jest bardzo ciężka, po jej usunięciu wzrost wydajności praktycznie 100% (~5,8). Warto się zastanowić czy robić bez niej, czy może jakoś uprościć losowość. P.S. Gynvael skąd te brzydkie przyzwyczajenie z używaniem wszędzie Self lub this? :)
}
2010-10-11 14:25:03 = Gynvael Coldwind
{
@Makdaam
Przyznaje że o FPGA za dużego pojęcia w tym momencie nie mam. Wisi to natomiast na mojej liście ToLearn, więc się w końcu tym zajmę :)

@Malcolm
Co do random_shuffle, to w nowej wersji tego już nie ma (z uwagi na przeróbkę architektury). Natomiast przyznaje, że nie wiedziałem że aż tak to zjada CPU (nie robiłem profilowania jeszcze).
Co do Self lub this: po prostu tak lubie i nie uważam tego za brzydkie :) Wiesz, kompilator i tak to tam wstawi, czy ja to napisze, czy nie, a przynajmniej od razu widać gdzie się odwołuje do klasy, a gdzie nie.
}

Add a comment:

Nick:
URL (optional):
Math captcha: 2 ∗ 7 + 4 =