Home Documentation: Introduction Python Perl PCI_Model Demo Future Other: Download Contact_Info |
Currently, most companies develop and continually enhance their own proprietary PCI model for simulation. The development and maintenance costs of these models are substantial, and in many cases, the models do not accurately match the PCI specification.
This open-source PCI model is intended to eliminate the need for proprietary models, thereby reducing the money spent on such models, and providing a better quality model.
The PCI model is written in ScriptSim Python and can be used with verilog simulators supporting PLI. It provides arbitration, master, and target functionality. The master and target modules read commands from a file, and/or directly from verilog. No knowledge of PLI or python are required to use the model. The downloadable model has the following features:
All mandatory features of 32-bit and 64-bit 33Mhz/66Mhz PCI as documented in the PCI Local Bus Specification Version 2.2, plus:
Both masters and targets support unlimited length burst.
Targets support up to 5 address spaces, including any mix of memory and I/O.
New features are constantly being added. Please let me know of any features you would like to see.
The PCI monitor is a passive display of PCI bus activity, and uses the Python/Tk GUI to create a window showing traffic. A real display is shown to the right. Each entry shows the following information:
The start time of the transfer.
The name of the master, as determined by which agent won the arbitration. The text names of agents is provided in the verilog $scriptsim() call.
The name of the target, as determined by which agent drives DEVSEL.
The operation type, such as "Config Read" for configuration register reads.
A decode of the address, if possible. For configuration cycles, the device number is decoded, and for standard PCI configuration space registers, the register name is shown.
The data.
Error messages, if appropriate.
Bus operations are displayed in a text format, and includes protocol checks. Because the monitor does not drive any simulation signals, it has little effect on simulator performance.
The "Update" button allows the user to update the display as the simulation progresses. During an update, transactions which were incomplete are updated, and new transactions are added. Continuous updates are not performed because these updates would slow the simulation.
The agent both drives and receives PCI signals. All agent outputs must be connected to dedicated verilog register bits. Your verilog code should resolve all these register bits to determine the actual PCI signal value. See the example code. Generally, if all agents output 'z', an effective 'pullup' should be present to force an inactive level. To create an agent, add the following line to your verlog code inside an 'initial begin' block:
$scriptsim("pci/agent.py", ss_id, "pci/pci_cmds0", clk, reset_l, ... );There are 3 methods to specify the agents configuration and activity. The easiest method is to use a file to specify the target capabilities and the master cycles.
The second method is to use the file to specify the target capabilities, but use a verilog task to request the model to perform PCI bus cycles.
The third method is to use python to generate the activity. This is more complex than the other options because it requires an understanding of python and scriptsim, but can be used to create more complex applications, such as co-simulation with software or sophisticated GUIs.
The model reads a command file to determine how it should act as bus master and/or target. Multiple agents can be instantiated in your verilog simulation, and each agent usually reads from a different command file. If no bus master commands are present in the file, the agent will only act as a target. If no base registers are defined in configuration space, the agent will never respond as a target except for configuration cycles.
General notes on the file format:All configuration commands begin with the keyword 'config'. All other options are in the form keyword=value. The order of keywords is unimportant. A command occupies one line. Blank lines and comments are allowed. Comments begin with '#' or '//'. Commas ',' are ignored by the parser and can be added for readability.
Below is a sample program:
#Master keywords:
| Keyword | Value | Description |
| cmd | 2 letter command abbreviation | Specify the command to be driven on the cbe lines. Valid commands are 'ia' for interrupt acknowledge, 'sc' for special cycle, 'ir' for i/o read, 'iw' for i/o write, 'mr' for memory read, 'mw' for memory write, 'cr' for configuration read, 'cw' for configuration write, 'mm' for memory read multiple, 'ml' for memory read line, and 'mi' for memory write and invalidate. Currently dual address cycles are not supported. |
| adr | number | Specify the address. If the cycle is a configuration read or write, bits 15:11 designate the device number. For device 'n', bit 'n+16' of the address will be asserted. |
| data | number(s) | Specify the write data, or read verify data. If a burst is desired, specify multiple values in parenthesis. Multipliers are allowed. Values are maximum 32 bits. If 64-bit transfers are performed, 2 values will be transferred per cycle. The first data value will appear on bits 31:0 of the ad bus. Examples are: data=0, data=(0*32), data=(0,1,2,3). |
| be | number(s) | Specify the byte enables for a single cycle or burst transfer. Decimal or hex are allowed. As with data, byte enables are for 32-bit quantities, even if 64-bit transfers are performed. Byte enables can vary during the burst. Examples: be=0xf, be=(0xf*32), be=(0xf, 0xf, 0xf, 0x3). A '1' bit indicates the byte is enabled. Byte enables default to 0xf, i.e. all bytes enabled. |
| burst | number | Specify the burst length in terms of 32-bit data blocks. If this exceeds the amount of write data specified, extra blocks will be 0. If this exceeds the amount of data specified on a read, no read data checking will occur for the extra blocks. Defaults to the number of data blocks, or 1 if no data blocks are specified. |
| nodevsel | none | Verify that no device responds, i.e. devsel is not asserted. |
Target keywords: These are keywords following the 'config' command. Note that configuration registers generally have a 'hardwired' capability plus a writable component. So 2 numbers are generally specified. The first number specifies the hardwired capability or value. The second number is effectively written to the register and affects writeable bits. Some registers such as deviceid have no writable bits, so the second number is not needed.
| Keyword | Value | Description | |
| deviceid | number | Specify the hardwired value in the configuration space Device ID register at address 0x0 (upper 16 bits) | |
| vendorid | number | Specify the hardwired value in the configuration space Vendor ID register at address 0x0 (lower 16 bits) | |
| status | number(s) | Specify the hardwired capability and written value of the configuration space Status register. Example: status=(0x20,0xfa00) the 0x20 indicates 66Mhz capability, and the 0xfa00 resets all error bits. | |
| command | number(s) | Specify the hardwired capability and written value of the configuration space Command register. Example: command=(0x6,0) would support bus master and memory space, but currently disable that capability. | |
| base0 | number(s) | Specify the hardwired capability and written value of the base register at address 0x10. Example: base0=(0xffff0000,0x10000) would specify that this target uses 64 of memory space, and is currently configured to occupy PCI address space 0x10000 to 0x1ffff. | |
| base1 | number(s) | Same as base0, but at configuration register address 0x14. | |
| base2 | number(s) | Same as base0, but at configuration register address 0x18. | |
| base3 | number(s) | Same as base0, but at configuration register address 0x1c. | |
| base4 | number(s) | Same as base0, but at configuration register address 0x20. | |
| base5 | number(s) | Same as base0, but at configuration register address 0x24. |
Verilog code can directly generate PCI operations, and get the results. This is done with a $scriptsim call like the following:
$scriptsim(id, command, address, bytes, options, data, results, done);
Where 'id' is the id of one of the PCI agents, 'command' is the 4-bit PCI command code, 'address' is any byte address, 'bytes' is a byte count, 'options' specifies various options, 'data' is write data or read-compare data, 'results' indicates errors, and 'done' is a register which is set to 1 when the PCI command completes.
Following the call, you wait for completion with the verilog statement:
@(posedge done) // here you check the results
Note that any address and length is acceptable. The PCI model will generate a burst if appropriate.
Here is a verilog testbench where the verilog code specifies the PCI bus cycles. Only the PCI initialization comes from the command file.
Complete examples are part of the download.
The verilog code can pass any string, which is interpreted as python commands. Details and an example to be added later.
Copyright 2000-2002 NelSim Software Inc. All Rights Reserved.