Skocz do zawartości

Project A - czyli kolejny procesor w FPGA


Pomocna odpowiedź

Dnia 3.01.2020 o 18:21, marek1707 napisał:

W żadnym razie nie chodziło mi o niszczenie zaangażowania Kolegi @rafal2808 a raczej o pokazanie, a) że jest mnóstwo dobrych przykładów, b) że nawet prosty procesor jest o wiele bardziej skomplikowanym projektem niż się wydaje na pierwszy rzut oka.  ...

1) A tej uwagi o kompilatorze C nie bardzo rozumiem. Tworzenie kompilatorów jest dzisiaj zautomatyzowane, ale projektant sprzętu nie musi umieć ich pisać. Od tego są inni ludzie. Ma zrobić procesor, który nie ma wąskich gardeł i spełnia założenia (np. jeśli ma być programowany głównie w C to ma się niego dobrze pisać kompilatory - to też widać w architekturze) natomiast może i powinien przetestować swój procesor na wielu typowych programach/testach a do tego wystarczy asembler. Zaznaczam, że wciąż mówimy o małych, jednowątkowych maszynkach do nauko-zabawy w domu.

2) BTW: Chyba pamiętam ten walizkowy system na 8080.

EDIT: --------------------------------------

3) "Zgadzam się z Tobą, że jego architektura (MOS6502) była dużo lepsza od Intela 8080.."

Hej, nigdzie tego nie napisałem. Wspomniałem o minimalnej, czyli prostej do implementacji nawet dla początkującego a dającej już frajdę w pisaniu programów.

Cześć Marek,

odnośnie 1) - chciałem tylko zwrócić uwagę, że dla takiego "własnego" procesora raczej nigdy nie powstanie kompilator języka C. Nawet dla Picoblaze Xilinx'a nie jest dostępny działający kompilator języka C (jest jakiś napisany w ramach pracy magisterskiej przez czeskiego studenta, ale nie działa on prawidłowo). A była mowa o właściwościach procesora ułatwiających pisanie programów w języku C.

2) Mam do tego "komputerka" bardzo duży sentyment, na nim uczyłem się podstaw programowania i budowy CPU 😁

3) Może to wyłącznie moje subiektywne zdanie, ale o ile pamiętam to na MOS6502 programy pisało się fajniej niż na Intela 8080, szczególnie duża liczba dostępnych trybów adresowania była pomocna.

Pozdrawiam

  • Lubię! 1
Link do komentarza
Share on other sites

1. Wiesz, z tym kompilatorem to nie mozna przesądzać. Wszystko zależy od zainteresowań i umiejętności samego twórcy. Dziś (niestety?) bardzo się specjalizujemy i to jest normalne, bo nie spsób wiedzieć wszystkiego o wszystkim. Dlatego kiedyś (np. czasach np. "lampowych") będąc elektronikiem w zasadzie mogłeś policzyć i zbudować wszystko co było. Miałeś wybór między wzmacniaczem audio, odbiornikiem radiowym, jakimś przyrządzem pomiarowym czy nadajnikiem. Znano kilka sposobów modulacji i wszystkie były do zrozumienia i opanowania w godzinę. Dzisiaj jeśli elektronik zna się dobrze na jakiejś rodzinie przetwornic impulsowych to jest fachowcem w tym temacie, inny wie dużo o pewnej klasie wzmacniaczy operacyjnych a inny ma w małym palcu układy RF. I oczywiście każdy z nich zbuduje ultradźwiękowy wykrywacz nietoperzy, ale żaden z nich osobno nie stworzy kompletnego hydrofonu dla okrętu podwodnego. Nawet nie myślę czy projektant FPGA to jest jeszcze elektornik czy już programista a już ktoś kto bierze udzaiał w przedsięwzięciu pt. GCC programistą musi być z definicji. Natomiast wracając do zabaw amatorskich, to na pewnym poziomie da się posiadać wiedzę rozległą. I wtedy jeden człowiek może zaprojektować i płytkę do FPGA i sprzętowe otoczenie układu (zasilanie, interfejsy) i zrobić projekt wnętrza i napisać asebmbler a w końcu stworzyć kompilator C, Pascala czy Ady. Wszystko z takiego samego powodu z jakiego Ty bawisz się w AVR na FPGA - dla czystego fanu, bo przecież nie ma szans by wymyślony w domowym zaciszu procesorek znalazł dziś jakieś komercyjne zastosowanie. Daleko szukać: ze mnie jest programista jak z koziej dupy trąba, a napisałem od zera i asemblery kilku procesorów i interpreter BASCIa dla swojego komputerka, bo to było fajne 🙂 Także: nigdy nie wiadomo.

