Skip to content

Commit

Permalink
feat: create api for rarity simulation
Browse files Browse the repository at this point in the history
 - also improve readability of rarity simulation internals
  • Loading branch information
ChristianMoesl committed Mar 7, 2021
1 parent a0ed9d4 commit 10aded4
Show file tree
Hide file tree
Showing 13 changed files with 1,683 additions and 1,574 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ anyhow = "~1.0.38"
thiserror = "~1.0.24"
divisors = "~0.2.1"
const_format = "~0.2.13"
lazy_static = "~1.4.0"
boolector = { version = "~0.4.2", features = ["vendor-lgl"], optional = true }
z3 = { version = "~0.9.0", features = ["static-link-z3"], optional = true }

Expand Down
74 changes: 41 additions & 33 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use crate::{
engine::{DEFAULT_MAX_EXECUTION_DEPTH, DEFAULT_MEMORY_SIZE},
rarity::MetricType,
solver::SolverType,
};
use anyhow::{anyhow, Context, Result};
use clap::{crate_authors, crate_description, crate_version, App, AppSettings, Arg, ArgMatches};
use const_format::formatcp;
use lazy_static::lazy_static;
use monster::{
engine::{
rarity_simulation::{defaults as rarity_defaults, MeanType},
symbolic_execution::defaults as symbolic_defaults,
},
solver::SolverType,
};
use std::str::FromStr;
use strum::{EnumString, EnumVariantNames, IntoStaticStr, VariantNames};

Expand All @@ -19,6 +22,10 @@ pub enum LogLevel {
Error,
}

lazy_static! {
static ref COPY_INIT_RATIO: String = format!("{}", rarity_defaults::COPY_INIT_RATIO);
}

pub fn args() -> App<'static, 'static> {
App::new("Monster")
.version(crate_version!())
Expand Down Expand Up @@ -99,8 +106,8 @@ pub fn args() -> App<'static, 'static> {
.long("execution-depth")
.takes_value(true)
.value_name("NUMBER")
.default_value(formatcp!("{}", DEFAULT_MAX_EXECUTION_DEPTH))
.validator(is_u64),
.default_value(formatcp!("{}", symbolic_defaults::MAX_EXECUTION_DEPTH))
.validator(is::<u64>),
)
.arg(
Arg::with_name("memory")
Expand All @@ -109,7 +116,7 @@ pub fn args() -> App<'static, 'static> {
.long("memory")
.takes_value(true)
.value_name("NUMBER")
.default_value(formatcp!("{}", DEFAULT_MEMORY_SIZE.0 / bytesize::MB))
.default_value(formatcp!("{}", symbolic_defaults::MEMORY_SIZE.0 / bytesize::MB))
.validator(is_valid_memory_size),
),
)
Expand All @@ -130,28 +137,26 @@ pub fn args() -> App<'static, 'static> {
.long("memory")
.takes_value(true)
.value_name("NUMBER")
.default_value("1")
.default_value(formatcp!("{}", rarity_defaults::MEMORY_SIZE.0 / bytesize::MB))
.validator(is_valid_memory_size),
)
.arg(
Arg::with_name("cycles")
Arg::with_name("step-size")
.help("Instructions to be executed for each round")
.short("c")
.long("cycles")
.long("step-size")
.takes_value(true)
.value_name("NUMBER")
.default_value("1000")
.validator(is_u64),
.default_value(formatcp!("{}", rarity_defaults::STEP_SIZE))
.validator(is::<u64>),
)
.arg(
Arg::with_name("runs")
.help("Number of distinct runs")
.short("r")
.long("runs")
Arg::with_name("states")
.help("Number of distinct states")
.long("states")
.takes_value(true)
.value_name("NUMBER")
.default_value("3000")
.validator(is_u64),
.default_value(formatcp!("{}", rarity_defaults::AMOUNT_OF_STATES))
.validator(is::<usize>),
)
.arg(
Arg::with_name("selection")
Expand All @@ -160,34 +165,34 @@ pub fn args() -> App<'static, 'static> {
.long("selection")
.takes_value(true)
.value_name("NUMBER")
.default_value("50")
.validator(is_u64))
.default_value(formatcp!("{}", rarity_defaults::SELECTION))
.validator(is::<usize>))
.arg(
Arg::with_name("iterations")
.help("Iterations of rarity simulation to run")
.short("i")
.long("iterations")
.takes_value(true)
.value_name("NUMBER")
.default_value("20")
.validator(is_u64))
.default_value(formatcp!("{}", rarity_defaults::ITERATIONS))
.validator(is::<u64>))
.arg(
Arg::with_name("copy-init-ratio")
.help("Determines how much new states are copied instead of started from the beginning")
.long("copy-init-ratio")
.takes_value(true)
.value_name("RATIO")
.default_value("0.6")
.default_value(COPY_INIT_RATIO.as_str())
.validator(is_ratio)
)
.arg(
Arg::with_name("metric")
Arg::with_name("mean")
.help("The average to be used for the counts")
.long("metric")
.long("mean")
.takes_value(true)
.value_name("METRIC")
.possible_values(&MetricType::VARIANTS)
.default_value(MetricType::Harmonic.into())
.value_name("MEAN")
.possible_values(&MeanType::VARIANTS)
.default_value(rarity_defaults::MEAN_TYPE.into())
)
)
.setting(AppSettings::SubcommandRequiredElseHelp)
Expand All @@ -205,12 +210,15 @@ where
})
}

fn is_u64(v: String) -> Result<(), String> {
v.parse::<u64>().map(|_| ()).map_err(|e| e.to_string())
fn is<T: FromStr>(v: String) -> Result<(), String>
where
<T as FromStr>::Err: std::fmt::Display,
{
v.parse::<T>().map(|_| ()).map_err(|e| e.to_string())
}

fn is_valid_memory_size(v: String) -> Result<(), String> {
is_u64(v.clone()).and_then(|_| {
is::<u64>(v.clone()).and_then(|_| {
let memory_size = v.parse::<u64>().expect("have checked that already");

let valid_range = 1_u64..=1024_u64;
Expand Down
117 changes: 14 additions & 103 deletions src/engine/bug.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,40 @@
use crate::{
engine::{instruction_to_str, Value},
solver::{BVOperator, BitVector},
};
use super::system::instruction_to_str;
use riscu::Instruction;
use std::fmt;

pub trait BugInfo: fmt::Display + fmt::Debug + Clone {
type Value: fmt::Display + fmt::Debug + Clone;
}

#[derive(Debug, Clone)]
pub enum Bug<T: fmt::Display + fmt::Debug + Clone> {
pub enum Bug<Info: BugInfo> {
DivisionByZero {
info: T,
info: Info,
},

AccessToUnitializedMemory {
info: T,
info: Info,
instruction: Instruction,
operands: Vec<Value>,
operands: Vec<Info::Value>,
},

AccessToUnalignedAddress {
info: T,
info: Info,
address: u64,
},

AccessToOutOfRangeAddress {
info: T,
info: Info,
},

ExitCodeGreaterZero {
info: T,
info: Info,
},
}

impl<T> fmt::Display for Bug<T>
impl<Info> fmt::Display for Bug<Info>
where
T: fmt::Display + fmt::Debug + Clone,
Info: BugInfo,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Expand Down Expand Up @@ -63,93 +64,3 @@ where
}
}
}

#[derive(Debug, Clone)]
pub struct BasicInfo {
pub witness: Witness,
pub pc: u64,
}

impl fmt::Display for BasicInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "pc: {:#010x}\nwitness: {}", self.pc, self.witness)
}
}

#[derive(Debug, Clone)]
pub(crate) enum Term {
Constant(u64),
Variable(String, u64),
Unary(BVOperator, usize, u64),
Binary(usize, BVOperator, usize, u64),
}

#[derive(Debug, Clone)]
pub struct Witness {
assignments: Vec<Term>,
}

impl Default for Witness {
fn default() -> Self {
Self {
assignments: Vec::new(),
}
}
}

impl Witness {
pub fn new() -> Self {
Witness::default()
}

pub fn add_constant(&mut self, value: BitVector) -> usize {
self.assignments.push(Term::Constant(value.0));

self.assignments.len() - 1
}

pub fn add_variable(&mut self, name: &str, result: BitVector) -> usize {
self.assignments
.push(Term::Variable(name.to_owned(), result.0));

self.assignments.len() - 1
}

pub fn add_unary(&mut self, op: BVOperator, v: usize, result: BitVector) -> usize {
self.assignments.push(Term::Unary(op, v, result.0));

self.assignments.len() - 1
}

pub fn add_binary(
&mut self,
lhs: usize,
op: BVOperator,
rhs: usize,
result: BitVector,
) -> usize {
self.assignments.push(Term::Binary(lhs, op, rhs, result.0));

self.assignments.len() - 1
}
}

impl fmt::Display for Witness {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "[").and_then(|_| {
self.assignments
.clone()
.into_iter()
.enumerate()
.try_for_each(|(id, a)| match a {
Term::Constant(c) => writeln!(f, " x{} := {},", id, c),
Term::Variable(name, v) => writeln!(f, " x{} := {:?} ({}),", id, name, v),
Term::Unary(op, x, v) => writeln!(f, " x{} := {}x{} ({}),", id, op, x, v),
Term::Binary(lhs, op, rhs, v) => {
writeln!(f, " x{} := x{} {} x{} ({}),", id, lhs, op, rhs, v)
}
})
.and_then(|_| writeln!(f, "]"))
})
}
}
Loading

0 comments on commit 10aded4

Please sign in to comment.