Skip to content

ryukzak/wrench

Repository files navigation

Wrench

wrench CI

This is an educational project designed to explore different types of processor architectures. It includes simple CPU models and assemblers for them.

  • wrench -- translator/simulator itself
  • wrench-fmt -- formatter for assembly files
  • wrench-serv -- service for uploading and running testcases

Table of Contents

How to Run

Build Locally

  1. Clone the repository.
  2. Install Haskell Stack via GHCup.
  3. Run stack build to build the project.
  4. You have two options to run the project:
    • Run stack exec wrench -- <ARGS> to execute the project without installation.
    • Install the project with stack install to run it from the command line using wrench <ARGS>.

Install from a Binary Release

  1. Open the last master build on the Actions.
  2. Download the binary for your platform: windows-x64, linux-x64, linux-arm64, macos-intel, macos-arm64.
  3. Add the binary to your PATH.
  4. Run wrench <ARGS> to execute the project.

Via Docker Image

docker run -it --rm ryukzak/wrench:latest --help

Use it as a Service

This service will be used to send laboratory works to check.

  1. Open wrench.edu.swampbuds.me.
  2. Fill the form and submit.
  3. Check the results.

Usage

$ wrench --help
Usage: wrench INPUT [--isa ISA] [-c|--conf CONF] [-S] [-v|--verbose]

  App for laboratory course of computer architecture.

Available options:
  INPUT                    Input assembler file (.s)
  --isa ISA                ISA (risc-iv-32, f32a, acc32) (default: "risc-iv-32")
  -c,--conf CONF           Configuration file (.yaml)
  -S                       Only run preprocess and translation steps
  -v,--verbose             Verbose output
  -h,--help                Show this help text
  --version                Show version information

The wrench app requires an input assembler file and a configuration file. The assembler file should contain the source code in the ISA-specific assembly language. The configuration file is a YAML file that specifies various settings and parameters for the simulation.

Assembly File

See docs for the specific assembly language for each ISA.

Configuration File

limit

  • Type: Integer

  • Description: Specifies the maximum number of instructions the simulation can execute. If the simulation exceeds this limit, it will be terminated.

  • Example:

    limit: 40

memorySize

  • Type: Integer

  • Description: Specifies the memory size.

  • Example:

    memorySize: 40

input_streams

  • Type: Map of decimal or hexadecimal addresses to lists of inputs

  • Description: Defines the memory-mapped IO streams for the simulation. Each key is a memory address, and the value is a list of inputs that should be fed into the simulation at that address. To define an output port only, leave the list empty.

  • Example:

    input_streams:
      0x80: [5]
      132: []

reports

  • Type: List of report configurations

  • Description: Specifies the reports to generate during the simulation. Each report configuration includes settings such as the name, slice, filter, inspector, and assertions.

    reports:
      - name: Step-by-step log
        slice: all
        view: |
          {pc}: {instruction} {pc:label}

Each report configuration can include the following fields:

name
  • Type: String (optional)

  • Description: The name of the report, used as a header in the generated output.

  • Example:

    name: Step-by-step log
slice
  • Type: String or List

  • Description: Specifies which part of the simulation records should be included in the report. Possible values are:

    • "all": Include all records.
    • ["head", n]: Include the first n records.
    • ["tail", n]: Include the last n records.
    • "last": Include only the last record.
  • Example:

    slice: all
view

Text template to print log record. In template a user can use state view in curly brackets. E.g.: program counter: {pc}.

General state view implemented for all ISA:

  • pc:dec, pc:hex -- print program counter in dec or hex format.
  • pc:label -- print @label-name if current program counter assigned with label.
  • instruction -- print current instruction.
  • memory:<a>:<b> -- print memory dump between <a> and <b> address.
  • io:<a>:dec, io:<a>:sym, io:<a>:hex -- print input-output stream state for the specific address in dec, sym or hex format. Some non-printable characters will be replaced with #, other will raise error.

For ISA specific state views see docs.

assert
  • Type: String (optional)

  • Description: Specifies the expected final state of the simulation. If the actual final state does not match, an assertion failure will be reported.

  • Example:

    assert: |
      numio[0x80]: [] >>> []
      numio[0x84]: [] >>> [120]

Example

Task: Factorial computation in RISC-V-like 32-bit ISA: n!.

  • n should be read from the input at address 0x80.
  • The result should be written to the output at address 0x84.

Results:

  • Source code with comments: factorial.s (RISC).
  • Configuration file: factorial-5.yaml, which:
    • Limits the simulation to 40 instructions.
    • Defines memory-mapped IO:
      • 0x80: Input token for n = 5.
      • 0x84: Output without any tokens for reading.
    • Defines the following reports:
      • Step-by-step log, which is useful for debugging as it includes instructions and register states.
      • Check results, which verifies the processor's state on the last step and compares it with the expected outcome.

To see the translation result:

stack exec wrench -- example/risc-iv-32/factorial.s -c example/risc-iv-32/factorial-5.yaml -S

To execute the simulation and see reports:

stack exec wrench -- example/risc-iv-32/factorial.s -c example/risc-iv-32/factorial-5.yaml

For other results see ./test/golden directory.