forked from libre-chip/fayalite
		
	Compare commits
	
		
			No commits in common. "c16726cee63cd5afbf720dad14fcba7f738cf6b6" and "903ca1bf30827903608938f6993e586e13cf54ca" have entirely different histories.
		
	
	
		
			c16726cee6
			...
			903ca1bf30
		
	
		
					 17 changed files with 440 additions and 13203 deletions
				
			
		
							
								
								
									
										8
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -543,9 +543,9 @@ dependencies = [ | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "proc-macro2" | name = "proc-macro2" | ||||||
| version = "1.0.92" | version = "1.0.83" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" | checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "unicode-ident", |  "unicode-ident", | ||||||
| ] | ] | ||||||
|  | @ -647,9 +647,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "syn" | name = "syn" | ||||||
| version = "2.0.93" | version = "2.0.66" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" | checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "proc-macro2", |  "proc-macro2", | ||||||
|  "quote", |  "quote", | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ quote = "1.0.36" | ||||||
| serde = { version = "1.0.202", features = ["derive"] } | serde = { version = "1.0.202", features = ["derive"] } | ||||||
| serde_json = { version = "1.0.117", features = ["preserve_order"] } | serde_json = { version = "1.0.117", features = ["preserve_order"] } | ||||||
| sha2 = "0.10.8" | sha2 = "0.10.8" | ||||||
| syn = { version = "2.0.93", features = ["full", "fold", "visit", "extra-traits"] } | syn = { version = "2.0.66", features = ["full", "fold", "visit", "extra-traits"] } | ||||||
| tempfile = "3.10.1" | tempfile = "3.10.1" | ||||||
| thiserror = "1.0.61" | thiserror = "1.0.61" | ||||||
| trybuild = "1.0" | trybuild = "1.0" | ||||||
|  |  | ||||||
|  | @ -3,20 +3,14 @@ | ||||||
| #![cfg_attr(test, recursion_limit = "512")] | #![cfg_attr(test, recursion_limit = "512")] | ||||||
| use proc_macro2::{Span, TokenStream}; | use proc_macro2::{Span, TokenStream}; | ||||||
| use quote::{quote, ToTokens}; | use quote::{quote, ToTokens}; | ||||||
| use std::{ | use std::io::{ErrorKind, Write}; | ||||||
|     collections::{hash_map::Entry, HashMap}, |  | ||||||
|     io::{ErrorKind, Write}, |  | ||||||
| }; |  | ||||||
| use syn::{ | use syn::{ | ||||||
|     bracketed, |     bracketed, parenthesized, | ||||||
|     ext::IdentExt, |  | ||||||
|     parenthesized, |  | ||||||
|     parse::{Parse, ParseStream, Parser}, |     parse::{Parse, ParseStream, Parser}, | ||||||
|     parse_quote, |     parse_quote, | ||||||
|     punctuated::{Pair, Punctuated}, |     punctuated::Pair, | ||||||
|     spanned::Spanned, |     spanned::Spanned, | ||||||
|     token::{Bracket, Paren}, |     AttrStyle, Attribute, Error, Item, ItemFn, Token, | ||||||
|     AttrStyle, Attribute, Error, Ident, Item, ItemFn, LitBool, LitStr, Meta, Token, |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| mod fold; | mod fold; | ||||||
|  | @ -25,7 +19,6 @@ mod hdl_enum; | ||||||
| mod hdl_type_alias; | mod hdl_type_alias; | ||||||
| mod hdl_type_common; | mod hdl_type_common; | ||||||
| mod module; | mod module; | ||||||
| mod process_cfg; |  | ||||||
| 
 | 
 | ||||||
| pub(crate) trait CustomToken: | pub(crate) trait CustomToken: | ||||||
|     Copy |     Copy | ||||||
|  | @ -66,11 +59,6 @@ mod kw { | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     custom_keyword!(__evaluated_cfgs); |  | ||||||
|     custom_keyword!(all); |  | ||||||
|     custom_keyword!(any); |  | ||||||
|     custom_keyword!(cfg); |  | ||||||
|     custom_keyword!(cfg_attr); |  | ||||||
|     custom_keyword!(clock_domain); |     custom_keyword!(clock_domain); | ||||||
|     custom_keyword!(connect_inexact); |     custom_keyword!(connect_inexact); | ||||||
|     custom_keyword!(custom_bounds); |     custom_keyword!(custom_bounds); | ||||||
|  | @ -87,7 +75,6 @@ mod kw { | ||||||
|     custom_keyword!(no_reset); |     custom_keyword!(no_reset); | ||||||
|     custom_keyword!(no_runtime_generics); |     custom_keyword!(no_runtime_generics); | ||||||
|     custom_keyword!(no_static); |     custom_keyword!(no_static); | ||||||
|     custom_keyword!(not); |  | ||||||
|     custom_keyword!(outline_generated); |     custom_keyword!(outline_generated); | ||||||
|     custom_keyword!(output); |     custom_keyword!(output); | ||||||
|     custom_keyword!(reg_builder); |     custom_keyword!(reg_builder); | ||||||
|  | @ -914,346 +901,15 @@ fn hdl_module_impl(item: ItemFn) -> syn::Result<TokenStream> { | ||||||
|     Ok(contents) |     Ok(contents) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, PartialEq, Eq, Hash, Debug)] | pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> { | ||||||
| pub(crate) enum CfgExpr { |     let kw = kw::hdl_module::default(); | ||||||
|     Option { |     hdl_module_impl(syn::parse2(quote! { #[#kw(#attr)] #item })?) | ||||||
|         ident: Ident, |  | ||||||
|         value: Option<(Token![=], LitStr)>, |  | ||||||
|     }, |  | ||||||
|     All { |  | ||||||
|         all: kw::all, |  | ||||||
|         paren: Paren, |  | ||||||
|         exprs: Punctuated<CfgExpr, Token![,]>, |  | ||||||
|     }, |  | ||||||
|     Any { |  | ||||||
|         any: kw::any, |  | ||||||
|         paren: Paren, |  | ||||||
|         exprs: Punctuated<CfgExpr, Token![,]>, |  | ||||||
|     }, |  | ||||||
|     Not { |  | ||||||
|         not: kw::not, |  | ||||||
|         paren: Paren, |  | ||||||
|         expr: Box<CfgExpr>, |  | ||||||
|         trailing_comma: Option<Token![,]>, |  | ||||||
|     }, |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Parse for CfgExpr { | pub fn hdl_attr(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> { | ||||||
|     fn parse(input: ParseStream) -> syn::Result<Self> { |     let kw = kw::hdl::default(); | ||||||
|         match input.cursor().ident() { |     let item = quote! { #[#kw(#attr)] #item }; | ||||||
|             Some((_, cursor)) if cursor.eof() => { |     let item = syn::parse2::<Item>(item)?; | ||||||
|                 return Ok(CfgExpr::Option { |  | ||||||
|                     ident: input.call(Ident::parse_any)?, |  | ||||||
|                     value: None, |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|             _ => {} |  | ||||||
|         } |  | ||||||
|         if input.peek(Ident::peek_any) && input.peek2(Token![=]) { |  | ||||||
|             return Ok(CfgExpr::Option { |  | ||||||
|                 ident: input.call(Ident::parse_any)?, |  | ||||||
|                 value: Some((input.parse()?, input.parse()?)), |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|         let contents; |  | ||||||
|         if input.peek(kw::all) { |  | ||||||
|             Ok(CfgExpr::All { |  | ||||||
|                 all: input.parse()?, |  | ||||||
|                 paren: parenthesized!(contents in input), |  | ||||||
|                 exprs: contents.call(Punctuated::parse_terminated)?, |  | ||||||
|             }) |  | ||||||
|         } else if input.peek(kw::any) { |  | ||||||
|             Ok(CfgExpr::Any { |  | ||||||
|                 any: input.parse()?, |  | ||||||
|                 paren: parenthesized!(contents in input), |  | ||||||
|                 exprs: contents.call(Punctuated::parse_terminated)?, |  | ||||||
|             }) |  | ||||||
|         } else if input.peek(kw::not) { |  | ||||||
|             Ok(CfgExpr::Not { |  | ||||||
|                 not: input.parse()?, |  | ||||||
|                 paren: parenthesized!(contents in input), |  | ||||||
|                 expr: contents.parse()?, |  | ||||||
|                 trailing_comma: contents.parse()?, |  | ||||||
|             }) |  | ||||||
|         } else { |  | ||||||
|             Err(input.error("expected cfg-pattern")) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl ToTokens for CfgExpr { |  | ||||||
|     fn to_tokens(&self, tokens: &mut TokenStream) { |  | ||||||
|         match self { |  | ||||||
|             CfgExpr::Option { ident, value } => { |  | ||||||
|                 ident.to_tokens(tokens); |  | ||||||
|                 if let Some((eq, value)) = value { |  | ||||||
|                     eq.to_tokens(tokens); |  | ||||||
|                     value.to_tokens(tokens); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             CfgExpr::All { all, paren, exprs } => { |  | ||||||
|                 all.to_tokens(tokens); |  | ||||||
|                 paren.surround(tokens, |tokens| exprs.to_tokens(tokens)); |  | ||||||
|             } |  | ||||||
|             CfgExpr::Any { any, paren, exprs } => { |  | ||||||
|                 any.to_tokens(tokens); |  | ||||||
|                 paren.surround(tokens, |tokens| exprs.to_tokens(tokens)); |  | ||||||
|             } |  | ||||||
|             CfgExpr::Not { |  | ||||||
|                 not, |  | ||||||
|                 paren, |  | ||||||
|                 expr, |  | ||||||
|                 trailing_comma, |  | ||||||
|             } => { |  | ||||||
|                 not.to_tokens(tokens); |  | ||||||
|                 paren.surround(tokens, |tokens| { |  | ||||||
|                     expr.to_tokens(tokens); |  | ||||||
|                     trailing_comma.to_tokens(tokens); |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Clone, PartialEq, Eq, Hash, Debug)] |  | ||||||
| pub(crate) struct Cfg { |  | ||||||
|     cfg: kw::cfg, |  | ||||||
|     paren: Paren, |  | ||||||
|     expr: CfgExpr, |  | ||||||
|     trailing_comma: Option<Token![,]>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Cfg { |  | ||||||
|     fn parse_meta(meta: &Meta) -> syn::Result<Self> { |  | ||||||
|         syn::parse2(meta.to_token_stream()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl ToTokens for Cfg { |  | ||||||
|     fn to_tokens(&self, tokens: &mut TokenStream) { |  | ||||||
|         let Self { |  | ||||||
|             cfg, |  | ||||||
|             paren, |  | ||||||
|             expr, |  | ||||||
|             trailing_comma, |  | ||||||
|         } = self; |  | ||||||
|         cfg.to_tokens(tokens); |  | ||||||
|         paren.surround(tokens, |tokens| { |  | ||||||
|             expr.to_tokens(tokens); |  | ||||||
|             trailing_comma.to_tokens(tokens); |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Parse for Cfg { |  | ||||||
|     fn parse(input: ParseStream) -> syn::Result<Self> { |  | ||||||
|         let contents; |  | ||||||
|         Ok(Self { |  | ||||||
|             cfg: input.parse()?, |  | ||||||
|             paren: parenthesized!(contents in input), |  | ||||||
|             expr: contents.parse()?, |  | ||||||
|             trailing_comma: contents.parse()?, |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Clone, PartialEq, Eq, Hash, Debug)] |  | ||||||
| pub(crate) struct CfgAttr { |  | ||||||
|     cfg_attr: kw::cfg_attr, |  | ||||||
|     paren: Paren, |  | ||||||
|     expr: CfgExpr, |  | ||||||
|     comma: Token![,], |  | ||||||
|     attrs: Punctuated<Meta, Token![,]>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl CfgAttr { |  | ||||||
|     pub(crate) fn to_cfg(&self) -> Cfg { |  | ||||||
|         Cfg { |  | ||||||
|             cfg: kw::cfg(self.cfg_attr.span), |  | ||||||
|             paren: self.paren, |  | ||||||
|             expr: self.expr.clone(), |  | ||||||
|             trailing_comma: None, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     fn parse_meta(meta: &Meta) -> syn::Result<Self> { |  | ||||||
|         syn::parse2(meta.to_token_stream()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Parse for CfgAttr { |  | ||||||
|     fn parse(input: ParseStream) -> syn::Result<Self> { |  | ||||||
|         let contents; |  | ||||||
|         Ok(Self { |  | ||||||
|             cfg_attr: input.parse()?, |  | ||||||
|             paren: parenthesized!(contents in input), |  | ||||||
|             expr: contents.parse()?, |  | ||||||
|             comma: contents.parse()?, |  | ||||||
|             attrs: contents.call(Punctuated::parse_terminated)?, |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub(crate) struct CfgAndValue { |  | ||||||
|     cfg: Cfg, |  | ||||||
|     eq_token: Token![=], |  | ||||||
|     value: LitBool, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Parse for CfgAndValue { |  | ||||||
|     fn parse(input: ParseStream) -> syn::Result<Self> { |  | ||||||
|         Ok(Self { |  | ||||||
|             cfg: input.parse()?, |  | ||||||
|             eq_token: input.parse()?, |  | ||||||
|             value: input.parse()?, |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub(crate) struct Cfgs<T> { |  | ||||||
|     pub(crate) bracket: Bracket, |  | ||||||
|     pub(crate) cfgs_map: HashMap<Cfg, T>, |  | ||||||
|     pub(crate) cfgs_list: Vec<Cfg>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl<T> Default for Cfgs<T> { |  | ||||||
|     fn default() -> Self { |  | ||||||
|         Self { |  | ||||||
|             bracket: Default::default(), |  | ||||||
|             cfgs_map: Default::default(), |  | ||||||
|             cfgs_list: Default::default(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl<T> Cfgs<T> { |  | ||||||
|     fn insert_cfg(&mut self, cfg: Cfg, value: T) { |  | ||||||
|         match self.cfgs_map.entry(cfg) { |  | ||||||
|             Entry::Occupied(_) => {} |  | ||||||
|             Entry::Vacant(entry) => { |  | ||||||
|                 self.cfgs_list.push(entry.key().clone()); |  | ||||||
|                 entry.insert(value); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Parse for Cfgs<bool> { |  | ||||||
|     fn parse(input: ParseStream) -> syn::Result<Self> { |  | ||||||
|         let contents; |  | ||||||
|         let bracket = bracketed!(contents in input); |  | ||||||
|         let mut cfgs_map = HashMap::new(); |  | ||||||
|         let mut cfgs_list = Vec::new(); |  | ||||||
|         for CfgAndValue { |  | ||||||
|             cfg, |  | ||||||
|             eq_token, |  | ||||||
|             value, |  | ||||||
|         } in contents.call(Punctuated::<CfgAndValue, Token![,]>::parse_terminated)? |  | ||||||
|         { |  | ||||||
|             let _ = eq_token; |  | ||||||
|             match cfgs_map.entry(cfg) { |  | ||||||
|                 Entry::Occupied(_) => {} |  | ||||||
|                 Entry::Vacant(entry) => { |  | ||||||
|                     cfgs_list.push(entry.key().clone()); |  | ||||||
|                     entry.insert(value.value); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         Ok(Self { |  | ||||||
|             bracket, |  | ||||||
|             cfgs_map, |  | ||||||
|             cfgs_list, |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Parse for Cfgs<()> { |  | ||||||
|     fn parse(input: ParseStream) -> syn::Result<Self> { |  | ||||||
|         let contents; |  | ||||||
|         let bracket = bracketed!(contents in input); |  | ||||||
|         let mut cfgs_map = HashMap::new(); |  | ||||||
|         let mut cfgs_list = Vec::new(); |  | ||||||
|         for cfg in contents.call(Punctuated::<Cfg, Token![,]>::parse_terminated)? { |  | ||||||
|             match cfgs_map.entry(cfg) { |  | ||||||
|                 Entry::Occupied(_) => {} |  | ||||||
|                 Entry::Vacant(entry) => { |  | ||||||
|                     cfgs_list.push(entry.key().clone()); |  | ||||||
|                     entry.insert(()); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         Ok(Self { |  | ||||||
|             bracket, |  | ||||||
|             cfgs_map, |  | ||||||
|             cfgs_list, |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl ToTokens for Cfgs<()> { |  | ||||||
|     fn to_tokens(&self, tokens: &mut TokenStream) { |  | ||||||
|         let Self { |  | ||||||
|             bracket, |  | ||||||
|             cfgs_map: _, |  | ||||||
|             cfgs_list, |  | ||||||
|         } = self; |  | ||||||
|         bracket.surround(tokens, |tokens| { |  | ||||||
|             for cfg in cfgs_list { |  | ||||||
|                 cfg.to_tokens(tokens); |  | ||||||
|                 <Token![,]>::default().to_tokens(tokens); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn hdl_main( |  | ||||||
|     kw: impl CustomToken, |  | ||||||
|     attr: TokenStream, |  | ||||||
|     item: TokenStream, |  | ||||||
| ) -> syn::Result<TokenStream> { |  | ||||||
|     fn parse_evaluated_cfgs_attr<R>( |  | ||||||
|         input: ParseStream, |  | ||||||
|         parse_inner: impl FnOnce(ParseStream) -> syn::Result<R>, |  | ||||||
|     ) -> syn::Result<R> { |  | ||||||
|         let _: Token![#] = input.parse()?; |  | ||||||
|         let bracket_content; |  | ||||||
|         bracketed!(bracket_content in input); |  | ||||||
|         let _: kw::__evaluated_cfgs = bracket_content.parse()?; |  | ||||||
|         let paren_content; |  | ||||||
|         parenthesized!(paren_content in bracket_content); |  | ||||||
|         parse_inner(&paren_content) |  | ||||||
|     } |  | ||||||
|     let (evaluated_cfgs, item): (_, TokenStream) = Parser::parse2( |  | ||||||
|         |input: ParseStream| { |  | ||||||
|             let peek = input.fork(); |  | ||||||
|             if parse_evaluated_cfgs_attr(&peek, |_| Ok(())).is_ok() { |  | ||||||
|                 let evaluated_cfgs = parse_evaluated_cfgs_attr(input, Cfgs::<bool>::parse)?; |  | ||||||
|                 Ok((Some(evaluated_cfgs), input.parse()?)) |  | ||||||
|             } else { |  | ||||||
|                 Ok((None, input.parse()?)) |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         item, |  | ||||||
|     )?; |  | ||||||
|     let cfgs = if let Some(cfgs) = evaluated_cfgs { |  | ||||||
|         cfgs |  | ||||||
|     } else { |  | ||||||
|         let cfgs = process_cfg::collect_cfgs(syn::parse2(item.clone())?)?; |  | ||||||
|         if cfgs.cfgs_list.is_empty() { |  | ||||||
|             Cfgs::default() |  | ||||||
|         } else { |  | ||||||
|             return Ok(quote! { |  | ||||||
|                 ::fayalite::__cfg_expansion_helper! { |  | ||||||
|                     [] |  | ||||||
|                     #cfgs |  | ||||||
|                     {#[::fayalite::#kw(#attr)]} { #item } |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     let item = syn::parse2(quote! { #[#kw(#attr)] #item })?; |  | ||||||
|     let Some(item) = process_cfg::process_cfgs(item, cfgs)? else { |  | ||||||
|         return Ok(TokenStream::new()); |  | ||||||
|     }; |  | ||||||
|     match item { |     match item { | ||||||
|         Item::Enum(item) => hdl_enum::hdl_enum(item), |         Item::Enum(item) => hdl_enum::hdl_enum(item), | ||||||
|         Item::Struct(item) => hdl_bundle::hdl_bundle(item), |         Item::Struct(item) => hdl_bundle::hdl_bundle(item), | ||||||
|  | @ -1265,11 +921,3 @@ fn hdl_main( | ||||||
|         )), |         )), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> { |  | ||||||
|     hdl_main(kw::hdl_module::default(), attr, item) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub fn hdl_attr(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> { |  | ||||||
|     hdl_main(kw::hdl::default(), attr, item) |  | ||||||
| } |  | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -5,9 +5,6 @@ use std::{env, fs, path::Path}; | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
|     println!("cargo::rustc-check-cfg=cfg(todo)"); |     println!("cargo::rustc-check-cfg=cfg(todo)"); | ||||||
|     println!("cargo::rustc-check-cfg=cfg(cfg_false_for_tests)"); |  | ||||||
|     println!("cargo::rustc-check-cfg=cfg(cfg_true_for_tests)"); |  | ||||||
|     println!("cargo::rustc-cfg=cfg_true_for_tests"); |  | ||||||
|     let path = "visit_types.json"; |     let path = "visit_types.json"; | ||||||
|     println!("cargo::rerun-if-changed={path}"); |     println!("cargo::rerun-if-changed={path}"); | ||||||
|     println!("cargo::rerun-if-changed=build.rs"); |     println!("cargo::rerun-if-changed=build.rs"); | ||||||
|  |  | ||||||
|  | @ -4,14 +4,12 @@ | ||||||
| use crate::{ | use crate::{ | ||||||
|     expr::{ops::BundleLiteral, Expr, ToExpr}, |     expr::{ops::BundleLiteral, Expr, ToExpr}, | ||||||
|     intern::{Intern, Interned}, |     intern::{Intern, Interned}, | ||||||
|     sim::{SimValue, ToSimValue}, |  | ||||||
|     source_location::SourceLocation, |     source_location::SourceLocation, | ||||||
|     ty::{ |     ty::{ | ||||||
|         impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, StaticType, Type, |         impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, StaticType, Type, | ||||||
|         TypeProperties, TypeWithDeref, |         TypeProperties, TypeWithDeref, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| use bitvec::vec::BitVec; |  | ||||||
| use hashbrown::HashMap; | use hashbrown::HashMap; | ||||||
| use std::{fmt, marker::PhantomData}; | use std::{fmt, marker::PhantomData}; | ||||||
| 
 | 
 | ||||||
|  | @ -325,7 +323,7 @@ macro_rules! impl_tuple_builder_fields { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| macro_rules! impl_tuples { | macro_rules! impl_tuples { | ||||||
|     ([$({#[num = $num:literal, field = $field:ident, ty = $ty_var:ident: $Ty:ident] $var:ident: $T:ident})*] []) => { |     ([$({#[num = $num:literal, field = $field:ident] $var:ident: $T:ident})*] []) => { | ||||||
|         impl_tuple_builder_fields! { |         impl_tuple_builder_fields! { | ||||||
|             {} |             {} | ||||||
|             [$({ |             [$({ | ||||||
|  | @ -425,79 +423,6 @@ macro_rules! impl_tuples { | ||||||
|                 BundleLiteral::new(ty, field_values[..].intern()).to_expr() |                 BundleLiteral::new(ty, field_values[..].intern()).to_expr() | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<CanonicalType> for ($($T,)*) { |  | ||||||
|             #[track_caller] |  | ||||||
|             fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> { |  | ||||||
|                 ToSimValue::<Bundle>::to_sim_value(self, Bundle::from_canonical(ty)).into_canonical() |  | ||||||
|             } |  | ||||||
|             #[track_caller] |  | ||||||
|             fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType> |  | ||||||
|             { |  | ||||||
|                 ToSimValue::<Bundle>::into_sim_value(self, Bundle::from_canonical(ty)).into_canonical() |  | ||||||
|             } |  | ||||||
|             #[track_caller] |  | ||||||
|             fn box_into_sim_value(self: Box<Self>, ty: CanonicalType) -> SimValue<CanonicalType> { |  | ||||||
|                 ToSimValue::<Bundle>::box_into_sim_value(self, Bundle::from_canonical(ty)).into_canonical() |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<Bundle> for ($($T,)*) { |  | ||||||
|             #[track_caller] |  | ||||||
|             fn to_sim_value(&self, ty: Bundle) -> SimValue<Bundle> { |  | ||||||
|                 let ($($var,)*) = self; |  | ||||||
|                 let [$($ty_var,)*] = *ty.fields() else { |  | ||||||
|                     panic!("bundle has wrong number of fields"); |  | ||||||
|                 }; |  | ||||||
|                 $(let $var = $var.to_sim_value($ty_var.ty);)* |  | ||||||
|                 ToSimValue::into_sim_value(($($var,)*), ty) |  | ||||||
|             } |  | ||||||
|             #[track_caller] |  | ||||||
|             fn into_sim_value(self, ty: Bundle) -> SimValue<Bundle> { |  | ||||||
|                 #![allow(unused_mut)] |  | ||||||
|                 #![allow(clippy::unused_unit)] |  | ||||||
|                 let ($($var,)*) = self; |  | ||||||
|                 let [$($ty_var,)*] = *ty.fields() else { |  | ||||||
|                     panic!("bundle has wrong number of fields"); |  | ||||||
|                 }; |  | ||||||
|                 let mut bits: Option<BitVec> = None; |  | ||||||
|                 $(let $var = $var.into_sim_value($ty_var.ty); |  | ||||||
|                 assert_eq!($var.ty(), $ty_var.ty); |  | ||||||
|                 if !$var.bits().is_empty() { |  | ||||||
|                     if let Some(bits) = &mut bits { |  | ||||||
|                         bits.extend_from_bitslice($var.bits()); |  | ||||||
|                     } else { |  | ||||||
|                         let mut $var = $var.into_bits(); |  | ||||||
|                         $var.reserve(ty.type_properties().bit_width - $var.len()); |  | ||||||
|                         bits = Some($var); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 )* |  | ||||||
|                 bits.unwrap_or_else(BitVec::new).into_sim_value(ty) |  | ||||||
|             } |  | ||||||
|             #[track_caller] |  | ||||||
|             fn box_into_sim_value(self: Box<Self>, ty: Bundle) -> SimValue<Bundle> { |  | ||||||
|                 Self::into_sim_value(*self, ty) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         impl<$($T: ToSimValue<$Ty>, $Ty: Type,)*> ToSimValue<($($Ty,)*)> for ($($T,)*) { |  | ||||||
|             #[track_caller] |  | ||||||
|             fn to_sim_value(&self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> { |  | ||||||
|                 let ($($var,)*) = self; |  | ||||||
|                 let ($($ty_var,)*) = ty; |  | ||||||
|                 $(let $var = $var.to_sim_value($ty_var).into_canonical();)* |  | ||||||
|                 SimValue::from_canonical(ToSimValue::into_sim_value(($($var,)*), ty.canonical())) |  | ||||||
|             } |  | ||||||
|             #[track_caller] |  | ||||||
|             fn into_sim_value(self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> { |  | ||||||
|                 let ($($var,)*) = self; |  | ||||||
|                 let ($($ty_var,)*) = ty; |  | ||||||
|                 $(let $var = $var.into_sim_value($ty_var).into_canonical();)* |  | ||||||
|                 SimValue::from_canonical(ToSimValue::into_sim_value(($($var,)*), ty.canonical())) |  | ||||||
|             } |  | ||||||
|             #[track_caller] |  | ||||||
|             fn box_into_sim_value(self: Box<Self>, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> { |  | ||||||
|                 Self::into_sim_value(*self, ty) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }; |     }; | ||||||
|     ([$($lhs:tt)*] [$rhs_first:tt $($rhs:tt)*]) => { |     ([$($lhs:tt)*] [$rhs_first:tt $($rhs:tt)*]) => { | ||||||
|         impl_tuples!([$($lhs)*] []); |         impl_tuples!([$($lhs)*] []); | ||||||
|  | @ -507,18 +432,18 @@ macro_rules! impl_tuples { | ||||||
| 
 | 
 | ||||||
| impl_tuples! { | impl_tuples! { | ||||||
|     [] [ |     [] [ | ||||||
|         {#[num = 0, field = field_0, ty = ty0: Ty0] v0: T0} |         {#[num = 0, field = field_0] v0: T0} | ||||||
|         {#[num = 1, field = field_1, ty = ty1: Ty1] v1: T1} |         {#[num = 1, field = field_1] v1: T1} | ||||||
|         {#[num = 2, field = field_2, ty = ty2: Ty2] v2: T2} |         {#[num = 2, field = field_2] v2: T2} | ||||||
|         {#[num = 3, field = field_3, ty = ty3: Ty3] v3: T3} |         {#[num = 3, field = field_3] v3: T3} | ||||||
|         {#[num = 4, field = field_4, ty = ty4: Ty4] v4: T4} |         {#[num = 4, field = field_4] v4: T4} | ||||||
|         {#[num = 5, field = field_5, ty = ty5: Ty5] v5: T5} |         {#[num = 5, field = field_5] v5: T5} | ||||||
|         {#[num = 6, field = field_6, ty = ty6: Ty6] v6: T6} |         {#[num = 6, field = field_6] v6: T6} | ||||||
|         {#[num = 7, field = field_7, ty = ty7: Ty7] v7: T7} |         {#[num = 7, field = field_7] v7: T7} | ||||||
|         {#[num = 8, field = field_8, ty = ty8: Ty8] v8: T8} |         {#[num = 8, field = field_8] v8: T8} | ||||||
|         {#[num = 9, field = field_9, ty = ty9: Ty9] v9: T9} |         {#[num = 9, field = field_9] v9: T9} | ||||||
|         {#[num = 10, field = field_10, ty = ty10: Ty10] v10: T10} |         {#[num = 10, field = field_10] v10: T10} | ||||||
|         {#[num = 11, field = field_11, ty = ty11: Ty11] v11: T11} |         {#[num = 11, field = field_11] v11: T11} | ||||||
|     ] |     ] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -603,27 +528,3 @@ impl<T: ?Sized + Send + Sync + 'static> ToExpr for PhantomData<T> { | ||||||
|         BundleLiteral::new(PhantomData, Interned::default()).to_expr() |         BundleLiteral::new(PhantomData, Interned::default()).to_expr() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| impl<T: ?Sized + Send + Sync + 'static> ToSimValue<Self> for PhantomData<T> { |  | ||||||
|     #[track_caller] |  | ||||||
|     fn to_sim_value(&self, ty: Self) -> SimValue<Self> { |  | ||||||
|         ToSimValue::into_sim_value(BitVec::new(), ty) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl<T: ?Sized> ToSimValue<Bundle> for PhantomData<T> { |  | ||||||
|     #[track_caller] |  | ||||||
|     fn to_sim_value(&self, ty: Bundle) -> SimValue<Bundle> { |  | ||||||
|         assert!(ty.fields().is_empty()); |  | ||||||
|         ToSimValue::into_sim_value(BitVec::new(), ty) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl<T: ?Sized> ToSimValue<CanonicalType> for PhantomData<T> { |  | ||||||
|     #[track_caller] |  | ||||||
|     fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> { |  | ||||||
|         let ty = Bundle::from_canonical(ty); |  | ||||||
|         assert!(ty.fields().is_empty()); |  | ||||||
|         ToSimValue::into_sim_value(BitVec::new(), ty).into_canonical() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -11,59 +11,6 @@ extern crate self as fayalite; | ||||||
| #[doc(hidden)] | #[doc(hidden)] | ||||||
| pub use std as __std; | pub use std as __std; | ||||||
| 
 | 
 | ||||||
| #[doc(hidden)] |  | ||||||
| #[macro_export] |  | ||||||
| macro_rules! __cfg_expansion_helper { |  | ||||||
|     ( |  | ||||||
|         [ |  | ||||||
|             $($evaluated_cfgs:ident($($evaluated_exprs:tt)*) = $evaluated_results:ident,)* |  | ||||||
|         ] |  | ||||||
|         [ |  | ||||||
|             $cfg:ident($($expr:tt)*), |  | ||||||
|             $($unevaluated_cfgs:ident($($unevaluated_exprs:tt)*),)* |  | ||||||
|         ] |  | ||||||
|         // pass as tt so we get right span for attribute
 |  | ||||||
|         $after_evaluation_attr:tt $after_evaluation_body:tt |  | ||||||
|     ) => { |  | ||||||
|         #[$cfg($($expr)*)] |  | ||||||
|         $crate::__cfg_expansion_helper! { |  | ||||||
|             [ |  | ||||||
|                 $($evaluated_cfgs($($evaluated_exprs)*) = $evaluated_results,)* |  | ||||||
|                 $cfg($($expr)*) = true, |  | ||||||
|             ] |  | ||||||
|             [ |  | ||||||
|                 $($unevaluated_cfgs($($unevaluated_exprs)*),)* |  | ||||||
|             ] |  | ||||||
|             $after_evaluation_attr $after_evaluation_body |  | ||||||
|         } |  | ||||||
|         #[$cfg(not($($expr)*))] |  | ||||||
|         $crate::__cfg_expansion_helper! { |  | ||||||
|             [ |  | ||||||
|                 $($evaluated_cfgs($($evaluated_exprs)*) = $evaluated_results,)* |  | ||||||
|                 $cfg($($expr)*) = false, |  | ||||||
|             ] |  | ||||||
|             [ |  | ||||||
|                 $($unevaluated_cfgs($($unevaluated_exprs)*),)* |  | ||||||
|             ] |  | ||||||
|             $after_evaluation_attr $after_evaluation_body |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     ( |  | ||||||
|         [ |  | ||||||
|             $($evaluated_cfgs:ident($($evaluated_exprs:tt)*) = $evaluated_results:ident,)* |  | ||||||
|         ] |  | ||||||
|         [] |  | ||||||
|         // don't use #[...] so we get right span for `#` and `[]` of attribute
 |  | ||||||
|         {$($after_evaluation_attr:tt)*} {$($after_evaluation_body:tt)*} |  | ||||||
|     ) => { |  | ||||||
|         $($after_evaluation_attr)* |  | ||||||
|         #[__evaluated_cfgs([ |  | ||||||
|             $($evaluated_cfgs($($evaluated_exprs)*) = $evaluated_results,)* |  | ||||||
|         ])] |  | ||||||
|         $($after_evaluation_body)* |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[doc(inline)] | #[doc(inline)] | ||||||
| /// The `#[hdl_module]` attribute is applied to a Rust function so that that function creates
 | /// The `#[hdl_module]` attribute is applied to a Rust function so that that function creates
 | ||||||
| /// a [`Module`][`::fayalite::module::Module`] when called.
 | /// a [`Module`][`::fayalite::module::Module`] when called.
 | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -7,13 +7,12 @@ use fayalite::{ | ||||||
|     clock::{Clock, ClockDomain}, |     clock::{Clock, ClockDomain}, | ||||||
|     expr::{CastTo, HdlPartialEq}, |     expr::{CastTo, HdlPartialEq}, | ||||||
|     firrtl::ExportOptions, |     firrtl::ExportOptions, | ||||||
|     formal::{any_const, any_seq, formal_reset, hdl_assert, hdl_assume}, |     formal::{any_seq, formal_reset, hdl_assert, hdl_assume}, | ||||||
|     hdl, hdl_module, |     hdl_module, | ||||||
|     int::{Bool, DynSize, Size, UInt, UIntType}, |     int::{Bool, UInt}, | ||||||
|     module::{connect, connect_any, instance, memory, reg_builder, wire}, |     module::{connect, connect_any, reg_builder, wire}, | ||||||
|     reset::ToReset, |     reset::ToReset, | ||||||
|     testing::assert_formal, |     testing::assert_formal, | ||||||
|     ty::StaticType, |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// Test hidden state
 | /// Test hidden state
 | ||||||
|  | @ -132,164 +131,3 @@ mod hidden_state { | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /// Formal verification of designs containing memories
 |  | ||||||
| ///
 |  | ||||||
| /// There is a trick for memories, described in the [Zipcpu blog].
 |  | ||||||
| /// First, select a fixed but arbitrary memory address, monitoring all reads
 |  | ||||||
| /// and writes made to it. Then, assert that anything read from that location
 |  | ||||||
| /// matches the last stored value.
 |  | ||||||
| ///
 |  | ||||||
| /// A difficulty for induction is that the memory represents [hidden_state]. A
 |  | ||||||
| /// solution is to include an additional read port to the memory and assert
 |  | ||||||
| /// that the memory location effectively contains the last stored value.
 |  | ||||||
| /// This additional debug port is present only to assist the proof and is
 |  | ||||||
| /// unused (optimized out) in actual use.
 |  | ||||||
| ///
 |  | ||||||
| /// [Zipcpu blog]: <https://zipcpu.com/zipcpu/2018/07/13/memories.html>
 |  | ||||||
| mod memory { |  | ||||||
|     use super::*; |  | ||||||
| 
 |  | ||||||
|     /// Test a simple 8-bit SRAM model
 |  | ||||||
|     #[test] |  | ||||||
|     fn test_sram() { |  | ||||||
|         #[hdl] |  | ||||||
|         struct WritePort<AddrWidth: Size> { |  | ||||||
|             addr: UIntType<AddrWidth>, |  | ||||||
|             data: UInt<8>, |  | ||||||
|             en: Bool, |  | ||||||
|         } |  | ||||||
|         #[hdl] |  | ||||||
|         struct ReadPort<AddrWidth: Size> { |  | ||||||
|             addr: UIntType<AddrWidth>, |  | ||||||
|             #[hdl(flip)] |  | ||||||
|             data: UInt<8>, |  | ||||||
|         } |  | ||||||
|         /// This debug port is only meant to assist the proof.
 |  | ||||||
|         /// For normal use in a design, a wrapper could be provided,
 |  | ||||||
|         /// omitting this port.
 |  | ||||||
|         /// The implementation is forbidden to use any information
 |  | ||||||
|         /// provided on this port in its internal workings.
 |  | ||||||
|         #[hdl] |  | ||||||
|         struct DebugPort<AddrWidth: Size> { |  | ||||||
|             selected: UIntType<AddrWidth>, |  | ||||||
|             stored: UInt<8>, |  | ||||||
|             wrote: Bool, |  | ||||||
|         } |  | ||||||
|         /// simple 1R1W SRAM model (one asynchronous read port and one
 |  | ||||||
|         /// independent write port) with `n`-bit address width
 |  | ||||||
|         #[hdl_module] |  | ||||||
|         fn example_sram(n: usize) { |  | ||||||
|             #[hdl] |  | ||||||
|             let wr: WritePort<DynSize> = m.input(WritePort[n]); |  | ||||||
|             #[hdl] |  | ||||||
|             let rd: ReadPort<DynSize> = m.input(ReadPort[n]); |  | ||||||
|             #[hdl] |  | ||||||
|             let cd: ClockDomain = m.input(); |  | ||||||
| 
 |  | ||||||
|             // declare and connect the backing memory
 |  | ||||||
|             #[hdl] |  | ||||||
|             let mut mem = memory(); |  | ||||||
|             mem.depth(1 << n); |  | ||||||
|             let read_port = mem.new_read_port(); |  | ||||||
|             let write_port = mem.new_write_port(); |  | ||||||
|             connect(write_port.clk, cd.clk); |  | ||||||
|             connect(write_port.addr, wr.addr); |  | ||||||
|             connect(write_port.en, wr.en); |  | ||||||
|             connect(write_port.data, wr.data); |  | ||||||
|             connect(write_port.mask, true); |  | ||||||
|             connect(read_port.clk, cd.clk); |  | ||||||
|             connect(read_port.addr, rd.addr); |  | ||||||
|             connect(read_port.en, true); |  | ||||||
|             connect(rd.data, read_port.data); |  | ||||||
| 
 |  | ||||||
|             // To assist with induction, ensure that the chosen memory location
 |  | ||||||
|             // really contains, always, the last value written to it.
 |  | ||||||
|             #[hdl] |  | ||||||
|             let dbg: DebugPort<DynSize> = m.input(DebugPort[n]); |  | ||||||
|             let debug_port = mem.new_read_port(); |  | ||||||
|             connect(debug_port.en, true); |  | ||||||
|             connect(debug_port.clk, cd.clk); |  | ||||||
|             connect(debug_port.addr, dbg.selected); |  | ||||||
|             #[hdl] |  | ||||||
|             if dbg.wrote { |  | ||||||
|                 hdl_assert(cd.clk, debug_port.data.cmp_eq(dbg.stored), ""); |  | ||||||
|                 // Try commenting out the assert above, induction will fail.
 |  | ||||||
|                 // Opening the trace, it can be seen that the memory contents
 |  | ||||||
|                 // and the stored value don't match, which is an unreachable
 |  | ||||||
|                 // state. By asserting the above, it will become invalid
 |  | ||||||
|                 // as well, so induction will skip this kind of situation.
 |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /// formal verification of the SRAM module, parametrized by the
 |  | ||||||
|         /// address bit-width
 |  | ||||||
|         #[hdl_module] |  | ||||||
|         fn test_module(n: usize) { |  | ||||||
|             #[hdl] |  | ||||||
|             let clk: Clock = m.input(); |  | ||||||
|             let cd = #[hdl] |  | ||||||
|             ClockDomain { |  | ||||||
|                 clk, |  | ||||||
|                 rst: formal_reset().to_reset(), |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|             // instantiate the SRAM model, connecting its inputs to
 |  | ||||||
|             // a random sequence
 |  | ||||||
|             #[hdl] |  | ||||||
|             let rd: ReadPort<DynSize> = wire(ReadPort[n]); |  | ||||||
|             connect(rd.addr, any_seq(UInt[n])); |  | ||||||
|             #[hdl] |  | ||||||
|             let wr: WritePort<DynSize> = wire(WritePort[n]); |  | ||||||
|             connect(wr.addr, any_seq(UInt[n])); |  | ||||||
|             connect(wr.data, any_seq(UInt::<8>::TYPE)); |  | ||||||
|             connect(wr.en, any_seq(Bool)); |  | ||||||
|             #[hdl] |  | ||||||
|             let dut = instance(example_sram(n)); |  | ||||||
|             connect(dut.cd, cd); |  | ||||||
|             connect(dut.rd, rd); |  | ||||||
|             connect(dut.wr, wr); |  | ||||||
| 
 |  | ||||||
|             // select a fixed but arbitrary test address
 |  | ||||||
|             #[hdl] |  | ||||||
|             let selected = wire(UInt[n]); |  | ||||||
|             connect(selected, any_const(UInt[n])); |  | ||||||
|             // store the last value written to that address
 |  | ||||||
|             #[hdl] |  | ||||||
|             let stored: UInt<8> = reg_builder().clock_domain(cd).reset(0u8); |  | ||||||
|             // since memories are not initialized, track whether we wrote to the
 |  | ||||||
|             // memory at least once
 |  | ||||||
|             #[hdl] |  | ||||||
|             let wrote: Bool = reg_builder().clock_domain(cd).reset(false); |  | ||||||
|             // on a write, capture the last written value
 |  | ||||||
|             #[hdl] |  | ||||||
|             if wr.en & wr.addr.cmp_eq(selected) { |  | ||||||
|                 connect(stored, wr.data); |  | ||||||
|                 connect(wrote, true); |  | ||||||
|             } |  | ||||||
|             // on a read, assert that the read value is the same which was stored
 |  | ||||||
|             #[hdl] |  | ||||||
|             if rd.addr.cmp_eq(selected) & wrote { |  | ||||||
|                 hdl_assert(clk, rd.data.cmp_eq(stored), ""); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // to assist induction, pass our state to the underlying instance
 |  | ||||||
|             let dbg = #[hdl] |  | ||||||
|             DebugPort { |  | ||||||
|                 selected, |  | ||||||
|                 stored, |  | ||||||
|                 wrote, |  | ||||||
|             }; |  | ||||||
|             connect(dut.dbg, dbg); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         assert_formal( |  | ||||||
|             "sram", |  | ||||||
|             test_module(8), |  | ||||||
|             FormalMode::Prove, |  | ||||||
|             2, |  | ||||||
|             None, |  | ||||||
|             ExportOptions::default(), |  | ||||||
|         ); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -4287,61 +4287,3 @@ circuit check_deduce_resets: | ||||||
| ",
 | ",
 | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // intentionally not outline_generated to ensure we get correct macro hygiene
 |  | ||||||
| #[hdl_module] |  | ||||||
| pub fn check_cfgs<#[cfg(cfg_false_for_tests)] A: Type, #[cfg(cfg_true_for_tests)] B: Type>( |  | ||||||
|     #[cfg(cfg_false_for_tests)] a: A, |  | ||||||
|     #[cfg(cfg_true_for_tests)] b: B, |  | ||||||
| ) { |  | ||||||
|     #[hdl] |  | ||||||
|     struct S<#[cfg(cfg_false_for_tests)] A, #[cfg(cfg_true_for_tests)] B> { |  | ||||||
|         #[cfg(cfg_false_for_tests)] |  | ||||||
|         a: A, |  | ||||||
|         #[cfg(cfg_true_for_tests)] |  | ||||||
|         b: B, |  | ||||||
|     } |  | ||||||
|     #[hdl] |  | ||||||
|     #[cfg(cfg_false_for_tests)] |  | ||||||
|     let i_a: A = m.input(a); |  | ||||||
|     #[hdl] |  | ||||||
|     #[cfg(cfg_true_for_tests)] |  | ||||||
|     let i_b: B = m.input(b); |  | ||||||
|     #[hdl] |  | ||||||
|     let w: S<UInt<8>> = wire(); |  | ||||||
|     #[cfg(cfg_false_for_tests)] |  | ||||||
|     { |  | ||||||
|         #[hdl] |  | ||||||
|         let o_a: A = m.output(a); |  | ||||||
|         connect(o_a, w.a.cast_bits_to(a)); |  | ||||||
|         connect_any(w.a, i_a.cast_to_bits()); |  | ||||||
|     } |  | ||||||
|     #[cfg(cfg_true_for_tests)] |  | ||||||
|     { |  | ||||||
|         #[hdl] |  | ||||||
|         let o_b: B = m.output(b); |  | ||||||
|         connect(o_b, w.b.cast_bits_to(b)); |  | ||||||
|         connect_any(w.b, i_b.cast_to_bits()); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[test] |  | ||||||
| fn test_cfgs() { |  | ||||||
|     let _n = SourceLocation::normalize_files_for_tests(); |  | ||||||
|     let m = check_cfgs(UInt[8]); |  | ||||||
|     dbg!(m); |  | ||||||
|     #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
 |  | ||||||
|     assert_export_firrtl! { |  | ||||||
|         m => |  | ||||||
|         "/test/check_cfgs.fir": r"FIRRTL version 3.2.0
 |  | ||||||
| circuit check_cfgs: |  | ||||||
|     type Ty0 = {b: UInt<8>} |  | ||||||
|     module check_cfgs: @[the_test_file.rs 9962:1] |  | ||||||
|         input i_b: UInt<8> @[the_test_file.rs 9979:20] |  | ||||||
|         output o_b: UInt<8> @[the_test_file.rs 9992:24] |  | ||||||
|         wire w: Ty0 @[the_test_file.rs 9981:25] |  | ||||||
|         connect o_b, w.b @[the_test_file.rs 9993:9] |  | ||||||
|         connect w.b, i_b @[the_test_file.rs 9994:9] |  | ||||||
| ",
 |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -5,8 +5,7 @@ use fayalite::{ | ||||||
|     int::UIntValue, |     int::UIntValue, | ||||||
|     prelude::*, |     prelude::*, | ||||||
|     reset::ResetType, |     reset::ResetType, | ||||||
|     sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation, ToSimValue}, |     sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation}, | ||||||
|     ty::StaticType, |  | ||||||
|     util::RcWriter, |     util::RcWriter, | ||||||
| }; | }; | ||||||
| use std::num::NonZeroUsize; | use std::num::NonZeroUsize; | ||||||
|  | @ -255,14 +254,8 @@ fn test_shift_register() { | ||||||
|     let mut sim = Simulation::new(shift_register()); |     let mut sim = Simulation::new(shift_register()); | ||||||
|     let mut writer = RcWriter::default(); |     let mut writer = RcWriter::default(); | ||||||
|     sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); |     sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); | ||||||
|     sim.write( |     sim.write_clock(sim.io().cd.clk, false); | ||||||
|         sim.io().cd, |     sim.write_reset(sim.io().cd.rst, true); | ||||||
|         #[hdl] |  | ||||||
|         ClockDomain { |  | ||||||
|             clk: false.to_clock(), |  | ||||||
|             rst: true.to_sync_reset(), |  | ||||||
|         }, |  | ||||||
|     ); |  | ||||||
|     sim.write_bool(sim.io().d, false); |     sim.write_bool(sim.io().d, false); | ||||||
|     sim.advance_time(SimDuration::from_micros(1)); |     sim.advance_time(SimDuration::from_micros(1)); | ||||||
|     sim.write_clock(sim.io().cd.clk, true); |     sim.write_clock(sim.io().cd.clk, true); | ||||||
|  | @ -278,7 +271,7 @@ fn test_shift_register() { | ||||||
|                 assert_eq!( |                 assert_eq!( | ||||||
|                     *expected, |                     *expected, | ||||||
|                     sim.read_bool(sim.io().q), |                     sim.read_bool(sim.io().q), | ||||||
|                     "vcd:\n{}\ncycle: {cycle}", |                     "cycle: {cycle}\nvcd:\n{}", | ||||||
|                     String::from_utf8(writer.take()).unwrap(), |                     String::from_utf8(writer.take()).unwrap(), | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|  | @ -316,8 +309,6 @@ pub fn enums() { | ||||||
|     let which_out: UInt<2> = m.output(); |     let which_out: UInt<2> = m.output(); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let data_out: UInt<4> = m.output(); |     let data_out: UInt<4> = m.output(); | ||||||
|     #[hdl] |  | ||||||
|     let b_out: HdlOption<(UInt<1>, Bool)> = m.output(); |  | ||||||
| 
 | 
 | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     struct MyStruct<T> { |     struct MyStruct<T> { | ||||||
|  | @ -357,8 +348,6 @@ pub fn enums() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     connect(b_out, HdlNone()); |  | ||||||
| 
 |  | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     match the_reg { |     match the_reg { | ||||||
|         MyEnum::A => { |         MyEnum::A => { | ||||||
|  | @ -368,7 +357,6 @@ pub fn enums() { | ||||||
|         MyEnum::B(v) => { |         MyEnum::B(v) => { | ||||||
|             connect(which_out, 1_hdl_u2); |             connect(which_out, 1_hdl_u2); | ||||||
|             connect_any(data_out, v.0 | (v.1.cast_to_static::<UInt<1>>() << 1)); |             connect_any(data_out, v.0 | (v.1.cast_to_static::<UInt<1>>() << 1)); | ||||||
|             connect(b_out, HdlSome(v)); |  | ||||||
|         } |         } | ||||||
|         MyEnum::C(v) => { |         MyEnum::C(v) => { | ||||||
|             connect(which_out, 2_hdl_u2); |             connect(which_out, 2_hdl_u2); | ||||||
|  | @ -394,33 +382,13 @@ fn test_enums() { | ||||||
|     sim.advance_time(SimDuration::from_nanos(100)); |     sim.advance_time(SimDuration::from_nanos(100)); | ||||||
|     sim.write_reset(sim.io().cd.rst, false); |     sim.write_reset(sim.io().cd.rst, false); | ||||||
|     sim.advance_time(SimDuration::from_nanos(900)); |     sim.advance_time(SimDuration::from_nanos(900)); | ||||||
|     type BOutTy = HdlOption<(UInt<1>, Bool)>; |     #[derive(Debug, PartialEq, Eq)] | ||||||
|     #[derive(Debug)] |  | ||||||
|     struct IO { |     struct IO { | ||||||
|         en: bool, |         en: bool, | ||||||
|         which_in: u8, |         which_in: u8, | ||||||
|         data_in: u8, |         data_in: u8, | ||||||
|         which_out: u8, |         which_out: u8, | ||||||
|         data_out: u8, |         data_out: u8, | ||||||
|         b_out: Expr<BOutTy>, |  | ||||||
|     } |  | ||||||
|     impl PartialEq for IO { |  | ||||||
|         fn eq(&self, other: &Self) -> bool { |  | ||||||
|             let Self { |  | ||||||
|                 en, |  | ||||||
|                 which_in, |  | ||||||
|                 data_in, |  | ||||||
|                 which_out, |  | ||||||
|                 data_out, |  | ||||||
|                 b_out, |  | ||||||
|             } = *self; |  | ||||||
|             en == other.en |  | ||||||
|                 && which_in == other.which_in |  | ||||||
|                 && data_in == other.data_in |  | ||||||
|                 && which_out == other.which_out |  | ||||||
|                 && data_out == other.data_out |  | ||||||
|                 && b_out.to_sim_value(BOutTy::TYPE) == other.b_out.to_sim_value(BOutTy::TYPE) |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     let io_cycles = [ |     let io_cycles = [ | ||||||
|         IO { |         IO { | ||||||
|  | @ -429,7 +397,6 @@ fn test_enums() { | ||||||
|             data_in: 0, |             data_in: 0, | ||||||
|             which_out: 0, |             which_out: 0, | ||||||
|             data_out: 0, |             data_out: 0, | ||||||
|             b_out: HdlNone(), |  | ||||||
|         }, |         }, | ||||||
|         IO { |         IO { | ||||||
|             en: true, |             en: true, | ||||||
|  | @ -437,7 +404,6 @@ fn test_enums() { | ||||||
|             data_in: 0, |             data_in: 0, | ||||||
|             which_out: 0, |             which_out: 0, | ||||||
|             data_out: 0, |             data_out: 0, | ||||||
|             b_out: HdlNone(), |  | ||||||
|         }, |         }, | ||||||
|         IO { |         IO { | ||||||
|             en: false, |             en: false, | ||||||
|  | @ -445,7 +411,6 @@ fn test_enums() { | ||||||
|             data_in: 0, |             data_in: 0, | ||||||
|             which_out: 1, |             which_out: 1, | ||||||
|             data_out: 0, |             data_out: 0, | ||||||
|             b_out: HdlSome((0_hdl_u1, false)), |  | ||||||
|         }, |         }, | ||||||
|         IO { |         IO { | ||||||
|             en: true, |             en: true, | ||||||
|  | @ -453,7 +418,6 @@ fn test_enums() { | ||||||
|             data_in: 0xF, |             data_in: 0xF, | ||||||
|             which_out: 1, |             which_out: 1, | ||||||
|             data_out: 0, |             data_out: 0, | ||||||
|             b_out: HdlSome((0_hdl_u1, false)), |  | ||||||
|         }, |         }, | ||||||
|         IO { |         IO { | ||||||
|             en: true, |             en: true, | ||||||
|  | @ -461,7 +425,6 @@ fn test_enums() { | ||||||
|             data_in: 0xF, |             data_in: 0xF, | ||||||
|             which_out: 1, |             which_out: 1, | ||||||
|             data_out: 0x3, |             data_out: 0x3, | ||||||
|             b_out: HdlSome((1_hdl_u1, true)), |  | ||||||
|         }, |         }, | ||||||
|         IO { |         IO { | ||||||
|             en: true, |             en: true, | ||||||
|  | @ -469,7 +432,6 @@ fn test_enums() { | ||||||
|             data_in: 0xF, |             data_in: 0xF, | ||||||
|             which_out: 1, |             which_out: 1, | ||||||
|             data_out: 0x3, |             data_out: 0x3, | ||||||
|             b_out: HdlSome((1_hdl_u1, true)), |  | ||||||
|         }, |         }, | ||||||
|         IO { |         IO { | ||||||
|             en: true, |             en: true, | ||||||
|  | @ -477,7 +439,6 @@ fn test_enums() { | ||||||
|             data_in: 0xF, |             data_in: 0xF, | ||||||
|             which_out: 2, |             which_out: 2, | ||||||
|             data_out: 0xF, |             data_out: 0xF, | ||||||
|             b_out: HdlNone(), |  | ||||||
|         }, |         }, | ||||||
|     ]; |     ]; | ||||||
|     for ( |     for ( | ||||||
|  | @ -488,7 +449,6 @@ fn test_enums() { | ||||||
|             data_in, |             data_in, | ||||||
|             which_out: _, |             which_out: _, | ||||||
|             data_out: _, |             data_out: _, | ||||||
|             b_out: _, |  | ||||||
|         }, |         }, | ||||||
|     ) in io_cycles.into_iter().enumerate() |     ) in io_cycles.into_iter().enumerate() | ||||||
|     { |     { | ||||||
|  | @ -509,12 +469,11 @@ fn test_enums() { | ||||||
|                 .to_bigint() |                 .to_bigint() | ||||||
|                 .try_into() |                 .try_into() | ||||||
|                 .expect("known to be in range"), |                 .expect("known to be in range"), | ||||||
|             b_out: sim.read(sim.io().b_out).to_expr(), |  | ||||||
|         }; |         }; | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             expected, |             expected, | ||||||
|             io, |             io, | ||||||
|             "vcd:\n{}\ncycle: {cycle}", |             "cycle: {cycle}\nvcd:\n{}", | ||||||
|             String::from_utf8(writer.take()).unwrap(), |             String::from_utf8(writer.take()).unwrap(), | ||||||
|         ); |         ); | ||||||
|         sim.write_clock(sim.io().cd.clk, false); |         sim.write_clock(sim.io().cd.clk, false); | ||||||
|  | @ -712,7 +671,7 @@ fn test_memories() { | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             expected, |             expected, | ||||||
|             io, |             io, | ||||||
|             "vcd:\n{}\ncycle: {cycle}", |             "cycle: {cycle}\nvcd:\n{}", | ||||||
|             String::from_utf8(writer.take()).unwrap(), |             String::from_utf8(writer.take()).unwrap(), | ||||||
|         ); |         ); | ||||||
|         sim.advance_time(SimDuration::from_micros(1)); |         sim.advance_time(SimDuration::from_micros(1)); | ||||||
|  | @ -735,514 +694,4 @@ fn test_memories() { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl_module(outline_generated)] | // TODO: add more tests for memories
 | ||||||
| pub fn memories2() { |  | ||||||
|     #[hdl] |  | ||||||
|     let rw: fayalite::memory::ReadWriteStruct<UInt<2>, ConstUsize<3>> = m.input(); |  | ||||||
|     #[hdl] |  | ||||||
|     let mut mem = memory_with_init([HdlSome(true); 5]); |  | ||||||
|     mem.read_latency(1); |  | ||||||
|     mem.write_latency(NonZeroUsize::new(1).unwrap()); |  | ||||||
|     mem.read_under_write(ReadUnderWrite::New); |  | ||||||
|     let rw_port = mem.new_rw_port(); |  | ||||||
|     connect_any(rw_port.addr, rw.addr); |  | ||||||
|     connect(rw_port.en, rw.en); |  | ||||||
|     connect(rw_port.clk, rw.clk); |  | ||||||
|     connect_any(rw.rdata, rw_port.rdata.cast_to_bits()); |  | ||||||
|     connect(rw_port.wmode, rw.wmode); |  | ||||||
|     connect(rw_port.wdata, HdlNone()); |  | ||||||
|     #[hdl] |  | ||||||
|     if rw.wdata[0] { |  | ||||||
|         connect(rw_port.wdata, HdlSome(rw.wdata[1])); |  | ||||||
|     } |  | ||||||
|     connect(rw_port.wmask, rw.wmask); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[hdl] |  | ||||||
| #[test] |  | ||||||
| fn test_memories2() { |  | ||||||
|     let _n = SourceLocation::normalize_files_for_tests(); |  | ||||||
|     let mut sim = Simulation::new(memories2()); |  | ||||||
|     let mut writer = RcWriter::default(); |  | ||||||
|     sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); |  | ||||||
|     sim.write_clock(sim.io().rw.clk, false); |  | ||||||
|     #[derive(Debug, PartialEq, Eq)] |  | ||||||
|     struct IO { |  | ||||||
|         addr: u8, |  | ||||||
|         en: bool, |  | ||||||
|         rdata: u8, |  | ||||||
|         wmode: bool, |  | ||||||
|         wdata: u8, |  | ||||||
|         wmask: bool, |  | ||||||
|     } |  | ||||||
|     let io_cycles = [ |  | ||||||
|         IO { |  | ||||||
|             addr: 0, |  | ||||||
|             en: false, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 0, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0x3, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 0, |  | ||||||
|             en: false, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 0, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: true, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: true, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 0, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 0, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: true, |  | ||||||
|             wdata: 3, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 1, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: true, |  | ||||||
|             wdata: 1, |  | ||||||
|             wmask: true, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 2, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: true, |  | ||||||
|             wdata: 2, |  | ||||||
|             wmask: true, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 3, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: true, |  | ||||||
|             wdata: 3, |  | ||||||
|             wmask: true, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 4, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: true, |  | ||||||
|             wdata: 2, |  | ||||||
|             wmask: true, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 5, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: true, |  | ||||||
|             wdata: 1, |  | ||||||
|             wmask: true, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 6, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: true, |  | ||||||
|             wdata: 1, |  | ||||||
|             wmask: true, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 7, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: true, |  | ||||||
|             wdata: 1, |  | ||||||
|             wmask: true, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 7, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 6, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 5, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 4, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 3, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 3, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 2, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 0, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 1, |  | ||||||
|             en: true, |  | ||||||
|             rdata: 1, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             addr: 0, |  | ||||||
|             en: false, |  | ||||||
|             rdata: 0, |  | ||||||
|             wmode: false, |  | ||||||
|             wdata: 0, |  | ||||||
|             wmask: false, |  | ||||||
|         }, |  | ||||||
|     ]; |  | ||||||
|     for ( |  | ||||||
|         cycle, |  | ||||||
|         expected @ IO { |  | ||||||
|             addr, |  | ||||||
|             en, |  | ||||||
|             rdata: _, |  | ||||||
|             wmode, |  | ||||||
|             wdata, |  | ||||||
|             wmask, |  | ||||||
|         }, |  | ||||||
|     ) in io_cycles.into_iter().enumerate() |  | ||||||
|     { |  | ||||||
|         sim.write_bool_or_int(sim.io().rw.addr, addr.cast_to_static()); |  | ||||||
|         sim.write_bool(sim.io().rw.en, en); |  | ||||||
|         sim.write_bool(sim.io().rw.wmode, wmode); |  | ||||||
|         sim.write_bool_or_int(sim.io().rw.wdata, wdata.cast_to_static()); |  | ||||||
|         sim.write_bool(sim.io().rw.wmask, wmask); |  | ||||||
|         sim.advance_time(SimDuration::from_nanos(250)); |  | ||||||
|         sim.write_clock(sim.io().rw.clk, true); |  | ||||||
|         sim.advance_time(SimDuration::from_nanos(250)); |  | ||||||
|         let io = IO { |  | ||||||
|             addr, |  | ||||||
|             en, |  | ||||||
|             rdata: sim |  | ||||||
|                 .read_bool_or_int(sim.io().rw.rdata) |  | ||||||
|                 .to_bigint() |  | ||||||
|                 .try_into() |  | ||||||
|                 .expect("known to be in range"), |  | ||||||
|             wmode, |  | ||||||
|             wdata, |  | ||||||
|             wmask, |  | ||||||
|         }; |  | ||||||
|         assert_eq!( |  | ||||||
|             expected, |  | ||||||
|             io, |  | ||||||
|             "vcd:\n{}\ncycle: {cycle}", |  | ||||||
|             String::from_utf8(writer.take()).unwrap(), |  | ||||||
|         ); |  | ||||||
|         sim.advance_time(SimDuration::from_nanos(250)); |  | ||||||
|         sim.write_clock(sim.io().rw.clk, false); |  | ||||||
|         sim.advance_time(SimDuration::from_nanos(250)); |  | ||||||
|     } |  | ||||||
|     sim.flush_traces().unwrap(); |  | ||||||
|     let vcd = String::from_utf8(writer.take()).unwrap(); |  | ||||||
|     println!("####### VCD:\n{vcd}\n#######"); |  | ||||||
|     if vcd != include_str!("sim/expected/memories2.vcd") { |  | ||||||
|         panic!(); |  | ||||||
|     } |  | ||||||
|     let sim_debug = format!("{sim:#?}"); |  | ||||||
|     println!("#######\n{sim_debug}\n#######"); |  | ||||||
|     if sim_debug != include_str!("sim/expected/memories2.txt") { |  | ||||||
|         panic!(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[hdl_module(outline_generated)] |  | ||||||
| pub fn memories3() { |  | ||||||
|     #[hdl] |  | ||||||
|     let r: fayalite::memory::ReadStruct<Array<UInt<8>, 8>, ConstUsize<3>> = m.input(); |  | ||||||
|     #[hdl] |  | ||||||
|     let w: fayalite::memory::WriteStruct<Array<UInt<8>, 8>, ConstUsize<3>> = m.input(); |  | ||||||
|     #[hdl] |  | ||||||
|     let mut mem: MemBuilder<Array<UInt<8>, 8>> = memory(); |  | ||||||
|     mem.depth(8); |  | ||||||
|     mem.read_latency(2); |  | ||||||
|     mem.write_latency(NonZeroUsize::new(2).unwrap()); |  | ||||||
|     mem.read_under_write(ReadUnderWrite::Old); |  | ||||||
|     connect_any(mem.new_read_port(), r); |  | ||||||
|     connect_any(mem.new_write_port(), w); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[hdl] |  | ||||||
| #[test] |  | ||||||
| fn test_memories3() { |  | ||||||
|     let _n = SourceLocation::normalize_files_for_tests(); |  | ||||||
|     let mut sim = Simulation::new(memories3()); |  | ||||||
|     let mut writer = RcWriter::default(); |  | ||||||
|     sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); |  | ||||||
|     sim.write_clock(sim.io().r.clk, false); |  | ||||||
|     sim.write_clock(sim.io().w.clk, false); |  | ||||||
|     #[derive(Debug, PartialEq, Eq, Clone, Copy)] |  | ||||||
|     struct IO { |  | ||||||
|         r_addr: u8, |  | ||||||
|         r_en: bool, |  | ||||||
|         r_data: [u8; 8], |  | ||||||
|         w_addr: u8, |  | ||||||
|         w_en: bool, |  | ||||||
|         w_data: [u8; 8], |  | ||||||
|         w_mask: [bool; 8], |  | ||||||
|     } |  | ||||||
|     let io_cycles = [ |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: false, |  | ||||||
|             r_data: [0; 8], |  | ||||||
|             w_addr: 0, |  | ||||||
|             w_en: true, |  | ||||||
|             w_data: [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0], |  | ||||||
|             w_mask: [false, true, false, true, true, false, false, true], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: true, |  | ||||||
|             r_data: [0; 8], |  | ||||||
|             w_addr: 1, |  | ||||||
|             w_en: false, |  | ||||||
|             w_data: [0; 8], |  | ||||||
|             w_mask: [false; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: true, |  | ||||||
|             r_data: [0, 0x34, 0, 0x78, 0x9A, 0, 0, 0xF0], |  | ||||||
|             w_addr: 1, |  | ||||||
|             w_en: false, |  | ||||||
|             w_data: [0; 8], |  | ||||||
|             w_mask: [false; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: true, |  | ||||||
|             r_data: [0, 0x34, 0, 0x78, 0x9A, 0, 0, 0xF0], |  | ||||||
|             w_addr: 0, |  | ||||||
|             w_en: true, |  | ||||||
|             w_data: [0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10], |  | ||||||
|             w_mask: [true; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: true, |  | ||||||
|             r_data: [0, 0x34, 0, 0x78, 0x9A, 0, 0, 0xF0], |  | ||||||
|             w_addr: 0, |  | ||||||
|             w_en: true, |  | ||||||
|             w_data: [0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10], |  | ||||||
|             w_mask: [true; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: true, |  | ||||||
|             r_data: [0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10], |  | ||||||
|             w_addr: 0, |  | ||||||
|             w_en: true, |  | ||||||
|             w_data: [0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10], |  | ||||||
|             w_mask: [true; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: false, |  | ||||||
|             r_data: [0; 8], |  | ||||||
|             w_addr: 1, |  | ||||||
|             w_en: true, |  | ||||||
|             w_data: [0x13, 0x57, 0x9B, 0xDF, 0x02, 0x46, 0x8A, 0xCE], |  | ||||||
|             w_mask: [true; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: false, |  | ||||||
|             r_data: [0; 8], |  | ||||||
|             w_addr: 2, |  | ||||||
|             w_en: true, |  | ||||||
|             w_data: *b"testing!", |  | ||||||
|             w_mask: [true; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: false, |  | ||||||
|             r_data: [0; 8], |  | ||||||
|             w_addr: 3, |  | ||||||
|             w_en: true, |  | ||||||
|             w_data: *b"more tst", |  | ||||||
|             w_mask: [true; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 0, |  | ||||||
|             r_en: true, |  | ||||||
|             r_data: [0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10], |  | ||||||
|             w_addr: 0, |  | ||||||
|             w_en: false, |  | ||||||
|             w_data: [0; 8], |  | ||||||
|             w_mask: [false; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 1, |  | ||||||
|             r_en: true, |  | ||||||
|             r_data: [0x13, 0x57, 0x9B, 0xDF, 0x02, 0x46, 0x8A, 0xCE], |  | ||||||
|             w_addr: 0, |  | ||||||
|             w_en: false, |  | ||||||
|             w_data: [0; 8], |  | ||||||
|             w_mask: [false; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 2, |  | ||||||
|             r_en: true, |  | ||||||
|             r_data: *b"testing!", |  | ||||||
|             w_addr: 0, |  | ||||||
|             w_en: false, |  | ||||||
|             w_data: [0; 8], |  | ||||||
|             w_mask: [false; 8], |  | ||||||
|         }, |  | ||||||
|         IO { |  | ||||||
|             r_addr: 3, |  | ||||||
|             r_en: true, |  | ||||||
|             r_data: *b"more tst", |  | ||||||
|             w_addr: 0, |  | ||||||
|             w_en: false, |  | ||||||
|             w_data: [0; 8], |  | ||||||
|             w_mask: [false; 8], |  | ||||||
|         }, |  | ||||||
|     ]; |  | ||||||
|     for cycle in 0..io_cycles.len() + 2 { |  | ||||||
|         { |  | ||||||
|             let IO { |  | ||||||
|                 r_addr, |  | ||||||
|                 r_en, |  | ||||||
|                 r_data: _, |  | ||||||
|                 w_addr, |  | ||||||
|                 w_en, |  | ||||||
|                 w_data, |  | ||||||
|                 w_mask, |  | ||||||
|             } = io_cycles.get(cycle).copied().unwrap_or(IO { |  | ||||||
|                 r_addr: 0, |  | ||||||
|                 r_en: false, |  | ||||||
|                 r_data: [0; 8], |  | ||||||
|                 w_addr: 0, |  | ||||||
|                 w_en: false, |  | ||||||
|                 w_data: [0; 8], |  | ||||||
|                 w_mask: [false; 8], |  | ||||||
|             }); |  | ||||||
|             sim.write_bool_or_int(sim.io().r.addr, r_addr.cast_to_static()); |  | ||||||
|             sim.write_bool(sim.io().r.en, r_en); |  | ||||||
|             sim.write_bool_or_int(sim.io().w.addr, w_addr.cast_to_static()); |  | ||||||
|             sim.write_bool(sim.io().w.en, w_en); |  | ||||||
|             for (i, v) in w_data.into_iter().enumerate() { |  | ||||||
|                 sim.write_bool_or_int(sim.io().w.data[i], v); |  | ||||||
|             } |  | ||||||
|             for (i, v) in w_mask.into_iter().enumerate() { |  | ||||||
|                 sim.write_bool_or_int(sim.io().w.mask[i], v); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         sim.advance_time(SimDuration::from_nanos(250)); |  | ||||||
|         sim.write_clock(sim.io().r.clk, true); |  | ||||||
|         sim.write_clock(sim.io().w.clk, true); |  | ||||||
|         sim.advance_time(SimDuration::from_nanos(250)); |  | ||||||
|         if let Some( |  | ||||||
|             expected @ IO { |  | ||||||
|                 r_addr, |  | ||||||
|                 r_en, |  | ||||||
|                 r_data: _, |  | ||||||
|                 w_addr, |  | ||||||
|                 w_en, |  | ||||||
|                 w_data, |  | ||||||
|                 w_mask, |  | ||||||
|             }, |  | ||||||
|         ) = cycle.checked_sub(1).and_then(|i| io_cycles.get(i).copied()) |  | ||||||
|         { |  | ||||||
|             let io = IO { |  | ||||||
|                 r_addr, |  | ||||||
|                 r_en, |  | ||||||
|                 r_data: std::array::from_fn(|i| { |  | ||||||
|                     sim.read_bool_or_int(sim.io().r.data[i]) |  | ||||||
|                         .to_bigint() |  | ||||||
|                         .try_into() |  | ||||||
|                         .expect("known to be in range") |  | ||||||
|                 }), |  | ||||||
|                 w_addr, |  | ||||||
|                 w_en, |  | ||||||
|                 w_data, |  | ||||||
|                 w_mask, |  | ||||||
|             }; |  | ||||||
|             assert_eq!( |  | ||||||
|                 expected, |  | ||||||
|                 io, |  | ||||||
|                 "vcd:\n{}\ncycle: {cycle}", |  | ||||||
|                 String::from_utf8(writer.take()).unwrap(), |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|         sim.advance_time(SimDuration::from_nanos(250)); |  | ||||||
|         sim.write_clock(sim.io().r.clk, false); |  | ||||||
|         sim.write_clock(sim.io().w.clk, false); |  | ||||||
|         sim.advance_time(SimDuration::from_nanos(250)); |  | ||||||
|     } |  | ||||||
|     sim.flush_traces().unwrap(); |  | ||||||
|     let vcd = String::from_utf8(writer.take()).unwrap(); |  | ||||||
|     println!("####### VCD:\n{vcd}\n#######"); |  | ||||||
|     if vcd != include_str!("sim/expected/memories3.vcd") { |  | ||||||
|         panic!(); |  | ||||||
|     } |  | ||||||
|     let sim_debug = format!("{sim:#?}"); |  | ||||||
|     println!("#######\n{sim_debug}\n#######"); |  | ||||||
|     if sim_debug != include_str!("sim/expected/memories3.txt") { |  | ||||||
|         panic!(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -9,25 +9,18 @@ $var wire 2 $ which_in $end | ||||||
| $var wire 4 % data_in $end | $var wire 4 % data_in $end | ||||||
| $var wire 2 & which_out $end | $var wire 2 & which_out $end | ||||||
| $var wire 4 ' data_out $end | $var wire 4 ' data_out $end | ||||||
| $scope struct b_out $end |  | ||||||
| $var string 1 ( \$tag $end |  | ||||||
| $scope struct HdlSome $end |  | ||||||
| $var wire 1 ) \0 $end |  | ||||||
| $var wire 1 * \1 $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct the_reg $end | $scope struct the_reg $end | ||||||
| $var string 1 + \$tag $end | $var string 1 ( \$tag $end | ||||||
| $scope struct B $end | $scope struct B $end | ||||||
| $var reg 1 , \0 $end | $var reg 1 ) \0 $end | ||||||
| $var reg 1 - \1 $end | $var reg 1 * \1 $end | ||||||
| $upscope $end | $upscope $end | ||||||
| $scope struct C $end | $scope struct C $end | ||||||
| $scope struct a $end | $scope struct a $end | ||||||
| $var reg 1 . \[0] $end | $var reg 1 + \[0] $end | ||||||
| $var reg 1 / \[1] $end | $var reg 1 , \[1] $end | ||||||
| $upscope $end | $upscope $end | ||||||
| $var reg 2 0 b $end | $var reg 2 - b $end | ||||||
| $upscope $end | $upscope $end | ||||||
| $upscope $end | $upscope $end | ||||||
| $upscope $end | $upscope $end | ||||||
|  | @ -40,15 +33,12 @@ b0 $ | ||||||
| b0 % | b0 % | ||||||
| b0 & | b0 & | ||||||
| b0 ' | b0 ' | ||||||
| sHdlNone\x20(0) ( | sA\x20(0) ( | ||||||
| 0) | 0) | ||||||
| 0* | 0* | ||||||
| sA\x20(0) + | 0+ | ||||||
| 0, | 0, | ||||||
| 0- | b0 - | ||||||
| 0. |  | ||||||
| 0/ |  | ||||||
| b0 0 |  | ||||||
| $end | $end | ||||||
| #1000000 | #1000000 | ||||||
| 1! | 1! | ||||||
|  | @ -65,8 +55,7 @@ b1 $ | ||||||
| #5000000 | #5000000 | ||||||
| 1! | 1! | ||||||
| b1 & | b1 & | ||||||
| sHdlSome\x20(1) ( | sB\x20(1) ( | ||||||
| sB\x20(1) + |  | ||||||
| #6000000 | #6000000 | ||||||
| 0# | 0# | ||||||
| b0 $ | b0 $ | ||||||
|  | @ -83,10 +72,8 @@ b1111 % | ||||||
| b11 ' | b11 ' | ||||||
| 1) | 1) | ||||||
| 1* | 1* | ||||||
|  | 1+ | ||||||
| 1, | 1, | ||||||
| 1- |  | ||||||
| 1. |  | ||||||
| 1/ |  | ||||||
| #10000000 | #10000000 | ||||||
| 0! | 0! | ||||||
| #11000000 | #11000000 | ||||||
|  | @ -98,11 +85,8 @@ b10 $ | ||||||
| 1! | 1! | ||||||
| b10 & | b10 & | ||||||
| b1111 ' | b1111 ' | ||||||
| sHdlNone\x20(0) ( | sC\x20(2) ( | ||||||
| 0) | b11 - | ||||||
| 0* |  | ||||||
| sC\x20(2) + |  | ||||||
| b11 0 |  | ||||||
| #14000000 | #14000000 | ||||||
| 0! | 0! | ||||||
| #15000000 | #15000000 | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,363 +0,0 @@ | ||||||
| $timescale 1 ps $end |  | ||||||
| $scope module memories2 $end |  | ||||||
| $scope struct rw $end |  | ||||||
| $var wire 3 ! addr $end |  | ||||||
| $var wire 1 " en $end |  | ||||||
| $var wire 1 # clk $end |  | ||||||
| $var wire 2 $ rdata $end |  | ||||||
| $var wire 1 % wmode $end |  | ||||||
| $var wire 2 & wdata $end |  | ||||||
| $var wire 1 ' wmask $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $scope struct contents $end |  | ||||||
| $scope struct [0] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var string 1 1 \$tag $end |  | ||||||
| $var reg 1 6 HdlSome $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [1] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var string 1 2 \$tag $end |  | ||||||
| $var reg 1 7 HdlSome $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [2] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var string 1 3 \$tag $end |  | ||||||
| $var reg 1 8 HdlSome $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [3] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var string 1 4 \$tag $end |  | ||||||
| $var reg 1 9 HdlSome $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [4] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var string 1 5 \$tag $end |  | ||||||
| $var reg 1 : HdlSome $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct rw0 $end |  | ||||||
| $var wire 3 ( addr $end |  | ||||||
| $var wire 1 ) en $end |  | ||||||
| $var wire 1 * clk $end |  | ||||||
| $scope struct rdata $end |  | ||||||
| $var string 1 + \$tag $end |  | ||||||
| $var wire 1 , HdlSome $end |  | ||||||
| $upscope $end |  | ||||||
| $var wire 1 - wmode $end |  | ||||||
| $scope struct wdata $end |  | ||||||
| $var string 1 . \$tag $end |  | ||||||
| $var wire 1 / HdlSome $end |  | ||||||
| $upscope $end |  | ||||||
| $var wire 1 0 wmask $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $enddefinitions $end |  | ||||||
| $dumpvars |  | ||||||
| sHdlSome\x20(1) 1 |  | ||||||
| 16 |  | ||||||
| sHdlSome\x20(1) 2 |  | ||||||
| 17 |  | ||||||
| sHdlSome\x20(1) 3 |  | ||||||
| 18 |  | ||||||
| sHdlSome\x20(1) 4 |  | ||||||
| 19 |  | ||||||
| sHdlSome\x20(1) 5 |  | ||||||
| 1: |  | ||||||
| b0 ! |  | ||||||
| 0" |  | ||||||
| 0# |  | ||||||
| b0 $ |  | ||||||
| 0% |  | ||||||
| b0 & |  | ||||||
| 0' |  | ||||||
| b0 ( |  | ||||||
| 0) |  | ||||||
| 0* |  | ||||||
| sHdlNone\x20(0) + |  | ||||||
| 0, |  | ||||||
| 0- |  | ||||||
| sHdlNone\x20(0) . |  | ||||||
| 0/ |  | ||||||
| 00 |  | ||||||
| $end |  | ||||||
| #250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #500000 |  | ||||||
| #750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #1000000 |  | ||||||
| 1" |  | ||||||
| 1) |  | ||||||
| #1250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| b11 $ |  | ||||||
| sHdlSome\x20(1) + |  | ||||||
| 1, |  | ||||||
| #1500000 |  | ||||||
| #1750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #2000000 |  | ||||||
| 0" |  | ||||||
| 0) |  | ||||||
| #2250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| b0 $ |  | ||||||
| sHdlNone\x20(0) + |  | ||||||
| 0, |  | ||||||
| #2500000 |  | ||||||
| #2750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #3000000 |  | ||||||
| 1" |  | ||||||
| 1% |  | ||||||
| 1' |  | ||||||
| 1) |  | ||||||
| 1- |  | ||||||
| 10 |  | ||||||
| #3250000 |  | ||||||
| sHdlNone\x20(0) 1 |  | ||||||
| 06 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #3500000 |  | ||||||
| #3750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #4000000 |  | ||||||
| 0% |  | ||||||
| 0' |  | ||||||
| 0- |  | ||||||
| 00 |  | ||||||
| #4250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #4500000 |  | ||||||
| #4750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #5000000 |  | ||||||
| 1% |  | ||||||
| b11 & |  | ||||||
| 1- |  | ||||||
| sHdlSome\x20(1) . |  | ||||||
| 1/ |  | ||||||
| #5250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #5500000 |  | ||||||
| #5750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #6000000 |  | ||||||
| b1 ! |  | ||||||
| b1 & |  | ||||||
| 1' |  | ||||||
| b1 ( |  | ||||||
| 0/ |  | ||||||
| 10 |  | ||||||
| #6250000 |  | ||||||
| sHdlSome\x20(1) 2 |  | ||||||
| 07 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #6500000 |  | ||||||
| #6750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #7000000 |  | ||||||
| b10 ! |  | ||||||
| b10 & |  | ||||||
| b10 ( |  | ||||||
| sHdlNone\x20(0) . |  | ||||||
| #7250000 |  | ||||||
| sHdlNone\x20(0) 3 |  | ||||||
| 08 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #7500000 |  | ||||||
| #7750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #8000000 |  | ||||||
| b11 ! |  | ||||||
| b11 & |  | ||||||
| b11 ( |  | ||||||
| sHdlSome\x20(1) . |  | ||||||
| 1/ |  | ||||||
| #8250000 |  | ||||||
| sHdlSome\x20(1) 4 |  | ||||||
| 19 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #8500000 |  | ||||||
| #8750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #9000000 |  | ||||||
| b100 ! |  | ||||||
| b10 & |  | ||||||
| b100 ( |  | ||||||
| sHdlNone\x20(0) . |  | ||||||
| 0/ |  | ||||||
| #9250000 |  | ||||||
| sHdlNone\x20(0) 5 |  | ||||||
| 0: |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #9500000 |  | ||||||
| #9750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #10000000 |  | ||||||
| b101 ! |  | ||||||
| b1 & |  | ||||||
| b101 ( |  | ||||||
| sHdlSome\x20(1) . |  | ||||||
| #10250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #10500000 |  | ||||||
| #10750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #11000000 |  | ||||||
| b110 ! |  | ||||||
| b110 ( |  | ||||||
| #11250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #11500000 |  | ||||||
| #11750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #12000000 |  | ||||||
| b111 ! |  | ||||||
| b111 ( |  | ||||||
| #12250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #12500000 |  | ||||||
| #12750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #13000000 |  | ||||||
| 0% |  | ||||||
| b0 & |  | ||||||
| 0' |  | ||||||
| 0- |  | ||||||
| sHdlNone\x20(0) . |  | ||||||
| 00 |  | ||||||
| #13250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #13500000 |  | ||||||
| #13750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #14000000 |  | ||||||
| b110 ! |  | ||||||
| b110 ( |  | ||||||
| #14250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #14500000 |  | ||||||
| #14750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #15000000 |  | ||||||
| b101 ! |  | ||||||
| b101 ( |  | ||||||
| #15250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #15500000 |  | ||||||
| #15750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #16000000 |  | ||||||
| b100 ! |  | ||||||
| b100 ( |  | ||||||
| #16250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #16500000 |  | ||||||
| #16750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #17000000 |  | ||||||
| b11 ! |  | ||||||
| b11 ( |  | ||||||
| #17250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| b11 $ |  | ||||||
| sHdlSome\x20(1) + |  | ||||||
| 1, |  | ||||||
| #17500000 |  | ||||||
| #17750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #18000000 |  | ||||||
| b10 ! |  | ||||||
| b10 ( |  | ||||||
| #18250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| b0 $ |  | ||||||
| sHdlNone\x20(0) + |  | ||||||
| 0, |  | ||||||
| #18500000 |  | ||||||
| #18750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #19000000 |  | ||||||
| b0 ! |  | ||||||
| b0 ( |  | ||||||
| #19250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| #19500000 |  | ||||||
| #19750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #20000000 |  | ||||||
| b1 ! |  | ||||||
| b1 ( |  | ||||||
| #20250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| b1 $ |  | ||||||
| sHdlSome\x20(1) + |  | ||||||
| #20500000 |  | ||||||
| #20750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #21000000 |  | ||||||
| b0 ! |  | ||||||
| 0" |  | ||||||
| b0 ( |  | ||||||
| 0) |  | ||||||
| #21250000 |  | ||||||
| 1# |  | ||||||
| 1* |  | ||||||
| b0 $ |  | ||||||
| sHdlNone\x20(0) + |  | ||||||
| #21500000 |  | ||||||
| #21750000 |  | ||||||
| 0# |  | ||||||
| 0* |  | ||||||
| #22000000 |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,836 +0,0 @@ | ||||||
| $timescale 1 ps $end |  | ||||||
| $scope module memories3 $end |  | ||||||
| $scope struct r $end |  | ||||||
| $var wire 3 ! addr $end |  | ||||||
| $var wire 1 " en $end |  | ||||||
| $var wire 1 # clk $end |  | ||||||
| $scope struct data $end |  | ||||||
| $var wire 8 $ \[0] $end |  | ||||||
| $var wire 8 % \[1] $end |  | ||||||
| $var wire 8 & \[2] $end |  | ||||||
| $var wire 8 ' \[3] $end |  | ||||||
| $var wire 8 ( \[4] $end |  | ||||||
| $var wire 8 ) \[5] $end |  | ||||||
| $var wire 8 * \[6] $end |  | ||||||
| $var wire 8 + \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct w $end |  | ||||||
| $var wire 3 , addr $end |  | ||||||
| $var wire 1 - en $end |  | ||||||
| $var wire 1 . clk $end |  | ||||||
| $scope struct data $end |  | ||||||
| $var wire 8 / \[0] $end |  | ||||||
| $var wire 8 0 \[1] $end |  | ||||||
| $var wire 8 1 \[2] $end |  | ||||||
| $var wire 8 2 \[3] $end |  | ||||||
| $var wire 8 3 \[4] $end |  | ||||||
| $var wire 8 4 \[5] $end |  | ||||||
| $var wire 8 5 \[6] $end |  | ||||||
| $var wire 8 6 \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct mask $end |  | ||||||
| $var wire 1 7 \[0] $end |  | ||||||
| $var wire 1 8 \[1] $end |  | ||||||
| $var wire 1 9 \[2] $end |  | ||||||
| $var wire 1 : \[3] $end |  | ||||||
| $var wire 1 ; \[4] $end |  | ||||||
| $var wire 1 < \[5] $end |  | ||||||
| $var wire 1 = \[6] $end |  | ||||||
| $var wire 1 > \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $scope struct contents $end |  | ||||||
| $scope struct [0] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var reg 8 ] \[0] $end |  | ||||||
| $var reg 8 e \[1] $end |  | ||||||
| $var reg 8 m \[2] $end |  | ||||||
| $var reg 8 u \[3] $end |  | ||||||
| $var reg 8 } \[4] $end |  | ||||||
| $var reg 8 '" \[5] $end |  | ||||||
| $var reg 8 /" \[6] $end |  | ||||||
| $var reg 8 7" \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [1] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var reg 8 ^ \[0] $end |  | ||||||
| $var reg 8 f \[1] $end |  | ||||||
| $var reg 8 n \[2] $end |  | ||||||
| $var reg 8 v \[3] $end |  | ||||||
| $var reg 8 ~ \[4] $end |  | ||||||
| $var reg 8 (" \[5] $end |  | ||||||
| $var reg 8 0" \[6] $end |  | ||||||
| $var reg 8 8" \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [2] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var reg 8 _ \[0] $end |  | ||||||
| $var reg 8 g \[1] $end |  | ||||||
| $var reg 8 o \[2] $end |  | ||||||
| $var reg 8 w \[3] $end |  | ||||||
| $var reg 8 !" \[4] $end |  | ||||||
| $var reg 8 )" \[5] $end |  | ||||||
| $var reg 8 1" \[6] $end |  | ||||||
| $var reg 8 9" \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [3] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var reg 8 ` \[0] $end |  | ||||||
| $var reg 8 h \[1] $end |  | ||||||
| $var reg 8 p \[2] $end |  | ||||||
| $var reg 8 x \[3] $end |  | ||||||
| $var reg 8 "" \[4] $end |  | ||||||
| $var reg 8 *" \[5] $end |  | ||||||
| $var reg 8 2" \[6] $end |  | ||||||
| $var reg 8 :" \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [4] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var reg 8 a \[0] $end |  | ||||||
| $var reg 8 i \[1] $end |  | ||||||
| $var reg 8 q \[2] $end |  | ||||||
| $var reg 8 y \[3] $end |  | ||||||
| $var reg 8 #" \[4] $end |  | ||||||
| $var reg 8 +" \[5] $end |  | ||||||
| $var reg 8 3" \[6] $end |  | ||||||
| $var reg 8 ;" \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [5] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var reg 8 b \[0] $end |  | ||||||
| $var reg 8 j \[1] $end |  | ||||||
| $var reg 8 r \[2] $end |  | ||||||
| $var reg 8 z \[3] $end |  | ||||||
| $var reg 8 $" \[4] $end |  | ||||||
| $var reg 8 ," \[5] $end |  | ||||||
| $var reg 8 4" \[6] $end |  | ||||||
| $var reg 8 <" \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [6] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var reg 8 c \[0] $end |  | ||||||
| $var reg 8 k \[1] $end |  | ||||||
| $var reg 8 s \[2] $end |  | ||||||
| $var reg 8 { \[3] $end |  | ||||||
| $var reg 8 %" \[4] $end |  | ||||||
| $var reg 8 -" \[5] $end |  | ||||||
| $var reg 8 5" \[6] $end |  | ||||||
| $var reg 8 =" \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct [7] $end |  | ||||||
| $scope struct mem $end |  | ||||||
| $var reg 8 d \[0] $end |  | ||||||
| $var reg 8 l \[1] $end |  | ||||||
| $var reg 8 t \[2] $end |  | ||||||
| $var reg 8 | \[3] $end |  | ||||||
| $var reg 8 &" \[4] $end |  | ||||||
| $var reg 8 ." \[5] $end |  | ||||||
| $var reg 8 6" \[6] $end |  | ||||||
| $var reg 8 >" \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct r0 $end |  | ||||||
| $var wire 3 ? addr $end |  | ||||||
| $var wire 1 @ en $end |  | ||||||
| $var wire 1 A clk $end |  | ||||||
| $scope struct data $end |  | ||||||
| $var wire 8 B \[0] $end |  | ||||||
| $var wire 8 C \[1] $end |  | ||||||
| $var wire 8 D \[2] $end |  | ||||||
| $var wire 8 E \[3] $end |  | ||||||
| $var wire 8 F \[4] $end |  | ||||||
| $var wire 8 G \[5] $end |  | ||||||
| $var wire 8 H \[6] $end |  | ||||||
| $var wire 8 I \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct w1 $end |  | ||||||
| $var wire 3 J addr $end |  | ||||||
| $var wire 1 K en $end |  | ||||||
| $var wire 1 L clk $end |  | ||||||
| $scope struct data $end |  | ||||||
| $var wire 8 M \[0] $end |  | ||||||
| $var wire 8 N \[1] $end |  | ||||||
| $var wire 8 O \[2] $end |  | ||||||
| $var wire 8 P \[3] $end |  | ||||||
| $var wire 8 Q \[4] $end |  | ||||||
| $var wire 8 R \[5] $end |  | ||||||
| $var wire 8 S \[6] $end |  | ||||||
| $var wire 8 T \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $scope struct mask $end |  | ||||||
| $var wire 1 U \[0] $end |  | ||||||
| $var wire 1 V \[1] $end |  | ||||||
| $var wire 1 W \[2] $end |  | ||||||
| $var wire 1 X \[3] $end |  | ||||||
| $var wire 1 Y \[4] $end |  | ||||||
| $var wire 1 Z \[5] $end |  | ||||||
| $var wire 1 [ \[6] $end |  | ||||||
| $var wire 1 \ \[7] $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $upscope $end |  | ||||||
| $enddefinitions $end |  | ||||||
| $dumpvars |  | ||||||
| b0 ] |  | ||||||
| b0 e |  | ||||||
| b0 m |  | ||||||
| b0 u |  | ||||||
| b0 } |  | ||||||
| b0 '" |  | ||||||
| b0 /" |  | ||||||
| b0 7" |  | ||||||
| b0 ^ |  | ||||||
| b0 f |  | ||||||
| b0 n |  | ||||||
| b0 v |  | ||||||
| b0 ~ |  | ||||||
| b0 (" |  | ||||||
| b0 0" |  | ||||||
| b0 8" |  | ||||||
| b0 _ |  | ||||||
| b0 g |  | ||||||
| b0 o |  | ||||||
| b0 w |  | ||||||
| b0 !" |  | ||||||
| b0 )" |  | ||||||
| b0 1" |  | ||||||
| b0 9" |  | ||||||
| b0 ` |  | ||||||
| b0 h |  | ||||||
| b0 p |  | ||||||
| b0 x |  | ||||||
| b0 "" |  | ||||||
| b0 *" |  | ||||||
| b0 2" |  | ||||||
| b0 :" |  | ||||||
| b0 a |  | ||||||
| b0 i |  | ||||||
| b0 q |  | ||||||
| b0 y |  | ||||||
| b0 #" |  | ||||||
| b0 +" |  | ||||||
| b0 3" |  | ||||||
| b0 ;" |  | ||||||
| b0 b |  | ||||||
| b0 j |  | ||||||
| b0 r |  | ||||||
| b0 z |  | ||||||
| b0 $" |  | ||||||
| b0 ," |  | ||||||
| b0 4" |  | ||||||
| b0 <" |  | ||||||
| b0 c |  | ||||||
| b0 k |  | ||||||
| b0 s |  | ||||||
| b0 { |  | ||||||
| b0 %" |  | ||||||
| b0 -" |  | ||||||
| b0 5" |  | ||||||
| b0 =" |  | ||||||
| b0 d |  | ||||||
| b0 l |  | ||||||
| b0 t |  | ||||||
| b0 | |  | ||||||
| b0 &" |  | ||||||
| b0 ." |  | ||||||
| b0 6" |  | ||||||
| b0 >" |  | ||||||
| b0 ! |  | ||||||
| 0" |  | ||||||
| 0# |  | ||||||
| b0 $ |  | ||||||
| b0 % |  | ||||||
| b0 & |  | ||||||
| b0 ' |  | ||||||
| b0 ( |  | ||||||
| b0 ) |  | ||||||
| b0 * |  | ||||||
| b0 + |  | ||||||
| b0 , |  | ||||||
| 1- |  | ||||||
| 0. |  | ||||||
| b10010 / |  | ||||||
| b110100 0 |  | ||||||
| b1010110 1 |  | ||||||
| b1111000 2 |  | ||||||
| b10011010 3 |  | ||||||
| b10111100 4 |  | ||||||
| b11011110 5 |  | ||||||
| b11110000 6 |  | ||||||
| 07 |  | ||||||
| 18 |  | ||||||
| 09 |  | ||||||
| 1: |  | ||||||
| 1; |  | ||||||
| 0< |  | ||||||
| 0= |  | ||||||
| 1> |  | ||||||
| b0 ? |  | ||||||
| 0@ |  | ||||||
| 0A |  | ||||||
| b0 B |  | ||||||
| b0 C |  | ||||||
| b0 D |  | ||||||
| b0 E |  | ||||||
| b0 F |  | ||||||
| b0 G |  | ||||||
| b0 H |  | ||||||
| b0 I |  | ||||||
| b0 J |  | ||||||
| 1K |  | ||||||
| 0L |  | ||||||
| b10010 M |  | ||||||
| b110100 N |  | ||||||
| b1010110 O |  | ||||||
| b1111000 P |  | ||||||
| b10011010 Q |  | ||||||
| b10111100 R |  | ||||||
| b11011110 S |  | ||||||
| b11110000 T |  | ||||||
| 0U |  | ||||||
| 1V |  | ||||||
| 0W |  | ||||||
| 1X |  | ||||||
| 1Y |  | ||||||
| 0Z |  | ||||||
| 0[ |  | ||||||
| 1\ |  | ||||||
| $end |  | ||||||
| #250000 |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| 1L |  | ||||||
| #500000 |  | ||||||
| #750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #1000000 |  | ||||||
| 1" |  | ||||||
| b1 , |  | ||||||
| 0- |  | ||||||
| b0 / |  | ||||||
| b0 0 |  | ||||||
| b0 1 |  | ||||||
| b0 2 |  | ||||||
| b0 3 |  | ||||||
| b0 4 |  | ||||||
| b0 5 |  | ||||||
| b0 6 |  | ||||||
| 08 |  | ||||||
| 0: |  | ||||||
| 0; |  | ||||||
| 0> |  | ||||||
| 1@ |  | ||||||
| b1 J |  | ||||||
| 0K |  | ||||||
| b0 M |  | ||||||
| b0 N |  | ||||||
| b0 O |  | ||||||
| b0 P |  | ||||||
| b0 Q |  | ||||||
| b0 R |  | ||||||
| b0 S |  | ||||||
| b0 T |  | ||||||
| 0V |  | ||||||
| 0X |  | ||||||
| 0Y |  | ||||||
| 0\ |  | ||||||
| #1250000 |  | ||||||
| b0 ] |  | ||||||
| b110100 e |  | ||||||
| b0 m |  | ||||||
| b1111000 u |  | ||||||
| b10011010 } |  | ||||||
| b0 '" |  | ||||||
| b0 /" |  | ||||||
| b11110000 7" |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| 1L |  | ||||||
| #1500000 |  | ||||||
| #1750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #2000000 |  | ||||||
| #2250000 |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| 1L |  | ||||||
| #2500000 |  | ||||||
| #2750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #3000000 |  | ||||||
| b0 , |  | ||||||
| 1- |  | ||||||
| b11111110 / |  | ||||||
| b11011100 0 |  | ||||||
| b10111010 1 |  | ||||||
| b10011000 2 |  | ||||||
| b1110110 3 |  | ||||||
| b1010100 4 |  | ||||||
| b110010 5 |  | ||||||
| b10000 6 |  | ||||||
| 17 |  | ||||||
| 18 |  | ||||||
| 19 |  | ||||||
| 1: |  | ||||||
| 1; |  | ||||||
| 1< |  | ||||||
| 1= |  | ||||||
| 1> |  | ||||||
| b0 J |  | ||||||
| 1K |  | ||||||
| b11111110 M |  | ||||||
| b11011100 N |  | ||||||
| b10111010 O |  | ||||||
| b10011000 P |  | ||||||
| b1110110 Q |  | ||||||
| b1010100 R |  | ||||||
| b110010 S |  | ||||||
| b10000 T |  | ||||||
| 1U |  | ||||||
| 1V |  | ||||||
| 1W |  | ||||||
| 1X |  | ||||||
| 1Y |  | ||||||
| 1Z |  | ||||||
| 1[ |  | ||||||
| 1\ |  | ||||||
| #3250000 |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| b110100 C |  | ||||||
| b1111000 E |  | ||||||
| b10011010 F |  | ||||||
| b11110000 I |  | ||||||
| 1L |  | ||||||
| b110100 % |  | ||||||
| b1111000 ' |  | ||||||
| b10011010 ( |  | ||||||
| b11110000 + |  | ||||||
| #3500000 |  | ||||||
| #3750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #4000000 |  | ||||||
| #4250000 |  | ||||||
| b11111110 ] |  | ||||||
| b11011100 e |  | ||||||
| b10111010 m |  | ||||||
| b10011000 u |  | ||||||
| b1110110 } |  | ||||||
| b1010100 '" |  | ||||||
| b110010 /" |  | ||||||
| b10000 7" |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| 1L |  | ||||||
| #4500000 |  | ||||||
| #4750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #5000000 |  | ||||||
| #5250000 |  | ||||||
| b11111110 ] |  | ||||||
| b11011100 e |  | ||||||
| b10111010 m |  | ||||||
| b10011000 u |  | ||||||
| b1110110 } |  | ||||||
| b1010100 '" |  | ||||||
| b110010 /" |  | ||||||
| b10000 7" |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| 1L |  | ||||||
| #5500000 |  | ||||||
| #5750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #6000000 |  | ||||||
| 0" |  | ||||||
| b1 , |  | ||||||
| b10011 / |  | ||||||
| b1010111 0 |  | ||||||
| b10011011 1 |  | ||||||
| b11011111 2 |  | ||||||
| b10 3 |  | ||||||
| b1000110 4 |  | ||||||
| b10001010 5 |  | ||||||
| b11001110 6 |  | ||||||
| 0@ |  | ||||||
| b1 J |  | ||||||
| b10011 M |  | ||||||
| b1010111 N |  | ||||||
| b10011011 O |  | ||||||
| b11011111 P |  | ||||||
| b10 Q |  | ||||||
| b1000110 R |  | ||||||
| b10001010 S |  | ||||||
| b11001110 T |  | ||||||
| #6250000 |  | ||||||
| b11111110 ] |  | ||||||
| b11011100 e |  | ||||||
| b10111010 m |  | ||||||
| b10011000 u |  | ||||||
| b1110110 } |  | ||||||
| b1010100 '" |  | ||||||
| b110010 /" |  | ||||||
| b10000 7" |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| b11111110 B |  | ||||||
| b11011100 C |  | ||||||
| b10111010 D |  | ||||||
| b10011000 E |  | ||||||
| b1110110 F |  | ||||||
| b1010100 G |  | ||||||
| b110010 H |  | ||||||
| b10000 I |  | ||||||
| 1L |  | ||||||
| b11111110 $ |  | ||||||
| b11011100 % |  | ||||||
| b10111010 & |  | ||||||
| b10011000 ' |  | ||||||
| b1110110 ( |  | ||||||
| b1010100 ) |  | ||||||
| b110010 * |  | ||||||
| b10000 + |  | ||||||
| #6500000 |  | ||||||
| #6750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #7000000 |  | ||||||
| b10 , |  | ||||||
| b1110100 / |  | ||||||
| b1100101 0 |  | ||||||
| b1110011 1 |  | ||||||
| b1110100 2 |  | ||||||
| b1101001 3 |  | ||||||
| b1101110 4 |  | ||||||
| b1100111 5 |  | ||||||
| b100001 6 |  | ||||||
| b10 J |  | ||||||
| b1110100 M |  | ||||||
| b1100101 N |  | ||||||
| b1110011 O |  | ||||||
| b1110100 P |  | ||||||
| b1101001 Q |  | ||||||
| b1101110 R |  | ||||||
| b1100111 S |  | ||||||
| b100001 T |  | ||||||
| #7250000 |  | ||||||
| b10011 ^ |  | ||||||
| b1010111 f |  | ||||||
| b10011011 n |  | ||||||
| b11011111 v |  | ||||||
| b10 ~ |  | ||||||
| b1000110 (" |  | ||||||
| b10001010 0" |  | ||||||
| b11001110 8" |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| b0 B |  | ||||||
| b0 C |  | ||||||
| b0 D |  | ||||||
| b0 E |  | ||||||
| b0 F |  | ||||||
| b0 G |  | ||||||
| b0 H |  | ||||||
| b0 I |  | ||||||
| 1L |  | ||||||
| b0 $ |  | ||||||
| b0 % |  | ||||||
| b0 & |  | ||||||
| b0 ' |  | ||||||
| b0 ( |  | ||||||
| b0 ) |  | ||||||
| b0 * |  | ||||||
| b0 + |  | ||||||
| #7500000 |  | ||||||
| #7750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #8000000 |  | ||||||
| b11 , |  | ||||||
| b1101101 / |  | ||||||
| b1101111 0 |  | ||||||
| b1110010 1 |  | ||||||
| b1100101 2 |  | ||||||
| b100000 3 |  | ||||||
| b1110100 4 |  | ||||||
| b1110011 5 |  | ||||||
| b1110100 6 |  | ||||||
| b11 J |  | ||||||
| b1101101 M |  | ||||||
| b1101111 N |  | ||||||
| b1110010 O |  | ||||||
| b1100101 P |  | ||||||
| b100000 Q |  | ||||||
| b1110100 R |  | ||||||
| b1110011 S |  | ||||||
| b1110100 T |  | ||||||
| #8250000 |  | ||||||
| b1110100 _ |  | ||||||
| b1100101 g |  | ||||||
| b1110011 o |  | ||||||
| b1110100 w |  | ||||||
| b1101001 !" |  | ||||||
| b1101110 )" |  | ||||||
| b1100111 1" |  | ||||||
| b100001 9" |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| 1L |  | ||||||
| #8500000 |  | ||||||
| #8750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #9000000 |  | ||||||
| 1" |  | ||||||
| b0 , |  | ||||||
| 0- |  | ||||||
| b0 / |  | ||||||
| b0 0 |  | ||||||
| b0 1 |  | ||||||
| b0 2 |  | ||||||
| b0 3 |  | ||||||
| b0 4 |  | ||||||
| b0 5 |  | ||||||
| b0 6 |  | ||||||
| 07 |  | ||||||
| 08 |  | ||||||
| 09 |  | ||||||
| 0: |  | ||||||
| 0; |  | ||||||
| 0< |  | ||||||
| 0= |  | ||||||
| 0> |  | ||||||
| 1@ |  | ||||||
| b0 J |  | ||||||
| 0K |  | ||||||
| b0 M |  | ||||||
| b0 N |  | ||||||
| b0 O |  | ||||||
| b0 P |  | ||||||
| b0 Q |  | ||||||
| b0 R |  | ||||||
| b0 S |  | ||||||
| b0 T |  | ||||||
| 0U |  | ||||||
| 0V |  | ||||||
| 0W |  | ||||||
| 0X |  | ||||||
| 0Y |  | ||||||
| 0Z |  | ||||||
| 0[ |  | ||||||
| 0\ |  | ||||||
| #9250000 |  | ||||||
| b1101101 ` |  | ||||||
| b1101111 h |  | ||||||
| b1110010 p |  | ||||||
| b1100101 x |  | ||||||
| b100000 "" |  | ||||||
| b1110100 *" |  | ||||||
| b1110011 2" |  | ||||||
| b1110100 :" |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| 1L |  | ||||||
| #9500000 |  | ||||||
| #9750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #10000000 |  | ||||||
| b1 ! |  | ||||||
| b1 ? |  | ||||||
| #10250000 |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| b11111110 B |  | ||||||
| b11011100 C |  | ||||||
| b10111010 D |  | ||||||
| b10011000 E |  | ||||||
| b1110110 F |  | ||||||
| b1010100 G |  | ||||||
| b110010 H |  | ||||||
| b10000 I |  | ||||||
| 1L |  | ||||||
| b11111110 $ |  | ||||||
| b11011100 % |  | ||||||
| b10111010 & |  | ||||||
| b10011000 ' |  | ||||||
| b1110110 ( |  | ||||||
| b1010100 ) |  | ||||||
| b110010 * |  | ||||||
| b10000 + |  | ||||||
| #10500000 |  | ||||||
| #10750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #11000000 |  | ||||||
| b10 ! |  | ||||||
| b10 ? |  | ||||||
| #11250000 |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| b10011 B |  | ||||||
| b1010111 C |  | ||||||
| b10011011 D |  | ||||||
| b11011111 E |  | ||||||
| b10 F |  | ||||||
| b1000110 G |  | ||||||
| b10001010 H |  | ||||||
| b11001110 I |  | ||||||
| 1L |  | ||||||
| b10011 $ |  | ||||||
| b1010111 % |  | ||||||
| b10011011 & |  | ||||||
| b11011111 ' |  | ||||||
| b10 ( |  | ||||||
| b1000110 ) |  | ||||||
| b10001010 * |  | ||||||
| b11001110 + |  | ||||||
| #11500000 |  | ||||||
| #11750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #12000000 |  | ||||||
| b11 ! |  | ||||||
| b11 ? |  | ||||||
| #12250000 |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| b1110100 B |  | ||||||
| b1100101 C |  | ||||||
| b1110011 D |  | ||||||
| b1110100 E |  | ||||||
| b1101001 F |  | ||||||
| b1101110 G |  | ||||||
| b1100111 H |  | ||||||
| b100001 I |  | ||||||
| 1L |  | ||||||
| b1110100 $ |  | ||||||
| b1100101 % |  | ||||||
| b1110011 & |  | ||||||
| b1110100 ' |  | ||||||
| b1101001 ( |  | ||||||
| b1101110 ) |  | ||||||
| b1100111 * |  | ||||||
| b100001 + |  | ||||||
| #12500000 |  | ||||||
| #12750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #13000000 |  | ||||||
| b0 ! |  | ||||||
| 0" |  | ||||||
| b0 ? |  | ||||||
| 0@ |  | ||||||
| #13250000 |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| b1101101 B |  | ||||||
| b1101111 C |  | ||||||
| b1110010 D |  | ||||||
| b1100101 E |  | ||||||
| b100000 F |  | ||||||
| b1110100 G |  | ||||||
| b1110011 H |  | ||||||
| b1110100 I |  | ||||||
| 1L |  | ||||||
| b1101101 $ |  | ||||||
| b1101111 % |  | ||||||
| b1110010 & |  | ||||||
| b1100101 ' |  | ||||||
| b100000 ( |  | ||||||
| b1110100 ) |  | ||||||
| b1110011 * |  | ||||||
| b1110100 + |  | ||||||
| #13500000 |  | ||||||
| #13750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #14000000 |  | ||||||
| #14250000 |  | ||||||
| 1# |  | ||||||
| 1. |  | ||||||
| 1A |  | ||||||
| b0 B |  | ||||||
| b0 C |  | ||||||
| b0 D |  | ||||||
| b0 E |  | ||||||
| b0 F |  | ||||||
| b0 G |  | ||||||
| b0 H |  | ||||||
| b0 I |  | ||||||
| 1L |  | ||||||
| b0 $ |  | ||||||
| b0 % |  | ||||||
| b0 & |  | ||||||
| b0 ' |  | ||||||
| b0 ( |  | ||||||
| b0 ) |  | ||||||
| b0 * |  | ||||||
| b0 + |  | ||||||
| #14500000 |  | ||||||
| #14750000 |  | ||||||
| 0# |  | ||||||
| 0. |  | ||||||
| 0A |  | ||||||
| 0L |  | ||||||
| #15000000 |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue