Skip to content

Add Smstateen/Ssstateen Extension and CSRs #592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 33 commits into
base: main
Choose a base branch
from

Conversation

neverlandiz
Copy link
Contributor

This PR addresses Issue #547 and adds the Smstateen extension, along with the following Smstateen/Ssstateen CSRs

  • mstateen0, mstateen1, mstateen2, mstateen3
  • mstateen0h, mstateen1h, mstateen2h, mstateen3h
  • hstateen0, hstateen1, hstateen2, hstateen3
  • hstateen0h, hstateen1h, hstateen2h, hstateen3h
  • sstateen0, sstateen1, sstateen2, sstateen3

@neverlandiz neverlandiz requested a review from dhower-qc as a code owner April 4, 2025 02:15
Copy link
Collaborator

@ThinkOpenly ThinkOpenly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My comments in hstateen0/hstateen0h generally apply to the others as well.

Copy link
Collaborator

@dhower-qc dhower-qc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments apply to all the CSRs.

Copy link
Collaborator

@dhower-qc dhower-qc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need an arch/ext/Ssstateen.yaml file.

@neverlandiz
Copy link
Contributor Author

I think there is already a Ssstateen.yaml file?

@dhower-qc
Copy link
Collaborator

I think there is already a Ssstateen.yaml file?

You're right. Ignore my ignorance please ;)

The SE0 bit in `hstateen0` controls access to the `sstateen0` CSR.
type: RW
reset_value: UNDEFINED_LEGAL
ENVCFG:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The {h/s}stateen bits are 0 if the corresponding mstateen bit is 0. It doesn't look like that is captured here right now. I assume this needs a sw_read() call to represent this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that's right.

Copy link
Contributor Author

@neverlandiz neverlandiz May 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jordancarlin Thanks for pointing that out! Could you check if this implementation is correct (for hstateen0)?

sw_read(): |
  # for every bit in an mstateen CSR that is zero, the same bit 
  # appears as read-only zero in the matching hstateen CSR

  Bit<64> mstateen0_mask = CSR[mstateen0].csr_value;
  Bit<64> hstateen0_value = csr_value & mstateen0_mask;
  return hstateen0_value;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that seems reasonable. For sstateen it will probably be a little more complicated since it changes depending on if the H extension is enabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a sw_write() here, too, that enforces read-only for corresponding bits that are zero in mstateen0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to use type() instead of sw_write() to set the specific field to RO whenever the corresponding field is zero? For example, when CSR[mstateen0].JVT is 0, then CSR[sstateen0].JVT would have type RO.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand type() to be an expression that must be knowable at compile time. Since JVT can vary during runtime, I believe it needs to be a dynamic check with each write operation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought to look at the definition of that attribute in the schema to see if what I was saying was (1) accurate, and (2) documented, and nicely it is:

        "type()": {
          "type": "string",
          "description": "Function that returns a configuration-dependent type. The return value should be a CsrFieldType enum, and must be compile-time-known."
        },

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks for the clarification!

@neverlandiz
Copy link
Contributor Author

neverlandiz commented May 5, 2025

