Applies To:
  • CitectSCADA  All versions 7.00 and below
  • CitectHMI  All versions 7.00 and below

Summary:

Cicode compiler will refuse to compile some large Cicode fragments 


Solution:

The Cicode compiler at times needs to create internal ‘Branch’ commands as the result of control structure statements (also referred to Conditional Operators) such as:

 

         IF/THEN
        
SELECT CASE
        
FOR
        
WHILE

 

The run-time Cicode processor is limited to relative jumps (positive or negative) of 32K (K=1024) in size. This is not the same as the module size limitation of 64K, but related.

 

As a result, it is possible for Cicode functions to be less than 64K in size, but for some required branch statements to be greater than 32K.

 

Note that only very large Cicode control structure statements will report this error. In practice, Cicode SELECT statements of two thousand lines have been seen that have this problem, and they were readily refactored to avoid this issue using methods such as those discussed here.

 

Consider the following Cicode fragment:

 

FUNCTION
foo(INT x) 
            
IF x > 1 THEN 
                        
… // sample code more than 32K
            
END
END

 

In this situation, a conditional branch is generated around the body of the IF statement. The architecture of the Cicode run-time engine is that branches are a signed 16-bit pointer which makes a jump of more than 32K in either direction impossible.

 

The Cicode compiler now detects this situation and forces a terminating error. The error will be reported by the compiler at the end of the block of Cicode because it is not till that point that the compiler knows how big the jump needs to be.

 

The Cicode which receives this error needs to be re-written in such a way that jumps of more than 32K are not required. The 32K limit is within a function. The sample foo() function above could be re-written in any number of ways so that it looks similar, but does not require any large branches like so:

 

FUNCTION
foo2(INT x) 
            
IF NOT (x > 1) THEN RETURN;
                        
… // sample code more than 32K Cicode addresses
END

 

Or another method might be:

 

FUNCTION
foo2b (INT x) 
            
IF x > 1 THEN 
                        
… // sample code less than 32K
                        
… // makes sure x is not modified in this block
            
END
            
IF x > 1 THEN // same test as the first one
                        
… // rest of the sample code, but also than 32K
            
END
END

 

RETURN does not generate branches. Large compound statements can be decreased in size by using RETURN and starting new compound statements.

 

Alternatively, break the 32K of Cicode instructions into 2 or more function calls. Each function has the same limitations on jump size and code size. For example:

 

FUNCTION
foo3(INT x) 
            
IF x > 1 THEN
                        
bar1(); // 1 st half of the 32K bytes of code is put in function bar1()
                        
bar2(); // 2 nd half of the code goes in bar2()
            
END
END

 

In the case of foo3(), the branch is very small. Putting the large block of code in another function means the function foo3 is dramatically reduced in size.

 

For example, SELECT statements could be refactored like so:

 

FUNCTION
another()
            
SELECT CASE x
                        
CASE 1 statements
                        
CASE 2 statements
                        

                        
CASE 100 statements
                        
CASE ELSE
                                    
Other_statements
            
END SELECT
END

 

Becomes

 

FUNCTION
another() // refactored
            
SELECT CASE x
            
IF x = 1 statements; RETURN;
            
IF x = 2 statements; RETURN;
            

            IF x = 100 statements; RETURN;
                        

            
Other_statements
END

 

The first version above would normally be preferred, and before refactoring the Cicode, we would recommend reducing the size of functions instead.

 

Keywords:
 

Attachments