Skip to content

Commit 525ccea

Browse files
committed
[chip, gpio, dv] Added W1's, W0's, T1's and T0's testing for GPIOs
The smoketest.c and top_chip_dv_gpio_base_vseq works in pairs in a way that C drives W1's and W0's pattern on the outputs and vseq drives T1's and T0's pattern on the inputs. Both C and vseq waits for an expected pattern to arrive in order to drive the next pattern. Signed-off-by: Kinza Qamar <kqzaman@lowrisc.org>
1 parent 164024a commit 525ccea

File tree

2 files changed

+211
-2
lines changed

2 files changed

+211
-2
lines changed

hw/top_chip/dv/env/seq_lib/top_chip_dv_gpio_base_vseq.sv

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ class top_chip_dv_gpio_base_vseq extends top_chip_dv_base_vseq;
88
// Standard SV/UVM methods
99
extern function new(string name="");
1010
extern task body();
11+
12+
// Class specific methods
13+
//
14+
// Waits for the pattern to appear on the GPIOs
15+
extern virtual task wait_for_pattern(logic [NUM_GPIOS-1:0] exp_val);
1116
endclass : top_chip_dv_gpio_base_vseq
1217

1318
function top_chip_dv_gpio_base_vseq::new (string name = "");
@@ -17,5 +22,111 @@ endfunction : new
1722
task top_chip_dv_gpio_base_vseq::body();
1823
super.body();
1924
`DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInTest);
20-
// TODO
25+
26+
// Checks the GPIOs in both input and output mode. A smoketest.c writes walking 0's and walking
27+
// 1's pattern on the first and third of direct_out register and body() waits (for a reasonable
28+
// amount of timeout) for that pattern to appear on the pads to drive 1's and 0's in temperature
29+
// sequence fashion.
30+
//
31+
// Enable the pulldowns so that the pads are driving 0's rather than Z's when no external driver
32+
// is connected
33+
cfg.gpio_vif.set_pulldown_en('1);
34+
35+
// Current Current GPIOs pads state state : 'h0
36+
37+
`uvm_info(`gfn, "Starting GPIOs outputs test", UVM_LOW)
38+
39+
// The C code first sets the first and third quater of GPIOs to 0's in order to walk 1's on them.
40+
//
41+
// Wait and check for all 0s.
42+
wait_for_pattern({NUM_GPIOS{1'b0}});
43+
44+
// Check for walking 1's pattern on the first quater of pins.
45+
for (int i = 0; i < NUM_GPIOS/4; i++) begin
46+
wait_for_pattern({24'h0, 1 << i});
47+
end
48+
49+
// Wait for a cycle so that the pads can transition from the current pin state to the next pin
50+
// state
51+
cfg.peri_clk_vif.wait_clks(1);
52+
53+
// Current GPIOs pads state : 'h00000080
54+
//
55+
// Drive 1's in temperature pattern on the second quater of pins.
56+
for (int i = NUM_GPIOS/4; i < (NUM_GPIOS/4) * 2; i++) begin
57+
cfg.gpio_vif.drive_pin(i, 1);
58+
end
59+
60+
// Current GPIOs pads state : 'h0000FF80
61+
//
62+
// Check for walking 1's pattern on the third quater of pins.
63+
for (int i = 0; i < NUM_GPIOS/4; i++) begin
64+
wait_for_pattern({8'h?, 1 << i, 16'h????});
65+
end
66+
67+
// Wait for a cycle so that the pads can transition from the current pin state to the next pin
68+
// state
69+
cfg.peri_clk_vif.wait_clks(1);
70+
71+
// Current GPIOs pads state : 'h0080FF80
72+
//
73+
// Drive 1's in temperature pattern on the fourth quater of pins.
74+
for (int i = (NUM_GPIOS/4) * 3; i < NUM_GPIOS; i++) begin
75+
cfg.gpio_vif.drive_pin(i, 1);
76+
end
77+
78+
// Current GPIOs pads state : 'hFF80FF80
79+
//
80+
// The C code first sets the first and third quater of GPIOs to 1's in order to walk 0's on them.
81+
// The second and fourth quater of pads should contain all 1's by now.
82+
//
83+
//
84+
// Wait and check for all 1s.
85+
wait_for_pattern({NUM_GPIOS{1'b1}});
86+
87+
// Current GPIOs pads state : 'hFFFFFFFF
88+
//
89+
// Check for walking 0's pattern on the first quater of pins.
90+
for (int i = 0; i < NUM_GPIOS/4; i++) begin
91+
wait_for_pattern({24'h?, ~(1 << i)});
92+
end
93+
94+
// Wait for a cycle so that the pads can transition from the current pin state to the next pin
95+
// state
96+
cfg.peri_clk_vif.wait_clks(1);
97+
98+
// Current GPIOs pads state : 'hFFFFFF7F
99+
//
100+
// Drive 0's in temperature pattern on the second quater of pins.
101+
for (int i = NUM_GPIOS/4; i < (NUM_GPIOS/4) * 2; i++) begin
102+
cfg.gpio_vif.drive_pin(i, 0);
103+
end
104+
105+
// Current GPIOs pads state : 'hFFFF007F
106+
//
107+
// Check for walking 0's pattern on on the third quater of pins.
108+
for (int i = 0; i < NUM_GPIOS/4; i++) begin
109+
wait_for_pattern({8'h?, ~(1 << i), 16'h?});
110+
end
111+
112+
// Wait for a cycle so that the pads can transition from the current pin state to the next pin
113+
// state
114+
cfg.peri_clk_vif.wait_clks(1);
115+
116+
// Current GPIOs pads state : 'hFF00007F
117+
//
118+
// Drive 0's in temperature pattern on the fourth quater of pins.
119+
for (int i = (NUM_GPIOS/4) * 3; i < NUM_GPIOS; i++) begin
120+
cfg.gpio_vif.drive_pin(i, 0);
121+
end
122+
123+
// Current GPIOs pads state : 'h7F00007F
124+
21125
endtask : body
126+
127+
task top_chip_dv_gpio_base_vseq::wait_for_pattern(logic [NUM_GPIOS-1:0] exp_val);
128+
`DV_SPINWAIT(wait(cfg.gpio_vif.pins ==? exp_val);,
129+
$sformatf("Timed out waiting for GPIOs == %0h", exp_val),
130+
/*use default_spinwait_timeout_ns*/,
131+
`gfn)
132+
endtask : wait_for_pattern

sw/device/tests/gpio/smoketest.c

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,106 @@ static bool reg_test(gpio_t gpio)
4949
return true;
5050
}
5151

52+
// Drive a pattern (val)
53+
static void drive(gpio_t gpio, uint32_t masked_reg, uint32_t val)
54+
{
55+
gpio_write(gpio, masked_reg, 0XFFFF0000 | val);
56+
}
57+
58+
// Wait for an expected pattern (compare_val).
59+
static void wait(gpio_t gpio, uint32_t compare_val)
60+
{
61+
while (DEV_READ(gpio + GPIO_REG_DATA_IN) != compare_val){
62+
}
63+
}
64+
65+
// Verifies GPIOs in partially output and input direction. The test distributes GPIOs as four equal
66+
// quaters. The idea is to drive first quater of GPIOs as outputs and wait for a pattern to appear
67+
// on the second quater of pins as inputs. Next, drive a pattern on the third quater and waits for a
68+
// pattern to appear on the fourth quater as inputs. Repeat the same process second time but with a
69+
// different pattern.
70+
//
71+
// The pattern driven on the outputs is going to be walking 1's (1, 10, 0100, 1000, ...) first and
72+
// then walking 0's (1110, 1101, 1011, 0111, ...) whereas it is a temperature 1's (1, 11, 111, 1111,
73+
// ...) then a temperature 0's (1110, 1100, 1000, 0000, ...) sequence for the inputs.
74+
//
75+
// 1- First, drive 0's on the first and third quater of GPIOs.
76+
// 2- Walk 1's on the first quater of GPIOs in output mode.
77+
// 3- top_chip_dv_gpio_base_vseq will wait for walking 1's pattern to appear on the pads. Once it
78+
// sees that pattern, it will drive 1's in temperature sequence on to the second quater.
79+
// 4- gpio_test waits for the pattern 0x0000T1W1 on the GPIO pads by reading DATA_IN register. Then
80+
// it will walk 1's on the third quater of pins and waits for pattern 0xT1W1T1W1.
81+
// 5- On the other side, the vseq waits for the walking 1's pattern on the third quater of pins and
82+
// drive 1's in temperature sequence on the fourth quater.
83+
// 6- After all that, gpio_test start to write 1's to the first and third quater of pins in order to
84+
// drive walking 0's. Everything beyond that is similar but the expected driven sequence is going
85+
// to be temperature 0's and walking 0's.
86+
static bool gpio_test(gpio_t gpio)
87+
{
88+
// Enable the first and third quater of pins in output mode
89+
gpio_set_all_oe(gpio, 0x00FF00FF);
90+
91+
// Set the gpios to all 0's in order to walk 1's on first and third quater,
92+
gpio_write(gpio, GPIO_REG_DIRECT_OUT, 0x0);
93+
94+
// Current GPIOs pads state : 0x00000000
95+
//
96+
// Walk 1's on the first quater. vseq drives the second quater as temperature 1's. Hence, the
97+
// expected value to wait for is 0xFF80,
98+
for (int i = 0; i < GPIO_NUM_PINS / 4; i++) {
99+
drive(gpio, GPIO_REG_MASKED_OUT_LOWER, 1 << i);
100+
if (i == ((GPIO_NUM_PINS / 4) - 1)) {
101+
wait(gpio, 0xFF80);
102+
}
103+
}
104+
105+
// Current GPIOs pads state : 0x0000FF80
106+
//
107+
// Walk 1's on the third quater. vseq drives the fourth quater as temperature 1's. Additionally,
108+
// the pads contains 0xFF80 by now on the first two quaters. Hence, the expected value to wait
109+
// for is 0xFF80FF80,
110+
for (int i = 0; i < GPIO_NUM_PINS / 4; i++) {
111+
drive(gpio, GPIO_REG_MASKED_OUT_UPPER, 1 << i);
112+
if (i == ((GPIO_NUM_PINS / 4) - 1)) {
113+
wait(gpio, 0xFF80FF80);
114+
}
115+
}
116+
117+
// Current GPIOs pads state : 0xFF80FF80
118+
//
119+
// Now, set the first and third quater (which are enabled as outputs) to all 1's in order to
120+
// walk 0's on them.
121+
gpio_write(gpio, GPIO_REG_DIRECT_OUT, 0x00FF00FF);
122+
123+
// Current GPIOs pads state : 0xFFFFFFFF
124+
//
125+
// Walk 0's on the first quater of pins. vseq drives the second quater as temperature 0's.
126+
// Hence, the expected value to wait for is 0xFFFF007F.
127+
for (int i = 0; i < GPIO_NUM_PINS / 4; i++) {
128+
drive(gpio, GPIO_REG_MASKED_OUT_LOWER, ~(1 << i));
129+
if (i == ((GPIO_NUM_PINS / 4) - 1)) {
130+
wait(gpio, 0xFFFF007F);
131+
}
132+
}
133+
134+
// Current GPIOs pads state : 0xFFFF007F
135+
//
136+
// Walk 0's on the third quater of pins. vseq drives the fourth quater as temperature 0's.
137+
// Hence, the expected value to wait for is 0x007F007F.
138+
for (int i = 0; i < GPIO_NUM_PINS / 4; i++) {
139+
drive(gpio, GPIO_REG_MASKED_OUT_UPPER, ~(1 << i));
140+
if (i == ((GPIO_NUM_PINS / 4) - 1)) {
141+
wait(gpio, 0x007F007F);
142+
}
143+
}
144+
145+
// Current GPIOs pads state : 0x007F007F
146+
147+
return true;
148+
}
149+
52150
bool test_main()
53151
{
54152
gpio_t gpio = mocha_system_gpio();
55-
return reg_test(gpio);
153+
return gpio_test(gpio);
56154
}

0 commit comments

Comments
 (0)