برکلی ریسک
یکی از دو پروژههای تحقیقاتی اصلی در باب طراحی میکرو پروسسورهای بر پایه معماری ریسک است که تحت پروژه VLSI از ARPA جایگاه دارد. ریسک تحت مدیریت David Patterson (کسی که واژه ریسک را اختراع کرد) در دانشگاه کالیفرنیا، برکلی بین سالهای ۱۹۸۰ و ۱۹۸۴ انجام گرفت. پروژه بعدی که بر روی MIPS اندکی بعد انجام گرفت؛ در دانشگاه استنفورد و در طی سالهای ۱۹۸۱ و ۱۹۸۴ بود. پروپزه برکلی بسیار موفقیتآمیز بود بهطوریکه به عنوان نامی برای تمامی طراحیهای بعدی شد، بهطوریکه حتی MIPS هم به عنوان “RISK processor” شهرت یافت. طراحی RISC اندکی بعد نام تجاری پروسسور SPARC را به خود گرفت و معماری DEC Alpha را همچون معماری ARM که امروزه در اکثر موبایلها مورد استفادهاند را مورد الهام خود قرار داد.
هر دو مورد ریسک و میپس بر این واقعیت استوار بودند که تعداد زیادی از زبانها از تعداد زیادی از دستورها پروسسور استفاده نمیکنند. در محاسباتی که انجام شدهاست یه این موضوع رسیدهایم که سیستم یونیکس به هنگام کامپایل شدن تنها ۳۰ درصد از دستورها در دسترس در Motorola ۶۸۰۰۰ را استفاده میکند. بسیاری از مدارات و جریانات در داخل m68k و طراحیهای مشابه، اختصاص به دیکد کردن دستورهایی میشد که هیچگاه مورد استفاده نبودند. ایدهٔ RISC این بود که تنها دستورهایی را شامل شود که واقعاً استفاده میشوند. استفاده از فضای مدارات پاک شده برای مدارات جدید که سرعت را افزایش دهد. بر این پایه معماری RISC تمرکزش را بر اضافه کردن تعداد بیشتر ثباتها گذاشت. بیتهای کوچک حافظه برای نگه داشتن مقادیر موقت که با صرف هزینه کم در دسترس قرار میگیرد. این مخالف با حافظه نرمال اصلی میباشد که زمان زیادی را صرف دسترسی میکرد. با فراهم کردن تعداد بیشتر از ثباتها و اطمینان به این که کامپایلر واقعاً از آنها استفاده میکند، برنامهها باید با سرعت بیشتری اجرا شوند. به علاوه سرعت پردازنده با Clock سرعت آن معرفی میشود. زیرا میزان کمی از زمان آن برای منتظر ماندن برای دسترسی به حافظه صرف میشود. در واقع، دستورهایی که پاک شدند، دستورها اضافهای بودند که نقش دستورها زیر برنامهای داشتند. برای مثال در روشهای قدیمی، چندین روش برای دستور ADD وجود داشت، یکی این بود که اعداد را در دو ثبات قرار دهد و نهایتاً جواب را در ثبات سوم جای دهد. روش دیگر این بود که اعدادی را که در حافظه پیدا میکرد را با یکدیگر جمع میکرد و جواب را در یک ثبات نهایی قرار میداد و غیره. از طرف دیگر معماری RISC تنها یک روش برای هر دستور را شامل کرد، برای مثال دستور ADD همیشه برای هر عملوند یک ثبات استفاده میکرد. این روند باعث میشود که برنامهنویس را مجبور کند تا دستورها اضافهای برای load کردن مقادیر از حافظه بنویسد. در دوره حافظههای گران، این تنها علاقه و هدف بود، به ویژه این که حافظه بسیار کندتر از CPU بود. به دلیل آنکه در طراحی ADD در معماری ریسک به چهار دستور (دو دستور Load، یک add و یک ذخیره) نیاز بود، ماشین بایستی به حافظه بیشتر دسترسی پیدا میکرد تا دستورها اضافی را بخواند و این باعث کند شدن قابل توجه آن میشد. این در واقع یک تعادل بود، که طراحی جدید آن را استفاده کرد، که در واقع دستورها بزرگی (۳۲ بیت) بودکه اجازه میداد ثابتهای کوچک بدون load شدن جداگانه در دستور قرار بگیرند. به علاوه استفاده نتیجه یک عمل زودتر از انجام گرفتن جای دیگر استفاده میشد، در نهایت با چشم پوشی از نوشتن در حافظه و ذخیره آن در یک ثبات، برنامه بزرگ نمیشد و در این تئوری میتوانست سریع تر اجرا شود. برای مثال دستورهایی که یک عمل ریاضی را انجام میداد میتوانست با تعداد کمی بار شدن از حافظه انجام گیرد در حالی که تعداد زیادی از اعدادی که استفاده میشد به صورت ثابت در یک دستور بودند یا به صورت یک عملگر میانی در بین ثبات. در این حالت، در این تکنولوژی برخی از ثباتها به عنوان «سایه» مکان حافظه استفاده میشدند بنابراین ثباتها نقش مکانهای حافظه را بازی مس کردند تا مقدار نهایی آنها بعد از تعداد زیادی از دستورها محقق شود. برای ناظران غیر جدی، این موضوع روشن نبود که مفهوم ریسک اجرا را بهبود میبخشد و ممکن است که آن را بدتر بکند. تنها راه مطمئن شدن شبیهسازی آن بود. بنابر این، این موضوع انجام گرفت و نتیجه مشخص بود. در آزمایشهای متوالی، هر شبیهسازی مفید بودن این طرح را نشان داد. جایی که تفاوت دو پروژه RISC و MIPS در مدیریت ثباتها بود.MIPS به سادگی بسیاری از آن هارا اضافه کرد و آنها را به کامپایل (یا برنامه نویسان زبان اسمبلی) داد که از آن استفاده کند. از طرفیRISC مداراتی را به CPU اضافه کرد تا به کامپایلر کمک کند. ریسک از مفهوم پنجرههای ثبات استفاده کرد که در آن تمام فایلهای رجیستر به بلوکهایی شکسته میشوند و اجازه میدهد تا کامپایلر یک بلوک را به عنوان متغیرهای جهانی و یک بلوک را به عنوان متغیر محلی ببیند. ایده این بود که یک دستور معمول ویژه بسازیم، procedure call، تا پیادهسازی ان در کامپایلر بسیار ساده و آسان باشد. تقریباً تمام زبانهای کامپیوتر از یک سیستم به نام Activation record یا Stack frame برای هر پروسیجر که شامل آدرسی که پروسیجر خوانده شدهاست، پارامترهای گذر داده شده و فضایی که برای برگرداندن نتیجه تابع استفاده میکنند. اکثر اوقات این فریمها بسیار کوچک هستند و معمولاً با ۳ یا کمتر ورودی و یک یا هیچ خروجی که گاهی اوقات یک ورودی به عنوان خروجی دوباره استفاده میشود. در طراحی برکلی یک ثبات پنجرهای مجموعهای از ثباتها بود، تعداد کافی از آنها که Stach frame میتوانست کاملاً در داخل ثباتهای پنجرهای قرار گیرد. در این مورد فراخواندن و خواند از یک پروسیجر بسیار ساده و بسیار سریع است. یک دستور منفرد خوانده میشود تا بلوکهای جدید از ثبات را بسازد (یک پنجره ثبات جدید) و بعد با گذراندن عملوندها به پروسیجر در قسمت “low end” از پنجره جدید، برنامه به سمت پروسیجر پرش میکند. در بازگشت، نتایج در پنجره در انتهای مشابه جای گزین میشوند و پروسیجر میماند. پنجرههای ثبات ساخته میشوند تا در دو انتها overlap شوند. بنابراین نتیجه فراخوانی در پنجره فراخواننده مشاهده میشود. بدون هیچ کپی دادهای. بنابراین فراخوانی پروسیجرهای معمول نباید با حافظه اصلی متقابلاً اثر داشته باشد و بسیار خوب آن را سرعت میدهد. قسمت تاریک این روش این است که پروسیجرهای با متغیرهای محلی بزرگ مشکل آفرینند و با متغیرهای کوچکتر باعث میشود که ثباتها (یک منبع گرانقیمت) ضایع شود. تعداد محدودی از پنجرههای ثبات در این طراحی، مثلاً ۸ عدد، وجود دارد. بنابراین پروسیجرها تنها میتوانند این تعداد مرحله را بسازند تا پیش از اینکه مکانیزم ثبات پنجرهای به حد خود برسد. وقتی که یک پنجره به حد خود رسید هیچ پنجره جدیدی نمیتواند ساخته شود و اگر پروسیجرها تنها مقداری پیش روی کرده باشند؛ ثباتهای بالای عمیقترین فراخوانی قابل دسترس نمیباشند و بنابراین همه آنها به هدر میروند. این کار استنفورد بود به این موضوع عقیده داشت که یک کامپایلر کارآمد میتواند استفاده بهتر از ثباتها ببرد تا یک سیستم سختافزاری ثابت. (دلیل مشابهی برای برنامهنویسی هوشمند زبان اسمبلی به کار میرود)
اولین هدف برای پیادهسازی مفهوم ریسک به "طلاً شهرت دارد. کار بر روی طرح از سال ۱۹۸۰ آغاز شد. کار بر روی طرح در سال ۱۹۸۰ به عنوان بخشی از طراحی VLSI انجام گرفت، اما طراحی پیچیده بعدی همه طراحیهای موجود را خراب کرد. تیم موجود باید ساعتها وقت صرف میکردند تا ابزار را دوباره بنویسند یا بهتر کنند و حتی با این ابزار تنها کمتر از یک ساعت زمان صرف میشد تا طرح از VAX-۱۱/۷۸۰ خارج شود. طراحی نهایی که به ریسک ۱ مشهور است در ACM ISCA در سال ۱۹۸۱ منتشر شد. شامل ۴۴٬۵۰۰ ترانزیستور بود که ۳۱ دستور را پیادهسازی میکرد و یک فایل ثباتها که شامل ۷۸ ثبات ۳۲ بیتی بود. این برای ۶ ثبات پنجره که هر یک شامل ۱۴ ثبات با ۱۸ جهانی اضافه بود. کنترل و دستورها دیکد تنها ۶٪ هسته را شامل میشد در حالی که نوعی از طراحی تنها ۵۰٪ برای نقشه مشابه را استفاده میکرد. فایل ثبات بیشتر فضا را در بر میگرفت. همچنین ریسک ۱ از دستور پایپ لاین دو بخشی برای سرعت بالاتر استفاده کرد اما بدون دستورها پیچیده برای مرتبسازی طراحی مدرن تر. این باعث ایجاد یک مشکل در شاخههای شرطی شد، زیرا کامپایلر باید دستور را با توجه به شاخه شرطی پر کندبه اصطلاح "branch delay slot"با چیزی که که انتخاب شده تا “safe” باشد (برای مثال به نتیجه شرطی وابسته نباشد) بعضی اوقات تنها دستور مناسب برای این زمان NOPاست. تعداد قابل توجهی از طراحی RISC-styleهنوز نیاز به توجه به تأخیر شاخه دارد. بعد از یک ماه تأیید و تصحیح سرانجام طرح به سیستم نوآوری MOSIS برای تولید در۲۲ ژوئن سال ۱۹۸۱ فرستاده شد و از پروسه (۲۰۰۰ nm) استفاده شد. تاخیرهای متنوع باعث شد تا ماسک هایشان را ترک کنند. اولین کامپیوتر ریسک ۱ کارشده در ۱۱ ژوئن راه افتاد. در تست ثابت شد که چیپها اجرایی پایینتر از اجرای مورد انتظار دارند. در کل، یک دستورالعمل در واقع ۲μs طول میکشد تا کامل شود در حالی که طرح اصلی ۴μs تخصیص داده میشود(۵ بار سریع تر). دلیل دقیق برای این مشکل هرگز به تور دقیق توضیح داده نشد. اما در طی تست این موضوع مشخص بود که برخی دستورها در سرعت مورد نظر اجرا نمیشدند. پیشنهادهایی برای این مشکل فیزیکی بود و نه منطقی. باید طرح در سرعت بالایی اجرا میشد تا خوب به نظر میآمد. شبیهسازی برنامههای کوچکی را برای مقایسه ۴MHz RISC۱ با 5 MHz 32-bit VAX ۱۱/۷۸۰ استفاده میکرد و 5 MHz 16-bit Zilog Z۸۰۰۰این را به صورت واضح نشان میداد. سایز برنامه۳۰٪ بیشتر از VAX بود اما بسیار نزدیک به آن از ۸۰۰۰Z. به صورت کلی اجرای کلی RISC۱ دو برابر سریع تر از VAX بود و ۴ برابر Z8000. بسیار جالب، این که برنامهها به صورت کلی میزان یکسانی از حافظه را استفاده میکردندزیرا فایل ثباتها به صورت قابل تأملی احتمال وجود عملوندمورد نیازرا افزایش دادند. این مهم است که به این اجرا ارج نهیم اگرچه طراحی RISC کندتر از VAX بود هیچ خللی بر اهمیت آن وارد نمیکرد. ریسک اجازه تولید یک پروسسور حقیقی ۳۲ بیتی را بر روی یک هسته واقعی میداد و استفاده از چیزی که از قبل یک فاب قدیمی تر بود. طراحی سنتی به سادگی با تعداد زیادی چیپ که به منطق دیکدر اختصاص داده میشوند نمیتواند این کار را انجام دهد. یک طراحی ۳۲ بیتی مانند Motorola ۶۸۰۲۰ نیاز به فابهای جدیدی داشت قبل از اینکه مورد استفاده قرار گیرد. با استفاده از همان فاب، RISC۱ میتوانست کارایی بهتری داشته باشد.
هنگامی که طراحی ریسک ۱ به تأخیر افتاد، کار در برکلی به طراحی آبی تغییر یافت. کار بر روی آبی پروسهٔ کندتری داشت. این سرعت باعث شد که ویژگیهای جدیدی به طرح اضافه شود. کلید تفاوت کش سادهتری بود که یک خط در هر بیت را حذف میکردو به صورت قابل توجهی سایز فایل ثبات را افزایش داد. با توجه به طراحی جدید ذخیره کردن افزایش یافت. ساختار «طلایی» شامل ۷۸ ثبات در ۶ پنجره بود و آبی شامل ۱۳۸ ثبات در ۸ پنجره بود که هر یک ۱۶ ثبات داشت با ۱۰ جهانی. این گسترش باعث شد که هر پروسیجر شانس این را داشته باشد تا تمام متغیرهای محلی خود را ذخیره کند. با این وجود فایلهای بزرگتر ثبات نیاز به ترانزیستورهای کمتری داشتند و در آخر طراحی آبی، به عنوان ریسک ۲ پیادهسازی شد. همه دستورها با تنها ۳۹۰۰۰ ترانزیستور ست شدند.
منابع
- مشارکتکنندگان ویکیپدیا. «Berkeley RISC». در دانشنامهٔ ویکیپدیای انگلیسی، بازبینیشده در ۲۹ آذر ۱۳۹۲.