Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved HDL simulation flow for Questa #47

Merged
merged 18 commits into from
Jan 14, 2022
Merged

Conversation

nielshaandbaek
Copy link
Contributor

@nielshaandbaek nielshaandbaek commented Dec 6, 2021

Overview

The purpose of the following PR is to provide an improved HDL simulation flow. The main changes are:

  • Adds support for dbt run and dbt test in addition to dbt build
  • Now, dbt run is used for starting the simulation in UI mode
  • And dbt test is used for running unit tests (i.e. batch mode)
  • New flags are available including the ability to define the parameters of the top-level design from the Simulation target.
  • Coverage information can also be activated.

How to use

Run the usual dbt build command to see a list of available build targets. Each target now has additional information as shown below:

$ dbt build
...
//exp-compute/vta/hw/dta_v1/sim/dta_core/DtaCoreSimulation  //exp-compute/vta/hw/dta_v1/sim/dta_core/DtaCoreSimulation ( Name: DtaCore TestCases: add-10x10-16ch.json add-2x2-16ch.json conv-10x10-16ch.json conv-1x1-16ch.json conv-3x3-16ch.json conv-3x3-1ch.json conv-big.json maxpool-10x10-16ch.json maxpool-3x3-16ch.json relu-2x2-16ch.json resize-10x10-16ch.json resize-2x2-16ch.json )
...
//exp-compute/vta/hw/dta_v1/sim/common/axi/axi_register_bank/Simulation  //exp-compute/vta/hw/dta_v1/sim/common/axi/axi_register_bank/Simulation ( Name: AxiRegisterBankSimulation Params: default AxiDataWidth64 AxiAddrWidth32 DefaultMask RegisterCount1 RegisterCount16 )
...

The additional information will be discussed in more detail below.

Test

Use the dbt test command to execute unit tests. The command will execute the simulator in batch mode and create code coverage if selected.

Run

Use the dbt run command to execute tests in GUI mode. The simulator will open the UI and read in an optional waveform configuration file. Note that it will not automatically store code coverage data at the end of the simulation.

Coverage

Code coverage may be generated using the dbt test with the flag questa-coverage=true. Code coverage will produce an HTML report of the entire design in the BUILD/OUTPUT-XXX folder as well as a coverage database in UCDB format. The coverage database can be viewed using the vsim -viewcov <database> command.

Note that the tool will create a single coverage database for every simulation target, which merges the results of all simulation runs from e.g. multiple testcases and/or multiple parameter sets.

Params

The Params enables different named parameter sets to be defined. The option is useful for modules with parameters where a single top-level testbench may be used to verify different configurations of the modules. To add a parameter set use the Params field of the hdl.Simulation target like this:

var Simulation = hdl.Simulation{
	Name:   "AxiRegisterBankSimulation",
	Srcs:   ins("tb.sv"),
	Ips:    Ips,
	Top:    "tb",
	Params: hdl.ParamMap{
		"default": {}, 
		"AxiDataWidth64": {"AxiDataWidth": "64"},
		"AxiAddrWidth32": {"AxiAddrWidth": "32"},
		"DefaultMask":    {
			"DefaultMask": "1",
			"DefaultReadOnly": "1",
		},
		"RegisterCount1":  {"RegisterCount": "1"},
		"RegisterCount16": {"RegisterCount": "16"},
	},
	WaveformInit: in("wave.do"),
}

The Params field is a map with strings as keys. The key is the name of the parameter set. The content of each entry should themselves be a map from strings to strings. The key is the parameter name and the value is the parameter value. The parameters of a parameter set will be applied during the vopt step using the -G option, e.g. -G AxiDataWidth=64.

Parameters can be selected using the -params flag. For example, to select RegisterCount16 as the parameter set one should execute e.g.

$ dbt test compute/vta/hw/dta_v1/sim/common/axi/axi_register_bank/Simulation : -params=RegisterCount16

Note that all parameter sets are always compiled, so make sure that they are syntactically correct. You can select multiple parameter sets to execute by specifying them as a comma separated list.

