国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

IEC61131標(biāo)準(zhǔn)的結(jié)構(gòu)化文本語(yǔ)言解釋器設(shè)計(jì)

2019-01-17 03:14:50,,,,
關(guān)鍵詞:序號(hào)指令定義

,,,,

(南京南瑞繼保電氣有限公司,南京 211102)

引 言

IEC61131是國(guó)際電工委員會(huì)(IEC)頒布的可編程控制器(PLC)國(guó)際標(biāo)準(zhǔn)[1-5],它可以規(guī)范工業(yè)控制系統(tǒng)平臺(tái)和應(yīng)用程序開(kāi)發(fā),從而降低用戶(hù)的使用難度和維護(hù)成本[6]。IEC61131-3為軟件設(shè)計(jì)提供了標(biāo)準(zhǔn)化的編程概念和編程方法,定義了5種語(yǔ)言規(guī)范,國(guó)內(nèi)外工控廠(chǎng)家和科研機(jī)構(gòu)已經(jīng)開(kāi)始提供基于該標(biāo)準(zhǔn)的產(chǎn)品并進(jìn)行了應(yīng)用[7-10]。參考文獻(xiàn)[7]介紹了嵌入式軟PLC系統(tǒng)的架構(gòu),設(shè)計(jì)了將IEC61131-3語(yǔ)言轉(zhuǎn)換為C語(yǔ)言的開(kāi)發(fā)系統(tǒng)。參考文獻(xiàn)[8]提出一種將ST語(yǔ)言轉(zhuǎn)換為IL指令的方法,解決了ST語(yǔ)言語(yǔ)法分解和優(yōu)先級(jí)算法的相關(guān)問(wèn)題。參考文獻(xiàn)[9]提出了基于指令向量表的軟PLC系統(tǒng)實(shí)現(xiàn)方法,實(shí)現(xiàn)了梯形圖指令的高效執(zhí)行。參考文獻(xiàn)[10]是本課題組的前期研究成果,介紹了結(jié)構(gòu)化文本的虛擬機(jī)指令架構(gòu)和編譯優(yōu)化方法。PLC系統(tǒng)編程指令的執(zhí)行方式有編譯型和解釋型方式。編譯型效率高,需要針對(duì)運(yùn)行的硬件環(huán)境開(kāi)發(fā)專(zhuān)門(mén)的編譯器。解釋型執(zhí)行方式具有靈活性高、易于跨平臺(tái)移植的特點(diǎn),適用于在線(xiàn)無(wú)擾更新的應(yīng)用場(chǎng)景,但在實(shí)時(shí)性方面存在不足。針對(duì)參考文獻(xiàn)[10]開(kāi)發(fā)的編譯器形成的二進(jìn)制虛擬機(jī)指令,設(shè)計(jì)了配套的上位機(jī)仿真用解釋器,本文介紹了一種高效解釋執(zhí)行的方案。

1 解釋器設(shè)計(jì)

1.1 指令格式設(shè)計(jì)

本文在指令設(shè)計(jì)時(shí)參考了VCODE和CIL指令集的部分理念[10]:使執(zhí)行頻繁的部分保持高效,使其他部分保持正確。根據(jù)ST語(yǔ)言的規(guī)范和特性,支持可變形參,可內(nèi)置調(diào)用更豐富的庫(kù)函數(shù)接口。以算術(shù)運(yùn)算為例,在存儲(chǔ)時(shí)指令類(lèi)型占用1字節(jié),指令存在二元運(yùn)算如add(rd,rs1,rs2)、一元運(yùn)算如not(rd,rs)、跳轉(zhuǎn)指令jmp(lab)、函數(shù)調(diào)用scall等模式。采用緊湊型存儲(chǔ),根據(jù)指令類(lèi)型動(dòng)態(tài)輸出形參個(gè)數(shù)??紤]內(nèi)存對(duì)齊、方便快速掃描定位的前提下,內(nèi)存中三地址碼指令存儲(chǔ)格式定義如下:

指令碼(2 Bytes)參數(shù)1(2 Bytes)參數(shù)2可選(2 Bytes)參數(shù)3可選(2 Bytes)

存儲(chǔ)和讀取時(shí)根據(jù)指令類(lèi)型動(dòng)態(tài)計(jì)算參數(shù)偏移,例如add指令為3個(gè)形參,not指令為2個(gè)形參。

