Compare commits

...

5 commits

Author SHA1 Message Date
1c63a441a9
add needed tools to CI
Some checks failed
/ test (push) Failing after 1m5s
2024-10-03 00:35:43 -07:00
0cf01600b3
add mod formal and move assert/assume/cover stuff to it 2024-10-01 19:56:17 -07:00
f3d6528f5b
make annotations easier to use 2024-10-01 19:54:17 -07:00
f35d88d2bb
remove unused valueless.rs 2024-10-01 18:41:41 -07:00
e8c393f3bb
sort pub mod items 2024-10-01 18:40:52 -07:00
11 changed files with 401 additions and 285 deletions

View file

@ -11,10 +11,28 @@ jobs:
fetch-depth: 0
- run: |
scripts/check-copyright.sh
- run: |
apt-get update -qq
apt-get install -qq cvc5 z3
- run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.80.1
source "$HOME/.cargo/env"
echo "$PATH" >> "$GITHUB_PATH"
- run: |
git clone --depth=1 --branch=yosys-0.45 https://github.com/YosysHQ/sby.git
make -C sby install
- run: |
git clone --depth=1 --branch=0.45 https://github.com/YosysHQ/yosys.git
cd yosys
autoconf -f
./configure
make install -j6
- run: |
wget -O firrtl.tar.gz https://github.com/llvm/circt/releases/download/firtool-1.86.0/firrtl-bin-linux-x64.tar.gz
sha256sum -c - <<<'bf6f4ab18ae76f135c944efbd81e25391c31c1bd0617c58ab0592640abefee14 firrtl.tar.gz'
tar -xvaf firrtl.tar.gz
export PATH="$(realpath firtool-1.86.0/bin):$PATH"
echo "$PATH" >> "$GITHUB_PATH"
- uses: https://github.com/Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/master' }}

View file

