PARAMLIB - The Parameter Library

The parameter library is used to create the type definitions of parameters used by the project. HASE supplies the built-in types: bit, bool, char, integer, unsigned integer, long, floating-point, string and range, from which more complex types can be created, for example structures, enumerations and ranges. Once types have been defined in the parameter library, instances of these types can then be created in the GLOBALS section of the project definition file and within entity declarations (in the ENTITYLIB section).
^ Enum - Enumerated Type Parameter - ENUM ( typename, [ enumerate : icon, ... ] )

The ENUM declaration enables the creation of an enumerated type similar to those found in C and C++. It provides a means of enumerating a finite set of elements.

Example: ENUM ( cache_state, [ cache_hit : hit_icon, cache_miss : miss_icon ] )
^ Struct - Structure Parameter - STRUCT ( typename, [ reference_parameter , ... ] )

The STRUCT construct allows the creation of data structures, similar to the struct declaration in C and C++. This mechanism provides a means to aggregate variables of different types.

Example: STRUCT ( Data_Packet, [ RINT (Packet_No, 0) , RINT (Packet_Data, 0) ] )
^ Instr - Instruction Parameter

The Instr parameter is best explained by means of an example. The following example shows the full instruction set of a simple computer (described in more detail in Example Project), preceded by the necessary operand STRUCT definitions. Each instruction consists of a function and zero, one or more operands.

-- operands for loading a register from memory using address + (index reg)
    STRUCT (t_load, [RSTRING (dest_reg, "-", 5),
                     RSTRING (src_reg, "-", 5),
                     RINT (address, 0)]);

-- operands for storing a register to memory using address + (index reg)
    STRUCT (t_store, [RSTRING (src_reg, "-", 5),
                      RSTRING (dest_reg, "-", 5),
                      RINT (address, 0)]);

-- operand for loading register with immediate
    STRUCT (t_loadi, [RSTRING (dest_reg, "-", 5),
                      RINT (immediate, 0)]);

-- operands for move instruction
    STRUCT (t_move, [RSTRING (dest_reg, "-", 5),
                    RSTRING (src_reg, "-", 5)]);

 -- operands for ALU scalar instruction group
    STRUCT (t_alu,  [RSTRING (dest_reg, "-", 5),
                     RSTRING (src_reg1, "-", 5),
                     RSTRING (src_reg2, "-", 5)]);

--  operands for ALUI scalar instruction group
     STRUCT (t_alui,  [RSTRING (dest_reg, "-", 5),
                       RSTRING (src_reg1, "-", 5),
                       RINT (immediate, 0)]);

-- operands for COMP instruction
    STRUCT (t_comp, [RSTRING (src_reg1, "-", 5),
                     RSTRING (src_reg2, "-", 5)]);

-- Definition of a simple instruction set
    INSTR (t_simple_instrn_set, [(NOP),
          (JUMP, RINT (immediate, 0)),
          (JREG, RSTRING (src_reg,  "-")),
          (SETCC(SEQ,SNE,SGT,SLT,SGE,SLE), RSTRUCT (t_comp, comp_field)),
          (BRANCH, RSTRING (label, "-", 50)),
          (LDM, RSTRUCT (t_load,  load_field)),
          (LDI, RSTRUCT (t_loadi, loadi_field)),
          (STM, RSTRUCT (t_store, store_field)),
          (ALU(ADD,SUB,MUL,DIV,AND,OR,XOR,SLL,SRL,SRA), RSTRUCT (t_alu, alu_field)),
          (ALUI(ADDI,SUBI,MULI,DIVI,ANDI,ORI,XORI,SLLI,SRLI,SRAI), RSTRUCT (t_alui, alui_field)),
          (STOP) ], function);
Notes
  1. t_simple_instrn_set is the (str) typename of the instruction set, used when creating instances; a project can include more than instruction set definition.
  2. In STRUCT (t_loadi, [RSTRING (dest_reg, "-", 5), RINT (immediate, 0)]); "-" is the initial value of dest_reg while the value 5 limits the length of the string to 5 characters; the default string length in HASE is 100 characters, so this parameter reduces the storage requirements of a project (NB: the length must allow for the end-of-string character).
  3. In (JUMP, RINT (immediate, 0)), the operand is just an integer, so doesn't need a STRUCT definition.
  4. NOP and STOP> have no operand.
  5. In (ALU(ADD,SUB,MUL,DIV,AND,OR,XOR,SLL,SRL,SRA), ALU is the (str) tag of a class of instructions, while ADD etc. are members of the class_enum (in this case called function; this allows the construct
      if (IR.decode_ALU())
    
    to be used in e.g. the processor Hase++ file (proc.hase when a common set of actions is to be performed for all ALU functions, where IR is an instruction register type t_simple_instrn_set.
  6. Individual instructions within the ALU set can be decoded using a switch construct:

     switch (IR.function)
      {
       case ADD:  // ADD Rx Ry Rz: Rx = Ry + Rz
       dest_op = src1_op + src2_op;
       break;
    etc.
    }
    

    OR by using the construct:

     if (IR.function == t_simple_instrn_set::JUMP)
      {
      
      }
    
  7. The semantics of the instructions are determined by the behavioural code in the Hase++ files. Thus the above definitions could be used as a basis for creating the instruction set of the simple processor described in Structure of a Project.

^ Link - LINK ( typename, [ ( tag , reference_parameter : icon), ... ] )

Example: LINK ( DLink, [ ( MEM_R, RINT ( Address, 0) ), ( MEM_W, RSTRUCT ( Info, I ) : PktIcon ) ] )
^ Array - Array Parameter - ARRAY ( typename, type_of_elements )

The ARRAY construct provides a mechanism for defining lists of objects of the same type, similar to the array construct in C & C++. Anytime such a declaration is encountered, a new C++ class will be created. This class will have the name typename.

Example: ARRAY (data_mem_array, int);
^ ArrayI - Instruction Array Parameter - ARRAYI ( typename, type_of_elements )

The ARRAYI construct provides a mechanism similar to ARRAY for defining lists of objects of the same type but specific to the ARRAYI construct is the ability to produce labels to address arrays of instructions (typically in memory).

Example: ARRAYI (instr_mem_array, t_dlx_instrn_set);

Labels
Labels are automatically built from the symbolic name associated with the ARRAYI construct. These labels can be then used in Hase++ code by means of a method called process. The signature of this method is as follows:

process(char * symbolicName, int offset)

The offset refers to a cell in the array of instructions bound to the symbolic name of the first parameter.

Hase++ Example:

int addr = instr_mem.process(InstrMemRequest.addr.label, InstrMemRequest.addr.offset);

Instruction Memory Example:

label2:
ADDI R7 R7 42
BNEZ R7 label2
SUBI R7 R7 126
J label3
ADDI R8 R0 68
label3:
ADDI R8 R0 17