Skip to content

Introduction: Concurrency

Julian Oppermann edited this page Dec 5, 2022 · 9 revisions

A key requirement in the design of CoreDSL 2 is the ability to describe behavior outside of the main execution pipeline. We initially focus on supporting the two most promising use-cases for such ISAXes:

  1. Long-running instructions, such as computing trigonometric functions using the CORDIC algorithm.
  2. Functional units in the background, such as a zero-overhead loop controller, which continuously watch and react to architectural state changes.

CoreDSL 2 introduces two separate constructs* to support these use-cases:

  • Long-running instructions may contain a spawn block (marked with the spawn keyword), whose execution is decoupled from the main pipeline, meaning other instructions can be issued and retired independently of the spawn block.
  • Functional units in the background are described as always blocks (inside an always section). These blocks contain behavior that is executed repeatedly, at the same rate as instructions are fetched.

*) We settled on these constructs after unsuccessfully considering concepts based on cooperative multitasking and guarded atomic actions to cover both use-cases at once.

Examples

Long-running instruction

InstructionSet TRIG extends RV32I {
  instructions {
    SIN {
      encoding: ... :: rs1[4:0] :: ... :: rd[4:0] :: ...;
      behavior: {
        unsigned<32> x = X[rs1];
        spawn {
          unsigned<32> sine; /* ... other decls ... */
          for (short k = 0; k < 16; ++k) {
            // CORDIC magic
          }
          X[rd] = sine;
        }
      }
    }
  }
}

Functional unit in the background

// Following RI5CY/pulp extensions
InstructionSet ZOL extends RV32I {
  architectural_state {
    unsigned<32> &lpstart_0 = CSR[0x7C0];
    unsigned<32> &lpend_0   = CSR[0x7C1];
    unsigned<32> &lpcount_0 = CSR[0x7C2];
  }
  
  always {
    zol_0 {
      if (PC == lpend_0 && lpcount_0 != 0) {
        PC = lpstart_0;
        lpcount_0 -= 1;
      }
    }
  }
  
  instructions {
    setup_zol_0 {
      encoding: uimm[11:0] :: rs1[4:0] :: ...;
      behavior: {
        lpstart_0 = (unsigned<32>) (PC + 4)
        lpend_0   = (unsigned<32>) (PC + ((unsigned<13>) uimm << 1);
        lpcount_0 = X[rs1];
      }
    }
  }
}
Clone this wiki locally