-
Notifications
You must be signed in to change notification settings - Fork 124
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
Lean: Adding features to support structs and bitfields #817
Conversation
Looks good! The convention for Lean files is to start with an upper case, I think we'd better stick to that |
f15991b
to
84df9be
Compare
b0de2a6
to
4583c5a
Compare
3a9f237
to
9999aff
Compare
67b5ae7
to
e0ca20c
Compare
src/sail_lean_backend/Sail/Sail.lean
Outdated
def extractLsb {w: Nat} (x: BitVec w) (hi lo: Nat) : BitVec (hi - lo + 1) := | ||
x.extractLsb hi lo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def extractLsb {w: Nat} (x: BitVec w) (hi lo: Nat) : BitVec (hi - lo + 1) := | |
x.extractLsb hi lo | |
def extractLsb {w : Nat} (x : BitVec w) (hi lo : Nat) : BitVec (hi - lo + 1) := | |
x.extractLsb hi lo |
Lean style puts a space before the :
in arguments. I did notice the rest of the file has the same formatting, so we might want to address this in a separate formatting PR and fix the whole file in one go.
src/sail_lean_backend/Sail/Sail.lean
Outdated
def truncateLSB {w: Nat} (x: BitVec w) (w': Nat) : BitVec w' := | ||
x.extractLsb' 0 w' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def truncateLSB {w: Nat} (x: BitVec w) (w': Nat) : BitVec w' := | |
x.extractLsb' 0 w' | |
def truncateLsb {w: Nat} (x: BitVec w) (w': Nat) : BitVec w' := | |
x.extractLsb' 0 w' |
We generally treat Lsb
as one word, for the sake of capitalization. (Outside of the diff of this PR, so feel free to ignore)
src/sail_lean_backend/Sail/Sail.lean
Outdated
def update_subrange' {w: Nat} (x: BitVec w) (start len: Nat) (y: BitVec len) : BitVec w := | ||
let mask := ~~~(((BitVec.allOnes len).zeroExtend w) <<< start) | ||
let y' := mask ||| ((y.zeroExtend w) <<< start) | ||
x &&& y' | ||
|
||
def update_subrange {w: Nat} (x: BitVec w) (hi lo: Nat) (y: BitVec (hi - lo + 1)) : BitVec w := | ||
update_subrange' x lo _ y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def update_subrange' {w: Nat} (x: BitVec w) (start len: Nat) (y: BitVec len) : BitVec w := | |
let mask := ~~~(((BitVec.allOnes len).zeroExtend w) <<< start) | |
let y' := mask ||| ((y.zeroExtend w) <<< start) | |
x &&& y' | |
def update_subrange {w: Nat} (x: BitVec w) (hi lo: Nat) (y: BitVec (hi - lo + 1)) : BitVec w := | |
update_subrange' x lo _ y | |
def updateSubrange' {w: Nat} (x: BitVec w) (start len: Nat) (y: BitVec len) : BitVec w := | |
let mask := ~~~(((BitVec.allOnes len).zeroExtend w) <<< start) | |
let y' := mask ||| ((y.zeroExtend w) <<< start) | |
x &&& y' | |
def updateSubrange {w: Nat} (x: BitVec w) (hi lo: Nat) (y: BitVec (hi - lo + 1)) : BitVec w := | |
updateSubrange' x lo _ y |
Lean style uses lowerCamelCase
for definitions
src/sail_lean_backend/Sail/Sail.lean
Outdated
end BitVec | ||
end Sail | ||
|
||
structure registerRef (regstate regval a : Type) where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
structure registerRef (regstate regval a : Type) where | |
structure RegisterRef (regstate regval a : Type) where |
In this case, RegisterRef
is a type(-valued function) and thus is written UpperCamelCase
! (Sorry for not catching that before)
src/sail_lean_backend/Sail/Sail.lean
Outdated
def truncate {w: Nat} (x: BitVec w) (w': Nat) : BitVec w' := | ||
def truncate {w : Nat} (x : BitVec w) (w' : Nat) : BitVec w' := | ||
x.truncate w' | ||
|
||
def truncateLSB {w: Nat} (x: BitVec w) (w': Nat) : BitVec w' := | ||
def truncateLsb {w : Nat} (x : BitVec w) (w' : Nat) : BitVec w' := | ||
x.extractLsb' 0 w' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this is stuff outside the scope of your PR diff, but since you're cleaning it up I'll comment anyway:
truncate
and truncateLsb
are provably equivalent. It's unclear to me why we need both definitions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, let's delete truncateLsb
and avoid redundant defs.
Thank you for the annotations, @alexkeizer!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see
This is my bad, truncateLsb
is supposed to extract the most significant bits, the first argument is wrong here.
Since this changes more, I think I'll just open a separate PR to fix this and the formatting
81fe816
to
e75d960
Compare
This will fail until #870 is merged, because I need the parentheses fix it introduces |
662fa50
to
ab6fefd
Compare
test/lean/struct.expected.lean
Outdated
|
||
/-- Type quantifiers: i : Int -/ | ||
def mk_struct (i : Int) (b : (BitVec 1)) : My_struct := | ||
{field1 := i, field2 := b} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Canonical Lean style would mandate spaces inside the curly brackets. But we could also print this as
def mk_struct (i : Int) (b : (BitVec 1)) : My_struct :=
{ field1 := i
field2 := b }
which might be better for bigger terms
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with your solution, I'll do that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Note that we don't even need the ,
if we do the indentation right)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be sure I follow the style: should it be
def mk_struct (i : Int) (b : (BitVec 1)) : My_struct :=
{
field1 := i
field2 := b
}
or
def mk_struct (i : Int) (b : (BitVec 1)) : My_struct :=
{ field1 := i
field2 := b }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The latter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the following should also be a valid spelling of the same definition:
def mk_struct (i : Int) (b : (BitVec 1)) : My_struct where
field1 := i
field2 := b
Not that there's any clear benefit over this style, so I'm not suggesting we switch to it necessarily, just wanted to make you aware of the full space of options
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wouldn't be practical here I think, since the :=
is in the function definition, not in the expression.
but good to know
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I think keeping the :=
is easier. This might be a task that could be given to the mighty future Lean reformatter ™
because the imports in Sail.lean needed the output folder's name to work properly
523c16e
to
8242d70
Compare
This implements the translation of bitfields, and of the operations on structs (accessing a field, editing a field, making a new instance of a struct)