Home   Documentation: Introduction Python Perl PCI_Model Demo Future   Other: Download Contact_Info


PCI Bus Functional Model
Reference Manual


1.0 Introduction
2.0 PCI Monitor
3.0 Instantiation in Verilog
4.0 Configuration and Generating Activity
  4.1 Using a Control File
  4.2 Using Verilog Tasks
  4.3 Using Python

1.0 Introduction

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.

pci display

2.0 PCI Monitor

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.

3.0 Instantiation in Verilog

3.1 Agent Instantiation

Here is a complete verilog testbench using the arbiter, monitor, and 4 agents, 3 of which are 64-bit and one is 32-bit.
Here is a different verilog testbench where the verilog code specifies the PCI bus cycles. Only the PCI initialization comes from the command file.
Here is a typical command file used to configure a slave and generate bus cycles.

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, ... );

The first parameter (pci/agent.py) is the scriptsim program filename.
The second parameter is the scriptsim id. This is an integer value returned by scriptsim which can be used on later calls to allow verilog code to generate bus cycles. (Scheduled for PCI version 1.01)
The third parameter (pci/pci_cmds0) is the command file for master and target configuration.
The remaining parameters are the pci signals.

3.2 Arbiter Instantiation

$scriptsim("pci/arb.py", clk, reset_l, req_l, gnt_l, frame_l, irdy_l);

The first parameter (pci/arb.py) is the scriptsim program filename.
The other parameters are pci signals relevant for arbitration.

3.3 Monitor Instantiation

$scriptsim("pci/monitor.py", "req0_agent_name, req1_agent_name, ...", clk, reset_l, req_l, gnt_l, frame_l, irdy_l, trdy_l, stop_l, lock_l, idsel, devsel_l, ad, cbe_l, par_l, perr_l, serr_l);

The first parameter (pci/monitor.py) is the scriptsim program filename.
The second parameter is a list of the agent names. The first name is the name of the agent which drives req[0] and devsel[0]. Note: make sure that req[n] and devsel[n] are driven by the SAME agent. The other parameters are the PCI signals relevant for the monitor.

4.0 Configuration and Generating Activity

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.

4.1 Using a Control File

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:

#
# Here we create a target by specifying the values (hardwired and writable) of the configuration registers.
# This target has 64K of memory, and is 66Mhz capable. The keywords are defined later on this page.
# This line could be broken up into 5 config commands.
config deviceid=0x3323, vendorid=0x1023, status=(0x20, 0xfa00), command=(0x6,0x6), base0=(0xffff0000, 0)
#
# Now we cause this agent to initiate cycles
cmd=mr, adr=0x100, data=0 # memory read 1 word from address 0x100 and verify it is zero
cmd=mw, adr=0x100, data=0xffffffff # memory write to that address
cmd=mr, adr=0x100, data=0xffffffff # verify write was successful
cmd=mw, adr=0x200, data=(0xffffffff*32) # 32 word burst write
cmd=mr, adr=0x200, data=(0xffffffff*32) # 32 word burst read with verify

#
# We could write a python program which dynamically generates the traffic, rather than putting the commands in a file.
# So you could write a python function called 'get_command' which returns a string, and put this is a file called 'my_python_program.py'.
# Guess you would need to learn python to do this. But that is easy.
# Co-simulation with software is possible using this capability.
execute=my_python_program.py function=get_command

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.

4.2 Using Verilog Tasks

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.

4.3 Using Python

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.