~/writing/heartbeat-fde $
    04/08
    intro ⏻
    LEVEL 2 — THE MACHINERYপর্ব ০৪/০৮~১৪ মিনিট

    হার্টবিট: Fetch-Decode-Execute

    CPU একটা instruction কীভাবে বোঝে আর চালায়?

    আগের আর্টিকেলে দেখা গেছে — ২ আর ৩ কীভাবে যোগ হয়ে ৫ হয়। কিন্তু পুরো কাহিনী শেষ হয়নি। একটা প্রশ্নের উত্তর বাকি ছিল।

    CPU জানল কীভাবে যে এই মুহূর্তে তাকে যোগ করতে হবে? বিয়োগ না, গুণ না — যোগ। আর এই দুইটা register-এর ডেটা নিতে হবে, বাকিগুলো না। সেই control signal-গুলো এল কোথা থেকে?

    আজকের গল্পটা ঠিক এখান থেকেই শুরু।

    // সিলিকন সিটির time-lapse

    আমরা এখনও সিলিকনের সেই ছোট্ট শহরের ভেতরেই আছি, যেখানে ALU, register, datapath আর clock একসাথে কাজ করছে। তবে আজকের ফোকাস যন্ত্রাংশের ওপর নয়, কাজের ধারাবাহিকতার ওপর। আগের আর্টিকেলটি ছিল একটি স্থিরচিত্র — ভেতরে কী কী আছে তার বিবরণ। আজকেরটা চলমান ছবি: একটা instruction কীভাবে memory থেকে CPU-তে আসে, নিজের অর্থ control signal-এ রূপ নেয়, আর শেষে CPU-র state বদলে দেয়।

    01

    Instruction-ও শুধু bits

    আমরা যখন code লিখি, তখন "code" আর "data" সম্পূর্ণ আলাদা জিনিস মনে হয়। কিন্তু memory-র স্তরে instruction আর data — দুটোই শেষ পর্যন্ত bit pattern।

    ADD instruction   →  একটা bit pattern
    42                →  একটা bit pattern
    একটা pixel value  →  একটা bit pattern

    Memory নিজে বসে সিদ্ধান্ত নেয় না — "এই bit-গুলো instruction" আর "ওগুলো data"।

    তবে তাই বলে CPU যেকোনো bit-কে ইচ্ছামতো instruction বানিয়ে ফেলে না। CPU যখন instruction fetch করার জন্য একটা নির্দিষ্ট memory address থেকে bit pattern আনে, তখনই সেই bits instruction হিসেবে decode হওয়ার process-এ ঢোকে।

    Instruction নাকি data — সেটা bit pattern-এর গায়ে লেখা থাকে না; CPU কোন কাজে সেই bits ব্যবহার করছে, তার ওপরই interpretation নির্ভর করে।

    তাহলে প্রশ্নটা দাঁড়ায় — CPU কোন address থেকে instruction আনবে, সেটা ঠিক হয় কীভাবে? তার আগে দেখা যাক, একটা instruction দেখতে কেমন।

    02

    একটা instruction-এর ব্যবচ্ছেদ

    ধরুন CPU-কে বলতে চাই: "Register A আর Register B যোগ করে ফলাফল Register C-তে রাখো।" এই বাক্যটা CPU-র কাছে মানুষের ভাষায় যায় না। Machine instruction-এর একটা নির্দিষ্ট binary format থাকে, যেখানে আলাদা আলাদা bit field-এর আলাদা মানে।

    বাস্তব processor-এ instruction format নির্ভর করে তার architecture বা ISA-র ওপর। সব processor-এ instruction একই মাপের — এমন নয়।

    বোঝার সুবিধার জন্য আমরা একটা কাল্পনিক ১৩-bit format ধরে নিচ্ছি:

      0001  |  001  |  010  |  011
     Opcode | Reg A | Reg B | Reg C
    • Opcode — কোন operation হবে সেটা নির্দেশ করে। আমাদের কাল্পনিক CPU-তে ধরা যাক 0001 = ADD, 0010 = SUB, 0011 = LOAD।
    • Register field — কোন register থেকে operand নিতে হবে আর কোন register-এ result রাখতে হবে, সেগুলোর পরিচয় নম্বর।

    খেয়াল করুন, 001, 010, 011 কোনো memory address নয় — এগুলো CPU-র register-গুলোর identifier।

    এই field-গুলো decode করার পর CPU এমন control signal তৈরি করতে পারে, যা A আর B-এর value ALU-তে পাঠায়, ALU-কে ADD-এর জন্য configure করে, আর destination হিসেবে Register C বেছে নেয়। এখানেই instruction-এর bit pattern থেকে CPU-র ভেতরের আচরণের যোগসূত্র তৈরি হয়। নিচের যন্ত্রে opcode আর operand পাল্টে দেখুন:

    যন্ত্র ০১ — THE INSTRUCTION
    ০০০১
    ADD · opcode
    Reg A · উৎস ১ ↻
    Reg B · উৎস ২ ↻
    Reg C · গন্তব্য ↻
    CPU পড়ছে: ADD — Reg A + Reg B → Reg C
    ১৩ বিটের কাল্পনিক instruction: প্রথম ৪ বিট opcode (কী করতে হবে), পরের ৩×৩ বিট operand (কার ওপর)। operand-এ ক্লিক করে register বদলান।
    03

    Program Counter: কার পালা এখন?

    Memory-র কাছে instruction আর data দেখতে একইরকম হলে স্বাভাবিক প্রশ্ন আসে — CPU কীভাবে জানে এখন কোন bits-কে instruction হিসেবে fetch করতে হবে?

    এর জন্য CPU-তে একটা গুরুত্বপূর্ণ register আছে — Program Counter (PC)। কোনো কোনো architecture-এ একে Instruction Pointer-ও বলে। সহজভাবে, PC ধরে রাখে পরবর্তী instruction কোন memory address থেকে fetch হবে।

    আমাদের simplified CPU-তে instruction-গুলো যদি fixed-size হয়, তাহলে একটা instruction fetch করার পর PC পরেরটার address-এ এগিয়ে যেতে পারে।

    [ Memory ]
    
    0x004: 0001001010011   ← PC
    0x008: 0000000000010   ← data
    0x00C: 0000000000011   ← data

    PC এখন 0x004 নির্দেশ করছে। CPU সেখান থেকে fetch করলে ওই bit pattern instruction হিসেবে decode হওয়ার পথে যায়। তারপর simplified model-এ PC পরের instruction-এর দিকে এগোয়।

    কোনো program চালু হলে system সেটির entry point থেকে execution শুরুর ব্যবস্থা করে — আমাদের model-এ ধরে নিতে পারি, PC-তে প্রথম instruction-এর address বসানো হয়।

    যন্ত্র ০২ — THE POINTER
    PC ▶0x0040001001010011instruction!
    PC ▶0x0080000000000010শুধু bit (মান: ২)
    PC ▶0x00C0000000000011শুধু bit (মান: ৩)
    PC 0x004-কে point করছে — CPU এই bit-গুলোকেই instruction হিসেবে fetch করবে।
    মেমোরির কোনো ঘরে "আমি instruction" লেখা নেই — Program Counter যাকে point করে, সে-ই instruction।

    তবে বাস্তব CPU-তে PC সবসময় শুধু "এক ধাপ বাড়ে" — এমন নয়। Instruction-এর size, branch, jump, function call, return — এসবের কারণে পরের instruction কোথা থেকে আসবে, সেটা বদলে যেতে পারে।

    Memory-তে instruction আর data-র জন্য আলাদা কোনো label থাকে না। CPU-র instruction-fetch process ঠিক করে, কোন memory location-এর bits instruction হিসেবে decode হবে।

    এবার সব উপাদান হাতে আছে। Instruction memory-তে বসে আছে, PC জানে কোনটা এখন পড়তে হবে। কিন্তু সেই bits থেকে আসল কাজটা হয় কীভাবে?

    04

    Fetch-Decode-Execute: মৌলিক flow

    একটা instruction CPU-তে আসা থেকে তার effect CPU-র state-এ বসা পর্যন্ত পুরো ব্যাপারটাকে তিনটি বড় conceptual phase-এ ভাগ করে দেখা যায়: Fetch → Decode → Execute।

    এটা একটা কাজে দেওয়া mental model। কিন্তু একটা কথা গুরুত্বপূর্ণ:

    Fetch, Decode আর Execute মানেই তিনটা clock tick — এমন নয়। কোনো processor-এ একটা instruction একাধিক clock cycle নিতে পারে; আবার pipelined CPU-তে একই সময়ে ভিন্ন instruction এই তিন phase-এর ভিন্ন অংশে থাকতে পারে।

    তাই "phase" বলতে এখানে বোঝাচ্ছি কাজের ধরন, নির্দিষ্ট সময় নয়।

    flow · simplified model
    Fetch
      ↓
    Decode
      ↓
    Execute / state update
    Fetch-Decode-Execute বলে কী ধরনের কাজ হচ্ছে; clock বলে stored state কখন update হওয়ার সুযোগ পাবে। দুটো এক জিনিস নয়।

    ১ · Fetch — instruction আনা

    Fetch phase-এর কাজ একটাই — পরবর্তী instruction-এর bits CPU-র execution machinery-র কাছে আনা।

    • PC-তে পরবর্তী instruction-এর address আছে।
    • CPU সেই address ব্যবহার করে memory subsystem-এর কাছে instruction চায়।
    • Memory থেকে instruction-এর bits CPU-র কাছে আসে।
    • CPU-র একটা internal storage element — আমাদের model-এ Instruction Register (IR) — সেই bits ধরে রাখে।

    একই সঙ্গে simplified model-এ PC পরবর্তী instruction-এর দিকে এগোয়।

    Fetch মানে clock tick এসে data-কে ঠেলে এক জায়গা থেকে আরেক জায়গায় পাঠানো নয়। Signal propagate করে, আর data ready হলে CPU নির্দিষ্ট timing boundary-তে নিজের state update করতে পারে।
    flow · fetch
    PC
     ↓
    instruction address
     ↓
    memory subsystem
     ↓
    instruction bits
     ↓
    IR

    ২ · Decode — instruction থেকে control তৈরি

    Instruction-এর bits এখন CPU-র ভেতরে। এবার সেই bits থেকে পরবর্তী কাজের control information তৈরি করতে হবে। এই কাজটা করে Control Unit (CU) আর তার decoding logic।

    0001 | 001 | 010 | 011
      ↓     ↓     ↓     ↓
     ADD    A     B     C

    Instruction-এর field দেখে control logic এমন signal তৈরি করতে পারে:

    Select Register A
    Select Register B
    ALU operation = ADD
    Destination = Register C
    Write Enable for C = 1

    খেয়াল করুন — CU এখানে ALU-কে "চালু" করেনি, MUX-কে "রাস্তা খুলতে" বলেনি।

    Control logic datapath-এর বিভিন্ন অংশকে নির্দিষ্ট configuration-এ সেট করে। তারপর combinational logic সেই configuration আর current input অনুযায়ী output তৈরি করে।
    flow · decode
    Instruction bits
          ↓
       Decode
          ↓
    Control signals
          ↓
    Configured datapath

    ৩ · Execute — computation আর state update

    Control signal এখন datapath-কে configure করে রেখেছে। Register A আর B-এর বর্তমান value MUX-এর input-এ আছে; select signal অনুযায়ী সেগুলো ALU-র input-এ পৌঁছায়।

    ALU-র combinational logic সেই input নিয়ে কাজ করে, আর propagation delay পেরোনোর পর output-এ দাঁড়ায় ৫ (0101)।

    Clock ALU-কে হিসাব শুরু করায়নি। Control signal datapath configure করেছে, আর combinational logic current input থেকে result তৈরি করেছে।

    এখন সেই result Register C-এর input-এ available, আর WE_C active। পরবর্তী appropriate clock edge-এ Register C সেটা capture করতে পারে:

    flow · capture
    ALU result = 0101
           │
           ▼
       Clock edge
           │
           ▼
    Register C captures 0101

    অর্থাৎ পুরো hardware pattern-টা এই:

    Instruction-এর bits → control signals → datapath configuration → combinational computation → state update

    নিচের যন্ত্রে পুরো পথটা ধাপে ধাপে চালিয়ে দেখুন:

    যন্ত্র ০৩ — THE HEARTBEAT
    IDLE
    RAM0x00400010010100110x00800000000000100x00C0000000000011PCIRControl Unitaddr busdata buscontrol wiresReg AReg BMUXALUReg Cclock0x004—23—
    PC ধরে আছে 0x004 — পরের instruction-এর ঠিকানা। ধাপে ধাপে এগোন।
    এক instruction-এর পুরো পথ: PC address দেয় → memory bits ফেরত দেয় → IR ধরে রাখে → CU decode করে control signal সেট করে → datapath result তৈরি করে। নিচের dashed clock line বলে, register কখন নতুন মান capture করবে।
    05

    অবিরাম চক্র

    একটা instruction-এর state update হয়ে গেলেই CPU থেমে যায় না। পরের instruction-এর জন্য আবার fetch শুরু হয় — আর modern processor-এ একই সময়ে অন্য instruction-গুলো ভিন্ন stage-এ থাকতে পারে।

    চিত্র ০১ — THE LOOP
    FETCHIR ← mem[PC]; PC++DECODECU reads opcodeEXECUTEALU + bus commit
    Fetch → Decode → Execute → আবার Fetch — যতক্ষণ পাওয়ার আছে, এই লুপ থামে না।

    তবে এই loop দেখে ভাববেন না যে প্রতিটা instruction ঠিক এই তিন ধাপে, নির্দিষ্ট সংখ্যক clock tick-এ শেষ হয়।

    Clock cycle হলো timing-এর একক; Fetch-Decode-Execute হলো কাজের conceptual stage।

    একটা 3 GHz CPU-তে প্রতি সেকেন্ডে প্রায় ৩ বিলিয়ন clock cycle থাকে। কিন্তু প্রতি সেকেন্ডে ঠিক ৩ বিলিয়ন instruction পুরো fetch-decode-execute সেরে ফেলে — তা নয়। একটা cycle-এ একাধিক instruction-এর কাজ এগোতে পারে, আবার একটা instruction একাধিক cycle নিতেও পারে।

    06

    পুরো গল্পটা একবার

    Memory-তে কোথাও একটা bit pattern বসে আছে — 0001 001 010 011। তার গায়ে "instruction" লেখা নেই।

    কিন্তু PC-তে সেই address রাখা আছে। CPU সেখান থেকে fetch করে, আর bits চলে আসে IR-এ। PC এগিয়ে যায় পরেরটার দিকে।

    Control logic সেই bits-এর field পড়ে control signal তৈরি করে: কোন register select হবে, ALU কোন operation করবে, কোন register result নেবে।

    Configured datapath-এ ২ আর ৩ ALU-তে পৌঁছায়, combinational logic settle করে ৫-এ, আর একটা clock edge-এ Register C সেই ৫ capture করে। এই মুহূর্তে result CPU-র state-এর অংশ।

    তারপর আবার পরের instruction। এই loop চলতেই থাকে।

    আপনার React app, YouTube, Photoshop বা AI chatbot — সবই শেষ পর্যন্ত machine instruction-এ নেমে আসে, আর সেই instruction-গুলো fetch, decode আর execution-এর বিভিন্ন stage-এর মধ্য দিয়ে process হয়। বাস্তব CPU-তে এই stage-গুলো অনেক বেশি জটিল, একসাথে overlap-ও করে — কিন্তু conceptual flow-টা এখান থেকেই শুরু।

    07

    সবকিছু এত সরল নয়: Pipelining

    বোঝার সুবিধার জন্য আমরা instruction-এর flow দেখিয়েছি একটা সরল ধারাবাহিক প্রক্রিয়া হিসেবে — একটা instruction-এর তিন phase conceptually শেষ হওয়ার পর পরেরটা। এটা শুধু একটা teaching model।

    বাস্তব processor-এ pipelining ব্যবহার করে একই সময়ে একাধিক instruction-এর কাজ ভিন্ন stage-এ চলতে পারে:

    flow · pipelining
    Cycle 1:  I1 Fetch
    Cycle 2:  I1 Decode   | I2 Fetch
    Cycle 3:  I1 Execute  | I2 Decode  | I3 Fetch

    I1 যখন execute হচ্ছে, তখনই I2 decode আর I3 fetch হতে পারে। এভাবে প্রতিটা clock cycle-এ আরও বেশি কাজ এগোয়। নিচের যন্ত্রে দুই mode-এর তফাত দেখুন:

    যন্ত্র ০৪ — THE PIPELINE
    t১t২t৩t৪t৫t৬t৭t৮t৯
    instr ১···
    instr ২···
    instr ৩···
    tick চেপে clock চালান।
    অ্যাসেম্বলি লাইন: একটা করে চালালে এক instruction শেষ না হওয়া পর্যন্ত পরেরটা শুরু হয় না; pipelined-এ একই cycle-এ একজন execute, একজন decode, একজন fetch হচ্ছে।
    // এই আর্টিকেলে কী শিখলাম
    • Instruction-ও শেষ পর্যন্ত bits — memory-র স্তরে instruction আর data দুটোই bit pattern হিসেবে থাকে।
    • Instruction format বলে দেয় কী করতে হবে — opcode operation শনাক্ত করে, বাকি field operand আর destination জানায়।
    • Program Counter ঠিক করে পরের instruction কোথা থেকে fetch হবে — branch বা অন্য control-flow হলে সেই address বদলাতে পারে।
    • Control Unit instruction-এর field থেকে control signal তৈরি করে — কোন register select হবে, ALU কোন operation করবে, কোন register result capture করবে।
    • Fetch-Decode-Execute একটা conceptual flow — modern CPU-তে এগুলো একাধিক clock cycle জুড়ে থাকতে পারে, আর একাধিক instruction-এর stage overlap করতে পারে।
    • Clock আর Fetch-Decode-Execute এক জিনিস নয় — clock দেয় timing boundary, FDE বলে কাজের ধরন।
    এই পাতা খোলার পর থেকে আপনার device-এ আনুমানিক ২৫৭.৬ কোটি বার transistor switch হয়েছে।
    cd ~  # back to terminal