Skip to content

Commit

Permalink
Create Sim from a design.
Browse files Browse the repository at this point in the history
  • Loading branch information
maloneymr committed May 2, 2024
1 parent eaab5c0 commit a73ca62
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 62 deletions.
8 changes: 4 additions & 4 deletions src/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::context::Context;
use crate::types::Type;

#[salsa::query_group(QueryGroupStorage)]
trait QueryGroup: salsa::Database {
pub trait QueryGroup: salsa::Database {
#[salsa::input]
fn source(&self) -> Arc<String>;

Expand Down Expand Up @@ -300,7 +300,7 @@ fn moddef_entity_names(db: &dyn QueryGroup, moddef: Ident) -> Result<Vec<Ident>,

#[salsa::database(QueryGroupStorage)]
#[derive(Default)]
struct DatabaseStruct {
pub struct DatabaseStruct {
storage: salsa::Storage<Self>,
}

Expand All @@ -316,10 +316,10 @@ pub fn compile(input: &str) -> VirdantResult<()> {
Ok(())
}

pub fn check_module(input: &str) -> VirdantResult<()> {
pub fn check_module(input: &str) -> VirdantResult<hir::Package> {
let mut db = DatabaseStruct::default();
db.set_source(Arc::new(input.to_string()));
db.check()
Ok(db.package_hir()?)
}

#[test]
Expand Down
6 changes: 0 additions & 6 deletions src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,6 @@ impl InlineConnect {
}
}

impl Package {
pub fn moddefs(&self) -> Vec<ModDef> {
self.moddefs.values().cloned().collect()
}
}

impl Component {
pub fn name(&self) -> Ident {
match self {
Expand Down
42 changes: 19 additions & 23 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use virdant::types::Type;
use virdant::checker;

fn main() {
mlir();
sim();
}

pub fn mlir() {
Expand Down Expand Up @@ -54,31 +54,32 @@ pub fn parse() {
}

pub fn sim() {
let ctx = Context::from(vec![
("r".into(), Type::Word(8).into()),
("in".into(), Type::Word(8).into()),
("out".into(), Type::Word(8).into()),
]);

let out_expr: Expr = Expr::from_ast(&parse_expr("r").unwrap()).typeinfer(ctx.clone()).unwrap();
let in_expr: Expr = Expr::from_ast(&parse_expr("1w8").unwrap()).typeinfer(ctx.clone()).unwrap();
let r_expr: Expr = Expr::from_ast(&parse_expr("r->add(in)").unwrap()).typeinfer(ctx.clone()).unwrap();

let mut sim = Sim::new()
.add_simple_node("top.out".into(), out_expr)
.add_simple_node("top.in".into(), in_expr)
.add_reg_node("top.r".into(), Type::Word(8).into(), Some(Value::Word(8, 100)), r_expr)
.build();
let package = "
public module Top {
incoming clock : Clock;
incoming in : Word[8];
outgoing out : Word[8];
reg r : Word[8] on clock;
r <= r->add(in);
out := r;
}
";

let mut sim = virdant::sim::simulator(package, "Top").unwrap();
println!("################################################################################");
println!("Initial");
println!("{sim}");

sim.reset();
sim.poke("top.in".into(), Value::Word(8, 10));
println!("################################################################################");
println!("reset");
println!("poke top.in = 10w8");
println!("{sim}");

// sim.reset();
// println!("################################################################################");
// println!("reset");
// println!("{sim}");

sim.clock();
println!("################################################################################");
println!("clock");
Expand All @@ -89,11 +90,6 @@ pub fn sim() {
println!("clock");
println!("{sim}");

sim.poke("top.in".into(), Value::Word(8, 10));
println!("poke top.in = 10w8");
println!("################################################################################");
println!("{sim}");

sim.clock();
println!("################################################################################");
println!("clock");
Expand Down
124 changes: 95 additions & 29 deletions src/sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl SimBuilder {
self
}

pub fn add_reg_node(mut self, path: Path, typ: Arc<Type>, reset: Option<Value>, expr: Expr) -> Self {
pub fn add_reg_node(mut self, path: Path, typ: Arc<Type>, clock: Expr, reset: Option<Value>, expr: Expr) -> Self {
let set_cell_id = self.sim.cells.len();
let val_cell_id = self.sim.cells.len() + 1;

Expand All @@ -76,6 +76,20 @@ impl SimBuilder {
self
}

pub fn add_input_node(mut self, path: Path, typ: Arc<Type>) -> Self {
let cell_id = self.sim.cells.len();

let node = Node::Input {
cell_id,
path: path.clone(),
typ: typ.clone(),
};

self.sim.nodes.push(node);
self.sim.cells.push(Value::X(typ.clone()));
self
}

fn patch_sensitivity_lists(&mut self) {
let mut path_read_cell_ids = HashMap::new();
for node in &self.sim.nodes {
Expand All @@ -84,28 +98,30 @@ impl SimBuilder {


for node in &mut self.sim.nodes {
let update = node.update_mut();
let sensitivities: Vec<CellId> = update
.expr
.references()
.iter()
.map(|path| {
let full_path = update.rel.join(path);
path_read_cell_ids[&full_path]
})
.collect();
update.sensitivities = sensitivities;
if let Some(update) = node.update_mut() {
let sensitivities: Vec<CellId> = update
.expr
.references()
.iter()
.map(|path| {
let full_path = update.rel.join(path);
path_read_cell_ids[&full_path]
})
.collect();
update.sensitivities = sensitivities;
}
}
}

fn initialize_constants(&mut self) {
for i in 0..self.sim.nodes.len() {
let node = &self.sim.nodes[i];
let update = node.update().clone();
if update.is_constant() {
let value = self.sim.eval(&update);
let cell_id = node.target_cell_id();
self.sim.update_cell(cell_id, value);
if let Some(update) = node.update().clone() {
if update.is_constant() {
let value = self.sim.eval(&update);
let cell_id = node.target_cell_id();
self.sim.update_cell(cell_id, value);
}
}
}
}
Expand All @@ -128,11 +144,12 @@ impl Sim {
for node in &self.nodes.clone() {
match (event, node) {
(Event::CellUpdated(updated_cell_id), _) => {
let update = node.update();
if update.is_sensitive_to(updated_cell_id) {
let value = self.eval(update);
let cell_id = node.target_cell_id();
self.update_cell(cell_id, value);
if let Some(update) = node.update() {
if update.is_sensitive_to(updated_cell_id) {
let value = self.eval(update);
let cell_id = node.target_cell_id();
self.update_cell(cell_id, value);
}
}
},
(Event::Clock(_clock_id), Node::Reg { set_cell_id, val_cell_id, .. }) => {
Expand Down Expand Up @@ -196,7 +213,7 @@ impl Sim {
return &node;
}
}
panic!()
panic!("No such node: {path}")
}

fn get_cell(&self, cell_id: CellId) -> &Value {
Expand Down Expand Up @@ -242,6 +259,10 @@ impl std::fmt::Display for Sim {
write!(f, "{} : {} = ", node.path(), node.type_of())?;
writeln!(f, "{} <= {}", *self.get_cell(*val_cell_id), *self.get_cell(*set_cell_id))?;
},
Node::Input { cell_id, .. } => {
write!(f, "{} : {} = ", node.path(), node.type_of())?;
writeln!(f, "{}", *self.get_cell(*cell_id))?;
},
}
}

Expand All @@ -268,48 +289,59 @@ enum Node {
update: Comb,
reset: Option<Value>,
},
Input {
path: Path,
typ: Arc<Type>,
cell_id: CellId,
},
}

impl Node {
pub fn type_of(&self) -> Arc<Type> {
match self {
Node::Simple { typ, .. } => typ.clone(),
Node::Reg { typ, .. } => typ.clone(),
Node::Input { typ, .. } => typ.clone(),
}
}

pub fn read_cell_id(&self) -> CellId {
match self {
Node::Simple { cell_id, .. } => *cell_id,
Node::Reg { val_cell_id, .. } => *val_cell_id,
Node::Input { cell_id, .. } => *cell_id,
}
}

pub fn target_cell_id(&self) -> CellId {
match self {
Node::Simple { cell_id, .. } => *cell_id,
Node::Reg { set_cell_id, .. } => *set_cell_id,
Node::Input { cell_id, .. } => *cell_id,
}
}

pub fn update(&self) -> &Comb {
pub fn update(&self) -> Option<&Comb> {
match self {
Node::Simple { update, .. } => update,
Node::Reg { update, .. } => update,
Node::Simple { update, .. } => Some(update),
Node::Reg { update, .. } => Some(update),
Node::Input { .. } => None,
}
}

fn update_mut(&mut self) -> &mut Comb {
fn update_mut(&mut self) -> Option<&mut Comb> {
match self {
Node::Simple { update, .. } => update,
Node::Reg { update, .. } => update,
Node::Simple { update, .. } => Some(update),
Node::Reg { update, .. } => Some(update),
Node::Input { .. } => None,
}
}

fn path(&self) -> &Path {
match self {
Node::Simple { path, .. } => path,
Node::Reg { path, .. } => path,
Node::Input { path, .. } => path,
}
}
}
Expand Down Expand Up @@ -337,3 +369,37 @@ enum Event {
Clock(ClockId),
Reset(ResetId),
}

pub fn simulator(input: &str, top: &str) -> VirdantResult<Sim> {
use crate::hir;
let top: Ident = top.into();
use crate::checker::QueryGroup;

let mut db = crate::checker::DatabaseStruct::default();
db.set_source(Arc::new(input.to_string()));

let ctx = db.moddef_context(top.clone())?;
let mut sim = Sim::new();

for component_name in db.moddef_component_names(top.clone())? {
let component = db.moddef_component_hir(top.clone(), component_name.clone())?;
let full_path: Path = format!("top.{}", component_name.clone()).into();
match component {
hir::Component::Incoming(name, typ) => {
sim = sim.add_input_node(full_path, typ);
}
hir::Component::Outgoing(name, typ, expr) => {
sim = sim.add_simple_node(full_path, expr);
},
hir::Component::Wire(name, typ, expr) => {
sim = sim.add_simple_node(full_path, expr);
},
hir::Component::Reg(name, typ, clk, expr) => {
let reset = None;
sim = sim.add_reg_node(full_path, typ, clk, reset, expr);
},
}
}

Ok(sim.build())
}

0 comments on commit a73ca62

Please sign in to comment.