add address_range to MemoryInterfaceConfig and add support to simple_uart

This commit is contained in:
Jacob Lifshay 2026-03-02 23:28:01 -08:00
parent 2c8de5bec4
commit 3080ea4ce2
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
5 changed files with 169 additions and 50 deletions

View file

@ -3,16 +3,110 @@
use crate::{config::CpuConfig, next_pc::FETCH_BLOCK_ID_WIDTH, util::array_vec::ArrayVec};
use fayalite::{prelude::*, util::ready_valid::ReadyValid};
use std::num::NonZeroUsize;
use std::num::{NonZeroU64, NonZeroUsize, Wrapping};
pub mod simple_uart;
#[derive(Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
pub enum AddressRange {
Full,
Limited {
start: Wrapping<u64>,
size: NonZeroU64,
},
}
impl AddressRange {
pub const fn from_wrapping_range_inclusive(range: std::ops::RangeInclusive<u64>) -> Self {
let start = Wrapping(*range.start());
let Some(size) = NonZeroU64::new(range.end().wrapping_sub(start.0).wrapping_add(1)) else {
return Self::Full;
};
Self::Limited { start, size }
}
pub const fn try_from_range(range: std::ops::Range<u64>) -> Option<Self> {
let start = Wrapping(range.start);
let Some(size) = NonZeroU64::new(range.end.saturating_sub(range.start)) else {
return None;
};
Some(Self::Limited { start, size })
}
#[track_caller]
pub const fn from_range(range: std::ops::Range<u64>) -> Self {
Self::try_from_range(range).expect("range must not be empty")
}
pub const fn try_from_range_inclusive(range: std::ops::RangeInclusive<u64>) -> Option<Self> {
let start = Wrapping(*range.start());
let Some(end_minus_start) = range.end().checked_sub(start.0) else {
return None;
};
let Some(size) = end_minus_start.checked_add(1) else {
return Some(Self::Full);
};
let Some(size) = NonZeroU64::new(size) else {
unreachable!();
};
Some(Self::Limited { start, size })
}
#[track_caller]
pub const fn from_range_inclusive(range: std::ops::RangeInclusive<u64>) -> Self {
Self::try_from_range_inclusive(range).expect("range must not be empty")
}
pub const fn start(self) -> Wrapping<u64> {
match self {
Self::Full => Wrapping(0),
Self::Limited { start, .. } => start,
}
}
pub const fn size(self) -> Option<NonZeroU64> {
match self {
Self::Full => None,
Self::Limited { size, .. } => Some(size),
}
}
pub const fn size_minus_one(self) -> u64 {
match self {
AddressRange::Full => u64::MAX,
AddressRange::Limited { size, .. } => size.get() - 1,
}
}
/// last address contained in `self`
pub const fn last(self) -> u64 {
self.start().0.wrapping_add(self.size_minus_one())
}
pub const fn contains(self, address: u64) -> bool {
match self {
Self::Full => true,
Self::Limited { start, size } => address.wrapping_sub(start.0) < size.get(),
}
}
pub const fn wrapping_add(self, offset: u64) -> Self {
match self {
Self::Full => Self::Full,
Self::Limited { start, size } => Self::Limited {
start: Wrapping(start.0.wrapping_add(offset)),
size,
},
}
}
pub const fn wrapping_sub(self, offset: u64) -> Self {
match self {
Self::Full => Self::Full,
Self::Limited { start, size } => Self::Limited {
start: Wrapping(start.0.wrapping_sub(offset)),
size,
},
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
#[non_exhaustive]
pub struct MemoryInterfaceConfig {
pub log2_bus_width_in_bytes: u8,
pub queue_capacity: NonZeroUsize,
pub op_id_width: usize,
pub address_range: AddressRange,
}
impl MemoryInterfaceConfig {
@ -21,6 +115,7 @@ impl MemoryInterfaceConfig {
log2_bus_width_in_bytes: config.log2_fetch_width_in_bytes,
queue_capacity: config.max_fetches_in_flight,
op_id_width: FETCH_BLOCK_ID_WIDTH,
address_range: AddressRange::Full,
}
}
pub const fn bus_width_in_bytes(&self) -> usize {

View file

@ -1,12 +1,13 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use std::num::NonZeroUsize;
use std::num::{NonZeroU64, NonZeroUsize, Wrapping};
use crate::{
main_memory_and_io::{
MemoryInterface, MemoryInterfaceConfig, MemoryOperationErrorKind, MemoryOperationFinish,
MemoryOperationFinishKind, MemoryOperationKind, MemoryOperationStart,
AddressRange, MemoryInterface, MemoryInterfaceConfig, MemoryOperationErrorKind,
MemoryOperationFinish, MemoryOperationFinishKind, MemoryOperationKind,
MemoryOperationStart,
},
util::array_vec::ArrayVec,
};
@ -357,7 +358,8 @@ pub fn receiver(queue_capacity: NonZeroUsize) {
pub const SIMPLE_UART_RECEIVE_OFFSET: u64 = 0;
pub const SIMPLE_UART_TRANSMIT_OFFSET: u64 = 0;
pub const SIMPLE_UART_STATUS_OFFSET: u64 = 1;
pub const SIMPLE_UART_SIZE: u64 = 1 << SIMPLE_UART_LOG2_SIZE;
pub const SIMPLE_UART_SIZE: NonZeroU64 =
NonZeroU64::new(1 << SIMPLE_UART_LOG2_SIZE).expect("known to be non-zero");
pub const SIMPLE_UART_LOG2_SIZE: u8 = 1;
#[hdl(no_static)]
@ -366,11 +368,22 @@ struct Operation<C: PhantomConstGet<MemoryInterfaceConfig>> {
finish: HdlOption<MemoryOperationFinish<C>>,
}
pub const fn simple_uart_memory_interface_config(op_id_width: usize) -> MemoryInterfaceConfig {
pub const fn simple_uart_memory_interface_config(
op_id_width: usize,
start_address: Wrapping<u64>,
) -> MemoryInterfaceConfig {
assert!(
start_address.0 % SIMPLE_UART_SIZE.get() == 0,
"start_address must be properly aligned"
);
MemoryInterfaceConfig {
log2_bus_width_in_bytes: SIMPLE_UART_LOG2_SIZE,
queue_capacity: const { NonZeroUsize::new(1).unwrap() },
op_id_width,
address_range: AddressRange::Limited {
start: start_address,
size: SIMPLE_UART_SIZE,
},
}
}
@ -381,9 +394,10 @@ pub fn simple_uart(
baud_rate: f64,
receiver_queue_size: NonZeroUsize,
) {
let start_address = config.get().address_range.start();
assert_eq!(
*config.get(),
simple_uart_memory_interface_config(config.get().op_id_width),
simple_uart_memory_interface_config(config.get().op_id_width, start_address),
);
#[hdl]
let cd: ClockDomain = m.input();
@ -486,14 +500,18 @@ pub fn simple_uart(
match kind {
MemoryOperationKind::Read => {
#[hdl]
if byte_addr.cmp_eq(SIMPLE_UART_RECEIVE_OFFSET) {
if byte_addr
.cmp_eq(start_address.0.wrapping_add(SIMPLE_UART_RECEIVE_OFFSET))
{
connect(receiver.output_byte.ready, valid_addr);
#[hdl]
if let HdlSome(byte) = receiver.output_byte.data {
connect(read_data, byte);
}
// if there is no byte ready yet, we read a zero to avoid blocking the CPU on external inputs.
} else if byte_addr.cmp_eq(SIMPLE_UART_STATUS_OFFSET) {
} else if byte_addr
.cmp_eq(start_address.0.wrapping_add(SIMPLE_UART_STATUS_OFFSET))
{
connect(
read_data,
receiver
@ -507,7 +525,9 @@ pub fn simple_uart(
}
MemoryOperationKind::Write => {
#[hdl]
if byte_addr.cmp_eq(SIMPLE_UART_TRANSMIT_OFFSET) {
if byte_addr
.cmp_eq(start_address.0.wrapping_add(SIMPLE_UART_TRANSMIT_OFFSET))
{
#[hdl]
if !transmitter.input_byte.ready {
connect(all_ready, false);

View file

@ -3633,7 +3633,7 @@ b0 UA{3,"
0mS#3<"
0^qjb["
b0 tN>yu"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) '@T[?"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) '@T[?"
0BXk&["
sHdlNone\x20(0) &wG|&"
sSuccess\x20(0) ^F2z4"
@ -3647,7 +3647,7 @@ b0 VXdV?"
b0 =`@6L"
b0 e2JF6"
b0 ]ocL{"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) ^<ah9"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) ^<ah9"
02sb.i"
sHdlNone\x20(0) JC:kM"
b0 .*4N""
@ -3668,7 +3668,7 @@ b0 huWrb"
b0 EO39y"
b0 |d_{U"
sPhantomConst(\"0..=16\") 3(idJ"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) P'(UK"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) P'(UK"
sHdlSome\x20(1) N^Lck"
b1000000000000 q3ltq"
b0 zZOnr"
@ -3756,7 +3756,7 @@ b0 46)Xi"
0"(@LS"
0&NGtM"
b0 "tB6}"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) Hn\.r"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) Hn\.r"
0jbUZ8"
sHdlNone\x20(0) NcD^Z"
sSuccess\x20(0) X3rb0"
@ -3770,7 +3770,7 @@ b0 vyE_1"
b0 D}2RZ"
b0 \XUCp"
b0 [^@q%"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) G4KC#"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) G4KC#"
01thaQ"
sHdlNone\x20(0) +5LtZ"
b0 {6^Pl"
@ -3791,7 +3791,7 @@ b0 iB{BF"
b0 eR=Hx"
b0 8!8=?"
sPhantomConst(\"0..=16\") V?X!X"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) T-cQB"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) T-cQB"
sHdlSome\x20(1) JqP67"
b1000000000000 iRy|N"
b0 IIeMq"
@ -4439,7 +4439,7 @@ b0 H{?Xz"
03\z-w"
00^&W_"
b0 n/%-/"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) ./0U4"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) ./0U4"
0NE4rt"
sHdlNone\x20(0) :GU,#"
sSuccess\x20(0) D87*9"
@ -4453,7 +4453,7 @@ b0 d%H]f"
b0 zgzi@"
b0 7B-!)"
b0 Y1Qf)"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) a.$Aw"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) a.$Aw"
0*d$ca"
sHdlNone\x20(0) /N@6H"
b0 '10Cg"
@ -4474,7 +4474,7 @@ b0 hn|]["
b0 bWF^\"
b0 -"k'e"
sPhantomConst(\"0..=16\") uoZP0"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) /KK^t"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) /KK^t"
sHdlSome\x20(1) e\)?v"
b1000000000000 %G_Dt"
b0 E7iTa"
@ -4919,7 +4919,7 @@ b0 H{?Xz
03\z-w
00^&W_
b0 n/%-/
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) ./0U4
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) ./0U4
0NE4rt
sHdlNone\x20(0) :GU,#
sSuccess\x20(0) D87*9
@ -4933,7 +4933,7 @@ b0 d%H]f
b0 zgzi@
b0 7B-!)
b0 Y1Qf)
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) a.$Aw
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) a.$Aw
0*d$ca
sHdlNone\x20(0) /N@6H
b0 '10Cg
@ -4954,7 +4954,7 @@ b0 hn|][
b0 bWF^\
b0 -"k'e
sPhantomConst(\"0..=16\") uoZP0
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) /KK^t
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) /KK^t
sHdlSome\x20(1) e\)?v
b1000000000000 %G_Dt
b0 E7iTa
@ -5399,7 +5399,7 @@ b0 46)Xi
0"(@LS
0&NGtM
b0 "tB6}
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) Hn\.r
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) Hn\.r
0jbUZ8
sHdlNone\x20(0) NcD^Z
sSuccess\x20(0) X3rb0
@ -5413,7 +5413,7 @@ b0 vyE_1
b0 D}2RZ
b0 \XUCp
b0 [^@q%
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) G4KC#
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) G4KC#
01thaQ
sHdlNone\x20(0) +5LtZ
b0 {6^Pl
@ -5434,7 +5434,7 @@ b0 iB{BF
b0 eR=Hx
b0 8!8=?
sPhantomConst(\"0..=16\") V?X!X
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) T-cQB
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) T-cQB
sHdlSome\x20(1) JqP67
b1000000000000 iRy|N
b0 IIeMq
@ -5522,7 +5522,7 @@ b0 UA{3,
0mS#3<
0^qjb[
b0 tN>yu
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) '@T[?
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) '@T[?
0BXk&[
sHdlNone\x20(0) &wG|&
sSuccess\x20(0) ^F2z4
@ -5536,7 +5536,7 @@ b0 VXdV?
b0 =`@6L
b0 e2JF6
b0 ]ocL{
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) ^<ah9
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) ^<ah9
02sb.i
sHdlNone\x20(0) JC:kM
b0 .*4N"
@ -5557,7 +5557,7 @@ b0 huWrb
b0 EO39y
b0 |d_{U
sPhantomConst(\"0..=16\") 3(idJ
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) P'(UK
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) P'(UK
sHdlSome\x20(1) N^Lck
b1000000000000 q3ltq
b0 zZOnr
@ -5645,7 +5645,7 @@ b0 %poA2"
0Bw<V4"
0'@.QH"
b0 !3G%M"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) nRws$"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) nRws$"
0";E`m"
sHdlNone\x20(0) QVVGm"
sSuccess\x20(0) H{!U&"
@ -5659,7 +5659,7 @@ b0 hCJZ("
b0 yV&`["
b0 o&C+Q"
b0 :R>Z\"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) %zH|b"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) %zH|b"
0'(8m+"
sHdlNone\x20(0) MMwRE"
b0 96-j|"
@ -5680,7 +5680,7 @@ b0 n:O1E"
b0 \TnT)"
b0 %KEY#"
sPhantomConst(\"0..=16\") 2S<L;"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) <f)US"
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) <f)US"
b0 i/#1{"
b0 $/d2*"
b0 mdUW+"
@ -5753,7 +5753,7 @@ b0 %poA2
0Bw<V4
0'@.QH
b0 !3G%M
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) nRws$
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) nRws$
0";E`m
sHdlNone\x20(0) QVVGm
sSuccess\x20(0) H{!U&
@ -5767,7 +5767,7 @@ b0 hCJZ(
b0 yV&`[
b0 o&C+Q
b0 :R>Z\
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) %zH|b
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) %zH|b
0'(8m+
sHdlNone\x20(0) MMwRE
b0 96-j|
@ -5788,7 +5788,7 @@ b0 n:O1E
b0 \TnT)
b0 %KEY#
sPhantomConst(\"0..=16\") 2S<L;
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8}) <f)US
sPhantomConst({\"log2_bus_width_in_bytes\":3,\"queue_capacity\":16,\"op_id_width\":8,\"address_range\":\"Full\"}) <f)US
b0 i/#1{
b0 $/d2*
b0 mdUW+

View file

@ -549,7 +549,7 @@ b0 YK<TM
0dM>i/
0f><7V
b0 #+y/d
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) k$)j$
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) k$)j$
1z'<O{
sHdlNone\x20(0) kC4Z@
sSuccess\x20(0) DSj6>
@ -557,13 +557,13 @@ sRead\x20(0) i8%Hy
sGeneric\x20(0) }u<b|
b0 [i|C-
b0 NB*xP
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) b|P(G
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) b|P(G
0p\ULz
sHdlSome\x20(1) $x:NB
b0 E*{c-
0:C'8U
sPhantomConst(\"0..=1\") E=NM+
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) eQf|o
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) eQf|o
1-x}z)
0*K&(X
1N12hA
@ -575,7 +575,7 @@ b0 ^'LkA
0LMy1=
0YG=uN
b0 ),#g]
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) pukV=
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) pukV=
1\u*{A
sHdlNone\x20(0) ax>!d
sSuccess\x20(0) $TH!~
@ -583,13 +583,13 @@ sRead\x20(0) @nru
sGeneric\x20(0) =rNet
b0 _aF6z
b0 fBY~q
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) 3Cr%:
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) 3Cr%:
0jP_rY
sHdlSome\x20(1) fl1G|
b0 >-gg}
0d2Gl|
sPhantomConst(\"0..=1\") |@PWl
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) 7A<7@
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) 7A<7@
1?:DT^
1*V%!4
01-L[%
@ -730,14 +730,14 @@ b0 &]$B;
0N-YM;
0R,uS'
b0 GEq-0
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) ,;U@A
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) ,;U@A
sHdlNone\x20(0) 0?MV,
sSuccess\x20(0) D>VoK
sRead\x20(0) d8ku7
sGeneric\x20(0) Y[<1d
b0 .^N`/
b0 'ThQe
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) 8pZSz
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) 8pZSz
1'LW/7
1(+=/^
b0 Whx|K
@ -752,7 +752,7 @@ b0 qwy9i
044.En
0Pq(.9
b0 4zG]Q
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) MTVBb
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) MTVBb
1IifsN
sHdlNone\x20(0) EA1Ra
sSuccess\x20(0) [<sgF
@ -760,13 +760,13 @@ sRead\x20(0) j.}nI
sGeneric\x20(0) z\\(W
b0 Z*eyX
b0 MRBv>
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) {[zRy
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) {[zRy
0q2OoF
sHdlSome\x20(1) d#Of8
b0 J4y0s
0vC#Sj
sPhantomConst(\"0..=1\") ye/Gl
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8}) bH=hU
sPhantomConst({\"log2_bus_width_in_bytes\":1,\"queue_capacity\":1,\"op_id_width\":8,\"address_range\":{\"Limited\":{\"start\":0,\"size\":2}}}) bH=hU
1"QAdC
1K%|4s
$end

View file

@ -21,7 +21,11 @@ use fayalite::{
sim::vcd::VcdWriterDecls,
util::{RcWriter, ready_valid::ReadyValid},
};
use std::{borrow::BorrowMut, marker::PhantomData, num::NonZeroUsize};
use std::{
borrow::BorrowMut,
marker::PhantomData,
num::{NonZeroUsize, Wrapping},
};
const fn half_period(frequency: f64) -> SimDuration {
SimDuration::from_attos((SimDuration::from_secs(1).as_attos() as f64 / frequency / 2.0) as u128)
@ -603,7 +607,7 @@ fn simple_uart_loopback(
}
const SIMPLE_UART_MEMORY_INTERFACE_CONFIG: MemoryInterfaceConfig =
simple_uart_memory_interface_config(FETCH_BLOCK_ID_WIDTH);
simple_uart_memory_interface_config(FETCH_BLOCK_ID_WIDTH, Wrapping(0));
struct MemoryOperationRunner<Sim: BorrowMut<Simulation<T>>, T: BundleType> {
sim: Sim,
@ -916,10 +920,10 @@ fn test_simple_uart() {
for i in 0..2 * BUS_WIDTH_IN_BYTES as u64 {
mem_op_runner
.read_bytes::<1>(SIMPLE_UART_SIZE + i, 1)
.read_bytes::<1>(SIMPLE_UART_SIZE.get() + i, 1)
.unwrap_err();
mem_op_runner
.write_bytes(SIMPLE_UART_SIZE + i, [0], 1)
.write_bytes(SIMPLE_UART_SIZE.get() + i, [0], 1)
.unwrap_err();
}