Minres / CoreDSL

Xtext project to parse CoreDSL files
Apache License 2.0
14 stars 2 forks source link

PC increment #54

Closed wysiwyng closed 1 year ago

wysiwyng commented 2 years ago

Currently, the PC increment is not defined; implementers have to assume that it will be ~automagically~ performed correctly. From what I see, the current intended behavior (and what ETISS as well as DBT-RISE implement) is roughly this:

This behavior must be documented somewhere. It is however problematic with regard to repeated accesses to the PC register:

instruction ins1 [[cond]] [[no_cont]] {
    ...
    behavior: {
        if (X[rs1] == X[rs2]) {
            LR = PC;
            PC = PC + imm;
            X[rd] = PC;
        }
        GP = PC + 0x100;
    }
}

With the behavior explained above, the repeated PC reads in this example would not yield the expected results. I propose the following mechanisms to avoid these issues:

  1. Increment PC implicitly for non-branching instructions, and explicitly for branching instructions: This means a conditional branch needs to update the PC in all code paths, otherwise the execution will get stuck. An additional caveat of this solution is that technically any instruction which may raise an exception is also a conditional branch.
  2. Only explicit PC increments: absolutely annoying to use, but very clear
  3. Define PC increment for non-branching instructions somewhere centrally, reuse this function if any conditional branch needs a standard PC increment
  4. Don't do anything, but clearly document the implications of the current behavior

More suggestions on how to solve this issue are very welcome, especially regarding normal usage of the PC register in CoreDSL code.

jopperm commented 2 years ago

I don't think 4. would work well in CoreDSL, because then the current ISS-driven behavior for PC updates would resemble non-blocking assignments (<=) in Verilog, whereas the rest of the language uses C-style, blocking assignments. Through this C-lens, I would expect X[rd] == address-of(ins1) + imm (in case X[rs1] == X[rs2]).

Option 1. or 3. (or a mix thereof) sound promising to me. I'd let the compiler detect CF paths on which the register with the [[is_pc]] attribute is not written.

jopperm commented 2 years ago

For completeness:

  1. @neithernut suggested distinguishing a current PC (read-only) and a next PC (write-only). 5a. ... instead of a variable-like thing, the next PC could also be the argument of a return-like statement at the end of the control-path(s) through the instruction behavior.
eyck commented 2 years ago

I would opt for 4 since the PC is by adding the [[is_pc]]attribute a special veriable, in my understanding it makes it a deferred-update variable. This means if I read the PC I always read the actual value not the written value being scheduled to be updated. For me as a user of CoreDSL it feels natural to write PC=PC+X[rs1] and this is also inline with e.g. instruction descriptions (not only for RISC-V)

jopperm commented 1 year ago

I think this should be decided for 2.0 -- ISS people (@eyck @wysiwyng), are you happy with handling the implicit PC increment via an always block (somewhere high up in the hierarchy)? If so, we could just close this issue.

always { implicit_increment { PC += sizeof(encoding); } }
eyck commented 1 year ago

Yes, let's do it this way.