One topic per concept, word for word as wtf explains it: :help <topic> shows one in the window, and an agent reads it with the help tool. The tour and the recipes show them at work.
names
Naming signals: paths, bits, slices, VHDL forms, scope, streams.
A signal is named by its full path (top.dut.s_axi_awaddr) or by the end of a path if only one
signal ends that way (s_axi_awaddr); an ambiguous name is an error listing the candidates.
- One bit:
data[3]. A slicetdata[63:32]and a concatenation{a, b}are signals too, as is a name made withcommandsignal op = cmd[7:0]. - VHDL or Verilog forms both: any case,
gen(4).xorgen[4].x,data(7 downto 4)ordata[7:4]. - A scope (
commandscope top.dut, orworkspacescope) makes names resolve under it first in every tool:s_axi_awvalidistop.dut.s_axi_awvalid.scopewith no path: none. - A radix goes with a name wherever tools take signals:
awaddr:dec(help radix). - A decoded stream is a signal (
bus.wr, its value the record's number#n), and so is each of its fields (bus.wr.addr,zbetween records), forfind,valuesand rows alike. - A struct, record or array, or part of one (
pkt,pkts[1],grid[1]), is a signal of its whole value: its fields joined, the first the most significant (pkt == 0x5A5,pkt[10]); with a text field (an nvc enum) text,'{valid:1, state:busy, pair:'{hi:A, lo:5}}.value_atadds a line per field;signalslists it as one line, its fields withpkt.**.
times
Time units, the workspace's unit and rounding.
Times take units: 120ns, 1.5us, 2595ps; a plain number is file ticks.
- Answers use one unit per workspace, so they compare across calls: once a search names a clock
(
@clk, also in a protocol or a decode), the unit is the largest that keeps that clock's shortest phase at 1 or more (nsfor a 10 ns or a 200 MHz clock).commandunit nssets it,unit autogoes back to the clocks'. A call'sunitargument overrides it for that call. - Times are rounded to a thousandth of the unit (
2595nsfor 2595.000001ns);unit: "fs"gives them exactly. A time given back stands for every tick that rounds to it:value_atreads after them all (asfindshowandrecordssample), and says a change among them (data = 0x5 (0x4 earlier in 2595ns));from/totake them all, andfindfroma match starts after it. - Durations a decoder works out (a pair's
delay) are times: shown in the unit, and compared with a time inwhere(delay > 40ns).
radix
Radixes and colours of values and rows.
Radixes: hex, bin, dec, sdec (signed), oct, ascii, float, fixed point like q4.12, and enum (the
names the file gives values, as state READ). The default is enum where the file names values,
otherwise hex; 1-bit signals always show 0 / 1 / X / Z.
- A call's
radixsets it for all its signals;data:decfor one signal. - Rows (
help workspace) take a radix and a colour:awaddr:dec,wvalid:red,awaddr:hex:red. Colours: red orange yellow green cyan blue magenta gray (offremoves it).
expressions
Search expressions for find: operators, arithmetic, values, @clk, past / rose / fell / stable.
valid && ready && data == 0x40, state == 3 || state == 5, !rst.
- Operators: == != < <= > >= (unsigned numbers), &&, ||, !, ?: and parentheses. A bare signal is
true when 1 (some bit 1, none unknown).
* / %bind tighter than+ -;?:is lowest. - Arithmetic, written as in SystemVerilog but stricter: + - * / % & | ^ ~ << >> and signed(x). Values
are exact integers: nothing wraps unless sliced, so a 32-bit add is
(a + b)[31:0];signed(x)reads x as two's complement (signed(imm[11:0]) < 0), andsigned(x)[31:0]is its sign extension to 32 bits./truncates toward zero,%takes the dividend's sign; dividing by zero is x. - Ternary
c ? a : bis a value; a nested one needs parentheses:rd != (a < b ? 1 : 0). An unknown bit incmakes the result x. &,|,^need parentheses beside another operator,<<and>>beside arithmetic:(x & 3) == 0,wmask != 1 << addr[1:0]. A comparison or!xis a value, 1 or 0. A field's bits areb[4:0], as a signal's, on either side of a comparison. An unknown operand makes the result x. Operands up to 64 bits; an error shows each fix.- Values: 0x40, 64, 0b1000000, -12, SV numbers (8'h40, 'd64, 4'b10x0, '1), x (unknown), z (high impedance), a name the file gives a
value, a time (
40ns), or another signal (mi_addr != reg_waddr,data != past(data)). Two events at different times (a request and its response) are compared as records instead: a stream of each, matched withpair(help decode), their fields inrecordswhere. - Without a clock, a match is where the expression becomes true, so back-to-back handshakes
are one match: use
@clkto see each cycle. @clkfirst (a clock signal): a match is each clock cycle whose ending rising edge samples the expression true, as a flip-flop does, reported at the cycle's starting edge. Consecutive matching cycles are one row (from,last,cycles).- Over time:
past(x)is x one cycle earlier (without a clock, one tick);rose(x),fell(x)andstable(x)compare x with it. So a protocol check is a search for its violations:@clk fell(valid) && !past(ready). findshowlists signals' values on each match, so@clk awvalid && awreadywith show["awaddr", "wdata"]is a table of the writes, a row per cycle;count_onlycounts them.
decode
Decoding interfaces into records: built-in protocols, protocol, frame, pair, check.
Decode first: records are exact and their handshake checks built in. open and info list the
interfaces a built-in protocol decodes, each with its line; command runs it:
decode bus axilite clock=aclk prefix=s_axi_
The answer lists the streams made (bus.wr, bus.rd, ...) with their counts, and the
violations (bus.errors, bus.wr.unmatched). protocols lists the protocols, protocols <name>
each one's roles, params, streams and fields.
decode <name> <protocol> clock=<clk> <role>=<signal>... <param>=<value>...: built inaxis,axilite,axi4, and without a clockspi(mode=0) anduart(baud=115200).prefix=s_axi_plays each role not given by<prefix><role>. A value runs to the nextkey=, so it can have spaces; in quotes it runs to the closing one (when="x=1").- An interface of the design's own:
protocol <name> roles=<a,b> when=<expr> <field>=<expr>...defines a protocol on its roles, no signals: a record per clock cycle wherewhenholds (help expressions), the fields sampled with it.decode <name> <protocol> clock=<clk> <role>=<signal>...puts it on signals, as a built-in:protocol hs roles=valid,ready,data when=valid && ready d=datathendecode rx hs clock=clk valid=rx_valid ready=rx_ready data=rx_data. A field is any expression of roles without past:next=pc + 4,imm=signed(insn[31:20])(a field that can be negative is signed, shown in decimal); later fields andwhencan name it (f3=insn[14:12] ok=f3 == 0). - On streams:
decode f frame input=rx.beat last=tlastgroups records into frames;decode m pair request=axi.wr response=mimatches requests with responses (by order, orid=/req_id=andresp_id=), each record both sides with itsdelay;decode c check clock=clk dropped=fell(valid) && !past(ready)is a violation record, fieldrule, per cycle where a rule holds. signal <name> = <expr>names a computed signal (help names). Decoding doesn't touch the rows. Read a stream withrecords(help records).
records
Reading streams: where, n, field comparisons, group_by, count_only.
records lists a stream as a table: n (the record's number), start, end and a field per column,
headed 20 of 157. stream may name a set: a decode (bus: its results and violations, not the
streams they are made from), a glob (bus.*) or several (bus.wr bus.rd); their records come
in order of start with a stream column, fields of the same name and kind sharing a column, empty
where a stream has none. start is the rising edge that starts the record's first clock cycle, as
find @clk reports a match; end is the edge that samples its last. With more than one record long values are shortened (a frame's data to 8
bytes and its size); count: 1 with from shows one whole.
from/topick records by their start;counthow many (default 20).wherekeeps the records a search expression over the fields holds for, the fields named bare and evaluated on each record:addr != 0x1C && resp != 0,rule == dropped,delay > 40ns.past(x)is x of the record before;nis the record's number (n == 138, a testbench's packet #138); a field compares with another field (req_addr != resp_addr, a pair's two sides, as a scoreboard checks them). On a set it keeps the streams having every field it names.group_bynames fields and answers a line per distinct value, with how many records have it and the first and last start:128 × addr=0x1C data=0x3 (2.975us .. 69.015us).- Fields show in hex;
radixgives another for every number field (dec) or for one (len:dec, several with commas). Times stay in the unit. count_onlyonly counts, with the first and last start.
workspace
Showing evidence: the workspace declaration, view, render, present.
To show the user evidence, declare the workspace, check it with view / render, then present
it into the user's wtf windows on the trace (they can undo with u). With none open, present
writes a session file that wtf <trace> shows when the user opens the trace: tell them so. The user also sees each query and change
you make as a step (:trail), with its time, so ask what you mean to show. workspace replaces everything at once, as
one undo step:
rows, top to bottom:"name","name:radix","name:radix:colour"(help radix), or a group{"group": "write", "rows": ["awaddr", "awvalid"], "collapsed": false}. Groups hold signals only. A struct or array is one row ("pkts");{"signal": "pkts", "open": ["pkts", "pkts[1]"]}opens levels of it, each named from the row's name;"fields": ["pkts[1].pair.hi:dec:red"]gives lines under a row a radix and colour of their own.cursorsby number,{"1": "80ns", "2": "390ns"}: 1 is the cursor, where values are read; 2 - 9 are marks on the events to show. The user jumps to a mark with 'N. Say what a mark shows with{"time": "390ns", "name": "first bad write", "note": "AW before W, so the address latched is stale"}: the name stands on the ruler, the note on the user's status line when they jump there.range: the visible range,["60ns", "480ns"]; default the whole trace.scope(help names);signals: computed signals,["op = cmd[7:0]"].protocols:{name, roles, when, fields: ["op = data[7:0]"]}, asprotocoldefines them;decode:{name, protocol, clock, signals: ["tvalid = rx_tvalid"], params: ["prefix = rx_"]}, asdecodedoes (help decode). Streams can then be rows. Every name, radix and time is checked first and all the errors come back at once.commandedits the workspace step by step instead (help commands).
commands
The : commands command runs.
command runs one of wtf's : commands, without the colon, on the workspace.
- Rows:
add <path|pattern>...(below the selected row, joining its group; a scope becomes a group of its direct signals, a struct or array one row),rm <path|pattern>...(rm **clears),select <row> [<last row>](the rows the next commands act on),group <name>,rename <name>,ungroup,radix <radix>,color <colour|off>(help radix),names <signal> <value>=<name>...(names for its values, as an FST enum table gives them;offremoves them),undo,redo. The answer lists the rows added and removed. - Cursors and view:
cursor <1-9> [time|off] [name=<text>] [note=<text>](without a time or keys, jump to that mark;name=/note=say what a mark shows),<time>(moves the cursor),zoom <time per column>,fit [<from> <to>](all, or between cursors'2 '3or times). - Names and times:
scope <path>(help names),unit <ns|ps|...|auto>(help times). - Decoding:
decode,protocol,signal(help decode).