3. Z gustami sie nie dyskutuje. Ja generalnie lubię konstrukcje z tamtych lat, mogę dyskutować o ich wadach i zaletach względem pozostałych, ale nie wyróżniam jakoś istotnie któregoś. To był czas bardzo szybkiego rozwoju i każda następna generacja chipów mogła mieć więcej tranzystorów co od razu było widać w architekturze i liście instrukcji. 8080 miał sporo rejestrów i dużo instrukcji co było miłe, a brakujące tryby adresowania można było emulować dzięki kilku instrukcjom arytmetyki 16-bitowej (dodawanie, inkremetacja, dekrementacja całych par rejestrów). Miał fajnie przemyślane wsparcie przekazywania parametrów przez stos lub przez umieszczanie argumentów za wywołaniem i to była spora zaleta. 6502 płacił za rozbudowane tryby adresowania czasem wykonania i ubogą listą instrukcji. Liczba rejestrów także była minimalna bo jak zwykle.. kołderka była za krótka. Jeśli rozbudowałeś sterowanie/sekwencer to brakowało powierzchni na jednostkę obliczania adresów czy rejestry. Przecież 6502 liczył 16-bitowe adresy za pomocą 8-bitowego sumatora co w przypadku przekroczenia 256-bajtowej strony wymuszało wydłużenie czasu o 1-2 cykle maszynowe - dziś to się wydaje śmieszne. Za to skromne wyposażenie w rejestry kompensował krótkimi instrukcjami adresującymi stronę zerową, ale już tylko 256 bajtów na stos na stronie 1 było poważnym ograniczeniem. To co prawda były czasy gdy 1Kbajt RAMu to już było coś więc tak bardzo nie bolało, ale RAMy rosły chyba wtedy szybciej niż procesory.. Tak samo można pisać o każdej innej konstrukcji z tamtego okresu. Coś wymyślili lepiej, ale zabrakło tranzystorów na coś innego i Centralny Wyrównywacz w postaci ograniczeń technologicznych obowiązującyh wszystkich bez wyjątku działał niezwykle sprawnie. Dzisiaj mamy ten komfort, że możemy na te projekty spojrzeć zimnym okiem i bez emocji porównywać a przede wszystkim na nich się uczyć. Dostępne są przecież dokumentacje chyba do wszystkich istotnych maszyn z tamtego okresu. Proponuję zatem zagłębić się w temat, czytać i.. podziwiać 🙂 

Moje typy: PDP-8, PDP-11, AGC, 6800, 65xx, 4004, 4040, 8008, 8080, Z80, 8048, 8051, PIC16, Z8... Każdy z nich miał coś wyjątkowego,, co zwykle było jakimś kamieniem milowym w rozwoju procesorów albo przynajmniej był wzorcowym przykładem optymalzacji projektu w obecności poważnych ograniczeń i wielu sprzecznych wymagań. Trywialny przykład: przecież 4004 nie był tak mały (fizycznie) dlatego, że to było wygodne (bo nie było) tylko dlatego, że nie było sprawdzonych większych obudów do scalaków. DIP24 czy DIP40 to dopiero przyszłość..

  • Lubię! 2
Link do komentarza
Share on other sites

1 godzinę temu, marek1707 napisał:

Moje typy: PDP-8, PDP-11, AGC, 6800, 65xx, 4004, 4040, 8008, 8080, Z80, 8048, 8051, PIC16, Z8... Każdy z nich miał coś wyjątkowego,, co zwykle było jakimś kamieniem milowym w rozwoju procesorów albo przynajmniej był wzorcowym przykładem optymalzacji projektu w obecności poważnych ograniczeń i wielu sprzecznych wymagań. Trywialny przykład: przecież 4004 nie był tak mały (fizycznie) dlatego, że to było wygodne (bo nie było) tylko dlatego, że nie było sprawdzonych większych obudów do scalaków. DIP24 czy DIP40 to dopiero przyszłość..

Cześć,

z tych wymienionych znam Z80 i PDP11 (dokładnie zwalona jednostka centralna z PDP [rosyjski układ scalony] była w sterownikach dysków twardych z krajów RWPG - chyba bułgarskich). PDP-11 miał bardzo ciekawą listę rozkazów, szczególnie rozkazy dwu-adresowe to było coś fajnego (gdzie rozkaz mógł działać nawet na dwóch lokalizacjach w pamięci).

Co do reszty przemyśleń to się zgadzam, miło powspominać tamte czasy 😉 Kto wie może masz rację, że Rafał napisze kiedyś jakiś assembler lub kompilator dla swojego CPU.

Pozdrawiam

  • Lubię! 1
Link do komentarza
Share on other sites

Tak szczerze mówiąc to bez jakiegokolwiek wsparcia trudno mówić o zabawie we własny procesor. No bo ile można dłubać na kartce papieru kody szesnastkowe? No dobra, trochę można, ale żaden większy program w ten sposób nie powstanie. Liczenie adresów skoków - szczególnie po zmianach w kodzie - to najbardziej głupia i żmudna robota. Język mnemoniczny jest jednak na tyle prosty, że już dziesiątki lat temu powstały asemblery uniwersalne, tzw. meta--asemblery, sterowane tablicami umieszczanymi w plikach konfiguracyjnych. Swego czasu używałem namiętnie czegoś co nazywało się CROSS-16, pracowało pod DOS-em i miało "w pakiecie" tablice dla większości 8-bitowych procesorków (a na pewno 8080, 6502, 8048, 8051, Z80 itp). Stworzenie swojej własnej dla nowego procka w FPGA, mając podręcznik albo nawet patrząc jak zrobione są te już gotowe nie powinno stanowić problemu. Wierzę, że jest to gdzieś do znalezienia w sieci.

A propos. Skoro mówimy o pisaniu programów, to dobrze jest - tworząc taki procesor - przewidzieć możliwości ładowania kodu i debugowania. Jakiś interfejs ze świata zewnętrznego (SPI? USB? cokolwiek) umożliwiający przeładowanie nowego programu bez konieczności rekompilacji FPGA jest koniecznością, którą trzeba tworzyć razem (a może raczej wokół lub obok) ze strukturą procesora. To samo z uruchamianiem: mając prawie nieograniczone możliwości logiki bez poblemu można wbudować w jądro jakieś wsparcie w tym zakresie: wymuszanie startu, stopu, pracy krokowej, podgląd rejestrów i pamięci, pułapki na adresach programu czy pamięci danych itd itp.

BTW: Zapomniałem o TMS9900 - ciekawym, bezakumulatorowym 16-bitowcu od Texasa, oraz o 6100 czyli o 12-bitowym CPU z PDP-8 na jedym chipie od Intersila 🙂 

  • Lubię! 2
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

8 minut temu, marek1707 napisał:

A propos. Skoro mówimy o pisaniu programów, to dobrze jest - tworząc taki procesor - przewidzieć możliwości ładowania kodu i debugowania. Jakiś interfejs ze świata zewnętrznego (SPI? USB? cokolwiek) umożliwiający przeładowanie nowego programu bez konieczności rekompilacji FPGA jest koniecznością, którą trzeba tworzyć razem (a może raczej wokół lub obok) ze strukturą procesora. To samo z uruchamianiem: mając prawie nieograniczone możliwości logiki bez poblemu można wbudować w jądro jakieś wsparcie w tym zakresie: wymuszanie startu, stopu, pracy krokowej, podgląd rejestrów i pamięci, pułapki na adresach programu czy pamięci danych itd itp.

BTW: Zapomniałem o TMS9900 - ciekawym, bezakumulatorowym 16-bitowcu od Texasa, oraz o 6100 czyli o 12-bitowym CPU z PDP-8 na jedym chipie od Intersila 🙂 

Tak,

zgadzam się w pełni - zewnętrzny interfejs do debugowania CPU i bootloade r(działający np. na UART'cie) umożliwiający wczytanie programu dla procesora to bardzo pomocne i ważne części projektu CPU.

TMS9900 niestety nie znam i nie miałem z nim do czynienia.

Pozdrawiam

  • Lubię! 1
Link do komentarza
Share on other sites

Po otrzymaniu rad od @FlyingDutch oraz @marek1707 postanowiłem zmienić nieco założenia całego projektu. 

Project A będzie 8-bitowym procesorem zrealizowanym na układzie FPGA, początkowo planowałem umieścić go na płytce Elbert v2 jednak w międzyczasie udało mi się zdobyć płytkę Core3S500E na której umieszczono chip FPGA dysponujący zasobami większymi niż ten umieszczony na Elbert v2.  Tak więc Project A będzie bazować Core3S500E. 

Modułowa budowa procesora w stylu podobnym jak np.Nios II na razie odpada, a bardziej przerasta moje możliwości. Architektura również uległa pewnym zmianą, postaram się  udostępnić ją w najbliższym czasie.

Planuję wprowadzić cztery tryby adresowania: natychmiastowy, rejestrowy, bezpośredni oraz pośredni. Ułatwią one znacznie programowanie procesora. 

Układ wspierać będzie interfejsy UART i I2C, oraz obsługa wyświetlaczy LCD i 7 segm.

Na początek planuję zaprojektować bardzo prosty układ przerwań wspierający tylko jedno maskowalne przerwanie zewnętrzne. Po jego otrzymaniu procesor zapisywał będzie tylko adres powrotu. Stan innych rejestrów będzie w pełni zależny od programisty. Ich zawartość można będzie odłożyć na stosie, którego obsługa również zostanie dodana. 

Procesor posiadać będzie dodatkowe 8 rejestrów ogólnego przeznaczenia, nie będą one jednak osobną strukturą a wydzielonym obszarem pamięci RAM.

Programowanie odbywać się będzie podobnie jak w moich wcześniejszych projektach poprzez określenie zawartości pamięci w pliku VHDL. 

Wiem że są to dość szczątkowe informacje na temat mojego procesora, ale chciałem dać znać że Project A nie został zapomniany😉.   

 

  • Lubię! 1
Link do komentarza
Share on other sites

Heh, w ciągu ostatniego miesiąca zrobiłem sobie kompletny 8080 w architekturze mikroprogramowanej. W końcu przechodzi wszystkie testy napisane dla tego procesora a nie dalej jak w weekend skompilowałem na PC odpaliłem na FPGA interpreter BASIC'a napisany w 1976 roku przez Li Chen Wanga 🙂 (Tiny BASIC). Oczywiście sam procesor to za mało więc dostał (na razie) wyjście VGA, i UART. To pokazuje, że warto korzystać z popularnych architektur - oprogramowanie jest gotowe (od 40 lat..) i czeka. Moim zdaniem (chyba już to pisałem) lepiej poćwiczysz swój ulubiony język opisu sprzętu na znanej i możliwej do przetestowania architekturze (mając jakiś jasny cel: ma na tym ruszyć CP/M albo gra z C16/C64) niż walcząc z problemami złych (lub niekompletnych) założeń w nowym układzie. No ale to Twój wybór.

A teraz o Twoim nowym pomyśle. Co to znaczy, że "Układ wspierać będzie interfejsy UART i I2C, oraz obsługa wyświetlaczy LCD i 7 segm"? Przecież procesor to procesor, wykonuje instrukcje i ma kontakt ze światem poprzez magistrale. Co ma do tego wspieranie, bądź nie, jakichś konkretnych peryferiów. Ze swojej strony radzę, byś rozejrzał się trochę w świecie OpenCores, bo w tworzeniu bloków dla FPGA także obowiązują pewne standardy. Jednym z nich jest kilka rodzajów magistral. Ja u siebie korzystam z Wishbone - przyjąłem go z dobrodziejstwem układów f-my Lattice na których głównie działam,  ale są i inne, np. AXI czy AMBA. Jeżeli już raz przyjmiesz sobie jakiś typ magistrali staraj się, by wszystkie bloki jakie zrobisz do niej pasowały. Na początek musisz zapewnić, aby Twój procesor "widział świat" właśnie przez okno np. Wishbone a potem - czy zrobisz I2C czy driver 7-seg czy kontroler SDRAM czy UART czy cokolwiek innego - wszystko podłączysz do procesora przez proste dołączenie kolejnego jądra do projektu, z ew. ustaleniem mapy adresów itp. W żadnym wypadku nie włączaj do procesora bloków które w jakiś sposób są specjalizowanymi interfejsami zewnętrznymi a już na pewno nie wymyślaj żadnych specjalnych instrukcji do ich obsługi itp. Wszystko co nie jest jądrem wykonującym instrukcje wywalaj na zewnątrz: DMA, timery, kontroler przerwań i oczywiście wszystkie porty, UARTy itd. Każda z tych rzeczy powinna być widoczna jako zestaw rejestrów w przestrzeni I/O lub w pamięci (nie wiem czy to rozdzielasz)z łatwym , zaszytym w kodzie Veriilog/VHDL mechanizmem przydzielania adresów. A najlepiej skupić to wszystko w jednym arbitrze pamięci do którego procesor zgłasza się jako master inicjujący transfer a ten "przesyła" takie żądanie do odpowiedniego bloku slave, który po wykonaniu przesłania potwierdza to odpowiednim sygnałem. W takiej architekturze możesz dowolnie łączyć ze sobą bloki i wyposażać swój procesor w coraz to nowe peryferia lub pamięci.

A o ładowaniu RAMu programem i mechanizmach debugowania pomyśl na samym początku a nie dopiero gdy staniesz przed problemem błędu w pierwszym programie. Rozwiązaniem może być np. osobny UART z prostym FSM odbierający ramki danych wprost z PC lub nawet SPI_SLAVE podłączony do Arduino, które odbiera dane z PC (udając jakiś popularny programator) i zamienia to na komendy ładowania danych do RAMu Twojego procesora - można oprzeć się na gotowych programatorach np. EEPROMów czy FLASHy opartych na Arduino. To samo z pracą krokową i/lub podglądem rejestrów.

No i napisz, czy odrobiłeś pracę domową tzn.  czy jesteś za pan brat z istniejącymi już projektami procesorów? Czy możesz opisać (samemu sobie, nie musisz się tu spowiadać) cechy które w nich się spodobały, wady albo wąskie gardła przyjętej architektury?

Czekamy oczywiście na szczegóły: długość adresów i możliwe na nich operacje, rodzaj stosu, konstrukcję ALU i najważniejsze, które skupia to wszystko razem czyli listę instrukcji.

  • Lubię! 2
Link do komentarza
Share on other sites

Dnia 5.03.2020 o 19:31, marek1707 napisał:

Moim zdaniem (chyba już to pisałem) lepiej poćwiczysz swój ulubiony język opisu sprzętu na znanej i możliwej do przetestowania architekturze (mając jakiś jasny cel: ma na tym ruszyć CP/M albo gra z C16/C64) niż walcząc z problemami złych (lub niekompletnych) założeń w nowym układzie. No ale to Twój wybór.

Oczywiście tego typu projekty są bardzo ciekawe, jednak tym razem chciałbym zaprojektować coś swojego. Nawet jeśli będzie to obarczone wieloma błędami, a bądźmy szczerzy będzie, to mimo wszystko dla mnie osobiście proces rozwiązywania tych problemów jest jak najbardziej przyjemny. 

Dnia 5.03.2020 o 19:31, marek1707 napisał:

Co to znaczy, że "Układ wspierać będzie interfejsy UART i I2C, oraz obsługa wyświetlaczy LCD i 7 segm"?

Miałem tutaj na myśli iż układ posiadał będzie dedykowane bloki oraz rejestry odpowiedzialne za obsługę tych interfejsów.

Przy okazji uświadomiłem sobie że trafniejszym określeniem mojego projektu będzie mikrokontroler, nie procesor. 

architektura1.thumb.jpg.3892a5157c81c116a8a82456e6b94698.jpg

Tak prezentuje się poprawiona architektura projektowanego przeze mnie układu. Nie różni się ona znacząco od schematów udostępnianych wcześniej. Różnice są raczej kosmetyczne, według mnie najważniejszą z nich jest dodanie "obejścia ALU" umożliwiającego łatwiejsze przesyłanie danych. Dodatkowo muszę wspomnieć, że układ z założenia projektowany jest według architektury Harwardzkiej. Dlaczego nie von Neumanna, po prostu nie podoba mi się koncepcja przechowywania programu i danych w tej samej pamięci. 

Dnia 5.03.2020 o 19:31, marek1707 napisał:

Czekamy oczywiście na szczegóły: długość adresów i możliwe na nich operacje

Układ nie będzie posiadał jako takiej przestrzeni adresowej. Jedyne adresy występujące w układzie to te dla pamięci ROM generowane przez licznik adresów oraz dla RAM, które stają się adresami dopiero po wpisaniu do rejestru ARR, wcześniej jest to po po prostu zwykła zmienna.   

Link do komentarza
Share on other sites

Ech: integracja CPU z peryferiami, brak wyróżnionego i dobrze zdefioniwanego interfejsu/magistali do urządzeń peryferyjnych, trochę niepokojące to "opóźnienie zegara" (zegar dwufazowy?) itd.. czyli grochem ościanę. No dobra, to Twój projekt, powodzenia. Napisz jakbyś miał jakieś konkrety.

Dlaczego nie podoba Ci się architektura von Neumann? Obie mają swoje zalety i wady - to jasne, ale nie widać podstawowej, istotnej przewagi jednej nad drugą choćby w projektach uznanych za standardy światowe. Czy np. możliwość ładowania/przesuwania kodu do pamięci RAM z peryferiów (dysków, interfejsów komunikacyjnych) za pomocą podstawowych (i z definicji istniejących) mechanizmów/instrukcji dostępu procesora do RAMu nie jest kusząca? Ty będziesz musiał zrobić dodatkowe (zwykle ograniczone i kulawe -> patrz AVR, 8051, PIC) instrukcje zapisu/odczytu danej do/z pamięci programu choćby po to, by ładować kod przed startem mając jedynie w ROMie jakiś bootloader. Procesor z połączonymi przestrzeniami robi to z palcem w nosie bo w każdej chwili każde słowo pamięci może być zarówno kodem jak i daną.

15 godzin temu, rafal2808 napisał:

Układ nie będzie posiadał jako takiej przestrzeni adresowej

???

15 godzin temu, rafal2808 napisał:

które stają się adresami dopiero po wpisaniu do rejestru ARR

No właśnie o tym myślę. Jakie przewidujesz możliwości modyfikacji tych "zmiennych" stających sie zadresami? Jak ma się podstawowe słowo danych (8-bitów?) do słowa adresów czyli jak długi jest ARR i jak go składasz do kupy gdy jest dłuższy niż słowo danych? Przecież m.in. od tego jak procesor może obliczać adresy argumentów zależy jego "moc". Jak będziesz adresował stos i jak możesz (np. w funkcji) dostawać się do argumentów na nim odłożonych bez modyfikacji SP, ile obszarów danych możesz na raz adresować czyli np. jak będzie wyglądać podstawowa pętla przepisywania obszaru RAMu z jednego miejsca w drugie albo jak napiszesz pętlę szukającą końca łańcucha (bajtu 0x00) w zadanym obszarze pamięci (czyli jak separujesz obliczenia na adresach od operacji ALU i jej flagów), czy planujesz pre/post in-/de-krementację adresów itd itp. Ciekaw jestem Twoich przemyśleń. 

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.