1.2 指令文件格式

圖1 指令文件格式

在上位機(jī)通過(guò)工具處理將ST/FBD/LD/SFC等類(lèi)型的POU編譯形成解釋器側(cè)所需的指令文件,文件采用小端方式存儲(chǔ)。文件結(jié)構(gòu)如圖1所示,包括文件頭 、引用的外部變量信息區(qū)、POU變量區(qū)、常量區(qū)、臨時(shí)變量區(qū)、指令區(qū)、字符串池(變長(zhǎng)存儲(chǔ))、擴(kuò)展信息段等。

圖中的變量區(qū)按照POU聲明的變量順序排列,即POU的輸入變量、輸出變量、輸入-輸出變量、中間變量。變量序號(hào)從0遞增,指令區(qū)的操作數(shù)記錄的是變量序號(hào),對(duì)于復(fù)雜結(jié)構(gòu)體采用深度優(yōu)先遍歷平鋪展開(kāi)為基本變量類(lèi)型的成員變量。

1.3 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)定義

單個(gè)IEC61131定義的基本變量用IecVar結(jié)構(gòu)體表示,作為最小粒度的邏輯分區(qū)存儲(chǔ)單元,它有兩個(gè)子結(jié)構(gòu)體成員,為VAR_FLAG和VAR_VALUE。邏輯變量定義如圖2所示。

圖2 邏輯變量定義

VAR_FLAG是個(gè)2字節(jié)的結(jié)構(gòu)體,記錄變量下IEC61131定義的變量屬性:

struct VAR_FLAG{

ushort var_type: 5; //參照ST的標(biāo)準(zhǔn)定義

ushort bretain: 1; //是否掉電保留

ushort bnegate: 1; //是否取反,

ushort bin_out: 1; //是否為輸入-輸出類(lèi)型

ushort bconst: 1; //是否為常量,寫(xiě)保護(hù)

ushort bredge: 1; //是否上升沿檢測(cè)

ushort bfedge: 1; //是否下降沿檢測(cè)

ushort bwrite_back: 1; //是否需要回寫(xiě)

ushort bupdate: 1; //更新位

ushort resv : 3;

};

VAR_VALUE用于表示變量的值、字符串類(lèi)型信息、時(shí)間類(lèi)型變量信息,為枚舉結(jié)構(gòu):

union LOGIC_VAR_VALUE{

uint m_uint;

int m_int;

float m_float;

USTR m_str; //字符串

uint64 m_uint64;

double m_double;

IEC_TIME m_t;

IEC_DATE m_date;

…};

其中字符串用4字節(jié)的結(jié)構(gòu)體表示,2字節(jié)表示長(zhǎng)度,2字節(jié)表示在字符串池中的起始位置。

指令編碼定義如下:

struct IRCode {

OpType tp; //指令類(lèi)型add/sub等

ushort arg1; //通常是目的地址序號(hào)

ushort arg2; //通常是源操作數(shù)序號(hào)1

ushort arg3; //通常是源操作數(shù)序號(hào)2

};

指令運(yùn)行條目信息,存儲(chǔ)運(yùn)行中變量地址和關(guān)聯(lián)的指令執(zhí)行函數(shù),是運(yùn)行時(shí)調(diào)度的基本單位:

struct IRItem{

ushort idx; //指令序號(hào)

uint parg1; //形參1對(duì)應(yīng)變量區(qū)變量地址

uint parg2; //形參2對(duì)應(yīng)變量區(qū)變量地址

uint parg3; //形參地址或立即數(shù)

void (*irfunc)(IRItem* p); //指令執(zhí)行函數(shù)

};

指令文件類(lèi)定義如下:

class CMidFile {

public:

CMidFile(); ~CMidFile();

public:

MID_HEADER m_header; //文件頭

QList m_externVarList; //外部變量區(qū)

QList m_pouVarList; //POU數(shù)據(jù)區(qū)

QList m_constVarList; //常量區(qū)

QList m_tempVarList; //臨時(shí)變量區(qū)

QList m_IRList; //指令數(shù)組

QList m_strList;

//存儲(chǔ)字符串列表

…};

解釋器在初始化時(shí),讀取指令文件,形成變量鏈表和指令數(shù)組。

1.4 解釋器架構(gòu)設(shè)計(jì)

根據(jù)控制器內(nèi)ST指令文件解析、執(zhí)行的流程,可將解釋器的功能結(jié)構(gòu)分為三個(gè)子模塊,如圖3所示。

圖3 解釋器運(yùn)行模型

初始化加載:對(duì)指令文件進(jìn)行初步解析,包括將緊湊排列的變量按照以IecVar為單位分配,方便數(shù)據(jù)信息的結(jié)構(gòu)化封裝以及索引定位。

解釋執(zhí)行任務(wù):根據(jù)預(yù)處理后形成的內(nèi)存文件,對(duì)指令區(qū)的指令逐條解釋執(zhí)行,并讀取外部變量區(qū)和本地變量區(qū)的相關(guān)數(shù)據(jù)。

數(shù)據(jù)刷新任務(wù):通過(guò)監(jiān)視接口對(duì)內(nèi)存文本中的數(shù)據(jù)進(jìn)行設(shè)置、觀(guān)測(cè),通過(guò)調(diào)試接口和調(diào)試符號(hào)表對(duì)指令區(qū)執(zhí)行過(guò)程進(jìn)行干預(yù)控制。

1.5 初始化設(shè)計(jì)

解釋器在初始化時(shí)讀取指令文件,先讀取文件頭,獲取各個(gè)變量區(qū)變量個(gè)數(shù)、指令個(gè)數(shù)等統(tǒng)計(jì)信息。之后依次讀取變量區(qū)、指令區(qū)、字符串池、調(diào)試表、擴(kuò)展信息區(qū)。為了節(jié)省空間,變量值VAR_VALUE在文件中存儲(chǔ)時(shí)按照實(shí)際類(lèi)型大小存儲(chǔ),在讀取時(shí),需要根據(jù)變量類(lèi)型動(dòng)態(tài)調(diào)整讀取的buf長(zhǎng)度,單個(gè)變量的讀取示例如下:

CIecVar* pvar = new CIecVar(varIdx++);

varList.append(pvar);

getMemory(buf, &tmpoff, (uchar*)&pvar->flag, len1);

switch( pvar->m_flag.var_type){

case e_BOOL:

case e_SINT:

pvar->m_val.m_char = (char)getChar(buf, &tmpoff);

break;

case e_USINT:

case e_BYTE:

pvar->m_val.m_uchar = getChar(buf, &tmpoff);

break;

…}

指令區(qū)解析根據(jù)指令類(lèi)型解析若干形參,形成指令編碼如下:

IRCode* pIR = new IRCode();

m_IRList.append(pIR);

pIR->tp = (OpType)getInt16(pbuf, &tmpoff);

switch(pIR->tp){

case e_add: //3個(gè)形參

case e_div:

pIR->arg1 = getInt16(pbuf, &tmpoff);

pIR->arg2 = getInt16(pbuf, &tmpoff);

pIR->arg3 = getInt16(pbuf, &tmpoff);

break;

case e_asgn: // 2個(gè)形參

case e_not:

pIR->arg1 = getInt16(pbuf, &tmpoff);

pIR->arg2 = getInt16(pbuf, &tmpoff);

break;

case e_jmp:// 1個(gè)形參

case e_lab:

pIR->arg1 = getInt16(pbuf, &tmpoff);

break;

}

在初始化過(guò)程中,通過(guò)如下處理為運(yùn)行時(shí)提高效率創(chuàng)造條件:

① 在讀取完變量區(qū)和指令區(qū)后,根據(jù)指令形參中記錄的變量區(qū)序號(hào),查找到動(dòng)態(tài)分配的IecVar變量的地址,形成IRItem條目結(jié)構(gòu),并根據(jù)指令類(lèi)型關(guān)聯(lián)對(duì)應(yīng)的指令解析函數(shù)或系統(tǒng)庫(kù)函數(shù)指針,在初始化時(shí)完成數(shù)據(jù)形參、執(zhí)行函數(shù)的關(guān)聯(lián),實(shí)現(xiàn)初始化一次查找關(guān)聯(lián),執(zhí)行時(shí)直接使用轉(zhuǎn)換。圖4是add指令的形參和執(zhí)行函數(shù)的關(guān)聯(lián)過(guò)程。

圖4 IRItem形成過(guò)程示例

② 創(chuàng)建lab標(biāo)號(hào)和指令序號(hào)的hash表,即QHashm_labelHash, 實(shí)現(xiàn)運(yùn)行shi跳轉(zhuǎn)指令快速跳轉(zhuǎn)到對(duì)應(yīng)的指令區(qū)域。

1.6 運(yùn)行時(shí)設(shè)計(jì)

根據(jù)ST語(yǔ)言的基本指令碼索引其函數(shù)指針數(shù)組,獲得對(duì)應(yīng)功能函數(shù)指針,傳入形參地址,進(jìn)行解釋執(zhí)行。對(duì)于系統(tǒng)庫(kù)函數(shù)指令碼的解釋執(zhí)行,首先定位scall指令,再根據(jù)其第一個(gè)形參值(系統(tǒng)庫(kù)函數(shù)的指令碼值)索引定位系統(tǒng)庫(kù)函數(shù)指令碼函數(shù)指針數(shù)組,獲取對(duì)應(yīng)功能函數(shù)指針,傳入在系統(tǒng)庫(kù)變量區(qū)的功能塊結(jié)構(gòu)體首地址,進(jìn)行解釋執(zhí)行。當(dāng)執(zhí)行到JZ、JMP等跳轉(zhuǎn)指令時(shí),將當(dāng)前執(zhí)行的指令數(shù)組下標(biāo)修改為跳轉(zhuǎn)指令記錄的跳轉(zhuǎn)目的標(biāo)號(hào),之后順序執(zhí)行從新下標(biāo)起始對(duì)應(yīng)的指令。由于初始化過(guò)程中已經(jīng)根據(jù)指令類(lèi)型設(shè)置了對(duì)應(yīng)的執(zhí)行函數(shù)指針,故運(yùn)行過(guò)程中不需要進(jìn)行指令類(lèi)型判斷,順次執(zhí)行即可:

void CInterpreter:::execIRList(){

readInput(); //刷新外部輸入

m_curpos = 0;

m_it =m_IRList.begin();

while(m_curpos

IRItem* pitem =*m_it;

if(pitem->irfunc ) pitem->irfunc(pitem);

++m_it;

++m_curpos; }

writeOutput(); //將值更新到輸出

}

其中跳轉(zhuǎn)指令執(zhí)行函數(shù)的作用是動(dòng)態(tài)調(diào)整當(dāng)前指令游標(biāo)m_it、m_curpos,從而間接修改主函數(shù)while循環(huán)中下次運(yùn)行的起始位置,實(shí)現(xiàn)指令數(shù)組順次執(zhí)行可跳轉(zhuǎn)的功能:

inline exec_jmp(IRItem* p){

ushort label = (ushort)p->arg1;

QHash::Iterator it;

it = m_labelHash.find(label);

if(it!=m_labelHash.end()){

//動(dòng)態(tài)調(diào)整當(dāng)前下標(biāo)到跳轉(zhuǎn)的標(biāo)簽處

int labpos = (int)it.value();

m_it += labpos-m_curpos;

m_curpos = labpos;

}

}

結(jié) 語(yǔ)

猜你喜歡
序號(hào)指令定義
聽(tīng)我指令:大催眠術(shù)
ARINC661顯控指令快速驗(yàn)證方法
LED照明產(chǎn)品歐盟ErP指令要求解讀
技術(shù)指標(biāo)選股
技術(shù)指標(biāo)選股
技術(shù)指標(biāo)選股
技術(shù)指標(biāo)選股
成功的定義
山東青年(2016年1期)2016-02-28 14:25:25
坐標(biāo)系旋轉(zhuǎn)指令數(shù)控編程應(yīng)用
修辭學(xué)的重大定義
石屏县| 东安县| 西城区| 宝坻区| 吴旗县| 龙州县| 密山市| 杭锦后旗| 子洲县| 衡水市| 龙岩市| 通道| 清丰县| 蒲江县| 西贡区| 鄂伦春自治旗| 磐石市| 苍梧县| 尼玛县| 蒲江县| 钟山县| 井冈山市| 阳西县| 沁阳市| 广宁县| 铁力市| 乌什县| 宿松县| 德清县| 文化| 修文县| 凤台县| 南郑县| 黑龙江省| 淳化县| 辉南县| 于都县| 汝阳县| 微山县| 安徽省| 栾城县|