مسئله: جا دادن مقادیر بزرگ در دستورات با عرض ثابت
هر دستور RISC-V در یک کلمه ثابت ۳۲ بیتی بستهبندی میشود. از آنجا که برخی از آن بیتها باید opcode و فیلدهای رجیستر را کدگذاری کنند، فقط تعداد محدودی بیت برای یک ثابت جاسازیشده، معروف به Immediate Value، باقی میماند. این یک مسئله ایجاد میکند: چگونه یک برنامه میتواند با یک ثابت ۳۲ بیتی یا ۶۴ بیتی، یا یک آدرس حافظه که بسیار بزرگتر از چیزی است که در بیتهای باقیمانده یک دستور جا میشود، کار کند؟
ساخت ثابتهای بزرگ از قطعات کوچکتر
RISC-V این مسئله را با تقسیم یک ثابت بزرگ بین دو دستور حل میکند، بهجای تلاش برای جا دادن آن در یک دستور.
lui a, upperBits
addi a, a, lowerBitslui (load upper immediate) مجموعهای از بیتها را در بخش بالایی یک رجیستر قرار میدهد و بخش پایینی را صفر میکند. دستور addi بعدی سپس یک مقدار فوری کوچکتر را اضافه میکند تا بیتهای پایینی را پر کند. با ترکیب این دو دستور معمولی، مقداری بسیار بزرگتر از آنچه هر دستور بهتنهایی میتوانست کدگذاری کند ساخته میشود.
رسیدن به آدرسها و برچسبهای دور در حافظه
همین محدودیت اندازه در مورد دستورات jump و branch نیز صدق میکند وقتی مقصد در حافظه دور باشد. از آنجا که آفست مقصد یک branch نیز باید در فیلد فوری محدود دستور جا شود، پرشهای بسیار دور یا با ترکیب چند دستور مشابه ساخت ثابت مدیریت میشوند، یا با استفاده از نسخههای دستوری که بهطور خاص برای رسیدن به بازه آدرس گستردهتر طراحی شدهاند، به قیمت بیتهای کدگذاری اضافی اختصاصیافته به آفست.
چرا چند پردازنده به همگامسازی نیاز دارند
وقتی یک برنامه واحد روی یک هسته اجرا میشود، دستورات به ترتیبی قابلپیشبینی اجرا میشوند. اما وقتی یک برنامه بین چند هسته که حافظه یکسانی را به اشتراک میگذارند تقسیم شود، مسئله جدیدی پیش میآید: دو هسته ممکن است تلاش کنند تقریباً همزمان همان مکان حافظه را بخوانند و بهروزرسانی کنند، وضعیتی به نام Race Condition، که اگر مدیریت نشود میتواند بیسروصدا داده مشترک را خراب کند.
دستورات اتمیک: خواندن-تغییر-نوشتن بدون وقفه
برای جلوگیری از این مسئله، RISC-V Atomic Instructions فراهم میکند، که یک خواندن، یک تغییر، و یک نوشتن به حافظه را بهعنوان یک گام واحد و تجزیهناپذیر انجام میدهند که هیچ هسته دیگری نمیتواند در میانه آن وقفه ایجاد کند.
یک دستور اتمیک نماینده استفادهشده برای همگامسازی:
amoswap.d a, b, (c)این دستور بهطور اتمیک مقدار رجیستر b را با مقداری که در حال حاضر در آدرس حافظه نگهداشتهشده در رجیستر c ذخیره شده، جابهجا میکند، و مقدار قدیمی حافظه را در رجیستر a قرار میدهد. از آنجا که تضمین میشود این کل توالی بدون دخالت هسته دیگری در میانهاش کامل شود، میتوان از آن برای ساخت ابزارهای هماهنگی سطح بالاتر مانند Lock استفاده کرد، که تضمین میکند فقط یک هسته در هر لحظه میتواند به یک منبع مشترک دسترسی داشته باشد.
چرا این دو موضوع به یکدیگر مرتبطاند
هم ساخت مقادیر بزرگ و هم همگامسازی اتمیک، به یک محدودیت زیربنایی یکسان میپردازند: یک فرمت دستور ثابت و باریک. درست همانطور که ثابتهای بزرگ باید از قطعات کوچکتر در چند دستور مجزا مونتاژ شوند، هماهنگی امن بین هستهها نیز باید از عملیاتهای سختافزاری کوچک و تضمینشدهی تجزیهناپذیر ساخته شود، نه اینکه فرض شود بهطور پیشفرض بهدرستی رخ میدهد.