WIP adding Platform
All checks were successful
/ test (pull_request) Successful in 4m28s

This commit is contained in:
Jacob Lifshay 2025-10-17 05:52:56 -07:00
parent def406ab52
commit 3f5dd61e46
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
10 changed files with 1468 additions and 218 deletions

View file

@ -66,6 +66,7 @@ mod kw {
}
custom_keyword!(__evaluated_cfgs);
custom_keyword!(add_platform_io);
custom_keyword!(all);
custom_keyword!(any);
custom_keyword!(cfg);

View file

@ -4,7 +4,7 @@ use crate::{
Errors, HdlAttr, PairsIterExt,
hdl_type_common::{ParsedGenerics, SplitForImpl},
kw,
module::transform_body::{HdlLet, HdlLetKindIO},
module::transform_body::{HdlLet, HdlLetKindIO, ModuleIOOrAddPlatformIO},
options,
};
use proc_macro2::TokenStream;
@ -39,7 +39,7 @@ pub(crate) fn check_name_conflicts_with_module_builder(name: &Ident) -> syn::Res
if name == "m" {
Err(Error::new_spanned(
name,
"name conflicts with implicit `m: &mut ModuleBuilder<_>`",
"name conflicts with implicit `m: &ModuleBuilder`",
))
} else {
Ok(())
@ -67,7 +67,7 @@ struct ModuleFnModule {
vis: Visibility,
sig: Signature,
block: Box<Block>,
struct_generics: ParsedGenerics,
struct_generics: Option<ParsedGenerics>,
the_struct: TokenStream,
}
@ -290,7 +290,7 @@ impl ModuleFn {
paren_token,
body,
} => {
debug_assert!(io.is_empty());
debug_assert!(matches!(io, ModuleIOOrAddPlatformIO::ModuleIO(v) if v.is_empty()));
return Ok(Self(ModuleFnImpl::Fn {
attrs,
config_options: HdlAttr {
@ -322,6 +322,21 @@ impl ModuleFn {
body,
},
};
let io = match io {
ModuleIOOrAddPlatformIO::ModuleIO(io) => io,
ModuleIOOrAddPlatformIO::AddPlatformIO => {
return Ok(Self(ModuleFnImpl::Module(ModuleFnModule {
attrs,
config_options,
module_kind: module_kind.unwrap(),
vis,
sig,
block,
struct_generics: None,
the_struct: TokenStream::new(),
})));
}
};
let (_struct_impl_generics, _struct_type_generics, struct_where_clause) =
struct_generics.split_for_impl();
let struct_where_clause: Option<WhereClause> = parse_quote! { #struct_where_clause };
@ -364,7 +379,7 @@ impl ModuleFn {
vis,
sig,
block,
struct_generics,
struct_generics: Some(struct_generics),
the_struct,
})))
}
@ -433,9 +448,14 @@ impl ModuleFn {
ModuleKind::Normal => quote! { ::fayalite::module::ModuleKind::Normal },
};
let fn_name = &outer_sig.ident;
let (_struct_impl_generics, struct_type_generics, _struct_where_clause) =
struct_generics.split_for_impl();
let struct_ty = quote! {#fn_name #struct_type_generics};
let struct_ty = match struct_generics {
Some(struct_generics) => {
let (_struct_impl_generics, struct_type_generics, _struct_where_clause) =
struct_generics.split_for_impl();
quote! {#fn_name #struct_type_generics}
}
None => quote! {::fayalite::bundle::Bundle},
};
body_sig.ident = parse_quote! {__body};
body_sig
.inputs

View file

@ -39,6 +39,7 @@ options! {
pub(crate) enum LetFnKind {
Input(input),
Output(output),
AddPlatformIO(add_platform_io),
Instance(instance),
RegBuilder(reg_builder),
Wire(wire),
@ -216,6 +217,49 @@ impl HdlLetKindToTokens for HdlLetKindInstance {
}
}
#[derive(Clone, Debug)]
pub(crate) struct HdlLetKindAddPlatformIO {
pub(crate) m: kw::m,
pub(crate) dot_token: Token![.],
pub(crate) add_platform_io: kw::add_platform_io,
pub(crate) paren: Paren,
pub(crate) platform_io_builder: Box<Expr>,
}
impl ParseTypes<Self> for HdlLetKindAddPlatformIO {
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
Ok(input.clone())
}
}
impl_fold! {
struct HdlLetKindAddPlatformIO<> {
m: kw::m,
dot_token: Token![.],
add_platform_io: kw::add_platform_io,
paren: Paren,
platform_io_builder: Box<Expr>,
}
}
impl HdlLetKindToTokens for HdlLetKindAddPlatformIO {
fn ty_to_tokens(&self, _tokens: &mut TokenStream) {}
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
let Self {
m,
dot_token,
add_platform_io,
paren,
platform_io_builder,
} = self;
m.to_tokens(tokens);
dot_token.to_tokens(tokens);
add_platform_io.to_tokens(tokens);
paren.surround(tokens, |tokens| platform_io_builder.to_tokens(tokens));
}
}
#[derive(Clone, Debug)]
pub(crate) struct RegBuilderClockDomain {
pub(crate) dot_token: Token![.],
@ -711,6 +755,7 @@ impl HdlLetKindMemory {
#[derive(Clone, Debug)]
pub(crate) enum HdlLetKind<IOType = ParsedType> {
IO(HdlLetKindIO<ModuleIOKind, IOType>),
AddPlatformIO(HdlLetKindAddPlatformIO),
Incomplete(HdlLetKindIncomplete),
Instance(HdlLetKindInstance),
RegBuilder(HdlLetKindRegBuilder),
@ -721,6 +766,7 @@ pub(crate) enum HdlLetKind<IOType = ParsedType> {
impl_fold! {
enum HdlLetKind<IOType,> {
IO(HdlLetKindIO<ModuleIOKind, IOType>),
AddPlatformIO(HdlLetKindAddPlatformIO),
Incomplete(HdlLetKindIncomplete),
Instance(HdlLetKindInstance),
RegBuilder(HdlLetKindRegBuilder),
@ -736,6 +782,9 @@ impl<T: ParseTypes<I>, I> ParseTypes<HdlLetKind<I>> for HdlLetKind<T> {
) -> Result<Self, ParseFailed> {
match input {
HdlLetKind::IO(input) => ParseTypes::parse_types(input, parser).map(HdlLetKind::IO),
HdlLetKind::AddPlatformIO(input) => {
ParseTypes::parse_types(input, parser).map(HdlLetKind::AddPlatformIO)
}
HdlLetKind::Incomplete(input) => {
ParseTypes::parse_types(input, parser).map(HdlLetKind::Incomplete)
}
@ -861,6 +910,23 @@ impl HdlLetKindParse for HdlLetKind<Type> {
ModuleIOKind::Output(output),
)
.map(Self::IO),
LetFnKind::AddPlatformIO((add_platform_io,)) => {
if let Some(parsed_ty) = parsed_ty {
return Err(Error::new_spanned(
parsed_ty.1,
"type annotation not allowed for instance",
));
}
let (m, dot_token) = unwrap_m_dot(m_dot, kind)?;
let paren_contents;
Ok(Self::AddPlatformIO(HdlLetKindAddPlatformIO {
m,
dot_token,
add_platform_io,
paren: parenthesized!(paren_contents in input),
platform_io_builder: paren_contents.call(parse_single_fn_arg)?,
}))
}
LetFnKind::Instance((instance,)) => {
if let Some(parsed_ty) = parsed_ty {
return Err(Error::new_spanned(
@ -936,6 +1002,7 @@ impl HdlLetKindToTokens for HdlLetKind {
fn ty_to_tokens(&self, tokens: &mut TokenStream) {
match self {
HdlLetKind::IO(v) => v.ty_to_tokens(tokens),
HdlLetKind::AddPlatformIO(v) => v.ty_to_tokens(tokens),
HdlLetKind::Incomplete(v) => v.ty_to_tokens(tokens),
HdlLetKind::Instance(v) => v.ty_to_tokens(tokens),
HdlLetKind::RegBuilder(v) => v.ty_to_tokens(tokens),
@ -947,6 +1014,7 @@ impl HdlLetKindToTokens for HdlLetKind {
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
match self {
HdlLetKind::IO(v) => v.expr_to_tokens(tokens),
HdlLetKind::AddPlatformIO(v) => v.expr_to_tokens(tokens),
HdlLetKind::Incomplete(v) => v.expr_to_tokens(tokens),
HdlLetKind::Instance(v) => v.expr_to_tokens(tokens),
HdlLetKind::RegBuilder(v) => v.expr_to_tokens(tokens),
@ -1149,7 +1217,7 @@ impl<T: ToString> ToTokens for ImplicitName<T> {
struct Visitor<'a> {
module_kind: Option<ModuleKind>,
errors: Errors,
io: Vec<ModuleIO>,
io: ModuleIOOrAddPlatformIO,
block_depth: usize,
parsed_generics: &'a ParsedGenerics,
}
@ -1289,7 +1357,81 @@ impl Visitor<'_> {
}),
semi_token: hdl_let.semi_token,
};
self.io.push(hdl_let);
match &mut self.io {
ModuleIOOrAddPlatformIO::ModuleIO(io) => io.push(hdl_let),
ModuleIOOrAddPlatformIO::AddPlatformIO => {
self.errors.error(
kind,
"can't have other inputs/outputs in a module using m.add_platform_io()",
);
}
}
let_stmt
}
fn process_hdl_let_add_platform_io(
&mut self,
hdl_let: HdlLet<HdlLetKindAddPlatformIO>,
) -> Local {
let HdlLet {
mut attrs,
hdl_attr: _,
let_token,
mut_token,
ref name,
eq_token,
kind:
HdlLetKindAddPlatformIO {
m,
dot_token,
add_platform_io,
paren,
platform_io_builder,
},
semi_token,
} = hdl_let;
let mut expr = quote! {#m #dot_token #add_platform_io};
paren.surround(&mut expr, |expr| {
let name_str = ImplicitName {
name,
span: name.span(),
};
quote_spanned! {name.span()=>
#name_str, #platform_io_builder
}
.to_tokens(expr);
});
self.require_module(add_platform_io);
attrs.push(parse_quote_spanned! {let_token.span=>
#[allow(unused_variables)]
});
let let_stmt = Local {
attrs,
let_token,
pat: parse_quote! { #mut_token #name },
init: Some(LocalInit {
eq_token,
expr: parse_quote! { #expr },
diverge: None,
}),
semi_token,
};
match &mut self.io {
ModuleIOOrAddPlatformIO::ModuleIO(io) => {
for io in io {
self.errors.error(
io.kind.kind,
"can't have other inputs/outputs in a module using m.add_platform_io()",
);
}
}
ModuleIOOrAddPlatformIO::AddPlatformIO => {
self.errors.error(
add_platform_io,
"can't use m.add_platform_io() more than once in a single module",
);
}
}
self.io = ModuleIOOrAddPlatformIO::AddPlatformIO;
let_stmt
}
fn process_hdl_let_instance(&mut self, hdl_let: HdlLet<HdlLetKindInstance>) -> Local {
@ -1510,6 +1652,7 @@ impl Visitor<'_> {
}
the_match! {
IO => process_hdl_let_io,
AddPlatformIO => process_hdl_let_add_platform_io,
Incomplete => process_hdl_let_incomplete,
Instance => process_hdl_let_instance,
RegBuilder => process_hdl_let_reg_builder,
@ -1753,15 +1896,20 @@ impl Fold for Visitor<'_> {
}
}
pub(crate) enum ModuleIOOrAddPlatformIO {
ModuleIO(Vec<ModuleIO>),
AddPlatformIO,
}
pub(crate) fn transform_body(
module_kind: Option<ModuleKind>,
mut body: Box<Block>,
parsed_generics: &ParsedGenerics,
) -> syn::Result<(Box<Block>, Vec<ModuleIO>)> {
) -> syn::Result<(Box<Block>, ModuleIOOrAddPlatformIO)> {
let mut visitor = Visitor {
module_kind,
errors: Errors::new(),
io: vec![],
io: ModuleIOOrAddPlatformIO::ModuleIO(vec![]),
block_depth: 0,
parsed_generics,
};

View file

@ -99,12 +99,12 @@ pub mod intern;
pub mod memory;
pub mod module;
pub mod phantom_const;
pub mod platform;
pub mod prelude;
pub mod reg;
pub mod reset;
pub mod sim;
pub mod source_location;
pub mod target;
pub mod testing;
pub mod ty;
pub mod util;

View file

@ -19,6 +19,7 @@ use crate::{
int::{Bool, DynSize, Size},
intern::{Intern, Interned},
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
platform::PlatformIOBuilder,
reg::Reg,
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
sim::{ExternModuleSimGenerator, ExternModuleSimulation},
@ -2119,6 +2120,27 @@ impl ModuleBuilder {
self.output_with_loc(implicit_name.0, SourceLocation::caller(), ty)
}
#[track_caller]
pub fn add_platform_io_with_loc(
&self,
name: &str,
source_location: SourceLocation,
platform_io_builder: PlatformIOBuilder<'_>,
) -> Expr<Bundle> {
platform_io_builder.add_platform_io(name, source_location, self)
}
#[track_caller]
pub fn add_platform_io(
&self,
implicit_name: ImplicitName<'_>,
platform_io_builder: PlatformIOBuilder<'_>,
) -> Expr<Bundle> {
self.add_platform_io_with_loc(
implicit_name.0,
SourceLocation::caller(),
platform_io_builder,
)
}
#[track_caller]
pub fn run<T: BundleType>(
name: &str,
module_kind: ModuleKind,
@ -2743,6 +2765,22 @@ impl<T: Type> ModuleIO<T> {
source_location,
}
}
pub fn from_canonical(canonical_module_io: ModuleIO<CanonicalType>) -> Self {
let ModuleIO {
containing_module_name,
bundle_field,
id,
ty,
source_location,
} = canonical_module_io;
Self {
containing_module_name,
bundle_field,
id,
ty: T::from_canonical(ty),
source_location,
}
}
pub fn bundle_field(&self) -> BundleField {
self.bundle_field
}

File diff suppressed because it is too large Load diff

View file

@ -1,202 +0,0 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{intern::Interned, util::job_server::AcquiredJob};
use std::{
any::Any,
fmt,
iter::FusedIterator,
sync::{Arc, Mutex},
};
pub trait Peripheral: Any + Send + Sync + fmt::Debug {}
pub trait Tool: Any + Send + Sync + fmt::Debug {
fn name(&self) -> Interned<str>;
fn run(&self, acquired_job: &mut AcquiredJob);
}
pub trait Target: Any + Send + Sync + fmt::Debug {
fn name(&self) -> Interned<str>;
fn peripherals(&self) -> Interned<[Interned<dyn Peripheral>]>;
}
#[derive(Clone)]
struct TargetsMap(Vec<(Interned<str>, Interned<dyn Target>)>);
impl TargetsMap {
fn sort(&mut self) {
self.0.sort_by(|(k1, _), (k2, _)| str::cmp(k1, k2));
self.0.dedup_by_key(|(k, _)| *k);
}
fn from_unsorted_vec(unsorted_vec: Vec<(Interned<str>, Interned<dyn Target>)>) -> Self {
let mut retval = Self(unsorted_vec);
retval.sort();
retval
}
fn extend_from_unsorted_slice(&mut self, additional: &[(Interned<str>, Interned<dyn Target>)]) {
self.0.extend_from_slice(additional);
self.sort();
}
}
impl Default for TargetsMap {
fn default() -> Self {
Self::from_unsorted_vec(vec![
// TODO: add default targets here
])
}
}
fn access_targets<F: FnOnce(&mut Option<Arc<TargetsMap>>) -> R, R>(f: F) -> R {
static TARGETS: Mutex<Option<Arc<TargetsMap>>> = Mutex::new(None);
let mut targets_lock = TARGETS.lock().expect("shouldn't be poisoned");
f(&mut targets_lock)
}
pub fn add_targets<I: IntoIterator<Item = Interned<dyn Target>>>(additional: I) {
// run iterator and target methods outside of lock
let additional = Vec::from_iter(additional.into_iter().map(|v| (v.name(), v)));
access_targets(|targets| {
Arc::make_mut(targets.get_or_insert_default()).extend_from_unsorted_slice(&additional);
});
}
pub fn targets() -> TargetsSnapshot {
access_targets(|targets| match targets {
Some(targets) => TargetsSnapshot {
targets: targets.clone(),
},
None => {
let new_targets = Arc::<TargetsMap>::default();
*targets = Some(new_targets.clone());
TargetsSnapshot {
targets: new_targets,
}
}
})
}
#[derive(Clone)]
pub struct TargetsSnapshot {
targets: Arc<TargetsMap>,
}
impl TargetsSnapshot {
pub fn get(&self, key: &str) -> Option<Interned<dyn Target>> {
let index = self
.targets
.0
.binary_search_by_key(&key, |(k, _v)| k)
.ok()?;
Some(self.targets.0[index].1)
}
pub fn iter(&self) -> TargetsIter {
self.into_iter()
}
pub fn len(&self) -> usize {
self.targets.0.len()
}
}
impl fmt::Debug for TargetsSnapshot {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("TargetsSnapshot ")?;
f.debug_map().entries(self).finish()
}
}
impl IntoIterator for &'_ mut TargetsSnapshot {
type Item = (Interned<str>, Interned<dyn Target>);
type IntoIter = TargetsIter;
fn into_iter(self) -> Self::IntoIter {
self.clone().into_iter()
}
}
impl IntoIterator for &'_ TargetsSnapshot {
type Item = (Interned<str>, Interned<dyn Target>);
type IntoIter = TargetsIter;
fn into_iter(self) -> Self::IntoIter {
self.clone().into_iter()
}
}
impl IntoIterator for TargetsSnapshot {
type Item = (Interned<str>, Interned<dyn Target>);
type IntoIter = TargetsIter;
fn into_iter(self) -> Self::IntoIter {
TargetsIter {
indexes: 0..self.targets.0.len(),
targets: self.targets,
}
}
}
#[derive(Clone)]
pub struct TargetsIter {
targets: Arc<TargetsMap>,
indexes: std::ops::Range<usize>,
}
impl fmt::Debug for TargetsIter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("TargetsIter ")?;
f.debug_map().entries(self.clone()).finish()
}
}
impl Iterator for TargetsIter {
type Item = (Interned<str>, Interned<dyn Target>);
fn next(&mut self) -> Option<Self::Item> {
Some(self.targets.0[self.indexes.next()?])
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.indexes.size_hint()
}
fn count(self) -> usize {
self.indexes.len()
}
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
Some(self.targets.0[self.indexes.nth(n)?])
}
fn fold<B, F: FnMut(B, Self::Item) -> B>(self, init: B, mut f: F) -> B {
self.indexes
.fold(init, move |retval, index| f(retval, self.targets.0[index]))
}
}
impl FusedIterator for TargetsIter {}
impl DoubleEndedIterator for TargetsIter {
fn next_back(&mut self) -> Option<Self::Item> {
Some(self.targets.0[self.indexes.next_back()?])
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
Some(self.targets.0[self.indexes.nth_back(n)?])
}
fn rfold<B, F: FnMut(B, Self::Item) -> B>(self, init: B, mut f: F) -> B {
self.indexes
.rfold(init, move |retval, index| f(retval, self.targets.0[index]))
}
}
impl ExactSizeIterator for TargetsIter {
fn len(&self) -> usize {
self.indexes.len()
}
}

View file

@ -6,6 +6,7 @@ use fayalite::{
int::{UIntInRange, UIntInRangeInclusive},
intern::Intern,
module::transform::simplify_enums::SimplifyEnumsKind,
platform::PlatformIOBuilder,
prelude::*,
reset::ResetType,
ty::StaticType,
@ -4631,3 +4632,55 @@ circuit check_uint_in_range:
",
};
}
#[hdl_module(outline_generated)]
pub fn check_platform_io(platform_io_builder: PlatformIOBuilder<'_>) {
#[hdl]
let io = m.add_platform_io(platform_io_builder);
}
#[cfg(todo)]
#[test]
fn test_platform_io() {
let _n = SourceLocation::normalize_files_for_tests();
let m = check_platform_io(todo!());
dbg!(m);
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
assert_export_firrtl! {
m =>
"/test/check_platform_io.fir": r"FIRRTL version 3.2.0
circuit check_platform_io:
type Ty0 = {value: UInt<0>, range: {}}
type Ty1 = {value: UInt<1>, range: {}}
type Ty2 = {value: UInt<2>, range: {}}
type Ty3 = {value: UInt<2>, range: {}}
type Ty4 = {value: UInt<3>, range: {}}
type Ty5 = {value: UInt<3>, range: {}}
type Ty6 = {value: UInt<4>, range: {}}
type Ty7 = {value: UInt<0>, range: {}}
type Ty8 = {value: UInt<1>, range: {}}
type Ty9 = {value: UInt<2>, range: {}}
type Ty10 = {value: UInt<2>, range: {}}
type Ty11 = {value: UInt<3>, range: {}}
type Ty12 = {value: UInt<3>, range: {}}
type Ty13 = {value: UInt<4>, range: {}}
type Ty14 = {value: UInt<4>, range: {}}
module check_platform_io: @[module-XXXXXXXXXX.rs 1:1]
input i_0_to_1: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input i_0_to_2: Ty1 @[module-XXXXXXXXXX.rs 3:1]
input i_0_to_3: Ty2 @[module-XXXXXXXXXX.rs 4:1]
input i_0_to_4: Ty3 @[module-XXXXXXXXXX.rs 5:1]
input i_0_to_7: Ty4 @[module-XXXXXXXXXX.rs 6:1]
input i_0_to_8: Ty5 @[module-XXXXXXXXXX.rs 7:1]
input i_0_to_9: Ty6 @[module-XXXXXXXXXX.rs 8:1]
input i_0_through_0: Ty7 @[module-XXXXXXXXXX.rs 9:1]
input i_0_through_1: Ty8 @[module-XXXXXXXXXX.rs 10:1]
input i_0_through_2: Ty9 @[module-XXXXXXXXXX.rs 11:1]
input i_0_through_3: Ty10 @[module-XXXXXXXXXX.rs 12:1]
input i_0_through_4: Ty11 @[module-XXXXXXXXXX.rs 13:1]
input i_0_through_7: Ty12 @[module-XXXXXXXXXX.rs 14:1]
input i_0_through_8: Ty13 @[module-XXXXXXXXXX.rs 15:1]
input i_0_through_9: Ty14 @[module-XXXXXXXXXX.rs 16:1]
",
};
}

View file

@ -11,4 +11,20 @@ pub fn my_module(a: i32, m: u32, (m, _): (i32, u32)) {
let o: UInt<8> = m.output();
}
#[hdl_module]
pub fn my_module2(platform_io_builder: PlatformIOBuilder<'_>) {
#[hdl]
let a: UInt<8> = m.input();
#[hdl]
let b: UInt<8> = m.output();
#[hdl]
let io = m.add_platform_io(platform_io_builder);
#[hdl]
let c: UInt<8> = m.input();
#[hdl]
let d: UInt<8> = m.output();
#[hdl]
let io = m.add_platform_io(platform_io_builder);
}
fn main() {}

View file

@ -1,17 +1,47 @@
error: name conflicts with implicit `m: &mut ModuleBuilder<_>`
error: name conflicts with implicit `m: &ModuleBuilder`
--> tests/ui/module.rs:7:26
|
7 | pub fn my_module(a: i32, m: u32, (m, _): (i32, u32)) {
| ^
error: name conflicts with implicit `m: &mut ModuleBuilder<_>`
error: name conflicts with implicit `m: &ModuleBuilder`
--> tests/ui/module.rs:7:35
|
7 | pub fn my_module(a: i32, m: u32, (m, _): (i32, u32)) {
| ^
error: name conflicts with implicit `m: &mut ModuleBuilder<_>`
error: name conflicts with implicit `m: &ModuleBuilder`
--> tests/ui/module.rs:9:9
|
9 | let m: UInt<8> = m.input();
| ^
error: can't have other inputs/outputs in a module using m.add_platform_io()
--> tests/ui/module.rs:17:24
|
17 | let a: UInt<8> = m.input();
| ^^^^^
error: can't have other inputs/outputs in a module using m.add_platform_io()
--> tests/ui/module.rs:19:24
|
19 | let b: UInt<8> = m.output();
| ^^^^^^
error: can't have other inputs/outputs in a module using m.add_platform_io()
--> tests/ui/module.rs:23:24
|
23 | let c: UInt<8> = m.input();
| ^^^^^
error: can't have other inputs/outputs in a module using m.add_platform_io()
--> tests/ui/module.rs:25:24
|
25 | let d: UInt<8> = m.output();
| ^^^^^^
error: can't use m.add_platform_io() more than once in a single module
--> tests/ui/module.rs:27:16
|
27 | let io = m.add_platform_io(platform_io_builder);
| ^^^^^^^^^^^^^^^