Skip to content
kevin56348 edited this page Dec 21, 2024 · 6 revisions

欢迎来到 VerilogOJ wiki

简介

VerilogOJ(Verilog 在线测评系统,以下简称“本项目”),虽然名为 OJ,但实质上只是一个测评系统的简单后端,打包在了 Docker 镜像中。可以实现对同一道题目进行详细评判,实现多测试点以及 Special Judge 等功能。

虽然在硬件的世界里几乎容不得差错,如奔腾的一个浮点除错误导致了 Intel 数亿美元的损失,但对于刚刚迈入 Verilog 大门的初级学习者来说,知道自己错在何处、有何错误是很重要的,这样可以帮助初学者更加理解电路、熟悉电路。同时对于诸如平时作业、考试等场景来说,一个功能的缺失或错误后果并没有严重到完全不可以给分,而 Verilog 的测评系统目前似乎缺少这种功能。本项目是为了此种目的而设,并将相关环境封装为了 Docker image,便于使用与部署。

声明

本项目使用了 Icarus Verilog 与 Verilator 对 Verilog 文件进行仿真。

本项目基于 GNU 通用公共许可协议发布,发布该程序是 希望它能有用,但是并无保障;甚至连可销售和符合某个特定的目的都不保证。请参看 GNU 通用公共许可证,了解详情。

部署与使用

我们提供了带有最新代码的 Docker 镜像,如果需要,还可自行挂载测试脚本。该 Docker 镜像默认g++版本为14.1,默认python版本为3.8.10,包括如下库:

name version
pip 20.0.2
PyYAML 6.0.1
setuptools 45.2.0
sh 2.0.7
six 1.16.0
svgwrite 1.4.3
wavedrom 2.0.3.post3
wheel 0.34.2

在 Release 中下载本项目的 Docker 镜像,加载镜像:

docker load -i X:\path\to\your\image

并执行以下指令即可进行评测。评测结果将会输出到标准输出。

docker run --rm `
    -v X:\path\to\your\code\submit:/coursegrader/submit/ `
    -v X:\path\to\your\tespoints\testdata:/coursegrader/testdata/ `
    -e PATH="/usr/bin/:/usr/local/bin/:/root/gcc/gcc141/bin:${PATH}" `
    -e LD_LIBRARY_PATH="/root/gcc/gcc141/lib:/root/gcc/gcc141/lib64:/root/gcc/gcc141/libxec:${LD_LIBRARY_PATH}" `
    ustb/oj:v1.0 `
    python3.8 /home/test/exec.py

测试用例规范

位置

测试用例需要挂载至 Docker 中的 /coursegrader/testdata 目录下。

结构与内容要求

testdata目录应包括以下内容:

  • 答案.v
    • 答案文件可以是多个文件,不允许以_tb.v结尾
    • test1.vtesx222.vNooooooo.v,这三个文件可以组成一个“答案”;
    • 答案文件的文件名不重要,只需要保证以.v结尾且不以_tb.v结尾即可;
    • .v中的v需要小写!不允许随意更改大小写!
  • 测试激励_tb.v
    • 测试激励可以是多个文件,必须以_tb.v结尾
    • ans_tb.vtesx22x_tb.v,这两个文件可以组成一个“答案”;
    • 答案文件的文件名不重要,只需要保证以_tb.v结尾即可;
    • _tb.v中的v需要小写!不允许随意更改大小写!
    • 测试激励中必须包括一个输出函数,输出要求如下:
      • 用于对比信号的,输出必须以monitor开始,即使输出的函数不是$monitor
        • $display("monitor clk=%b:x=%h")是符合要求的;
        • $strobe("monitor clk=%b,in=%b:x=%h,out=%d")也是符合要求的。
      • 建议使用$strobe
      • 输出字符串中,输入与输入、输出与输出之间使用,隔开;输入与输出之间使用:隔开;
      • 不要加入空格,以免影响名称解析
  • config.yaml
    • 可选项,若此文件不存在则使用默认配置;
    • 文件名需完全一致
  • 子测试用例文件夹
    • 文件夹名称需要在config.yaml中定义;
    • config.yaml中定义有子测试用例,但未定义名称,则默认为point$i$,其中$i$为测试点编号,从 0 开始。
    • 子测试用例文件夹中需要包括:
      • 答案.v
      • 测试激励_tb.v

