Skip to content

Repository files navigation

VIPS, MIPS32 based single-cycle model in Veryl-lang

Dependencies

Installation

Rust based tooling (Veryl, Surfer) works as expected cross the board of operating systems. First make sure that you have a working Rust tool-chain installed (Rust), and follow the instructions for installing Veryl and Surfer as above. Marlin is brought in as a library by Veryl, so no separate installation is required.

For Verilator, you may use your system's package manager. Under arch based Linux pacman, while under MacOs either Brew or Mac Ports. For better performance you may want to install Verilator from source. This allows to use ccachefor accelerating incremental builds and moldfor improved linker performance. Further details are operating system dependent and not covered here.

Cocotb, is implemented in Python. Here you have the option to either install Cocotb using the Python package manager or through the system wide package manager, so it depends on your system installation which way to go (Python provides a jungle of opportunities for you to get lost).

The tests in this repo, exemplifies the various methods to test Veryl modules adopting System Verilog, Cocotb and Marlin.

Veryl Test, Simulation, and View

To test all modules:

veryl test --wave
surfer src/<module.vcd>

One can also test individual modules and their dependencies: E.g., the PcPlus4 module (which depends on adder, which depends on full_adder):

veryl test src/pc_plus4.veryl src/adder.veryl src/full_adder.veryl --wave
surfer src/pcplus4.vcd

Once this work, Drag TOP/test to the view pane, and you should get:

image

Marlin Test

This allos us to reap the benefits of the Rust built in test framework. For convenience we recommend that you install rust-analyzer and optional quality of life vscode plugins (e.g., better toml and dependi).

The module under test is represented by a struct which fields correspond to the module "interface".

// src/alu32.verylmoduleAlu32 (
a :inputlogic<32>,
b :inputlogic<32>,
sub:inputlogic ,
op :inputlogic<2> ,
r : output logic<32>,
v : output logic ,
c : output logic ,
z : output logic ,
)
// tests/veryl_tests.rs
...#[veryl(src = "src/alu32.veryl", name = "Alu32")]pubstructAlu;#[test]#[snafu::report]fn test_alu() -> Result<(),Whatever>{
...
let runtime = VerylRuntime::new(VerylRuntimeOptions{call_veryl_build: env::var("RUNNING_TESTS_INDEPENDENTLY").map(|value| &value == "1").unwrap_or(false),
..Default::default()})?;letmut alu = runtime.create_model::<Alu32>()?;
alu.a = 0;
alu.b = 0;
alu.sub = 0;
alu.op = 0;
alu.eval();assert_eq!(alu.r,0); ...

To run tests and capture the output:

cargo test -- --nocapture

You can also run the test directly from within vscode by pressing the Run Test button.

Vips registers

NumberName
0zero
1at
2..3v0..v1
4..7a0..a2
8..15t0..t7
16..23s0..s7
24..25t8..t9
26..27k0..k1
28gp
29sp
30fp
31ra

Modules

Alu

The Alu module, configured for 4 bit wide inputs:

image

The Alu has the sub and op inputs defined as follows:

Operationsubop
and000
or001
add010
sub110
slt111

Decoder

The VIPS support a subset of the MIPS32 ISA. We can capture the control logic for the supported arithmetic operations in the below table:

Operationrf_wew_reg_selsubopalu_b_selsign_ext
and110000x
or110010x
add110100x
sub111100x
slt111110x
andi1000010
ori1000110
addi1001011
slti1011111

image

Simple Vips

Adding control logic for branches. The decoder/control unit implements the following logic.

Notice (*), for beq the pc_sel is eq ? 10 : 00, bne the pc_sel is eq ? 00 : 10, respectively. The z signal is not used.

Operationrf_wew_reg_selsubopalu_b_selsign_extpc_sel
and110000x00
or110010x00
add110100x00
sub111100x00
slt111110x00
andi100001000
ori100011000
addi100101100
slti101111100
jr000100x01
beq00xxxx1(*)
bne00xxxx1(*)
j00xxxx111

The branch target for the relative branches (beq and bne) is computed by a seprate adder (not by the Alu). This decision allows the Alu to compute return address for function calls in the real MIPS.

Notice, for generating the pc_sel signal we need to take into accunt the eq input (a_data == b_data).

The jr instruction assumes the rt field to be zero and adds that (0) to the rs field. The real MIPS has a special ALU opcode for just passing the rs field, so here we break a bit with the MIPS specification.

The corresponding implementation is found in src/decoder1.veryl. A test program is found in src/instr_mem1.veryl allong with the top level src/vips1.veryl. See List of current tests, for running the model.

image

Full Vips

The Full Vips adds support for word sized access to data memory. The decoder/control unit implements the following logic.

Notice (*), for beq the pc_sel is eq ? 10 : 00, bne the pc_sel is eq ? 00 : 10, respectively. The z signal is not used.

Operationrf_wew_reg_selsubopalu_b_selsign_extpc_seld_sel
and110000x000
or110010x000
add110100x000
sub111100x000
slt111110x000
andi1000010000
ori1000110000
addi1001011000
slti1011111000
jr000100x01x
beq00xxxx1(*)x
bne00xxxx1(*)x
j00xxxxx11x
lw1001011001
sw000101100x

The load and store instructions computes the effective address using the Alu (rs + sig_ext(imm)). The data to store comes from the rt field (b_data).

The corresponding implementation is found in src/decoder.veryl. A test program is found in src/instr_mem.veryl allong with the top level src/vips1.veryl. See List of current tests, for running the model.

image

List of current tests

For now using the explicit syntax for declaring dependencies.

# simple components
veryl test src/mux2.veryl --wave
veryl test src/mux4.veryl --wave
veryl test src/half_adder.veryl --wave
veryl test src/decoder1.veryl --wave
veryl test src/decoder.veryl --wave
veryl test src/zero_extend.veryl --wave
veryl test src/extend16to32.veryl --wave
veryl test src/regfile.veryl --wave veryl test src/data_memory.veryl --wave # composite components, alu 
veryl test src/pc_plus4.veryl src/adder.veryl src/full_adder.veryl --wave
veryl test src/arith_test.veryl src/arith.veryl src/full_adder.veryl --wave
veryl test src/alu.veryl src/mux4.veryl src/zero_extend.veryl src/arith.veryl src/full_adder.veryl --wave
veryl test src/alu4.veryl src/alu.veryl src/mux4.veryl src/zero_extend.veryl src/arith.veryl src/full_adder.veryl --wave
veryl test src/alu32.veryl src/alu.veryl src/mux4.veryl src/zero_extend.veryl src/arith.veryl src/full_adder.veryl --wave
# top level Vips1 (correspondinging to Simple Vips)
veryl test src/vips1.veryl src/alu.veryl src/mux4.veryl src/zero_extend.veryl src/arith.veryl src/full_adder.veryl src/mux2.veryl src/extend16to32.veryl src/regfile.veryl src/decoder1.veryl src/instr_mem1.veryl src/pc_plus4.veryl src/adder.veryl --wave
# top level Vips (corresponding to Full Vips)
veryl test src/vips.veryl src/pc.veryl src/adder.veryl src/mux4.veryl src/instr_mem.veryl src/decoder.veryl src/mux2.veryl src/regfile.veryl src/branch.veryl src/extend16to32.veryl src/alu.veryl src/data_memory.veryl src/full_adder.veryl src/arith.veryl src/zero_extend.veryl --wave

About

VIPS, MIPS32 based single-cycle model in Veryl-lang

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages