Skip to content

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

Notifications You must be signed in to change notification settings

perlindgren/vips

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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.veryl
module Alu32 (
    a  : input  logic<32>,
    b  : input  logic<32>,
    sub: input  logic    ,
    op : input  logic<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")]
pub struct Alu;

#[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()
    })?;

    let mut 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

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

Modules

Alu

The Alu module, configured for 4 bit wide inputs:

image

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

Operation sub op
and 0 00
or 0 01
add 0 10
sub 1 10
slt 1 11

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:

Operation rf_we w_reg_sel sub op alu_b_sel sign_ext
and 1 1 0 00 0 x
or 1 1 0 01 0 x
add 1 1 0 10 0 x
sub 1 1 1 10 0 x
slt 1 1 1 11 0 x
andi 1 0 0 00 1 0
ori 1 0 0 01 1 0
addi 1 0 0 10 1 1
slti 1 0 1 11 1 1

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.

Operation rf_we w_reg_sel sub op alu_b_sel sign_ext pc_sel
and 1 1 0 00 0 x 00
or 1 1 0 01 0 x 00
add 1 1 0 10 0 x 00
sub 1 1 1 10 0 x 00
slt 1 1 1 11 0 x 00
andi 1 0 0 00 1 0 00
ori 1 0 0 01 1 0 00
addi 1 0 0 10 1 1 00
slti 1 0 1 11 1 1 00
jr 0 0 0 10 0 x 01
beq 0 0 x xx x 1 (*)
bne 0 0 x xx x 1 (*)
j 0 0 x xx x 1 11

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.

Operation rf_we w_reg_sel sub op alu_b_sel sign_ext pc_sel d_sel
and 1 1 0 00 0 x 00 0
or 1 1 0 01 0 x 00 0
add 1 1 0 10 0 x 00 0
sub 1 1 1 10 0 x 00 0
slt 1 1 1 11 0 x 00 0
andi 1 0 0 00 1 0 00 0
ori 1 0 0 01 1 0 00 0
addi 1 0 0 10 1 1 00 0
slti 1 0 1 11 1 1 00 0
jr 0 0 0 10 0 x 01 x
beq 0 0 x xx x 1 (*) x
bne 0 0 x xx x 1 (*) x
j 0 0 x xx x x 11 x
lw 1 0 0 10 1 1 00 1
sw 0 0 0 10 1 1 00 x

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

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •