Skip to content

Commit

Permalink
Add pest grammar, examples, and a test to check each of them.
Browse files Browse the repository at this point in the history
  • Loading branch information
maloneymr committed Jul 27, 2024
1 parent 0029578 commit 0e51f50
Show file tree
Hide file tree
Showing 19 changed files with 1,536 additions and 0 deletions.
398 changes: 398 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ name = "vir"
path = "src/main.rs"

[dependencies]
pest = "2.7.11"
pest_derive = { version = "2.7.11", features = ["grammar-extras"] }
clap = { version = "4.5.4", features = ["derive"] }
23 changes: 23 additions & 0 deletions examples/buffer.vir
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
mod Top {
incoming clk : Clock;
incoming reset : Word[1];
outgoing out : Word[8];

reg r : Word[8] on clk;
r <= if reset { 10w8 } else { r->add(1) };

mod buffer of Buffer;
buffer.clk := clk;
buffer.inp := r;
out := buffer.out;
}

mod Buffer {
incoming clk : Clock;
incoming inp : Word[8];
outgoing out : Word[8];

reg r : Word[8] on clk;
r <= inp;
out <= r;
}
46 changes: 46 additions & 0 deletions examples/echo.vir
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import uart;
import edge;
import resetter;
import queue;

mod Top {
incoming clock : Clock; // 12MHz

outgoing uart_tx : Word[1];
incoming uart_rx : Word[1];

outgoing led_0 : Word[1];
outgoing led_1 : Word[1];
outgoing led_2 : Word[1];
outgoing led_3 : Word[1];
outgoing led_4 : Word[1];

node reset : Word[1];

mod resetter of resetter::Resetter;
resetter.clock := clock;
reset := resetter.out;

led_0 := 1;
led_1 := 1;
led_2 := 0;
led_3 := 0;
led_4 := uart_sender.ready;

mod uart_receiver of uart::UartReceiver;
uart_receiver.clock := clock;
uart_receiver.reset := reset;
uart_receiver.uart_rx := uart_rx;

mod uart_sender of uart::UartSender;
uart_sender.clock := clock;
uart_sender.reset := reset;
uart_sender.data := uart_receiver.data->sub(32);
uart_sender.data_valid := edge_detector.out;

mod edge_detector of edge::Edge;
edge_detector.clock := clock;
edge_detector.inp := uart_receiver.data_valid;

uart_tx := uart_sender.uart_tx;
}
10 changes: 10 additions & 0 deletions examples/edge.vir
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
mod Edge {
incoming clock : Clock;
incoming inp : Word[1];
outgoing out : Word[1];

reg last : Word[1] on clock;
last <= inp;

out := last->not()->and(inp);
}
43 changes: 43 additions & 0 deletions examples/gcd.vir
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
union type State {
Idle();
Running(Word[8], Word[8]);
Done(Word[8]);
}

mod Top {
incoming clock : Clock;
mod gcd of Gcd;
gcd.clock := clock;
gcd.x := 89;
gcd.y := 144;
}

mod Gcd {
incoming clock : Clock;
incoming x : Word[8];
incoming y : Word[8];
outgoing result : Word[8];

reg state : State on clock;

state <= match state {
@Idle() => @Running(x, y);
@Running(x, y) =>
if y->eq(0) {
@Done(x)
} else {
if x->lt(y) {
@Running(y->sub(x), x)
} else {
@Running(x->sub(y), y)
}
};
@Done(result) => @Idle();
};

result := match state {
@Idle() => 0;
@Running(x, y) => 0;
@Done(result) => result;
};
}
27 changes: 27 additions & 0 deletions examples/lfsr.vir
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
mod Lfsr {
incoming clock : Clock;
incoming reset : Word[1];
outgoing out : Word[8];

node taps : Word[8];
taps := 29w8;

reg r : Word[8] on clock;
r <= if reset {
255w8
} else {
cat(r[7..0], 0w1)->xor(if feedback { taps } else { 0w8 })
};

out := r;

node feedback : Word[1];
feedback := r[7];

reg s : Word[4] on clock;
s <= if reset {
1
} else {
cat(s[3..0], s[3])
};
}
216 changes: 216 additions & 0 deletions examples/lights.vir
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import uart;
import edge;
import resetter;
import lfsr;

mod Top {
incoming clock : Clock; // 12MHz

outgoing uart_tx : Word[1];
incoming uart_rx : Word[1];

outgoing led_0 : Word[1];
outgoing led_1 : Word[1];
outgoing led_2 : Word[1];
outgoing led_3 : Word[1];
outgoing led_4 : Word[1];

node reset : Word[1];

mod resetter of resetter::Resetter;
resetter.clock := clock;
reset := resetter.out;

mod uart_receiver of uart::UartReceiver;
uart_receiver.clock := clock;
uart_receiver.reset := reset;
uart_receiver.uart_rx := uart_rx;

mod uart_sender of uart::UartSender;
uart_sender.clock := clock;
uart_sender.reset := reset;
uart_sender.data := uart_receiver.data;
uart_sender.data_valid := edge_detector.out;

mod edge_detector of edge::Edge;
edge_detector.clock := clock;
edge_detector.inp := uart_receiver.data_valid;

uart_tx := uart_sender.uart_tx;

reg counter : Word[32] on clock;
counter <= counter->inc();

mod led_controller of LedController;
led_controller.clock := clock;
led_controller.reset := reset;
led_controller.set_random := uart_receiver.data_valid->and(uart_receiver.data->eq(114));
led_controller.set_idle := uart_receiver.data_valid->and(uart_receiver.data->eq(105));
led_controller.set_cw := uart_receiver.data_valid->and(uart_receiver.data->eq(99));
led_controller.set_ccw := uart_receiver.data_valid->and(uart_receiver.data->eq(119));
led_controller.set_rate := rate->eq(0)->not();

node rate : Word[3];
rate :=
if uart_receiver.data->eq(49) {
1
} else if uart_receiver.data->eq(50) {
2
} else if uart_receiver.data->eq(51) {
3
} else if uart_receiver.data->eq(52) {
4
} else if uart_receiver.data->eq(53) {
5
} else if uart_receiver.data->eq(54) {
6
} else if uart_receiver.data->eq(55) {
7
} else {
0
};
led_controller.rate := rate;

led_0 := led_controller.leds[0];
led_1 := led_controller.leds[1];
led_2 := led_controller.leds[2];
led_3 := led_controller.leds[3];
led_4 := led_controller.leds[4];
}

union type LedControllerState {
Idle(Word[4], Word[1]);
SpinCW(Word[5], Word[4]);
SpinCCW(Word[5], Word[4]);
Memory(Word[16]);
Random(Word[5]);
}

mod LedController {
incoming clock : Clock; // 12MHz
incoming reset : Word[1];
outgoing leds : Word[5];

incoming set_random : Word[1];
incoming set_cw : Word[1];
incoming set_ccw : Word[1];
incoming set_idle : Word[1];
incoming set_rate : Word[1];
incoming rate : Word[3];

reg counter : Word[32] on clock;
counter <= counter->inc();


reg rate_reg : Word[3] on clock;
rate_reg <= if set_rate {
rate
} else {
rate_reg
};

mod edge_detector of edge::Edge;
edge_detector.clock := clock;
edge_detector.inp :=
if rate_reg->eq(0) {
counter[25]
} else if rate_reg->eq(1) {
counter[24]
} else if rate_reg->eq(2) {
counter[23]
} else if rate_reg->eq(3) {
counter[22]
} else if rate_reg->eq(4) {
counter[21]
} else if rate_reg->eq(5) {
counter[20]
} else if rate_reg->eq(6) {
counter[19]
} else if rate_reg->eq(7) {
counter[18]
} else {
counter[17]
};

node change : Word[1];
change := edge_detector.out;

reg state : LedControllerState on clock;
state <= if reset {
//@Idle(0, 0)
@Memory(0)
} else if set_random {
//@Random(lfsr.out[5..0])
@Memory(0)
} else if set_idle {
@Idle(0, 0)
} else if set_cw {
@SpinCW(0b00001, 0)
} else if set_ccw {
@SpinCCW(0b01000, 0)
} else if change {
match state {
@Idle(round, next) => if round->lt(3) {
@Idle(round->inc(), next)
} else if next {
@SpinCCW(0b01000, 0)
} else {
@SpinCW(0b00001, 0)
};
@SpinCW(x, round) => if x->eq(0b01000) {
if round->lt(3) {
@SpinCW(0b00001, round->inc())
} else {
@Idle(0, 1)
}
} else {
@SpinCW(x->sll(1), round)
};
@SpinCCW(x, round) => if x->eq(0b00001) {
if round->lt(3) {
@SpinCCW(0b01000, round->inc())
} else {
@Idle(0, 0)
}
} else {
@SpinCCW(x->srl(1), round)
};
@Random(leds) => @Random(lfsr.out[5..0]);
@Memory(addr) => if addr->lt(16) {
@Memory(addr->inc())
} else {
@Memory(0)
};
}
} else {
state
};

mod lfsr of lfsr::Lfsr;
lfsr.clock := clock;
lfsr.reset := reset;

leds := match state {
@Idle(round, next) => 0;
@SpinCW(leds, round) => leds;
@SpinCCW(leds, round) => leds;
@Random(leds) => leds;
@Memory(addr) => mem.read_data[5..0];
};

mod mem of Memory;
mem.clock := clock;
mem.read_addr := match state {
@Idle(x, y) => 0;
@SpinCW(x, y) => 0;
@SpinCCW(x, y) => 0;
@Random(leds) => 0;
@Memory(addr) => addr;
};
}

ext mod Memory {
incoming clock : Clock;
incoming read_addr : Word[16];
outgoing read_data : Word[8];
}
6 changes: 6 additions & 0 deletions examples/passthrough.vir
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
mod Passthrough {
incoming inp : Word[8];
outgoing out : Word[8];

out := inp;
}
Loading

0 comments on commit 0e51f50

Please sign in to comment.