@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize};
use std::{
fmt,
hash::{Hash, Hasher},
iter::FusedIterator,
ops::Deref,
};
@ -118,6 +119,9 @@ pub struct CustomFirrtlAnnotation {
pub additional_fields: CustomFirrtlAnnotationFields,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
pub struct DontTouchAnnotation;
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
pub struct SVAttributeAnnotation {
pub text: Interned<str>,
@ -139,15 +143,63 @@ pub struct DocStringAnnotation {
pub text: Interned<str>,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
#[non_exhaustive]
pub enum Annotation {
DontTouch,
SVAttribute(SVAttributeAnnotation),
BlackBoxInline(BlackBoxInlineAnnotation),
BlackBoxPath(BlackBoxPathAnnotation),
DocString(DocStringAnnotation),
CustomFirrtl(CustomFirrtlAnnotation),
macro_rules! make_annotation_enum {
(
$(#[$meta:meta])*
$vis:vis enum $Annotation:ident {
$($Variant:ident($T:ident),)*
}
) => {
$(#[$meta])*
$vis enum $Annotation {
$($Variant($T),)*
}
$(impl IntoAnnotations for $T {
type IntoAnnotations = [$Annotation; 1];
fn into_annotations(self) -> Self::IntoAnnotations {
[$Annotation::$Variant(self)]
}
}
impl IntoAnnotations for &'_ $T {
type IntoAnnotations = [$Annotation; 1];
fn into_annotations(self) -> Self::IntoAnnotations {
[$Annotation::$Variant(*self)]
}
}
impl IntoAnnotations for &'_ mut $T {
type IntoAnnotations = [$Annotation; 1];
fn into_annotations(self) -> Self::IntoAnnotations {
[$Annotation::$Variant(*self)]
}
}
impl IntoAnnotations for Box<$T> {
type IntoAnnotations = [$Annotation; 1];
fn into_annotations(self) -> Self::IntoAnnotations {
[$Annotation::$Variant(*self)]
}
})*
};
}
make_annotation_enum! {
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
#[non_exhaustive]
pub enum Annotation {
DontTouch(DontTouchAnnotation),
SVAttribute(SVAttributeAnnotation),
BlackBoxInline(BlackBoxInlineAnnotation),
BlackBoxPath(BlackBoxPathAnnotation),
DocString(DocStringAnnotation),
CustomFirrtl(CustomFirrtlAnnotation),
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
@ -212,10 +264,70 @@ impl IntoAnnotations for &'_ mut Annotation {
}
}
impl<T: IntoIterator<Item = Annotation>> IntoAnnotations for T {
type IntoAnnotations = Self;
pub struct IterIntoAnnotations<T: Iterator<Item: IntoAnnotations>> {
outer: T,
inner: Option<<<T::Item as IntoAnnotations>::IntoAnnotations as IntoIterator>::IntoIter>,
}
fn into_annotations(self) -> Self::IntoAnnotations {
self
impl<T: Iterator<Item: IntoAnnotations>> Iterator for IterIntoAnnotations<T> {
type Item = Annotation;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(inner) = &mut self.inner {
let Some(retval) = inner.next() else {
self.inner = None;
continue;
};
return Some(retval);
} else {
self.inner = Some(self.outer.next()?.into_annotations().into_iter());
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
if let (0, Some(0)) = self.outer.size_hint() {
self.inner
.as_ref()
.map(|v| v.size_hint())
.unwrap_or((0, Some(0)))
} else {
(
self.inner.as_ref().map(|v| v.size_hint().0).unwrap_or(0),
None,
)
}
}
fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.inner
.into_iter()
.chain(self.outer.map(|v| v.into_annotations().into_iter()))
.flatten()
.fold(init, f)
}
}
impl<
T: FusedIterator<
Item: IntoAnnotations<IntoAnnotations: IntoIterator<IntoIter: FusedIterator>>,
>,
> FusedIterator for IterIntoAnnotations<T>
{
}
impl<T: IntoIterator<Item: IntoAnnotations>> IntoAnnotations for T {
type IntoAnnotations = IterIntoAnnotations<T::IntoIter>;
fn into_annotations(self) -> Self::IntoAnnotations {
IterIntoAnnotations {
outer: self.into_iter(),
inner: None,
}
}
}

View file

@ -4,7 +4,7 @@
use crate::{
annotations::{
Annotation, BlackBoxInlineAnnotation, BlackBoxPathAnnotation, CustomFirrtlAnnotation,
DocStringAnnotation, SVAttributeAnnotation,
DocStringAnnotation, DontTouchAnnotation, SVAttributeAnnotation,
},
array::Array,
bundle::{Bundle, BundleField, BundleType},
@ -17,6 +17,7 @@ use crate::{
},
Expr, ExprEnum,
},
formal::FormalKind,
int::{Bool, DynSize, IntType, SIntValue, UInt, UIntValue},
intern::{Intern, Interned},
memory::{Mem, PortKind, PortName, ReadUnderWrite},
@ -27,8 +28,8 @@ use crate::{
},
AnnotatedModuleIO, Block, ExternModuleBody, ExternModuleParameter,
ExternModuleParameterValue, Module, ModuleBody, NameId, NormalModuleBody, Stmt,
StmtConnect, StmtDeclaration, StmtFormal, StmtFormalKind, StmtIf, StmtInstance, StmtMatch,
StmtReg, StmtWire,
StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg,
StmtWire,
},
reset::{AsyncReset, Reset, SyncReset},
source_location::SourceLocation,
@ -1805,7 +1806,7 @@ impl<'a> Exporter<'a> {
}
fn annotation(&mut self, path: AnnotationTargetPath, annotation: &Annotation) {
let data = match annotation {
Annotation::DontTouch => AnnotationData::DontTouch,
Annotation::DontTouch(DontTouchAnnotation {}) => AnnotationData::DontTouch,
Annotation::SVAttribute(SVAttributeAnnotation { text }) => {
AnnotationData::AttributeAnnotation { description: *text }
}
@ -2011,9 +2012,9 @@ impl<'a> Exporter<'a> {
let pred = self.expr(Expr::canonical(pred), &definitions, false);
let en = self.expr(Expr::canonical(en), &definitions, false);
let kind = match kind {
StmtFormalKind::Assert => "assert",
StmtFormalKind::Assume => "assume",
StmtFormalKind::Cover => "cover",
FormalKind::Assert => "assert",
FormalKind::Assume => "assume",
FormalKind::Cover => "cover",
};
let text = EscapedString {
value: &text,

View file

@ -0,0 +1,186 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{intern::Intern, prelude::*};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum FormalKind {
Assert,
Assume,
Cover,
}
impl FormalKind {
pub fn as_str(self) -> &'static str {
match self {
Self::Assert => "assert",
Self::Assume => "assume",
Self::Cover => "cover",
}
}
}
#[track_caller]
pub fn formal_stmt_with_enable_and_loc(
kind: FormalKind,
clk: Expr<Clock>,
pred: Expr<Bool>,
en: Expr<Bool>,
text: &str,
source_location: SourceLocation,
) {
crate::module::add_stmt_formal(crate::module::StmtFormal {
kind,
clk,
pred,
en,
text: text.intern(),
source_location,
});
}
#[track_caller]
pub fn formal_stmt_with_enable(
kind: FormalKind,
clk: Expr<Clock>,
pred: Expr<Bool>,
en: Expr<Bool>,
text: &str,
) {
formal_stmt_with_enable_and_loc(kind, clk, pred, en, text, SourceLocation::caller());
}
#[track_caller]
pub fn formal_stmt_with_loc(
kind: FormalKind,
clk: Expr<Clock>,
pred: Expr<Bool>,
text: &str,
source_location: SourceLocation,
) {
formal_stmt_with_enable_and_loc(kind, clk, pred, true.to_expr(), text, source_location);
}
#[track_caller]
pub fn formal_stmt(kind: FormalKind, clk: Expr<Clock>, pred: Expr<Bool>, text: &str) {
formal_stmt_with_loc(kind, clk, pred, text, SourceLocation::caller());
}
macro_rules! make_formal {
($kind:ident, $formal_stmt_with_enable_and_loc:ident, $formal_stmt_with_enable:ident, $formal_stmt_with_loc:ident, $formal_stmt:ident) => {
#[track_caller]
pub fn $formal_stmt_with_enable_and_loc(
clk: Expr<Clock>,
pred: Expr<Bool>,
en: Expr<Bool>,
text: &str,
source_location: SourceLocation,
) {
formal_stmt_with_enable_and_loc(
FormalKind::$kind,
clk,
pred,
en,
text,
source_location,
);
}
#[track_caller]
pub fn $formal_stmt_with_enable(
clk: Expr<Clock>,
pred: Expr<Bool>,
en: Expr<Bool>,
text: &str,
) {
formal_stmt_with_enable(FormalKind::$kind, clk, pred, en, text);
}
#[track_caller]
pub fn $formal_stmt_with_loc(
clk: Expr<Clock>,
pred: Expr<Bool>,
text: &str,
source_location: SourceLocation,
) {
formal_stmt_with_loc(FormalKind::$kind, clk, pred, text, source_location);
}
#[track_caller]
pub fn $formal_stmt(clk: Expr<Clock>, pred: Expr<Bool>, text: &str) {
formal_stmt(FormalKind::$kind, clk, pred, text);
}
};
}
make_formal!(
Assert,
hdl_assert_with_enable_and_loc,
hdl_assert_with_enable,
hdl_assert_with_loc,
hdl_assert
);
make_formal!(
Assume,
hdl_assume_with_enable_and_loc,
hdl_assume_with_enable,
hdl_assume_with_loc,
hdl_assume
);
make_formal!(
Cover,
hdl_cover_with_enable_and_loc,
hdl_cover_with_enable,
hdl_cover_with_loc,
hdl_cover
);
pub trait MakeFormalExpr: Type {}
impl<T: Type> MakeFormalExpr for T {}
#[hdl]
pub fn formal_global_clock() -> Expr<Clock> {
#[hdl_module(extern)]
fn formal_global_clock() {
#[hdl]
let clk: Clock = m.output();
m.annotate_module(BlackBoxInlineAnnotation {
path: "fayalite_formal_global_clock.v".intern(),
text: r"module __fayalite_formal_global_clock(output clk);
(* gclk *)
reg clk;
endmodule
"
.intern(),
});
m.verilog_name("__fayalite_formal_global_clock");
}
#[hdl]
let formal_global_clock = instance(formal_global_clock());
formal_global_clock.clk
}
#[hdl]
pub fn formal_reset() -> Expr<AsyncReset> {
#[hdl_module(extern)]
fn formal_reset() {
#[hdl]
let rst: AsyncReset = m.output();
m.annotate_module(BlackBoxInlineAnnotation {
path: "fayalite_formal_reset.v".intern(),
text: r"module __fayalite_formal_reset(output rst);
reg rst;
(* gclk *)
reg gclk;
initial rst = 1;
always @(posedge gclk)
rst <= 0;
endmodule
"
.intern(),
});
m.verilog_name("__fayalite_formal_reset");
}
#[hdl]
let formal_reset = instance(formal_reset());
formal_reset.rst
}

View file

@ -30,7 +30,6 @@ pub struct __;
#[cfg(feature = "unstable-doc")]
pub mod _docs;
// FIXME: finish
pub mod annotations;
pub mod array;
pub mod bundle;
@ -39,16 +38,16 @@ pub mod clock;
pub mod enum_;
pub mod expr;
pub mod firrtl;
pub mod formal;
pub mod int;
pub mod intern;
pub mod memory;
pub mod module;
pub mod prelude;
pub mod reg;
pub mod reset;
pub mod source_location;
pub mod testing;
pub mod ty;
pub mod util;
//pub mod valueless;
pub mod prelude;
pub mod testing;
pub mod wire;

View file

@ -15,6 +15,7 @@ use crate::{
},
Expr, Flow, ToExpr,
},
formal::FormalKind,
int::{Bool, DynSize, Size},
intern::{Intern, Interned},
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
@ -233,26 +234,9 @@ impl fmt::Debug for StmtConnect {
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum StmtFormalKind {
Assert,
Assume,
Cover,
}
impl StmtFormalKind {
pub fn as_str(self) -> &'static str {
match self {
Self::Assert => "assert",
Self::Assume => "assume",
Self::Cover => "cover",
}
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct StmtFormal {
pub kind: StmtFormalKind,
pub kind: FormalKind,
pub clk: Expr<Clock>,
pub pred: Expr<Bool>,
pub en: Expr<Bool>,
@ -279,6 +263,19 @@ impl fmt::Debug for StmtFormal {
}
}
#[track_caller]
pub(crate) fn add_stmt_formal(formal: StmtFormal) {
ModuleBuilder::with(|m| {
m.impl_
.borrow_mut()
.body
.builder_normal_body()
.block(m.block_stack.top())
.stmts
.push(formal.into());
});
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct StmtIf<S: ModuleBuildingStatus = ModuleBuilt> {
pub cond: Expr<Bool>,
@ -2439,119 +2436,6 @@ pub fn match_with_loc<T: Type>(
T::match_variants(expr.to_expr(), source_location)
}
#[track_caller]
pub fn formal_with_enable_and_loc(
kind: StmtFormalKind,
clk: Expr<Clock>,
pred: Expr<Bool>,
en: Expr<Bool>,
text: &str,
source_location: SourceLocation,
) {
ModuleBuilder::with(|m| {
m.impl_
.borrow_mut()
.body
.builder_normal_body()
.block(m.block_stack.top())
.stmts
.push(
StmtFormal {
kind,
clk,
pred,
en,
text: text.intern(),
source_location,
}
.into(),
);
});
}
#[track_caller]
pub fn formal_with_enable(
kind: StmtFormalKind,
clk: Expr<Clock>,
pred: Expr<Bool>,
en: Expr<Bool>,
text: &str,
) {
formal_with_enable_and_loc(kind, clk, pred, en, text, SourceLocation::caller());
}
#[track_caller]
pub fn formal_with_loc(
kind: StmtFormalKind,
clk: Expr<Clock>,
pred: Expr<Bool>,
text: &str,
source_location: SourceLocation,
) {
formal_with_enable_and_loc(kind, clk, pred, true.to_expr(), text, source_location);
}
#[track_caller]
pub fn formal(kind: StmtFormalKind, clk: Expr<Clock>, pred: Expr<Bool>, text: &str) {
formal_with_loc(kind, clk, pred, text, SourceLocation::caller());
}
macro_rules! make_formal {
($kind:ident, $formal_with_enable_and_loc:ident, $formal_with_enable:ident, $formal_with_loc:ident, $formal:ident) => {
#[track_caller]
pub fn $formal_with_enable_and_loc(
clk: Expr<Clock>,
pred: Expr<Bool>,
en: Expr<Bool>,
text: &str,
source_location: SourceLocation,
) {
formal_with_enable_and_loc(StmtFormalKind::$kind, clk, pred, en, text, source_location);
}
#[track_caller]
pub fn $formal_with_enable(clk: Expr<Clock>, pred: Expr<Bool>, en: Expr<Bool>, text: &str) {
formal_with_enable(StmtFormalKind::$kind, clk, pred, en, text);
}
#[track_caller]
pub fn $formal_with_loc(
clk: Expr<Clock>,
pred: Expr<Bool>,
text: &str,
source_location: SourceLocation,
) {
formal_with_loc(StmtFormalKind::$kind, clk, pred, text, source_location);
}
#[track_caller]
pub fn $formal(clk: Expr<Clock>, pred: Expr<Bool>, text: &str) {
formal(StmtFormalKind::$kind, clk, pred, text);
}
};
}
make_formal!(
Assert,
hdl_assert_with_enable_and_loc,
hdl_assert_with_enable,
hdl_assert_with_loc,
hdl_assert
);
make_formal!(
Assume,
hdl_assume_with_enable_and_loc,
hdl_assume_with_enable,
hdl_assume_with_loc,
hdl_assume
);
make_formal!(
Cover,
hdl_cover_with_enable_and_loc,
hdl_cover_with_enable,
hdl_cover_with_loc,
hdl_cover
);
#[track_caller]
pub fn connect_any_with_loc<Lhs: ToExpr, Rhs: ToExpr>(
lhs: Lhs,

View file

@ -4,7 +4,7 @@
use crate::{
annotations::{
Annotation, BlackBoxInlineAnnotation, BlackBoxPathAnnotation, CustomFirrtlAnnotation,
DocStringAnnotation, SVAttributeAnnotation, TargetedAnnotation,
DocStringAnnotation, DontTouchAnnotation, SVAttributeAnnotation, TargetedAnnotation,
},
array::ArrayType,
bundle::{Bundle, BundleField, BundleType},
@ -18,14 +18,15 @@ use crate::{
},
Expr, ExprEnum,
},
formal::FormalKind,
int::{Bool, SIntType, SIntValue, Size, UIntType, UIntValue},
intern::{Intern, Interned},
memory::{Mem, MemPort, PortKind, PortName, PortType, ReadUnderWrite},
module::{
AnnotatedModuleIO, Block, BlockId, ExternModuleBody, ExternModuleParameter,
ExternModuleParameterValue, Instance, Module, ModuleBody, ModuleIO, NameId,
NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal,
StmtFormalKind, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire,
NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf,
StmtInstance, StmtMatch, StmtReg, StmtWire,
},
reg::Reg,
reset::{AsyncReset, Reset, SyncReset},

View file

@ -1,7 +1,10 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
pub use crate::{
annotations::Annotation,
annotations::{
BlackBoxInlineAnnotation, BlackBoxPathAnnotation, CustomFirrtlAnnotation,
DocStringAnnotation, DontTouchAnnotation, SVAttributeAnnotation,
},
array::{Array, ArrayType},
cli::Cli,
clock::{Clock, ClockDomain, ToClock},
@ -10,13 +13,16 @@ pub use crate::{
repeat, CastBitsTo, CastTo, CastToBits, Expr, HdlPartialEq, HdlPartialOrd, MakeUninitExpr,
ReduceBits, ToExpr,
},
formal::{
formal_global_clock, formal_reset, hdl_assert, hdl_assert_with_enable, hdl_assume,
hdl_assume_with_enable, hdl_cover, hdl_cover_with_enable, MakeFormalExpr,
},
hdl, hdl_module,
int::{Bool, DynSize, KnownSize, SInt, SIntType, Size, UInt, UIntType},
memory::{Mem, MemBuilder, ReadUnderWrite},
module::{
annotate, connect, connect_any, hdl_assert, hdl_assert_with_enable, hdl_assume,
hdl_assume_with_enable, hdl_cover, hdl_cover_with_enable, incomplete_wire, instance,
memory, memory_array, memory_with_init, reg_builder, wire, Instance, Module, ModuleBuilder,
annotate, connect, connect_any, incomplete_wire, instance, memory, memory_array,
memory_with_init, reg_builder, wire, Instance, Module, ModuleBuilder,
},
reg::Reg,
reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset},

View file

@ -1,88 +0,0 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
int::{DynIntType, DynSIntType, DynUIntType, IntTypeTrait, SIntType},
ty::{Type, Value},
};
use std::ops::RangeBounds;
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Default)]
pub struct Valueless<T> {
pub ty: T,
}
impl<T: Type> Valueless<T> {
pub fn to_canonical(&self) -> Valueless<T::CanonicalType> {
Valueless {
ty: self.ty.canonical(),
}
}
pub fn from_canonical(v: Valueless<T::CanonicalType>) -> Self {
Valueless {
ty: T::from_canonical_type(v.ty),
}
}
}
mod sealed {
pub trait Sealed {}
}
pub trait ValuelessTr: sealed::Sealed {
type Type: Type<Value = Self::Value>;
type Value: Value<Type = Self::Type>;
}
impl<T> sealed::Sealed for Valueless<T> {}
impl<T: Type> ValuelessTr for Valueless<T> {
type Type = T;
type Value = T::Value;
}
impl<T: IntTypeTrait> Valueless<T> {
pub fn signum(&self) -> Valueless<SIntType<2>> {
Valueless::default()
}
pub fn as_same_width_uint(self) -> Valueless<T::SameWidthUInt> {
Valueless {
ty: self.ty.as_same_width_uint(),
}
}
pub fn as_same_width_sint(self) -> Valueless<T::SameWidthSInt> {
Valueless {
ty: self.ty.as_same_width_sint(),
}
}
pub fn as_same_value_uint(self) -> Valueless<DynUIntType> {
Valueless {
ty: self.ty.as_same_value_uint(),
}
}
pub fn as_same_value_sint(self) -> Valueless<DynSIntType> {
Valueless {
ty: self.ty.as_same_value_sint(),
}
}
pub fn concat<HighType: IntTypeTrait>(
&self,
high_part: Valueless<HighType>,
) -> Valueless<DynIntType<HighType::Signed>> {
let ty = DynIntType::new(
self.ty
.width()
.checked_add(high_part.ty.width())
.expect("result has too many bits"),
);
Valueless { ty }
}
pub fn repeat(&self, count: usize) -> Valueless<DynIntType<T::Signed>> {
let width = self.ty.width();
let ty = DynIntType::new(width.checked_mul(count).expect("result has too many bits"));
Valueless { ty }
}
pub fn slice<I: RangeBounds<usize>>(&self, index: I) -> Valueless<DynUIntType> {
let ty = self.ty.slice(index);
Valueless { ty }
}
}

View file

@ -1,16 +1,8 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use fayalite::{
annotations::{
BlackBoxInlineAnnotation, BlackBoxPathAnnotation, CustomFirrtlAnnotation,
DocStringAnnotation, SVAttributeAnnotation,
},
assert_export_firrtl,
firrtl::ExportOptions,
intern::Intern,
module::transform::simplify_enums::SimplifyEnumsKind,
prelude::*,
ty::StaticType,
assert_export_firrtl, firrtl::ExportOptions, intern::Intern,
module::transform::simplify_enums::SimplifyEnumsKind, prelude::*, ty::StaticType,
};
use serde_json::json;
@ -3057,30 +3049,30 @@ circuit check_memory_of_array_of_enum:
#[hdl_module(outline_generated)]
pub fn check_annotations() {
m.annotate_module(Annotation::CustomFirrtl(CustomFirrtlAnnotation {
m.annotate_module(CustomFirrtlAnnotation {
class: "the.annotation.Example".intern(),
additional_fields: json!({
"bar": "a nice module!",
})
.try_into()
.unwrap(),
}));
m.annotate_module(Annotation::DocString(DocStringAnnotation {
});
m.annotate_module(DocStringAnnotation {
text: r"This module is used as a test that fayalite's firrtl
backend properly emits annotations.
Testing...
"
.intern(),
}));
});
#[hdl]
let raddr: UInt<8> = m.input();
annotate(raddr, Annotation::DontTouch);
annotate(raddr, DontTouchAnnotation);
#[hdl]
let rdata: Array<UInt<4>, 2> = m.output();
annotate(
rdata,
Annotation::CustomFirrtl(CustomFirrtlAnnotation {
CustomFirrtlAnnotation {
class: "the.annotation.ExampleClass".intern(),
additional_fields: json!({
"foo": "bar",
@ -3088,7 +3080,7 @@ Testing...
})
.try_into()
.unwrap(),
}),
},
);
#[hdl]
let waddr: UInt<8> = m.input();
@ -3098,21 +3090,21 @@ Testing...
let wmask: Array<Bool, 2> = m.input();
annotate(
wmask[1],
Annotation::CustomFirrtl(CustomFirrtlAnnotation {
CustomFirrtlAnnotation {
class: "some.annotation.Class".intern(),
additional_fields: json!({
"baz": "second mask bit",
})
.try_into()
.unwrap(),
}),
},
);
#[hdl]
let clk: Clock = m.input();
#[hdl]
let mut mem = memory();
mem.depth(0x100);
mem.annotate(Annotation::CustomFirrtl(CustomFirrtlAnnotation {
mem.annotate(CustomFirrtlAnnotation {
class: "the.annotation.ExampleClass2".intern(),
additional_fields: json!({
"bar": "foo",
@ -3120,18 +3112,18 @@ Testing...
})
.try_into()
.unwrap(),
}));
});
let read_port = mem.new_read_port();
annotate(
read_port,
Annotation::CustomFirrtl(CustomFirrtlAnnotation {
CustomFirrtlAnnotation {
class: "the.annotation.ExampleClass3".intern(),
additional_fields: json!({
"foo": "my read port",
})
.try_into()
.unwrap(),
}),
},
);
connect_any(read_port.addr, raddr);
connect(read_port.en, true);
@ -3140,14 +3132,14 @@ Testing...
let write_port = mem.new_write_port();
annotate(
write_port.data[0],
Annotation::CustomFirrtl(CustomFirrtlAnnotation {
CustomFirrtlAnnotation {
class: "some.annotation.Class".intern(),
additional_fields: json!({
"baz": "first mask bit",
})
.try_into()
.unwrap(),
}),
},
);
connect_any(write_port.addr, waddr);
connect(write_port.en, true);
@ -3157,35 +3149,35 @@ Testing...
#[hdl_module(extern)]
fn black_box1() {
m.verilog_name("BlackBox1");
m.annotate_module(Annotation::BlackBoxInline(BlackBoxInlineAnnotation {
m.annotate_module(BlackBoxInlineAnnotation {
path: "black_box1.v".intern(),
text: r"(* blackbox *)
module BlackBox1();
endmodule
"
.intern(),
}));
});
}
#[hdl]
let black_box1_instance = instance(black_box1());
annotate(black_box1_instance, Annotation::DontTouch);
annotate(black_box1_instance, DontTouchAnnotation);
#[hdl_module(extern)]
fn black_box2() {
m.verilog_name("BlackBox2");
m.annotate_module(Annotation::BlackBoxPath(BlackBoxPathAnnotation {
m.annotate_module(BlackBoxPathAnnotation {
path: "black_box2.v".intern(),
}));
});
}
#[hdl]
let black_box2_instance = instance(black_box2());
annotate(black_box2_instance, Annotation::DontTouch);
annotate(black_box2_instance, DontTouchAnnotation);
#[hdl]
let a_wire: (SInt<1>, Bool) = wire();
annotate(
a_wire.1,
Annotation::SVAttribute(SVAttributeAnnotation {
SVAttributeAnnotation {
text: "custom_sv_attr = \"abc\"".intern(),
}),
},
);
connect(a_wire, (0_hdl_i1, false));
}

View file

@ -1089,7 +1089,7 @@
"source_location": "Visible"
}
},
"StmtFormalKind": {
"FormalKind": {
"data": {
"$kind": "Enum",
"Assert": null,
@ -1163,7 +1163,7 @@
"Annotation": {
"data": {
"$kind": "Enum",
"DontTouch": null,
"DontTouch": "Visible",
"SVAttribute": "Visible",
"BlackBoxInline": "Visible",
"BlackBoxPath": "Visible",
@ -1171,6 +1171,11 @@
"CustomFirrtl": "Visible"
}
},
"DontTouchAnnotation": {
"data": {
"$kind": "Struct"
}
},
"SVAttributeAnnotation": {
"data": {
"$kind": "Struct",