From fc2a6351d5f6903e70f06c3ec77aad2d4ab216c9 Mon Sep 17 00:00:00 2001 From: Thad House Date: Sat, 9 Sep 2023 23:18:22 -0700 Subject: [PATCH 1/6] Update to new api --- .gitignore | 10 +++ Cargo.lock | 66 ++------------------ Cargo.toml | 1 - lvbitfile2rust-cli/Cargo.toml | 4 +- lvbitfile2rust-cli/src/main.rs | 2 +- lvbitfile2rust-macros/Cargo.toml | 4 +- lvbitfile2rust-macros/src/lib.rs | 2 +- lvbitfile2rust/Cargo.toml | 4 +- lvbitfile2rust/src/lib.rs | 103 ++++++++++++++++--------------- 9 files changed, 75 insertions(+), 121 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7fe7d14 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock index 9a06edf..ac2943d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,39 +1,16 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "anyhow" version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b" -[[package]] -name = "bitvec" -version = "0.17.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" -dependencies = [ - "either", - "radium", -] - -[[package]] -name = "either" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f" - -[[package]] -name = "example" -version = "0.1.0" -dependencies = [ - "lvbitfile2rust-macros", - "ni-fpga", - "ni-fpga-macros", -] - [[package]] name = "lvbitfile2rust" -version = "0.1.0" +version = "0.2.0" dependencies = [ "proc-macro2", "quote", @@ -44,7 +21,7 @@ dependencies = [ [[package]] name = "lvbitfile2rust-cli" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "lvbitfile2rust", @@ -52,40 +29,13 @@ dependencies = [ [[package]] name = "lvbitfile2rust-macros" -version = "0.1.0" +version = "0.2.0" dependencies = [ "lvbitfile2rust", "quote", "syn", ] -[[package]] -name = "ni-fpga" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5d78540f253a540cc1455011cb950f5b09ad9e22d16c87d0bdeab5f98f39f8" -dependencies = [ - "bitvec", - "ni-fpga-sys", - "thiserror", -] - -[[package]] -name = "ni-fpga-macros" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63db566ab7c85356f297c918a92c6a8d873bedee049f19e34a51e791faa3bb6" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "ni-fpga-sys" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe22ec861b584675eb2cbbd4c150c4eeb9111527ed3ef64cc75ca69adb7f0051" - [[package]] name = "proc-macro2" version = "1.0.19" @@ -104,12 +54,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" - [[package]] name = "roxmltree" version = "0.13.0" diff --git a/Cargo.toml b/Cargo.toml index 1282eae..7a4af10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,5 @@ [workspace] members = [ - "example", "lvbitfile2rust", "lvbitfile2rust-cli", "lvbitfile2rust-macros", diff --git a/lvbitfile2rust-cli/Cargo.toml b/lvbitfile2rust-cli/Cargo.toml index bc3a625..a11858f 100644 --- a/lvbitfile2rust-cli/Cargo.toml +++ b/lvbitfile2rust-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lvbitfile2rust-cli" -version = "0.1.1" +version = "0.2.0" authors = ["Connor Worley "] edition = "2018" license-file = "LICENSE.md" @@ -10,4 +10,4 @@ repository = "https://github.com/first-rust-competition/lvbitfile2rust" [dependencies] anyhow = "1.0.32" -lvbitfile2rust = { version = "0.1.0", path = "../lvbitfile2rust" } +lvbitfile2rust = { version = "0.2.0", path = "../lvbitfile2rust" } diff --git a/lvbitfile2rust-cli/src/main.rs b/lvbitfile2rust-cli/src/main.rs index 6b27ff8..5aef0e1 100644 --- a/lvbitfile2rust-cli/src/main.rs +++ b/lvbitfile2rust-cli/src/main.rs @@ -3,6 +3,6 @@ use anyhow::Result; fn main() -> Result<()> { let mut args: Vec = std::env::args().collect(); assert_eq!(args.len(), 2, "usage: lvbitfile2rust-cli "); - println!("{}", lvbitfile2rust::codegen(args.remove(1))?); + println!("{}", lvbitfile2rust::codegen(args.remove(1), false)?); Ok(()) } diff --git a/lvbitfile2rust-macros/Cargo.toml b/lvbitfile2rust-macros/Cargo.toml index d16a83f..e9ac28f 100644 --- a/lvbitfile2rust-macros/Cargo.toml +++ b/lvbitfile2rust-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lvbitfile2rust-macros" -version = "0.1.1" +version = "0.2.0" authors = ["Connor Worley "] edition = "2018" license-file = "LICENSE.md" @@ -12,6 +12,6 @@ repository = "https://github.com/first-rust-competition/lvbitfile2rust" proc-macro = true [dependencies] -lvbitfile2rust = { version = "0.1.0", path = "../lvbitfile2rust" } +lvbitfile2rust = { version = "0.2.0", path = "../lvbitfile2rust" } quote = "1.0.7" syn = "1.0.23" diff --git a/lvbitfile2rust-macros/src/lib.rs b/lvbitfile2rust-macros/src/lib.rs index 9abcd64..516b4b6 100644 --- a/lvbitfile2rust-macros/src/lib.rs +++ b/lvbitfile2rust-macros/src/lib.rs @@ -6,7 +6,7 @@ use quote::quote; #[proc_macro] pub fn lvbitfile2rust(item: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(item as syn::LitStr); - match lvbitfile2rust::codegen(input.value()) { + match lvbitfile2rust::codegen(input.value(), true) { Ok(tokens) => tokens, Err(e) => { let err_string = e.to_string(); diff --git a/lvbitfile2rust/Cargo.toml b/lvbitfile2rust/Cargo.toml index 9898a2e..395bf64 100644 --- a/lvbitfile2rust/Cargo.toml +++ b/lvbitfile2rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lvbitfile2rust" -version = "0.1.1" +version = "0.2.0" authors = ["Connor Worley "] edition = "2018" license-file = "LICENSE.md" @@ -13,4 +13,4 @@ proc-macro2 = "1.0.19" quote = "1.0.7" roxmltree = "0.13.0" syn = { version = "1.0.23", features = ["full"] } -thiserror = "1.0.20" \ No newline at end of file +thiserror = "1.0.20" diff --git a/lvbitfile2rust/src/lib.rs b/lvbitfile2rust/src/lib.rs index e03b562..6489600 100644 --- a/lvbitfile2rust/src/lib.rs +++ b/lvbitfile2rust/src/lib.rs @@ -133,7 +133,10 @@ fn type_node_to_rust_typedecl( } } -pub fn codegen(bitfile_path: String) -> Result { +pub fn codegen( + bitfile_path: String, + embed_bitfile: bool, +) -> Result { let bitfile_contents = match std::fs::read_to_string(&bitfile_path) { Ok(contents) => contents, Err(e) => return Err(CodegenError::BitfileRead(bitfile_path, e)), @@ -142,6 +145,11 @@ pub fn codegen(bitfile_path: String) -> Result doc, Err(e) => return Err(CodegenError::BitfileParse(bitfile_path, e)), }; + let bitfile_literal = if embed_bitfile { + Some(syn::LitStr::new(&bitfile_contents, proc_macro2::Span::call_site())) + } else { + None + }; let mut typedefs = std::collections::HashSet::::new(); let mut register_defs = Vec::::new(); @@ -215,32 +223,37 @@ pub fn codegen(bitfile_path: String) -> Result quote! { - pub fn write(&self, value: &#typedecl) -> Result<(), ni_fpga::Error> { - unsafe { SESSION.as_ref() }.unwrap().write(#offset, value) - } - }, - _ => quote! {}, + let readable = true; + let writeable = match node_text(&first_child_by_tag(&node, "Indicator")?)? { + "false" => true, + "true" => false, + _ => todo!(), }; - register_defs.push(quote! { - pub struct #ident { - _marker: PhantomData<*const ()>, - } - impl #ident { - pub fn read(&self) -> Result<#typedecl, ni_fpga::Error> { - unsafe { SESSION.as_ref() }.unwrap().read(#offset) - } - #write_fn + let access_type = if readable { + if writeable { + "ReadWrite" + } else { + "ReadOnly" } + } else if writeable { + "WriteOnly" + } else { + // Error + todo!(); + }; + + let access = syn::Ident::new(access_type, proc_macro2::Span::call_site()); + + register_defs.push(quote! { + pub #ident: Option>> + }); + register_inits.push(quote! { + #ident: Some(unsafe { ni_fpga::Register::new_const() }) }); register_fields.push(quote! { pub #ident: #ident }); - register_inits.push(quote! { - #ident: #ident{ _marker: PhantomData } - }); } } "SignatureRegister" => { @@ -256,47 +269,35 @@ pub fn codegen(bitfile_path: String) -> Result, - #(#register_fields),* + pub struct FpgaBitfile { + #(#register_defs),* } - impl Peripherals { - pub fn take(resource: &str) -> Result> { - if unsafe{ !SESSION.is_null() } { - Err("Peripherals already in use")? - } else { - let session = ni_fpga::Session::open( - #bitfile_path, - #vi_signature, - resource, - )?; - unsafe { SESSION = &session as *const ni_fpga::Session; } - std::mem::forget(session); - Ok( - Self{ - _marker: PhantomData, - #(#register_inits),* - }, - ) - } + impl FpgaBitfile { + pub fn take() -> Option { + static REGISTERS: std::sync::Mutex> = std::sync::Mutex::new(Some(FpgaBitfile { + #(#register_inits),* + })); + let mut lock = REGISTERS.lock().unwrap(); + lock.take() + } + + pub const fn contents() -> &'static str { + #bitfile_literal + } + + pub const fn signature() -> &'static str { + #vi_signature } - } - impl Drop for Peripherals { - fn drop(&mut self) { - std::mem::drop(unsafe { SESSION.as_ref() }.unwrap()) + pub fn session_builder(resource: impl AsRef) -> Result { + ni_fpga::SessionBuilder::new().bitfile_contents(Self::contents())?.signature(Self::signature())?.resource(resource) } } }) From e6a61ab7e587ba6efb0066393b2f382609a4b04f Mon Sep 17 00:00:00 2001 From: Thad House Date: Sat, 9 Sep 2023 23:48:19 -0700 Subject: [PATCH 2/6] Fix generation of integration --- lvbitfile2rust/src/lib.rs | 41 +++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/lvbitfile2rust/src/lib.rs b/lvbitfile2rust/src/lib.rs index 6489600..869e776 100644 --- a/lvbitfile2rust/src/lib.rs +++ b/lvbitfile2rust/src/lib.rs @@ -53,19 +53,19 @@ impl ToTokens for HashableTokenStream { } fn sanitize_ident(ident: &str) -> String { - ident.replace(".", "_").replace(" ", "_") + ident.replace(['.', ' '], "_") } fn first_child_by_tag<'a, 'b>( node: &'a roxmltree::Node<'b, 'b>, child_tag: &'a str, ) -> Result, CodegenError> { - Ok(node + node .children() .find(|child| child.tag_name().name() == child_tag) .ok_or_else(|| { CodegenError::MissingChild(node.tag_name().name().to_owned(), child_tag.to_owned()) - })?) + }) } fn node_text<'a>(node: &'a roxmltree::Node) -> Result<&'a str, CodegenError> { @@ -73,6 +73,20 @@ fn node_text<'a>(node: &'a roxmltree::Node) -> Result<&'a str, CodegenError> { .ok_or_else(|| CodegenError::NoText(node.tag_name().name().to_owned())) } +pub fn find_cluster_name(type_node: &roxmltree::Node) -> Result { + Ok(match node_text(&first_child_by_tag(type_node, "Name")?) { + Ok(name) => name.into(), + Err(_) => { + // Navigate up 2 parents, see if we find an Array + let parent_block = type_node + .parent() + .and_then(|f| f.parent()) + .ok_or_else(|| CodegenError::NoText(type_node.tag_name().name().to_owned()))?; + node_text(&first_child_by_tag(&parent_block, "Name")?)?.into() + } + }) +} + fn type_node_to_rust_typedecl( type_node: &roxmltree::Node, ) -> Result { @@ -96,12 +110,22 @@ fn type_node_to_rust_typedecl( let inner_type_node = first_child_by_tag(type_node, "Type")? .first_element_child() .ok_or_else(|| CodegenError::NoChildren("Type".to_owned()))?; + let inner_typedecl = type_node_to_rust_typedecl(&inner_type_node)?; Ok(quote! { [#inner_typedecl; #size] }) } - "Cluster" | "EnumU8" | "EnumU16" | "EnumU32" | "EnumU64" => { + "Cluster" => { + let ident = syn::Ident::new( + &sanitize_ident(&find_cluster_name(type_node)?), + proc_macro2::Span::call_site(), + ); + Ok(quote! { + types::#ident + }) + } + "EnumU8" | "EnumU16" | "EnumU32" | "EnumU64" => { let ident = syn::Ident::new( &sanitize_ident(node_text(&first_child_by_tag(type_node, "Name")?)?), proc_macro2::Span::call_site(), @@ -146,7 +170,10 @@ pub fn codegen( Err(e) => return Err(CodegenError::BitfileParse(bitfile_path, e)), }; let bitfile_literal = if embed_bitfile { - Some(syn::LitStr::new(&bitfile_contents, proc_macro2::Span::call_site())) + Some(syn::LitStr::new( + &bitfile_contents, + proc_macro2::Span::call_site(), + )) } else { None }; @@ -161,7 +188,7 @@ pub fn codegen( match node.tag_name().name() { "Cluster" => { let ident = syn::Ident::new( - &sanitize_ident(node_text(&first_child_by_tag(&node, "Name")?)?), + &sanitize_ident(&find_cluster_name(&node)?), proc_macro2::Span::call_site(), ); let mut fields = Vec::::new(); @@ -267,8 +294,6 @@ pub fn codegen( typedefs_sorted.sort(); Ok(quote! { - use std::marker::PhantomData; - mod types { use ni_fpga_macros::{Cluster, Enum}; use super::types; From 49cc6cf10659beaffdb4783b444d1c4a41394752 Mon Sep 17 00:00:00 2001 From: Thad House Date: Sun, 10 Sep 2023 00:21:44 -0700 Subject: [PATCH 3/6] Use StoredOffset and dynamically load --- lvbitfile2rust/src/lib.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/lvbitfile2rust/src/lib.rs b/lvbitfile2rust/src/lib.rs index 869e776..0e8a030 100644 --- a/lvbitfile2rust/src/lib.rs +++ b/lvbitfile2rust/src/lib.rs @@ -242,10 +242,14 @@ pub fn codegen( &sanitize_ident(node_text(&first_child_by_tag(&node, "Name")?)?), proc_macro2::Span::call_site(), ); - let offset = syn::LitInt::new( - &sanitize_ident(node_text(&first_child_by_tag(&node, "Offset")?)?), + let str_ident = syn::LitStr::new( + &sanitize_ident(node_text(&first_child_by_tag(&node, "Name")?)?), proc_macro2::Span::call_site(), ); + // let offset = syn::LitInt::new( + // &sanitize_ident(node_text(&first_child_by_tag(&node, "Offset")?)?), + // proc_macro2::Span::call_site(), + // ); let type_node = first_child_by_tag(&node, "Datatype")? .first_element_child() .ok_or_else(|| CodegenError::NoChildren("Datatype".to_owned()))?; @@ -273,10 +277,10 @@ pub fn codegen( let access = syn::Ident::new(access_type, proc_macro2::Span::call_site()); register_defs.push(quote! { - pub #ident: Option>> + pub #ident: Option> }); register_inits.push(quote! { - #ident: Some(unsafe { ni_fpga::Register::new_const() }) + #ident: Some(unsafe { ni_fpga::Register::new(session.find_offset(#str_ident)?) }) }); register_fields.push(quote! { pub #ident: #ident @@ -305,12 +309,19 @@ pub fn codegen( } impl FpgaBitfile { - pub fn take() -> Option { - static REGISTERS: std::sync::Mutex> = std::sync::Mutex::new(Some(FpgaBitfile { - #(#register_inits),* - })); + pub fn take(session: &impl ni_fpga::SessionAccess) -> Result { + static REGISTERS: std::sync::Mutex> = std::sync::Mutex::new(Some(())); let mut lock = REGISTERS.lock().unwrap(); - lock.take() + let contents = lock.take(); + drop(lock); + + if contents.is_none() { + return Err(ni_fpga::Error::ResourceAlreadyTaken); + } + + Ok(Self { + #(#register_inits),* + }) } pub const fn contents() -> &'static str { From 8ec19e877c1232b3f48bfa7fee19621572f5287d Mon Sep 17 00:00:00 2001 From: Thad House Date: Sun, 10 Sep 2023 15:02:44 -0700 Subject: [PATCH 4/6] Fix hidden registers --- lvbitfile2rust/src/lib.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lvbitfile2rust/src/lib.rs b/lvbitfile2rust/src/lib.rs index 0e8a030..74bf6e4 100644 --- a/lvbitfile2rust/src/lib.rs +++ b/lvbitfile2rust/src/lib.rs @@ -60,8 +60,7 @@ fn first_child_by_tag<'a, 'b>( node: &'a roxmltree::Node<'b, 'b>, child_tag: &'a str, ) -> Result, CodegenError> { - node - .children() + node.children() .find(|child| child.tag_name().name() == child_tag) .ok_or_else(|| { CodegenError::MissingChild(node.tag_name().name().to_owned(), child_tag.to_owned()) @@ -237,19 +236,17 @@ pub fn codegen( })); } "Register" => { - if node_text(&first_child_by_tag(&node, "Hidden")?)? == "false" { + if node_text(&first_child_by_tag(&node, "Hidden")?)? == "false" + && node_text(&first_child_by_tag(&node, "Internal")?)? == "false" + { let ident = syn::Ident::new( &sanitize_ident(node_text(&first_child_by_tag(&node, "Name")?)?), proc_macro2::Span::call_site(), ); let str_ident = syn::LitStr::new( - &sanitize_ident(node_text(&first_child_by_tag(&node, "Name")?)?), + node_text(&first_child_by_tag(&node, "Name")?)?, proc_macro2::Span::call_site(), ); - // let offset = syn::LitInt::new( - // &sanitize_ident(node_text(&first_child_by_tag(&node, "Offset")?)?), - // proc_macro2::Span::call_site(), - // ); let type_node = first_child_by_tag(&node, "Datatype")? .first_element_child() .ok_or_else(|| CodegenError::NoChildren("Datatype".to_owned()))?; From 5c5f2ffc0efa438010251c8b02ccb9e1ae218da6 Mon Sep 17 00:00:00 2001 From: Thad House Date: Sun, 10 Sep 2023 15:30:51 -0700 Subject: [PATCH 5/6] Add HMB --- lvbitfile2rust/src/lib.rs | 49 ++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/lvbitfile2rust/src/lib.rs b/lvbitfile2rust/src/lib.rs index 74bf6e4..726618e 100644 --- a/lvbitfile2rust/src/lib.rs +++ b/lvbitfile2rust/src/lib.rs @@ -179,8 +179,9 @@ pub fn codegen( let mut typedefs = std::collections::HashSet::::new(); let mut register_defs = Vec::::new(); - let mut register_fields = Vec::::new(); + let mut hmb_fields = Vec::::new(); let mut register_inits = Vec::::new(); + let mut hmb_inits = Vec::::new(); let mut vi_signature = String::new(); for node in bitfile.root().descendants() { @@ -279,14 +280,41 @@ pub fn codegen( register_inits.push(quote! { #ident: Some(unsafe { ni_fpga::Register::new(session.find_offset(#str_ident)?) }) }); - register_fields.push(quote! { - pub #ident: #ident - }); } } "SignatureRegister" => { vi_signature = node_text(&node)?.to_owned(); } + "HMB" => { + let blocks = first_child_by_tag(&node, "MemoryBlockList")?; + for block in blocks + .children() + .filter(|child| child.is_element() && child.tag_name().name() == "MemoryBlock") + { + let ident = syn::Ident::new( + &sanitize_ident(node_text(&first_child_by_tag(&block, "Name")?)?), + proc_macro2::Span::call_site(), + ); + let ident_raw = syn::LitStr::new( + node_text(&first_child_by_tag(&block, "Name")?)?, + proc_macro2::Span::call_site(), + ); + let stride = syn::LitInt::new( + &sanitize_ident(node_text(&first_child_by_tag(&block, "Stride")?)?), + proc_macro2::Span::call_site(), + ); + let elements = syn::LitInt::new( + &sanitize_ident(node_text(&first_child_by_tag(&block, "Elements")?)?), + proc_macro2::Span::call_site(), + ); + hmb_fields.push(quote! { + pub #ident: ni_fpga::HmbDefinition + }); + hmb_inits.push(quote! { + #ident: ni_fpga::HmbDefinition { name: #ident_raw, stride: #stride, elements: #elements } + }); + } + } _ => {} } } @@ -301,8 +329,13 @@ pub fn codegen( #(#typedefs_sorted)* } + pub struct FpgaBitfileHmbDefs { + #(#hmb_fields),* + } + pub struct FpgaBitfile { - #(#register_defs),* + #(#register_defs),*, + hmb_definitions: FpgaBitfileHmbDefs, } impl FpgaBitfile { @@ -317,7 +350,11 @@ pub fn codegen( } Ok(Self { - #(#register_inits),* + #(#register_inits),*, + + hmb_definitions: FpgaBitfileHmbDefs { + #(#hmb_inits),* + } }) } From 833ce6f2b8f3de0ae56ec45b594468029e5ec2af Mon Sep 17 00:00:00 2001 From: Thad House Date: Sun, 10 Sep 2023 16:49:07 -0700 Subject: [PATCH 6/6] Include overflow bit --- lvbitfile2rust/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lvbitfile2rust/src/lib.rs b/lvbitfile2rust/src/lib.rs index 726618e..4ffff63 100644 --- a/lvbitfile2rust/src/lib.rs +++ b/lvbitfile2rust/src/lib.rs @@ -146,8 +146,14 @@ fn type_node_to_rust_typedecl( node_text(&first_child_by_tag(type_node, "IntegerWordLength")?)?, proc_macro2::Span::call_site(), ); + let include_overflow = syn::LitBool { + value: node_text(&first_child_by_tag(type_node, "IncludeOverflowStatus")?)? + == "true", + span: proc_macro2::Span::call_site(), + }; + Ok(quote! { - ni_fpga::fxp::FXP<#word_length, #integer_word_length, #signed> + ni_fpga::fxp::FXP<#word_length, #integer_word_length, #signed, #include_overflow> }) } _ => Err(CodegenError::UnknownBitfileType(