Regression tests are failing due to missing Sscsrind (depends on Issue #557) and Zfinx extensions.

@ThinkOpenly
Copy link
Collaborator

Regression tests are failing due to missing Sscsrind

Sscsrind is going in as we speak.

and Zfinx extensions.

I don't even see an issue open for that. :-/

@ThinkOpenly
Copy link
Collaborator

There are still a couple of unresolved comments about changing a reset_value and adding a sw_read().

As for Zfinx, I'd be tempted to comment it out in the PR, since Zfinx isn't even started, then open an issue for Zfinx to be added, including a note to uncomment the content here.

@neverlandiz
Copy link
Contributor Author

Ok, sounds good. Should I open an issue for Zfinx?

I'm still working on resolving the remaining comments, but I'll probably finish them by the end of today.

@jordancarlin
Copy link
Contributor

#711 adds the Zfinx (and other Z*inx) extensions.

@ThinkOpenly
Copy link
Collaborator

#711 adds the Zfinx (and other Z*inx) extensions.

Ah, so it does. I searched issues and PRs, but unsurprisingly didn't search for Z.*f.*inx.

Still, that PR and this one depend on each other. I suggest proceeding as planned... comment out Zfinx here, and move this one along.

@neverlandiz , if you would, please add a comment there requesting that your commented out content be uncommented via that PR.

@neverlandiz
Copy link
Contributor Author

Sounds good, thanks!

# for every bit in an mstateen CSR that is zero, the same bit
# appears as read-only zero in the matching hstateen CSR

Bits<64> mstateen0_mask = CSR[mstateen0].csr_value;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI failures are complaining about this. Looking at other files, when the entire CSR value is accessed, it seems you should use:

$bits(CSR[mstateen0])

here and elsewhere

@@ -160,6 +160,6 @@ sw_read(): |
# for every bit in an mstateen CSR that is zero, the same bit
# appears as read-only zero in the matching hstateen CSR

Bits<64> mstateen0_mask = CSR[mstateen0];
Bits<64> mstateen0_mask = CSR[mstateen0].csr_value;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To turn an entire CSR into a Bits type, you want to cast:

Bits<64> mstateen0_mask = $bits(CSR[mstateen0]);

Comment on lines +80 to +86
sw_write(csr_value): |
if (CSR[mstateen0].JVT == 1'b0){
return 0;
}
else if (mode() == PrivilegeMode::VS && CSR[hstateen0].JVT == 1'b0) {
return 0;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This brings up an interesting question. What happens if you write '1' to sstateen0.JVT while mstateen0.JVT is 0, and then change mstateen0.JVT to 1? Should sstateen0.JVT read as 0, 1, or undefined? I don't see any clarity on this in the spec. The answer will dictate whether this gets handled via sw_write() or sw_read().

While we figure that out...

All the stateen bits are WARL, and can thus be configured to be RW, read-only-0, or read-only-1. This will require a parameter for every bit in every mode. For example, for JVT:

arch/ext/Zcmt.yaml

parameters:
  MSTATEEN_JVT_TYPE:
    when: Smstateen
    schema:
      enum: [rw, read-only-0, read-only-1]
    description: |
      Behavior of the mstateen0.JVT bit:

        * 'rw': read-write
        * 'read-only-0': read-only, fixed to 0
        * 'read-only-1': read-only, fixed to 1
  HSTATEEN_JVT_TYPE:
    when:
      allOf:
        - H
        - Ssstateen
    schema:
      enum: [rw, read-only-0, read-only-1]
    description: |
      Behavior of the hstateen0.JVT bit:

        * 'rw': read-write
        * 'read-only-0': read-only, fixed to 0
        * 'read-only-1': read-only, fixed to 1
    extra_validation: |
      assert HSTATEEN_JVT_TYPE == 'read-only-0' if MSTATEEN_JVT_TYPE == 'read-only-0'
      assert HSTATEEN_JVT_TYPE == 'read-only-1' if MSTATEEN_JVT_TYPE == 'read-only-1'
  SSTATEEN_JVT_TYPE:
    when:
      allOf:
        - S
        - Sstateen
    schema:
      enum: [rw, read-only-0, read-only-1]
    description: |
      Behavior of the sstateen0.JVT bit:

        * 'rw': read-write
        * 'read-only-0': read-only, fixed to 0
        * 'read-only-1': read-only, fixed to 1
    extra_validation: |
      assert SSTATEEN_JVT_TYPE == 'read-only-0' if MSTATEEN_JVT_TYPE == 'read-only-0'
      assert SSTATEEN_JVT_TYPE == 'read-only-0' if HSTATEEN_JVT_TYPE == 'read-only-0'
      assert SSTATEEN_JVT_TYPE == 'read-only-1' if MSTATEEN_JVT_TYPE == 'read-only-1'
      assert SSTATEEN_JVT_TYPE == 'read-only-1' if HSTATEEN_JVT_TYPE == 'read-only-1'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback! Could you explain the purpose of this line when: Smstateen? When I tried adding it, it resulted in a schema error because Smstateen is not a when_condition. I looked at other extension yaml files and noticed that some use also_defined_in, but I'm not sure if it applies in this case.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad. After checking the schema, it's looking for an extension requirement (e.g., "~> 1.0"), which is assumed to be a requirement of the extension being defined (Zcmt here). That's not descriptive enough for us in this case, so we'll need a schema change. I will get that in ASAP and point you to it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#751 adds the support. You can say:

  when:
    name: Smstateen
    version: ~> 1.0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks!

Copy link
Contributor Author

@neverlandiz neverlandiz May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this schema also be added?

when:
 allOf:
   - S
   - Sstateen

@ThinkOpenly
Copy link
Collaborator

There was a newer version of The RISC-V Instruction Set Manual: Volume II: Privileged Archtecture last week (20250508). Sorry to do this to you, but could you verify the current content in this PR is up-to-date? @syedowaisalishah mentioned in #653 that, for example, mstateen0 now has more defined bits (SRMCFG and CTR).

@neverlandiz
Copy link
Contributor Author

Ok, sounds good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants