לחץ כאן לקריאת המאמר המלא

Transcription

לחץ כאן לקריאת המאמר המלא
‫נכתב ע"י‪:‬‬
‫רוני פאר‬
‫‪[email protected]‬‬
‫תאריך עדכון אחרון‪:‬‬
‫‪7.12.2010‬‬
‫מעודכן לגרסה‪:‬‬
‫‪MATLAB 7.11 - R2010b‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫הקדמה‬
‫השימוש בתוכנת ‪ MATLAB‬הרגיל את משתמשיה לעבוד בצורה חופשית ‪ -‬ללא דאגה להקצאות‬
‫זיכרון‪ ,‬ללא חשש להגדרת סוגי המשתנים‪ ,‬והנאה רבה מהיכולת לביצוע פעולות על מטריצות‬
‫בצורה פשוטה וקלה‪ .‬עקב כך‪ ,‬אלגוריתמאים ומתכננים מתחומי תעשייה שונים עושים שימוש רב‬
‫ומתקדם בתוכנה זו‪.‬‬
‫תיכנות בשפת ‪ ,C‬מאידך‪ ,‬הוא אופטימלי לתכנון מערכות זמן‪-‬אמת מבחינת ביצועים‪ ,‬ניצול‬
‫הזיכרון ועוצמת החישוב‪ .‬קוד זה יכול לכלול גם שימוש ב‪ ,Fixed Point-‬ומהנדסי חומרה ותוכנה‬
‫עובדים שעות רבות על ניצול מקסימלי של רכיבים אלו‪ ,‬בכדי להפיק מהם את המירב ולהשיג‬
‫יתרון של ממש על פני המתחרים‪.‬‬
‫כתוצאה מכך‪ ,‬אחד מאתגרי הפיתוח הנפוצים בתעשיה הוא כיצד לבצע המרה מהירה‪ ,‬יעילה‬
‫ואוטומטית במידת האפשר ‪ -‬של תוכנית שנכתבה בסביבה החופשית של ‪ ,MATLAB‬לסביבה‬
‫בעלת האילוצים הקשים וצורת התכנות של שפת ‪.C‬‬
‫מטרת מסמך זה הינה להציג את אחד הפתרונות לאתגר זה‪ :‬שימוש בפרדיגמת ה‪Embedded-‬‬
‫‪) MATLAB‬או‪ (EML :‬ויצירת קוד ‪ C‬באמצעות ‪ .Real-Time Workshop‬ע"י שימוש בדוגמא‬
‫של פונקציה הכתובה ב‪ ,MATLAB-‬מוסבר הליך המרת הקוד כך שיכיל עקרונות תכנות של שפת‬
‫‪ :C‬הגדרות טיפוסי משתנים – לרבות ‪ ,Fixed Point‬הקצאות זיכרון וביצוע אופטימיזציה לניצול‬
‫זיכרון הרכיב וייעול הקוד עצמו‪ .‬כמו כן‪ ,‬משולבים ידע ופרקטיקות שנאספו מתחומי תעשייה‬
‫רבים מרחבי העולם ומקנים לקורא תהליכים מומלצים לביצוע המרה אוטומטית של קוד‬
‫‪ MATLAB‬ל‪.C-‬‬
‫יש לציין כי גם במודלים של ‪ Simulink‬ניתן לשלב פונקציות של ‪ .EML‬בצורה שכזו ניתן לבנות‬
‫סביבת בדיקות קלה ונוחה יותר‪ ,‬או לשלב קוד ‪ EML‬בתוך מודלים מערכתיים גדולים יותר שנבנו‬
‫בעזרת ‪.Simulink‬‬
‫מסמך זה מסתמך בחלקו הגדול על מסמכי ה‪ help-‬המסופקים עם תוכנת ‪ ,MATLAB‬ובא לתת‬
‫מראי מקום חשובים מתוכם – מומלץ לקרוא מסמכים אלו‪.‬‬
‫עמוד ‪ 2‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫תוכן העניינים‬
‫‪.1‬‬
‫הגדרות כלליות ‪5......................................................................................................‬‬
‫‪5.............................................................................................................. MATLAB .1.1‬‬
‫‪ Embedded MATLAB .1.2‬או ‪5........................................................................... EML‬‬
‫‪5....................................................................................................................... RTW .1.3‬‬
‫‪6................................................................................................................ RTW-EC .1.4‬‬
‫‪6....................................................................................................................... MEX .1.5‬‬
‫‪.2‬‬
‫אבני דרך מרכזיות ‪7..................................................................................................‬‬
‫‪ .2.1‬כתיבת קוד ‪ MATLAB‬ובדיקה התנהגותית של האלגוריתם‪7...........................................‬‬
‫‪ .2.2‬בדיקה האם הקוד שנכתב תואם ל‪7.......................................................................EML-‬‬
‫‪ .2.3‬התאמת הקוד למערכות זמן‪-‬אמת ‪8.................................................................................‬‬
‫‪ .2.4‬יצירת פונקציית ‪ MEX‬לצורך בדיקה פונקציונלית של הקוד ‪8............................................‬‬
‫‪ .2.5‬יצירת קוד ‪9...................................................................................................................‬‬
‫‪.3‬‬
‫בדיקה האם הקוד שנכתב תואם ל‪10 ............................................................... EML-‬‬
‫‪ .3.1‬טיפול והסרה של כל ה"הערות" שנתגלו ע"י שימוש ב‪10 ........................................ m-lint-‬‬
‫‪ .3.2‬שימוש בפרגמה ‪11 ............................................................................................ %#eml‬‬
‫‪.4‬‬
‫התאמת הקוד למערכות זמן‪-‬אמת ‪14 ..........................................................................‬‬
‫‪" .4.1‬טיפול" בפונקציות של ‪ MATLAB‬באמצעות ‪14 .................................... eml.extrinsic‬‬
‫‪ 4.2‬הגדרת טיפוסי משתנים ‪15 ...............................................................................................‬‬
‫‪ .4.3‬הגדרת פרמטרים בעלי גודל משתנה )‪16 .................................................. (Variable Size‬‬
‫‪ .4.4‬עבודה עם פרמטרים מסוג ‪18 ............................................................................... struct‬‬
‫‪ .4.5‬עבודה עם מטריצות "ריקות" ‪19 ......................................................................................‬‬
‫‪ .4.6‬הגדרת משתנים בצורה מותנית ‪19 ...................................................................................‬‬
‫‪ .4.7‬הקצאת זיכרון מינימלית באמצעות ‪20 ..................................................... eml.nullcopy‬‬
‫‪ .4.8‬אינדקסים של וקטורים בעלי גודל משתנה ‪20 ....................................................................‬‬
‫‪ .4.9‬תמיכה במשתנים גלובליים ‪21 ........................................................................... global -‬‬
‫‪ .4.10‬שימוש ב‪21 ............................................................................................. streaming-‬‬
‫‪ .4.11‬בדיקה פונקציונלית ‪22 ..................................................................................................‬‬
‫‪.5‬‬
‫יצירת פונקציית ‪ MEX‬לצורך בדיקה פונקציונלית של הקוד ‪24 .....................................‬‬
‫‪ .5.1‬יצירת פונקציית ‪25 .............................................................................................. MEX‬‬
‫‪ .5.2‬בדיקה למול קוד המקור ‪26 .............................................................................................‬‬
‫‪ .5.3‬בדיקת זמני ריצה של קוד ה‪ MEX-‬והשוואה למקור ‪26 .....................................................‬‬
‫‪.6‬‬
‫יצירת קוד ‪27 ...........................................................................................................‬‬
‫‪ .6.1‬תוצרים שונים מהפקודה ‪27 ................................................................................... emlc‬‬
‫‪ .6.2‬התאמה אישית של הקוד הנוצר )דגלון ‪28 ................................................................... (–s‬‬
‫עמוד ‪ 3‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .6.3‬שימוש בדו"ח יצירת הקוד ‪32 ..........................................................................................‬‬
‫סיכום ‪33 .................................................................................................................‬‬
‫‪.7‬‬
‫עמוד ‪ 4‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .1‬הגדרות כלליות‬
‫במסמך זה נעשה שימוש במספר ביטויים מעולם התוכן של משתמשי ‪ .MATLAB‬מטרת חלק זה‬
‫היא להבהיר מושגים אלו‪ ,‬וליצור שפה משותפת אחידה‪:‬‬
‫‪MATLAB .1.1‬‬
‫ה"סטנדרט" בתעשייה ‪ -‬התוכנה מבית היוצר של חברת ™‪ MathWorks‬אשר מאפשרת‬
‫לבצע חישובים נומריים‪ ,‬לנתח מידע ולהציגו בצורה גרפית‪ ,‬לפתח ולבדוק אלגוריתמים‬
‫סבוכים ופשוטים כאחד‪ ,‬והבסיס לכל המוצרים הנלווים של ‪ - MathWorks‬המוסיפים‬
‫יכולות מתקדמות בתחום עיבוד התמונה‪ ,‬עיבוד האות‪ ,‬תכנון מערכות בקרה‪ ,‬ועוד‪.‬‬
‫‪ MATLAB‬הינה שפה עילית‪ ,‬המאפשרת לבנות אלגוריתמים מורכבים ללא צורך לדאגה‬
‫להקצאת זיכרון‪ ,‬להגדרות משתנים ופעולות נוספות הנדרשות בשפות תכנות נמוכות יותר‪.‬‬
‫‪ Embedded MATLAB .1.2‬או ‪EML‬‬
‫כאשר אנו מעוניינים לעבור מעולם הפיתוח ב‪ MATLAB®-‬למערכות זמן‪-‬אמת‪ ,‬אנו‬
‫צריכים לכתוב בפונקציות המתאימות למערכות אלו‪ .‬אוסף הפונקציות הזה‪ ,‬הנגזר מתוך‬
‫‪ MATLAB‬עצמה – נקרא ‪ .Embedded MATLAB‬האיור הבא מדגים את עולם ה‪-‬‬
‫‪ ,Embedded‬בהשוואה למקור‪.‬‬
‫כפי שניתן לראות‪ ,‬הפעולות שאינן נתמכות מחולקות ל‪ 2-‬סוגים – ויזואליזציה והקצאת‬
‫זיכרון דינמית‪ .‬עם זאת‪ ,‬חשוב לזכור שבמערכות זמן‪-‬אמת אמיתיות‪ ,‬אין שימוש של ממש‬
‫בפעולות אלו‪ ,‬ולכן אין כאן פגיעה ברמת העבודה‪.‬‬
‫‪RTW .1.3‬‬
‫על מנת לייצר קוד ‪ C‬מתוך ‪ ,MATLAB‬יש להתקין כלי נוסף‪ ,‬הנקרא ‪Real-Time‬‬
‫‪ ,Workshop‬או בקיצור ‪ .RTW‬כלי זה מאפשר לייצר קוד ‪ C‬גנרי‪ ,‬שניתן להפעילו על כל‬
‫מערכות המחשוב הקיימות כיום )‪ Linux ,MAC ,PC‬וכדומה(‪ .‬הקוד הנוצר מיועד‬
‫למערכות אלו‪ ,‬שבעיקרן אינן מוגבלות מבחינת משאבים )למשל ‪ -‬תמיד ניתן להוסיף עוד‬
‫זיכרון או לעבור ל‪ 64-‬ביט(‪ ,‬ועל כן הוא יעיל בצורה הולמת‪.‬‬
‫עמוד ‪ 5‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪RTW-EC .1.4‬‬
‫למערכות זמן‪-‬אמת המוגבלות במשאבים )זיכרון‪ ,‬זמני ריצה( קיים כלי נוסף‪ ,‬אשר נקרא‬
‫‪ ,Real-Time Workshop – Embedded Coder‬או בקצרה ‪ .RTW-EC‬כלי זה מאפשר‬
‫לייצר קוד ‪ C‬המותאם למעבדים ספציפיים )אינטל‪ ,‬מוטורולה‪ ,‬מיקרוצ'יפ‪Analog ,TI ,‬‬
‫‪ Devices‬וכדומה(‪ .‬הקוד שנוצר הוא יעיל ביותר‪ ,‬ניתן לשלוט על מראהו ועל אופן השמתו‬
‫במרחב הזיכרון של הרכיב‪ ,‬ועוד‪.‬‬
‫‪MEX .1.5‬‬
‫פונקציות ‪) MEX‬או ‪ (MATLAB Executables‬הן למעשה פונקציות שנכתבו בשפה השונה‬
‫מ‪ ,MATLAB-‬ושולבו בתוך ‪ .MATLAB‬ניתן לייבא קוד ‪ C‬קיים‪ ,‬קוד ‪ Fortran‬ואפילו‬
‫קוד ‪ .ADA‬השימוש בפונקציות אלו זהה לשימוש בפונקציות ‪ ,MATLAB‬והן מאפשרות‬
‫למשתמשי ה‪ MATLAB-‬לנצל קוד קיים במקום לכותבו שוב‪.‬‬
‫עמוד ‪ 6‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .2‬אבני דרך מרכזיות‬
‫תהליך יצירת הקוד והמרת קוד ה‪ MATLAB-‬לקוד ‪ C‬מושתת על מספר שלבים מרכזיים‪ ,‬אשר‬
‫אופייניים גם לשלבי הפיתוח המקובלים בתעשיה‪ .‬בפרק זה יפורטו השלבים המרכזיים ו הפעולות‬
‫המרכזיות המבוצעות בשלבים אלו‪ .‬בהמשך יפורטו שלבים אלו בצורה מעמיקה ורחבה יותר‪,‬‬
‫וישולבו דוגמאות הלכה למעשה‪.‬‬
‫להלן הסכימה הכללית של התהליך‪:‬‬
‫‪ .2.1‬כתיבת קוד ‪ MATLAB‬ובדיקה התנהגותית של האלגוריתם‬
‫בשלב הראשון‪ ,‬נכתב האלגוריתם הטהור ע"י המתכנן או האלגוריתמאי‪ .‬אלגוריתם זה יכול‬
‫לכלול פעולות הנוגעות לתחום עיבוד תמונה‪/‬וידאו‪ ,‬עיבוד אותות‪ ,‬מערכות בקרה ועוד‪,‬‬
‫ויתכן כי המתכנן נעזר בפונקציות עזר מתוך ספריות המסופקות עם ‪ MATLAB‬או עם כלי‬
‫ההרחבה הנשענים עליה‪.‬‬
‫ברוב המקרים יבנה המתכנן סביבת בדיקות לאלגוריתם שלו‪ ,‬באמצעותה יבדוק פרמטרים‬
‫שונים ואליה יכניס כניסות שונות ויבחן את תוצאות האלגוריתם באמצעים ויזואליים‬
‫)גרפים‪ ,‬סקופים וכדומה(‪ ,‬יקרא או יכתוב מידע מסביבת העבודה או מקבצים‪ ,‬ויבצע‬
‫השוואות לתיאוריה שאותה בחן‪.‬‬
‫בסוף הליך זה נמצא בידי המתכנן קוד הכתוב בשפת ‪ MATLAB‬אשר מממש את‬
‫האלגוריתם בצורה המדוייקת ביותר‪ .‬נהוג לקרוא לאלגוריתם זה "‪"Golden Reference‬‬
‫או "אמת הסמך להשוואה"‪ .‬בכל אחד מהשלבים הבאים‪ ,‬נרצה לבחון את השינויים שנעשו‬
‫למול המקור‪ ,‬ולוודא כי פונקציית ה‪ MATLAB-‬עדיין תואמת בפעולתה ל‪Golden -‬‬
‫‪.Reference‬‬
‫חלק זה לא יפורט בהמשך‪ ,‬ומסתמך על כך שהקורא מכיר את התכנות ב‪MATLAB-‬‬
‫ברמה בסיסית‪.‬‬
‫‪ .2.2‬בדיקה האם הקוד שנכתב תואם ל‪EML-‬‬
‫כפי שהוזכר קודם‪ ,‬בכדי לייצר קוד ‪ C‬מתוך ‪ ,MATLAB‬ראשית עלינו לוודא כי צורת‬
‫הכתיבה שלנו‪ ,‬והפונקציות שבהן השתמשנו נתמכות ל‪ .EML-‬קיימות כ‪ 300-‬פונקציות‬
‫‪ MATLAB‬הנתמכות ל‪ ,EML-‬עוד כ‪ 100-‬פונקציות נוספות הקשורות ל‪ Fixed Point-‬ועוד‬
‫עמוד ‪ 7‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫כ‪ 40-‬פונקציות הקשורות לכלי ה‪ .Signal Processing-‬רשימת הפונקציות המלאה ניתן‬
‫למצוא בקישור הבא )או ב‪ help-‬של ‪ ,MATLAB‬תחת ‪:(Embedded MATLAB‬‬
‫‪http://www.mathworks.com/access/helpdesk/help/toolbox/eml/ug/bq1h2z7-9.html‬‬
‫הערה‪ :‬יש לציין כי בגרסה ‪ R2010a‬פיתחה חברת ‪ MathWorks‬את השימוש ב‪System -‬‬
‫‪ ,Objects‬אשר מרחיבים פונקציות אלו וכוללים פונקציות רבות מתחום עיבוד התמונה‪,‬‬
‫עיבוד האות )והחל מ‪ R2010b-‬התקשורת( – אשר עד כה נתמכו ליצירת קוד רק מתוך‬
‫‪.Simulink‬‬
‫כאמור‪ ,‬על מנת לייצר קוד‪ ,‬נדרש כי כל הפונקציות ייתמכו‪.‬‬
‫על מנת לוודא התאמה זו‪ ,‬יתכן ונידרש לכתוב מחדש חלק מהפונקציות שאנו משתמשים‬
‫בהן‪ .‬לצורך כך‪ ,‬מומלץ כי ההמרה תיעשה ע"י המתכנן‪ ,‬אשר מכיר את אופן הפעולה של‬
‫הפונקציה ויודע במידת הצורך כיצד ניתן להמירה‪.‬‬
‫‪ .2.3‬התאמת הקוד למערכות זמן‪-‬אמת‬
‫לאחר שבסעיף הקודם בדקנו כי כל ה"טקסט" הנמצא בתוך קוד ה‪ MATLAB-‬תואם ל‪-‬‬
‫‪ ,EML‬עלינו כעת לחבוש את כובע המתכנת‪ ,‬ולדאוג לכך שהאלגוריתם לא רק יהיה כתוב‬
‫ב‪ ,EML-‬אלא גם יתאים מבחינת אופן הפעולה שלו למערכות זמן אמת – מערכות‬
‫‪ .Embedded‬למשל‪ ,‬עלינו לוודא שהאלגוריתם מקבל כניסות שהן ב‪ Stream-‬של מידע‪ ,‬ולא‬
‫כ‪ Bulk-‬של מידע‪ .‬לרוב מערכות זמן‪-‬האמת ישנה כניסה דיגיטלית אשר מסוגלת להעביר‬
‫מידע ב"חבילות" )או ‪ (Packets‬של מידע‪ ,‬ולא נעשה תרגום אוטומטי ל"תמונה" או ל"אות"‬
‫או ל"חיישן"‪ .‬לכן‪ ,‬עלינו לדאוג לכך שהאלגוריתם הנדון יידע לאגור מידע שמגיע אליו‬
‫בתצורה של חבילות מידע‪ ,‬ולבצע את הפעולה שלשמה נועד רק כאשר קיבל מספיק מידע‪.‬‬
‫בנוסף‪ ,‬עלינו לוודא שהקוד יהיה יעיל וינצל כמה שפחות זיכרון או משאבי מערכת‪.‬‬
‫בשלב זה גם לרוב נוסיף שימוש באותות בעלי גודל משתנה )או ‪ (Variable Size‬אשר‬
‫מאפשרים לנו לעבוד עם כניסות שגודלן אינו קבוע בכל שלב ושלב של ריצת האלגוריתם‪.‬‬
‫בשלב זה יש כמובן להחליט על ארכיטקטורת המעבד שאיתו נעבוד‪ ,‬וכתוצאה מכך גודל‬
‫המשתנים שאיתם נעבוד )‪ 16 ,8‬או ‪ 32‬ביט(‪ .‬בעבודה עם ‪ MATLAB‬ניתן לבחור כל אחד‬
‫מהגדלים הללו תוך כדי ריצה‪ ,‬אך מערכות זמן אמת חייבות לדעת מראש מהם סוגי‬
‫המשתנים‪.‬‬
‫‪ .2.4‬יצירת פונקציית ‪ MEX‬לצורך בדיקה פונקציונלית של הקוד‬
‫בטרם נייצר קוד ‪ C‬ונטמיע אותו ברכיב החומרה שבחרנו‪ ,‬נרצה לוודא כי הקוד שאנחנו‬
‫כותבים מבצע את אותן הפעולות כמו ה‪ .Golden Reference-‬לשם כך‪ ,‬נייצר פונקציית‬
‫‪ .MEX‬פונקציות ‪) MEX‬או ‪ (MATLAB Executable‬הן פונקציות שניתן להריץ אותן‬
‫בסביבת ‪ ,MATLAB‬אך הן למעשה קוד ‪ C‬שעבר תהליך של קומפילציה – כלומר הרצה‬
‫של קוד ‪ C‬בתוך ‪.MATLAB‬‬
‫את פונקציית ה‪ MEX-‬ניתן לשלב באותה סביבת בדיקות שבה נבדק האלגוריתם המקורי‪.‬‬
‫את אותן הפעולות שבוצעו על קוד ה‪ MATLAB-‬ניתן לבצע גם על פונקציה זו‪ ,‬ולהשוות‬
‫עמוד ‪ 8‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫בצורה מלאה ביניהן‪ .‬כל שינוי בתוצאות המתקבלות מפונקציית ה‪ MEX-‬מעיד על חוסר‬
‫דיוק שהוכנס בהליך ההמרה ל‪ .EML-‬המטרה היא לוודא שחוסר הדיוק הוא מספיק קטן‬
‫בכדי שיהיה "זניח"‪ .‬יש להבין כי חוסר דיוק זה נובע מהמעבר מעבודה בסביבת מחשוב של‬
‫‪ 64‬ביט )עם דיוק כפול( לסביבת עבודה הנמצאת לרוב ב‪ 32-‬ביט )דיוק יחיד(‪ .‬לכן – שגיאות‬
‫קוונטיזציה צפויות להתקבל‪.‬‬
‫בשלב זה יש גם להחליט על האם המעבד הסופי שאליו נייצר קוד הוא מסוג ‪ Float‬או‬
‫‪ .Fixed‬במידה והוא מסוג ‪ – Float‬נוכל להמשיך לשלב הבא‪ .‬אחרת‪ ,‬עלינו לעבור שלב נוסף‬
‫של המרת האלגוריתם לעבודה ב‪ .Fixed-‬הליך זה יכול להיות קל יותר ע"י שימוש ב‪Fixed -‬‬
‫‪ ,Point Toolbox‬ולאחר סיומו מצריך בדיקה נוספת של פונקציית ‪ MEX‬למול ה‪Golden -‬‬
‫‪ ,Reference‬בכדי לוודא שחוסר הדיוק הנובע מקוונטיזציה לא פגע באופן הפעולה של‬
‫האלגוריתם‪.‬‬
‫‪ .2.5‬יצירת קוד‬
‫לאחר שייצרנו פונקציית ‪ MEX‬ובדקנו אותה למול ה‪ ,Golden Reference-‬ניתן לייצר‬
‫קוד‪ .‬בשלב זה עלינו להגדיר לאיזה מעבד ברצוננו לייצר קוד‪ ,‬כאשר הרשימה של המעבדים‬
‫הנתמכים הינה ארוכה )ומתארכת עם השנים(‪ .‬רשימה מלאה ניתן למצוא ב‪:‬‬
‫‪http://www.mathworks.com/products/rtwembedded/supportedio.html‬‬
‫יש להדגיש כי ישנן פעולות מתימטיות רבות אשר יש להן מימוש אופטימלי בהתאם לסוג‬
‫החומרה‪ ,‬ולכן מומלץ להגדיר מהי החומרה שעובדים איתה‪ .‬מעבר להגדרות הבסיסיות‬
‫האופייניות למעבדים )כמו ‪ ,Big/Little Endian‬גודל משתנים וכדומה(‪ ,‬גם המימוש עצמו‬
‫ייעשה בהתאם למעבד‪.‬‬
‫במידה ועל מחשב יצירת הקוד מותקנים כלי יצירת קוד מתקדמים )כמו ‪Embedded IDE‬‬
‫‪ Link‬או ‪ (Target Support Package‬אזי ניתן לממש בצורה יעילה גם פונקציות מתקדמות‬
‫יותר )כמו ‪ ,(FFT‬ולהגיע למימוש חומרתי ברמת אסמבלי של פעולות בסיסיות אשר זמינות‬
‫על הרכיב עצמו )כמו ‪ PID‬עבור בקר מסדרת ‪ C2000‬של ‪ Texas Instruments‬או ‪ADC‬‬
‫למעבדים של ‪.(Analog Devices‬‬
‫את הקוד שייצרנו ניתן לשלב בפרוייקט גדול יותר של ‪ Visual C++‬למשל‪ ,‬או בפרוייקטים‬
‫של מערכות זמן‪-‬אמת הקשורים ל‪ IDE-‬של הסביבה איתה עובדים )כמו ‪ CCS‬של ‪Texas‬‬
‫‪ Instruments‬או ‪ Visual DSP++‬של ‪ .(Analog Devices‬את הקוד הזה לא ניתן כמובן‬
‫להחזיר לתוך ‪ MATLAB‬ולבדוק אותו שוב – שכן הארכיטקטורה איננה זהה‬
‫לארכיטקטורה של המחשב עליו מותקן ‪.MATLAB‬‬
‫במידה ואנחנו עובדים עם ‪ ,Simulink‬ניתן לשלב את קוד ה‪ EML-‬בתוך מודל רחב יותר‪,‬‬
‫ולהמשיך בהליך הפיתוח כאשר האלגוריתם שנכתב הוא כעת בלוק אחד מתוך מערכת‬
‫מלאה יותר‪ ,‬לאחר שנבדק בצורה מלאה וידוע אופן פעולתו‪.‬‬
‫ישנה כמובן אפשרות לשילוב קוד ‪ C‬קיים‪ ,‬שנכתב בעבר‪ ,‬בתוך ‪ EML‬או בתוך ‪,Simulink‬‬
‫ובמקרה זה סביבת הפיתוח של ‪ MATLAB‬יכולה להיות סביבת האינטגרציה המלאה‪.‬‬
‫עמוד ‪ 9‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .3‬בדיקה האם הקוד שנכתב תואם ל‪EML-‬‬
‫בתחילת שלב זה‪ ,‬קיים אלגוריתם הכתוב בשפת ‪ ,MATLAB‬ואשר נבדק כי הוא מבצע את‬
‫תפקידו בצורה תקינה‪ .‬מטרת שלב זה היא ליצור קוד הכתוב ב‪ .EML-‬לפני תחילת העבודה‬
‫המפורטת בפרק זה‪ ,‬מומלץ לשמור גרסה חדשה של הקובץ שעימו עובדים – בכדי לא לפגוע ב‪-‬‬
‫‪.Golden Reference‬‬
‫המלצה מס' ‪1‬‬
‫בטרם ביצוע שינויים כלשהם‪ ,‬מומלץ לשמור את הקובץ בשם חדש‪ ,‬על מנת שתמיד יהיה ניתן לחזור‬
‫לשמירה האחרונה‪.‬‬
‫לדוגמא‪ :‬אם שם הפונקציה המקורית הוא ‪ ,myFunction‬מומלץ לשמור את הגרסאות בסדר עולה‪ ,‬כגון‬
‫‪. myFunction_01‬‬
‫את השינויים שבוצעו מומלץ לתעד באמצעות הערות‪ ,‬וניתן כמובן לשמור גרסאות שונות בכלי ה‪Version -‬‬
‫‪ Control‬במידה והוא בשימוש במערכותיכם‪ .‬קראו על איך ‪ MATLAB‬מחובר למערכות ‪:VC‬‬
‫‪http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_env/f7-5297.html‬‬
‫או ב‪ help-‬כמובן‪.‬‬
‫‪ .3.1‬טיפול והסרה של כל ה"הערות" שנתגלו ע"י שימוש ב‪m-lint-‬‬
‫החל מגרסה ‪ ,R2007a‬שולב בתוך ה‪ editor-‬של ‪ MATLAB‬כלי ה‪ m-lint-‬אשר בודק את‬
‫הקוד בצורה סטטית‪ .‬תפקידו הוא לוודא כי הקוד שכתבנו אינו מכיל שגיאות‪ ,‬ובמידה‬
‫ושגינו‪ ,‬יעיר לנו על "הערה" )הקוד בעייתי‪ ,‬אך יכול לרוץ( או "שגיאה" )הקוד בעייתי‪ ,‬ולא‬
‫יכול לרוץ(‪.‬‬
‫בטרם אנו ממשיכים הלאה‪ ,‬מומלץ )וחובה( לוודא כי אין הערות‪/‬הודעות‪/‬שגיאות כלשהן‬
‫אשר לא טופלו‪ .‬במידת הצורך יש להשתמש ב‪ "Suppress this Instance of … "-‬ע"י‬
‫לחיצת כפתור ימני בעכבר על ההערה שהתגלתה‪ .‬להלן דוגמא להערה על כך שמומלץ לסיים‬
‫כל פקודה ב ";"‪:‬‬
‫עמוד ‪ 10‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .3.2‬שימוש בפרגמה ‪%#eml‬‬
‫כאשר נעבוד ב‪ ,EML-‬ה‪ m-lint-‬הוא בעל יכולות נוספות‪ ,‬ויכול לבדוק נושאים הקשורים ל‪-‬‬
‫‪ .EML‬למשל ‪ -‬לבדוק שכל הפונקציות שאנו משתמשים בהן‪ ,‬נתמכות ב‪ .EML-‬על מנת‬
‫להפעיל את ה‪ m-lint-‬במצב זה‪ ,‬יש להשתמש בפרגמה ‪ . %#eml‬את הפרגמה ניתן למקם‬
‫בכל מקום בתוך קובץ ה‪ ,m-‬אך מומלץ לשים אותה לפני הגדרת הפונקציה‪ .‬להלן דוגמא‪:‬‬
‫לאחר שמיקמנו את הפרגמה במקומה‪ ,‬על ה‪ m-lint-‬להיות "ירוק"‪ ,‬כלומר לא להכיל אף‬
‫שגיאה )ראה תמונה(‪.‬‬
‫להלן דוגמא לקוד שמכיל שגיאה שכזו‪ .‬קוד זה משתמש בפונקציית ה‪ edge-‬מתוך ספריית‬
‫ה‪ .Image Processing-‬פונקציה זו איננה נתמכת ב‪ ,EML-‬ולכן מתקבלת שגיאה‪:‬‬
‫עמוד ‪ 11‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫מהיכרות עם הקוד‪ ,‬קובץ ה‪ m-‬שנכתב אמור להשתמש בשיטת ‪ sobel‬של פונקציה זו‪.‬‬
‫אלגוריתם זה מבוסס על שימוש ב‪ 2-‬פעולות של קונבולוציה‪ ,‬ולכן אם נכתוב רק אותו‬
‫כפונקציה‪ ,‬הוא כן ייתמך והשגיאות כבר לא קיימות‪:‬‬
‫באופן זה יש לוודא כי כל הפונקציות שאנו משתמשים בהן ייתמכו‪.‬‬
‫דוגמא נוספת אשר עשויה להתקבל‪ ,‬היא על ביצוע הקצאות דינמיות של זיכרון‪ ,‬אשר אינן‬
‫נתמכות‪ .‬נסתכל לדוגמא על מקטע הקוד הבא‪ ,‬אשר אמור לבצע העתקה פשוטה של זכרון‬
‫בין ‪ 2‬משתנים‪ .‬המשתנה ‪ CarbonCopy‬הוא לא בעל גודל מוגדר מראש‪ ,‬ולכן מתקבלת‬
‫הערה על כך שמשתנה זה חייב להיות מוגדר בזמן הקריאה לפונקציה‪:‬‬
‫עמוד ‪ 12‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫מצב זה הינו מקובל ביותר בעבודה עם ‪ ,MATLAB‬שכן מערכת ההפעלה של ‪MATLAB‬‬
‫המטפלת בנושא הקצאת הזיכרון‪ ,‬תדאג בכל שלב ריצה של הלולאה להגדיל את המשתנה‬
‫בהתאם‪ .‬היא למעשה תעשה בכל שלב הקצאה מחודשת של זיכרון‪ ,‬ותעתיק אליו את‬
‫הערכים החדשים‪.‬‬
‫פעולה זו כמובן איננה נתמכת ב‪ ,EML-‬שכן בזמן הקריאה לפונקציה לא ידוע כמה פעמים‬
‫תיקרא‪ ,‬ולכן גודל המשתנה איננו מוגדר מראש‪ .‬הקצאת זיכרון דינמית זו איננה נתמכת‪,‬‬
‫מה גם שבמערכות זמן‪-‬אמת רבות לא היינו רוצים לקבל גדילה של משתנים בצורה לא‬
‫מבוקרת‪.‬‬
‫על מנת לטפל בבעיה זו‪ ,‬יש לבצע הקצאה של גודל המשתנה בזמן הכניסה לפונקציה‪ .‬דוגמא‬
‫לכך מצויה בשורה ‪ 3‬של הקוד לעיל – ע"י שימוש בפקודה ‪.zeros‬‬
‫הערה‪:‬‬
‫בהתאם ל‪ 2-‬הדוגמאות שראינו לעיל‪ ,‬ניתן להסיק כי ייתכן מצב שבו נכתוב חלק מהקוד‬
‫מחדש‪ ,‬ולא "נהנה" מהיתרונות שבעבודה עם ‪ .MATLAB‬עם זאת‪ ,‬ברגע שנבצע את‬
‫השינויים‪ ,‬אנו נקבל פעולה מהירה יותר גם של קוד ה‪ ,MATLAB-‬שכן הוא ירוץ בצורה‬
‫יעילה יותר ‪ -‬ההעתקות הרבות שלא יבוצעו‪ ,‬ההימנעות מבדיקות "מיותרות" של פונקציות‬
‫רובסטיות וכדומה ‪ -‬יחסכו זמן ריצה רב‪ .‬משתמשים רבים שעברו מ‪ MATLAB-‬ל‪EML-‬‬
‫דיווחו על חיסכון בזמני ריצה ברמה של אחוזים רבים‪ ,‬ובמקרים קיצוניים עד כדי ‪90%‬‬
‫מזמן הריצה )!(‪.‬‬
‫המלצה מס' ‪2‬‬
‫מומלץ לפעול בהתאם להנחיות ה‪ .m-lint-‬הנחיות אלו נובעות מסיבות של יעילות‪ ,‬בדיקת אפשרות‬
‫ליצירת קוד‪ ,‬וכן הימנעות משגיאות מיותרות‪ .‬קיימת אפשרות לביצוע תיקון אוטומטי לחלק מההערות‪.‬‬
‫ניתן להפעיל את ה‪ M-Lint-‬ולבחור בדיקות ספציפיות ע"י שינוי ה‪ Preferences-‬של ה‪ m-lint-‬באופן‬
‫הבא )תחת סביבת העבודה של ‪:(MATLAB‬‬
‫‪File-> Preferences-> M-Lint-> Enable Integrated M-Lint Warnings and Error Messages‬‬
‫עמוד ‪ 13‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .4‬התאמת הקוד למערכות זמן‪-‬אמת‬
‫בשלב זה יש לחבוש את כובע המתכנת יותר מאשר את כובע האלגוריתמאי ב‪ ,MATLAB-‬שכן‬
‫כעת עלינו לחשוב על הקוד שהולך להיווצר ובאיזו מערכת הוא הולך להיות משולב‪.‬‬
‫בקוד הנוצר‪ ,‬נרצה למנוע שכפולים מיותרים של משתנים )על מנת לחסוך בזיכרון(‪ ,‬להגדיר את‬
‫טיפוסי המשתנים ואת גודלם המירבי בכדי להקצות זיכרון בצורה מתאימה‪ ,‬ולטפל בפונקציות‬
‫הדואגות לויזואליזציה של ‪ ,MATLAB‬או בקריאה לפונקציות שאינן נתמכות‪ .‬כאן נטפל גם‬
‫בממשקי הפונקציה ולכך שהיא צריכה לעבוד בסופו של דבר על מעבד בזמן‪-‬אמת‪.‬‬
‫‪" .4.1‬טיפול" בפונקציות של ‪ MATLAB‬באמצעות ‪eml.extrinsic‬‬
‫תוכנת ‪ MATLAB‬מכילה הרבה מאד פונקציות אשר אינן נתמכות ליצירת קוד‪ .‬הדוגמא‬
‫הכי פשוטה לפונקציה שכזו היא פונקציית ‪ ,plot‬אשר מדפיסה גרף בחלון חדש‪ .‬פונקציה זו‬
‫כמובן איננה רלוונטית בעיסוק במערכות זמן‪-‬אמת‪.‬‬
‫על מנת שלא לשנות את כל הקוד מספר פעמים‪ ,‬וליצור פונקציות נפרדות לריצה ב‪-‬‬
‫‪ MATLAB‬ופונקציות אחרות ליצירת קוד‪ ,‬ניתן להגדיר פונקציות אלו כפונקציות‬
‫"חיצוניות" )או ‪ .(extrinsic‬הגדרה זו בעלת ‪ 2‬משמעויות‪ .1 :‬בזמן הרצת הפונקציה ב‪-‬‬
‫‪ – MATLAB‬תתנהג באופן רגיל‪ .2 .‬בזמן יצירת קוד – לא ייווצר קוד מפונקציה זו‪.‬‬
‫להלן דוגמא לפונקציה שכזו‪:‬‬
‫בדוגמא זו ניתן לראות הגדרת הפונקציות ‪ patch‬ו‪ axis-‬כ‪ .extrinsic-‬כפי שניתן לראות‬
‫הפונקציה הסופית נתמכת ב‪ %#eml-‬ונתמכת גם ליצירת קוד כמובן‪.‬‬
‫עמוד ‪ 14‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫המלצה מס' ‪3‬‬
‫בצעו הפרדה בתוך הפונקציות בין פעולות הקשורות לויזואליזציה לבין האלגוריתם המקורי‪.‬‬
‫בדוגמא הקודמת הייתה הפרדה בין ‪ – create_plot‬פונקציה הדואגת להדפסת התוצאות לבין‬
‫‪ – Pythagoras‬הפונקציה אשר מבצעת את עיבוד הנתונים‪ .‬בצורה כזו ייחסכו קריאות רבות‪,‬‬
‫והקוד שנוצר יהיה "נקי" ויעיל יותר‪ .‬בדוגמא שלעיל – כלל לא ייווצר קוד מהפונקציה השניה‪.‬‬
‫‪ .4.2‬הגדרת טיפוסי משתנים‬
‫על מנת ליצור את טיפוסי המשתנים‪ ,‬עלינו להצהיר עליהם‪ .‬ניתן לעשות זאת ב‪ 2-‬אופנים‪:‬‬
‫‪ .1‬שימוש בפקודה ‪.assert‬‬
‫‪ .2‬שימוש במשתנה לדוגמא‪ ,‬שמכיל את הגודל וטיפוס המשתנה‪.‬‬
‫שימוש בפקודה ‪assert‬‬
‫הפקודה ‪ assert‬מחזירה ערך שלילי כאשר התנאי שהיא בודקת איננו מתקיים‪ .‬למשל‪ ,‬קטע‬
‫הקוד הבא איננו נכון ולכן התוצאה היא שלילית‪:‬‬
‫כאשר אנו משתמשים ב‪ ,EML-‬לפונקציה זו ישנה חשיבות ראשונה במעלה‪ ,‬שכן במהלך‬
‫יצירת הקוד‪ ,‬הקומפיילר בוחן את הערכים הנבדקים ע"י פונקציה זו‪ ,‬ומשתמש בהם בכדי‬
‫להגדיר את הפרמטרים השונים מבחינת טיפוס ומבחינת גודל‪.‬‬
‫לדוגמא‪ ,‬אם ברצוננו להגדיר פרמטר סקלרי‪ ,X ,‬שיהיה מטיפוס ‪ uint16‬ובעל גודל מקסימלי‬
‫של ‪ ,1,000‬נעשה זאת ע"י ההגדרה הבאה‪:‬‬
‫;))'‪assert(isa(X, 'uint16‬‬
‫;)‪assert(X <= 1000‬‬
‫הפקודה ‪ isa‬בודקת את טיפוס הפרמטר ומשווה אותו ל‪ uint16-‬במקרה זה‪.‬‬
‫באופן דומה‪ ,‬אם ברצוננו להגדיר פרמטר‪ ,A ,‬כך שיהיה מטריצה בגודל ‪ ,10x20‬מטיפוס‬
‫‪ ,complex‬נעשה זאת באופן הבא‪:‬‬
‫;))‪assert(~isreal(A‬‬
‫;))]‪asser(all(size(A) == [10 20‬‬
‫הפקודה ‪ all‬בודקת כי בתוצאה המתקבלת מההשוואה‪ ,‬כל הערכים הם "נכונים"‪.‬‬
‫עמוד ‪ 15‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫באופן זהה‪ ,‬ניתן להשתמש בפקודה ‪ assert‬בכדי לוודא גדלי וטיפוסי פרמטרים סקלריים‪,‬‬
‫מטריצות בעלות ‪ N‬מימדים‪ ,‬מערכים )‪ ,(struct‬משתני ‪) Fixed Point‬עם הפקודה ‪,(isfi‬‬
‫משתני כניסה לפונקציה ומשתנים שנעשה בהם שימוש בתוך הפונקציה‪.‬‬
‫==< משתני המוצא "יורשים" ערכים אלו מתוך נתוני המשתנים הבונים אותם – ולכן לא‬
‫נדרש להגדירם‪.‬‬
‫שימוש במשתנה לדוגמא‬
‫השימוש במשתנים לדוגמא יכול להיעשות רק בזמן הליך יצירת הקוד עצמו ולא ניתן‬
‫לשילוב בתוך הקוד‪ .‬לצורך כך נעשה שימוש בדגלון ‪ –eg‬בתוספת לפונקציה ‪emlmex‬‬
‫)יצירת ‪ (MEX‬או ‪) emlc‬יצירת קוד ‪:(C‬‬
‫‪emlmex -eg {single(0)} myFunction‬‬
‫‪emlc -eg {zeros(1,4,'uint16'),double(0)} myFunc‬‬
‫‪1.‬‬
‫‪2.‬‬
‫בדוגמא הראשונה‪ ,‬נאמר לקומפיילר שהפונקציה מצפה לקבל משתנה מטיפוס ‪.single‬‬
‫שימו לב כי ערך המספר עצמו – ‪ 0‬בדוגמא זו – כלל איננו משפיע על התוצאה‪ ,‬אלא רק על‬
‫טיפוס המשתנה‪.‬‬
‫בדוגמא השניה‪ ,‬נאמר לקומפיילר שהפונקציה מצפה לקבל ‪ 2‬פרמטרים‪ .‬הראשון הוא מערך‬
‫בגודל ‪ 1x4‬מטיפוס ‪ uint16‬והשני הוא מטיפוס ‪.double‬‬
‫השימוש במשתנים לדוגמא יכול להכיל רק את סוג המשתנים‪ ,‬ולא הגודל המקסימלי‬
‫שלהם‪ .‬לכן הדרך הראשונה )ע"י שימוש ב‪ (assert-‬היא מומלצת יותר‪.‬‬
‫בשלב יצירת הקוד נדון בהרחבה בפקודות ‪ emlc‬ו‪.emlmex-‬‬
‫המלצה מס' ‪4‬‬
‫השתמש ב‪ assert-‬בתוך קובץ האלגוריתם‪ .‬בצורה זו יצירת הקוד איננה תלויה בקובץ הבנייה‬
‫ובדוגמאות חיצוניות אשר עלולות להפריע להליך זה‪.‬‬
‫ניתן לקרוא על פונקציות המסייעות לה‪ ,‬כגון‪ any ,isa, all, isfi :‬ו‪.isequal -‬‬
‫‪ .4.3‬הגדרת פרמטרים בעלי גודל משתנה )‪(Variable Size‬‬
‫פרמטרים בעלי גודל משתנה הינם פרמטרים אשר גודלם יכול להשתנות במהלך ריצת הקוד‪.‬‬
‫גודל זה חייב להיות תחום בגבול עליון כלשהו‪ ,‬על מנת שבשלב יצירת הקוד ניתן יהיה‬
‫להקצות מספיק זיכרון לעבודה עימם‪.‬‬
‫השימוש בפרמטרים אלו הוא הכרח המציאות כאשר עובדים עם כניסות שגודלן יכול‬
‫להשתנות – למשל גודל תמונה או אורך אות‪ .‬שימוש אחר נפוץ הוא בפקודה ‪ – find‬אשר‬
‫מחזירה תוצאות חיפוש על מערך בהתאם לקריטריון מסויים‪.‬‬
‫קיימות מספר דרכים להגדרת פרמטרים כבעלי גודל משתנה‪:‬‬
‫שימוש ב‪eml.varsize-‬‬
‫תחת ‪ EML‬נוספה הפונקציה ‪ eml.varsize‬אשר מאפשרת להגדיר בצורה ישירה כי פרמטר‬
‫מסויים הוא בעל גודל משתנה‪ .‬למשל הפקודה‪:‬‬
‫;)]‪eml.varsize('Y', [1 8‬‬
‫עמוד ‪ 16‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫מגדירה מטריצה ‪,Y‬בעלת ‪ 2‬מימדים מטיפוס ‪ ,double‬כאשר גודל המטריצה יכול להיות‬
‫‪ ,1x:8‬כלומר "אחד על )עד שמונה("‪ .‬הגודל השני של המטריצה יכול להשתנות בכל הטווח‬
‫מ‪ 0-‬ועד ‪ .8‬יש לשים לב כי פרמטרים בעלי גודל משתנה מקבלים את הסימון "‪ ,":‬אשר‬
‫מסמל את השינוי הצפוי בגודלם‪.‬‬
‫בצורה דומה‪ ,‬הפקודה הבאה‪:‬‬
‫;)]‪eml.varsize('myMatrix',[100 20000], [0 1‬‬
‫מגדירה את המטריצה ‪ myMatrix‬שגודלה המקסימלי הוא ‪ .100x20000‬עם זאת במקרה‬
‫זה‪ ,‬תוספת ההגדרה ]‪ [0 1‬מוסיפה אילוץ שרק הגודל השני של המטריצה הוא משתנה‪,‬‬
‫כלומר גודל המטריצה יהיה ‪ .100x:20000‬כלומר "מאה על )עד ‪ 20‬אלף("‪.‬‬
‫ובכדי להגדיר ‪ struct‬כבעל גודל משתנה‪:‬‬
‫;)‪d = struct('values', zeros(1,0), 'color', 0‬‬
‫;)]‪data = repmat(d, [3 3‬‬
‫;)'‪eml.varsize('data(:).values‬‬
‫כאן מוגדר ‪ struct‬בעל השם ‪ ,data‬אשר כל שדות ה‪ values-‬שלו הם בעלי גודל משתנה‪.‬‬
‫הערה בנוגע ליצירת הקוד‪:‬‬
‫קוד בעל פרמטרים בגודל משתנה‪ ,‬מתוקף היותו כזה‪ ,‬יהיה פחות יעיל‪ .‬זאת עקב הבדיקות‬
‫הנוספות שיש לבצע על הפרמטרים‪ ,‬העברת משתנים שמייצגים את גודלו הנוכחי של‬
‫הפרמטר‪ ,‬ועוד‪ .‬מומלץ להשתמש ביכולת זו רק כאשר אין כל פתרון אחר‪.‬‬
‫הגדרת חסמים עליונים באמצעות שימוש בפרמטרים‬
‫ניתן להגדיר פרמטרים בעלי גודל משתנה גם באמצעות חסימת גודלם המקסימלי באמצעות‬
‫פרמטר נוסף‪ .‬למשל הדוגמא הבאה‪:‬‬
‫‪function y = dim_need_bound(n) %#eml‬‬
‫;)‪assert (n <= 5‬‬
‫;)‪L= ones(n,n‬‬
‫;)‪M = zeros(n,n‬‬
‫;]‪M = [L; M‬‬
‫;‪y = M‬‬
‫בדוגמא זו מוגדרים הפרמטרים ‪ L‬ו‪ M-‬שהן מטריצות בעלות גודל של ‪. :5x:5‬‬
‫במקרים רבים נראה את הסימון "?‪ ,":‬אשר מייצג את הפרמטר שגודלו בזמן ריצה למעשה‬
‫איננו חסום בגודל‪ ,‬אלא רק בטיפוסו‪ .‬הודעה זו לרוב תלווה בהודעת שגיאה‪ ,‬שכן הגדרה זו‬
‫איננה נתמכת ב‪.EML-‬‬
‫הגדרת הפרמטר ע"י שימוש בפקודה ‪ emlcoder.egs‬ובדוגמא‬
‫כפי שראינו בפרק ‪ ,4.2‬ניתן להשתמש בפרמטר לדוגמא בשימוש עם ‪ emlmex‬או ‪ .emlc‬ניתן‬
‫להשתמש בדרך זו גם בכדי להגדיר פרמטר כבעל גודל משתנה‪ ,‬באופן הבא‪:‬‬
‫})]‪emlmex myFcn -eg {emlcoder.egs(0,[2 4‬‬
‫בדוגמא זו מוגדר כי הפרמטר המסופק לפונקציה ‪ myFcn‬הינו מטריצה בעלת הגודל‬
‫המשתנה ‪ , :2x:4‬והיא מטיפוס ‪ ,double‬בהתאם לדוגמא )]‪. (0, [2 4‬‬
‫עמוד ‪ 17‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫פתרון "אוטומטי" של הגדרת הפרמטר כבעל גודל משתנה‬
‫נסתכל על הדוגמא הבאה‪:‬‬
‫‪function y = var_by_multiassign(u) %#eml‬‬
‫)‪if (u > 0‬‬
‫;)‪y = ones(3,4,5‬‬
‫‪else‬‬
‫;)‪y = zeros(3,1‬‬
‫‪end‬‬
‫בדוגמא זו מוגדר המשתנה ‪ Y‬כמטריצה בעלת הערכים )‪ .3x(nxm‬כלומר – המימד הראשון‬
‫הוא תמיד ‪ ,3‬והערכים האחרים משתנים בהתאם לתנאי ה‪ .if-‬על מנת לפתור בעיה זו‪ ,‬נוקט‬
‫הקומפיילר בגישה המתפשרת ומגדיר את ‪ Y‬כבעל המימדים ‪.3x:4x:5‬‬
‫המלצה מס' ‪5‬‬
‫במידה והקוד אמור לקבל פרמטרים בעלי גודל משתנה‪ ,‬מומלץ להגדיר אותם בצורה חד‪-‬‬
‫ערכית בקוד עצמו‪ ,‬ע"י השימוש ב‪ eml.varsize-‬וב‪ assert-‬בכדי לחסום את גודלם‪ .‬בדרך זו לא‬
‫תהיה תלות בקריאה חיצונית לפונקציה ויופחת הסיכוי לשגיאות‪.‬‬
‫ בגרסה ‪ R2010b‬נוספה היכולת לייצר באמצעות הקצאת זיכרון דינמי עבור פרמטרים‬
‫שאינם חסומים בגודלם מלמעלה‪ .‬קראו על יכולת חדשה זו ב‪ help-‬או בקישור הבא‪:‬‬
‫‪http://www.mathworks.com/help/toolbox/eml/ug/br7rggy.html#bspud0r‬‬
‫‪ .4.4‬עבודה עם פרמטרים מסוג ‪struct‬‬
‫במידה ובקוד משולבים טיפוסי פרמטרים מסוג ‪ ,struct‬יש לפעול לפי ההנחיות הבאות‪:‬‬
‫יש להגדיר ‪ struct‬בצורה מלאה לפני השימוש באיבריו השונים‬
‫לא ניתן לקרוא לאחד מאיברי ה‪ ,struct-‬ולאחר מכן להגדיר איבר אחר‪ .‬למשל‪:‬‬
‫‪function y = Struct_01(x) %#eml‬‬
‫;‪y.f = x‬‬
‫;‪a = y.f * y.f‬‬
‫;‪y.h = exp(a) + y.f‬‬
‫פעולה זו תחזיר שגיאה‪.‬‬
‫על מנת להימנע מבעיה זו‪ ,‬יש לאתחל את כל איברי המ‪ struct-‬לפני השימוש בהם‪ .‬בדוגמא‬
‫לעיל‪ ,‬ניתן להוסיף את השורה‬
‫;‪y.h = 0‬‬
‫לפני ביצוע הפעולה על ‪ .a‬כעת הפעולה כן תיתמך‪.‬‬
‫יש להגדיר בצורה מפורשת את שדות ה‪ struct-‬כמשתנים‬
‫בתחילת הפרק דובר על השימוש בפקודה ‪ assert‬בכדי להגדיר גדלי משתנים וטיפוסים‪.‬‬
‫בעבודה עם ‪ ,struct‬יש לבצע זאת עבור כל אחד מהשדות השונים‪ ,‬בצורה מפורשת‪ .‬כלומר‪,‬‬
‫במידה וישנו ‪ struct‬בעל ‪ 2‬שדות‪ - Values, Length :‬יש להגדיר את שניהם‪.‬‬
‫עמוד ‪ 18‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫עם זאת‪ ,‬במידה ונעזרים בפרמטר לדוגמא )ע"י שימוש ב‪ ,("-eg"-‬אזי ה‪ struct-‬המקורי‬
‫מגדיר את כל השדות‪ ,‬ואין צורך לעשות זאת שוב‪.‬‬
‫שליטה על שם ה‪ struct-‬בקוד ה‪C-‬‬
‫בתהליך המרת הקוד‪ ,‬שמות ה‪ struct-‬הם אקראיים‪ .‬במידה וברצונך לשלוט על שמות אלו‪,‬‬
‫יש להשתמש בפקודה ‪ eml.cstructname‬באופן הבא‪:‬‬
‫‪%#eml‬‬
‫)‪function y = topfun(x‬‬
‫;)'‪eml.cstructname(x, 'MyStruct‬‬
‫;‪y = x‬‬
‫במידה וכבר קיים ‪ struct‬ב‪ ,C-‬ואנו רוצים להשתמש בהגדרה הקיימת עבורו‪ ,‬אזי נעשה‬
‫שימוש בדגלון '‪ 'extern‬בפקודה זו‪ ,‬לפי הדוגמא הבאה‪:‬‬
‫;)'‪eml.cstructname(structVar, 'MyStruct', 'extern‬‬
‫יש לשים לב כי במקרה זה‪ ,‬נדרש כי ‪ MyStruct‬יהיה מוגדר בקוד ‪ C‬שנכתב או הוגדר‬
‫במיקום אחר בקוד‪ .‬ניתן כמובן להשתמש ב"קבצים החיצוניים" בשימוש בפקודה ‪,emlc‬‬
‫עליה ידובר בשלב יצירת הקוד‪.‬‬
‫‪ .4.5‬עבודה עם מטריצות "ריקות"‬
‫במקרים רבים נהוג לאתחל פרמטרים כבעלי ערך "ריק" )או "]["(‪ ,‬ואז להגדיל את‬
‫הפרמטר בתוך לולאות‪ .‬בעבודה עם ‪ EML‬יש להתייחס למטריצות ריקות בצורה שונה‬
‫מהרגיל‪ ,‬שכן היינו רוצים להגדיר אותן כבעלות גודל משתנה‪ .‬במקרה זה‪ ,‬במקום ההגדרה‬
‫הבאה‪:‬‬
‫‪function y = NullMatrix(x) %#eml‬‬
‫;][ = ‪y‬‬
‫)‪while (x > 0‬‬
‫;‪x = sqrt(x) – 1‬‬
‫;]‪y = [y x‬‬
‫‪end‬‬
‫יש כמובן להגדיר את ‪ y‬כפרמטר בעל גודל משתנה‪ .‬אך במקרה זה יש להגדירו באופן הבא‪:‬‬
‫;)‪y = zeros(1, 0‬‬
‫;]‪eml.varsize('y', [1 10‬‬
‫זאת‪ ,‬כיוון שבכדי שפרמטר יוגדר כבעל גודל משתנה‪ ,‬אחד מהגדלים שלו חייב להיות שונה‬
‫מאפס‪ .‬בהגדרה "] [ "– גודל המשתנה הוא ‪ ,0x0‬ולכן לא יהיה בעל גודל משתנה‪ .‬ברגע‬
‫שנוסיף את השימוש ב‪ – zeros(1, 0)-‬הבעיה תיפתר‪.‬‬
‫‪ .4.6‬הגדרת משתנים בצורה מותנית‬
‫השימוש ב‪ EML-‬אינו מאפשר להגדיר משתנים בצורה התלויה בתנאי כלשהו‪ .‬לדוגמא‪:‬‬
‫‪function y = NullMatrix_02(x) %#eml‬‬
‫)‪if (x > 0‬‬
‫;‪y = 1‬‬
‫‪end‬‬
‫)‪if (x < 0‬‬
‫עמוד ‪ 19‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫;‪y = 2‬‬
‫‪end‬‬
‫בפונקציה זו יתכן מצב שבו אף אחד מהתנאים לא יתקיים‪ ,‬ולכן המשתנה ‪ y‬לעולם לא‬
‫יוגדר‪ EML .‬מחייב שכל הפרמטרים יאותחלו ויוגדרו‪ ,‬ועל כן יש להוסיף אתחול למשתנה‬
‫‪ ,y‬למשל הוספת ‪ y=0‬בתחילת הפונקציה‪.‬‬
‫‪ .4.7‬הקצאת זיכרון מינימלית באמצעות ‪eml.nullcopy‬‬
‫במקרים רבים נהוג לאתחל פרמטרים ע"י השימוש בפקודה ‪ ,zeros‬ולאחר מכן לשנות את‬
‫ערכם‪ .‬מצב זה יכול להוביל להעתקות זיכרון רבות אשר עשויות להיות מיותרות ולארוך‬
‫זמן רב‪.‬‬
‫בעזרת השימוש בפונקציה ‪ ,eml.nullcopy‬ניתן להגדיר את כמות הזיכרון הנדרשת‪ ,‬אך לא‬
‫לאתחל אותה בערך ראשוני‪ .‬להלן דוגמא‪:‬‬
‫‪%#eml‬‬
‫‪function X = foo‬‬
‫;‪N = 5‬‬
‫;))‪X = eml.nullcopy(zeros(1,N‬‬
‫‪for i = 1:N‬‬
‫‪if mod(i,2) == 0‬‬
‫;‪X(i) = i‬‬
‫‪else‬‬
‫;‪X(i) = 0‬‬
‫‪end‬‬
‫‪end‬‬
‫בדוגמא זו‪ ,‬המשתנה ‪ X‬מאותחל לגודל ראשוני של ]‪ ,[1 5‬מטיפוס ‪ double‬אך ערכיו ניתנים‬
‫לו רק בתוך לולאת ה‪.for-‬‬
‫יש לשים לב כי בהקצאת זיכרון‪ ,‬הערך המצוי בתא זה הוא אקראי‪ ,‬ויש לוודא כי לא נעשה‬
‫שימוש בערכים אלו לפני אתחולם‪ .‬פעולה זו עשויה להוביל לתוצאות בלתי צפויות ובלתי‬
‫רצויות‪.‬‬
‫‪ .4.8‬אינדקסים של וקטורים בעלי גודל משתנה‬
‫בשימוש באינדקסים ב‪ ,EML-‬יש לחסום את גודל הווקטור כך שיהיה סופי‪ .‬לשם כך‪ ,‬לא‬
‫ניתן להשתמש בהגדרה הבאה‪:‬‬
‫;)‪myMatrix(n:n+L-1‬‬
‫מאחר והגדלים ‪ n‬ו‪ L-‬הם בעלי גודל משתנה‪ ,‬האינדקסים של המטריצה אינם חסומים‬
‫בצורה מפורשת‪ .‬על כן‪ ,‬יש להשתמש בהגדרה הבאה‪:‬‬
‫;))‪myMatrix(n+(0:L-1‬‬
‫אשר הינה זהה לחלוטין בתפקודה‪ ,‬וכך גם האינדקסים חסומים בגודלם‪.‬‬
‫המלצה מס' ‪6‬‬
‫בדקו את הפונקציות הבאות וכיצד הן יכולות לסייע בייעול הקוד‪:‬‬
‫* ‪eml.unroll‬‬
‫* ‪eml.inline‬‬
‫עמוד ‪ 20‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .4.9‬תמיכה במשתנים גלובליים ‪global -‬‬
‫החל מגרסה ‪ ,R2010a‬נוספה התמיכה במשתנים גלובליים‪ ,‬כלומר משתנים המזוהים בכל‬
‫קבצי ה‪ m-‬עימם עובדים‪ .‬הגדרת משתנה שכזה מבוצעת באמצעות הפקודה ‪:global‬‬
‫)‪function y = use_globals(u‬‬
‫‪%#eml‬‬
‫‪% Turn off inlining to make‬‬
‫‪% generated code easier to read‬‬
‫;)'‪eml.inline('never‬‬
‫‪% Declare AR and B as global variables‬‬
‫;‪global AR‬‬
‫;‪global B‬‬
‫;)‪AR(1) = u + B(1‬‬
‫;‪y = AR * 2‬‬
‫;))‪yMatrix(n+(0:+L-1‬‬
‫כשננסה לייצר קוד או ‪ MEX‬מפונקציה זו‪ ,‬הקומפיילר יזהה כי קיימים כאן פרמטרים‬
‫גלובליים‪ ,‬ויגדיר אותם בהתאם‪ .‬אם נרצה להגדיר אותם באמצעות הדגלון ‪ ,-eg‬נעשה זאת‬
‫כך‪:‬‬
‫… ‪>> emlmex -o myGlobalMEXFunction‬‬
‫‪-global {'AR',ones(4),'B',[1 2 3]} my_Global_UsingFunction‬‬
‫‪ .4.10‬שימוש ב‪streaming-‬‬
‫ברוב מערכות זמן‪-‬האמת‪ ,‬האלגוריתם נועד לבצע פעולה מסויימת על גודל מסויים של‬
‫מידע‪ .‬עם זאת‪ ,‬המידע מגיע בתצורה של חבילות )או חלקי מידע(‪ ,‬ולכן יש לאגור את המידע‬
‫החלקי בכדי לבנות ממנו מידע בגודל הנדרש‪.‬‬
‫לדוגמא‪ ,‬עבור אלגוריתם שמבצע זיהוי שפות בתמונה‪ ,‬יש לוודא כי התמונה מגיעה במלואה‬
‫לאלגוריתם‪ ,‬ורק לאחר מכן הוא מופעל‪ .‬לשם כך יש לאסוף את המידע שמגיע בחבילות של‬
‫‪ 32‬ביט‪ ,‬לשחזר את התמונה ממצב של שורה‪-‬שורה לרמה של תמונה בגודל אמיתי‪.‬‬
‫לשם כך‪ ,‬יש להשתמש בחוצץ )או ‪ ,(buffer‬אשר מסוגל לשמור מידע לאורך זמן ריצת הקוד‪,‬‬
‫גם כאשר הפונקציה איננה פעילה‪ .‬ב‪ ,MATLAB-‬על מנת להגדיר משתנה בצורה כזו‪,‬‬
‫משתמשים בהגדרת ‪ .persistent‬צורת פתרון זו קיימת גם ב‪ ,EML-‬ואיננה מצריכה שינוי‬
‫מסויים‪.‬‬
‫להלן מקטע קוד לדוגמא להגדרת חוצצים בעלי השם ‪ fifo‬ו‪:weights-‬‬
‫‪%#eml‬‬
‫)‪function [signal_out] = myFunction(signal_in, desired‬‬
‫הגדרת הפרמטרים‬
‫אתחול ראשוני‬
‫}‬
‫}‬
‫;‪persistent weights‬‬
‫;‪persistent fifo‬‬
‫‪% Filter length:‬‬
‫;)‪L = uint32(32‬‬
‫‪% Adaptation step size:‬‬
‫;)‪mu = 4/(32*1024‬‬
‫‪% Signal length:‬‬
‫;)‪N = length(signal_in‬‬
‫‪if length(desired) == N‬‬
‫)‪if isempty(weights‬‬
‫‪% Filter coefficients:‬‬
‫;)‪weights = zeros(L,1‬‬
‫‪% FIFO Shift Register:‬‬
‫;)‪fifo = zeros(L,1‬‬
‫עמוד ‪ 21‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪end‬‬
‫‪% Pre-allocate output and error signals:‬‬
‫;)‪signal_out = zeros(N,1‬‬
‫;)‪err = zeros(N,1‬‬
‫‪% Filter Update Loop:‬‬
‫‪for n = 1:N‬‬
‫עדכון בזמן ריצה‬
‫;)‪fifo(1:L-1) = fifo(2:L‬‬
‫;)‪fifo(L) = distorted(n‬‬
‫;‪signal_out(n) = weights' * fifo‬‬
‫; )‪err(n) = desired(n) - signal_out(n‬‬
‫;‪weights = weights + mu*err(n)*fifo‬‬
‫‪end‬‬
‫}‬
‫‪else‬‬
‫;)'‪error('Lengths of input signals are not equal‬‬
‫‪end‬‬
‫‪end‬‬
‫מקטע קוד זה נתמך ליצירת קוד ו‪ ,EML-‬במגבלה הבאה‪:‬‬
‫פרמטר שמוחזר מהפונקציה לא יכול להיות משתנה מסוג ‪ .persistent‬כלומר – הפרמטר‬
‫‪ fifo‬או ‪ weights‬לא יכול להיות מוצא מפורש של הפונקציה‪ .‬במידה ונדרש לעשות זאת‪ ,‬יש‬
‫להגדיר פרמטר חדש שיכיל ערכים אלו‪ .‬למשל‪ ,‬הגדרת השורה הבאה‪:‬‬
‫;‪weights_out = weights‬‬
‫⇐ יש לשים לב‪ ,‬כי במידה ונדרש לבצע ‪ Streaming‬לאלגוריתמים העוסקים בעיבוד אותות‪,‬‬
‫עיבוד תמונה או מערכות תקשורת‪ ,‬אזי החל מגרסה ‪ R2010a‬קיימות פונקציות אלו‬
‫לשימוש המתכנן בצורה חופשית‪ ,‬בכלים המוספים – ‪Video and Image Processing‬‬
‫‪ Signal Processing Blockset ,Blockset‬ו‪.Communications Blockset-‬‬
‫המלצה מס' ‪7‬‬
‫לאחר ביצוע השינויים‪ ,‬ניתן להשוות בין קובץ המקור לקובץ עם השינויים מבחינת ה"טקסט"‪,‬‬
‫ע"י שימוש ב‪ . Tools > Compare Against > Browse -‬בחלון ה‪ editor-‬ייפתחו ‪ 2‬הקבצים‬
‫וניתן יהיה להשוות ביניהם בצורה פשוטה‪.‬‬
‫‪ .4.11‬בדיקה פונקציונלית‬
‫בפרק זה נעשו לא מעט שינויים בקובץ המקור‪ ,‬וייתכן והוזרקו מספר שגיאות לאלגוריתם‪.‬‬
‫על מנת לוודא שהקובץ החדש מבצע בדיוק את אותה הפעולה כמו הקובץ המקורי‪ ,‬יש‬
‫להשוות בין פעולתם‪.‬‬
‫בדיקה זו ניתן לבצע בפשטות ע"י כתיבת ‪ test-script‬אשר יקח כניסות מסוג מסויים‬
‫וישתמש בהן בכדי לקרוא לפונקציה המקורית ולפונקציה הנתמכת ב‪ .EML-‬באמצעות‬
‫‪ MATLAB‬ככלי וריפיקציה נוכל לאגור את התוצאות מכל פונקציה‪ ,‬ולהראות את‬
‫הסטיות בצורה ויזואלית – במידה וישנן כאלו‪.‬‬
‫מאחר והאלגוריתם החדש הוא זה שיועבר ליצירת קוד‪ ,‬בדיקה זו הינה חשובה יותר‪,‬‬
‫ואיננה בגדר "המלצה"‪.‬‬
‫יש לוודא כי הסטיות ‪ -‬במידה ונתגלו ‪ -‬הן מזעריות‪ ,‬או כאלו שהן צפויות בשינוי בין‬
‫המימושים – למשל שגיאות קוונטיזציה במעבר מ‪ double-‬ל‪.uint8-‬‬
‫עמוד ‪ 22‬מתוך ‪33‬‬
MATLAB ‫ מתוך‬C ‫קווים מנחים ליצירת קוד‬
‫ מקטעי הקוד )הקוד המקורי‬2-‫ המראה כיצד ניתן לקרוא ל‬test-script-‫להלן דוגמא ל‬
:(EML-‫והקוד הנתמך ל‬
%% Test Bench for LMS Filter Example
% Version #2 -- EML Compliant vs. Baseline MATLAB Code
%% Setting up:
% Initialize:
close all; clear all; clc;
%% Creating Signals:
% Load desired audio signal:
data = load('handel.mat');
desired = data.y;
Fs = data.Fs;
% Length of desired signal:
N = length(desired);
% Maximum signal length:
MaxLength = 128*1024;
% samples
% Filter length:
L = 32;
% Band-limited AWGN:
load emldemo_lms_filter.mat;
lambda = 1.0;
whiteNoise = lambda*randn(N,1);
noise = filter(b,1,whiteNoise);
% Distorted signal:
distorted = desired + noise;
%% Apply Algorithm:
% Golden reference:
[gold.signal gold.error gold.impulse] =
emldemo_lms_01(whiteNoise,distorted,L);
% Algorithm under test:
[test.signal test.error test.impulse] =
emldemo_lms_02_mex(whiteNoise,distorted);
%% Find differences:
diff.signal
=
test.signal
- gold.signal;
diff.error
=
test.error
- gold.error;
diff.impulse =
test.impulse - gold.impulse;
%% Plot differences:
figure;
subplot(3,1,1);
plot(diff.signal);
title({'Algorithm Under Test versus Golden Reference' 'Output
Signal'});
subplot(3,1,2);
plot(diff.error);
title('Error Signal');
subplot(3,1,3);
stem(diff.impulse);
title('Impulse Response');
8 '‫המלצה מס‬
:‫ למשל‬.‫ מומלץ לתת שמות התואמים לפעולת הקוד‬script ‫ או קבצי‬m ‫בשמירת קבצי‬
.02 ‫ גרסה‬,‫ – האלגוריתם הנדון‬myAlgorithm_02
.01 ‫ גרסה‬,myAlgorithm ‫ – קובץ המסייע לבניית קוד עבור‬myAlgorithm_build_01
.03 ‫ גרסה‬,‫ – קובץ המסייע לבדיקת האלגוריתם‬myAlgorithm_Test_03
33 ‫ מתוך‬23 ‫עמוד‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .5‬יצירת פונקציית ‪ MEX‬לצורך בדיקה פונקציונלית של הקוד‬
‫כפי שנכתב קודם‪ ,‬בטרם נייצר קוד ‪ C‬בצורה סופית‪ ,‬ונטמיע אותו ברכיב החומרה שבחרנו‪ ,‬נרצה‬
‫ראשית לוודא כי הקוד שנוצר מבצע את אותן הפעולות כמו ה‪.Golden Reference-‬‬
‫הדרך לעשות זאת היא ע"י יצירת פונקציית ‪.MEX‬‬
‫פונקציות ‪) MEX‬או ‪ (MATLAB Executable‬הן פונקציות שניתן להריץ אותן בסביבת‬
‫‪ ,MATLAB‬אך הן למעשה קוד ‪ C‬שעבר תהליך של קומפילציה – כלומר הרצה של קוד ‪ C‬בתוך‬
‫‪.MATLAB‬‬
‫את פונקציית ה‪ MEX-‬ניתן לשלב באותה סביבת בדיקות שבה נבדק האלגוריתם המקורי‪ .‬את‬
‫אותן הפעולות שבוצעו על קוד ה‪ MATLAB-‬ניתן לבצע גם על פונקציה זו‪ ,‬ולהשוות בצורה‬
‫מלאה ביניהן‪ .‬כל שינוי בתוצאות המתקבלות מפונקציית ה‪ MEX-‬מעיד על חוסר דיוק שהוכנס‬
‫בהליך ההמרה ל‪ .EML-‬המטרה היא לוודא שחוסר הדיוק הוא מספיק קטן בכדי שיהיה "זניח"‪.‬‬
‫יש להבין כי חוסר דיוק זה נובע מהמעבר מעבודה בסביבת מחשוב של ‪ 64‬ביט )עם ‪Double‬‬
‫‪ (Precision‬לסביבת עבודה הנמצאת לרוב ב‪ 32-‬ביט )‪ .(Single Precision‬לכן – שגיאות‬
‫קוונטיזציה צפויות להתקבל‪.‬‬
‫בשלב זה יש גם להחליט האם על המעבד הסופי שעבורו נייצר קוד הוא מסוג ‪ Float‬או ‪.Fixed‬‬
‫במידה והוא מסוג ‪ – Float‬נוכל להמשיך לשלב הבא‪ .‬אחרת‪ ,‬עלינו לעבור שלב נוסף של המרת‬
‫האלגוריתם לעבודה ב‪ .Fixed-‬הליך זה יכול להיות קצר ביותר ע"י שימוש ב‪Fixed Point -‬‬
‫‪ ,Toolbox‬ולאחר סיומו מצריך בדיקה נוספת של פונקציית ‪ MEX‬למול ה‪,Golden Reference-‬‬
‫בכדי לוודא שחוסר הדיוק הנובע מקוונטיזציה לא פגע באופן הפעולה של האלגוריתם‪.‬‬
‫עמוד ‪ 24‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .5.1‬יצירת פונקציית ‪MEX‬‬
‫על מנת לייצר פונקציית ‪ ,MEX‬יש לוודא כי על עמדת המשתמש מותקן ה‪ Simulink-‬או ה‪-‬‬
‫‪.Fixed Point Toolbox‬‬
‫הפקודה שמייצרת ‪ mex‬מתוך ‪ EML‬היא ‪ ,emlmex‬ושימוש לדוגמא‪:‬‬
‫‪>> emlmex -report -eg { myExamplePARAMS } myEMLFunction‬‬
‫דוגמא זו מייצרת קוד ‪ C‬מתוך הפונקציה ‪ ,myEMLFunction‬ו"עוטפת" אותו במעטפת‬
‫מתאימה לצורך הרצתו בתוך סביבת ‪.MATLAB‬‬
‫במידה וקיימת בעיה כלשהי – פונקציה שאיננה נתמכת למשל – תוצאת הריצה תהיה דו"ח‬
‫שמציג מהי מהות השגיאה והצעה לפתרונה‪.‬‬
‫ יש לשים לב‪ ,‬כי על מנת לייצר ‪ ,MEX‬יש להגדיר קומפיילר נתמך באמצעות הפקודה‪:‬‬
‫‪>> mex -setup‬‬
‫ובחירה של קומפיילר מתאים‪ .‬למערכות ‪ 32‬ביט‪ ,‬מסופק יחד עם ‪ MATLAB‬קומפיילר‬
‫שכזה‪ .LCC ,‬למערכות ‪ 64‬ביט‪ ,‬יש להתקין קומפיילר מתוך רשימה של קומפיילרים‬
‫נתמכים‪ .‬רשימה זו ניתן למצוא ב‪-‬‬
‫‪. http://www.mathworks.com/support/compilers/R2010b/index.html‬‬
‫לאחר סיום יצירת פונקציית ה‪ ,MEX-‬נוצר קובץ חדש‪ ,‬בעל השם ‪ ,myEMLFunction‬ובעל‬
‫הסיומת ‪) .mexw32‬למערכת הפעלה חלונות‪ 32 ,‬ביט(‪ .‬סיומת זו תשתנה ממערכת הפעלה‬
‫אחת לשניה‪) .‬עבור מערכת הפעלה ‪ 64 Linux‬ביט‪ ,‬תתקבל הסיומת ‪.(mexa64‬‬
‫המלצה מס' ‪9‬‬
‫ניתן לייבא לתוך סביבת ‪ MATLAB‬הן קבצי ‪ C‬והן קבצי ‪ Fortran‬שנכתבו בעבר‪ .‬לקריאה‬
‫נוספת על יכולת זו‪ ,‬אשר עשויה לחסוך זמן רב בתהליך הפיתוח‪ ,‬ניתן לקרוא ב‪:‬‬
‫‪>> doc mex‬‬
‫הסיומת ‪ ,MEX‬הינה בעלת קדימות גבוהה יותר מבחינת ‪ .MATLAB‬לכן‪ ,‬אם קיימים ‪2‬‬
‫קבצים‪ ,‬אחד בעל הסיומת ‪ ,.m‬והשני בעל הסיומת ‪ ,.mexw32‬הקובץ השני ייקרא לפני‬
‫הראשון‪ .‬לכן‪ ,‬כשמייצרים את פונקציית ה‪ ,MEX-‬מומלץ לתת לה שם ייחודי בעזרת הדגלון‬
‫‪ , -o‬למשל‪:‬‬
‫‪emlmex -eg { myExamplePARAMS } myFunction –o myMEXFunction‬‬
‫כעת הקובץ החדש יהיה בעל השם הייחודי ‪ , myMEXFunction.mexw32‬ולא ייקרא‬
‫במקום הקוד המקורי‪.‬‬
‫בפרק ‪ 6‬מוצגת היכולת לייצור קוד ‪ C‬מתוך ‪ ,EML‬ע"י השימוש בפקודה ‪ .emlc‬באמצעות‬
‫פקודה זו ניתן לייצר גם קוד ‪ ,MEX‬באופן הבא‪:‬‬
‫‪emlc -eg { myExamplePARAMS } myFunction –o myMEXFunction‬‬
‫או ע"י‪:‬‬
‫‪emlc –T MEX -eg { myExamplePARAMS } myFunction –o myMEXFunction‬‬
‫עמוד ‪ 25‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫תוצאת פקודה זו הינה גם כן קובץ ‪ ,.mexw32‬אך כזה שנוצר ע"י שימוש ב‪ .RTW-‬מאחר וקוד זה‬
‫יעיל יותר‪ ,‬ייתכנו שינויים בזמני ריצה ו‪/‬או ביצועים אחרים בהשוואה בין ‪ 2‬תוצרים אלו‪.‬‬
‫‪ .5.2‬בדיקה למול קוד המקור‬
‫בפרק ‪ 4.11‬בוצעה בדיקה של קוד ה‪ EML-‬למול קוד ה‪ .MATLAB-‬ניתן להשתמש באותה‬
‫סביבת הבדיקות על מנת לבדוק כי גם פונקציית ה‪ MEX-‬מחזירה בדיוק את אותן‬
‫התוצאות כמו ה‪ .EML-‬בבדיקה זו‪ ,‬אנו בודקים את קוד ה‪ C-‬בצורה פונקציונלית‪ ,‬כי הוא‬
‫מבצע בדיוק את מה שציפינו ממנו‪.‬‬
‫כאשר מיוצר קוד מתוך ה‪ ,EML-‬מבוצעות מספר פעולות של אופטימיזציה ושל התאמת‬
‫הקוד לפעולה יעילה יותר‪ .‬לכן‪ ,‬עלולה להתקבל התנהגות השונה מזו שציפינו‪ .‬התנהגות זו‪,‬‬
‫במידה ותתקבל‪ ,‬תתרחש בסבירות גבוהה במקרי קצה של גדלי הנתונים השונים‪.‬‬
‫‪ .5.3‬בדיקת זמני ריצה של קוד ה‪ MEX-‬והשוואה למקור‬
‫אנשים רבים ברחבי העולם טוענים כי קוד ‪ C‬רץ בצורה מהירה יותר מאשר ‪.MATLAB‬‬
‫עקב כך‪ ,‬הציפייה היא שקוד ‪ MEX‬ירוץ מהר יותר מאשר קוד המקור‪ ,‬ולכן מושקע מעמץ‬
‫בהאצת פעולת ‪ MATLAB‬ע"י המרת חלקים מהקוד ל‪.MEX-‬‬
‫ככלל – הנחה זו אינה מתקיימת תמיד – ממספר סיבות‪:‬‬
‫‪ MATLAB‬הינה שפה אשר עובדת כ‪ - Interpreter-‬כלומר לוקחת את הקוד שנכתב‪,‬‬
‫ומריצה אותו שלב אחר שלב ‪ -‬תוך קריאה לפונקציות המתאימות‪ .‬בשנים האחרונות‪,‬‬
‫השקיעה חברת ‪ MathWorks‬משאבים רבים במטרה להאיץ את ‪ .MATLAB‬זאת – ע"י‬
‫מימוש מחדש של חלק גדול מאד מהפונקציות הבסיסיות והמתקדמות‪ ,‬שימוש בספריות‬
‫‪ – (Basic Linear Algebra Subroutines) BLAS‬מימוש מהיר יותר של פעולות מתמטיות‪,‬‬
‫וכן שימוש נרחב יותר ויותר בפעולות ‪ – MultiThreaded‬כלומר מימוש מקבילי של‬
‫הפונקציות‪.‬‬
‫בעקבות עבודה נרחבת זו‪ ,‬ניתן כיום לראות שיפורים משמעותיים בעבודה בגרסה חדשה‬
‫של ‪ MATLAB‬לעומת גרסאות ותיקות יותר‪ .‬באחד המקרים בתעשיה‪ ,‬נתגלה שיפור של‬
‫כ‪ 65%-‬בזמן הרצת הקוד‪ ,‬מתוקף המעבר מגרסה ‪ R2006b‬לגרסה ‪.R2009b‬‬
‫המסקנה היא שגם אם נשלב פונקציות ‪ C‬לתוך ‪ ,MATLAB‬ונריץ את כולן יחדיו – כנראה‬
‫שעדיין ‪ MATLAB‬תוכל לרוץ מהר יותר‪.‬‬
‫חשוב לציין כאן כי כל השוואה בין זמני הריצה של קוד ה‪ MATLAB-‬לקוד הממומש כ‪-‬‬
‫‪ MEX‬היא גם חסרת תועלת – במידה וייוצר קוד ‪ ,C‬הרי הוא יופעל על גבי מערכת הפעלה‬
‫אחרת‪ ,‬ישולב עם קוד נוסף‪ ,‬או יועבר למעבד השונה מהמעבד עליו מותקנת ‪ .MATLAB‬על‬
‫כן‪ ,‬כל עוד לא נבחן את הקוד על מקומו הסופי – לא נדע בדיוק את מהירות הריצה שלו‪.‬‬
‫ואף על פי כן – אם נבדוק את השינויים בזמני הרצת הקוד – למשל‪ ,‬אם נשפר את קוד ה‪-‬‬
‫‪ EML‬וקוד ה‪ MEX-‬יואץ פי ‪ – 2‬אזי כנראה שגם על מעבד המטרה הקוד יעבוד מהר יותר‪.‬‬
‫עמוד ‪ 26‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .6‬יצירת קוד‬
‫מבחינה היסטורית‪ ,‬טכנולוגיית יצירת הקוד של ‪ MathWorks‬פותחה על מנת להאיץ סימולציות‬
‫של מאות ואלפי בלוקים בתוך ‪ .Simulink‬לכן‪ ,‬בכדי לייצר קוד מתוך ‪ ,MATLAB‬נדרש רישיון‬
‫זמין ל‪ Simulink-‬ול‪.RTW-‬‬
‫בפרק זה נדגים כיצד ניתן לייצר קוד מתוך ‪ MATLAB‬עבור ‪.EML‬‬
‫יש לציין כי ניתן לשלב קוד ‪ EML‬בתוך בלוקים של ‪Embedded MATLAB Function Blocks‬‬
‫כחלק מ‪ .Simulink-‬טכנולוגיית יצירת הקוד מתוך ‪ Simulink‬קיימת זמן רב יותר‪ ,‬ולכן קיימות‬
‫אפשרויות רבות יותר דרך הממשק הגרפי של ‪ .Simulink‬בסביבת ‪ Simulink‬ניתן‪ ,‬למשל‪ ,‬להגדיר‬
‫את חלוקת מרחבי הזיכרון למעבד המטרה‪.‬‬
‫עם זאת‪ ,‬גרסה ‪ R2010b‬של ‪ MATLAB‬מהווה קפיצת מדרגה בטכנולוגיה זו‪ ,‬וכמעט כל‬
‫האפשרויות זמינות גם ליצירת קוד מתוך ‪ MATLAB‬בגרסה זו‪.‬‬
‫הפקודה שמייצרת קוד מתוך ‪ EML‬היא ‪ ,emlc‬ושימוש לדוגמא‪:‬‬
‫‪emlc -report -eg { myExamplePARAMS } myEMLFunction –s rtwcfg‬‬
‫דוגמא זו מייצרת קוד ‪ C‬מתוך הפונקציה ‪ ,myEMLFunction‬מייצרת דו"ח ‪ HTML‬של הקוד‪.‬‬
‫במקרה זה ניתן לראות גם את הגדרות יצירת הקוד‪ ,‬ע"י השימוש בדגלון ‪ –s‬כשלאחריו מופיע‬
‫אובייקט הגדרות הקוד‪.‬‬
‫במידה וקיימת בעיה כלשהי – פונקציה שאיננה נתמכת למשל – תוצאת הריצה תהיה דו"ח שמציג‬
‫מהי מהות השגיאה והצעה לפתרונה‪.‬‬
‫ בטרם הגעה לשלב זה‪ ,‬יש לוודא כי קוד ה‪ MATLAB-‬מותאם ל‪ ,EML-‬וכן בוצעו כל‬
‫ההגדרות של הפרקים הקודמים‪.‬‬
‫ הגדרת טיפוסי המשתנים‪ ,‬גודלם ושאר הפרמטרים ‪ -‬מבוצע באותו האופן כמו עבור הפקודה‬
‫‪ emlmex‬כפי שהוצג בפרק הקודם‪.‬‬
‫כמו עבור יצירת ‪ MEX‬יש לשים לב כי על מנת לייצר קוד‪ ,‬יש להגדיר קומפיילר נתמך באמצעות‬
‫הפקודה‪:‬‬
‫‪>> mex –setup‬‬
‫‪ .6.1‬תוצרים שונים מהפקודה ‪emlc‬‬
‫כשאנחנו בוחרים לייצר קוד בצורה אוטומטית‪ ,‬אנחנו נדרשים לבחור גם את אופן יצירת‬
‫הקוד‪ ,‬כלומר באיזה פורמט היינו מעוניינים לקבל אותו‪ ,‬בהתאם לצורכינו‪ emlc .‬מאפשרת‬
‫לנו לייצר קוד במספר סוגים‪:‬‬
‫א‪ .‬ייצור קוד ‪ – MEX‬תוצר הזהה לשימוש בפקודה ‪ ,emlmex‬רק שכעת הקוד יעיל יותר‪,‬‬
‫וניתן לראות גם את קוד המקור שלו‪ .‬זוהי ברירת המחדל‪.‬‬
‫עמוד ‪ 27‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫ב‪ .‬יצירת ספריה – ‪ – lib‬הקוד הנוצר נעטף בספריה מתאימה‪.‬‬
‫ג‪ .‬יצירת קובץ עצמאי – ‪ – EXE‬הקוד נוצר‪ ,‬מקומפל ומקושר בכדי לייצר קובץ עצמאי‪.‬‬
‫בכדי לבחור את התוצר המתאים‪ ,‬יש להשתמש בדגלון ‪ –T‬באופן הבא‪:‬‬
‫‪%Generate mex-function‬‬
‫)‪% Generate library‬‬
‫)‪% Generate Standalone exe‬‬
‫‪>> emlc –T mex myEMLFunction‬‬
‫‪>> emlc –T rtw:lib myEMLFunction‬‬
‫‪>> emlc –T rtw:exe myEMLFunction‬‬
‫‪ .6.2‬התאמה אישית של הקוד הנוצר )דגלון ‪(–s‬‬
‫הקוד נוצר בצורה אוטומטית‪ ,‬ועל כן יש להגדיר כיצד היינו רוצים שהקוד ייראה בסוף‬
‫התהליך‪ .‬בחירת שפת הקוד‪ ,‬שמות המשתנים‪ ,‬הוספת הערות‪ ,‬שליטה על אופטימיזציה‪,‬‬
‫אופן אתחול והעתקת וקטורים וכדומה – כולם פרמטרים שניתן לשלוט עליהם‪.‬‬
‫אופן ההתאמה ב‪ MATLAB-‬נעשה ע"י שימוש ב‪ 3-‬אובייקטים מתאימים‪ ,‬אשר מאפשרים‬
‫לשלוט על‪:‬‬
‫א‪ .‬אופן יצירת קוד ה‪ .MEX-‬בעזרת האובייקט ‪. emlcoder.MEXConfig‬‬
‫ב‪ .‬הגדרות ה‪ .RTW-‬בעזרת האובייקט ‪. emlcoder.RTWConfig‬‬
‫ג‪ .‬הגדרות חומרה עבור מעבד המטרה‪ .‬זאת נבצע ע"י הגדרת האובייקט‬
‫‪. emlcoder.HardwareImplementation‬‬
‫אובייקטים אלו נוצרים בתוך ה‪ Workspace-‬של ‪ ,MATLAB‬וניתן כמובן לשמור אותם‬
‫לקובץ ‪ ,.mat‬ולדאוג להעברתם מ‪ session-‬ל‪ session-‬וממשתמש למשתמש‪ ,‬מבלי לדאוג‬
‫לייצר אותם בכל פעם מחדש‪.‬‬
‫‪ 6.2.1‬שימוש ב‪emlcoder.MEXConfig-‬‬
‫הגדרת האובייקט‪>> mxcfg = emlcoder.MEXConfig :‬‬
‫עריכת האובייקט‪>> open mxcfg :‬‬
‫מתקבל המסך הבא‪ ,‬בו אפשר להגדיר מספר רב של נתונים ואפשרויות‪.‬‬
‫תחת ‪ ,General‬נקבע האם ברצוננו לאפשר שימוש בוקטורים בעלי גודל משתנה‪ ,‬לאפשר‬
‫שימוש ב‪ ,BLAS-‬ולבחור האם למקם כל פונקציית ‪ MATLAB‬שנוצרת לקובץ ‪ C‬נפרד‪,‬‬
‫או האם לשלב את כל הקבצים לקובץ בודד‪ .‬כאן גם נבחר האם ברצוננו לייצר קוד ‪ C‬או‬
‫‪.C++‬‬
‫תחת ‪ Optimization‬ו‪ Advanced-‬מופיעים אובייקטי האופטימיזציה – למשל קביעת‬
‫ספים ל‪ inline-‬של פונקציות‪ ,‬שימוש ב‪ memcpy-‬וב‪ ,memset-‬ועוד‪.‬‬
‫אם ברצוננו להוסיף הערות ותיעוד לקוד המיוצר‪ ,‬נוכל לשלוט על כך ב‪ report-‬וב‪-‬‬
‫‪.comments‬‬
‫עמוד ‪ 28‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫מסך הגדרות ה‪emlcoder.MEXConfig-‬‬
‫‪ 6.2.2‬שימוש ב‪emlcoder.RTWConfig-‬‬
‫הגדרת האובייקט‪>> rtwcfg = emlcoder.RTWConfig :‬‬
‫עריכת האובייקט‪>> open rtwcfg :‬‬
‫מתקבל המסך הבא‪ ,‬בו אפשר להגדיר מספר רב של נתונים ואפשרויות‪.‬‬
‫תחת ‪ ,General‬נקבע האם ברצוננו לאפשר שימוש בוקטורים בעלי גודל משתנה‪ ,‬לאפשר‬
‫שימוש ב‪ ,BLAS-‬ולבחור האם למקם כל פונקציית ‪ MATLAB‬שנוצרת לקובץ ‪ C‬נפרד‪,‬‬
‫או האם לשלב את כל הקבצים לקובץ בודד‪ .‬כאן גם נבחר האם ברצוננו לייצר קוד ‪ C‬או‬
‫‪.C++‬‬
‫תחת ‪ Interface‬מצויות מספר הגדרות מאד משמעותיות‪ ,‬ביניהן בחירת ה‪Target -‬‬
‫)‪ ,Function Library (TFL‬תמיכה במספרים ‪ ,Floating‬הגדרת פונקציית ‪Terminate‬‬
‫ועוד‪.‬‬
‫ במידה וברצוננו לשלוט ולדאוג לאופטימיזציה גבוהה יותר של הקוד‪ ,‬נוכל לעשות‬
‫זאת ע"י שימוש ב‪ .RTW-EC-‬בכדי לייצר את האובייקט המתאים‪ ,‬יש להגדירו באופן‬
‫הבא‪:‬‬
‫עמוד ‪ 29‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫)'‪>> rtwcfg = emlcoder.RTWConfig('ert‬‬
‫מסך הגדרות ה‪emlcoder.RTWConfig('ert')-‬‬
‫‪ 6.2.3‬שימוש ב‪emlcoder.HardwareImplementation-‬‬
‫הגדרת האובייקט‪>> hwcfg = emlcoder.HardwareImplementation :‬‬
‫עריכת האובייקט‪>> open hwcfg :‬‬
‫באמצעות אובייקט זה ניתן לבחור את ארכיטקטורת המעבד והיצרן שעבורו ברצוננו‬
‫לייצר קוד‪.‬‬
‫בחירה ביצרן מסויים מגדירה לנו את ארכיטקטורת יצירת הקוד‪ ,‬שימוש ב‪ Little-‬או‬
‫‪ BigEndian‬וכדומה‪.‬‬
‫ במידה ויש גישה ל‪ ,Target Support Package-‬במסך זה יהיה מספר גדול יותר של‬
‫אפשרויות ומעבדים שונים‪.‬‬
‫עמוד ‪ 30‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫מסך הגדרות ה‪emlcoder.HardwareImplementation-‬‬
‫ במידה וברצוננו להשתמש במספר אובייקטים‪ ,‬נוכל לשרשר אותם‪:‬‬
‫‪>> emlc –T rtw:lib myEMLFunction –s rtwcfg –s hwcfg‬‬
‫עמוד ‪ 31‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .6.3‬שימוש בדו"ח יצירת הקוד‬
‫כחלק מהליך יצירת הקוד‪ ,‬מיוצר דו"ח מפורט המציג מספר נתונים מרכזיים‪:‬‬
‫‪ .1‬נתונים כלליים על מועד יצירת הקוד‪ ,‬סיכום התהליך‪.‬‬
‫‪ .2‬מסך סיכום נתונים על הפרמטרים שהוגדרו בקוד ובממשק אליו – האם הם ממשיים‬
‫או מרוכבים‪ ,‬גודל‪ ,‬טיפוס וכדומה‪.‬‬
‫‪ .3‬מסך על מעבד המטרה שעבורו נוצר הקוד‪.‬‬
‫‪ .4‬מסך קוד המקור שממנו נוצר קוד ה‪.C-‬‬
‫‪ .5‬אופן הקריאה לכל הפונקציות שמהן נוצר הקוד‪.‬‬
‫‪ .6‬הקוד המיוצר בחלוקה לפונקציות‪ ,‬עם ניווט מהיר להגדרות הפרמטרים השונים‪.‬‬
‫דו"ח זה מפשט ומקל על אופן בחינת הקוד והגדרתו‪ ,‬ניתן לייצוא למסמך ‪ word‬ו‪pdf-‬‬
‫וכמובן לבחינה בסקרי תכנון שונים‪.‬‬
‫‪ .6.4‬המלצות לייצור הקוד‬
‫‪ 6.4.1‬כפי שהוצג קודם‪ ,‬ישנן אפשרויות רבות יותר לשליטה על הקוד באמצעות‬
‫‪ .Simulink‬מאחר ומבחינה רישיונית בכל מקרה נעשה שימוש ב‪ ,Simulink-‬הרי שמומלץ‬
‫להשתמש בה כסביבת יצירת קוד‪ .‬משתמשים רבים ב‪ RTW-‬משתמשים ב‪Simulink-‬‬
‫כסביבת בדיקות וכסביבת יצירת קוד ולא כסביבת הפיתוח )למרות היתרונות הרבים‬
‫שלה(‪.‬‬
‫‪ 6.4.2‬תהליך יצירת הקוד יכול להיות מאד מורכב וארוך‪ .‬על כן‪ ,‬מומלץ להיעזר במשתמש‬
‫שכבר עבר הליך זה בעבר‪ ,‬או ביועץ‪/‬מהנדס אפליקציה של נציג ‪ MathWorks‬בארץ‪.‬‬
‫עמוד ‪ 32‬מתוך ‪33‬‬
‫קווים מנחים ליצירת קוד ‪ C‬מתוך ‪MATLAB‬‬
‫‪ .7‬סיכום‬
‫השימוש ב‪ Embedded MATLAB-‬ותהליך יצירת הקוד מסיר את הצורך לקודד‪ ,‬לתחזק ולבדוק‬
‫קוד שנכתב בצורה ידנית‪ .‬סבבי הפיתוח מתקצרים כתוצאה מכך‪ ,‬ומאפשרים להתמקד בשיפור‬
‫וייעול התכנון במקום לתחזק עותקים כפולים של קוד שנכתבו בשפות שונות‪.‬‬
‫במסמך זה הוצג תהליך העבודה הנדרש לצורך התאמת קוד המקור ל‪ ,EML-‬כיצד ניתן לבדוק‬
‫את הקוד מבחינה פונקציונלית ולוודא כי הוא מבצע את הנדרש ממנו‪ ,‬כיצד ניתן לייצר קוד‬
‫‪ C/C++‬בצורה אוטומטית‪ ,‬וכיצד ניתן להתאימו למעבד המטרה‪.‬‬
‫חשוב לציין כי טכנולוגיה זו התפתחה בשנים האחרונות‪ ,‬והיא ממשיכה להתפתח ולהיות יעילה‬
‫יותר עם התקדמות הגרסאות‪ .‬יכולות רבות נוספו בגרסאות האחרונות של התוכנה‪ ,‬אשר לא היו‬
‫זמינות בעבר‪ ,‬ומומלץ לקורא להתעדכן מפעם לפעם על החידושים בגרסאות האחרונות בתחום‬
‫זה‪.‬‬
‫תהליך יצירת הקוד יכול להיות מאד מורכב וארוך‪ .‬על כן‪ ,‬מומלץ להיעזר במשתמש שכבר עבר‬
‫הליך זה בעבר‪ ,‬או ביועץ‪/‬מהנדס אפליקציה של חברת ‪ MathWorks‬בארץ‪.‬‬
‫יש לציין כי מפעם לפעם נערכים סמינרים חופשיים אשר עוסקים בטכנולוגיית יצירת הקוד מתוך‬
‫‪ MATLAB‬ואופן שילובו ובדיקתו בתהליכי הפיתוח‪ .‬במידה ותחום זה חשוב ויכול לתרום‬
‫לחברתך – מומלץ להגיע‪.‬‬
‫עמוד ‪ 33‬מתוך ‪33‬‬