Conversation
|
Have you done any tests to see if generated code does not need any trait bounds? To me it seems like it it shouldn't be required, but there's no usage examples, just making sure since I'm afraid of trait bounds 😱 |
I haven't done that yet, no. That's what I'll be working on today, so hopefully it's something I can complete today (^: |
85ac603 to
fed0aeb
Compare
| let input_str = input.to_string(); | ||
| if !(input_str.starts_with("0x") || input_str.starts_with("0X")) | ||
| || input_str | ||
| .chars() | ||
| .skip(2) | ||
| .any(|c| !(c.is_ascii_hexdigit() || c == ' ' || c == '_')) | ||
| { | ||
| return syn::Error::new( | ||
| input.span(), | ||
| concat!( | ||
| "Expected a hexadecimal literal! Must start with `0x` or `0X` and contain ", | ||
| "only hexdigits, spaces, and underscores", | ||
| ) | ||
| .to_string(), | ||
| ) | ||
| .into_compile_error() | ||
| .into(); | ||
| } |
There was a problem hiding this comment.
Wouldn't it make sense to also support binary literals and maybe even base 10 literals?
There was a problem hiding this comment.
I could add support for binary literals pretty easily, just the issue is that for decimal literals there's the issue of not having a way to turn that into binary very easily past a certain size.
3c4d3da to
5da7507
Compare
| let mut char_iter = input_str.chars().filter(char::is_ascii_hexdigit).rev(); | ||
| let mut lower = true; | ||
| let mut idx = 0; | ||
| loop { |
There was a problem hiding this comment.
I've been thinking if there is a good way to use from_str_radix for this instead of hand rolling this, but I guess you want arbitrarily large literals too, so this wouldn't work 😔 Maybe this could be a comment here though? Otherwise I'll wonder the same thing in two months when I look at this again haha
| array_str.push('['); | ||
| for byte in buf { | ||
| write!(array_str, "0x{byte:02x}, ").unwrap(); | ||
| } | ||
| array_str.pop(); | ||
| array_str.pop(); | ||
| array_str.push(']'); |
There was a problem hiding this comment.
This could check for the first element to have less manual shuffling of the characters in the string
| array_str.push('['); | |
| for byte in buf { | |
| write!(array_str, "0x{byte:02x}, ").unwrap(); | |
| } | |
| array_str.pop(); | |
| array_str.pop(); | |
| array_str.push(']'); | |
| array_str.push('['); | |
| for (i, byte) in buf.iter().enumerate() { | |
| if i > 0 { | |
| write!(array_str, ", ").unwrap(); | |
| } | |
| write!(array_str, "0x{byte:02x}").unwrap(); | |
| } | |
| array_str.push(']'); |
dbbb82e to
f2ca52c
Compare
2bf627f to
cdd3069
Compare
|
Marked as ready for review. I know there's one more thing I need to do (sign extension for |
NOTE: WILL NOT PASS CI
NOTE: WILL NOT PASS CI
NOTE: WILL NOT PASS CI
NOTE: WILL NOT PASS CI
cdd3069 to
d00584e
Compare
d00584e to
95fa3d0
Compare
hydrolarus
left a comment
There was a problem hiding this comment.
Overall looking good, but some questions regarding macro hygiene, style of type macros and usage of expr-macros
| let n = n as usize; | ||
| let len = n.div_ceil(8); | ||
| quote! { BitVector<#n, #len> } |
There was a problem hiding this comment.
This leaves suffixes everywhere, right? So BitVector<24usize, 3usize>. Wouldn't it make sense to use unsuffixed literals since usually the types of the literals aren't so important on the type level?
There was a problem hiding this comment.
Same goes for the other types below
| fn get_correct_size(n: u128) -> u32 { | ||
| let clog2 = (u128::BITS - (n - 1).leading_zeros()).next_power_of_two(); | ||
| clog2.max(8) | ||
| } |
There was a problem hiding this comment.
The name is a bit non-descriptive. Maybe native_size_in_bits or something? Same for the other local functions below
| bittide_hal::manual_additions::index::IndexTy<#n_lit, #ty> | ||
| Index<#n_lit, #ty> |
There was a problem hiding this comment.
Sadly proc macros don't have the same hygiene as declarative macros... I guess it's because of using the macros in the bittide_hal? Otherwise I feel like the fully qualified version would be more robust?
Maaaybe it's possible to check if the macro is being invoked in bittide_hal and then change the prefix?
| quote! { | ||
| crate::manual_additions::signed::Signed<#n_lit, #ty> | ||
| } | ||
| .into() |
There was a problem hiding this comment.
Here it's using crate again, so this wouldn't work outside of bittide_hal?
| pub fn write_slice(&self, src: &[[u8; 8]], offset: usize) { | ||
| assert!(src.len() + offset <= Self::GATHER_MEMORY_LEN); | ||
| let mut off = offset; | ||
| for &val in src { | ||
| unsafe { | ||
| self.set_gather_memory_unchecked(off, val); | ||
| self.set_gather_memory_unchecked(off, BitVector::new_unchecked(val)); |
There was a problem hiding this comment.
Haven't checked usage sites of this function yet, but with the changed code generator, wouldn't src: &[BitVector![64]] make this easier? Same for the ScatterUnit below and the other scatter_gather impls in the other files
|
|
||
| // Set margin and enable | ||
| elastic_buffer.set_auto_center_margin(margin); | ||
| elastic_buffer.set_auto_center_margin(Unsigned::new(margin).unwrap()); |
There was a problem hiding this comment.
Shouldn't unsigned!(margin, n = N) work here too?
|
|
||
| // Manually adjust buffer off-center | ||
| elastic_buffer.set_adjustment(perturbation); | ||
| elastic_buffer.set_adjustment(Signed::new(perturbation).unwrap()); |
There was a problem hiding this comment.
Same here, signed!(perturbation, n = N)
| peripheral.set_status(Unsigned::new(*status_val).unwrap()); | ||
| write!(name_buf, "peripheral{}.status.readback", i).unwrap(); | ||
| expect(&name_buf, *status_val, peripheral.status()); | ||
| expect(&name_buf, *status_val, peripheral.status().into_inner()); | ||
| name_buf.clear(); | ||
|
|
||
| // Write and read back control | ||
| peripheral.set_control(*control_val); | ||
| peripheral.set_control(Unsigned::new(*control_val).unwrap()); |
There was a problem hiding this comment.
unsigned!(<expr>, n = N)
| fn main() -> ! { | ||
| let active_entry0: [u8; 16] = core::array::from_fn(|i| i as u8); | ||
| let mut active_entry1: [u8; 16] = active_entry0; | ||
| let active_entry0 = core::array::from_fn(|i| Index::new(i as u8).unwrap()); |
| ve_repeat: Unsigned::new(8).unwrap(), | ||
| }, | ||
| ValidEntry_12 { | ||
| ve_entry: active_entry1, | ||
| ve_repeat: 16, | ||
| ve_repeat: Unsigned::new(16).unwrap(), | ||
| }, | ||
| ]; | ||
|
|
||
| let cal_shadow: [CalendarEntryType<Calendar>; 16] = core::array::from_fn(|i| ValidEntry_12 { | ||
| ve_entry: core::array::from_fn(|_j| i as u8), | ||
| ve_repeat: i as u16, | ||
| ve_entry: core::array::from_fn(|_j| Index::new(i as u8).unwrap()), | ||
| ve_repeat: Unsigned::new(i as u16).unwrap(), |
There was a problem hiding this comment.
Same here, contruction macros should probably be preferred unless there's a good reason to not use them
This implements basic functionality for
Index<N, T>,Unsigned<N, T>,Signed<N, T>, andBitVec<N, M>. This PR is currently marked as draft since I still need to:Anywho, at least an initial review pass and/or suggestions on things I should add in this PR that I didn't (and that I don't have WIP stuff for already from before I did a lot of downscoping, like operator
impls).