RO / EN

Capitol 5

Timp estimat de citire: 6-7 minute

"Deci schimbul de date intre "memorie" si "unitatea centrala" se facea ca si cum ai trimite azi un newsletter cu un porumbel călător"

Trebuie menționat că MECIPT-1 nu avea memorie în sensul modern.

Nu avea memorie RAM rapidă, cu acces direct.

Totul se făcea pe un tambur: programele, datele de intrare erau stocate pe un tambur magnetic de unde erau luate si transmise către un procesor care opera cu cateva registre de lucru. Rezultatele trebuiau stocate tot pe tambur.  

Deci schimbul de date intre "memorie" si "unitatea centrala" se facea ca si cum ai trimite azi un newsletter cu un porumbel călător. Câteodata datele din memorie nu ajungeau la întalnire cu adresa de pe tambur unde erau trimise si asteptau inca o tura de tambur.

Sarcina noastră inițială a fost aparent simplă: să scriem un program care să calculeze suma a două numere.

Evident, „simplitatea” este un concept relativ. Pentru mine, a fost ca și cum mi-ar fi cerut să vorbesc fluent o limbă străină pe care nu o cunosteam.

În cele din urmă, am înțeles logica acestei tehnologii silențioase, dar vibrante și excepțional de ușor de înțeles.

Pentru a face calculul trebuie sa folosesti registrele. Deci datele le plasezi din memorie in registrii. Rezultatele le pui inapoi in memorie. 

Ce s-a schimbat conceptual de atunci? Aș spune nimic.

Arhitectura von Neumann (CPU + Memorie RAM) a rezistat eroic. 

Dar progresul tehnologic a fost enorm.

Să vedem ce concept vor introduce mult-așteptatele calculatoarele quantice. QBITUL chiar aduce a concept nou.

Cu un amestec de frică și curiozitate, am început să scriu direct în cod mașină. Fiecare instrucțiune avea propriul său cod de operare, fiecare adresă de memorie o calculam cu precizie.

In timp ce scriam amintirile de mai sus,  mi-a venit idea năstrușnică să-l pun pe ChatGPT 5.2 să scrie un program in cod masina MECIPT-1 care sa adune două numere.

Apoi i-am dat instructiuni să scrie un program în Python care să simuleze execuția în cod mașină MECIPT-1 a program ului care adună două numere.

Nici nu a clipit, ca să zic asa, si s-a apucat constiincios de treaba.

I-am dat un prompt aproape complet ca să muncesc cit mai putin la adaptarea scriptului Python care urma sa il genereze.

Promptul care i l-am dat este următorul:

Scrie un singur fișier Python numit : mecipt1_demo_slow_tts.py (doar biblioteci standard).

Simulează execuția MECIPT-1 pentru programul care adună 32000 și 38000.

Asumări:

- Memorie/tambur: 1024 adrese (0..1777 octal).

- Programul e deja pe tambur la adresa 400(dec)=0620(o) și are exact:

 0620: stânga U 0144, dreapta A 0145

 0621: stânga ME 0147, dreapta AC 0094 (94 dec) => tipărește numărul

 0622: stânga O 0000 (stop), dreapta CU 0000 (nop)

- Datele: M[100]=32000 (0144 o), M[101]=38000 (0145 o). Rezultat în M[103]=M[0147 o].

- PC are forma cuvânt.jumătate: .0 = instrucțiunea stângă, .1 = instrucțiunea dreaptă.

- Afișează la fiecare pas:

 PC=....   RI=sign|opL(5b)|opR(5b)|addrL(10b)|addrR(10b)

 -> mnemonic + adresă (octal + decimal) + S curent

 S(bin)=...

Efecte:

- Afișare teletype (caracter cu caracter) pentru liniile de log.

- [TYPEWRITER] tipărește rezultatul cu delay între caractere.

Voce:

- Integrează ElevenLabs TTS: cheia ELEVENLABS_API_KEY din .env (în directorul curent).

- Config voce din voice_config.py (COMPANION / ro-RO). Nararea e BLOCKING între pași.

- Dacă TTS e indisponibil, scriptul rulează fără sunet (fără crash).

Înainte să scrii codul, spune în 4–5 rânduri cum vei proceda.

Deci am 176 de cuvinte în limbaj natural, așa cum vedeți mai sus, și m-am ales cu 2179 de cuvinte scrise în Python (cca 500 linii de cod), la care se adaugă încă 89 de cuvinte generate de ChatGPT 5.2 în limbaj natural ca să îmi explice cum va proceda.

Iată ce a răspuns ChatGPT 5.2, înainte de a genera codul Python.

Quote
Voi proceda astfel:

(1) încarc ELEVENLABS_API_KEY din .env (din directorul curent) și aleg vocea din voice_config.py (COMPANION/ro-RO), cu fallback la variabilele din .env.

(2) construiesc memoria MECIPT (1024 adrese) și încarc programul la 0620/0621/0622 și datele la 0144/0145.

(3) rulez bucla fetch–decode–execute cu PC = cuvânt.jumătate și RI = cuvântul curent, afișând fiecare pas „teletype” + „typewriter”.

(4) între pași, generez TTS cu ElevenLabs (cu cache) și redau audio blocking; dacă TTS nu merge, continui fără sunet.
(5) la final afișez rezultatul din memorie și opresc demo-ul.
EndQuote

Pentru cei ce nu cunosc:

ELEVENLABS este un site celebru unde ai acces la diferite voci sintetice în diferite limbi pentru servicii TTS – Text To Speech.

Există multe alte opțiuni.

Cei care au venit la ei cu legitimatia lor de IT pot vedea in continuare cum a function programul generat

Așa cum am arătat la începutul acestui capitol, MECIPT nu avea memorie RAM rapidă, cu acces direct.

Totul se făcea pe un tambur: programele, datele de intrare și rezultatele finale erau stocate și procesate în același spațiu fizic, secvențial.

Programul și datele erau încărcate pe tambur folosind un mic program hardcodat în MECIPT-1, numit „loader” – adică încărcător.

Banda perforată era citită de un dispozitiv special care convertea perforațiile în semnale electrice. Loaderul primea aceste semnale, le interpreta și le scria pe tambur la adresele indicate clar în codul perforat, iar întregul conținut al programului – instrucțiuni și date – era „descărcat” în tambur înainte de execuție.

Nimic nu putea fi făcut parțial sau din mers: totul trebuia perfect pregătit în avans, în ordine și sincronizat cu rotația tamburului.

Unitatea centrală avea doar câteva registre, dar fiecare avea un rol clar:

Contorul de programe – Program Counter (PC) stoca adresa de pe tambur a instrucțiunii care urma să se execute;

Registrul de instrucțiuni (RI) – registrul unde se încarcă și decodifică instrucțiunea curentă;

Acumulatorul (registrul S) efectua calculele aritmetice și logice.

Încărcai primul număr în registrul S cu o instrucțiune, apoi cu următoarea adunai la registrul S numărul al doilea aflat la adresa indicată în instrucțiunea de adunare. Această frază exprimă prima mea înțelegere profundă în științacalculatoarelor.

Execuția era secvențială: computerul citea o instrucțiune din tambur, o încărca în Registrul de Instrucțiuni, o decodificași apoi executa acțiunea – dacă era un calcul, era procesat în Acumulator; dacă era o scriere, rezultatul era returnat tamburului.

Faptul că instrucțiunile și datele erau codificate în cuvinte binare pe 31 de biți era un avantaj uriaș și o dovadă a expertizei echipei timișorene.

În timp ce mulți producători de computere, inclusiv unele companii prestigioase, adoptaseră arhitecturi pe 12 sau 16 biți, inginerii români au ales arhitectura pe 32 de biți – aceeași arhitectură pe care IBM a adoptat-o ulterior ca standard pentru System/360.

Diferența era mai mult decât cosmetică. Cei 31 de biți permiteau unui singur cuvânt să conțină două instrucțiuni.

Hai să vedem cum arată un cuvânt de 31 de biți când vorbim de instrucțiuni:

RI = 0|00001|00101|0001100100|0001100101

În simulatorul nostru, formatul este (l-am marcat eu cu sparatori):

0 = bit de semn / control (în cuvintele cu date e semnul numărului; în cuvintele cu instrucțiuni, de regulă rămâne 0 

00001 = opcode-ul instrucțiunii din stânga - opcode = codul instructiunii in cazul de fata inseamna incarca in acumulator

00101 = opcode-ul instrucțiunii din dreapta adica aduna la acumulator

0001100100 = adresa operandului instrucțiunii din stânga - adica la ce adresa pe tambur este primul numar -32000

0001100101 = adresa operandului instrucțiunii din dreapta - adica la ce adresa pe tambur este al doilea numar - 38000

1) Deci decodificăm opcode-urile (cele două coduri de instrucțiuni)

00001 în binar = 1 în zecimal → opcode 1 → instrucțiunea U

(U = “încarcă/LOAD”: ia un număr din memorie și îl pune în acumulator S)

00101 în binar = 5 în zecimal → opcode 5 → instrucțiunea A

(A = “Adună/ADD”: adună în S valoarea dintr-o adresă)

Până aici, știm deja cele două instrucțiuni:

stânga: U … incarca in accumulator (S)

dreapta: A … aduna la acumulator

‍2) Decodificăm adresele operanzilor – câte unul pentru fiecare instrucțiune

Acum vine partea frumoasă: cei 10 biți de adresă.

0001100100 = 100 în zecimal adresa pe tambur unde se afla 32000

0001100101 = 101 în zecimal adresa pe tambur unde se afla 38000

Cum ajung ei la forma “de epocă”, în octal, pentru a fi cititi mai usor de programatori.

Prin trucul simplu: grupe de câte 3 biți → o cifră octală. 

Uite-l pe 100 zecimal în binar (fără zerourile din față): 1100100

Îl completezi cu zerouri la stânga ca să ai multiplu de 3: 001 100 100

Asta în octal e: 1 4 4 → 0144(o)

La fel pentru 101: 1100101 → 001 100 101 → 145 → 0145(o)

Deci adresele sunt:

stânga: 0144(o) = 100(dec)

dreapta: 0145(o) = 101(dec)

3) Concluzia: în RI stau exact aceste două instrucțiuni:

Instrucțiunea din stânga: U 0144 → încarcă în S valoarea din adresa 100 (primul număr)

Instrucțiunea din dreapta: A 0145 → adună în S valoarea din adresa 101 (al doilea număr)

Adica cuvântul ăsta de memorie conține două comenzi complete, fiecare cu:

un opcode (ce să fac)

o adresă (cu ce să lucrez)

Și aici intervine o  “șmecherie” (și motivul pentru care nu era doar cosmetic):

în loc să citești de pe tambur o instrucțiune pe cuvânt, citești două dintr-un foc.

Ca și cum tamburul, fiind o “roată” care se învârte, îți spune:

„Tot ai prins momentul… ia și stânga, ia și dreapta. Că până mă întorc, mai trece un tur.”

În plus, cei 31 de biți permiteau numere întregi cuprinse între aproximativ minus 2 miliarde și plus 2 miliarde, comparativ cu doar 32.768 într-un sistem pe 16 biți – o diferență crucială pentru calculul economic și științific serios.

Această arhitectură oferea o programare mai eficientă, concisă și mai ușor de înțeles decât alte sisteme ale vremii. Era ca și cum ai compara un dicționar care oferă o definiție completă într-o singură intrare cu un dicționar în care trebuie să navighezi de la o pagină la alta pentru a înțelege sensul complet al unui cuvânt.

Cu aceste explicații puteți viziona filmul de mai jos, care simulează un program scris în cod asamblare MECIPT-1 pentru adunarea a două numere. Nu uitați să porniți sunetul.

Profesorul a mers printre bănci și s-a uitat peste umărul meu. A zâmbit ușor, lucru pe care l-am interpretat fie ca o aprobare, fie ca un gest de compasiune pentru un novice. Am aflat mai târziu că era, de fapt, cel din urmă.

„Bine, acum trebuie să transferăm programul pe banda perforată”, a anunțat el.

Și aici a început o altă aventură. O bandă perforată era un sul lung de hârtie cu găuri care simulau codul. Perforarea se făcea pe o mașină specială, iar fiecare eroare însemna reluarea întregii secvențe de la capăt.

După ce am terminat de perforat programul, l-am dus la „operatorul” computerului, o figură misterioasă care părea să dețină cheia sufletului mașinii. Operatorul a introdus banda în cititorul mașinii și… am așteptat.

După câteva momente care au părut o veșnicie, operatorul mi-a înmânat rezultatul.

- Sfârșit Capitol 5 -