TestCases

Some testbenches require the use of an external test generator script for creating input data and expected output. The generator can be entered using the TestCaseGenerator and TestCasesDir fields of the hdl.Simulator target, like this:

var DtaCoreSimulation = hdl.Simulation{
	Name: "DtaCore",
	Srcs: ins(
		"tb.sv",
	),
	Ips: []hdl.Ip{
		util.Logger,
		interfaces.Stream,
		common.DtaPackage,
		rtl.Dta,
		fetch.FetchTest,
		issue.IssueTest,
		dma.DmaTest,
		execute.ExecuteTest,
		axi_register_bank.AxiRegBankTestPackage,
	},
	TestCaseGenerator: in("../../../../../../../DEPS/exp-dta-compiler/testgen"),
	TestCasesDir:      sim.TestCases,
}

The TestCasesDir is optional. However, if defined, every file in the directory will be listed as an optional testcase. By default, if TestCaseGenerator is defined, the generator will always be executed. If no testcase is specifically selected on the command line and TestCasesDir is defined, then the first file in the directory will be used as the default testcase.

To execute a specific testcase do

$ dbt test //exp-compute/vta/hw/dta_v1/sim/dta_core/DtaCoreSimulation : -testcases=maxpool-10x10-16ch.json

Multiple testcases can be specified using a comma separated list, e.g. `-testcases=default.json,maxpool-10x10-16ch.json'.

Copy link
Contributor

@ganoam ganoam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has an informal first look at this proposal.
Thanks Niels! I like this a lot. This is much more flexible than our current solution. Please go ahead and let me know when this is ready to go.

RULES/hdl/questa.go Show resolved Hide resolved
RULES/hdl/questa.go Outdated Show resolved Hide resolved
@nielshaandbaek
Copy link
Contributor Author

I will test it on Jenkins tomorrow and then we can merge it.

Copy link
Contributor

@ganoam ganoam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is amazing, thanks!

I've got no useful comments on the code, it looks good to me. Maybe we can have @jf have a look from the software perspective.

I suggest that we test this for a day or two without merging, to see if we can think of anything else we'd like to add.

RULES/hdl/questa.go Outdated Show resolved Hide resolved
RULES/hdl/questa.go Show resolved Hide resolved
RULES/hdl/questa.go Show resolved Hide resolved
Comment on lines 452 to 454
" -directive -cvg -codeAll -testname %s" +
" -instance %s %s.ucdb\"",
testcase, rule.Instance(), coverage_db))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Weird formatting

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

RULES/hdl/questa.go Outdated Show resolved Hide resolved
RULES/hdl/questa.go Show resolved Hide resolved
@ganoam
Copy link
Contributor

ganoam commented Dec 8, 2021

If no testcase is specifically selected on the command line and TestCasesDir is defined, then the first file in the directory will be used as the default testcase.

Is there a way to execute all testcases? And similarly, is there a way to execute whatever test-case (or all) using all parameter sets?

@jf
Copy link

jf commented Dec 8, 2021

This is amazing, thanks!

I've got no useful comments on the code, it looks good to me. Maybe we can have @jf have a look from the software perspective.

has somebody been claiming "jf" here? The real "jf" is this guy, I'm sorry.

@nielshaandbaek
Copy link
Contributor Author

The newest version now has the capability of simulating all parameter sets and testcases. The behavior is that if no testcase or parameter set is specified, then all will be simulated.

It now also outputs OK when the simulation succeeds for a little visual feedback.

@ganoam
Copy link
Contributor

ganoam commented Dec 8, 2021

Haha, sorry @jf. I meant @jfrohnhofen. :)

Thanks, Niels. That's perfect.

Copy link
Contributor

@jfrohnhofen jfrohnhofen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only looked at the code from a DBT perspective, not from the perspective of a potential user.

  1. Two overall remoarks: The formatting seems to be off in a couple of places.
  2. Some functions in questa.go are only used inside his package and could be made private by giving them lowercase names.

return strings.HasSuffix(path, ".v") || strings.HasSuffix(path, ".sv") || strings.HasSuffix(path, ".vhd")
return strings.HasSuffix(path, ".v") ||
strings.HasSuffix(path, ".sv") ||
strings.HasSuffix(path, ".vhd")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The formatting looks weird


func IsVhdl(path string) bool {
return strings.HasSuffix(path, ".vhdl") ||
strings.HasSuffix(path, ".vhd")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting

cmd_preamble := ""

// Default log file
log_file_suffix := "vsim.log"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting

// Parse additional arguments
for _, arg := range args {
if strings.HasPrefix(arg, "-testcase=") && rule.TestCaseGenerator != nil {
var testcase string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatting

@nielshaandbaek
Copy link
Contributor Author

I hope to have fixed the formatting and made the questa.go functions private.

Copy link
Contributor

@ganoam ganoam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I finally took this PR for a spin. I like the new capabilities, and the new UI very much, thanks a million for taking the initiative.
However, I have discovered some problems with the code so far.

It seems the parsing of the command line flags does not yet work propperly. More precisely, I've made the following observations:

  • The argument for the verbosity flag is ignored. The simulation runs in silent mode no matter what.
  • Arguments outside the allowed range {"none", "low", "medim", "high") are also ignored - i.e. they don't make the command crash, as thy should. The same goes for the -params argument.
  • Arguments to the -params flag are "somewhat ignored": it seems that a simulation for every parameter set is triggered every second time the command is issued. On the alternate invokation, a specific parameter set is simulated, but not always the rght one.

I'm appending a snipped from a couple of consecutive trials I did. I'll not post my full setup publicly, please ping me privately for that.

ddln-ng[code/exp-compute] $ ninja: build stopped: interrupted by user.
dbt test //exp-compute/vta/hw/dta_v1/sim/dma/DmaSimulation -v -seed=4199734666 -verbosity=hih -params=SramLatency1
[2/3] Created exp-compute/vta/hw/dta_v1/sim/dma/DmaSimulation:
BUILD/OUTPUT-069C378E/DMA/SramLatency10_vopt.log
BUILD/OUTPUT-069C378E/DMA/SramLatency1_vopt.log
BUILD/OUTPUT-069C378E/DMA/default_vopt.log
BUILD/OUTPUT-069C378E/DMA/exp-compute/vta/hw/dta_v1/sim/dma/tb.sv.log
[2/3] Testing exp-compute/vta/hw/dta_v1/sim/dma/DmaSimulation:
Testcase SramLatency10:^C                         
ddln-ng[code/exp-compute] $ ninja: build stopped: interrupted by user.
dbt test //exp-compute/vta/hw/dta_v1/sim/dma/DmaSimulation -v -seed=4199734666 -verbosity=hih -params=SramLatency1
[2/3] Created exp-compute/vta/hw/dta_v1/sim/dma/DmaSimulation:
BUILD/OUTPUT-069C378E/DMA/SramLatency10_vopt.log
BUILD/OUTPUT-069C378E/DMA/SramLatency1_vopt.log
BUILD/OUTPUT-069C378E/DMA/default_vopt.log
BUILD/OUTPUT-069C378E/DMA/exp-compute/vta/hw/dta_v1/sim/dma/tb.sv.log
[2/3] Testing exp-compute/vta/hw/dta_v1/sim/dma/DmaSimulation:
Testcase default:^C
ddln-ng[code/exp-compute] $ dbt test //exp-compute/vta/hw/dta_v1/sim/dma/DmaSimulation -v -seed=4199734666 -verbosity=high -params=SramLatency1
[2/3] Created exp-compute/vta/hw/dta_v1/sim/dma/DmaSimulation:
BUILD/OUTPUT-069C378E/DMA/SramLatency10_vopt.log
BUILD/OUTPUT-069C378E/DMA/SramLatency1_vopt.log
BUILD/OUTPUT-069C378E/DMA/default_vopt.log
BUILD/OUTPUT-069C378E/DMA/exp-compute/vta/hw/dta_v1/sim/dma/tb.sv.log
[2/3] Testing exp-compute/vta/hw/dta_v1/sim/dma/DmaSimulation:
Testcase default:^C
ddln-ng[code/exp-compute] $ ninja: build stopped: interrupted by user.

Comment on lines 424 to 435
if rule.WaveformInit != nil {
do_flags = append(do_flags, rule.WaveformInit.String())
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we're at it: The WaveformInit rule parameter is somewhat superfluous: Can we work on the convention that waveformInit scripts are always called sth, (e.g. waves.do)? Then we could make do without that parameter. Just probe the source dir and if it exists, add the flag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrt. to your tests, keep in mind that runtime parameters should come after a ":" in the command line. For example:

❯ dbt test //exp-compute/vta/hw/dta_v1/sim/fetch/Simulation : -verbosity=foo
2022/01/10 10:49:48 invalid verbosity flag 'foo', only 'low', 'medium', 'high' or 'none' allowed!
exit status 1
Error: Failed to run generator: exit status 1.
A fatal error occured. Exiting...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with not having a WaveformInit rule is that probing the source directory from dbt is a bit difficult. I will need to see what I can do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For your example, please use a simulation target like this:

var Simulation = hdl.Simulation{
	Name: "dma",
	Srcs: ins(
		"tb.sv",
	),
	Ips: []hdl.Ip{
		util.Logger,
		dma.Dma,
		interfaces.Stream,
		DmaTest,
	},
	Params: hdl.ParamMap{
		"default": {},
		"SramLatency1": {"SramLatency": "1"},
		"SramLatency10": {"SramLatency": "10"},
	},
	WaveformInit: in("waves.do"),
}

with a command line like this:

dbt test //exp-compute/vta/hw/dta_v1/sim/dma/Simulation : -seed=4199734666 -params=SramLatency1

you can then add -verbosity=high too if you like.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and make sure you do a dbt sync --update too!

Copy link
Contributor

@ganoam ganoam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no relevant comments on the code. It looks good to me. I'll take this for a spin now. Will give more feedback later if I encounter any problems in practise, or approve if not.

RULES/hdl/questa.go Outdated Show resolved Hide resolved
RULES/hdl/questa.go Outdated Show resolved Hide resolved
@ganoam
Copy link
Contributor

ganoam commented Dec 22, 2021

Thanks a lot for your work. After about half a day of testing, I've got a few more comments. I've encountered three issues:

  • Invoking dbt test on a target runs the simulate command regardless weather or not the build step has succeeded. It doesn't matter in the big picture; the vsim command will just fail. But I believe it would be nicer to abort, if possible.
  • The arguments passed to dbt test and dbt run are not properly parsed. I tested the -verbosity and testcase arguments on a top-level test. They had no effect.
  • Again regarding top-level tests: The testgen binary is not taken into account in dependency management. If it gets out of date, it should be recompiled automatically if possible.

@ganoam
Copy link
Contributor

ganoam commented Jan 10, 2022

Thanks for the clarifications. Works now like a charm.

Comment on lines +397 to +360
cmd := fmt.Sprintf("{ echo -n %s && xsim %s %s %s && "+
"{ { ! grep -q FAILURE %s; } && echo PASS; } }",
cmd_echo, vsim_flags, rule.Name+params, cmd_devnull, log_file.String())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this only works reliably with our new testing environment. But that's not yet implemented consistently.

RULES/hdl/questa.go Outdated Show resolved Hide resolved
@nielshaandbaek nielshaandbaek force-pushed the nh-improved-hdl-flow branch 2 times, most recently from b4e9fe8 to 9f708cf Compare January 14, 2022 19:43
@nielshaandbaek nielshaandbaek merged commit 6e29332 into master Jan 14, 2022
@nielshaandbaek nielshaandbaek deleted the nh-improved-hdl-flow branch January 17, 2022 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants