Hlavní navigace

Mikroprogramové řadiče a mikroprogramování

Pavel Tišnovský 3. 5. 2011

Dnes navážeme na předchozí část, v níž jsme si vysvětlili princip funkce řadičů v procesorech i dva základní způsoby zapojení obvodových řadičů využívajících buď čítač nebo posuvný registr. Dnes se zaměříme na řadiče mikroprogramové, které jsou založeny na interní řídicí paměti obsahující mikroinstrukce.

Obsah

1. Princip činnosti mikroprogramového řadiče

2. Mikroprogra­mování a mikroinstrukce

3. Procesory s mikroprogramovým řadičem

4. Ukázkový procesor s mikroprogramovým řadičem: WISC CPU/16

5. Adresovatelná kapacita operační paměti a hloubky zásobníku operandů i zásobníku návratových adres

6. Formát mikroinstrukcí procesoru WISC CPU/16

7. Standardní instrukční sada procesoru WISC CPU/16

8. Obsah následující části seriálu

9. Odkazy na Internetu

1. Princip činnosti mikroprogramového řadiče

V předchozí části seriálu jsme si řekli základní informace o tom, jakým způsobem pracují řadiče v mikroprocesorech. Taktéž jsme si řekli, že jedním typem řadičů je takzvaný obvodový řadič, který jako svoji ústřední část většinou obsahuje buď čítač nebo posuvný registr (každý řadič je totiž ve skutečnosti konečným automatem, který se může nacházet vždy v jednom z konečného počtu stavů). Ovšem použití obvodového řadiče začíná být ekonomicky i z časového hlediska (doba vývoje nového mikroprocesoru) nevýhodné v případě, že má mikroprocesor rozsáhlou instrukční sadu, popř. pokud je jeho interní architektura složitější (větší množství interních sběrnic, více ALU, pipelining). Právě v těchto případech se konstruktéři mikroprocesorů uchylují k použití takzvaného mikroprogramo­vaného řadiče, jehož nedílnou součástí je řídicí paměť obsahující mikroinstrukce, přičemž každá ze strojových instrukcí je provedena pomocí několika jednodušších mikroinstrukcí.

Obrázek 1: Základní schéma mikroprogramového řadiče. Mezi nejdůležitější části tohoto typu řadiče patří především mikroprogramový čítač obsahující adresu další mikroinstrukce a taktéž řídicí paměť s uloženými mikroinstrukcemi.

Na prvním obrázku je zobrazeno schéma mikroprogramového řadiče spolu s řídicí pamětí a taktéž mikroprogramovým čítačem sloužícím pro výpočet a úschovu adresy další mikroinstrukce (funkce tohoto čítače je tedy podobná funkci programového čítače – program counter, PC). Na vstup mikroprogramového čítače jsou přiváděny kódy instrukcí načtené z operační paměti, výstupem jsou řídicí signály rozváděné jak do dalších funkčních bloků procesoru (ALU, registrů, interní sběrnice…), tak i k externím zařízením (jedná se například o signály pro čtení či zápis dat do operační paměti). Kód instrukce načtený z operační paměti je nejprve uložen do instrukčního registru (IR) a posléze do dekodéru, který od sebe oddělí operační kód instrukce a adresní část, v níž mohou být uloženy například indexy registrů, s nimiž instrukce pracuje. Operační znak instrukce udává adresu první mikroinstrukce z řídicí paměti, která implementuje danou operaci.

Obrázek 2: Načtení kódu instrukce z operační paměti (na základě adresy obsažené v programovém čítači PC) a uložení tohoto kódu do instrukčního registru.

V samotné mikroinstrukci je uložena jak adresa další mikroinstrukce (protože naprostá většina operací, například i „prázdná“ operace NOP, je implementována větším množstvím mikroinstrukcí), tak i bitové hodnoty řídicích signálů. Díky tomu, že samotný kód mikroinstrukce obsahuje i adresu mikroinstrukce následující, je zajištěna návaznost mikroinstrukcí bez toho, aby se musela používat sčítačka pro zvyšování mikroinstrukčního čítače. Další součástí mikroprogramového řadiče je takzvaný multiplexor podmínek sloužící pro výběr kombinace stavových bitů, jejichž hodnota může sloužit k modifikaci adresy následující mikroinstrukce a tím i k provedení podmíněného (mikro)skoku. Mezi stavové bity patří i příznaky příchodu maskovatelného přerušení (IRQ) a nemaskovatelného přerušení (NMI), protože právě mikroprogramový řadič je použit pro uskutečnění reakce na příchod těchto přerušení (a nejenom to, řadič totiž musí reagovat například i na externí signál typu BUSRQ, tj. na požadavek jiného čipu na převzetí řízení adresové a datové sběrnice).

2. Mikroprogra­mování a mikroinstrukce

Řídicí slovo tvořící mikroinstrukci, které je, jak již víme, uloženo v řídicí paměti, je obvykle rozděleno do několika polí, přičemž každé pole je určeno pro řízení určitého bloku v mikroprocesoru, například aritmeticko-logické jednotky, sady pracovních registrů, příznakových bitů, externích signálů vyvedených na řídicí sběrnici atd. Další pole mikroinstrukčního slova typicky obsahuje adresu následující mikroinstrukce, aby se nemusel používat mikroprogramový čítač ani pomalá ALU (i když se to nemusí na první pohled zdát, je aritmeticko-logická jednotka skutečně pomalá v případě, že by musela být použita pro zvyšování či snižování mikroprogramového čítače po provedení každé mikroinstrukce). Pokud je například kapacita řídicí paměti s mikroinstrukcemi rovna 1024 mikroinstruk­čním slovům, může být adresní část mikroinstrukce široká deset bitů, i když se v praxi používá i menší šířka s tím, že je adresní prostor pro skoky (mikroskoky?) omezen například na rozsah osmi nebo šestnácti sousedních mikroinstrukcí (to souvisí s komplexností instrukčního kódu). Adresa skoku je dále modifikována vybraným podmínkovým bitem, jímž se například může určit, která ze dvou adres další mikroinstrukce bude ve skutečnosti použita.

Obrázek 3: Dekódování instrukce a rozdělení jejího kódu na operační znak a adresní část (kde mohou být uloženy například indexy pracovních registrů). U některých mikroprocesorů je dekódování instrukčního kódu velmi jednoduché (například u mikroprocesoru Intel 8008, což je předchůdce známějšího čipu Intel 8080), ale například u platformy x86 se jedná o dosti složitou operaci.

Podle způsobu kódování řídicích signálů v mikroinstrukcích rozeznáváme horizontální formát mikroinstrukcí a vertikální formát mikroinstrukcí, popř. se u některých procesorů používal hybridní formát mající některé bloky zakódovány „horizontálně“ a jiné „vertikálně“. Při použití horizontálního formátu jsou bity pro jednotlivé signály přímo uloženy v mikroinstrukci, což je sice velmi jednoduché (není zapotřebí žádný dekodér), ovšem řídicí slovo musí mít poměrně velkou šířku, typicky 16 až 64 bitů, což klade větší nároky na kapacitu řídicí paměti. Naproti tomu je při použití vertikálního formátu vždy větší skupina navzájem se vylučujících signálů (z nichž může být aktivní pouze jeden) zakódována společně do jednoho bloku bitů – bity spadající do tohoto bloku jsou přiváděny do demultiplexoru, který na základě uložené hodnoty vybere jediný signál, který je nastavený na logickou jedničku (například do bloku o šířce čtyři bity lze uložit informaci o tom, který ze šestnácti řídicích signálů bude aktivován na logickou jedničku – nikdy však nemohou být aktivovány signály dva).

Obrázek 4: Operační znak instrukce slouží pro prvotní naplnění mikroprogramového čítače. Většinou není operační znak považován přímo za adresu, ale je zapotřebí provést nějaké (jednoduché) kódování, například bitový posun.

3. Procesory s mikroprogramovým řadičem

Mikroprocesorů obsahujících mikroprogramový řadič v minulosti existovalo a dodnes existuje takřka nepřeberné množství. Ostatně i známé a z hlediska historie vývoje výpočetní techniky i velmi důležité mikroprocesory, mezi něž patří zejména Intel 8080, Intel 8086, Intel 8088 (varianta 8086 s osmibi­tovou vnější datovou sběrnicí použitá v prvních osobních počítačích IBM PC) či konkurenční řada Motorola M68000 obsahovaly řídicí paměť s mikroinstrukcemi a mikroprogramový řadič; což ostatně bylo u těchto mikroprocesorů s komplexní instrukční sadou (CISC) takřka nezbytné (u některých mikroprocesorů byla dokonce každá mikroinstrukce realizována sadou ještě jednodušších nanoinstrukcí). Interní řídicí paměť obsahující mikroinstrukce však nebyla v naprosté většině případů přístupná ani profesionálním uživatelům, protože se jednalo o paměťovou matici typu ROM umístěnou přímo na čipu mikroprocesoru i s dalšími moduly. Obsah této paměti byl pevně zadán již při výrobě mikroprocesoru, i když je pravda, že některé moderní mikroprocesory obsahují možnost „opatchování“ původního obsahu řídicí paměti novým mikrokódem.

Obrázek 5: Mikroinstrukce se provádí v naznačené smyčce, v níž jsou z řídicí paměti postupně načítány adresy dalších mikroinstrukcí, které jsou modifikovány obsahem vybraného příznakového bitu (zero, carry, overflow…).

Kromě výše zmíněných mikroprocesorů s neměnitelnou (a taktéž externě nečitelnou) řídicí pamětí ovšem byly v minulosti navrženy i mikroprocesory, které umožňovaly přístup do řídicí paměti s mikroinstrukcemi i běžným uživatelům. Buď se jednalo o paměť typu PROM (tj. o paměť s možností zápisu každého bitu pouze jedenkrát), nebo dokonce o rychlou paměť typu SRAM. Díky tomu, že obsah této paměti byl přes samostatnou sběrnici přístupný a tím pádem i měnitelný zvnějšku, bylo možné modifikovat instrukční sadu těchto mikroprocesorů a připravit je tak pro provádění rozličných úkolů – například bylo možné vytvořit novou instrukci provádějící jeden krok při výpočtu kódu CRC, implementovat instrukce pro výpočty s hodnotami reprezentovanými v systému pevné řádové tečky (FX – fixed point), implementovat v instrukční sadě takzvaný P-kód (používaný v minulosti pro programy přeložené z Pascalu do bajtkódu), vytvořit instrukční sadu pro zpracování bajtkódu programovacího jazyka Java atd. Jedním z takových mikroprocesorů je i čip WISC CPU/16 popsaný v následujících dvou kapitolách.

Obrázek 6: Mikroinstrukce obsahují kromě adresy navazující mikroinstrukce samozřejmě i řídicí signály, které jsou rozvedeny ke všem dalším blokům mikroprocesoru.

4. Ukázkový mikroprocesor s mikroprogramovým řadičem: WISC CPU/16

Procesor WISC CPU/16, který byl navržen zejména pro studijní účely vedoucí například ke konstrukci mikroprocesorů používaných v kosmické technice (viz další text), náleží do kategorie šestnáctibitových zásobníkových procesorů, které se mj. vyznačují i tím, že všechny výpočty jsou prováděny nikoli s obsahem vybraných pracovních registrů, ale s položkami umístěnými na vrcholu zásobníku. Název tohoto mikroprocesoru WISC znamená Writable Instruction Set Computer. Jak již tento název napovídá, jedná se o procesor, ve kterém je umožněno zápisem dat do řídicí paměti s mikroinstrukcemi vytvořit a následně používat vlastní instrukční sadu. Tento procesor byl navržen zejména proto, aby se na jeho konstrukci a interním uspořádání otestovaly některé klíčové vlastnosti modernějšího a komerčně poměrně úspěšného mikroprocesoru RTX 32P. Velkou předností procesoru WISC CPU/16 a zejména jeho komerční varianty RTX 32P byl na dobu jeho vzniku výborný poměr cena/výkon, který byl překonán až v době vyspělejších šestnáctibitových mikroprocesorů a zejména mikrořadičů.

Obrázek 7: Blokové schéma procesoru WISC CPU/16.
Zdroj: P. Koopman – Architecture of the WISC CPU/16

Tento procesor byl zkonstruován z diskrétních integrovaných obvodů na bázi „rychlé“ řady čipů 74LS0 (aritmeticko-logická jednotka byla například tvořena čipem 74LS181), což mj. umožnilo jeho snadné rozšiřování a testování (připojení osciloskopu či logického analyzátoru přímo na vnitřní sběrnice procesoru). Celý procesor byl, spolu s pomocnými obvody, vytvořen na plošném spoji, který bylo možné zasunout do osobního počítače, kde mohl WISC pracovat jako koprocesor. Vzhledem k době vývoje tohoto procesoru byla pro komunikaci s osobním počítačem použita sběrnice ISA.

Obrázek 8: Moduly procesoru WISC CPU/16, v nichž je implementován mikroprogramo­vý řadič.

5. Adresovatelná kapacita operační paměti a hloubky zásobníku operandů i zásobníku návratových adres

Adresovat bylo možné operační paměť o kapacitě 128kB, adresa totiž byla uložena v šestnácti bitech a každá adresovatelná buňka měla velikost šestnáct bitů (po bytech nebylo možné adresování provést, podobně jako u některých dalších zásobníkových procesorů či DSP). V prakticky všech implementacích tohoto procesoru (zejména na testovací přídavné desce do PC) se však používala dynamická paměť o kapacitě pouhých 16kB (ona to zase tak malá paměťová kapacita není, zejména při použití programovacího jazyka Forth pro vývoj aplikací).

Obrázek 9: Subsystém zásobníku operandů (zvýrazněno modrou barvou) a zásobníku návratových adres (zvýrazněno barvou červenou).

Datový zásobník procesoru WISC CPU/16 měl hloubku (kapacitu) 256 položek, přičemž každá položka (v názvosloví používaném v programovacím jazyku Forth se jedná o buňku neboli cell) měla šířku šestnáct bitů. Taktéž zásobník návratových adres měl hloubku 256 položek po šestnácti bitech. Ukazatele na datový zásobník i zásobník návratových adres byly uloženy na osmi bitech a lze je považovat za registry, do kterých lze číst i zapisovat – teoreticky by však měla postačovat pouze inkrementace a dekrementace obsahu těchto registrů.

Obrázek 10: Manuál k procesorovému řezu AMD Am2900 popsanému v předchozích částech tohoto seriálu. Tento procesorový řez se programuje přímo pomocí mikroinstrukcí, neobsahuje tedy instrukční dekodér.

6. Formát mikroinstrukcí procesoru WISC CPU/16

Kromě pracovní paměti byla součástí procesoru WISC CPU/16 ještě mikroprogramová paměť o kapacitě 2kB×32 bitů. Tato paměť byla použita pro kódování mikroinstrukcí a díky konstrukci celého procesoru ji bylo možné po jeho resetu naplnit z řídicího osobního počítače (přes sběrnici ISA), což výrazným způsobem zjednodušovalo návrh a testování mikroinstrukcí. Formát mikroinstrukcí byl velmi jednoduchý, protože se používal horizontální formát kódování popsaný v předchozím textu – viz též obrázek číslo 10. Pomocí mikroinstrukčního kódu bylo možné vytvořit například instrukce, které prováděly rozeskok a současně jeden krok smyčky. Nejkratší mikrokód byl proveden již za dva až tři mikrocykly, nejdelší mohl zabrat i několik tisíc mikrocyklů. Adresování mikroinstrukcí probíhalo v rámci 256 stránek, přičemž v každé stránce bylo možné uložit osm slov o šířce 32 bitů (256×8=2048). Každá mikroinstrukce měla šířku 32 bitů, jež byly rozděleny do několika polí o pevné délce, což byl i formát používaný o desítky let dříve například u mainframů IBM System/360.

Obrázek 11: Formát mikroinstrukčního slova procesoru WISC CPU/16, na němž je patrné rozdělení mikroinstrukce na několik samostatných bloků. Adresa další mikroinstrukce je získána na základě obsahu bitů 23, 24 a 25.
Zdroj: P. Koopman – Architecture of the WISC CPU/16

Pro implementaci složitějších instrukcí bylo k dispozici osm způsobů nastavení podmínky, 17 základních aritmetických a logických operací, inkrementace čítače instrukcí PC, autoinkrementace či autodekrementace některého operandu a bitový posun doleva a doprava o jeden bit. Vstupní operand bylo možné adresovat jedenácti způsoby (mohl být uložen na zásobníku operandů, na adrese uložené v registru PC, v operační paměti apod.), výstupní operand bylo možné adresovat až třinácti způsoby, dokonce bylo umožněno tvořit „datové smyčky“, kdy byl jako vstupní operand použit výsledek předchozí instrukce (vhodné pro implementaci některých algoritmů pro zpracování signálu). Zajímavé je, že procesor neobsahoval registr pro příznaky (carry flag, zero flag, overflow flag atd.), příznaky se tedy musely ukládat na datový zásobník jako hodnoty 0, –1 apod.

Obrázek 12: Sovětská varianta čipu, který je součástí procesorového řezu kompatibilního s řadou Am 2900, jenž se programuje přímo pomocí mikroinstrukcí.

7. Standardní instrukční sada procesoru WISC CPU/16

Pomocí mikroinstrukcí bylo možné vytvořit prakticky libovolnou instrukční sadu. Standardně dodávaná instrukční sada se skládala z instrukcí, z nichž každá měla fixní délku šestnáct bitů. Existovaly dva základní formáty instrukcí: pomocí instrukce prvního formátu se zavolala příslušná mikroinstrukce (provedla se zvolená operace), s využitím instrukce druhého formátu se provedlo vyvolání podprogramu (call). Při použití instrukce prvního formátu (obrázek číslo 11) musely být všechny bity 8–15 nastaveny na logickou jedničku, zbývající bity 0–7 obsahovaly operační kód mikroinstrukce, kterých tak mohlo být pouze 256 (což ovšem v praxi dostačovalo).

Obrázek 13: Formát instrukce procesoru WISC CPU/16 v případě, že se jedná o instrukci aritmetickou, logickou či instrukci přesunu dat.
Zdroj: P. Koopman – Architecture of the WISC CPU/16

Při použití druhého formátu musel být naopak alespoň jeden z bitů 8–15 nulový, na všech bitech dohromady byla uložena adresa šestnáctibitového slova (nikoli bytu), na které se následně provedl skok. Jelikož alespoň jeden z horních osmi bitů instrukce musel být nulový (test lze snadno provést s využitím osmivstupového hradla NAND), nemohl se v adresovém prostoru o celkem 65536 slovech provést skok na 2048 „speciálních“ slov, což jsou pouhá tři procenta adresového prostoru. Formát těchto typů instrukcí je zobrazen na obrázku číslo 12..

Obrázek 14: Formát instrukce procesoru WISC CPU/16 v případě, že se jedná o instrukci skoku do podprogramu (call).
Zdroj: P. Koopman – Architecture of the WISC CPU/16

Při vývoji procesoru byla implementována mj. i instrukční sada vhodná pro MVP-Forth a Forth-79. Standardní mikrokód podporuje například následující Forthovská primitivní slova (průměrně trvá jedna instrukce tři hodinové cykly):

    !                        DDROP
    +                        DDUP
    +!                       DNEGATE
    -                        DROP
    0                        DSWAP
    0<                       DUP
    0=                       I
    0BRANCH                  I'
    1+                       J
    1-                       LEAVE
    2*                       LIT
    2/                       NEGATE
    <                        NOP
    PICK                     NOT
    ROLL                     OR
    =                        OVER
    >R                       R>
    ?DUP                     R@
    @                        ROT
    ABS                      S->D
    AND                      SWAP
    BRANCH                   U*
    D!                       U/MOD
    D+                       XOR

Do jedné instrukce je možné zakódovat i různé složeniny primitivních Forthovských slov, například:

    @ +
    @ -
    DROP ;
    DROP DUP
    I +
    I + @
    OVER +
    OVER -
    R> DROP
    R> SWAP >R
    SWAP -
    SWAP DROP
    DUP @ SWAP 1+        (fetch and increment address)
    DUP ROT ROT ! 1-     (store and decrement address)
    @ @                  (indirect fetch)
    @ !                  (indirect store)
    DUP @  @  1 ROT +!   (auto-postincrement indirect fetch for software stack)
    -1 OVER +!  @ !      (auto-predecrement indirect store for software stack)

8. Obsah následující části seriálu

Princip mikroprogramových řadičů a mikroprogramování vznikl již v roce 1951, kdy jej ve svých článcích představil svým kolegům sir Maurice V. Wilkes (titul sir získal Wilkes právě za svoji práci v oboru výpočetní techniky). Idea mikroprogramování spočívala v zobecnění konstrukce centrální procesorové jednotky (CPU) takovým způsobem, že strojové instrukce byly rozkládány na sekvenci řídicích signálů pomocí mikroprogramu uloženého v paměti typu ROM s velmi rychlou dobou přístupu. Zpočátku se sice zdálo, že mikroprogramové řadiče se kvůli své relativní složitosti (potřeba drahé paměti s relativně velkou kapacitou) nebudou v reálných počítačích používat, ale spolu se vznikem druhé generace mainframů s jejich rozsáhlými a komplexními instrukčními sadami (CISC) se ukázalo, že právě díky mikroprogramovým řadičům je možné zjednodušit návrh procesorových jednotek těchto mainframů. V následující části tohoto seriálu se seznámíme s tím, jakým způsobem byly mikroprogramové řadiče použity u sálových počítačů, zejména pak v systému IBM S/360.

ibm3_

Obrázek 15: Zrekonstruovaný řídicí panel počítače IBM System/360 Model 30. Na dlaždici před panelem (zhruba pod čtveřicí bílých tlačítek) je pro porovnání velikostí umístěný současný mikrořadič PIC.

9. Odkazy na Internetu

  1. Great moments in microprocessor history
    http://www.ib­m.com/developer­works/library/pa-microhist.html
  2. Microprogram-Based Processors
    http://resear­ch.microsoft.com/en-us/um/people/gbe­ll/Computer_Struc­tures_Principles_an­d_Examples/csp0167­.htm
  3. A Brief History of Microprogramming
    http://www.cs­.clemson.edu/~mar­k/uprog.html
  4. CPU design (Wikipedia)
    http://en.wiki­pedia.org/wiki/CPU_de­sign
  5. Architecture of the WISC CPU/16
    http://www.ece­.cmu.edu/~koop­man/stack_com­puters/sec4_2­.html
  6. Zásobníkový procesor WISC CPU/16 (Root.CZ)
    http://www.ro­ot.cz/clanky/pro­gramovaci-jazyk-forth-a-zasobnikove-procesory-16/#k03
  7. Writable instruction set, stack oriented computers: The WISC Concept
    http://www.ece­.cmu.edu/~koop­man/forth/roches­ter87.pdf
  8. The Great CPU List: Part X: Hitachi 6301 – Small and microcoded (1983)
    http://jbayko­.sasktelwebsi­te.net/cpu2.html#Sec2Par­t10
  9. Control unit (Wikipedia)
    http://en.wiki­pedia.org/wiki/Con­trol_unit
  10. Microcode (Wikipedia)
    http://en.wiki­pedia.org/wiki/Mi­crocode
  11. Microsequencer (Wikipedia)
    http://en.wiki­pedia.org/wiki/Mi­crosequencer
  12. Maurice V. Wilkes Home Page
    http://www.cl­.cam.ac.uk/ar­chive/mvw1/
  13. Maurice Wilkes (Wikipedia)
    http://en.wiki­pedia.org/wiki/Mau­rice_Wilkes
  14. Papers by M. V. Wilkes (důležitá je především jeho práce číslo 35)
    http://www.cl­.cam.ac.uk/ar­chive/mvw1/list-of-papers.txt
  15. The KimKlone: (Bride of Son of Cheap Video, page 2)
    http://laughto­nelectronics.com/ar­cana/BrideOfSon­Pg2.html
  16. Microprogram Memory
    http://free-books-online.org/com­puters/advanced-computer-architecture/mi­croprogram-memory/
  17. First Draft of a report on the EDVAC
    http://qss.stan­ford.edu/~god­frey/vonNeuman­n/vnedvac.pdf
Našli jste v článku chybu?
DigiZone.cz: Další dva kanály nabídnou HbbTV

Další dva kanály nabídnou HbbTV

Vitalia.cz: Vláknina: Rozpustná, nebo nerozpustná?

Vláknina: Rozpustná, nebo nerozpustná?

Vitalia.cz: Jak koupit Mikuláše a nenaletět

Jak koupit Mikuláše a nenaletět

Lupa.cz: E-shopy: jen sleva už nestačí

E-shopy: jen sleva už nestačí

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

Vitalia.cz: 9 největších mýtů o mase

9 největších mýtů o mase

Lupa.cz: UX přestává pro firmy být magie

UX přestává pro firmy být magie

Vitalia.cz: Tesco: Chudá rodina si koupí levné polské kuře

Tesco: Chudá rodina si koupí levné polské kuře

Lupa.cz: Avast po spojení s AVG propustí 700 lidí

Avast po spojení s AVG propustí 700 lidí

Podnikatel.cz: Prodává přes internet. Kdy platí zdravotko?

Prodává přes internet. Kdy platí zdravotko?

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Vitalia.cz: Říká amoleta - a myslí palačinka

Říká amoleta - a myslí palačinka

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Podnikatel.cz: Na poslední chvíli šokuje vyjímkami v EET

Na poslední chvíli šokuje vyjímkami v EET