WIP getting queue formal to pass -- passes for capacity <= 2
Some checks failed
/ test (push) Has been cancelled
Some checks failed
/ test (push) Has been cancelled
This commit is contained in:
parent
bc26fe32fd
commit
3e2fb9b94f
|
@ -12,7 +12,14 @@ use clap::{
|
|||
Parser, Subcommand, ValueEnum, ValueHint,
|
||||
};
|
||||
use eyre::{eyre, Report};
|
||||
use std::{error, ffi::OsString, fmt, io, path::PathBuf, process};
|
||||
use std::{
|
||||
error,
|
||||
ffi::OsString,
|
||||
fmt::{self, Write},
|
||||
fs, io, mem,
|
||||
path::{Path, PathBuf},
|
||||
process,
|
||||
};
|
||||
use tempfile::TempDir;
|
||||
|
||||
pub type Result<T = (), E = CliError> = std::result::Result<T, E>;
|
||||
|
@ -246,15 +253,51 @@ pub struct VerilogArgs {
|
|||
#[non_exhaustive]
|
||||
pub struct VerilogOutput {
|
||||
pub firrtl: FirrtlOutput,
|
||||
pub verilog_files: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl VerilogOutput {
|
||||
pub fn verilog_file(&self) -> PathBuf {
|
||||
pub fn main_verilog_file(&self) -> PathBuf {
|
||||
self.firrtl.file_with_ext("v")
|
||||
}
|
||||
fn unadjusted_verilog_file(&self) -> PathBuf {
|
||||
self.firrtl.file_with_ext("unadjusted.v")
|
||||
}
|
||||
}
|
||||
|
||||
impl VerilogArgs {
|
||||
fn process_unadjusted_verilog_file(&self, mut output: VerilogOutput) -> Result<VerilogOutput> {
|
||||
let input = fs::read_to_string(output.unadjusted_verilog_file())?;
|
||||
let file_separator_prefix = "\n// ----- 8< ----- FILE \"";
|
||||
let file_separator_suffix = "\" ----- 8< -----\n\n";
|
||||
let mut input = &*input;
|
||||
let main_verilog_file = output.main_verilog_file();
|
||||
let mut file_name: Option<&Path> = Some(&main_verilog_file);
|
||||
loop {
|
||||
let (chunk, next_file_name) = if let Some((chunk, rest)) =
|
||||
input.split_once(file_separator_prefix)
|
||||
{
|
||||
let Some((next_file_name, rest)) = rest.split_once(file_separator_suffix) else {
|
||||
return Err(CliError(eyre!("parsing firtool's output failed: found {file_separator_prefix:?} but no {file_separator_suffix:?}")));
|
||||
};
|
||||
input = rest;
|
||||
(chunk, Some(next_file_name.as_ref()))
|
||||
} else {
|
||||
(mem::take(&mut input), None)
|
||||
};
|
||||
let Some(file_name) = mem::replace(&mut file_name, next_file_name) else {
|
||||
break;
|
||||
};
|
||||
let file_name = output.firrtl.output_dir.join(file_name);
|
||||
fs::write(&file_name, chunk)?;
|
||||
if let Some(extension) = file_name.extension() {
|
||||
if extension == "v" || extension == "sv" {
|
||||
output.verilog_files.push(file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(output)
|
||||
}
|
||||
fn run_impl(&self, firrtl_output: FirrtlOutput) -> Result<VerilogOutput> {
|
||||
let Self {
|
||||
firrtl,
|
||||
|
@ -265,14 +308,15 @@ impl VerilogArgs {
|
|||
} = self;
|
||||
let output = VerilogOutput {
|
||||
firrtl: firrtl_output,
|
||||
verilog_files: vec![],
|
||||
};
|
||||
let mut cmd = process::Command::new(firtool);
|
||||
cmd.arg(output.firrtl.firrtl_file());
|
||||
cmd.arg("-o");
|
||||
cmd.arg(output.verilog_file());
|
||||
cmd.arg(output.unadjusted_verilog_file());
|
||||
if *debug {
|
||||
cmd.arg("-g");
|
||||
cmd.arg("--preserve-values=named");
|
||||
cmd.arg("--preserve-values=all");
|
||||
}
|
||||
if let Some(dialect) = verilog_dialect {
|
||||
cmd.args(dialect.firtool_extra_args());
|
||||
|
@ -281,7 +325,7 @@ impl VerilogArgs {
|
|||
cmd.current_dir(&output.firrtl.output_dir);
|
||||
let status = firrtl.base.run_external_command(cmd)?;
|
||||
if status.success() {
|
||||
Ok(output)
|
||||
self.process_unadjusted_verilog_file(output)
|
||||
} else {
|
||||
Err(CliError(eyre!(
|
||||
"running {} failed: {status}",
|
||||
|
@ -424,7 +468,7 @@ impl FormalOutput {
|
|||
}
|
||||
|
||||
impl FormalArgs {
|
||||
fn sby_contents(&self, output: &FormalOutput) -> String {
|
||||
fn sby_contents(&self, output: &FormalOutput) -> Result<String> {
|
||||
let Self {
|
||||
verilog: _,
|
||||
sby: _,
|
||||
|
@ -448,15 +492,8 @@ impl FormalArgs {
|
|||
}
|
||||
let space_solver = OptArg(solver.as_ref());
|
||||
let smtbmc_options = smtbmc_extra_args.join(" ");
|
||||
let verilog_file = output
|
||||
.verilog
|
||||
.verilog_file()
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.ok()
|
||||
.expect("verilog file path is not UTF-8");
|
||||
let top_module = &output.verilog.firrtl.top_module;
|
||||
format!(
|
||||
let mut retval = format!(
|
||||
"[options]\n\
|
||||
mode {mode}\n\
|
||||
depth {depth}\n\
|
||||
|
@ -465,18 +502,30 @@ impl FormalArgs {
|
|||
[engines]\n\
|
||||
smtbmc{space_solver} -- -- {smtbmc_options}\n\
|
||||
\n\
|
||||
[script]\n\
|
||||
read_verilog -sv -formal {verilog_file}\n\
|
||||
prep -top {top_module}\n
|
||||
"
|
||||
)
|
||||
[script]\n"
|
||||
);
|
||||
for verilog_file in &output.verilog.verilog_files {
|
||||
let verilog_file = verilog_file
|
||||
.to_str()
|
||||
.ok_or_else(|| CliError(eyre!("verilog file path is not UTF-8")))?;
|
||||
if verilog_file.contains(|ch: char| {
|
||||
(ch != ' ' && ch != '\t' && ch.is_ascii_whitespace()) || ch == '"'
|
||||
}) {
|
||||
return Err(CliError(eyre!(
|
||||
"verilog file path contains characters that aren't permitted"
|
||||
)));
|
||||
}
|
||||
writeln!(retval, "read_verilog -sv -formal \"{verilog_file}\"").unwrap();
|
||||
}
|
||||
writeln!(retval, "prep -top {top_module}").unwrap();
|
||||
Ok(retval)
|
||||
}
|
||||
fn run_impl(&self, verilog_output: VerilogOutput) -> Result<FormalOutput> {
|
||||
let output = FormalOutput {
|
||||
verilog: verilog_output,
|
||||
};
|
||||
let sby_file = output.sby_file();
|
||||
std::fs::write(&sby_file, self.sby_contents(&output))?;
|
||||
std::fs::write(&sby_file, self.sby_contents(&output)?)?;
|
||||
let mut cmd = process::Command::new(&self.sby);
|
||||
cmd.arg("-f");
|
||||
cmd.arg(sby_file);
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
use crate::{intern::Intern, prelude::*};
|
||||
use crate::{
|
||||
intern::{Intern, Interned},
|
||||
prelude::*,
|
||||
};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum FormalKind {
|
||||
|
@ -32,7 +36,7 @@ pub fn formal_stmt_with_enable_and_loc(
|
|||
kind,
|
||||
clk,
|
||||
pred,
|
||||
en,
|
||||
en: en & !formal_reset().cast_to_static::<Bool>(),
|
||||
text: text.intern(),
|
||||
source_location,
|
||||
});
|
||||
|
@ -160,11 +164,11 @@ endmodule
|
|||
}
|
||||
|
||||
#[hdl]
|
||||
pub fn formal_reset() -> Expr<AsyncReset> {
|
||||
pub fn formal_reset() -> Expr<SyncReset> {
|
||||
#[hdl_module(extern)]
|
||||
fn formal_reset() {
|
||||
#[hdl]
|
||||
let rst: AsyncReset = m.output();
|
||||
let rst: SyncReset = m.output();
|
||||
m.annotate_module(BlackBoxInlineAnnotation {
|
||||
path: "fayalite_formal_reset.v".intern(),
|
||||
text: r"module __fayalite_formal_reset(output rst);
|
||||
|
@ -180,7 +184,8 @@ endmodule
|
|||
});
|
||||
m.verilog_name("__fayalite_formal_reset");
|
||||
}
|
||||
static MOD: OnceLock<Interned<Module<formal_reset>>> = OnceLock::new();
|
||||
#[hdl]
|
||||
let formal_reset = instance(formal_reset());
|
||||
let formal_reset = instance(*MOD.get_or_init(formal_reset));
|
||||
formal_reset.rst
|
||||
}
|
||||
|
|
|
@ -5,7 +5,14 @@ use crate::{
|
|||
firrtl::ExportOptions,
|
||||
};
|
||||
use clap::Parser;
|
||||
use std::sync::OnceLock;
|
||||
use hashbrown::HashMap;
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
fmt::Write,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
sync::{Mutex, OnceLock},
|
||||
};
|
||||
|
||||
fn assert_formal_helper() -> FormalArgs {
|
||||
static FORMAL_ARGS: OnceLock<FormalArgs> = OnceLock::new();
|
||||
|
@ -15,8 +22,84 @@ fn assert_formal_helper() -> FormalArgs {
|
|||
.clone()
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CargoMetadata {
|
||||
target_directory: String,
|
||||
}
|
||||
|
||||
fn get_cargo_target_dir() -> &'static Path {
|
||||
static RETVAL: OnceLock<PathBuf> = OnceLock::new();
|
||||
RETVAL.get_or_init(|| {
|
||||
let output = Command::new(
|
||||
std::env::var_os("CARGO")
|
||||
.as_deref()
|
||||
.unwrap_or("cargo".as_ref()),
|
||||
)
|
||||
.arg("metadata")
|
||||
.output()
|
||||
.expect("can't run `cargo metadata`");
|
||||
if !output.status.success() {
|
||||
panic!(
|
||||
"can't run `cargo metadata`:\n{}\nexited with status: {}",
|
||||
String::from_utf8_lossy(&output.stderr),
|
||||
output.status
|
||||
);
|
||||
}
|
||||
let CargoMetadata { target_directory } =
|
||||
serde_json::from_slice(&output.stdout).expect("can't parse output of `cargo metadata`");
|
||||
PathBuf::from(target_directory)
|
||||
})
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn get_assert_formal_target_path(test_name: &dyn std::fmt::Display) -> PathBuf {
|
||||
static DIRS: Mutex<Option<HashMap<String, u64>>> = Mutex::new(None);
|
||||
let test_name = test_name.to_string();
|
||||
// don't use line/column numbers since that constantly changes as you edit tests
|
||||
let file = std::panic::Location::caller().file();
|
||||
// simple reproducible hash
|
||||
let simple_hash = file.bytes().chain(test_name.bytes()).fold(
|
||||
((file.len() as u32) << 16).wrapping_add(test_name.len() as u32),
|
||||
|mut h, b| {
|
||||
h = h.wrapping_mul(0xaa0d184b);
|
||||
h ^= h.rotate_right(5);
|
||||
h ^= h.rotate_right(13);
|
||||
h.wrapping_add(b as u32)
|
||||
},
|
||||
);
|
||||
let mut dir = String::with_capacity(64);
|
||||
write!(dir, "{simple_hash:08x}-").unwrap();
|
||||
for ch in Path::new(file)
|
||||
.file_stem()
|
||||
.unwrap_or_default()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.chars()
|
||||
.chain(['-'])
|
||||
.chain(test_name.chars())
|
||||
{
|
||||
dir.push(match ch {
|
||||
ch if ch.is_alphanumeric() => ch,
|
||||
'_' | '-' | '+' | '.' | ',' | ' ' => ch,
|
||||
_ => '_',
|
||||
});
|
||||
}
|
||||
let index = *DIRS
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_or_insert_with(HashMap::new)
|
||||
.entry_ref(&dir)
|
||||
.and_modify(|v| *v += 1)
|
||||
.or_insert(0);
|
||||
write!(dir, ".{index}").unwrap();
|
||||
get_cargo_target_dir()
|
||||
.join("fayalite_assert_formal")
|
||||
.join(dir)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn assert_formal<M>(
|
||||
test_name: impl std::fmt::Display,
|
||||
module: M,
|
||||
mode: FormalMode,
|
||||
depth: u64,
|
||||
|
@ -27,6 +110,7 @@ pub fn assert_formal<M>(
|
|||
{
|
||||
let mut args = assert_formal_helper();
|
||||
args.verilog.firrtl.base.redirect_output_for_rust_test = true;
|
||||
args.verilog.firrtl.base.output = Some(get_assert_formal_target_path(&test_name));
|
||||
args.verilog.firrtl.export_options = export_options;
|
||||
args.verilog.debug = true;
|
||||
args.mode = mode;
|
||||
|
|
|
@ -23,6 +23,19 @@ impl<T: Type> ReadyValid<T> {
|
|||
fire
|
||||
}
|
||||
#[hdl]
|
||||
pub fn fire_data(expr: impl ToExpr<Type = Self>) -> Expr<HdlOption<T>> {
|
||||
let expr = expr.to_expr();
|
||||
let option_ty = Expr::ty(expr).data;
|
||||
#[hdl]
|
||||
let fire_data = wire(option_ty);
|
||||
connect(fire_data, option_ty.HdlNone());
|
||||
#[hdl]
|
||||
if expr.ready {
|
||||
connect(fire_data, expr.data);
|
||||
}
|
||||
fire_data
|
||||
}
|
||||
#[hdl]
|
||||
pub fn map<R: Type>(
|
||||
expr: Expr<Self>,
|
||||
f: impl FnOnce(Expr<T>) -> Expr<R>,
|
||||
|
@ -163,7 +176,6 @@ pub fn queue<T: Type>(
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -171,27 +183,39 @@ mod tests {
|
|||
cli::FormalMode, firrtl::ExportOptions,
|
||||
module::transform::simplify_enums::SimplifyEnumsKind, testing::assert_formal,
|
||||
};
|
||||
use std::num::NonZero;
|
||||
|
||||
#[test]
|
||||
fn test_queue() {
|
||||
#[track_caller]
|
||||
fn test_queue(capacity: NonZeroUsize, inp_ready_is_comb: bool, out_valid_is_comb: bool) {
|
||||
assert_formal(
|
||||
format_args!("test_queue_{capacity}_{inp_ready_is_comb}_{out_valid_is_comb}"),
|
||||
queue_test(capacity, inp_ready_is_comb, out_valid_is_comb),
|
||||
FormalMode::BMC,
|
||||
20,
|
||||
None,
|
||||
ExportOptions {
|
||||
simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts),
|
||||
..ExportOptions::default()
|
||||
},
|
||||
);
|
||||
#[hdl_module]
|
||||
fn queue_test(capacity: NonZeroUsize, inp_ready_is_comb: bool, out_valid_is_comb: bool) {
|
||||
#[hdl]
|
||||
let clk: Clock = m.input();
|
||||
#[hdl]
|
||||
let rst: SyncReset = m.input();
|
||||
#[hdl]
|
||||
let inp_data: HdlOption<UInt<8>> = m.input();
|
||||
#[hdl]
|
||||
let out_ready: Bool = m.input();
|
||||
#[hdl]
|
||||
let start_check: Bool = m.input();
|
||||
#[hdl]
|
||||
let clk: Clock = m.input();
|
||||
#[hdl]
|
||||
let cd = wire();
|
||||
connect(
|
||||
cd,
|
||||
#[hdl]
|
||||
ClockDomain {
|
||||
clk,
|
||||
rst: rst.to_reset(),
|
||||
rst: formal_reset().to_reset(),
|
||||
},
|
||||
);
|
||||
#[hdl]
|
||||
|
@ -216,52 +240,139 @@ mod tests {
|
|||
} else if !ReadyValid::fire(dut.inp) & ReadyValid::fire(dut.out) {
|
||||
connect_any(next_count, count - 1u8);
|
||||
}
|
||||
hdl_assert(clk, count.cmp_eq(dut.count), "");
|
||||
hdl_assert(cd.clk, count.cmp_eq(dut.count), "");
|
||||
#[hdl]
|
||||
let index = reg_builder().clock_domain(cd).reset(HdlNone::<UInt<32>>());
|
||||
let started_check = reg_builder().clock_domain(cd).reset(false);
|
||||
#[hdl]
|
||||
let data = reg_builder().clock_domain(cd).reset(HdlNone());
|
||||
let steps_till_output = reg_builder().clock_domain(cd).reset(0u32);
|
||||
#[hdl]
|
||||
match index {
|
||||
HdlNone =>
|
||||
{
|
||||
#[hdl]
|
||||
if ReadyValid::fire(dut.inp) {
|
||||
connect(index, HdlSome(0u32));
|
||||
connect(data, dut.inp.data);
|
||||
}
|
||||
let expected_output = reg_builder().clock_domain(cd).reset(HdlNone());
|
||||
#[hdl]
|
||||
if start_check & !started_check {
|
||||
#[hdl]
|
||||
if let HdlSome(inp) = ReadyValid::fire_data(dut.inp) {
|
||||
connect(started_check, true);
|
||||
connect_any(
|
||||
steps_till_output,
|
||||
count + (!ReadyValid::fire(dut.out)).cast_to(UInt[1]),
|
||||
);
|
||||
connect(expected_output, HdlSome(inp));
|
||||
}
|
||||
HdlSome(cur_index) =>
|
||||
} else if started_check & steps_till_output.cmp_ne(0u32) & ReadyValid::fire(dut.out) {
|
||||
connect_any(steps_till_output, steps_till_output - 1u32);
|
||||
}
|
||||
#[hdl]
|
||||
let stored_output = reg_builder().clock_domain(cd).reset(HdlNone());
|
||||
#[hdl]
|
||||
if let HdlSome(out) = ReadyValid::fire_data(dut.out) {
|
||||
#[hdl]
|
||||
if (start_check & !started_check) | (started_check & steps_till_output.cmp_ne(0u32))
|
||||
{
|
||||
connect(stored_output, HdlSome(out));
|
||||
}
|
||||
}
|
||||
#[hdl]
|
||||
if started_check & steps_till_output.cmp_eq(0u32) {
|
||||
#[hdl]
|
||||
if let HdlSome(expected_output) = expected_output {
|
||||
#[hdl]
|
||||
if cur_index.cmp_ge(next_count) {
|
||||
connect(index, HdlNone());
|
||||
#[hdl]
|
||||
if let HdlSome(data) = data {
|
||||
#[hdl]
|
||||
if let HdlSome(out_data) = dut.out.data {
|
||||
hdl_assert(clk, data.cmp_eq(out_data), "");
|
||||
} else {
|
||||
hdl_assert(clk, false.to_expr(), "");
|
||||
}
|
||||
} else {
|
||||
hdl_assert(clk, false.to_expr(), "");
|
||||
}
|
||||
if let HdlSome(stored_output) = stored_output {
|
||||
hdl_assert(cd.clk, stored_output.cmp_eq(expected_output), "");
|
||||
} else {
|
||||
connect(index, HdlSome((cur_index + 1u8).cast_to_static()));
|
||||
hdl_assert(cd.clk, false.to_expr(), "");
|
||||
}
|
||||
} else {
|
||||
hdl_assert(cd.clk, false.to_expr(), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_formal(
|
||||
queue_test(NonZeroUsize::new(2).unwrap(), false, false),
|
||||
FormalMode::BMC,
|
||||
20,
|
||||
None,
|
||||
ExportOptions {
|
||||
simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts),
|
||||
..ExportOptions::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_false_false() {
|
||||
test_queue(NonZero::new(1).unwrap(), false, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_false_true() {
|
||||
test_queue(NonZero::new(1).unwrap(), false, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_true_false() {
|
||||
test_queue(NonZero::new(1).unwrap(), true, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_true_true() {
|
||||
test_queue(NonZero::new(1).unwrap(), true, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2_false_false() {
|
||||
test_queue(NonZero::new(2).unwrap(), false, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2_false_true() {
|
||||
test_queue(NonZero::new(2).unwrap(), false, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2_true_false() {
|
||||
test_queue(NonZero::new(2).unwrap(), true, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2_true_true() {
|
||||
test_queue(NonZero::new(2).unwrap(), true, true);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_3_false_false() {
|
||||
test_queue(NonZero::new(3).unwrap(), false, false);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_3_false_true() {
|
||||
test_queue(NonZero::new(3).unwrap(), false, true);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_3_true_false() {
|
||||
test_queue(NonZero::new(3).unwrap(), true, false);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_3_true_true() {
|
||||
test_queue(NonZero::new(3).unwrap(), true, true);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_4_false_false() {
|
||||
test_queue(NonZero::new(4).unwrap(), false, false);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_4_false_true() {
|
||||
test_queue(NonZero::new(4).unwrap(), false, true);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_4_true_false() {
|
||||
test_queue(NonZero::new(4).unwrap(), true, false);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_4_true_true() {
|
||||
test_queue(NonZero::new(4).unwrap(), true, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3390,7 +3390,15 @@ fn test_formal() {
|
|||
assert_export_firrtl! {
|
||||
m =>
|
||||
"/test/check_formal.fir": r#"FIRRTL version 3.2.0
|
||||
circuit check_formal:
|
||||
circuit check_formal: %[[
|
||||
{
|
||||
"class": "firrtl.transforms.BlackBoxInlineAnno",
|
||||
"name": "fayalite_formal_reset.v",
|
||||
"text": "module __fayalite_formal_reset(output rst);\n reg rst;\n (* gclk *)\n reg gclk;\n initial rst = 1;\n always @(posedge gclk)\n rst <= 0;\nendmodule\n",
|
||||
"target": "~check_formal|formal_reset"
|
||||
}
|
||||
]]
|
||||
type Ty0 = {rst: UInt<1>}
|
||||
module check_formal: @[module-XXXXXXXXXX.rs 1:1]
|
||||
input clk: Clock @[module-XXXXXXXXXX.rs 2:1]
|
||||
input en1: UInt<1> @[module-XXXXXXXXXX.rs 3:1]
|
||||
|
@ -3399,12 +3407,21 @@ circuit check_formal:
|
|||
input pred1: UInt<1> @[module-XXXXXXXXXX.rs 6:1]
|
||||
input pred2: UInt<1> @[module-XXXXXXXXXX.rs 7:1]
|
||||
input pred3: UInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
||||
assert(clk, pred1, en1, "en check 1") @[module-XXXXXXXXXX.rs 9:1]
|
||||
assume(clk, pred2, en2, "en check 2") @[module-XXXXXXXXXX.rs 10:1]
|
||||
cover(clk, pred3, en3, "en check 3") @[module-XXXXXXXXXX.rs 11:1]
|
||||
assert(clk, pred1, UInt<1>(0h1), "check 1") @[module-XXXXXXXXXX.rs 12:1]
|
||||
assume(clk, pred2, UInt<1>(0h1), "check 2") @[module-XXXXXXXXXX.rs 13:1]
|
||||
cover(clk, pred3, UInt<1>(0h1), "check 3") @[module-XXXXXXXXXX.rs 14:1]
|
||||
inst formal_reset of formal_reset @[formal.rs 189:24]
|
||||
assert(clk, pred1, and(en1, not(formal_reset.rst)), "en check 1") @[module-XXXXXXXXXX.rs 9:1]
|
||||
inst formal_reset_1 of formal_reset @[formal.rs 189:24]
|
||||
assume(clk, pred2, and(en2, not(formal_reset_1.rst)), "en check 2") @[module-XXXXXXXXXX.rs 10:1]
|
||||
inst formal_reset_2 of formal_reset @[formal.rs 189:24]
|
||||
cover(clk, pred3, and(en3, not(formal_reset_2.rst)), "en check 3") @[module-XXXXXXXXXX.rs 11:1]
|
||||
inst formal_reset_3 of formal_reset @[formal.rs 189:24]
|
||||
assert(clk, pred1, and(UInt<1>(0h1), not(formal_reset_3.rst)), "check 1") @[module-XXXXXXXXXX.rs 12:1]
|
||||
inst formal_reset_4 of formal_reset @[formal.rs 189:24]
|
||||
assume(clk, pred2, and(UInt<1>(0h1), not(formal_reset_4.rst)), "check 2") @[module-XXXXXXXXXX.rs 13:1]
|
||||
inst formal_reset_5 of formal_reset @[formal.rs 189:24]
|
||||
cover(clk, pred3, and(UInt<1>(0h1), not(formal_reset_5.rst)), "check 3") @[module-XXXXXXXXXX.rs 14:1]
|
||||
extmodule formal_reset: @[formal.rs 168:5]
|
||||
output rst: UInt<1> @[formal.rs 171:32]
|
||||
defname = __fayalite_formal_reset
|
||||
"#,
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue