Skip to content

Introduction: Syntax

Julian Oppermann edited this page Jun 21, 2021 · 13 revisions

The code below shows the CoreDSL2 description of a simple core implementing a subset of the RISC-V base ISA, shortened here for the purpose of highlighting the basic concepts used in the language.

The top-level entity, modelling a processor core, is the CoreDef. It is split into several, optional sections. In this example, only the architectural_state (definition of implementation parameters, declarations of registers and address spaces) and instructions (definitions of instruction encoding and behavior) sections are used.

In general, the syntax follows the conventions of the C/C++ language family. The manipulation of non-byte-sized data is common in the specification of instruction semantics, hence, we support arbitrary-precision integer types (with an explicit width specification in bits, e.g. unsigned<XLEN>), bit literals (3'b010), and bit-level operators such as bit ranges ([4:0]) and concatenation (::). We borrow C++'s attribute notation to augment declarations and instructions with additional information, e.g. marking a register as the core's program counter with the attribute [[is_pc]].

CoreDef My32bitRISCVCore {
  architectural_state {
             unsigned int    REG_LEN = 32;  // implementation parameter
             unsigned int    XLEN = 32;     // implementation parameter
    register unsigned<XLEN>  X[REG_LEN];    // register file
    register unsigned<XLEN>  PC [[is_pc]];  // single register with attribute
             unsigned<XLEN>& ZERO = X[0];   // register alias
    extern   unsigned<8>     MEM[1<<XLEN];  // address space declaration
  }

  instructions {
    LUI {
      encoding: imm[31:12] :: rd[4:0] :: 7'b0110111;
      behavior: if (rd != 0) X[rd] = imm;
    }
    JAL [[no_cont]] {
      encoding: imm[20:20] :: imm[10:1] :: imm[11:11] :: imm[19:12] :: rd[4:0] :: 7'b1101111;
      behavior: {
        if (rd != 0)
          X[rd] = (unsigned<XLEN>) (PC + 4);
        PC += (signed) imm;
      }
    }
    LW {
      encoding: imm[11:0] :: rs1[4:0] :: 3'b010 :: rd[4:0] :: 7'b0000011;
      behavior: if (rd != 0) {
        unsigned<XLEN> base = (unsigned<XLEN>) (X[rs1] + (signed) imm);
        X[rd] = MEM[base] :: MEM[base + 1] :: MEM[base + 2] :: MEM[base + 3];
      }
    }
    XOR {
      encoding: 7'b0000000 :: rs2[4:0] :: rs1[4:0] :: 3'b100 :: rd[4:0] :: 7'b0110011;
      behavior: if (rd != 0) X[rd] = X[rs1] ^ X[rs2];
    }
    // ... many more instructions, omitted for brevity
  }
}
Clone this wiki locally