以下是几个示例:

  • 多个测试点 有多个子测试点时,需要config.yaml进行配置。

    testdata/
    ├── answer.v
    ├── testname_tb.v
    ├── 123
    │   ├── answer.v
    │   └── testname_tb.v
    ├── 456
    │   ├── answer.v
    │   └── testname_tb.v
    ├── test2
    │   ├── answer.v
    │   └── testname_tb.v
    ├── test8
    │   ├── answer.v
    │   └── testname_tb.v
    ├── compile
    │   ├── answer.v
    │   └── testname_tb.v
    └── config.yaml
    
  • 单个测试点(没有config.yaml) 当config.yaml不存在时,不可以有子测试点。

    • 答案为单文件,测试用例为单文件

      testdata/
      ├── answer.v
      └── testname_tb.v
      
    • 答案为多文件,测试用例为多文件

      testdata/
      ├── answer1.v
      ├── answer2.v
      ├── answer3.v
      ├── testnamex_tb.v
      └── testnamey_tb.v
      
  • 单个测试点(有config.yaml) 当config.yaml存在时,可以不存在子测试点。

    • 答案为单文件,测试用例为单文件

      testdata/
      ├── answer.v
      ├── testname_tb.v
      └── config.yaml
      
    • 答案为多文件,测试用例为多文件

      testdata/
      ├── answer1.v
      ├── answer2.v
      ├── answer3.v
      ├── testnamex_tb.v
      ├── testnamey_tb.v
      └── config.yaml
      

config.yaml配置

config.yaml为 YAML 格式,但大小写不敏感,且忽略所有 key 中的下划线。如以下的key会被解析为一个key

TestSrcPathtestsrcpathTest_Src_Patht_EST_s_RC_p_ATH

配置样例:

# This is a sample configuration file.
# Suitable for CG platform
TestSrcPath: /coursegrader/testdata/
SubmitSrcPath: /coursegrader/submit/
TestDstPath: /home/ojfiles/
# if there is only one testpoint, just type 0
TestPointNumber: 3
# 'max' or 'sum'
# where max represents get the maximum score of all subtests points,
# and sum will add up all scores.
SubtestMergeMethod: max
# if there are no sub-testpoints, you MUST ignore TestPointNames
# whether it is a dictionary, where keys are the names of subtest points and the values are corresponding to key's score
# or a single list, contains the name of all testpoints. In this case, all subtest share a score of 100.
TestPointNames:
 t1: 1
 t2: 2
 t3: 3
# a list, make sure it matches the order of TestPointNames.
Comments:
 - "comment1"
 - "comment2"
 - "comment3"
# Normally, leave it blank
#NecessaryFiles:
#  - a
#  - b
#  - c
DisplayWave: False
# to control the core simulator: iverilog or verilator, default iverilog
# verilator is suitable for a complicated project, such as a pipeline cpu, etc.
# it takes a long time to compile
# iverilog compile *.v files very quickly, but executes slowly.
# however, iverlog supports "x" and "z", while verilator does not support them.
Simulator: iverilog
# when exam mode is open, block all messages except CE
ExamMode: False

config_path

config.yaml文件的位置,绝对路径,不可修改。

类型:字符串 默认值:"/coursegrader/testdata/config.yaml"

test_src_path

所有测试用例所在的文件夹,绝对路径,可修改。

类型:字符串 默认值:"/coursegrader/testdata/"

submit_src_path

提交的,待测评文件所在的文件夹,绝对路径,可修改。

类型:字符串 默认值:"/coursegrader/submit/"

test_dst_path

中间文件生成路径,需要保证该文件夹可读可写

类型:字符串 默认值:"/home/ojfiles/"

necessary_files

其他必要文件。如果测试中有其他文件是必须的,但又不可以以.v结尾,可以添加至此处,

类型:字符串列表 默认值:Null

test_point_number

子测试点数量,当没有子测试点时,为 0。

类型:整数 默认值:0

test_point_names

子测试点名称,需要与test_point_number长度一致,或长度为 0。此时各个子测试点权重相等。

或以子测试点名称为键,测试点分数权重为值形成字典,多个测试点组成字典列表。

类型:字典列表 或 列表 默认值:Null

no_frac_points

不给出 0 与 100 意外的成绩。

当该选项为True时,可以给出PC的判断,并给出 60 至 100 中间的成绩。成绩的给出将根据测试点通过“程度”给出。当输出与标准答案之间差距超过 60%时,才会输出PC的判断和相应分数。

类型:布尔值 默认值:True

display_wave

是否展示波形。

当该选项为True时,显示波形;否则不显示。

类型:布尔值 默认值:True

subtest_merge_method

可选项为maxsum

当主测试点通过时,此选项无效。否则:

当该选项为max时,取所有子测试点中分数加权后最高的;当该选项为sum时,取所有子测试点分数加权和并除以总权重total_weight

类型:字符串 默认值:sum

comments

评语,数量应与test_point_number一致。

类型:字符串列表 默认值:Null

total_weight

总权重。在subtest_merge_methodsum时使用。当此选项为空时,total_weight为所有子测试点权重之和。

类型:整数 默认值:Null

simulator

可选项为iverilogverilator

iverilogxz信号支持较为完整,但仿真速度慢,适合小型工程的仿真。

verilator不支持x信号,对z信号支持有限,编译速度,但仿真速度极快,适合大型工程,且测试激励内容较多的工程。

类型:字符串 默认值:iverilog

exam_mode

考试模式。

当考试模式为True时,只显示编译错误信息,其余信息均会被替换为Submitted

类型:布尔值 默认值:False